From 5fa9245bb4900bcacd665c1922e39613dd371905 Mon Sep 17 00:00:00 2001 From: Danyal Prout Date: Tue, 25 Aug 2026 16:17:48 -0500 Subject: [PATCH] fix(b20): share activity history with the account demo B20 kept its own session-local, non-persisted activity list and never logged into the shared account engine's activity log, so token demo transactions never showed up in the account demo's history (and vice versa) even though both demos already share the same local accounts via localStorage. Route B20 sends through engine.pushActivity and render the shared ActivityLog component so both demos show one consistent, persisted trail. Co-Authored-By: Claude --- app/vibenet/demos/b20/B20Demo.tsx | 40 +++++++--------- app/vibenet/demos/b20/components/Activity.tsx | 46 ------------------- app/vibenet/demos/b20/lib/types.ts | 2 - 3 files changed, 16 insertions(+), 72 deletions(-) delete mode 100644 app/vibenet/demos/b20/components/Activity.tsx diff --git a/app/vibenet/demos/b20/B20Demo.tsx b/app/vibenet/demos/b20/B20Demo.tsx index 0b6dd9e..3efece0 100644 --- a/app/vibenet/demos/b20/B20Demo.tsx +++ b/app/vibenet/demos/b20/B20Demo.tsx @@ -6,9 +6,9 @@ import { isAddress, type Address, type Hex } from 'viem'; import { trackB20Action, trackB20ModuleSelect } from '../../../analytics/events'; import { Tabs } from '../../../components/ui/Tabs'; import { walletErrorMessage } from '../../library/wallet'; +import { ActivityLog } from '../account/components/ActivityLog'; import { useAccountEngine } from '../account/useAccountEngine'; import { AccountDemoShell } from '../_components/AccountDemoShell'; -import { ActivityRows } from './components/Activity'; import { AnnouncementModule, SampleAnnouncementViewer } from './components/AnnouncementModule'; import { DeployModule } from './components/DeployModule'; import { MemoModule } from './components/MemoModule'; @@ -28,15 +28,7 @@ import { } from './lib/protocol'; import { readRecent, readRecentPolicies, writeRecent, writeRecentPolicy } from './lib/recent'; import { sampleTokenForAddress } from './lib/samples'; -import type { - ActivityItem, - CreatedToken, - Module, - RecentPolicy, - RecentToken, - TokenAccess, - TokenInfo, -} from './lib/types'; +import type { CreatedToken, Module, RecentPolicy, RecentToken, TokenAccess, TokenInfo } from './lib/types'; export function B20Demo() { const [module, setModule] = useState('policy'); @@ -60,7 +52,6 @@ export function B20Demo() { const [inspectError, setInspectError] = useState(''); const [checkAddress, setCheckAddress] = useState(''); const [checks, setChecks] = useState | null>(null); - const [activity, setActivity] = useState([]); const [busy, setBusy] = useState(null); const [isOperator, setIsOperator] = useState(false); const [isTokenAdmin, setIsTokenAdmin] = useState(false); @@ -264,26 +255,27 @@ export function B20Demo() { } setBusy(action); trackB20Action(module, action, 'submitted'); - setActivity((rows) => [{ label, state: 'pending' }, ...rows]); try { // Sign + broadcast through the shared account engine so account deploy, // sub-account, gas-estimation, and staged-settings behavior stays in one - // implementation across demos. - const { hash } = await engine.sendActiveCall({ to, data }); - setActivity((rows) => [ - { label, hash, state: 'success' }, - ...rows.filter((row) => row.label !== label || row.state !== 'pending'), - ]); + // implementation across demos. Logging via pushActivity puts this send in + // the same history the account demo reads, so both demos share one trail. + const { hash, serialized } = await engine.sendActiveCall({ to, data }); + engine.pushActivity({ + kind: 'transact', + title: label, + txHash: hash, + serialized, + network: engine.chain.name, + mode: engine.chain.mode, + account: activeAccount.address as Address, + }); trackB20Action(module, action, 'success'); refreshWallet(activeAccount.address as Address); if (token) await inspect(token.address); return hash; } catch (error) { const detail = walletErrorMessage(error); - setActivity((rows) => [ - { label, state: 'error', detail }, - ...rows.filter((row) => row.label !== label || row.state !== 'pending'), - ]); trackB20Action(module, action, 'error'); setInspectError(detail); return null; @@ -323,8 +315,8 @@ export function B20Demo() { return ( } - activityCount={activity.length} + activity={} + activityCount={engine.activity.length} activityEmptyMessage="Nothing has happened yet." className="animate-in gap-5 pb-6 dark:text-white" > diff --git a/app/vibenet/demos/b20/components/Activity.tsx b/app/vibenet/demos/b20/components/Activity.tsx deleted file mode 100644 index 65e5bea..0000000 --- a/app/vibenet/demos/b20/components/Activity.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import Link from 'next/link'; - -import { Text } from '../../../../components/ui/Text'; -import { VIBENET_EXPLORER_PATH } from '../../../library/config'; -import { shortAddress } from '../lib/protocol'; -import type { ActivityItem } from '../lib/types'; - -// Session-local log of decoded B20 events and errors. Rows only — the shared -// ActivityDrawer supplies the surrounding collapsible panel + header. -export function ActivityRows({ rows }: { rows: ActivityItem[] }) { - if (!rows.length) return null; - return ( -
- {rows.map((row, index) => ( -
- - {row.state === 'success' ? '✓' : row.state === 'error' ? '×' : '◌'} {row.label} - - {row.hash ? ( - - {shortAddress(row.hash)} ↗ - - ) : ( - - {row.detail ?? 'Pending…'} - - )} -
- ))} -
- ); -} diff --git a/app/vibenet/demos/b20/lib/types.ts b/app/vibenet/demos/b20/lib/types.ts index 3e73a8a..d572eb3 100644 --- a/app/vibenet/demos/b20/lib/types.ts +++ b/app/vibenet/demos/b20/lib/types.ts @@ -20,8 +20,6 @@ export type TokenInfo = RecentToken & { policies: Array<{ scope: string; label: string; id: bigint; exists: boolean; admin: Address }>; }; -export type ActivityItem = { label: string; hash?: Hex; state: 'success' | 'error' | 'pending'; detail?: string }; - export type CreatedToken = RecentToken & { hash: Hex; configured: string[] }; type PolicySummary = {