@aigne/afs-ocap 1.12.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE.md +26 -0
  2. package/README.md +144 -0
  3. package/aup/accounts/default.json +64 -0
  4. package/aup/accounts/item.json +510 -0
  5. package/aup/assets/default.json +70 -0
  6. package/aup/assets/item.json +360 -0
  7. package/aup/bridges/_addr/blocks/item.json +168 -0
  8. package/aup/bridges/default.json +79 -0
  9. package/aup/bridges/item.json +868 -0
  10. package/aup/config/default.json +806 -0
  11. package/aup/default.json +387 -0
  12. package/aup/delegates/default.json +71 -0
  13. package/aup/delegates/item.json +241 -0
  14. package/aup/factories/default.json +78 -0
  15. package/aup/factories/item.json +310 -0
  16. package/aup/stakes/default.json +76 -0
  17. package/aup/stakes/item.json +374 -0
  18. package/aup/tokens/default.json +76 -0
  19. package/aup/tokens/item.json +384 -0
  20. package/aup/transactions/default.json +102 -0
  21. package/aup/transactions/item.json +286 -0
  22. package/aup/validators/default.json +57 -0
  23. package/aup/validators/item.json +99 -0
  24. package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
  25. package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
  26. package/dist/index.cjs +7 -0
  27. package/dist/index.d.cts +5 -0
  28. package/dist/index.d.mts +5 -0
  29. package/dist/index.mjs +4 -0
  30. package/dist/method-colors.cjs +137 -0
  31. package/dist/method-colors.mjs +136 -0
  32. package/dist/method-colors.mjs.map +1 -0
  33. package/dist/provider.cjs +2490 -0
  34. package/dist/provider.d.cts +453 -0
  35. package/dist/provider.d.cts.map +1 -0
  36. package/dist/provider.d.mts +453 -0
  37. package/dist/provider.d.mts.map +1 -0
  38. package/dist/provider.mjs +2490 -0
  39. package/dist/provider.mjs.map +1 -0
  40. package/dist/remote-source.cjs +338 -0
  41. package/dist/remote-source.d.cts +62 -0
  42. package/dist/remote-source.d.cts.map +1 -0
  43. package/dist/remote-source.d.mts +62 -0
  44. package/dist/remote-source.d.mts.map +1 -0
  45. package/dist/remote-source.mjs +339 -0
  46. package/dist/remote-source.mjs.map +1 -0
  47. package/dist/source.d.cts +77 -0
  48. package/dist/source.d.cts.map +1 -0
  49. package/dist/source.d.mts +77 -0
  50. package/dist/source.d.mts.map +1 -0
  51. package/dist/types.d.cts +572 -0
  52. package/dist/types.d.cts.map +1 -0
  53. package/dist/types.d.mts +572 -0
  54. package/dist/types.d.mts.map +1 -0
  55. package/dist/utils.cjs +581 -0
  56. package/dist/utils.mjs +557 -0
  57. package/dist/utils.mjs.map +1 -0
  58. package/package.json +61 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.mjs","names":[],"sources":["../src/provider.ts"],"sourcesContent":["import {\n AFS_EVENT_TYPES,\n type AFSAccessMode,\n type AFSEntry,\n type AFSExplainOptions,\n type AFSExplainResult,\n type AFSListResult,\n type AFSModuleClass,\n type AFSModuleLoadParams,\n AFSNotFoundError,\n type AFSRoot,\n type AFSSearchOptions,\n type AFSStatResult,\n type OperationsDeclaration,\n type ProviderManifest,\n type ProviderTreeSchema,\n} from \"@aigne/afs\";\nimport {\n AFSBaseProvider,\n Explain,\n List,\n Meta,\n Read,\n type RouteContext,\n Search,\n Stat,\n} from \"@aigne/afs/provider\";\nimport { joinURL } from \"ufo\";\nimport { z } from \"zod\";\nimport { getTxColor, getTxGroup } from \"./method-colors.js\";\nimport { OcapRemoteSource } from \"./remote-source.js\";\nimport type { OcapDataSource } from \"./source.js\";\nimport type {\n AFSOCAPOptions,\n AssetState,\n IndexedRollupBlock,\n IndexedTransaction,\n PagedResult,\n TokenState,\n} from \"./types.js\";\nimport {\n buildDirEntry,\n buildListResult,\n COLLECTION_TO_TYPES,\n collectionKind,\n displayMoniker,\n extractAssetFilters,\n extractBridgeFilters,\n extractDelegationFilters,\n extractFactoryFilters,\n extractStakeFilters,\n extractTokenFilters,\n extractTxFilters,\n formatBignumValue,\n formatBridgeStatusColor,\n formatBridgeStatusLabel,\n formatIntegerOrSentinel,\n formatTxTypeName,\n listOpts,\n resolveDidRole,\n resolveDidRoleLabel,\n resolveTxParties,\n TOP_LEVEL_DIRS,\n TYPE_TO_COLLECTION,\n toPaging,\n toStakeAddress,\n txStatusIntent,\n} from \"./utils.js\";\n\n/**\n * Build the `content` payload for a token detail entry. Centralizes three\n * pieces of derivation that the AUP page consumes:\n *\n * 1. `genesisTime` / `renaissanceTime` — the chain wire delivers these\n * in two shapes (top-level for some token types, nested under a\n * `context` mixin for others). We normalize to top-level here so\n * the recipe can bind one stable path; this is a multi-source\n * fallback, NOT a workaround for AUP nesting limits (AUP binds\n * arbitrary `a.b.c` paths via `_surfaceBindField`). Stake / delegate\n * detail handlers don't need this because their wire shape is\n * consistent.\n * 2. `metadata.value` — issuer-supplied free-form info, sent as a JSON\n * string. Parsed into `_issuerName` (display name) and `_communityUrl`\n * so the page doesn't have to JSON-parse on the client.\n * 3. `_typeLabel` — humanized rendering of `state.type`. The chain stores\n * `Token` / `BondingCurveToken` / `CreditToken`; users want\n * \"Standard / Bonding Curve / Credit Token\". Falls back to deriving\n * from `tokenFactoryAddress` when the type field is empty (older\n * tokens minted before the type discriminator existed).\n *\n * Pure function — kept at module scope so the unit tests can exercise the\n * derivation without spinning up a provider.\n */\nfunction enrichTokenContent(state: TokenState): Record<string, unknown> {\n const wire = state as TokenState & {\n context?: { genesisTime?: string; renaissanceTime?: string };\n };\n const ctxBlock = wire.context;\n\n let metadataValue: Record<string, unknown> | undefined;\n const rawMeta = state.metadata?.value;\n if (typeof rawMeta === \"string\") {\n try {\n const parsed = JSON.parse(rawMeta);\n if (parsed && typeof parsed === \"object\") {\n metadataValue = parsed as Record<string, unknown>;\n }\n } catch {\n // Malformed metadata.value — issuer's problem, not ours. Leave the\n // field empty so the page renders blank rather than crashing.\n }\n } else if (rawMeta && typeof rawMeta === \"object\") {\n metadataValue = rawMeta;\n }\n\n const issuerName =\n typeof metadataValue?.issuer === \"string\" ? (metadataValue.issuer as string) : undefined;\n const communityUrl =\n typeof metadataValue?.communityUrl === \"string\"\n ? (metadataValue.communityUrl as string)\n : undefined;\n\n const typeLabel = (() => {\n switch (state.type) {\n case \"CreditToken\":\n return \"Credit Token\";\n case \"BondingCurveToken\":\n return \"Bonding Curve Token\";\n case \"Token\":\n return \"Standard Token\";\n default:\n return state.tokenFactoryAddress ? \"Bonding Curve Token\" : \"Standard Token\";\n }\n })();\n\n return {\n ...state,\n genesisTime: state.genesisTime ?? ctxBlock?.genesisTime,\n renaissanceTime: state.renaissanceTime ?? ctxBlock?.renaissanceTime,\n _issuerName: issuerName,\n _communityUrl: communityUrl,\n _typeLabel: typeLabel,\n };\n}\n\n/**\n * Build the `_nftDisplay` payload that the AUP `nft-display` renderer\n * binds to. The chain stores the rendering hint as `display.{type,\n * content}`; for `type === \"url\"` we pre-attach the asset's `assetId`\n * (and `vcId` when present) so the renderer doesn't have to know about\n * the URL convention. Other types (uri / svg / svg_gzipped) need no\n * URL preprocessing — the renderer dispatches on `type` and consumes\n * `content` directly.\n *\n * Returns `null` (rather than an empty object) when the chain doesn't\n * have a display descriptor — the AUP page binds `${content._nftDisplay}`\n * and renders a \"no display\" placeholder for null.\n */\nfunction deriveNftDisplay(state: AssetState): {\n type: string;\n content: string;\n vcId?: string;\n resolvedUrl?: string;\n} | null {\n const d = state.display;\n if (!d || !d.type || !d.content) return null;\n const out: { type: string; content: string; vcId?: string; resolvedUrl?: string } = {\n type: d.type,\n content: d.content,\n };\n if (d.vcId) out.vcId = d.vcId;\n if (d.type === \"url\") {\n try {\n const u = new URL(d.content);\n if (!u.searchParams.has(\"assetId\")) u.searchParams.set(\"assetId\", state.address);\n if (d.vcId && !u.searchParams.has(\"vcId\")) u.searchParams.set(\"vcId\", d.vcId);\n out.resolvedUrl = u.href;\n } catch {\n // Malformed URL — leave resolvedUrl undefined; the renderer falls\n // back to the broken-image placeholder.\n }\n }\n return out;\n}\n\n/**\n * Build per-tx-type label overrides for the \"Type Info\" card on the\n * transaction detail page. The card surfaces inner-tx subject fields\n * (`_itxAddress`, `_itxMoniker`, `_itxFactory`, `_itxRollup`,\n * `_itxBlockHash`, `_itxBlockHeight`) whose meaning is tx-type-specific —\n * \"Address\" alone is too vague when it could be a token, asset, factory,\n * stake, or account DID. Per-type labels make the row read clearly:\n * \"Token DID\" / \"Asset DID\" / \"Rollup Block Hash\" etc.\n *\n * Returns a flat object whose keys the AUP page binds via\n * `${content._typeContext.<key>}`. All keys carry a sensible fallback\n * (the same generic label the card used to ship with) so unknown tx\n * types still render without holes; the rest of the row's hide-when-\n * empty behavior keeps irrelevant rows out of the DOM regardless of\n * label content.\n */\nfunction deriveTypeContext(rawType: string | undefined): {\n addressLabel: string;\n addressPath: string;\n monikerLabel: string;\n factoryLabel: string;\n rollupLabel: string;\n blockHashLabel: string;\n blockHeightLabel: string;\n} {\n const t = (rawType || \"\").toLowerCase();\n const out = {\n addressLabel: \"Address\",\n // Default address path goes to /accounts. The renderer pre-substitutes\n // ${content._typeContext.addressPath}, then keeps {value} for the\n // click-time DID interpolation that `navigateTo` already handles.\n addressPath: \"accounts/{value}\",\n monikerLabel: \"Moniker\",\n factoryLabel: \"Factory\",\n rollupLabel: \"Bridge\",\n blockHashLabel: \"Block Hash\",\n blockHeightLabel: \"Block Height\",\n };\n switch (t) {\n case \"create_token\":\n case \"createtoken\":\n return {\n ...out,\n addressLabel: \"Token DID\",\n addressPath: \"tokens/{value}\",\n monikerLabel: \"Token Name\",\n factoryLabel: \"Token Factory\",\n };\n case \"create_token_factory\":\n case \"createtokenfactory\":\n case \"update_token_factory\":\n case \"updatetokenfactory\":\n return {\n ...out,\n addressLabel: \"Token Factory DID\",\n addressPath: \"factories/{value}\",\n monikerLabel: \"Token Factory Name\",\n };\n case \"mint_token\":\n case \"minttoken\":\n case \"burn_token\":\n case \"burntoken\":\n case \"deposit_token_v2\":\n case \"deposittokenv2\":\n case \"withdraw_token_v2\":\n case \"withdrawtokenv2\":\n return { ...out, factoryLabel: \"Token Factory\" };\n case \"create_factory\":\n case \"createfactory\":\n return {\n ...out,\n addressLabel: \"NFT Factory DID\",\n addressPath: \"factories/{value}\",\n monikerLabel: \"NFT Factory Name\",\n };\n case \"create_asset\":\n case \"createasset\":\n case \"mint_asset\":\n case \"mintasset\":\n case \"update_asset\":\n case \"updateasset\":\n case \"consume_asset\":\n case \"consumeasset\":\n case \"acquire_asset_v2\":\n case \"acquireassetv2\":\n case \"acquire_asset_v3\":\n case \"acquireassetv3\":\n return {\n ...out,\n addressLabel: \"Asset DID\",\n addressPath: \"assets/{value}\",\n monikerLabel: \"Asset Name\",\n factoryLabel: \"NFT Factory\",\n };\n case \"stake\":\n case \"revoke_stake\":\n case \"revokestake\":\n case \"claim_stake\":\n case \"claimstake\":\n case \"slash_stake\":\n case \"slashstake\":\n case \"return_stake\":\n case \"returnstake\":\n return { ...out, addressLabel: \"Stake DID\", addressPath: \"stakes/{value}\" };\n case \"create_rollup\":\n case \"createrollup\":\n case \"update_rollup\":\n case \"updaterollup\":\n case \"join_rollup\":\n case \"joinrollup\":\n case \"leave_rollup\":\n case \"leaverollup\":\n case \"pause_rollup\":\n case \"pauserollup\":\n case \"resume_rollup\":\n case \"resumerollup\":\n case \"close_rollup\":\n case \"closerollup\":\n case \"migrate_rollup\":\n case \"migraterollup\":\n case \"migrate_rollup_contract\":\n case \"migraterollupcontract\":\n case \"migrate_rollup_token\":\n case \"migraterolluptoken\":\n return { ...out, rollupLabel: \"Bridge Address\" };\n case \"create_rollup_block\":\n case \"createrollupblock\":\n case \"claim_block_reward\":\n case \"claimblockreward\":\n return {\n ...out,\n rollupLabel: \"Bridge Address\",\n blockHashLabel: \"Bridge Block Hash\",\n blockHeightLabel: \"Bridge Block Height\",\n };\n case \"declare\":\n case \"account_migrate\":\n case \"accountmigrate\":\n case \"delegate\":\n case \"revoke_delegate\":\n case \"revokedelegate\":\n return { ...out, addressLabel: \"Account DID\" };\n default:\n return out;\n }\n}\n\nexport const __testing__ = { enrichTokenContent, deriveNftDisplay, deriveTypeContext };\n\nexport class AFSOCAP extends AFSBaseProvider {\n static schema() {\n return z.object({\n endpoint: z.string().describe(\"OCAP endpoint URL\"),\n name: z.string().optional().describe(\"Provider name\"),\n description: z.string().optional().describe(\"Provider description\"),\n accessMode: z.enum([\"readonly\", \"readwrite\"]).optional().describe(\"Access mode\"),\n pageSize: z.number().optional().describe(\"Default page size\"),\n });\n }\n\n static manifest(): ProviderManifest {\n return {\n name: \"ocap\",\n description:\n \"OCAP blockchain — browse transactions, accounts, tokens, factories, and more.\\n- Read-only access to blockchain state\\n- Path structure: `/transactions/{hash}`, `/accounts/{address}`, `/tokens/{address}`\",\n uriTemplate: \"ocap://{endpoint+}\",\n category: \"blockchain\",\n schema: z.object({ endpoint: z.string() }),\n tags: [\"blockchain\", \"ocap\", \"arcblock\"],\n capabilityTags: [\"read-only\", \"search\", \"auth:none\", \"remote\"],\n security: {\n riskLevel: \"sandboxed\",\n resourceAccess: [],\n },\n capabilities: {\n filesystem: { read: true, write: false },\n },\n };\n }\n\n static treeSchema(): ProviderTreeSchema {\n return {\n operations: [\"list\", \"read\", \"search\", \"stat\", \"explain\"],\n tree: {\n \"/\": { kind: \"ocap:chain\" },\n \"/transactions\": { kind: \"ocap:transaction\" },\n \"/transactions/{hash}\": { kind: \"ocap:transaction\" },\n \"/transactions/{hash}/receipts\": { kind: \"ocap:receipt\" },\n \"/transactions/{hash}/receipts/{idx}\": { kind: \"ocap:receipt\" },\n \"/accounts\": { kind: \"ocap:account\" },\n \"/accounts/{address}\": { kind: \"ocap:account\" },\n \"/accounts/{address}/tokens\": { kind: \"ocap:token\" },\n \"/accounts/{address}/assets\": { kind: \"ocap:asset\" },\n \"/accounts/{address}/stakes\": { kind: \"ocap:stake\" },\n \"/accounts/{address}/stakes/sent\": { kind: \"ocap:stake\" },\n \"/accounts/{address}/stakes/received\": { kind: \"ocap:stake\" },\n \"/accounts/{address}/delegates\": { kind: \"ocap:delegate\" },\n \"/accounts/{address}/transactions\": { kind: \"ocap:transaction\" },\n \"/accounts/{address}/migration\": { kind: \"ocap:account:migration\" },\n \"/accounts/{address}/token-flows\": { kind: \"ocap:token-flow\" },\n \"/tokens\": { kind: \"ocap:token\" },\n \"/tokens/{address}\": { kind: \"ocap:token\" },\n \"/tokens/{address}/holders\": { kind: \"ocap:account\" },\n \"/tokens/{address}/transactions\": { kind: \"ocap:transaction\" },\n \"/factories\": { kind: \"ocap:factory\" },\n \"/factories/{address}\": { kind: \"ocap:factory\" },\n \"/factories/{address}/assets\": { kind: \"ocap:asset\" },\n \"/factories/{address}/transactions\": { kind: \"ocap:transaction\" },\n \"/assets\": { kind: \"ocap:asset\" },\n \"/assets/{address}\": { kind: \"ocap:asset\" },\n \"/assets/{address}/transactions\": { kind: \"ocap:transaction\" },\n \"/assets/{address}/stakes\": { kind: \"ocap:stake\" },\n \"/bridges\": { kind: \"ocap:bridge\" },\n \"/bridges/{address}\": { kind: \"ocap:bridge\" },\n \"/bridges/{address}/transactions\": { kind: \"ocap:transaction\" },\n \"/bridges/{address}/deposits\": { kind: \"ocap:transaction\" },\n \"/bridges/{address}/withdrawals\": { kind: \"ocap:transaction\" },\n \"/bridges/{address}/governance\": { kind: \"ocap:transaction\" },\n \"/bridges/{address}/slashes\": { kind: \"ocap:transaction\" },\n \"/bridges/{address}/nodes\": { kind: \"ocap:rollup-node\" },\n \"/bridges/{address}/stakes\": { kind: \"ocap:stake\" },\n \"/bridges/{address}/blocks\": { kind: \"ocap:rollup-block\" },\n \"/bridges/{address}/blocks/{hash}\": { kind: \"ocap:rollup-block\" },\n \"/stakes\": { kind: \"ocap:stake\" },\n \"/stakes/{address}\": { kind: \"ocap:stake\" },\n \"/stakes/{address}/transactions\": { kind: \"ocap:transaction\" },\n \"/stakes/{address}/tokens\": { kind: \"ocap:token\" },\n \"/stakes/{address}/assets\": { kind: \"ocap:asset\" },\n \"/delegates\": { kind: \"ocap:delegate\" },\n \"/delegates/{address}\": { kind: \"ocap:delegate\" },\n \"/delegates/{address}/transactions\": { kind: \"ocap:transaction\" },\n \"/delegates/{address}/permissions\": { kind: \"ocap:delegate_permission\" },\n \"/validators\": { kind: \"ocap:validator\" },\n \"/validators/{address}\": { kind: \"ocap:validator\" },\n \"/config\": { kind: \"ocap:config\" },\n },\n auth: { type: \"none\" },\n bestFor: [\"blockchain exploration\", \"transaction analysis\", \"account lookup\"],\n notFor: [\"write operations\", \"binary data\"],\n };\n }\n\n static async load({ config }: AFSModuleLoadParams = {}) {\n const valid = AFSOCAP.schema().parse(config);\n return new AFSOCAP(valid);\n }\n\n private _name: string;\n readonly description?: string;\n readonly accessMode: AFSAccessMode;\n\n get name(): string {\n return this._name;\n }\n\n private source: OcapDataSource;\n private defaultPageSize: number;\n private _nameResolved = false;\n\n // Phase 0.2 A.7 — token price cache. 60s TTL matches the upstream price\n // service refresh cadence; the cache is keyed by the token SYMBOL (the\n // upstream API queries by symbol, not address) and scoped per-provider\n // instance, so a /dev/chain/main lookup never bleeds into /dev/chain/beta.\n private priceCache = new Map<string, { value: Record<string, unknown>; expiresAt: number }>();\n private static readonly PRICE_TTL_MS = 60_000;\n private static readonly PRICE_API =\n \"https://token-data.arcblock.io/api/token-price-by-symbol?symbols=\";\n // Allow tests to swap in a deterministic fetch without monkey-patching globals.\n private fetchImpl: (url: string) => Promise<{ ok: boolean; json: () => Promise<unknown> }> = (\n url,\n ) => fetch(url) as unknown as Promise<{ ok: boolean; json: () => Promise<unknown> }>;\n\n // Short-TTL cache for chain-level aggregate queries (getChainInfo,\n // getForgeStats, list*-size:1, ...). 30s comfortably covers a chain\n // explorer's \"feels live\" expectation — block height in the microbar\n // refreshes ~6 blocks late at worst, while count cards (tokenCount /\n // factoryCount / ...) that change at minute-or-slower cadence dedupe\n // across virtually every back-to-back navigation. The cache is per\n // AFSOCAP instance, so /dev/chain/main and /dev/chain/beta never share\n // values (each chain has its own provider with its own endpoint).\n //\n // The cache stores the in-flight Promise itself so concurrent callers\n // share a single underlying request rather than each kicking off their\n // own. On rejection the entry is evicted so the next call retries.\n private chainCache = new Map<string, { promise: Promise<unknown>; expiresAt: number }>();\n private static readonly CHAIN_TTL_MS = 30_000;\n\n // Native gas/staking token resolution. The native token of a chain\n // doesn't change for the lifetime of a provider instance, so we cache\n // it once-per-instance instead of re-fetching listTokens(50) on every\n // microbar read.\n private nativeTokenPromise: Promise<{ symbol: string; address: string } | null> | null = null;\n\n constructor(options: AFSOCAPOptions) {\n super();\n\n if (options.source) {\n this.source = options.source;\n } else if (options.endpoint) {\n this.source = new OcapRemoteSource(options.endpoint);\n } else {\n throw new Error(\"AFSOCAP requires either 'source' or 'endpoint' option\");\n }\n this._name = options.name || \"ocap\";\n this.description = options.description;\n this.accessMode = options.accessMode ?? \"readonly\";\n this.defaultPageSize = options.pageSize ?? 20;\n }\n\n // ── Live subscription wiring (afs-live-updates Phase 3b) ──────────────────\n /**\n * Probed during onMount(); true when the underlying source exposes a\n * working `subscribe(topic, cb)`. Read by `getOperationsDeclaration()`\n * so capability discovery reflects runtime reality (worker bundles\n * without `@arcblock/ws` advertise live:false even when the rest of\n * the read API works fine).\n */\n private _liveCapable = false;\n private _unsubTxCreate: (() => void) | null = null;\n\n onMount(_root: AFSRoot, _mountPath?: string): void {\n // Probe optional source.subscribe — sources without live support\n // (mocks, static fixtures, sources whose runtime can't load\n // `@arcblock/ws`) simply skip this branch and capability stays false.\n if (typeof this.source.subscribe !== \"function\") {\n this._liveCapable = false;\n return;\n }\n try {\n this._unsubTxCreate = this.source.subscribe(\"tx.create\", (payload) => {\n this.handleTxCreatePayload(payload);\n });\n this._liveCapable = true;\n } catch {\n // Install failure (e.g. ws bundle unavailable) — degrade silently\n // so the rest of the provider keeps serving reads.\n this._liveCapable = false;\n this._unsubTxCreate = null;\n }\n }\n\n onUnmount(): void {\n if (this._unsubTxCreate) {\n try {\n this._unsubTxCreate();\n } catch {\n // tolerate adapter teardown errors\n }\n this._unsubTxCreate = null;\n }\n this._liveCapable = false;\n }\n\n /**\n * Bridge a phoenix `tx.create` payload onto the AFS event bus as an\n * `afs:append /transactions/<hash>` event. Path traversal is impossible\n * because the hash is bracketed with `joinURL` after validation; we drop\n * the event entirely if the hash isn't a plain string.\n */\n private handleTxCreatePayload(payload: unknown): void {\n const p = payload as {\n hash?: unknown;\n type?: unknown;\n time?: unknown;\n sender?: unknown;\n receiver?: unknown;\n };\n if (!p || typeof p.hash !== \"string\" || p.hash.length === 0 || p.hash.includes(\"/\")) {\n return;\n }\n this.emit({\n type: AFS_EVENT_TYPES.APPEND,\n path: joinURL(\"/transactions\", p.hash),\n data: {\n hash: p.hash,\n type: typeof p.type === \"string\" ? p.type : undefined,\n time: typeof p.time === \"string\" ? p.time : undefined,\n sender: typeof p.sender === \"string\" ? p.sender : undefined,\n receiver: typeof p.receiver === \"string\" ? p.receiver : undefined,\n },\n });\n }\n\n protected override getOperationsDeclaration(): OperationsDeclaration {\n const base = super.getOperationsDeclaration();\n return {\n ...base,\n subscribe: {\n supported: true,\n features: {\n live: this._liveCapable,\n eventTypes: \"append,write\",\n maxRateHz: 100,\n scope: \"global\",\n },\n },\n };\n }\n\n private async resolveNameOnce(): Promise<void> {\n if (this._nameResolved || this._name !== \"ocap\") return;\n this._nameResolved = true;\n const info = await this.memoize(\"getChainInfo\", AFSOCAP.CHAIN_TTL_MS, () =>\n this.source.getChainInfo(),\n );\n if (info.moniker) {\n this._name = info.moniker;\n }\n }\n\n /**\n * Memoize an async source call by `key` for `ttlMs`. Concurrent callers\n * share the in-flight Promise; rejections evict the entry so the next\n * call retries. Used by chain-level aggregate queries that are read by\n * multiple handlers within the same homepage load.\n */\n private memoize<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T> {\n const now = Date.now();\n const cached = this.chainCache.get(key);\n if (cached && cached.expiresAt > now) {\n return cached.promise as Promise<T>;\n }\n const promise = fn();\n this.chainCache.set(key, { promise, expiresAt: now + ttlMs });\n promise.catch(() => {\n // Evict on failure so the next caller retries instead of inheriting\n // a rejected promise. Guard against evicting a *newer* entry that\n // raced ahead — only delete if we still own the slot.\n if (this.chainCache.get(key)?.promise === promise) {\n this.chainCache.delete(key);\n }\n });\n return promise;\n }\n\n /**\n * Resolve the chain's native gas/staking token (ABT on ArcBlock-family\n * chains, with a fallback to the newest token when ABT isn't present —\n * test chains, custom genesis). The result is cached for the lifetime of\n * the provider; failures are not cached so the next caller retries.\n *\n * Returns `null` when no native token is discoverable (empty chain).\n */\n private resolveNativeToken(): Promise<{ symbol: string; address: string } | null> {\n if (this.nativeTokenPromise) return this.nativeTokenPromise;\n const promise = (async () => {\n try {\n const tokens = await this.memoize(\"listTokens:size50\", AFSOCAP.CHAIN_TTL_MS, () =>\n this.source.listTokens({ size: 50, offset: 0 }),\n );\n const items = (tokens?.items ?? []) as Array<{ symbol?: string; address?: string }>;\n const native = items.find((t) => t.symbol === \"ABT\") ?? items[0];\n if (!native?.address || !native.symbol) return null;\n return { symbol: native.symbol, address: native.address };\n } catch {\n return null;\n }\n })();\n this.nativeTokenPromise = promise;\n // If resolution fails to find a native, allow retry on next call.\n promise.then((result) => {\n if (!result && this.nativeTokenPromise === promise) {\n this.nativeTokenPromise = null;\n }\n });\n return promise;\n }\n\n /**\n * Symbol-keyed price fetch. Extracted from `readTokenPrice` so callers\n * that already know the symbol (e.g. microbar after resolveNativeToken)\n * can skip the `getTokenState` round-trip just to look up the symbol.\n *\n * Returns the normalized payload on success, a `{...stale, error}` object\n * when fetch fails but a cache entry exists, or `null` when fetch fails\n * with no cached fallback.\n */\n private async getPriceBySymbol(symbol: string): Promise<Record<string, unknown> | null> {\n const cacheKey = symbol;\n const now = Date.now();\n const cached = this.priceCache.get(cacheKey);\n if (cached && cached.expiresAt > now) {\n return { ...cached.value, fromCache: true };\n }\n\n const url = `${AFSOCAP.PRICE_API}${encodeURIComponent(symbol)}`;\n let payload: Record<string, unknown> | null = null;\n let fetchError: string | null = null;\n try {\n const res = await this.fetchImpl(url);\n if (!res.ok) {\n fetchError = \"price api returned !ok\";\n } else {\n payload = (await res.json()) as Record<string, unknown>;\n }\n } catch (err) {\n fetchError = err instanceof Error ? err.message : String(err);\n }\n\n if (payload) {\n const value = this.normalizePricePayload(payload, symbol, now);\n this.priceCache.set(cacheKey, { value, expiresAt: now + AFSOCAP.PRICE_TTL_MS });\n return value;\n }\n\n if (cached) {\n return { ...cached.value, stale: true, error: fetchError ?? \"fetch failed\" };\n }\n return null;\n }\n\n private resolveNavPath(address: string | undefined): string | undefined {\n if (!address) return undefined;\n const entityType = resolveDidRole(address);\n if (!entityType) return undefined;\n const collection = TYPE_TO_COLLECTION[entityType];\n if (!collection) return undefined;\n return joinURL(\"/\", collection, address);\n }\n\n /**\n * Phase 0.2 A.6 — Inject the request's account address as `_currentAccount`\n * on every entry's content. Used by /accounts/:addr/{transactions,stakes/*,\n * assets,token-flows} so the AUP `direction-pill` formatter can compute\n * IN/OUT/SELF without each blocklet reaching for ctx.params.\n *\n * Trust boundary: the address comes from the route param (set by the AFS\n * core router from the URL path), NOT from ctx.options (which is\n * caller-controlled). The object spread ordering also guarantees a\n * caller-supplied `content._currentAccount` cannot override us.\n */\n private withCurrentAccount(entries: AFSEntry[], currentAccount: string): AFSEntry[] {\n if (!currentAccount) return entries;\n return entries.map((e) => ({\n ...e,\n content: {\n ...((e.content as Record<string, unknown> | undefined) ?? {}),\n _currentAccount: currentAccount,\n },\n }));\n }\n\n /**\n * Phase 0.6 polish — single source of truth for tx content enrichment.\n *\n * Both `buildTxEntries` (list path) and `readTransaction` (detail path)\n * call this so columns and key-value-list rows that bind to the same\n * keys (e.g. `_gasFeeRaw`) render identically. Detail-only fields like\n * `_itxJson` / `_receiverPath` / `_prevHash` stay in `readTransaction`\n * so the list payload doesn't grow with rendering metadata.\n */\n private enrichTxContent(\n tx: IndexedTransaction & {\n tokenSymbols?: Array<{ symbol?: string; decimal?: number; address?: string }>;\n },\n itxJson: Record<string, unknown>,\n ): Record<string, unknown> {\n const itx = (tx.tx as Record<string, unknown>) || {};\n const itxInputs = itxJson.inputs as\n | Array<{\n owner?: string;\n tokens?: Array<{ address?: string; value?: string }>;\n assets?: unknown;\n }>\n | undefined;\n const itxOutputs = itxJson.outputs as\n | Array<{\n owner?: string;\n tokens?: Array<{ address?: string; value?: string }>;\n assets?: unknown;\n }>\n | undefined;\n const itxOutputOwner = itxOutputs?.[0]?.owner;\n const itxTo = itxJson.to as string | undefined;\n const token = itxJson.token as { address?: string; value?: string } | undefined;\n // transfer_v2 carries token amounts in a top-level \\`tokens[]\\` array\n // (sibling to \\`to\\`). Distinct from transfer_v3's \\`outputs[].tokens[]\\`\n // and the singleton \\`token\\` shape used by mint/burn-style txs.\n const itxTokens = itxJson.tokens as Array<{ address?: string; value?: string }> | undefined;\n const tokenSymbols = tx.tokenSymbols;\n const txReceipts =\n ((tx as { receipts?: unknown }).receipts as\n | Array<{ changes?: Array<{ action?: string; target?: string; value?: string }> }>\n | undefined) ?? [];\n // ── Tx types where \\`itxJson.value\\` (or singleton \\`token.value\\`) is a\n // placeholder (typically the literal \"1\") rather than a token amount in\n // wei. Skipping those itxJson sources for these types prevents the bignum\n // formatter from rendering \"0.000000000000000001 ABT\" for an asset\n // mint / acquire. The real subject value lives in receipts.\n const NO_TOKEN_VALUE_TX_TYPES = new Set([\n \"mint_asset\",\n \"create_asset\",\n \"update_asset\",\n \"consume_asset\",\n \"acquire_asset_v2\",\n \"acquire_asset_v3\",\n \"MintAsset\",\n \"MintAssetTx\",\n \"CreateAsset\",\n \"CreateAssetTx\",\n \"UpdateAsset\",\n \"UpdateAssetTx\",\n \"ConsumeAsset\",\n \"ConsumeAssetTx\",\n \"AcquireAssetV2\",\n \"AcquireAssetV2Tx\",\n \"AcquireAssetV3\",\n \"AcquireAssetV3Tx\",\n ]);\n const isNoTokenValueTx = NO_TOKEN_VALUE_TX_TYPES.has(tx.type || \"\");\n\n // ── Value column: leg aggregation ────────────────────────────────────\n //\n // A tx can move value across multiple legs (multi-output transfer_v3,\n // multi-recipient claim_block_reward fan-out, mixed-token exchanges,\n // multi-asset transfers). The Value column shows ONE primary number with\n // ONE symbol, so we aggregate all legs by token/asset target and pick a\n // principal:\n //\n // 1. Source the legs. Receipts are the PRIMARY source — they are the\n // on-chain record of value actually moved, as signed change\n // accounting (a transfer emits one -X debit and one +X credit on the\n // same token), so step 2's positive-sum collapses the two sides of\n // one movement to |X| with no double-count. Gas / service-fee actions\n // are excluded (tx cost, not subject value); receipts.action=\"fee\" is\n // kept because claim_block_reward uses it for the validator-reward\n // fan-out. itxJson is the FALLBACK, used only when receipts carry no\n // subject value (pending txs / receipt-less indexer payloads); it is\n // skipped for NO_TOKEN_VALUE_TX_TYPES whose envelope value is a\n // placeholder, and its inputs[]/outputs[] are merged per token via\n // max(in, out) — they are the two sides of one movement, so summing\n // them would re-introduce the very double-count receipts avoid.\n // 2. Aggregate token legs by (target address): sum positive values so\n // double-entry accounting (one +X / one -X) collapses to |X| and\n // multi-recipient fan-outs sum to the protocol total. All asset\n // legs collapse into a single \"Asset\" group with a count, since the\n // Value column displays \"N Asset\" rather than per-DID detail.\n // 3. Drop token groups whose positive total is zero (all-negative or\n // all-zero legs).\n // 4. Principal = first remaining group (token groups in encounter\n // order, then the asset group). When more than one group remains,\n // append \" · +N more\" so the user knows the row's number isn't the\n // whole tx — distinct token + asset legs.\n\n type TokenLegInfo = { symbol: string; decimal: number };\n const tokenInfoByAddr = new Map<string, TokenLegInfo>();\n for (const t of (tokenSymbols ?? []) as Array<{\n address?: string;\n symbol?: string;\n decimal?: number;\n }>) {\n if (\n typeof t.address === \"string\" &&\n typeof t.symbol === \"string\" &&\n typeof t.decimal === \"number\"\n ) {\n tokenInfoByAddr.set(t.address, { symbol: t.symbol, decimal: t.decimal });\n }\n }\n // The fallback token info covers two distinct legacy / minimal-payload\n // cases: (a) tokenSymbols absent altogether, (b) tokenSymbols present\n // but its entries omit \\`address\\` (older mocks). In case (b) we still\n // want the symbol / decimal from the first entry so a mint_token mock\n // renders \"10 AIGNEP\" rather than \"10 ABT\".\n const firstTokenSymbol = (tokenSymbols ?? [])[0] as\n | { address?: string; symbol?: string; decimal?: number }\n | undefined;\n const fallbackTokenInfo: TokenLegInfo = {\n symbol: typeof firstTokenSymbol?.symbol === \"string\" ? firstTokenSymbol.symbol : \"ABT\",\n decimal: typeof firstTokenSymbol?.decimal === \"number\" ? firstTokenSymbol.decimal : 18,\n };\n const fallbackTokenAddr = (() => {\n const first = tokenInfoByAddr.keys().next().value;\n return typeof first === \"string\" ? first : \"native\";\n })();\n\n type Leg =\n | { kind: \"token\"; target: string; symbol: string; decimal: number; value: string }\n | { kind: \"asset\"; target: string };\n const legs: Leg[] = [];\n\n function pushTokenLeg(target: string | undefined, value: string | undefined) {\n if (typeof value !== \"string\" || value === \"\") return;\n const addr = typeof target === \"string\" && target.length > 0 ? target : fallbackTokenAddr;\n const info = tokenInfoByAddr.get(addr) ?? fallbackTokenInfo;\n legs.push({\n kind: \"token\",\n target: addr,\n symbol: info.symbol,\n decimal: info.decimal,\n value,\n });\n }\n\n // 1. PRIMARY source — receipts. The on-chain record of value moved, as\n // signed change accounting: a transfer emits one -X debit + one +X\n // credit on the same token, so step 2's positive-sum collapses both\n // sides of one movement to |X| (and fans multi-recipient / multi-reward\n // payouts up to their protocol total) with no double-count. Gas /\n // service-fee actions are tx cost, not subject value, so excluded;\n // \"fee\" is kept because claim_block_reward uses it for the\n // validator-reward fan-out.\n const SUBJECT_RECEIPT_ACTIONS = new Set([\n \"mint\",\n \"burn\",\n \"stake\",\n \"claim\",\n \"fee\",\n \"transfer\",\n \"consume\",\n ]);\n const FEE_LIKE_RECEIPT_ACTIONS = new Set([\"gas\", \"service-fee\", \"service_fee\"]);\n for (const r of txReceipts) {\n for (const ch of r.changes ?? []) {\n if (typeof ch.action !== \"string\") continue;\n if (FEE_LIKE_RECEIPT_ACTIONS.has(ch.action)) continue;\n if (!SUBJECT_RECEIPT_ACTIONS.has(ch.action)) continue;\n if (typeof ch.value !== \"string\" || ch.value === \"\") continue;\n const target = typeof ch.target === \"string\" ? ch.target : \"\";\n // Back-compat allowance: legacy mocks omit `target` on the change.\n // We only require a target when we actually have a tokenSymbols\n // list to disambiguate against; otherwise fall through to the\n // fallback token branch below.\n if (!target && tokenInfoByAddr.size > 0) continue;\n if (target && tokenInfoByAddr.has(target)) {\n const info = tokenInfoByAddr.get(target)!;\n legs.push({\n kind: \"token\",\n target,\n symbol: info.symbol,\n decimal: info.decimal,\n value: ch.value,\n });\n } else if (target && tokenInfoByAddr.size > 0) {\n // Target is not a known token AND we have a tokenSymbols list:\n // treat as an asset receipt. The known-token guard prevents\n // asset-mint \"1\" placeholders from rendering as 1 wei.\n legs.push({ kind: \"asset\", target });\n } else {\n // Back-compat: tokenSymbols missing (legacy mocks / minimal\n // indexer payloads) OR target absent — fall back to treating\n // the change as a token leg with the first tokenSymbols entry\n // (or native ABT defaults) so older mint_token fixtures still\n // surface their value.\n legs.push({\n kind: \"token\",\n target: target || fallbackTokenAddr,\n symbol: fallbackTokenInfo.symbol,\n decimal: fallbackTokenInfo.decimal,\n value: ch.value,\n });\n }\n }\n }\n\n // 2. FALLBACK source — itxJson intent. Only consulted when receipts\n // carried no subject value (pending txs, or receipt-less indexer\n // payloads). Skipped for NO_TOKEN_VALUE_TX_TYPES whose envelope `value`\n // is an asset-count placeholder (\"1\"), not wei.\n if (legs.length === 0 && !isNoTokenValueTx) {\n // 2a. Singleton itxJson.token (mint_token / burn / ...)\n if (token && typeof token.value === \"string\") pushTokenLeg(token.address, token.value);\n // 2b. transfer_v2 top-level tokens[]\n for (const t of itxTokens ?? []) pushTokenLeg(t.address, t.value);\n // 2c+2d. v3 inputs[] / outputs[] are the two SIDES of one movement, not\n // independent legs: a balanced transfer lists the same token+amount\n // on both sides, so summing them double-counts (the transfer_v3 \"2x\n // value\" bug this fallback must not reintroduce). Take the per-token\n // net = max(inputTotal, outputTotal): equal sides collapse to the\n // amount (transfer), input-only survives (stake, no outputs),\n // output-only survives (claim, no inputs).\n const sideTotals = (side: typeof itxInputs): Map<string, bigint> => {\n const totals = new Map<string, bigint>();\n for (const entry of side ?? []) {\n for (const t of entry.tokens ?? []) {\n if (typeof t.value !== \"string\" || t.value === \"\") continue;\n let v: bigint;\n try {\n v = BigInt(t.value);\n } catch (_) {\n continue;\n }\n const addr =\n typeof t.address === \"string\" && t.address.length > 0 ? t.address : fallbackTokenAddr;\n totals.set(addr, (totals.get(addr) ?? BigInt(0)) + v);\n }\n }\n return totals;\n };\n const inTotals = sideTotals(itxInputs);\n const outTotals = sideTotals(itxOutputs);\n for (const addr of new Set([...inTotals.keys(), ...outTotals.keys()])) {\n const inV = inTotals.get(addr) ?? BigInt(0);\n const outV = outTotals.get(addr) ?? BigInt(0);\n const net = inV > outV ? inV : outV;\n pushTokenLeg(addr, net.toString());\n }\n // 2e. Assets - dedupe DIDs across inputs / outputs / legacy top-level\n // assets[]. A transfer lists the same asset DID on both sides;\n // counting both would double the \"N Asset\" count.\n const assetDids = new Set<string>();\n const collectAssetDids = (assets: unknown) => {\n if (!Array.isArray(assets)) return;\n for (const a of assets) {\n const addr = typeof a === \"string\" ? a : (a as { address?: string } | null)?.address;\n if (typeof addr === \"string\" && addr.length > 0) assetDids.add(addr);\n }\n };\n for (const entry of itxInputs ?? []) collectAssetDids(entry.assets);\n for (const entry of itxOutputs ?? []) collectAssetDids(entry.assets);\n collectAssetDids(itxJson.assets);\n for (const did of assetDids) legs.push({ kind: \"asset\", target: did });\n // 2f. legacy transfer top-level value (native ABT) - only when nothing\n // else surfaced.\n if (legs.length === 0 && typeof itxJson.value === \"string\" && itxJson.value !== \"\") {\n pushTokenLeg(undefined, itxJson.value);\n }\n }\n\n // 3. Aggregate. Token legs: sum positive values per (target). Asset legs:\n // collapse into a single \"Asset\" group with a count.\n type TokenGroup = {\n kind: \"token\";\n target: string;\n symbol: string;\n decimal: number;\n total: bigint;\n };\n const tokenGroups = new Map<string, TokenGroup>();\n const tokenOrder: string[] = [];\n let assetCount = 0;\n for (const leg of legs) {\n if (leg.kind === \"token\") {\n let v: bigint;\n try {\n v = BigInt(leg.value);\n } catch (_) {\n continue;\n }\n const positive = v > BigInt(0) ? v : BigInt(0);\n const existing = tokenGroups.get(leg.target);\n if (existing) {\n existing.total += positive;\n } else {\n tokenGroups.set(leg.target, {\n kind: \"token\",\n target: leg.target,\n symbol: leg.symbol,\n decimal: leg.decimal,\n total: positive,\n });\n tokenOrder.push(leg.target);\n }\n } else {\n assetCount++;\n }\n }\n type Group = TokenGroup | { kind: \"asset\"; count: number };\n const groups: Group[] = [];\n for (const k of tokenOrder) {\n const g = tokenGroups.get(k);\n if (g && g.total > BigInt(0)) groups.push(g);\n }\n if (assetCount > 0) groups.push({ kind: \"asset\", count: assetCount });\n\n // 4. Compose Value column fields from the principal group.\n const principal = groups[0];\n let txValue: string | undefined;\n let txDecimal: number | undefined;\n let txSymbol: string | undefined;\n if (principal && principal.kind === \"token\") {\n txValue = principal.total.toString();\n txDecimal = principal.decimal;\n txSymbol = principal.symbol;\n } else if (principal && principal.kind === \"asset\") {\n txValue = String(principal.count);\n txDecimal = 0;\n txSymbol = \"Asset\";\n }\n const _valueLegCount = groups.length;\n const _valueLegCountSuffix = _valueLegCount > 1 ? ` · +${_valueLegCount - 1} more` : \"\";\n const gasFeeRaw = String(itx.gasFee ?? \"0\");\n const gasPaidRaw = String((itx as { gasPaid?: unknown }).gasPaid ?? \"0\");\n const serviceFeeRaw = String(itx.serviceFee ?? \"0\");\n // ABT chains let stakers earn a gas-fee exemption: the chain still\n // *quotes* `gasFee` (so the cost is visible) but settles `gasPaid` to 0\n // when the sender qualifies. The strikethrough on the FEE column reads\n // \"this would have cost X but you got it for free because you've staked\".\n // It's an intentional signal, not visual noise — we keep the heuristic\n // identical to the chain protocol's own \"exemption granted\" semantics.\n const gasExempted = gasFeeRaw !== \"0\" && (gasPaidRaw === \"0\" || gasPaidRaw === \"\");\n // Method-color enrichment — chain-specific protocol knowledge stays in\n // the chain provider. The UI's generic colored-badge formatter reads\n // `_methodColor` per row without owning any tx-type → palette mapping.\n const methodGroup = getTxGroup(tx.type || \"\");\n const methodColor = getTxColor(tx.type || \"\");\n return {\n _typeName: formatTxTypeName(tx.type || \"\"),\n _statusIntent: txStatusIntent(tx.code),\n _statusLabel: tx.code === \"OK\" ? \"Success\" : tx.code || \"\",\n _resolvedReceiver: tx.receiver || itxTo || itxOutputOwner || null,\n _itxTokenSymbol: tokenSymbols?.[0]?.symbol,\n _itxTokenDecimal: tokenSymbols?.[0]?.decimal,\n // Companion to _itxTokenSymbol — the bridge / inline-tx Token\n // column uses this as `linkValueKey` so the symbol cell links to\n // the token detail page. Empty string keeps `linkValueKey` from\n // wiring a broken anchor when the tx has no token leg.\n _itxTokenAddress: tokenSymbols?.[0]?.address ?? \"\",\n _itxAmount: token?.value,\n _itxBlockHeight:\n (itxJson.height as number | undefined) ?? (itxJson.blockHeight as number | undefined),\n value: txValue,\n decimal: txDecimal,\n symbol: txSymbol,\n _valueLegCount: txValue !== undefined ? _valueLegCount : undefined,\n _valueLegCountSuffix,\n _gasFeeRaw: gasFeeRaw,\n _gasExempted: gasExempted,\n _gasStyle: gasExempted ? { textDecoration: \"line-through\", opacity: \"0.55\" } : {},\n // E0 — accompany the strikethrough with a positive caption so first-time\n // users read the visual as \"you saved on this fee\" instead of \"the fee\n // was rejected\". Empty string when the chain actually charged the fee.\n _gasExemptedNote: gasExempted ? \"Saved by staking ABT\" : \"\",\n _serviceFeeRaw: serviceFeeRaw,\n _methodGroup: methodGroup,\n _methodColor: methodColor,\n };\n }\n\n private buildTxEntries(result: PagedResult<IndexedTransaction>): AFSEntry[] {\n return result.items.map((tx) => {\n const itxJson = (tx.tx?.itxJson as Record<string, unknown>) || {};\n const parties = resolveTxParties(tx);\n if (parties.sender) tx.sender = parties.sender;\n if (parties.receiver) tx.receiver = parties.receiver;\n return {\n ...this.buildEntry(joinURL(\"/transactions\", tx.hash), {\n content: { ...tx, ...this.enrichTxContent(tx, itxJson) },\n meta: { kind: tx.type ? `ocap:transaction:${tx.type}` : \"ocap:transaction\" },\n }),\n summary: `${tx.type}: ${tx.sender} → ${tx.receiver}`,\n };\n });\n }\n\n private buildBlockEntries(\n rollupAddr: string,\n result: PagedResult<IndexedRollupBlock>,\n ): AFSEntry[] {\n return result.items.map((b) => ({\n ...this.buildEntry(joinURL(\"/bridges\", rollupAddr, \"blocks\", b.hash), {\n content: { ...b, tokenDecimal: b.tokenInfo?.decimal },\n meta: { kind: \"ocap:rollup-block\" },\n }),\n summary: `Block #${b.height} • ${b.txs?.length ?? 0} txs`,\n }));\n }\n\n // ============ Root ============\n\n @Read(\"/\")\n async readRoot(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n await this.resolveNameOnce();\n const minPage = { size: 1, offset: 0 };\n const ttl = AFSOCAP.CHAIN_TTL_MS;\n\n // Phase 0.2 A.4 — accountCount comes from `numDeclareTxs[-1]` (chain-wide\n // cumulative declare transactions), matching what the legacy\n // block-explorer surfaces as \"Accounts\" (~76k on main). The indexer's\n // listTopAccounts.total is the count of currently-active state rows\n // (~9.8k on main) and would silently regress users from the old UI.\n //\n // Each source call is memoized so concurrent handlers (root + microbar)\n // and back-to-back navigations within the TTL window dedupe upstream\n // GQL traffic. Validators are NOT fetched — the homepage doesn't bind\n // validatorCount, and no other root-level surface needs it.\n const [info, forgeStats, tokens, assets, factories, bridges, stakes] = await Promise.all([\n this.memoize(\"getChainInfo\", ttl, () => this.source.getChainInfo()),\n this.memoize(\"getForgeStats\", ttl, () => this.source.getForgeStats()).catch(() => null),\n this.memoize(\"listTokens:size1\", ttl, () => this.source.listTokens(minPage)).catch(() => ({\n total: 0,\n })),\n this.memoize(\"listAssets:size1\", ttl, () => this.source.listAssets(minPage)).catch(() => ({\n total: 0,\n })),\n this.memoize(\"listFactories:size1\", ttl, () => this.source.listFactories(minPage)).catch(\n () => ({ total: 0 }),\n ),\n this.memoize(\"listRollups:size1\", ttl, () => this.source.listRollups(minPage)).catch(() => ({\n total: 0,\n })),\n this.memoize(\"listStakes:size1\", ttl, () => this.source.listStakes(minPage)).catch(() => ({\n total: 0,\n })),\n ]);\n\n const accountCount = this.computeAccountCount(forgeStats);\n const numTxs = this.parseSafeCount(info.totalTxs);\n\n return this.buildEntry(\"/\", {\n content: {\n ...info,\n accountCount,\n tokenCount: tokens.total,\n assetCount: assets.total,\n factoryCount: factories.total,\n bridgeCount: bridges.total,\n stakeCount: stakes.total,\n numTxs,\n },\n meta: {\n kind: \"ocap:chain\",\n childrenCount: TOP_LEVEL_DIRS.length,\n },\n });\n }\n\n /**\n * Phase 0.5 B.1 — chainInfo.totalTxs is a string from GraphQL (\"5000\").\n * Same regex + BigInt clamp story as `computeAccountCount`: reject anything\n * that isn't a base-10 unsigned integer to keep \"1e308\" and negatives out\n * of the renderer, then clamp to MAX_SAFE_INTEGER so JSON serialization\n * stays lossless.\n */\n private parseSafeCount(raw: unknown): number {\n if (typeof raw !== \"string\" || raw.length === 0) return 0;\n if (!/^\\d+$/.test(raw)) return 0;\n const big = BigInt(raw);\n if (big > BigInt(Number.MAX_SAFE_INTEGER)) return Number.MAX_SAFE_INTEGER;\n return Number(big);\n }\n\n /**\n * Phase 0.2 A.10 — Convert the last `numDeclareTxs` entry (a string from\n * GraphQL) to a JS number, with explicit BigInt-then-bounds guard so a\n * malicious / corrupt payload like \"1e308\" or \"9\".repeat(40) cannot wrap\n * around to Infinity or lose precision via Number() coercion.\n *\n * Returns 0 when the source is unavailable; callers can detect \"no data\"\n * vs \"0 declare txs\" by checking forgeStats null upstream.\n */\n private computeAccountCount(\n forgeStats: { forgeStats: { numDeclareTxs: string[] } } | null,\n ): number {\n const arr = forgeStats?.forgeStats?.numDeclareTxs;\n if (!Array.isArray(arr) || arr.length === 0) return 0;\n const last = arr[arr.length - 1];\n if (typeof last !== \"string\" || last.length === 0) return 0;\n // Reject anything that isn't a base-10 unsigned integer string —\n // BigInt(non-numeric) throws and we don't want to surface cryptic GQL\n // payloads to the renderer.\n if (!/^\\d+$/.test(last)) return 0;\n const big = BigInt(last);\n // JS-safe integer cap; values above this would lose precision when\n // serialized as JSON numbers. The realistic chain count is ~76k now,\n // so the safe ceiling is comfortably distant.\n if (big > BigInt(Number.MAX_SAFE_INTEGER)) return Number.MAX_SAFE_INTEGER;\n return Number(big);\n }\n\n /**\n * Phase 1.1 — `/_microbar` aggregator powering the chain-explorer header\n * micro-bar. The renderer can't fan out to multiple sources cheaply, so\n * the provider produces a single object containing chain.height +\n * sync flag + native-token price + 24h change.\n *\n * Price fetch is best-effort (Promise.allSettled): a slow upstream MUST\n * NOT block chain navigation. When unavailable, tokens[i].price is null\n * and tokens[i].stale is true so the renderer can show a dim \"—\".\n */\n @Read(\"/_microbar\")\n async readMicrobar(ctx: RouteContext): Promise<AFSEntry | undefined> {\n // Resolve the native token first — it's cached for the provider's\n // lifetime so this is a single round-trip on the cold path and a\n // pointer-deref on every subsequent call. With the address known we\n // can fold the chain-info query and the price fetch into a single\n // Promise.all, eliminating the previous serial wait on price.\n const native = await this.resolveNativeToken();\n\n const [info, priceValue] = await Promise.all([\n this.memoize(\"getChainInfo\", AFSOCAP.CHAIN_TTL_MS, () => this.source.getChainInfo()),\n native ? this.getPriceBySymbol(native.symbol).catch(() => null) : Promise.resolve(null),\n ]);\n\n const tokenEntries: Array<Record<string, unknown>> = [];\n if (native) {\n if (priceValue) {\n tokenEntries.push({\n symbol: (priceValue.symbol as string | undefined) ?? native.symbol,\n address: native.address,\n price: priceValue.price ?? null,\n change24h: priceValue.change24h ?? null,\n currency: priceValue.currency ?? \"USD\",\n stale: Boolean(priceValue.stale),\n fetchedAt: priceValue.fetchedAt ?? null,\n });\n } else {\n // Cold cache + upstream down — emit a placeholder so the renderer\n // can still show the symbol in a stale state. Hiding the header\n // entirely on price-API failure is worse UX.\n tokenEntries.push({\n symbol: native.symbol,\n address: native.address,\n price: null,\n change24h: null,\n currency: \"USD\",\n stale: true,\n fetchedAt: null,\n });\n }\n }\n\n // AUP template substitution only supports single-level dot access\n // (`${content.field}`), so flatten the native-token fields onto the top\n // level. The nested `tokens[]` array is preserved for callers that want\n // to enumerate beyond the native token.\n const flat = tokenEntries[0];\n return this.buildEntry(ctx.path, {\n content: {\n chainHeight: this.parseSafeCount(info.blockHeight),\n synced: Boolean(info.synced),\n moniker: info.moniker || \"\",\n nativeSymbol: flat?.symbol ?? null,\n nativePrice: flat?.price ?? null,\n nativeChange24h: flat?.change24h ?? null,\n nativeCurrency: flat?.currency ?? \"USD\",\n nativeStale: flat ? Boolean(flat.stale) : false,\n tokens: tokenEntries,\n },\n // visibility:\"hidden\" keeps /_microbar out of afs-list (R2 filter); the\n // type only formally enumerates \"full\"/\"meta\" but the list pipeline\n // also filters on \"hidden\", matching utils.ts's dotfile policy.\n meta: { kind: \"ocap:microbar\", visibility: \"hidden\" as never },\n });\n }\n\n // ============ Config ============\n\n @Read(\"/config\")\n async readConfig(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const cfg = (await this.source.getConfig()) as Record<string, unknown>;\n const tx = (cfg.transaction ?? {}) as Record<string, unknown>;\n const txSize = (tx.maxTxSize ?? {}) as Record<string, number>;\n const txFee = (tx.txFee ?? {}) as Record<string, number>;\n const txGas = (tx.txGas ?? {}) as Record<string, unknown>;\n const txStake = (tx.txStake ?? {}) as Record<string, unknown>;\n const supported = (tx.supportedTxs ?? []) as string[];\n\n const strip = (s: string) => s.replace(/^fg:t:/, \"\");\n const group = (keys: string[]) =>\n keys\n .filter((k) => supported.includes(k))\n .map(strip)\n .join(\", \") || \"—\";\n\n const content = {\n maxAssetSize: tx.maxAssetSize,\n maxListSize: tx.maxListSize,\n maxMultisig: tx.maxMultisig,\n defaultMaxTxSize: txSize.default,\n\n gasPrice: txGas.price,\n gasCreateState: txGas.createState,\n gasUpdateState: txGas.updateState,\n gasDataStorage: txGas.dataStorage,\n gasMinStake: txGas.minStake,\n gasMaxStake: txGas.maxStake,\n gasStakeLockPeriod: txGas.stakeLockPeriod,\n\n feeDefault: txFee.default ?? 0,\n feeCreateAsset: txFee[\"fg:t:create_asset\"] ?? 0,\n feeMintAsset: txFee[\"fg:t:mint_asset\"] ?? 0,\n feeCreateFactory: txFee[\"fg:t:create_factory\"] ?? 0,\n feeCreateToken: txFee[\"fg:t:create_token\"] ?? 0,\n feeCreateRollup: txFee[\"fg:t:create_rollup\"] ?? 0,\n feeUpdateTokenFactory: txFee[\"fg:t:update_token_factory\"] ?? 0,\n\n stakeCreateToken: txStake.createToken,\n stakeCreateCreditToken: txStake.createCreditToken,\n stakeCreateTokenLockPeriod: txStake.createTokenLockPeriod,\n\n txGroupAccount: group([\"fg:t:account_migrate\", \"fg:t:delegate\", \"fg:t:revoke_delegate\"]),\n txGroupTrade: group([\n \"fg:t:transfer\",\n \"fg:t:transfer_v2\",\n \"fg:t:transfer_v3\",\n \"fg:t:exchange_v2\",\n ]),\n txGroupAsset: group([\n \"fg:t:create_asset\",\n \"fg:t:update_asset\",\n \"fg:t:consume_asset\",\n \"fg:t:acquire_asset_v2\",\n \"fg:t:acquire_asset_v3\",\n \"fg:t:mint_asset\",\n \"fg:t:create_factory\",\n ]),\n txGroupToken: group([\n \"fg:t:create_token\",\n \"fg:t:deposit_token_v2\",\n \"fg:t:withdraw_token_v2\",\n \"fg:t:create_token_factory\",\n \"fg:t:update_token_factory\",\n \"fg:t:mint_token\",\n \"fg:t:burn_token\",\n ]),\n txGroupGovernance: group([\n \"fg:t:stake\",\n \"fg:t:revoke_stake\",\n \"fg:t:claim_stake\",\n \"fg:t:slash_stake\",\n \"fg:t:return_stake\",\n ]),\n txGroupRollup: group([\n \"fg:t:create_rollup\",\n \"fg:t:update_rollup\",\n \"fg:t:pause_rollup\",\n \"fg:t:resume_rollup\",\n \"fg:t:close_rollup\",\n \"fg:t:join_rollup\",\n \"fg:t:leave_rollup\",\n \"fg:t:create_rollup_block\",\n \"fg:t:migrate_rollup\",\n \"fg:t:claim_block_reward\",\n ]),\n };\n return this.buildEntry(\"/config\", {\n content,\n meta: { kind: \"ocap:config\" },\n });\n }\n\n // ============ Validators ============\n\n @List(\"/validators\")\n async listValidators(_ctx: RouteContext): Promise<AFSListResult> {\n const validators = await this.source.getValidatorsInfo();\n const entries = validators.map((v) => ({\n ...this.buildEntry(joinURL(\"/validators\", v.address), {\n content: v,\n meta: { kind: \"ocap:validator\" },\n }),\n summary: `${v.name || v.address} • voting power: ${v.votingPower}`,\n }));\n return { data: entries };\n }\n\n @Read(\"/validators/:address\")\n async readValidator(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const validators = await this.source.getValidatorsInfo();\n const v = validators.find((x) => x.address === ctx.params.address);\n if (!v) throw new AFSNotFoundError(ctx.path);\n return {\n ...this.buildEntry(ctx.path, {\n content: v,\n meta: { kind: \"ocap:validator\" },\n }),\n summary: `${v.name || v.address} • voting power: ${v.votingPower}`,\n };\n }\n\n // ============ Transactions ============\n\n @List(\"/transactions\")\n async listTransactions(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const filters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, filters);\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/transactions/:hash\")\n async readTransaction(ctx: RouteContext<{ hash: string }>): Promise<AFSEntry | undefined> {\n const tx = await this.source.getTx(ctx.params.hash);\n if (!tx) throw new AFSNotFoundError(ctx.path);\n // Enrich missing top-level fields from nested tx object (OCAP v3 format)\n const itx = (tx.tx as Record<string, unknown>) || {};\n const itxJson = (itx.itxJson as Record<string, unknown>) || {};\n if (!tx.type && typeof itxJson.type_url === \"string\") {\n // \"fg:t:transfer_v3\" → \"transfer_v3\"\n tx.type = (itxJson.type_url as string).split(\":\").pop() || \"\";\n }\n const parties = resolveTxParties(tx);\n if (parties.sender) tx.sender = parties.sender;\n if (parties.receiver) tx.receiver = parties.receiver;\n\n // Phase 1.6 — derive prev/next neighbours via a tight time-window query.\n // listTransactions failure must not crash the read; the navigation\n // buttons just stay disabled (both null).\n const { prevHash, nextHash } = await this.findTxNeighbours(tx.time, tx.hash);\n\n // Phase 0.6 polish — common enrichment (status, value/decimal/symbol,\n // gas/service fee raws, etc.) lives in enrichTxContent so list and\n // detail render identically.\n const shared = this.enrichTxContent(\n tx as IndexedTransaction & { tokenSymbols?: Array<{ symbol?: string; decimal?: number }> },\n itxJson,\n );\n\n const resolvedReceiver = (shared._resolvedReceiver as string | null) || \"\";\n return {\n ...this.buildEntry(ctx.path, {\n content: {\n ...tx,\n ...shared,\n // Detail-only enrichments below — never sent on list payloads.\n _prevHash: prevHash,\n _nextHash: nextHash,\n _receiverPath: this.resolveNavPath(resolvedReceiver),\n _itxJson: itxJson,\n _itxTo: itxJson.to as string | undefined,\n _itxAddress: itxJson.address as string | undefined,\n _itxMoniker: itxJson.moniker as string | undefined,\n _itxFactory: itxJson.factory as string | undefined,\n _itxTokenFactory:\n (itxJson.tokenFactory as string | undefined) ||\n (itxJson.token_factory as string | undefined),\n _itxRollup: itxJson.rollup as string | undefined,\n _itxBlockHash:\n (itxJson.hash as string | undefined) ?? (itxJson.blockHash as string | undefined),\n _itxInputOwner: (itxJson.inputs as Array<{ owner?: string }> | undefined)?.[0]?.owner,\n _itxOutputOwner: (itxJson.outputs as Array<{ owner?: string }> | undefined)?.[0]?.owner,\n // Per-tx-type label dispatch for the Type Info card. Lets the\n // page render \"Token DID\" / \"Asset DID\" / \"Rollup Block Hash\"\n // instead of the ambiguous generic \"Address\" / \"Block Hash\".\n _typeContext: deriveTypeContext(tx.type),\n _hasReceipts:\n Array.isArray(tx.receipts) &&\n (tx.receipts as Array<{ changes?: unknown[] }>).some(\n (r) => (r.changes?.length ?? 0) > 0,\n ),\n _nonce: itx.nonce as number | string | undefined,\n // Pre-formatted fee strings retained for back-compat with the\n // legacy per-tx-type templates (now mostly unused after Phase\n // 0.5b deletion, but cheap to keep).\n _gasFeeFormatted: (() => {\n const fee = String(itx.gasFee ?? \"0\");\n if (!fee || fee === \"0\") return \"0 ABT\";\n return `${formatBignumValue(fee, 18).replace(/^\\+/, \"\")} ABT`;\n })(),\n _serviceFeeFormatted: (() => {\n const fee = String(itx.serviceFee ?? \"0\");\n if (!fee || fee === \"0\") return \"0 ABT\";\n return `${formatBignumValue(fee, 18).replace(/^\\+/, \"\")} ABT`;\n })(),\n // B3 — Service Fee=0 reads as \"Free\" rather than the literal \"0 ABT\"\n // that confused users into thinking they were charged. Detail page\n // binds this directly so the renderer doesn't need to reason about\n // sentinels.\n _serviceFeeDisplay: (() => {\n const fee = String(itx.serviceFee ?? \"0\");\n if (!fee || fee === \"0\") return \"Free\";\n return `${formatBignumValue(fee, 18).replace(/^\\+/, \"\")} ABT`;\n })(),\n },\n meta: { kind: tx.type ? `ocap:transaction:${tx.type}` : \"ocap:transaction\" },\n }),\n summary: `${tx.type || \"tx\"}: ${tx.sender} → ${tx.receiver}`,\n };\n }\n\n @Read(\"/transactions/:hash/receipts\")\n async readTxReceiptsDir(ctx: RouteContext<{ hash: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:receipt\", childrenCount: -1 },\n });\n }\n\n @List(\"/transactions/:hash/receipts\")\n async listTxReceipts(ctx: RouteContext<{ hash: string }>): Promise<AFSListResult> {\n return { data: await this._buildReceiptEntries(ctx.params.hash, ctx.path) };\n }\n\n @Read(\"/transactions/:hash/receipts/:idx\")\n async readTxReceiptEntry(\n ctx: RouteContext<{ hash: string; idx: string }>,\n ): Promise<AFSEntry | undefined> {\n const entries = await this._buildReceiptEntries(ctx.params.hash, joinURL(ctx.path, \"..\"));\n const entry = entries[Number(ctx.params.idx)];\n if (!entry) throw new AFSNotFoundError(ctx.path);\n return entry;\n }\n\n /**\n * Phase 1.6 — find adjacent tx hashes by querying a tight time window\n * around the current tx and selecting the immediate neighbours after\n * sorting by time desc. Returns nulls for missing neighbours (newest /\n * oldest tx). Failure of listTransactions must NOT propagate — the\n * detail page still needs to render even when the indexer is down.\n */\n private async findTxNeighbours(\n txTime: string,\n currentHash: string,\n ): Promise<{ prevHash: string | null; nextHash: string | null }> {\n if (!txTime || !currentHash) return { prevHash: null, nextHash: null };\n const t = Date.parse(txTime);\n if (!Number.isFinite(t)) return { prevHash: null, nextHash: null };\n const WINDOW_MS = 60_000; // ±60s; tx rate on real chains keeps this list small\n const startDateTime = new Date(t - WINDOW_MS).toISOString();\n const endDateTime = new Date(t + WINDOW_MS).toISOString();\n try {\n const res = await this.source.listTransactions(\n { size: 50, offset: 0 },\n { timeFilter: { startDateTime, endDateTime } },\n );\n const items = (res?.items ?? []) as Array<{ hash: string; time: string }>;\n // Sort by time desc; tie-break on hash for determinism\n const sorted = items.slice().sort((a, b) => {\n const dt = Date.parse(b.time) - Date.parse(a.time);\n if (dt !== 0) return dt;\n return a.hash < b.hash ? -1 : 1;\n });\n // Find the FIRST occurrence of the current hash (dedupe defence)\n const idx = sorted.findIndex((it) => it.hash === currentHash);\n if (idx < 0) return { prevHash: null, nextHash: null };\n // \"next\" = newer (earlier in desc-sorted array); \"prev\" = older\n const next = sorted.slice(0, idx).find((it) => it.hash !== currentHash);\n const prev = sorted.slice(idx + 1).find((it) => it.hash !== currentHash);\n return {\n prevHash: prev?.hash ?? null,\n nextHash: next?.hash ?? null,\n };\n } catch {\n return { prevHash: null, nextHash: null };\n }\n }\n\n private async _buildReceiptEntries(hash: string, basePath: string): Promise<AFSEntry[]> {\n const tx = await this.source.getTx(hash);\n if (!tx) return [];\n\n type ReceiptChange = { action?: string; target?: string; value?: string };\n type Receipt = { address?: string; changes?: ReceiptChange[] };\n\n const receipts = (tx.receipts as Receipt[]) ?? [];\n const tokenSymbols =\n (tx.tokenSymbols as Array<{ address: string; symbol: string; decimal: number }>) ?? [];\n const symbolMap = new Map(tokenSymbols.map((t) => [t.address, t]));\n\n // change.target can be either a token address (fungible, value is wei\n // with decimal) OR an asset address (NFT-like, value is an integer\n // count, no decimal scaling). tokenSymbols only covers tokens, so any\n // target not found there might be an asset — parallel-look up the\n // unknowns via getAssetState. Failures are silent: an unknown target\n // falls back to raw integer display, which is safer than misrendering\n // a 1-asset transfer as 0.000000000000000001 ABT.\n const unknownTargets = new Set<string>();\n for (const r of receipts) {\n for (const c of r.changes ?? []) {\n if (c.target && !symbolMap.has(c.target)) unknownTargets.add(c.target);\n }\n }\n const assetMap = new Map<string, { moniker?: string }>();\n if (unknownTargets.size > 0) {\n await Promise.all(\n Array.from(unknownTargets).map(async (addr) => {\n try {\n const a = await this.source.getAssetState(addr);\n if (a) assetMap.set(addr, a as { moniker?: string });\n } catch {\n // Ignore — target stays unknown, falls back to raw value display.\n }\n }),\n );\n }\n\n const entries: AFSEntry[] = [];\n let idx = 0;\n for (const receipt of receipts) {\n for (const change of receipt.changes ?? []) {\n const target = change.target ?? \"\";\n const rawValue = change.value ?? \"0\";\n const tokenInfo = symbolMap.get(target);\n const assetInfo = assetMap.get(target);\n\n let targetKind: \"token\" | \"asset\" | \"unknown\";\n let symbol: string;\n let valueFormatted: string;\n if (tokenInfo) {\n targetKind = \"token\";\n symbol = tokenInfo.symbol;\n valueFormatted = formatBignumValue(rawValue, tokenInfo.decimal);\n } else if (assetInfo) {\n targetKind = \"asset\";\n // Show the moniker when the asset advertises one, otherwise fall\n // back to the generic \"Asset\" label — never leave the cell empty\n // and never inherit the wrong \"ABT\" default from token symbols.\n symbol = assetInfo.moniker || \"Asset\";\n valueFormatted = rawValue; // integer count, no decimal scaling\n } else {\n targetKind = \"unknown\";\n symbol = \"—\";\n valueFormatted = rawValue;\n }\n\n entries.push(\n this.buildEntry(joinURL(basePath, String(idx)), {\n content: {\n account: receipt.address ?? \"\",\n action: change.action ?? \"\",\n target,\n targetKind,\n symbol,\n value: rawValue,\n valueFormatted,\n // _tokenLink — populated only when the receipt's target is\n // a token (not an asset, not unknown). The Token column on\n // the tx detail Receipts tab uses this as `linkValueKey`\n // so the symbol cell becomes a clickable link to the\n // token detail page; rows whose target is an asset / has\n // no resolved kind render the symbol as plain text.\n _tokenLink: targetKind === \"token\" ? target : \"\",\n },\n meta: { kind: \"ocap:receipt\" },\n }),\n );\n idx++;\n }\n }\n return entries;\n }\n\n // ============ Accounts ============\n\n @List(\"/accounts\")\n async listAccounts(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const result = await this.source.listTopAccounts(paging);\n const entries = result.items.map((a) => ({\n // B6 — when `moniker` is just the address echoed back (no human name set\n // on chain), surface \"—\" instead of duplicating the Address column.\n // The renderer can't make this judgement without the address it would\n // need to compare against, so we strip the duplicate at the provider.\n ...this.buildEntry(joinURL(\"/accounts\", a.address), {\n content: { ...a, _monikerDisplay: displayMoniker(a.moniker, a.address) },\n meta: { kind: \"ocap:account\", childrenCount: 7 },\n }),\n summary: `${a.moniker || a.address} • ${a.balance}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/accounts/:address\")\n async readAccount(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const state = await this.source.getAccountState(ctx.params.address);\n if (!state) throw new AFSNotFoundError(ctx.path);\n const content = {\n ...state,\n migratedToFirst: state.migratedTo?.[0],\n migratedFromFirst: state.migratedFrom?.[0],\n // Phase 0.5d B.4 — granular role label for the header pill, decoded\n // from the DID role byte (Validator / Bot / Node / Application /\n // Account / etc.). The generic `resolveDidRole` flattens these all\n // into \"account\" — fine for routing, useless for display.\n _roleLabel: resolveDidRoleLabel(ctx.params.address) ?? \"Account\",\n _hasMigration:\n (Array.isArray(state.migratedFrom) && state.migratedFrom.length > 0) ||\n (Array.isArray(state.migratedTo) && state.migratedTo.length > 0),\n };\n return {\n ...this.buildEntry(ctx.path, {\n content,\n meta: { kind: \"ocap:account\", childrenCount: 7 },\n }),\n summary: `${state.moniker || state.address} • ${state.balance}`,\n };\n }\n\n @List(\"/accounts/:address\")\n async listAccountChildren(ctx: RouteContext<{ address: string }>): Promise<AFSListResult> {\n if (ctx.params.address.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const entries = [\n \"tokens\",\n \"assets\",\n \"stakes\",\n \"delegates\",\n \"transactions\",\n \"migration\",\n \"token-flows\",\n ].map((sub) => buildDirEntry(ctx.path, sub));\n return { data: entries };\n }\n\n @Read(\"/accounts/:addr/tokens\")\n async readAccountTokensDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:token\", childrenCount: -1 },\n });\n }\n\n @Read(\"/accounts/:addr/assets\")\n async readAccountAssetsDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:asset\", childrenCount: -1 },\n });\n }\n\n @Read(\"/accounts/:addr/transactions\")\n async readAccountTxDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/accounts/:addr/tokens\")\n async listAccountTokens(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const tokens = await this.source.getAccountTokens(ctx.params.addr);\n // Entries point at the GLOBAL token detail path so a row click on the\n // account's tokens tab opens the token's own page (holders, supply,\n // metadata) — same convention as the assets tab uses\n // \\`joinURL(\"/assets\", a.address)\\`. The legacy\n // \\`/accounts/<addr>/tokens/<token>\\` path is still served by\n // \\`readAccountToken\\` for direct callers, but the list no longer\n // routes users into that account-scoped (and otherwise empty) view.\n const entries = tokens.map((t) => ({\n ...this.buildEntry(joinURL(\"/tokens\", t.address), {\n content: t,\n meta: { kind: \"ocap:token\" },\n }),\n summary: `${t.symbol} • ${t.balance}`,\n }));\n return { data: entries };\n }\n\n @Meta(\"/accounts/:addr/tokens\")\n async metaAccountTokens(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:token\", childrenCount: -1 },\n });\n }\n\n @Read(\"/accounts/:addr/tokens/:token\")\n async readAccountToken(\n ctx: RouteContext<{ addr: string; token: string }>,\n ): Promise<AFSEntry | undefined> {\n const tokens = await this.source.getAccountTokens(ctx.params.addr);\n const t = tokens.find((x) => x.address === ctx.params.token);\n if (!t) throw new AFSNotFoundError(ctx.path);\n return {\n ...this.buildEntry(ctx.path, {\n content: t,\n meta: { kind: \"ocap:token\" },\n }),\n summary: `${t.symbol} • ${t.balance}`,\n };\n }\n\n @List(\"/accounts/:addr/assets\")\n async listAccountAssets(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractAssetFilters(listOpts(ctx));\n const result = await this.source.listAssets(paging, {\n ...userFilters,\n ownerAddress: ctx.params.addr,\n });\n const entries = result.items.map((a) => ({\n ...this.buildEntry(joinURL(\"/assets\", a.address), {\n content: a,\n meta: { kind: \"ocap:asset\", childrenCount: 2 },\n }),\n summary: `${a.moniker || a.address} • owner: ${a.owner}`,\n }));\n return buildListResult(this.withCurrentAccount(entries, ctx.params.addr), result.total);\n }\n\n @List(\"/accounts/:addr/transactions\")\n async listAccountTransactions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n // accountFilter matches any tx in which the address participates as\n // sender, receiver, asset owner, or token endpoint — including transfer_v3\n // (token transfers) where the top-level sender/receiver fields are empty\n // and the real parties live inside tx.itxJson. addressFilter only matches\n // those top-level fields, so it silently drops every token transfer and\n // most asset-mutating txs (Update/Acquire/Consume Asset, …).\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n accountFilter: { accounts: [ctx.params.addr] },\n });\n const entries = this.withCurrentAccount(this.buildTxEntries(result), ctx.params.addr);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/accounts/:addr/stakes\")\n async readAccountStakesDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:stake\", childrenCount: -1 },\n });\n }\n\n @List(\"/accounts/:addr/stakes\")\n async listAccountStakes(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractStakeFilters(listOpts(ctx));\n const result = await this.source.listStakes(paging, {\n ...userFilters,\n addressFilter: { sender: ctx.params.addr, receiver: ctx.params.addr, direction: \"UNION\" },\n });\n const entries = result.items.map((s) => ({\n ...this.buildEntry(joinURL(\"/stakes\", s.address), {\n content: s,\n meta: { kind: \"ocap:stake\" },\n }),\n summary: `${s.sender} → ${s.receiver}`,\n }));\n return buildListResult(this.withCurrentAccount(entries, ctx.params.addr), result.total);\n }\n\n @Read(\"/accounts/:addr/stakes/sent\")\n async readAccountSentStakesDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:stake\", childrenCount: -1 },\n });\n }\n\n @List(\"/accounts/:addr/stakes/sent\")\n async listAccountSentStakes(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractStakeFilters(listOpts(ctx));\n const result = await this.source.listStakes(paging, {\n ...userFilters,\n addressFilter: { sender: ctx.params.addr },\n });\n const entries = result.items.map((s) => ({\n ...this.buildEntry(joinURL(\"/stakes\", s.address), {\n content: s,\n meta: { kind: \"ocap:stake\" },\n }),\n summary: `${s.sender} → ${s.receiver}`,\n }));\n return buildListResult(this.withCurrentAccount(entries, ctx.params.addr), result.total);\n }\n\n @Read(\"/accounts/:addr/stakes/received\")\n async readAccountReceivedStakesDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:stake\", childrenCount: -1 },\n });\n }\n\n @List(\"/accounts/:addr/stakes/received\")\n async listAccountReceivedStakes(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractStakeFilters(listOpts(ctx));\n const result = await this.source.listStakes(paging, {\n ...userFilters,\n addressFilter: { receiver: ctx.params.addr },\n });\n const items = result.items.map((s) => ({\n ...this.buildEntry(joinURL(\"/stakes\", s.address), {\n content: s,\n meta: { kind: \"ocap:stake\" },\n }),\n summary: `${s.sender} → ${s.receiver}`,\n }));\n const entries = this.withCurrentAccount(items, ctx.params.addr);\n return buildListResult(entries, result.total);\n }\n\n // ── Phase 0.2 — Account migration timeline ────────────────────────────\n // OCAP DIDs can migrate (account_migrate tx). The state exposes a chain\n // of `migratedFrom[]` and `migratedTo[]` addresses. The migration list\n // flattens them into an ordered sequence so AUP can render a timeline.\n\n @Read(\"/accounts/:addr/migration\")\n async readAccountMigrationDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:account:migration\", childrenCount: -1 },\n });\n }\n\n @List(\"/accounts/:addr/migration\")\n async listAccountMigration(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const state = await this.source.getAccountState(ctx.params.addr);\n if (!state) throw new AFSNotFoundError(ctx.path);\n const from = Array.isArray(state.migratedFrom) ? state.migratedFrom : [];\n const to = Array.isArray(state.migratedTo) ? state.migratedTo : [];\n // Order: oldest first (migratedFrom in chain order) → current → newest\n // (migratedTo in chain order). _isLatest marks the most recent address;\n // _isCurrent marks the queried account.\n const ordered: Array<{ address: string; role: \"from\" | \"current\" | \"to\" }> = [\n ...from.map((a) => ({ address: a, role: \"from\" as const })),\n { address: state.address, role: \"current\" as const },\n ...to.map((a) => ({ address: a, role: \"to\" as const })),\n ];\n const lastIdx = ordered.length - 1;\n const entries: AFSEntry[] = ordered.map((step, idx) => ({\n ...this.buildEntry(joinURL(\"/accounts\", step.address), {\n content: {\n address: step.address,\n _migrationRole: step.role,\n _isCurrent: step.role === \"current\",\n _isLatest: idx === lastIdx,\n _index: idx,\n _currentAccount: ctx.params.addr,\n },\n meta: { kind: \"ocap:account:migration:step\" },\n }),\n summary: `${step.role}: ${step.address}`,\n }));\n return buildListResult(entries, entries.length);\n }\n\n // ── Phase 0.2 — Account token flows ───────────────────────────────────\n // Per-token ledger of IN/OUT transfers. Wraps source.listTokenFlows.\n\n @Read(\"/accounts/:addr/token-flows\")\n async readAccountTokenFlowsDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:token-flow\", childrenCount: -1 },\n });\n }\n\n @List(\"/accounts/:addr/token-flows\")\n async listAccountTokenFlows(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const opts = (ctx.options ?? {}) as Record<string, unknown>;\n const tokenAddress = typeof opts.tokenAddress === \"string\" ? opts.tokenAddress : undefined;\n const depth = typeof opts.depth === \"number\" ? opts.depth : undefined;\n const dirRaw = typeof opts.direction === \"string\" ? opts.direction.toUpperCase() : undefined;\n const direction = dirRaw === \"IN\" || dirRaw === \"OUT\" || dirRaw === \"ALL\" ? dirRaw : undefined;\n const result = await this.source.listTokenFlows(ctx.params.addr, paging, {\n tokenAddress,\n depth,\n direction,\n });\n const items = result.items.map((flow) => {\n const isIn = flow.to === ctx.params.addr;\n const counterparty = isIn ? flow.from : flow.to;\n return {\n ...this.buildEntry(joinURL(ctx.path, flow.hash), {\n content: {\n ...flow,\n _direction: isIn ? \"in\" : \"out\",\n _counterparty: counterparty,\n },\n meta: { kind: \"ocap:token-flow:entry\" },\n }),\n summary: `${isIn ? \"in\" : \"out\"}: ${counterparty} • ${flow.value}`,\n };\n });\n const entries = this.withCurrentAccount(items, ctx.params.addr);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/accounts/:addr/delegates\")\n async readAccountDelegatesDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:delegate\", childrenCount: -1 },\n });\n }\n\n @List(\"/accounts/:addr/delegates\")\n async listAccountDelegates(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractDelegationFilters(listOpts(ctx));\n const result = await this.source.listDelegations(paging, {\n ...userFilters,\n from: ctx.params.addr,\n });\n const entries = result.items.map((d) => ({\n ...this.buildEntry(joinURL(\"/delegates\", d.address), {\n content: d,\n meta: { kind: \"ocap:delegate\" },\n }),\n summary: `${d.from} → ${d.to}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n // ============ Tokens ============\n\n @List(\"/tokens\")\n async listTokens(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const filters = extractTokenFilters(listOpts(ctx));\n const result = await this.source.listTokens(paging, filters);\n const entries = result.items.map((t) => ({\n ...this.buildEntry(joinURL(\"/tokens\", t.address), {\n content: t,\n meta: { kind: \"ocap:token\", childrenCount: 2 },\n }),\n summary: `${t.name} (${t.symbol}) • supply: ${t.totalSupply}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/tokens/:address\")\n async readToken(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const state = await this.source.getTokenState(ctx.params.address);\n if (!state) throw new AFSNotFoundError(ctx.path);\n const content = enrichTokenContent(state);\n return {\n ...this.buildEntry(ctx.path, {\n content,\n meta: { kind: \"ocap:token\", childrenCount: 3 },\n }),\n summary: `${state.name} (${state.symbol}) • supply: ${state.totalSupply}`,\n };\n }\n\n @List(\"/tokens/:address\")\n async listTokenChildren(ctx: RouteContext<{ address: string }>): Promise<AFSListResult> {\n if (ctx.params.address.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const entries = [\"holders\", \"transactions\", \"price\"].map((sub) => buildDirEntry(ctx.path, sub));\n return { data: entries };\n }\n\n /**\n * Phase 0.2 A.7 — Pull `{price, change24h}` out of the token-data\n * upstream shape into top-level fields. The upstream API returns a\n * paginated `{ symbol, data: [{ price: {USD, CNY}, percent_change_24h:\n * {USD, CNY}, ... }] }`. AUP nodes binding `${content.price}` should\n * just see a number — they shouldn't have to navigate the upstream\n * pagination wrapper.\n *\n * Also surfaces `currency: \"USD\"` so dark-launch testing or future\n * locale work can switch to other currencies. Falls back to the raw\n * shape (with the wrapper) when the upstream returns something\n * unexpected — partial structure is better than throwing on a price\n * lookup that the UI uses opportunistically.\n */\n private normalizePricePayload(\n payload: Record<string, unknown>,\n symbol: string,\n now: number,\n ): Record<string, unknown> {\n const fetchedAt = new Date(now).toISOString();\n const data = (payload.data as Array<Record<string, unknown>> | undefined) ?? [];\n const first = data[0];\n if (!first) {\n // Upstream returned a paginated wrapper with no entries — pass it\n // through as-is so callers can detect the empty case via .data length.\n // state.symbol overrides any upstream symbol field (the chain is the\n // authoritative source for what THIS token is called).\n return { ...payload, symbol, fetchedAt };\n }\n const priceMap = (first.price as Record<string, number> | undefined) ?? {};\n const changeMap = (first.percent_change_24h as Record<string, number> | undefined) ?? {};\n return {\n ...payload,\n symbol,\n price: priceMap.USD ?? null,\n change24h: changeMap.USD ?? null,\n currency: \"USD\",\n fetchedAt,\n };\n }\n\n /**\n * Phase 0.2 A.7 — Token price endpoint with 60s in-memory cache + stale\n * fallback on upstream failure. Backed by token-data.arcblock.io which\n * accepts only symbols (not addresses), so we resolve the token's symbol\n * via getTokenState first.\n *\n * Cache lifecycle:\n * - Fresh hit (within TTL) → return cached value immediately\n * - Miss → fetch upstream → cache → return\n * - Fetch failure WITH cached value → return cached + { stale: true, error }\n * - Fetch failure WITHOUT cached value → throw AFSError\n */\n @Read(\"/tokens/:addr/price\")\n async readTokenPrice(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n const addr = ctx.params.addr;\n // Path-traversal / dotfile guard — `:addr` should always be a single\n // path segment, but defense-in-depth is cheap.\n if (!addr || addr.startsWith(\".\") || addr.includes(\"/\")) {\n throw new AFSNotFoundError(ctx.path);\n }\n const state = await this.source.getTokenState(addr);\n if (!state) throw new AFSNotFoundError(ctx.path);\n if (!state.symbol) throw new AFSNotFoundError(joinURL(ctx.path, \"no-symbol\"));\n\n const value = await this.getPriceBySymbol(state.symbol);\n if (!value) {\n // Cold cache + upstream failure — surface as not-found so the public\n // route fails loudly rather than serving an empty body.\n throw new AFSNotFoundError(ctx.path);\n }\n return this.buildEntry(ctx.path, {\n content: value,\n meta: { kind: \"ocap:token:price\" },\n });\n }\n\n @Read(\"/tokens/:addr/holders\")\n async readTokenHoldersDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:account\", childrenCount: -1 },\n });\n }\n\n @List(\"/tokens/:addr/holders\")\n async listTokenHolders(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const tokenAddr = ctx.params.addr;\n const result = await this.source.listTopAccounts(paging, {\n tokenAddress: tokenAddr,\n });\n const entries = result.items.map((a) => {\n const tokenEntry = a.tokens?.find((t) => t.address === tokenAddr);\n // Phase 0.2 A.19 — surface the per-token balance as `_tokenBalance`\n // alongside the unmodified native `balance` (ABT). The legacy\n // implementation overwrote `balance` with the per-token value, which\n // made `content.balance` ambiguous: it was native ABT on the global\n // /accounts list but token-specific on /tokens/:addr/holders. AUP\n // table columns binding `${content.balance}` could not tell which\n // they would get. The new convention: `balance` always = native ABT,\n // `_tokenBalance` only present (and meaningful) on token-holders rows.\n const tokenBalance = tokenEntry?.balance ?? \"0\";\n const tokenDecimal = tokenEntry?.decimal;\n // Expose the token's own symbol so the holders table can suffix the\n // Balance column with it (\"1,500 ABT\" instead of a bare number). The\n // symbol is identical for every holder in the same listing (it's the\n // token being viewed), but we surface it per row so the AUP renderer\n // can resolve \\`symbol: \"@{content._tokenSymbol}\"\\` without needing\n // a separate parent-scope lookup.\n const tokenSymbol = tokenEntry?.symbol;\n return {\n ...this.buildEntry(joinURL(\"/accounts\", a.address), {\n content: {\n ...a,\n _monikerDisplay: displayMoniker(a.moniker, a.address),\n _tokenBalance: tokenBalance,\n _tokenDecimal: tokenDecimal,\n _tokenSymbol: tokenSymbol,\n },\n meta: { kind: \"ocap:account\" },\n }),\n summary: `${a.moniker || a.address} • ${tokenBalance}`,\n };\n });\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/tokens/:addr/transactions\")\n async readTokenTxDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/tokens/:addr/transactions\")\n async listTokenTransactions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n tokenFilter: { tokens: [ctx.params.addr] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n // ============ Assets ============\n\n @List(\"/assets\")\n async listAssets(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const filters = extractAssetFilters(listOpts(ctx));\n const result = await this.source.listAssets(paging, filters);\n const entries = result.items.map((a) => ({\n ...this.buildEntry(joinURL(\"/assets\", a.address), {\n content: a,\n meta: { kind: \"ocap:asset\", childrenCount: 2 },\n }),\n summary: `${a.moniker || a.address} • owner: ${a.owner}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/assets/:address\")\n async readAsset(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const state = await this.source.getAssetState(ctx.params.address);\n if (!state) throw new AFSNotFoundError(ctx.path);\n // ttl=0 on chain means \"no expiry\" — surface that intent rather than\n // letting the renderer print a literal 0 next to \"Expire After\".\n const ttlRaw = (state as { ttl?: number | string }).ttl;\n return {\n ...this.buildEntry(ctx.path, {\n content: {\n ...state,\n _issuerPath: this.resolveNavPath(state.issuer),\n _ttlDisplay: formatIntegerOrSentinel(ttlRaw, \"Never\"),\n _nftDisplay: deriveNftDisplay(state),\n },\n meta: { kind: \"ocap:asset\", childrenCount: 2 },\n }),\n summary: `${state.moniker || state.address} • owner: ${state.owner}`,\n };\n }\n\n @List(\"/assets/:address\")\n async listAssetChildren(ctx: RouteContext<{ address: string }>): Promise<AFSListResult> {\n if (ctx.params.address.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const entries = [\"transactions\", \"stakes\"].map((sub) => buildDirEntry(ctx.path, sub));\n return { data: entries };\n }\n\n @Read(\"/assets/:addr/transactions\")\n async readAssetTxDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/assets/:addr/transactions\")\n async listAssetTransactions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n assetFilter: { assets: [ctx.params.addr] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/assets/:addr/stakes\")\n async readAssetStakesDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:stake\", childrenCount: -1 },\n });\n }\n\n @List(\"/assets/:addr/stakes\")\n async listAssetStakes(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractStakeFilters(listOpts(ctx));\n const result = await this.source.listStakes(paging, {\n ...userFilters,\n addressFilter: { sender: ctx.params.addr, receiver: ctx.params.addr, direction: \"UNION\" },\n });\n const entries = result.items.map((s) => ({\n ...this.buildEntry(joinURL(\"/stakes\", s.address), {\n content: s,\n meta: { kind: \"ocap:stake\" },\n }),\n summary: `${s.sender} → ${s.receiver}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n // ============ Factories ============\n\n @List(\"/factories\")\n async listFactories(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const filters = extractFactoryFilters(listOpts(ctx));\n const result = await this.source.listFactories(paging, filters);\n const entries = result.items.map((f) => ({\n ...this.buildEntry(joinURL(\"/factories\", f.address), {\n content: { ...f, _limitDisplay: formatIntegerOrSentinel(f.limit, \"Unlimited\") },\n meta: { kind: \"ocap:factory\", childrenCount: 2 },\n }),\n summary: `${f.name} • minted: ${f.numMinted}/${f.limit}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/factories/:address\")\n async readFactory(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const state = await this.source.getFactoryState(ctx.params.address);\n if (!state) throw new AFSNotFoundError(ctx.path);\n return {\n ...this.buildEntry(ctx.path, {\n content: { ...state, _limitDisplay: formatIntegerOrSentinel(state.limit, \"Unlimited\") },\n meta: { kind: \"ocap:factory\", childrenCount: 2 },\n }),\n summary: `${state.name} • minted: ${state.numMinted}/${state.limit}`,\n };\n }\n\n @List(\"/factories/:address\")\n async listFactoryChildren(ctx: RouteContext<{ address: string }>): Promise<AFSListResult> {\n if (ctx.params.address.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const entries = [\"assets\", \"transactions\"].map((sub) => buildDirEntry(ctx.path, sub));\n return { data: entries };\n }\n\n @Read(\"/factories/:addr/assets\")\n async readFactoryAssetsDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:asset\", childrenCount: -1 },\n });\n }\n\n @List(\"/factories/:addr/assets\")\n async listFactoryAssets(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractAssetFilters(listOpts(ctx));\n const result = await this.source.listAssets(paging, {\n ...userFilters,\n factoryAddress: ctx.params.addr,\n });\n const entries = result.items.map((a) => ({\n ...this.buildEntry(joinURL(\"/assets\", a.address), {\n content: a,\n meta: { kind: \"ocap:asset\", childrenCount: 2 },\n }),\n summary: `${a.moniker || a.address} • owner: ${a.owner}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/factories/:addr/transactions\")\n async readFactoryTxDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/factories/:addr/transactions\")\n async listFactoryTransactions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n factoryFilter: { factories: [ctx.params.addr] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n // ============ Stakes ============\n\n @List(\"/stakes\")\n async listStakes(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const filters = extractStakeFilters(listOpts(ctx));\n const result = await this.source.listStakes(paging, filters);\n const entries = result.items.map((s) => ({\n ...this.buildEntry(joinURL(\"/stakes\", s.address), {\n content: s,\n meta: { kind: \"ocap:stake\", childrenCount: 3 },\n }),\n summary: `${s.sender} → ${s.receiver}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/stakes/:address\")\n async readStake(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const state = await this.source.getStakeState(ctx.params.address);\n if (!state) throw new AFSNotFoundError(ctx.path);\n // Note: `genesisTime` / `renaissanceTime` are NOT flattened here. AUP\n // binds nested paths (`content.context.genesisTime`) directly via\n // `_surfaceBindField`. `firstSlasher` IS derived because array-index\n // access can't be expressed in an AUP key — it's a real reshape, not\n // a flattening workaround.\n const content = {\n ...state,\n firstSlasher: state.slashers?.[0] ?? \"\",\n };\n return {\n ...this.buildEntry(ctx.path, {\n content,\n meta: { kind: \"ocap:stake\", childrenCount: 3 },\n }),\n summary: `${state.sender} → ${state.receiver}`,\n };\n }\n\n @List(\"/stakes/:address\")\n async listStakeChildren(ctx: RouteContext<{ address: string }>): Promise<AFSListResult> {\n if (ctx.params.address.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const entries = [\n buildDirEntry(ctx.path, \"transactions\"),\n buildDirEntry(ctx.path, \"tokens\"),\n buildDirEntry(ctx.path, \"assets\"),\n ];\n return { data: entries };\n }\n\n @Read(\"/stakes/:addr/transactions\")\n async readStakeTxDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/stakes/:addr/transactions\")\n async listStakeTransactions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n stakeFilter: { stakes: [ctx.params.addr] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/stakes/:addr/tokens\")\n async readStakeTokensDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:token\", childrenCount: -1 },\n });\n }\n\n @List(\"/stakes/:addr/tokens\")\n async listStakeTokens(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const state = await this.source.getStakeState(ctx.params.addr);\n if (!state) throw new AFSNotFoundError(ctx.path);\n type TokenRow = {\n address: string;\n symbol: string;\n decimal: number;\n unit: string;\n staked: string;\n revoked: string;\n };\n const tokenMap = new Map<string, TokenRow>();\n for (const t of state.tokens ?? []) {\n tokenMap.set(t.address, {\n address: t.address,\n symbol: t.symbol ?? \"\",\n decimal: t.decimal ?? 18,\n unit: t.unit ?? \"\",\n staked: t.value ?? \"0\",\n revoked: \"0\",\n });\n }\n for (const t of state.revokedTokens ?? []) {\n const existing = tokenMap.get(t.address);\n if (existing) {\n existing.revoked = t.value ?? \"0\";\n } else {\n tokenMap.set(t.address, {\n address: t.address,\n symbol: t.symbol ?? \"\",\n decimal: t.decimal ?? 18,\n unit: t.unit ?? \"\",\n staked: \"0\",\n revoked: t.value ?? \"0\",\n });\n }\n }\n const entries = [...tokenMap.values()].map((t) =>\n this.buildEntry(joinURL(\"/tokens\", t.address), {\n content: t,\n meta: { kind: \"ocap:token\" },\n }),\n );\n return { data: entries };\n }\n\n @Read(\"/stakes/:addr/assets\")\n async readStakeAssetsDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:asset\", childrenCount: -1 },\n });\n }\n\n @List(\"/stakes/:addr/assets\")\n async listStakeAssets(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const state = await this.source.getStakeState(ctx.params.addr);\n if (!state) throw new AFSNotFoundError(ctx.path);\n const stakedSet = new Set(state.assets ?? []);\n const revokedSet = new Set(state.revokedAssets ?? []);\n const allAddresses = new Set([...stakedSet, ...revokedSet]);\n const entries = [...allAddresses].map((addr) =>\n this.buildEntry(joinURL(\"/assets\", addr), {\n content: {\n address: addr,\n staked: stakedSet.has(addr) ? \"Yes\" : \"\",\n revoked: revokedSet.has(addr) ? \"Yes\" : \"\",\n },\n meta: { kind: \"ocap:asset\" },\n }),\n );\n return { data: entries };\n }\n\n // ============ Bridges (Rollups) ============\n\n @List(\"/bridges\")\n async listBridges(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const filters = extractBridgeFilters(listOpts(ctx));\n const result = await this.source.listRollups(paging, filters);\n const entries = result.items.map((r) => ({\n ...this.buildEntry(joinURL(\"/bridges\", r.address), {\n content: {\n ...r,\n _statusLabel: formatBridgeStatusLabel(r.closed, r.paused),\n _statusColor: formatBridgeStatusColor(r.closed, r.paused),\n },\n meta: { kind: \"ocap:bridge\", childrenCount: 8 },\n }),\n summary: `${r.tokenAddress} bridge`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:address\")\n async readBridge(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const state = await this.source.getRollupState(ctx.params.address);\n if (!state) throw new AFSNotFoundError(ctx.path);\n return {\n ...this.buildEntry(ctx.path, {\n content: {\n ...state,\n tokenDecimal: state.tokenInfo?.decimal,\n _statusLabel: formatBridgeStatusLabel(state.closed, state.paused),\n _statusColor: formatBridgeStatusColor(state.closed, state.paused),\n },\n meta: { kind: \"ocap:bridge\", childrenCount: 8 },\n }),\n summary: `${state.tokenAddress} bridge`,\n };\n }\n\n @List(\"/bridges/:address\")\n async listBridgeChildren(ctx: RouteContext<{ address: string }>): Promise<AFSListResult> {\n if (ctx.params.address.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const entries = [\n buildDirEntry(ctx.path, \"deposits\"),\n buildDirEntry(ctx.path, \"withdrawals\"),\n buildDirEntry(ctx.path, \"blocks\"),\n buildDirEntry(ctx.path, \"nodes\"),\n buildDirEntry(ctx.path, \"stakes\"),\n buildDirEntry(ctx.path, \"governance\"),\n buildDirEntry(ctx.path, \"slashes\"),\n buildDirEntry(ctx.path, \"transactions\"),\n ];\n return { data: entries };\n }\n\n @Read(\"/bridges/:addr/transactions\")\n async readBridgeTxDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/bridges/:addr/transactions\")\n async listBridgeTransactions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n rollupFilter: { rollups: [ctx.params.addr] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:addr/stakes\")\n async readBridgeStakeDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:stake\", childrenCount: -1 },\n });\n }\n\n @List(\"/bridges/:addr/stakes\")\n async listBridgeStakes(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractStakeFilters(listOpts(ctx));\n const result = await this.source.listStakes(paging, {\n ...userFilters,\n addressFilter: { ...userFilters?.addressFilter, receiver: ctx.params.addr },\n });\n const entries = result.items.map((s) => ({\n ...this.buildEntry(joinURL(\"/stakes\", s.address), {\n content: s,\n meta: { kind: \"ocap:stake\", childrenCount: 3 },\n }),\n summary: `${s.sender} → ${s.receiver}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:addr/deposits\")\n async readBridgeDepositsDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/bridges/:addr/deposits\")\n async listBridgeDeposits(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n rollupFilter: { rollups: [ctx.params.addr] },\n typeFilter: { types: [\"deposit_token_v2\", \"deposit_token\"] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:addr/withdrawals\")\n async readBridgeWithdrawalsDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, { meta: { kind: \"ocap:transaction\", childrenCount: -1 } });\n }\n\n @List(\"/bridges/:addr/withdrawals\")\n async listBridgeWithdrawals(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n rollupFilter: { rollups: [ctx.params.addr] },\n typeFilter: { types: [\"withdraw_token_v2\", \"withdraw_token\"] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:addr/governance\")\n async readBridgeGovernanceDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, { meta: { kind: \"ocap:transaction\", childrenCount: -1 } });\n }\n\n @List(\"/bridges/:addr/governance\")\n async listBridgeGovernance(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n rollupFilter: { rollups: [ctx.params.addr] },\n typeFilter: {\n types: [\n \"create_rollup\",\n \"update_rollup\",\n \"pause_rollup\",\n \"resume_rollup\",\n \"close_rollup\",\n \"migrate_rollup\",\n \"join_rollup\",\n \"leave_rollup\",\n ],\n },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:addr/slashes\")\n async readBridgeSlashesDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/bridges/:addr/slashes\")\n async listBridgeSlashes(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n // Slashes on a rollup are NOT a top-level tx type. They appear as a\n // `change.action === \"slash\"` line in the receipts of a `claim_block_reward`\n // tx, which the chain emits when a publisher fails the rollup's\n // publishSlashRate check. Reference: legacy block-explorer's\n // src/pages/explorer/components/rollup/slash-list.jsx\n //\n // Two earlier attempts got this wrong:\n // 1. typeFilter: [\"claim_block_reward\"] alone — listed every reward\n // claim regardless of whether anyone was slashed.\n // 2. typeFilter: [\"slash_stake\"] with rollupFilter — slash_stake is a\n // chain-level generic stake slashing tx, distinct from rollup\n // publisher punishment, and rollupFilter doesn't tag those rows.\n //\n // Correct path: enumerate the rollup's validator stake addresses (the\n // DID hash of `validator + rollup`), filter claim_block_reward txs whose\n // receipts touch those stakes, then keep only the rows that actually\n // contain a `slash` action. Each surviving entry surfaces the slashed\n // node + amount on `content._slash` for the AUP table to render.\n const rollupState = await this.source.getRollupState(ctx.params.addr).catch(() => null);\n const validators = (rollupState?.validators as Array<{ address?: string }> | undefined) ?? [];\n if (validators.length === 0) {\n return buildListResult([], 0);\n }\n // toStakeAddress(validator, rollup) — DID hash of (sender + receiver)\n // bytes under ROLE_STAKE. Same primitive the chain uses to derive\n // per-pair stake DIDs at stake-creation time.\n const stakeAddrToValidator = new Map<string, string>();\n for (const v of validators) {\n if (!v.address) continue;\n const stakeAddr = toStakeAddress(v.address, ctx.params.addr);\n stakeAddrToValidator.set(stakeAddr, v.address);\n }\n const stakeAddrs = Array.from(stakeAddrToValidator.keys());\n\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n accountFilter: { accounts: stakeAddrs },\n typeFilter: { types: [\"claim_block_reward\"] },\n });\n\n type Receipt = {\n address?: string;\n changes?: Array<{ action?: string; value?: string }>;\n };\n const slashEntries: AFSEntry[] = [];\n for (const tx of result.items) {\n const receipts = ((tx as { receipts?: Receipt[] }).receipts ?? []) as Receipt[];\n let slashStakeAddr: string | undefined;\n let slashAmount: string | undefined;\n for (const r of receipts) {\n const hit = (r.changes ?? []).find((c) => c.action === \"slash\");\n if (hit) {\n slashStakeAddr = r.address;\n slashAmount = hit.value;\n break;\n }\n }\n // Drop reward-only claims (no slash action present).\n if (!slashStakeAddr) continue;\n const slashedNode = slashAmount\n ? (slashAmount && stakeAddrToValidator.get(slashStakeAddr || \"\")) || \"\"\n : \"\";\n const itxJson = (tx.tx?.itxJson as Record<string, unknown>) || {};\n const parties = resolveTxParties(tx);\n if (parties.sender) tx.sender = parties.sender;\n if (parties.receiver) tx.receiver = parties.receiver;\n slashEntries.push({\n ...this.buildEntry(joinURL(\"/transactions\", tx.hash), {\n content: {\n ...tx,\n ...this.enrichTxContent(\n tx as IndexedTransaction & {\n tokenSymbols?: Array<{ symbol?: string; decimal?: number }>;\n },\n itxJson,\n ),\n _slashStakeAddress: slashStakeAddr,\n _slashedNode: slashedNode,\n _slashAmount: slashAmount,\n _slashBlockHeight: itxJson.blockHeight as number | undefined,\n _slashBlockHash: itxJson.blockHash as string | undefined,\n },\n meta: { kind: tx.type ? `ocap:transaction:${tx.type}` : \"ocap:transaction\" },\n }),\n summary: `slash ${slashedNode}`,\n });\n }\n return buildListResult(slashEntries, result.total);\n }\n\n @Read(\"/bridges/:addr/nodes\")\n async readBridgeNodesDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:rollup-node\", childrenCount: -1 },\n });\n }\n\n @List(\"/bridges/:addr/nodes\")\n async listBridgeNodes(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const [result, rollupState] = await Promise.all([\n this.source.listRollupValidators(ctx.params.addr, paging),\n this.source.getRollupState(ctx.params.addr).catch(() => null),\n ]);\n const activeSet = new Set(\n ((rollupState?.validators as Array<{ address?: string }> | undefined) || [])\n .map((v) => v.address)\n .filter((a): a is string => typeof a === \"string\"),\n );\n const entries = result.items.map((v) => {\n const isActive = activeSet.has(v.address);\n return {\n ...this.buildEntry(joinURL(\"/accounts\", v.address), {\n content: {\n ...v,\n _isActive: isActive,\n _status: isActive ? \"Active\" : \"Inactive\",\n // Active = green success pill; Inactive = amber warning pill.\n // Earlier we used a near-white grey (#F3F4F6) for Inactive which\n // visually read as \"no badge applied\" and several reviewers thought\n // the colored-badge formatter wasn't wired up at all. Amber gives\n // an unmistakable signal that the node is present-but-not-validating.\n _statusColor: isActive\n ? { main: \"#0E7C5A\", light: \"#E8F8F1\" }\n : { main: \"#92400E\", light: \"#FEF3C7\" },\n },\n meta: { kind: \"ocap:rollup-node\" },\n }),\n summary: `${v.moniker || v.address} (${v.proposedBlockCount ?? 0} blocks)`,\n };\n });\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:addr/blocks\")\n async readBridgeBlocksDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:rollup-block\", childrenCount: -1 },\n });\n }\n\n @Meta(\"/bridges/:addr/blocks\")\n async metaBridgeBlocks(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:rollup-block\", childrenCount: -1 },\n });\n }\n\n @List(\"/bridges/:addr/blocks\")\n async listBridgeBlocks(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const result = await this.source.listRollupBlocks(ctx.params.addr, paging);\n const entries = this.buildBlockEntries(ctx.params.addr, result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/bridges/:addr/blocks/:hash\")\n async readBridgeBlock(\n ctx: RouteContext<{ addr: string; hash: string }>,\n ): Promise<AFSEntry | undefined> {\n if (ctx.params.hash.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const [block, rollup] = await Promise.all([\n this.source.getRollupBlock(ctx.params.hash, ctx.params.addr),\n this.source.getRollupState(ctx.params.addr).catch(() => null),\n ]);\n if (!block) throw new AFSNotFoundError(ctx.path);\n return {\n ...this.buildEntry(ctx.path, {\n content: { ...block, tokenDecimal: rollup?.tokenInfo?.decimal },\n meta: { kind: \"ocap:rollup-block\" },\n }),\n summary: `Block #${block.height} • ${block.txs?.length ?? 0} txs`,\n };\n }\n\n // ============ Delegates ============\n\n @List(\"/delegates\")\n async listDelegates(ctx: RouteContext): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const filters = extractDelegationFilters(listOpts(ctx));\n const result = await this.source.listDelegations(paging, filters);\n const entries = result.items.map((d) => ({\n ...this.buildEntry(joinURL(\"/delegates\", d.address), {\n content: d,\n meta: { kind: \"ocap:delegate\", childrenCount: 1 },\n }),\n summary: `${d.from} → ${d.to}`,\n }));\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/delegates/:address\")\n async readDelegate(ctx: RouteContext<{ address: string }>): Promise<AFSEntry | undefined> {\n const state = await this.source.getDelegateState(ctx.params.address);\n if (!state) throw new AFSNotFoundError(ctx.path);\n // Note: `genesisTime` / `renaissanceTime` are NOT flattened here. AUP\n // binds nested paths (`content.context.genesisTime`) directly. Only\n // genuine derivations (JSON.stringify, .length) stay in the reshape.\n const content = {\n ...state,\n dataJson: JSON.stringify(state.data ?? {}, null, 2),\n opsCount: (state.ops || []).length,\n };\n return {\n ...this.buildEntry(ctx.path, {\n content,\n meta: { kind: \"ocap:delegate\", childrenCount: 2 },\n }),\n summary: `${state.from} → ${state.to}`,\n };\n }\n\n @List(\"/delegates/:address\")\n async listDelegateChildren(ctx: RouteContext<{ address: string }>): Promise<AFSListResult> {\n if (ctx.params.address.startsWith(\".\")) throw new AFSNotFoundError(ctx.path);\n const entries = [\n buildDirEntry(ctx.path, \"transactions\"),\n buildDirEntry(ctx.path, \"permissions\"),\n ];\n return { data: entries };\n }\n\n @Read(\"/delegates/:addr/transactions\")\n async readDelegateTxDir(ctx: RouteContext<{ addr: string }>): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:transaction\", childrenCount: -1 },\n });\n }\n\n @List(\"/delegates/:addr/transactions\")\n async listDelegateTransactions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const paging = toPaging(listOpts(ctx), this.defaultPageSize);\n const userFilters = extractTxFilters(listOpts(ctx));\n const result = await this.source.listTransactions(paging, {\n ...userFilters,\n delegationFilter: { delegations: [ctx.params.addr] },\n });\n const entries = this.buildTxEntries(result);\n return buildListResult(entries, result.total);\n }\n\n @Read(\"/delegates/:addr/permissions\")\n async readDelegatePermissionsDir(\n ctx: RouteContext<{ addr: string }>,\n ): Promise<AFSEntry | undefined> {\n return this.buildEntry(ctx.path, {\n meta: { kind: \"ocap:delegate_permission\", childrenCount: -1 },\n });\n }\n\n @List(\"/delegates/:addr/permissions\")\n async listDelegatePermissions(ctx: RouteContext<{ addr: string }>): Promise<AFSListResult> {\n const state = await this.source.getDelegateState(ctx.params.addr);\n if (!state) throw new AFSNotFoundError(ctx.path);\n const entries = (state.ops || []).map((op: any) => ({\n ...this.buildEntry(joinURL(ctx.path, encodeURIComponent(op.key)), {\n content: {\n typeUrl: op.key,\n rule: op.value?.rule || \"\",\n numTxs: op.value?.numTxs ?? 0,\n numTxsDelta: op.value?.numTxsDelta ?? 0,\n balance: op.value?.balance || \"0\",\n balanceDelta: op.value?.balanceDelta || \"0\",\n },\n meta: { kind: \"ocap:delegate_permission\" },\n }),\n summary: op.key,\n }));\n return { data: entries };\n }\n\n // ============ Search ============\n\n @Search(\"/:path*\")\n async searchHandler(\n ctx: RouteContext<{ path?: string }>,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; message?: string }> {\n const paging = toPaging(\n {\n limit: options?.limit,\n offset: (options as { offset?: number } | undefined)?.offset,\n },\n this.defaultPageSize,\n );\n\n // Server-side resolver handles exact-match (DID role / tx hash) and\n // semantic search uniformly — every result already carries enriched\n // title/subtitle/description/tags/timestamp.\n const result = await this.source.search(query, paging);\n\n // Path scope filter (e.g. /transactions/... limits to tx results only)\n let items = result.items;\n const scope = ctx.params.path?.split(\"/\")[0];\n if (scope) {\n const allowedTypes = COLLECTION_TO_TYPES[scope];\n if (allowedTypes) {\n items = items.filter((r) => allowedTypes.includes(r.type));\n }\n }\n\n const entries: AFSEntry[] = items.map((r) => ({\n ...this.buildEntry(joinURL(\"/\", TYPE_TO_COLLECTION[r.type] ?? `${r.type}s`, r.id), {\n content: r,\n meta: {\n kind: `ocap:${r.type}`,\n ...(r.tags?.length ? { tags: r.tags } : {}),\n ...(r.timestamp ? { timestamp: r.timestamp } : {}),\n },\n }),\n summary: r.description || r.subtitle,\n }));\n\n const message = `Found ${result.total} results${result.hasNext ? \" (more available)\" : \"\"}`;\n return { data: entries, message };\n }\n\n // ============ Explain ============\n\n @Explain(\"/:path*\")\n async explainHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSExplainResult> {\n const normalizedPath = joinURL(\"/\", ctx.params.path ?? \"\");\n const format = (ctx.options as AFSExplainOptions)?.format || \"markdown\";\n const segments = normalizedPath.split(\"/\").filter(Boolean);\n const lines: string[] = [];\n\n if (format === \"markdown\") {\n if (segments.length === 0) {\n const info = await this.source.getChainInfo();\n lines.push(`# ${info.moniker}`);\n lines.push(\"\");\n lines.push(`**Chain ID:** ${info.id}`);\n lines.push(`**Block Height:** ${info.blockHeight}`);\n lines.push(`**Total Txs:** ${info.totalTxs}`);\n lines.push(`**Synced:** ${info.synced}`);\n lines.push(\"\");\n lines.push(\"## Available Paths\");\n for (const dir of TOP_LEVEL_DIRS) {\n lines.push(`- \\`/${dir}\\``);\n }\n } else {\n lines.push(`# ${normalizedPath}`);\n lines.push(\"\");\n lines.push(`**Type:** ${segments[0]}`);\n if (segments.length > 1) {\n lines.push(`**ID:** ${segments[1]}`);\n }\n }\n } else {\n if (segments.length === 0) {\n const info = await this.source.getChainInfo();\n lines.push(`${info.moniker} (chain)`);\n lines.push(`Height: ${info.blockHeight}, Txs: ${info.totalTxs}`);\n } else {\n lines.push(`${normalizedPath} (${segments[0]})`);\n }\n }\n\n return { content: lines.join(\"\\n\"), format };\n }\n\n // ============ Collection Read (top-level directories) ============\n\n @Read(\"/:collection\")\n async readCollection(ctx: RouteContext<{ collection: string }>): Promise<AFSEntry | undefined> {\n if (!(TOP_LEVEL_DIRS as readonly string[]).includes(ctx.params.collection)) {\n throw new AFSNotFoundError(ctx.path);\n }\n return this.buildEntry(ctx.path, {\n meta: {\n kind: collectionKind(ctx.params.collection),\n childrenCount: -1,\n },\n });\n }\n\n // ============ Catch-all List ============\n\n @List(\"/:path*\")\n async listCatchAll(ctx: RouteContext<{ path?: string }>): Promise<AFSListResult> {\n const normalizedPath = joinURL(\"/\", ctx.params.path ?? \"\");\n\n // Root listing\n if (normalizedPath === \"/\") {\n const entries = TOP_LEVEL_DIRS.map((dir) => buildDirEntry(\"/\", dir));\n return { data: entries };\n }\n\n // Known paths under a valid collection → return empty (leaf node)\n const segments = normalizedPath.split(\"/\").filter(Boolean);\n if (segments.length >= 1 && (TOP_LEVEL_DIRS as readonly string[]).includes(segments[0]!)) {\n return { data: [] };\n }\n\n throw new AFSNotFoundError(normalizedPath);\n }\n\n // ============ Capabilities ============\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const operations = this.getOperationsDeclaration();\n return this.buildEntry(\"/.meta/.capabilities\", {\n content: { operations },\n meta: { kind: \"afs:capabilities\" },\n });\n }\n\n // ============ Stat ============\n\n @Stat(\"/:path*\")\n async statHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSStatResult> {\n const normalizedPath = joinURL(\"/\", ctx.params.path ?? \"\");\n const segments = normalizedPath.split(\"/\").filter(Boolean);\n\n if (segments.length >= 1 && !(TOP_LEVEL_DIRS as readonly string[]).includes(segments[0]!)) {\n throw new AFSNotFoundError(ctx.path);\n }\n\n const meta: Record<string, unknown> = {};\n if (segments.length === 0) {\n meta.kind = \"ocap:chain\";\n meta.childrenCount = TOP_LEVEL_DIRS.length;\n } else if (segments.length === 1) {\n meta.kind = collectionKind(segments[0]!);\n meta.childrenCount = -1;\n } else {\n meta.kind = collectionKind(segments[0]!);\n }\n\n const { content: _, ...statData } = this.buildEntry(normalizedPath, { meta });\n return { data: statData };\n }\n\n // ============ Meta ============\n\n @Meta(\"/:path*\")\n async metaHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSEntry | undefined> {\n const normalizedPath = joinURL(\"/\", ctx.params.path ?? \"\");\n const segments = normalizedPath.split(\"/\").filter(Boolean);\n\n // Validate path starts with a known directory\n if (segments.length >= 1 && !(TOP_LEVEL_DIRS as readonly string[]).includes(segments[0]!)) {\n throw new AFSNotFoundError(ctx.path);\n }\n\n const meta: Record<string, unknown> = {};\n if (segments.length === 0) {\n meta.kind = \"ocap:chain\";\n meta.childrenCount = TOP_LEVEL_DIRS.length;\n } else if (segments.length === 1) {\n meta.kind = collectionKind(segments[0]!);\n meta.childrenCount = -1;\n } else {\n meta.kind = collectionKind(segments[0]!);\n }\n\n // Use ctx.path to preserve the .meta suffix when read directly\n return this.buildEntry(ctx.path, { meta });\n }\n}\n\nconst _typeCheck: AFSModuleClass<AFSOCAP, AFSOCAPOptions> = AFSOCAP;\n\nexport default AFSOCAP;\n"],"mappings":"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"}