@mysten-incubation/devstack 0.2.0 → 0.4.0
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.
- package/README.md +1 -1
- package/dashboard-ui/assets/{grpc-a4usE3Nk.js → grpc-CpkDu4SA.js} +1 -1
- package/dashboard-ui/assets/{index-CRYJ4pru.js → index-jLPRmjst.js} +39 -33
- package/dashboard-ui/index.html +1 -1
- package/dist/api/inference-network.d.mts +5 -5
- package/dist/api/inference-network.mjs +5 -5
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/run-stack-internal.mjs +2 -3
- package/dist/api/run-stack-internal.mjs.map +1 -1
- package/dist/build-integrations/dapp-kit/index.d.mts +12 -0
- package/dist/build-integrations/dapp-kit/index.mjs +14 -1
- package/dist/build-integrations/dapp-kit/index.mjs.map +1 -1
- package/dist/build-integrations/playwright/config.d.mts +2 -1
- package/dist/build-integrations/playwright/config.mjs +1 -1
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +1 -1
- package/dist/build-integrations/playwright/errors.mjs.map +1 -1
- package/dist/build-integrations/playwright/index.d.mts +2 -2
- package/dist/build-integrations/playwright/index.mjs +2 -2
- package/dist/build-integrations/playwright/wallet-context.d.mts +2 -1
- package/dist/build-integrations/playwright/wallet-context.mjs +141 -41
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs +1 -1
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -1
- package/dist/build-integrations/vite/index.d.mts +82 -40
- package/dist/build-integrations/vite/index.mjs +281 -112
- package/dist/build-integrations/vite/index.mjs.map +1 -1
- package/dist/build-integrations/vitest/config.mjs +3 -4
- package/dist/build-integrations/vitest/config.mjs.map +1 -1
- package/dist/build-integrations/vitest/global-setup.mjs +8 -8
- package/dist/build-integrations/vitest/global-setup.mjs.map +1 -1
- package/dist/cli/doctor-probes.mjs +7 -2
- package/dist/cli/doctor-probes.mjs.map +1 -1
- package/dist/cli/main.mjs +5 -4
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +0 -1
- package/dist/cli/wirings/apply.mjs.map +1 -1
- package/dist/cli/wirings/codegen.mjs +37 -38
- package/dist/cli/wirings/codegen.mjs.map +1 -1
- package/dist/cli/wirings/dump-deployment.mjs +141 -0
- package/dist/cli/wirings/dump-deployment.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +0 -1
- package/dist/cli/wirings/snapshot.mjs.map +1 -1
- package/dist/cli/wirings/up.mjs +7 -0
- package/dist/cli/wirings/up.mjs.map +1 -1
- package/dist/contracts/codegenable.d.mts +22 -25
- package/dist/contracts/codegenable.mjs +35 -4
- package/dist/contracts/codegenable.mjs.map +1 -1
- package/dist/contracts/config-bindings.mjs +43 -18
- package/dist/contracts/config-bindings.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/orchestrators/boot.d.mts +0 -10
- package/dist/orchestrators/boot.mjs +24 -54
- package/dist/orchestrators/boot.mjs.map +1 -1
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/config-runtime.mjs +137 -112
- package/dist/orchestrators/codegen/config-runtime.mjs.map +1 -1
- package/dist/orchestrators/codegen/deployment-network-file.mjs +130 -0
- package/dist/orchestrators/codegen/deployment-network-file.mjs.map +1 -0
- package/dist/orchestrators/codegen/deployment-strict.mjs +77 -0
- package/dist/orchestrators/codegen/deployment-strict.mjs.map +1 -0
- package/dist/orchestrators/codegen/deployment.d.mts +63 -0
- package/dist/orchestrators/codegen/deployment.mjs +153 -0
- package/dist/orchestrators/codegen/deployment.mjs.map +1 -0
- package/dist/orchestrators/codegen/errors.mjs +7 -9
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +20 -1
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/paths.mjs +1 -8
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +369 -141
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/layers.mjs +0 -1
- package/dist/orchestrators/layers.mjs.map +1 -1
- package/dist/orchestrators/network-options.d.mts +37 -35
- package/dist/orchestrators/network-options.mjs +13 -10
- package/dist/orchestrators/network-options.mjs.map +1 -1
- package/dist/plugins/account/codegen.d.mts +3 -4
- package/dist/plugins/account/codegen.mjs +5 -7
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/index.mjs +1 -3
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/coin/codegen.mjs +5 -5
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/dashboard/domain.mjs +18 -1
- package/dist/plugins/dashboard/domain.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/root.mjs +5 -3
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/types.mjs +15 -2
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -1
- package/dist/plugins/deepbook/codegen.mjs +4 -4
- package/dist/plugins/deepbook/codegen.mjs.map +1 -1
- package/dist/plugins/deepbook/index.d.mts +7 -3
- package/dist/plugins/deepbook/index.mjs +3 -3
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/internal/codegen-helpers.mjs +0 -1
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -1
- package/dist/plugins/package/codegen.d.mts +1 -12
- package/dist/plugins/package/codegen.mjs +43 -25
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/dep-resolution.mjs +1 -1
- package/dist/plugins/package/dep-resolution.mjs.map +1 -1
- package/dist/plugins/package/index.d.mts +14 -11
- package/dist/plugins/package/index.mjs +6 -7
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/seal/codegen.mjs +3 -3
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/sui/codegen.mjs +5 -4
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +10 -10
- package/dist/plugins/sui/index.mjs +1 -2
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/plugins/sui/move-summary-runner.mjs +29 -2
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -1
- package/dist/plugins/wallet/codegen.d.mts +8 -12
- package/dist/plugins/wallet/codegen.mjs +22 -15
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +4 -3
- package/dist/plugins/wallet/index.mjs +1 -1
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +2 -2
- package/dist/plugins/wallet/service.mjs +2 -3
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.mjs +4 -4
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/index.mjs +1 -1
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/substrate/manifest.d.mts +17 -22
- package/dist/substrate/manifest.mjs +4 -6
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/plugin-ctx.d.mts +6 -6
- package/dist/substrate/plugin-ctx.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/index.mjs +1 -0
- package/dist/substrate/runtime/lifecycle/file-watcher.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/file-watcher.mjs +54 -0
- package/dist/substrate/runtime/lifecycle/file-watcher.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/index.mjs +1 -0
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs +76 -6
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/paths.mjs +1 -1
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +2 -6
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -1
- package/dist/surfaces/cli/command-tree.mjs +6 -6
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +6 -4
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/cli/wirings/dump-ids.mjs +0 -86
- package/dist/cli/wirings/dump-ids.mjs.map +0 -1
- package/dist/orchestrators/codegen/id-config.d.mts +0 -1
- package/dist/orchestrators/codegen/id-config.mjs +0 -107
- package/dist/orchestrators/codegen/id-config.mjs.map +0 -1
- package/dist/orchestrators/codegen/output-location.mjs +0 -32
- package/dist/orchestrators/codegen/output-location.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.mjs","names":[],"sources":["../../../src/plugins/dashboard/domain.ts"],"sourcesContent":["// Dashboard plugin-domain shaping.\n//\n// The substrate control-plane is GENERIC + name-blind: it hands out the\n// snapshot catalog, the observability rings, and a single uninterpreted\n// `resolvedValues` accessor (see `substrate/runtime/control-plane/`). This\n// module — which lives in the PLUGIN layer and is allowed to name plugins —\n// owns ALL plugin-name-aware shaping: it matches resolved plugin values by\n// resource id (`deepbook/`-prefix, `seal:`-prefix, `coin:`-prefix, `id ===\n// 'sui'`) and projects them into the app-agnostic shapes the GraphQL schema\n// renders. It also owns the `mode` derivation and the coin `mint` action.\n//\n// Design discipline (mirrors the old substrate seam, one layer up):\n// - We import NO plugin types — we narrow the opaque `unknown` resolved\n// value through shallow structural shapes that mirror the relevant\n// fields. A field missing on the live value collapses to the\n// null/empty default.\n// - Every accessor degrades to empty/`null` rather than failing, so a\n// single missing/uninitialised plugin can't take down a dashboard\n// query (`E = never` on the public surface).\n// - We match plugins by RESOURCE ID — a prefix for the multi-instance\n// kinds (`deepbook/`, `seal:`, `coin:`) and an exact id for the\n// singletons (`id === 'sui'`) — rather than\n// plugin-key substrings: the resource id is the stable identity the\n// plugin factories mint.\n\nimport { Effect } from 'effect';\n\nimport type {\n\tControlPlaneDomain,\n\tControlPlaneResolvedValue,\n} from '../../substrate/runtime/control-plane/service.ts';\nimport type { StrategyRegistry } from '../../contracts/strategy-contributor.ts';\nimport type { FaucetStrategy } from '../../contracts/faucet-strategy.ts';\nimport type { AccountFundingStrategy } from '../../contracts/funding-strategy.ts';\nimport type { AccountValue } from '../account/index.ts';\n// The faucet capability-key prefix is owned by the faucet plugin (single\n// source of truth). The dashboard plugin layer is allowed to name plugins,\n// so importing the key constructor is the same cross-plugin reference the\n// account funding pass (`plugins/account/funding.ts`) uses — NOT a resolved\n// plugin-VALUE import (those stay structurally narrowed below). Imported via\n// the sibling's barrel to satisfy the plugin-boundary invariant.\nimport { FAUCET_CAPABILITY_KEY_PREFIX } from '../faucet/index.ts';\n\n// -----------------------------------------------------------------------------\n// App-agnostic domain shapes the GraphQL schema renders.\n// -----------------------------------------------------------------------------\n\n/** One DeepBook pool object id + coin types (prices are chain-direct). */\nexport interface DashboardDeepbookPool {\n\treadonly name: string;\n\treadonly poolId: string;\n\treadonly baseCoinType: string;\n\treadonly quoteCoinType: string;\n}\n\nexport interface DashboardDeepbookInfo {\n\treadonly pluginKey: string;\n\treadonly name: string;\n\treadonly mode: 'local' | 'override' | 'known';\n\treadonly network: string;\n\treadonly packageId: string;\n\treadonly registryId: string;\n\treadonly adminCapId: string | null;\n\treadonly deepTreasuryId: string | null;\n\treadonly pools: ReadonlyArray<DashboardDeepbookPool>;\n\treadonly marketMakerRunning: boolean;\n\treadonly serverUrl: string | null;\n\treadonly indexerUrl: string | null;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud: schema drift surfaced to the caller\n\t * instead of silently degrading). */\n\treadonly narrowingFault: string | null;\n}\n\nexport interface DashboardSealKeyServer {\n\treadonly objectId: string;\n\treadonly weight: number;\n}\n\nexport interface DashboardSealInfo {\n\treadonly pluginKey: string;\n\treadonly mode: 'local-keygen' | 'live' | 'fork-known';\n\treadonly objectId: string;\n\treadonly keyServerUrl: string;\n\treadonly keyServers: ReadonlyArray<DashboardSealKeyServer>;\n\t/** Threshold = number of registered key-server configs. */\n\treadonly threshold: number;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud). */\n\treadonly narrowingFault: string | null;\n}\n\n/** A coin's treasury-cap id (drives the Mint action) + addressing facts. */\nexport interface DashboardCoinCap {\n\treadonly pluginKey: string;\n\treadonly symbol: string | null;\n\treadonly fullCoinType: string;\n\treadonly decimals: number;\n\treadonly source: 'registry' | 'on-chain' | 'builtin';\n\treadonly treasuryCapId: string | null;\n\treadonly packageId: string | null;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud). */\n\treadonly narrowingFault: string | null;\n}\n\n/** Input for the dashboard mint ACTION. `amountBaseUnits` is the raw\n * integer amount in the coin's smallest unit (decimals already applied\n * by the caller / form) — a string so large u64 values survive the wire\n * without precision loss. */\nexport interface DashboardMintInput {\n\treadonly coinType: string;\n\treadonly recipient: string;\n\treadonly amountBaseUnits: string;\n}\n\n/** Outcome of a dashboard mint ACTION. Mirrors the snapshot\n * restore/delete result shape plus the on-chain tx `digest` on success. */\nexport interface DashboardMintResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\n}\n\n/** Input for the dashboard fund ACTION.\n *\n * `coinType` selects the funding strategy: absent or the canonical SUI\n * type routes through the chain's faucet strategy (`faucet:request:<chainId>`,\n * fixed-amount); any other full coin type routes through the coin-specific\n * `coinType:<fullCoinType>` strategy (WAL exchange swap / DEEP pool swap).\n *\n * `amountBaseUnits` is the raw integer amount in the coin's smallest unit\n * (a string so large u64 values survive the wire without precision loss).\n * The SUI faucet is fixed-amount and IGNORES it; WAL/DEEP honor it. */\nexport interface DashboardFundInput {\n\treadonly recipient: string;\n\treadonly coinType?: string | null;\n\treadonly amountBaseUnits?: string | null;\n}\n\n/** Outcome of a dashboard fund ACTION. The in-process funding strategies\n * return `void` (not a digest), so the result carries only `ok`/`detail`.\n * `ok:true` means the strategy's `request(...)` completed (the faucet POST\n * landed / the swap executed on-chain); `detail` carries the reason on\n * failure. */\nexport interface DashboardFundResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n}\n\n/** One coin the dashboard faucet can actually fund, with whether the\n * underlying strategy honors a caller-supplied amount.\n *\n * SUI is always present (fixed-amount faucet, `honorsAmount: false`).\n * WAL/DEEP appear only when their plugin registered a `coinType:<X>`\n * funding strategy AND (for WAL) carries a swap that spends the\n * recipient account's SUI — so `honorsAmount: true`. */\nexport interface DashboardFundableCoin {\n\treadonly symbol: string;\n\treadonly coinType: string;\n\treadonly honorsAmount: boolean;\n\t/** True when funding requires the recipient to BE a resolved account in\n\t * the stack (the swap spends that account's own SUI via its in-process\n\t * signer). SUI is `false` (any 0x address); WAL/DEEP are `true`. */\n\treadonly requiresAccountSigner: boolean;\n}\n\n/** The dashboard plugin-domain accessor surface. Each member is a\n * self-contained Effect that never fails (`E = never`); they degrade to\n * empty/`null` so a single missing plugin can't take down the dashboard\n * query. */\nexport interface DashboardDomain {\n\t/** Fork-vs-local mode, derived from the resolved sui plugin's chain\n\t * identity. Used for advance-clock gating. `null` when no sui plugin\n\t * is present. */\n\treadonly mode: Effect.Effect<'fork' | 'local' | 'live' | null>;\n\t/** DeepBook deployments (registry/admin/pool ids + MM state). */\n\treadonly deepbook: Effect.Effect<ReadonlyArray<DashboardDeepbookInfo>>;\n\t/** Seal key-server deployments (objectId/threshold/mode). */\n\treadonly seal: Effect.Effect<ReadonlyArray<DashboardSealInfo>>;\n\t/** Coin treasury caps (drives Mint). */\n\treadonly coinCaps: Effect.Effect<ReadonlyArray<DashboardCoinCap>>;\n\t/** Mint ACTION — mints `amountBaseUnits` of `coinType` to `recipient`,\n\t * signed in-process by the treasury-cap-owning publisher signer the\n\t * resolved coin value's self-contained `mintFromCap` closure holds. */\n\treadonly mintCoin: (input: DashboardMintInput) => Effect.Effect<DashboardMintResult>;\n\t/** Coins the faucet can actually fund right now (SUI always; WAL/DEEP\n\t * only when their plugin registered a funding strategy). Drives the\n\t * faucet panel's coin pills + amount-field gating. */\n\treadonly fundableCoins: Effect.Effect<ReadonlyArray<DashboardFundableCoin>>;\n\t/** Fund ACTION — reuses devstack's in-process funding strategies. SUI\n\t * (absent/canonical type) routes through the chain faucet strategy\n\t * (fixed-amount); WAL/DEEP route through the coin-specific funding\n\t * strategy (account-signed exchange/pool swap). Real result — `ok`\n\t * reflects whether the strategy's `request(...)` completed. */\n\treadonly fundAccount: (input: DashboardFundInput) => Effect.Effect<DashboardFundResult>;\n}\n\n// -----------------------------------------------------------------------------\n// Structural projections of plugin-resolved values\n//\n// We narrow the opaque `unknown` resolved value through shallow structural\n// shapes that mirror the relevant fields. A field missing on the live value\n// collapses to the null/empty default.\n// -----------------------------------------------------------------------------\n\ninterface DeepbookShape {\n\treadonly mode?: unknown;\n\treadonly network?: unknown;\n\treadonly packageId?: unknown;\n\treadonly registryId?: unknown;\n\treadonly adminCapId?: unknown;\n\treadonly deepTreasuryId?: unknown;\n\treadonly pools?: ReadonlyArray<{\n\t\treadonly name?: unknown;\n\t\treadonly poolId?: unknown;\n\t\treadonly baseCoinType?: unknown;\n\t\treadonly quoteCoinType?: unknown;\n\t}>;\n\treadonly marketMakerRunning?: unknown;\n\treadonly serverUrl?: unknown;\n\treadonly indexerUrl?: unknown;\n}\n\ninterface SealShape {\n\treadonly mode?: unknown;\n\treadonly objectId?: unknown;\n\treadonly keyServerUrl?: unknown;\n\treadonly serverConfigs?: ReadonlyArray<{\n\t\treadonly objectId?: unknown;\n\t\treadonly weight?: unknown;\n\t}>;\n}\n\ninterface CoinShape {\n\treadonly symbol?: unknown;\n\treadonly fullCoinType?: unknown;\n\treadonly decimals?: unknown;\n\treadonly source?: unknown;\n\treadonly treasuryCapId?: unknown;\n\treadonly packageId?: unknown;\n\t/** Self-contained mint closure on the resolved coin value (present\n\t * for witness-form coins whose publisher still owns the cap). Read\n\t * structurally — we import no coin types. Returns an Effect that\n\t * resolves a `{ digest }`-bearing result or fails with a\n\t * coin/artifact-publisher tagged error. */\n\treadonly mintFromCap?: (opts: {\n\t\treadonly to: string;\n\t\treadonly amount: bigint;\n\t}) => Effect.Effect<{ readonly digest: string }, { readonly message?: unknown }>;\n}\n\ninterface SuiShape {\n\treadonly mode?: unknown;\n\t/** Genesis-digest chain id (`'sui:localnet'`, `'sui:testnet'`,\n\t * `'sui:mainnet-fork@123'`). Composes the faucet capability key\n\t * (`faucet:request:<chainId>`) the SUI funding path resolves. */\n\treadonly chainId?: unknown;\n}\n\n/** Structural shape of the resolved account value (`account/<name>`). The\n * WAL/DEEP funding strategies need this handle as `req.account` — the swap\n * spends the recipient account's own SUI through its in-process signer.\n * Narrowed to the fields the strategy dispatch reads; the full\n * `AccountValue` is assignable to it, so we cast the matched value across\n * the seam without importing the account VALUE shape structurally\n * elsewhere. */\ninterface AccountShape {\n\treadonly address?: unknown;\n\treadonly name?: unknown;\n}\n\n/** A 0x-prefixed Sui address: `0x` + 1..64 hex digits. Mirrors the\n * address validation the mint PTB's `tx.pure.address` ultimately\n * enforces, surfaced up front so the dashboard gets a clean rejection\n * rather than an opaque build failure. */\nconst SUI_ADDRESS_RE = /^0x[0-9a-fA-F]{1,64}$/;\n\n/** The canonical builtin SUI coin type — selects the SUI faucet funding\n * path. Mirrors `SUI_FULL_COIN_TYPE` in `plugins/account/funding.ts`\n * (inlined here so the dashboard plugin does not cross-import the account\n * funding module just for the string). */\nconst SUI_FULL_COIN_TYPE = '0x2::sui::SUI' as const;\n\n/** A positive integer base-unit amount string (no sign, no decimal\n * point, no leading zeros beyond a bare `0` — which is itself rejected\n * as non-positive). */\nconst isPositiveIntegerString = (s: string): boolean => {\n\tif (!/^\\d+$/.test(s)) return false;\n\ttry {\n\t\treturn BigInt(s) > 0n;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** Compose the chain faucet capability key (`faucet:request:<chainId>`)\n * the SUI funding path resolves. Uses the faucet plugin's prefix constant\n * (single source of truth) — same key the boot-time funding pass builds. */\nconst faucetCapabilityKeyFor = (\n\tchain: string,\n): `${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${string}` => `${FAUCET_CAPABILITY_KEY_PREFIX}:${chain}`;\n\n/** Parse a base-unit amount string into a positive bigint, or `null` when\n * absent / non-positive / non-integer. */\nconst parseAmount = (s: string | null | undefined): bigint | null => {\n\tif (s == null) return null;\n\tconst trimmed = s.trim();\n\tif (!isPositiveIntegerString(trimmed)) return null;\n\treturn BigInt(trimmed);\n};\n\n/** Derive a display symbol from a full coin type's module path\n * (`0x…::wal::WAL` → `WAL`, `0x…::deep::DEEP` → `DEEP`). Falls back to the\n * struct name, then the raw type. Keeps the dashboard name-blind on the\n * resolved coin VALUE while still labeling the faucet pill. */\nconst coinSymbolFromType = (coinType: string): string => {\n\tconst parts = coinType.split('::');\n\tconst struct = parts[parts.length - 1];\n\treturn struct !== undefined && struct.length > 0 ? struct : coinType;\n};\n\n/** Extract a human detail from a faucet/funding strategy failure. The\n * strategy error channels are tagged structs carrying `message`/`reason`;\n * read them structurally without importing each plugin's error type. */\nconst causeDetail = (cause: unknown): string => {\n\tif (cause !== null && typeof cause === 'object') {\n\t\tconst c = cause as {\n\t\t\treadonly message?: unknown;\n\t\t\treadonly reason?: unknown;\n\t\t\treadonly _tag?: unknown;\n\t\t};\n\t\tif (typeof c.message === 'string' && c.message.length > 0) return c.message;\n\t\tif (typeof c.reason === 'string' && c.reason.length > 0) return c.reason;\n\t\tif (typeof c._tag === 'string' && c._tag.length > 0) return c._tag;\n\t}\n\treturn String(cause);\n};\nconst faucetCauseDetail = causeDetail;\nconst fundingCauseDetail = causeDetail;\n\n// -----------------------------------------------------------------------------\n// Fail-aware structural narrowing\n//\n// The substrate hands us opaque `unknown` resolved values. We still narrow\n// through shallow structural shapes, but instead of SILENTLY degrading a\n// missing/wrong-typed required field to ''/0 (which hid integration-seam\n// drift), the `req*` readers ACCUMULATE a typed narrowing fault into a\n// per-shaping-call collector. The fault is threaded into the GraphQL-visible\n// result (`narrowingFault` / `detail`) so consumers SEE the drift — WITHOUT\n// ever throwing (the dashboard's `E = never` surface semantic is preserved).\n// `opt*` readers stay quiet: they are for genuinely-optional fields.\n// -----------------------------------------------------------------------------\n\n/** Mutable per-call sink for structural-narrowing faults. */\ntype FaultSink = Array<string>;\n\nconst newFaults = (): FaultSink => [];\n\n/** Collapse accumulated faults into a single nullable detail string for the\n * GraphQL-visible result. `null` when nothing drifted. */\nconst faultDetail = (faults: FaultSink): string | null =>\n\tfaults.length === 0 ? null : faults.join('; ');\n\n/** Describe why a value failed to narrow to the expected type — distinguishing\n * 'absent' from 'present but wrong type'. */\nconst typeFault = (field: string, expected: string, v: unknown): string => {\n\tif (v === undefined || v === null) return `${field}: missing (expected ${expected})`;\n\treturn `${field}: expected ${expected}, got ${typeof v}`;\n};\n\n/** Required string. On mismatch records a fault and returns '' so the panel\n * still renders a (degraded) cell. */\nconst reqStr = (v: unknown, field: string, faults: FaultSink): string => {\n\tif (typeof v === 'string') return v;\n\tfaults.push(typeFault(field, 'string', v));\n\treturn '';\n};\n\n/** Required finite number. On mismatch records a fault and returns the safe\n * display fallback (`fallback`, default 0). */\nconst reqNum = (v: unknown, field: string, faults: FaultSink, fallback = 0): number => {\n\tif (typeof v === 'number' && Number.isFinite(v)) return v;\n\tfaults.push(typeFault(field, 'number', v));\n\treturn fallback;\n};\n\n/** Allow-list enum narrow. Records a fault for an out-of-enum value while\n * still returning a safe display fallback so the panel renders. */\nconst narrowEnum = <T extends string>(\n\traw: unknown,\n\tallowed: ReadonlyArray<T>,\n\tfield: string,\n\tfaults: FaultSink,\n\tfallback: T,\n): T => {\n\tif (typeof raw === 'string' && (allowed as ReadonlyArray<string>).includes(raw)) return raw as T;\n\tfaults.push(\n\t\traw === undefined || raw === null\n\t\t\t? `${field}: missing (expected one of ${allowed.join('|')})`\n\t\t\t: `${field}: '${String(raw)}' not in ${allowed.join('|')}`,\n\t);\n\treturn fallback;\n};\n\n// Genuinely-optional readers — silent by design (absent is a valid state).\nconst optStr = (v: unknown): string | null => (typeof v === 'string' ? v : null);\nconst optNum = (v: unknown): number | null =>\n\ttypeof v === 'number' && Number.isFinite(v) ? v : null;\nconst bool = (v: unknown): boolean => v === true;\n\n/** Filter the generic resolved values down to those whose resource id\n * matches a predicate, in graph order. Returns the `{ pluginKey, value }`\n * the shaping functions consume. */\nconst matching = (\n\tvalues: ReadonlyArray<ControlPlaneResolvedValue>,\n\tmatches: (resourceId: string) => boolean,\n): ReadonlyArray<ControlPlaneResolvedValue> => values.filter((v) => matches(v.id));\n\n// -----------------------------------------------------------------------------\n// Builder\n// -----------------------------------------------------------------------------\n\nexport interface DashboardDomainDeps {\n\t/** The generic, name-blind control-plane domain (resolved values). */\n\treadonly control: ControlPlaneDomain;\n\t/** The scope-local strategy registry — the SAME registry the boot-time\n\t * account funding pass dispatches through (`plugins/account/funding.ts`).\n\t * Drives `fundableCoins` + `fundAccount`: SUI via `faucet:request:<chainId>`,\n\t * WAL/DEEP via `coinType:<fullCoinType>`. `null` in bare test paths; the\n\t * fund accessors degrade to unavailable then. */\n\treadonly strategyRegistry: StrategyRegistry | null;\n}\n\nexport const buildDashboardDomain = (deps: DashboardDomainDeps): DashboardDomain => {\n\tconst { control, strategyRegistry } = deps;\n\n\tconst mode: DashboardDomain['mode'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\tif (sui === undefined) return null;\n\t\t\tconst m = (sui.value as SuiShape).mode;\n\t\t\tswitch (m) {\n\t\t\t\tcase 'fork':\n\t\t\t\t\treturn 'fork';\n\t\t\t\tcase 'live':\n\t\t\t\t\treturn 'live';\n\t\t\t\tcase 'local':\n\t\t\t\tcase 'local-rpc':\n\t\t\t\t\treturn 'local';\n\t\t\t\tdefault:\n\t\t\t\t\treturn null;\n\t\t\t}\n\t\t}),\n\t);\n\n\tconst deepbook: DashboardDomain['deepbook'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('deepbook/')).map(\n\t\t\t\t({ pluginKey, value }): DashboardDeepbookInfo => {\n\t\t\t\t\tconst v = value as DeepbookShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst dbMode = narrowEnum(\n\t\t\t\t\t\tv.mode,\n\t\t\t\t\t\t['local', 'override', 'known'] as const,\n\t\t\t\t\t\t'deepbook.mode',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'local',\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tname: pluginKey.replace(/^deepbook:/, ''),\n\t\t\t\t\t\tmode: dbMode,\n\t\t\t\t\t\tnetwork: reqStr(v.network, 'deepbook.network', faults),\n\t\t\t\t\t\tpackageId: reqStr(v.packageId, 'deepbook.packageId', faults),\n\t\t\t\t\t\tregistryId: reqStr(v.registryId, 'deepbook.registryId', faults),\n\t\t\t\t\t\tadminCapId: optStr(v.adminCapId),\n\t\t\t\t\t\tdeepTreasuryId: optStr(v.deepTreasuryId),\n\t\t\t\t\t\tpools: (v.pools ?? []).map((p, i) => ({\n\t\t\t\t\t\t\tname: reqStr(p.name, `deepbook.pools[${i}].name`, faults),\n\t\t\t\t\t\t\tpoolId: reqStr(p.poolId, `deepbook.pools[${i}].poolId`, faults),\n\t\t\t\t\t\t\tbaseCoinType: reqStr(p.baseCoinType, `deepbook.pools[${i}].baseCoinType`, faults),\n\t\t\t\t\t\t\tquoteCoinType: reqStr(p.quoteCoinType, `deepbook.pools[${i}].quoteCoinType`, faults),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tmarketMakerRunning: bool(v.marketMakerRunning),\n\t\t\t\t\t\tserverUrl: optStr(v.serverUrl),\n\t\t\t\t\t\tindexerUrl: optStr(v.indexerUrl),\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst seal: DashboardDomain['seal'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('seal:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardSealInfo => {\n\t\t\t\t\tconst v = value as SealShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst sealMode = narrowEnum(\n\t\t\t\t\t\tv.mode,\n\t\t\t\t\t\t['local-keygen', 'live', 'fork-known'] as const,\n\t\t\t\t\t\t'seal.mode',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'local-keygen',\n\t\t\t\t\t);\n\t\t\t\t\tconst keyServers = (v.serverConfigs ?? []).map((c, i) => ({\n\t\t\t\t\t\tobjectId: reqStr(c.objectId, `seal.serverConfigs[${i}].objectId`, faults),\n\t\t\t\t\t\tweight: optNum(c.weight) ?? 1,\n\t\t\t\t\t}));\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tmode: sealMode,\n\t\t\t\t\t\tobjectId: reqStr(v.objectId, 'seal.objectId', faults),\n\t\t\t\t\t\tkeyServerUrl: reqStr(v.keyServerUrl, 'seal.keyServerUrl', faults),\n\t\t\t\t\t\tkeyServers,\n\t\t\t\t\t\tthreshold: keyServers.length,\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst coinCaps: DashboardDomain['coinCaps'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('coin:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardCoinCap => {\n\t\t\t\t\tconst v = value as CoinShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst source = narrowEnum(\n\t\t\t\t\t\tv.source,\n\t\t\t\t\t\t['registry', 'on-chain', 'builtin'] as const,\n\t\t\t\t\t\t'coin.source',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'on-chain',\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tsymbol: optStr(v.symbol),\n\t\t\t\t\t\tfullCoinType: reqStr(v.fullCoinType, 'coin.fullCoinType', faults),\n\t\t\t\t\t\tdecimals: reqNum(v.decimals, 'coin.decimals', faults, 0),\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\ttreasuryCapId: optStr(v.treasuryCapId),\n\t\t\t\t\t\tpackageId: optStr(v.packageId),\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\t// Mint ACTION — drives the dashboard Coins panel's Mint button.\n\t//\n\t// Signer source: the resolved coin VALUE carries a self-contained\n\t// `mintFromCap` closure (present only for witness-form coins whose\n\t// publisher still owns the TreasuryCap). That closure already captures\n\t// the treasury-cap-owning publisher `MintSigner` + the resolved cap id\n\t// in-process — the same lease-owning path `coin/service.ts`'s\n\t// `fundingStrategy` uses — so we mint WITHOUT threading a signer through\n\t// this seam (we read the resolved value, never plugin internals).\n\t//\n\t// Never fails (`E = never`): every reject path (bad address, non-\n\t// positive amount, no matching coin, cap-not-owned, on-chain failure)\n\t// degrades to `{ ok: false, detail, digest: null }` so the dashboard\n\t// query can't be taken down by a single bad mint.\n\tconst mintCoin: DashboardDomain['mintCoin'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (!isPositiveIntegerString(input.amountBaseUnits)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits}': expected a positive integer string`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\t// Locate the resolved coin whose fullCoinType matches. Match on the\n\t\t\t// resolved value's `fullCoinType` (the stable on-chain type), not the\n\t\t\t// resource-id prefix, so callers pass the same `coinType` the\n\t\t\t// `coinCaps` query surfaced. Read `fullCoinType` fail-loud so a coin\n\t\t\t// value missing/empty `fullCoinType` names the REAL cause (a drifted\n\t\t\t// resolved shape) rather than collapsing into the generic\n\t\t\t// 'no resolved coin found' reject.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst candidates = matching(values, (id) => id.startsWith('coin:')).map(\n\t\t\t\t({ value }) => value as CoinShape,\n\t\t\t);\n\t\t\tconst matchFaults = newFaults();\n\t\t\tconst match = candidates.find(\n\t\t\t\t(v) => reqStr(v.fullCoinType, 'coin.fullCoinType', matchFaults) === input.coinType,\n\t\t\t);\n\n\t\t\tif (match === undefined) {\n\t\t\t\tconst fault = faultDetail(matchFaults);\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\tfault === null\n\t\t\t\t\t\t\t? `no resolved coin found for type '${input.coinType}'`\n\t\t\t\t\t\t\t: `no resolved coin found for type '${input.coinType}' (${fault})`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (typeof match.mintFromCap !== 'function') {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${input.coinType}' has no in-process treasury cap signer — ` +\n\t\t\t\t\t\t'mint is only available for local-package coins whose publisher still owns the TreasuryCap',\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\treturn yield* match\n\t\t\t\t.mintFromCap({ to: recipient, amount: BigInt(input.amountBaseUnits) })\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(r): DashboardMintResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `minted ${input.amountBaseUnits} of ${input.coinType} to ${recipient}`,\n\t\t\t\t\t\t\tdigest: r.digest,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Typed coin/artifact-publisher failures carry `.message`.\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\t\ttypeof cause?.message === 'string'\n\t\t\t\t\t\t\t\t\t? cause.message\n\t\t\t\t\t\t\t\t\t: `mint failed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Residual defects (interrupts, unexpected throws) — degrade\n\t\t\t\t\t// rather than crash the dashboard query.\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `mint crashed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\t// --- Fund ACTION + fundable-coin derivation ------------------------\n\t//\n\t// Reuses devstack's IN-PROCESS funding strategies — the same strategy\n\t// registry the boot-time account funding pass dispatches through\n\t// (`plugins/account/funding.ts`). We never re-implement signing or the\n\t// exchange/pool swaps:\n\t//\n\t// - SUI (absent / canonical type) → `faucet:request:<chainId>`. The SUI\n\t// faucet strategy takes `{ address, amount }` only (no account handle)\n\t// and is FIXED-AMOUNT (the standard faucet ignores `amount`). Recipient\n\t// may be ANY 0x address.\n\t// - WAL/DEEP → `coinType:<fullCoinType>`. The strategy takes\n\t// `{ address, amount, account }` and runs an account-signed swap, so\n\t// the recipient MUST be a resolved account in the stack (we match the\n\t// recipient address against the resolved `account/<name>` values and\n\t// pass the live `AccountValue` as `req.account`).\n\t//\n\t// Never fails (`E = never`): every reject path degrades to\n\t// `{ ok:false, detail }` so a single bad fund can't take down the query.\n\n\t/** The chain id the SUI funding path keys on, read from the resolved sui\n\t * value (same `chainId` field the sui codegen/snapshot decls stamp). */\n\tconst readChainId = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\treturn sui === undefined ? null : optStr((sui.value as SuiShape).chainId);\n\t\t}),\n\t);\n\n\tconst fundableCoins: DashboardDomain['fundableCoins'] = Effect.gen(function* () {\n\t\t// SUI is always fundable when a faucet strategy is registered for the\n\t\t// active chain; the fixed-amount faucet ignores the requested amount.\n\t\tconst out: DashboardFundableCoin[] = [];\n\t\tif (strategyRegistry === null) return out;\n\n\t\tconst chain = yield* readChainId;\n\t\tconst keys = yield* strategyRegistry.list();\n\t\tif (chain !== null && keys.includes(faucetCapabilityKeyFor(chain))) {\n\t\t\tout.push({\n\t\t\t\tsymbol: 'SUI',\n\t\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t\t\thonorsAmount: false,\n\t\t\t\trequiresAccountSigner: false,\n\t\t\t});\n\t\t}\n\n\t\t// A coin is fundable iff a `coinType:<fullCoinType>` strategy is actually\n\t\t// registered (the walrus/deepbook/coin plugin contributed one). Derive the\n\t\t// display symbol from the coin type's module path (`::wal::WAL` → WAL,\n\t\t// `::deep::DEEP` → DEEP) so we stay name-blind on the coin VALUE while\n\t\t// still labeling the pill. `requiresAccountSigner` is read from the\n\t\t// strategy's own `requiresRecipientAccount` flag — NOT assumed true for\n\t\t// every coin: WAL/DEEP swaps spend the recipient's SUI (true), but a\n\t\t// managed-coin MINT strategy transfers to a passive recipient (false), so\n\t\t// it can fund any 0x address.\n\t\tfor (const key of keys) {\n\t\t\tif (!key.startsWith('coinType:')) continue;\n\t\t\tconst coinType = key.slice('coinType:'.length);\n\t\t\tif (coinType === SUI_FULL_COIN_TYPE) continue;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tout.push({\n\t\t\t\tsymbol: coinSymbolFromType(coinType),\n\t\t\t\tcoinType,\n\t\t\t\thonorsAmount: true,\n\t\t\t\trequiresAccountSigner: strategy?.requiresRecipientAccount ?? false,\n\t\t\t});\n\t\t}\n\t\treturn out;\n\t});\n\n\tconst fundAccount: DashboardDomain['fundAccount'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\t\t\tif (strategyRegistry === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: 'funding unavailable: no strategy registry wired',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst coinType = input.coinType?.trim() ?? '';\n\t\t\tconst isSui = coinType === '' || coinType === SUI_FULL_COIN_TYPE;\n\n\t\t\t// SUI path — chain faucet strategy. Fixed-amount: we pass a nominal\n\t\t\t// amount but the standard faucet ignores it. Recipient may be any\n\t\t\t// 0x address (no account handle required).\n\t\t\tif (isSui) {\n\t\t\t\tconst chain = yield* readChainId;\n\t\t\t\tif (chain === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: 'cannot fund SUI: no resolved sui plugin / chain id in this stack',\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\tconst key = faucetCapabilityKeyFor(chain);\n\t\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t\t.get<typeof key, FaucetStrategy>(key)\n\t\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\t\tif (strategy === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: `no SUI faucet strategy registered for chain '${chain}'`,\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\t// `amount` is nominal — the standard faucet grant is fixed and\n\t\t\t\t// ignores it. Default to 1 SUI in MIST so a strategy that DID\n\t\t\t\t// honor it lands a sane value.\n\t\t\t\tconst amount = parseAmount(input.amountBaseUnits) ?? 1_000_000_000n;\n\t\t\t\treturn yield* strategy.request({ address: recipient, amount }).pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `requested SUI for ${recipient} (fixed-amount faucet grant)`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request failed: ${faucetCauseDetail(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request crashed: ${String(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// WAL/DEEP path — coin-specific account-signed funding strategy.\n\t\t\tconst amount = parseAmount(input.amountBaseUnits);\n\t\t\tif (amount === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ''}': expected a positive integer string`,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst key = `coinType:${coinType}` as const;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tif (strategy === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`no funding strategy registered for coin '${coinType}' — ` +\n\t\t\t\t\t\t'WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\t// Match the recipient to a resolved account, if one holds this address.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst account = matching(values, (id) => id.startsWith('account/'))\n\t\t\t\t.map(({ value }) => value as AccountShape)\n\t\t\t\t.find((v) => optStr(v.address) === recipient);\n\n\t\t\t// Account-spending strategies (WAL/DEEP) swap the recipient's OWN SUI,\n\t\t\t// so the recipient must BE a resolved account with a signer. Mint-style\n\t\t\t// strategies (managed coins) transfer to a passive recipient, so any 0x\n\t\t\t// address is fine — gate the rejection on the strategy's flag, not on\n\t\t\t// the coin being non-SUI.\n\t\t\tif (strategy.requiresRecipientAccount === true && account === undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${coinType}' is funded by an account-signed swap, but '${recipient}' ` +\n\t\t\t\t\t\t'is not a resolved account in this stack — fund a configured account (the swap spends its SUI)',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\treturn yield* strategy\n\t\t\t\t.request({\n\t\t\t\t\taddress: recipient,\n\t\t\t\t\tamount,\n\t\t\t\t\t...(account === undefined ? {} : { account: account as unknown as AccountValue }),\n\t\t\t\t})\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `funded ${amount} base units of ${coinType} to ${recipient}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\treturn {\n\t\tmode,\n\t\tdeepbook,\n\t\tseal,\n\t\tcoinCaps,\n\t\tmintCoin,\n\t\tfundableCoins,\n\t\tfundAccount,\n\t};\n};\n\n/** An all-empty dashboard domain. Used by tests that exercise the\n * schema/server without a live registry. Every accessor resolves to\n * empty/`null`. */\nexport const emptyDashboardDomain: DashboardDomain = {\n\tmode: Effect.succeed(null),\n\tdeepbook: Effect.succeed([]),\n\tseal: Effect.succeed([]),\n\tcoinCaps: Effect.succeed([]),\n\tmintCoin: () => Effect.succeed({ ok: false, detail: 'unavailable', digest: null }),\n\tfundableCoins: Effect.succeed([]),\n\tfundAccount: () => Effect.succeed({ ok: false, detail: 'unavailable' }),\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"domain.mjs","names":[],"sources":["../../../src/plugins/dashboard/domain.ts"],"sourcesContent":["// Dashboard plugin-domain shaping.\n//\n// The substrate control-plane is GENERIC + name-blind: it hands out the\n// snapshot catalog, the observability rings, and a single uninterpreted\n// `resolvedValues` accessor (see `substrate/runtime/control-plane/`). This\n// module — which lives in the PLUGIN layer and is allowed to name plugins —\n// owns ALL plugin-name-aware shaping: it matches resolved plugin values by\n// resource id (`deepbook/`-prefix, `seal:`-prefix, `coin:`-prefix, `id ===\n// 'sui'`) and projects them into the app-agnostic shapes the GraphQL schema\n// renders. It also owns the `mode` derivation and the coin `mint` action.\n//\n// Design discipline (mirrors the old substrate seam, one layer up):\n// - We import NO plugin types — we narrow the opaque `unknown` resolved\n// value through shallow structural shapes that mirror the relevant\n// fields. A field missing on the live value collapses to the\n// null/empty default.\n// - Every accessor degrades to empty/`null` rather than failing, so a\n// single missing/uninitialised plugin can't take down a dashboard\n// query (`E = never` on the public surface).\n// - We match plugins by RESOURCE ID — a prefix for the multi-instance\n// kinds (`deepbook/`, `seal:`, `coin:`) and an exact id for the\n// singletons (`id === 'sui'`) — rather than\n// plugin-key substrings: the resource id is the stable identity the\n// plugin factories mint.\n\nimport { Effect } from 'effect';\n\nimport type {\n\tControlPlaneDomain,\n\tControlPlaneResolvedValue,\n} from '../../substrate/runtime/control-plane/service.ts';\nimport type { StrategyRegistry } from '../../contracts/strategy-contributor.ts';\nimport type { FaucetStrategy } from '../../contracts/faucet-strategy.ts';\nimport type { AccountFundingStrategy } from '../../contracts/funding-strategy.ts';\nimport type { AccountValue } from '../account/index.ts';\n// The faucet capability-key prefix is owned by the faucet plugin (single\n// source of truth). The dashboard plugin layer is allowed to name plugins,\n// so importing the key constructor is the same cross-plugin reference the\n// account funding pass (`plugins/account/funding.ts`) uses — NOT a resolved\n// plugin-VALUE import (those stay structurally narrowed below). Imported via\n// the sibling's barrel to satisfy the plugin-boundary invariant.\nimport { FAUCET_CAPABILITY_KEY_PREFIX } from '../faucet/index.ts';\n\n// -----------------------------------------------------------------------------\n// App-agnostic domain shapes the GraphQL schema renders.\n// -----------------------------------------------------------------------------\n\n/** One DeepBook pool object id + coin types (prices are chain-direct). */\nexport interface DashboardDeepbookPool {\n\treadonly name: string;\n\treadonly poolId: string;\n\treadonly baseCoinType: string;\n\treadonly quoteCoinType: string;\n}\n\n/** One Pyth price feed seeded inside DeepBook at boot. `price`/`expo` are the\n * FIXED boot-time mock values (static, not a live quote); `price` is carried\n * as a string so large signed values survive the wire without precision loss. */\nexport interface DashboardPythFeed {\n\treadonly symbol: string;\n\treadonly priceInfoObjectId: string;\n\treadonly price: string;\n\treadonly expo: number;\n}\n\nexport interface DashboardDeepbookInfo {\n\treadonly pluginKey: string;\n\treadonly name: string;\n\treadonly mode: 'local' | 'override' | 'known';\n\treadonly network: string;\n\treadonly packageId: string;\n\treadonly registryId: string;\n\treadonly adminCapId: string | null;\n\treadonly deepTreasuryId: string | null;\n\treadonly pools: ReadonlyArray<DashboardDeepbookPool>;\n\t/** Pyth price feeds seeded inside this DeepBook deployment (boot-time mock\n\t * prices). Empty when no Pyth feeds were configured. */\n\treadonly pythFeeds: ReadonlyArray<DashboardPythFeed>;\n\t/** `true` when one or more pools placed seed orders at boot (NOT a\n\t * market-maker process state). */\n\treadonly hasSeedLiquidity: boolean;\n\treadonly serverUrl: string | null;\n\treadonly indexerUrl: string | null;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud: schema drift surfaced to the caller\n\t * instead of silently degrading). */\n\treadonly narrowingFault: string | null;\n}\n\nexport interface DashboardSealKeyServer {\n\treadonly objectId: string;\n\treadonly weight: number;\n}\n\nexport interface DashboardSealInfo {\n\treadonly pluginKey: string;\n\treadonly mode: 'local-keygen' | 'live' | 'fork-known';\n\treadonly objectId: string;\n\treadonly keyServerUrl: string;\n\treadonly keyServers: ReadonlyArray<DashboardSealKeyServer>;\n\t/** Threshold = number of registered key-server configs. */\n\treadonly threshold: number;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud). */\n\treadonly narrowingFault: string | null;\n}\n\n/** A coin's treasury-cap id (drives the Mint action) + addressing facts. */\nexport interface DashboardCoinCap {\n\treadonly pluginKey: string;\n\treadonly symbol: string | null;\n\treadonly fullCoinType: string;\n\treadonly decimals: number;\n\treadonly source: 'registry' | 'on-chain' | 'builtin';\n\treadonly treasuryCapId: string | null;\n\treadonly packageId: string | null;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud). */\n\treadonly narrowingFault: string | null;\n}\n\n/** Input for the dashboard mint ACTION. `amountBaseUnits` is the raw\n * integer amount in the coin's smallest unit (decimals already applied\n * by the caller / form) — a string so large u64 values survive the wire\n * without precision loss. */\nexport interface DashboardMintInput {\n\treadonly coinType: string;\n\treadonly recipient: string;\n\treadonly amountBaseUnits: string;\n}\n\n/** Outcome of a dashboard mint ACTION. Mirrors the snapshot\n * restore/delete result shape plus the on-chain tx `digest` on success. */\nexport interface DashboardMintResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\n}\n\n/** Input for the dashboard fund ACTION.\n *\n * `coinType` selects the funding strategy: absent or the canonical SUI\n * type routes through the chain's faucet strategy (`faucet:request:<chainId>`,\n * fixed-amount); any other full coin type routes through the coin-specific\n * `coinType:<fullCoinType>` strategy (WAL exchange swap / DEEP pool swap).\n *\n * `amountBaseUnits` is the raw integer amount in the coin's smallest unit\n * (a string so large u64 values survive the wire without precision loss).\n * The SUI faucet is fixed-amount and IGNORES it; WAL/DEEP honor it. */\nexport interface DashboardFundInput {\n\treadonly recipient: string;\n\treadonly coinType?: string | null;\n\treadonly amountBaseUnits?: string | null;\n}\n\n/** Outcome of a dashboard fund ACTION. The in-process funding strategies\n * return `void` (not a digest), so the result carries only `ok`/`detail`.\n * `ok:true` means the strategy's `request(...)` completed (the faucet POST\n * landed / the swap executed on-chain); `detail` carries the reason on\n * failure. */\nexport interface DashboardFundResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n}\n\n/** One coin the dashboard faucet can actually fund, with whether the\n * underlying strategy honors a caller-supplied amount.\n *\n * SUI is always present (fixed-amount faucet, `honorsAmount: false`).\n * WAL/DEEP appear only when their plugin registered a `coinType:<X>`\n * funding strategy AND (for WAL) carries a swap that spends the\n * recipient account's SUI — so `honorsAmount: true`. */\nexport interface DashboardFundableCoin {\n\treadonly symbol: string;\n\treadonly coinType: string;\n\treadonly honorsAmount: boolean;\n\t/** True when funding requires the recipient to BE a resolved account in\n\t * the stack (the swap spends that account's own SUI via its in-process\n\t * signer). SUI is `false` (any 0x address); WAL/DEEP are `true`. */\n\treadonly requiresAccountSigner: boolean;\n}\n\n/** The dashboard plugin-domain accessor surface. Each member is a\n * self-contained Effect that never fails (`E = never`); they degrade to\n * empty/`null` so a single missing plugin can't take down the dashboard\n * query. */\nexport interface DashboardDomain {\n\t/** Fork-vs-local mode, derived from the resolved sui plugin's chain\n\t * identity. Used for advance-clock gating. `null` when no sui plugin\n\t * is present. */\n\treadonly mode: Effect.Effect<'fork' | 'local' | 'live' | null>;\n\t/** DeepBook deployments (registry/admin/pool ids + MM state). */\n\treadonly deepbook: Effect.Effect<ReadonlyArray<DashboardDeepbookInfo>>;\n\t/** Seal key-server deployments (objectId/threshold/mode). */\n\treadonly seal: Effect.Effect<ReadonlyArray<DashboardSealInfo>>;\n\t/** Coin treasury caps (drives Mint). */\n\treadonly coinCaps: Effect.Effect<ReadonlyArray<DashboardCoinCap>>;\n\t/** Mint ACTION — mints `amountBaseUnits` of `coinType` to `recipient`,\n\t * signed in-process by the treasury-cap-owning publisher signer the\n\t * resolved coin value's self-contained `mintFromCap` closure holds. */\n\treadonly mintCoin: (input: DashboardMintInput) => Effect.Effect<DashboardMintResult>;\n\t/** Coins the faucet can actually fund right now (SUI always; WAL/DEEP\n\t * only when their plugin registered a funding strategy). Drives the\n\t * faucet panel's coin pills + amount-field gating. */\n\treadonly fundableCoins: Effect.Effect<ReadonlyArray<DashboardFundableCoin>>;\n\t/** Fund ACTION — reuses devstack's in-process funding strategies. SUI\n\t * (absent/canonical type) routes through the chain faucet strategy\n\t * (fixed-amount); WAL/DEEP route through the coin-specific funding\n\t * strategy (account-signed exchange/pool swap). Real result — `ok`\n\t * reflects whether the strategy's `request(...)` completed. */\n\treadonly fundAccount: (input: DashboardFundInput) => Effect.Effect<DashboardFundResult>;\n}\n\n// -----------------------------------------------------------------------------\n// Structural projections of plugin-resolved values\n//\n// We narrow the opaque `unknown` resolved value through shallow structural\n// shapes that mirror the relevant fields. A field missing on the live value\n// collapses to the null/empty default.\n// -----------------------------------------------------------------------------\n\ninterface DeepbookShape {\n\treadonly mode?: unknown;\n\treadonly network?: unknown;\n\treadonly packageId?: unknown;\n\treadonly registryId?: unknown;\n\treadonly adminCapId?: unknown;\n\treadonly deepTreasuryId?: unknown;\n\treadonly pools?: ReadonlyArray<{\n\t\treadonly name?: unknown;\n\t\treadonly poolId?: unknown;\n\t\treadonly baseCoinType?: unknown;\n\t\treadonly quoteCoinType?: unknown;\n\t}>;\n\t/** Resolved Pyth handle (`PythHandle | null`); we read only `feeds`. */\n\treadonly pyth?: {\n\t\treadonly feeds?: ReadonlyArray<{\n\t\t\treadonly symbol?: unknown;\n\t\t\treadonly priceInfoObjectId?: unknown;\n\t\t\treadonly price?: unknown;\n\t\t\treadonly expo?: unknown;\n\t\t}>;\n\t} | null;\n\treadonly hasSeedLiquidity?: unknown;\n\treadonly serverUrl?: unknown;\n\treadonly indexerUrl?: unknown;\n}\n\ninterface SealShape {\n\treadonly mode?: unknown;\n\treadonly objectId?: unknown;\n\treadonly keyServerUrl?: unknown;\n\treadonly serverConfigs?: ReadonlyArray<{\n\t\treadonly objectId?: unknown;\n\t\treadonly weight?: unknown;\n\t}>;\n}\n\ninterface CoinShape {\n\treadonly symbol?: unknown;\n\treadonly fullCoinType?: unknown;\n\treadonly decimals?: unknown;\n\treadonly source?: unknown;\n\treadonly treasuryCapId?: unknown;\n\treadonly packageId?: unknown;\n\t/** Self-contained mint closure on the resolved coin value (present\n\t * for witness-form coins whose publisher still owns the cap). Read\n\t * structurally — we import no coin types. Returns an Effect that\n\t * resolves a `{ digest }`-bearing result or fails with a\n\t * coin/artifact-publisher tagged error. */\n\treadonly mintFromCap?: (opts: {\n\t\treadonly to: string;\n\t\treadonly amount: bigint;\n\t}) => Effect.Effect<{ readonly digest: string }, { readonly message?: unknown }>;\n}\n\ninterface SuiShape {\n\treadonly mode?: unknown;\n\t/** Genesis-digest chain id (`'sui:localnet'`, `'sui:testnet'`,\n\t * `'sui:mainnet-fork@123'`). Composes the faucet capability key\n\t * (`faucet:request:<chainId>`) the SUI funding path resolves. */\n\treadonly chainId?: unknown;\n}\n\n/** Structural shape of the resolved account value (`account/<name>`). The\n * WAL/DEEP funding strategies need this handle as `req.account` — the swap\n * spends the recipient account's own SUI through its in-process signer.\n * Narrowed to the fields the strategy dispatch reads; the full\n * `AccountValue` is assignable to it, so we cast the matched value across\n * the seam without importing the account VALUE shape structurally\n * elsewhere. */\ninterface AccountShape {\n\treadonly address?: unknown;\n\treadonly name?: unknown;\n}\n\n/** A 0x-prefixed Sui address: `0x` + 1..64 hex digits. Mirrors the\n * address validation the mint PTB's `tx.pure.address` ultimately\n * enforces, surfaced up front so the dashboard gets a clean rejection\n * rather than an opaque build failure. */\nconst SUI_ADDRESS_RE = /^0x[0-9a-fA-F]{1,64}$/;\n\n/** The canonical builtin SUI coin type — selects the SUI faucet funding\n * path. Mirrors `SUI_FULL_COIN_TYPE` in `plugins/account/funding.ts`\n * (inlined here so the dashboard plugin does not cross-import the account\n * funding module just for the string). */\nconst SUI_FULL_COIN_TYPE = '0x2::sui::SUI' as const;\n\n/** A positive integer base-unit amount string (no sign, no decimal\n * point, no leading zeros beyond a bare `0` — which is itself rejected\n * as non-positive). */\nconst isPositiveIntegerString = (s: string): boolean => {\n\tif (!/^\\d+$/.test(s)) return false;\n\ttry {\n\t\treturn BigInt(s) > 0n;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** Compose the chain faucet capability key (`faucet:request:<chainId>`)\n * the SUI funding path resolves. Uses the faucet plugin's prefix constant\n * (single source of truth) — same key the boot-time funding pass builds. */\nconst faucetCapabilityKeyFor = (\n\tchain: string,\n): `${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${string}` => `${FAUCET_CAPABILITY_KEY_PREFIX}:${chain}`;\n\n/** Parse a base-unit amount string into a positive bigint, or `null` when\n * absent / non-positive / non-integer. */\nconst parseAmount = (s: string | null | undefined): bigint | null => {\n\tif (s == null) return null;\n\tconst trimmed = s.trim();\n\tif (!isPositiveIntegerString(trimmed)) return null;\n\treturn BigInt(trimmed);\n};\n\n/** Derive a display symbol from a full coin type's module path\n * (`0x…::wal::WAL` → `WAL`, `0x…::deep::DEEP` → `DEEP`). Falls back to the\n * struct name, then the raw type. Keeps the dashboard name-blind on the\n * resolved coin VALUE while still labeling the faucet pill. */\nconst coinSymbolFromType = (coinType: string): string => {\n\tconst parts = coinType.split('::');\n\tconst struct = parts[parts.length - 1];\n\treturn struct !== undefined && struct.length > 0 ? struct : coinType;\n};\n\n/** Extract a human detail from a faucet/funding strategy failure. The\n * strategy error channels are tagged structs carrying `message`/`reason`;\n * read them structurally without importing each plugin's error type. */\nconst causeDetail = (cause: unknown): string => {\n\tif (cause !== null && typeof cause === 'object') {\n\t\tconst c = cause as {\n\t\t\treadonly message?: unknown;\n\t\t\treadonly reason?: unknown;\n\t\t\treadonly _tag?: unknown;\n\t\t};\n\t\tif (typeof c.message === 'string' && c.message.length > 0) return c.message;\n\t\tif (typeof c.reason === 'string' && c.reason.length > 0) return c.reason;\n\t\tif (typeof c._tag === 'string' && c._tag.length > 0) return c._tag;\n\t}\n\treturn String(cause);\n};\nconst faucetCauseDetail = causeDetail;\nconst fundingCauseDetail = causeDetail;\n\n// -----------------------------------------------------------------------------\n// Fail-aware structural narrowing\n//\n// The substrate hands us opaque `unknown` resolved values. We still narrow\n// through shallow structural shapes, but instead of SILENTLY degrading a\n// missing/wrong-typed required field to ''/0 (which hid integration-seam\n// drift), the `req*` readers ACCUMULATE a typed narrowing fault into a\n// per-shaping-call collector. The fault is threaded into the GraphQL-visible\n// result (`narrowingFault` / `detail`) so consumers SEE the drift — WITHOUT\n// ever throwing (the dashboard's `E = never` surface semantic is preserved).\n// `opt*` readers stay quiet: they are for genuinely-optional fields.\n// -----------------------------------------------------------------------------\n\n/** Mutable per-call sink for structural-narrowing faults. */\ntype FaultSink = Array<string>;\n\nconst newFaults = (): FaultSink => [];\n\n/** Collapse accumulated faults into a single nullable detail string for the\n * GraphQL-visible result. `null` when nothing drifted. */\nconst faultDetail = (faults: FaultSink): string | null =>\n\tfaults.length === 0 ? null : faults.join('; ');\n\n/** Describe why a value failed to narrow to the expected type — distinguishing\n * 'absent' from 'present but wrong type'. */\nconst typeFault = (field: string, expected: string, v: unknown): string => {\n\tif (v === undefined || v === null) return `${field}: missing (expected ${expected})`;\n\treturn `${field}: expected ${expected}, got ${typeof v}`;\n};\n\n/** Required string. On mismatch records a fault and returns '' so the panel\n * still renders a (degraded) cell. */\nconst reqStr = (v: unknown, field: string, faults: FaultSink): string => {\n\tif (typeof v === 'string') return v;\n\tfaults.push(typeFault(field, 'string', v));\n\treturn '';\n};\n\n/** Required finite number. On mismatch records a fault and returns the safe\n * display fallback (`fallback`, default 0). */\nconst reqNum = (v: unknown, field: string, faults: FaultSink, fallback = 0): number => {\n\tif (typeof v === 'number' && Number.isFinite(v)) return v;\n\tfaults.push(typeFault(field, 'number', v));\n\treturn fallback;\n};\n\n/** Allow-list enum narrow. Records a fault for an out-of-enum value while\n * still returning a safe display fallback so the panel renders. */\nconst narrowEnum = <T extends string>(\n\traw: unknown,\n\tallowed: ReadonlyArray<T>,\n\tfield: string,\n\tfaults: FaultSink,\n\tfallback: T,\n): T => {\n\tif (typeof raw === 'string' && (allowed as ReadonlyArray<string>).includes(raw)) return raw as T;\n\tfaults.push(\n\t\traw === undefined || raw === null\n\t\t\t? `${field}: missing (expected one of ${allowed.join('|')})`\n\t\t\t: `${field}: '${String(raw)}' not in ${allowed.join('|')}`,\n\t);\n\treturn fallback;\n};\n\n/** Required string-or-numeric coerced to a string. Pyth feed prices arrive as a\n * `bigint` on the resolved value (string in the cached/known shape); accept any\n * of string/number/bigint and record a fault otherwise. Returns '0' on\n * mismatch so the panel still renders a (degraded) cell. */\nconst reqNumericStr = (v: unknown, field: string, faults: FaultSink): string => {\n\tif (typeof v === 'string') return v;\n\tif (typeof v === 'bigint') return v.toString();\n\tif (typeof v === 'number' && Number.isFinite(v)) return String(v);\n\tfaults.push(typeFault(field, 'string|number|bigint', v));\n\treturn '0';\n};\n\n// Genuinely-optional readers — silent by design (absent is a valid state).\nconst optStr = (v: unknown): string | null => (typeof v === 'string' ? v : null);\nconst optNum = (v: unknown): number | null =>\n\ttypeof v === 'number' && Number.isFinite(v) ? v : null;\nconst bool = (v: unknown): boolean => v === true;\n\n/** Filter the generic resolved values down to those whose resource id\n * matches a predicate, in graph order. Returns the `{ pluginKey, value }`\n * the shaping functions consume. */\nconst matching = (\n\tvalues: ReadonlyArray<ControlPlaneResolvedValue>,\n\tmatches: (resourceId: string) => boolean,\n): ReadonlyArray<ControlPlaneResolvedValue> => values.filter((v) => matches(v.id));\n\n// -----------------------------------------------------------------------------\n// Builder\n// -----------------------------------------------------------------------------\n\nexport interface DashboardDomainDeps {\n\t/** The generic, name-blind control-plane domain (resolved values). */\n\treadonly control: ControlPlaneDomain;\n\t/** The scope-local strategy registry — the SAME registry the boot-time\n\t * account funding pass dispatches through (`plugins/account/funding.ts`).\n\t * Drives `fundableCoins` + `fundAccount`: SUI via `faucet:request:<chainId>`,\n\t * WAL/DEEP via `coinType:<fullCoinType>`. `null` in bare test paths; the\n\t * fund accessors degrade to unavailable then. */\n\treadonly strategyRegistry: StrategyRegistry | null;\n}\n\nexport const buildDashboardDomain = (deps: DashboardDomainDeps): DashboardDomain => {\n\tconst { control, strategyRegistry } = deps;\n\n\tconst mode: DashboardDomain['mode'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\tif (sui === undefined) return null;\n\t\t\tconst m = (sui.value as SuiShape).mode;\n\t\t\tswitch (m) {\n\t\t\t\tcase 'fork':\n\t\t\t\t\treturn 'fork';\n\t\t\t\tcase 'live':\n\t\t\t\t\treturn 'live';\n\t\t\t\tcase 'local':\n\t\t\t\tcase 'local-rpc':\n\t\t\t\t\treturn 'local';\n\t\t\t\tdefault:\n\t\t\t\t\treturn null;\n\t\t\t}\n\t\t}),\n\t);\n\n\tconst deepbook: DashboardDomain['deepbook'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('deepbook/')).map(\n\t\t\t\t({ pluginKey, value }): DashboardDeepbookInfo => {\n\t\t\t\t\tconst v = value as DeepbookShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst dbMode = narrowEnum(\n\t\t\t\t\t\tv.mode,\n\t\t\t\t\t\t['local', 'override', 'known'] as const,\n\t\t\t\t\t\t'deepbook.mode',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'local',\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tname: pluginKey.replace(/^deepbook:/, ''),\n\t\t\t\t\t\tmode: dbMode,\n\t\t\t\t\t\tnetwork: reqStr(v.network, 'deepbook.network', faults),\n\t\t\t\t\t\tpackageId: reqStr(v.packageId, 'deepbook.packageId', faults),\n\t\t\t\t\t\tregistryId: reqStr(v.registryId, 'deepbook.registryId', faults),\n\t\t\t\t\t\tadminCapId: optStr(v.adminCapId),\n\t\t\t\t\t\tdeepTreasuryId: optStr(v.deepTreasuryId),\n\t\t\t\t\t\tpools: (v.pools ?? []).map((p, i) => ({\n\t\t\t\t\t\t\tname: reqStr(p.name, `deepbook.pools[${i}].name`, faults),\n\t\t\t\t\t\t\tpoolId: reqStr(p.poolId, `deepbook.pools[${i}].poolId`, faults),\n\t\t\t\t\t\t\tbaseCoinType: reqStr(p.baseCoinType, `deepbook.pools[${i}].baseCoinType`, faults),\n\t\t\t\t\t\t\tquoteCoinType: reqStr(p.quoteCoinType, `deepbook.pools[${i}].quoteCoinType`, faults),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\t// Pyth feeds are seeded inside DeepBook (`pyth.feeds`); absent\n\t\t\t\t\t\t// when no Pyth feeds were configured (`pyth` is null/empty).\n\t\t\t\t\t\tpythFeeds: (v.pyth?.feeds ?? []).map((f, i) => ({\n\t\t\t\t\t\t\tsymbol: reqStr(f.symbol, `deepbook.pyth.feeds[${i}].symbol`, faults),\n\t\t\t\t\t\t\tpriceInfoObjectId: reqStr(\n\t\t\t\t\t\t\t\tf.priceInfoObjectId,\n\t\t\t\t\t\t\t\t`deepbook.pyth.feeds[${i}].priceInfoObjectId`,\n\t\t\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tprice: reqNumericStr(f.price, `deepbook.pyth.feeds[${i}].price`, faults),\n\t\t\t\t\t\t\texpo: reqNum(f.expo, `deepbook.pyth.feeds[${i}].expo`, faults),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\thasSeedLiquidity: bool(v.hasSeedLiquidity),\n\t\t\t\t\t\tserverUrl: optStr(v.serverUrl),\n\t\t\t\t\t\tindexerUrl: optStr(v.indexerUrl),\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst seal: DashboardDomain['seal'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('seal:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardSealInfo => {\n\t\t\t\t\tconst v = value as SealShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst sealMode = narrowEnum(\n\t\t\t\t\t\tv.mode,\n\t\t\t\t\t\t['local-keygen', 'live', 'fork-known'] as const,\n\t\t\t\t\t\t'seal.mode',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'local-keygen',\n\t\t\t\t\t);\n\t\t\t\t\tconst keyServers = (v.serverConfigs ?? []).map((c, i) => ({\n\t\t\t\t\t\tobjectId: reqStr(c.objectId, `seal.serverConfigs[${i}].objectId`, faults),\n\t\t\t\t\t\tweight: optNum(c.weight) ?? 1,\n\t\t\t\t\t}));\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tmode: sealMode,\n\t\t\t\t\t\tobjectId: reqStr(v.objectId, 'seal.objectId', faults),\n\t\t\t\t\t\tkeyServerUrl: reqStr(v.keyServerUrl, 'seal.keyServerUrl', faults),\n\t\t\t\t\t\tkeyServers,\n\t\t\t\t\t\tthreshold: keyServers.length,\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst coinCaps: DashboardDomain['coinCaps'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('coin:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardCoinCap => {\n\t\t\t\t\tconst v = value as CoinShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst source = narrowEnum(\n\t\t\t\t\t\tv.source,\n\t\t\t\t\t\t['registry', 'on-chain', 'builtin'] as const,\n\t\t\t\t\t\t'coin.source',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'on-chain',\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tsymbol: optStr(v.symbol),\n\t\t\t\t\t\tfullCoinType: reqStr(v.fullCoinType, 'coin.fullCoinType', faults),\n\t\t\t\t\t\tdecimals: reqNum(v.decimals, 'coin.decimals', faults, 0),\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\ttreasuryCapId: optStr(v.treasuryCapId),\n\t\t\t\t\t\tpackageId: optStr(v.packageId),\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\t// Mint ACTION — drives the dashboard Coins panel's Mint button.\n\t//\n\t// Signer source: the resolved coin VALUE carries a self-contained\n\t// `mintFromCap` closure (present only for witness-form coins whose\n\t// publisher still owns the TreasuryCap). That closure already captures\n\t// the treasury-cap-owning publisher `MintSigner` + the resolved cap id\n\t// in-process — the same lease-owning path `coin/service.ts`'s\n\t// `fundingStrategy` uses — so we mint WITHOUT threading a signer through\n\t// this seam (we read the resolved value, never plugin internals).\n\t//\n\t// Never fails (`E = never`): every reject path (bad address, non-\n\t// positive amount, no matching coin, cap-not-owned, on-chain failure)\n\t// degrades to `{ ok: false, detail, digest: null }` so the dashboard\n\t// query can't be taken down by a single bad mint.\n\tconst mintCoin: DashboardDomain['mintCoin'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (!isPositiveIntegerString(input.amountBaseUnits)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits}': expected a positive integer string`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\t// Locate the resolved coin whose fullCoinType matches. Match on the\n\t\t\t// resolved value's `fullCoinType` (the stable on-chain type), not the\n\t\t\t// resource-id prefix, so callers pass the same `coinType` the\n\t\t\t// `coinCaps` query surfaced. Read `fullCoinType` fail-loud so a coin\n\t\t\t// value missing/empty `fullCoinType` names the REAL cause (a drifted\n\t\t\t// resolved shape) rather than collapsing into the generic\n\t\t\t// 'no resolved coin found' reject.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst candidates = matching(values, (id) => id.startsWith('coin:')).map(\n\t\t\t\t({ value }) => value as CoinShape,\n\t\t\t);\n\t\t\tconst matchFaults = newFaults();\n\t\t\tconst match = candidates.find(\n\t\t\t\t(v) => reqStr(v.fullCoinType, 'coin.fullCoinType', matchFaults) === input.coinType,\n\t\t\t);\n\n\t\t\tif (match === undefined) {\n\t\t\t\tconst fault = faultDetail(matchFaults);\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\tfault === null\n\t\t\t\t\t\t\t? `no resolved coin found for type '${input.coinType}'`\n\t\t\t\t\t\t\t: `no resolved coin found for type '${input.coinType}' (${fault})`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (typeof match.mintFromCap !== 'function') {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${input.coinType}' has no in-process treasury cap signer — ` +\n\t\t\t\t\t\t'mint is only available for local-package coins whose publisher still owns the TreasuryCap',\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\treturn yield* match\n\t\t\t\t.mintFromCap({ to: recipient, amount: BigInt(input.amountBaseUnits) })\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(r): DashboardMintResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `minted ${input.amountBaseUnits} of ${input.coinType} to ${recipient}`,\n\t\t\t\t\t\t\tdigest: r.digest,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Typed coin/artifact-publisher failures carry `.message`.\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\t\ttypeof cause?.message === 'string'\n\t\t\t\t\t\t\t\t\t? cause.message\n\t\t\t\t\t\t\t\t\t: `mint failed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Residual defects (interrupts, unexpected throws) — degrade\n\t\t\t\t\t// rather than crash the dashboard query.\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `mint crashed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\t// --- Fund ACTION + fundable-coin derivation ------------------------\n\t//\n\t// Reuses devstack's IN-PROCESS funding strategies — the same strategy\n\t// registry the boot-time account funding pass dispatches through\n\t// (`plugins/account/funding.ts`). We never re-implement signing or the\n\t// exchange/pool swaps:\n\t//\n\t// - SUI (absent / canonical type) → `faucet:request:<chainId>`. The SUI\n\t// faucet strategy takes `{ address, amount }` only (no account handle)\n\t// and is FIXED-AMOUNT (the standard faucet ignores `amount`). Recipient\n\t// may be ANY 0x address.\n\t// - WAL/DEEP → `coinType:<fullCoinType>`. The strategy takes\n\t// `{ address, amount, account }` and runs an account-signed swap, so\n\t// the recipient MUST be a resolved account in the stack (we match the\n\t// recipient address against the resolved `account/<name>` values and\n\t// pass the live `AccountValue` as `req.account`).\n\t//\n\t// Never fails (`E = never`): every reject path degrades to\n\t// `{ ok:false, detail }` so a single bad fund can't take down the query.\n\n\t/** The chain id the SUI funding path keys on, read from the resolved sui\n\t * value (same `chainId` field the sui codegen/snapshot decls stamp). */\n\tconst readChainId = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\treturn sui === undefined ? null : optStr((sui.value as SuiShape).chainId);\n\t\t}),\n\t);\n\n\tconst fundableCoins: DashboardDomain['fundableCoins'] = Effect.gen(function* () {\n\t\t// SUI is always fundable when a faucet strategy is registered for the\n\t\t// active chain; the fixed-amount faucet ignores the requested amount.\n\t\tconst out: DashboardFundableCoin[] = [];\n\t\tif (strategyRegistry === null) return out;\n\n\t\tconst chain = yield* readChainId;\n\t\tconst keys = yield* strategyRegistry.list();\n\t\tif (chain !== null && keys.includes(faucetCapabilityKeyFor(chain))) {\n\t\t\tout.push({\n\t\t\t\tsymbol: 'SUI',\n\t\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t\t\thonorsAmount: false,\n\t\t\t\trequiresAccountSigner: false,\n\t\t\t});\n\t\t}\n\n\t\t// A coin is fundable iff a `coinType:<fullCoinType>` strategy is actually\n\t\t// registered (the walrus/deepbook/coin plugin contributed one). Derive the\n\t\t// display symbol from the coin type's module path (`::wal::WAL` → WAL,\n\t\t// `::deep::DEEP` → DEEP) so we stay name-blind on the coin VALUE while\n\t\t// still labeling the pill. `requiresAccountSigner` is read from the\n\t\t// strategy's own `requiresRecipientAccount` flag — NOT assumed true for\n\t\t// every coin: WAL/DEEP swaps spend the recipient's SUI (true), but a\n\t\t// managed-coin MINT strategy transfers to a passive recipient (false), so\n\t\t// it can fund any 0x address.\n\t\tfor (const key of keys) {\n\t\t\tif (!key.startsWith('coinType:')) continue;\n\t\t\tconst coinType = key.slice('coinType:'.length);\n\t\t\tif (coinType === SUI_FULL_COIN_TYPE) continue;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tout.push({\n\t\t\t\tsymbol: coinSymbolFromType(coinType),\n\t\t\t\tcoinType,\n\t\t\t\thonorsAmount: true,\n\t\t\t\trequiresAccountSigner: strategy?.requiresRecipientAccount ?? false,\n\t\t\t});\n\t\t}\n\t\treturn out;\n\t});\n\n\tconst fundAccount: DashboardDomain['fundAccount'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\t\t\tif (strategyRegistry === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: 'funding unavailable: no strategy registry wired',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst coinType = input.coinType?.trim() ?? '';\n\t\t\tconst isSui = coinType === '' || coinType === SUI_FULL_COIN_TYPE;\n\n\t\t\t// SUI path — chain faucet strategy. Fixed-amount: we pass a nominal\n\t\t\t// amount but the standard faucet ignores it. Recipient may be any\n\t\t\t// 0x address (no account handle required).\n\t\t\tif (isSui) {\n\t\t\t\tconst chain = yield* readChainId;\n\t\t\t\tif (chain === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: 'cannot fund SUI: no resolved sui plugin / chain id in this stack',\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\tconst key = faucetCapabilityKeyFor(chain);\n\t\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t\t.get<typeof key, FaucetStrategy>(key)\n\t\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\t\tif (strategy === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: `no SUI faucet strategy registered for chain '${chain}'`,\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\t// `amount` is nominal — the standard faucet grant is fixed and\n\t\t\t\t// ignores it. Default to 1 SUI in MIST so a strategy that DID\n\t\t\t\t// honor it lands a sane value.\n\t\t\t\tconst amount = parseAmount(input.amountBaseUnits) ?? 1_000_000_000n;\n\t\t\t\treturn yield* strategy.request({ address: recipient, amount }).pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `requested SUI for ${recipient} (fixed-amount faucet grant)`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request failed: ${faucetCauseDetail(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request crashed: ${String(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// WAL/DEEP path — coin-specific account-signed funding strategy.\n\t\t\tconst amount = parseAmount(input.amountBaseUnits);\n\t\t\tif (amount === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ''}': expected a positive integer string`,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst key = `coinType:${coinType}` as const;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tif (strategy === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`no funding strategy registered for coin '${coinType}' — ` +\n\t\t\t\t\t\t'WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\t// Match the recipient to a resolved account, if one holds this address.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst account = matching(values, (id) => id.startsWith('account/'))\n\t\t\t\t.map(({ value }) => value as AccountShape)\n\t\t\t\t.find((v) => optStr(v.address) === recipient);\n\n\t\t\t// Account-spending strategies (WAL/DEEP) swap the recipient's OWN SUI,\n\t\t\t// so the recipient must BE a resolved account with a signer. Mint-style\n\t\t\t// strategies (managed coins) transfer to a passive recipient, so any 0x\n\t\t\t// address is fine — gate the rejection on the strategy's flag, not on\n\t\t\t// the coin being non-SUI.\n\t\t\tif (strategy.requiresRecipientAccount === true && account === undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${coinType}' is funded by an account-signed swap, but '${recipient}' ` +\n\t\t\t\t\t\t'is not a resolved account in this stack — fund a configured account (the swap spends its SUI)',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\treturn yield* strategy\n\t\t\t\t.request({\n\t\t\t\t\taddress: recipient,\n\t\t\t\t\tamount,\n\t\t\t\t\t...(account === undefined ? {} : { account: account as unknown as AccountValue }),\n\t\t\t\t})\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `funded ${amount} base units of ${coinType} to ${recipient}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\treturn {\n\t\tmode,\n\t\tdeepbook,\n\t\tseal,\n\t\tcoinCaps,\n\t\tmintCoin,\n\t\tfundableCoins,\n\t\tfundAccount,\n\t};\n};\n\n/** An all-empty dashboard domain. Used by tests that exercise the\n * schema/server without a live registry. Every accessor resolves to\n * empty/`null`. */\nexport const emptyDashboardDomain: DashboardDomain = {\n\tmode: Effect.succeed(null),\n\tdeepbook: Effect.succeed([]),\n\tseal: Effect.succeed([]),\n\tcoinCaps: Effect.succeed([]),\n\tmintCoin: () => Effect.succeed({ ok: false, detail: 'unavailable', digest: null }),\n\tfundableCoins: Effect.succeed([]),\n\tfundAccount: () => Effect.succeed({ ok: false, detail: 'unavailable' }),\n};\n"],"mappings":"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"}
|
|
@@ -99,8 +99,8 @@ builder.queryType({ fields: (t) => ({
|
|
|
99
99
|
type: [SnapshotEntry],
|
|
100
100
|
resolve: (_parent, _args, ctx) => Effect.runPromise(ctx.domain.snapshots)
|
|
101
101
|
}),
|
|
102
|
-
/** DeepBook deployments: registry/admin/pool ids +
|
|
103
|
-
* state. (Pool prices / order books are chain-direct.) */
|
|
102
|
+
/** DeepBook deployments: registry/admin/pool ids + seed-liquidity
|
|
103
|
+
* state + Pyth feeds. (Pool prices / order books are chain-direct.) */
|
|
104
104
|
deepbookInfo: t.field({
|
|
105
105
|
type: [DeepbookInfo],
|
|
106
106
|
resolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.deepbook)
|
|
@@ -314,7 +314,9 @@ state: t.field({
|
|
|
314
314
|
/** Bridge an Effect `SubscriptionRef` to an async iterable for GraphQL
|
|
315
315
|
* subscriptions. `SubscriptionRef.changes` emits the current value first,
|
|
316
316
|
* then each subsequent update. The pump fiber is interrupted when the
|
|
317
|
-
* consumer (yoga) stops iterating.
|
|
317
|
+
* consumer (yoga) stops iterating.
|
|
318
|
+
*
|
|
319
|
+
* @yields {SubscribableState} the current subscribable state on each change */
|
|
318
320
|
async function* subscribeState(ref) {
|
|
319
321
|
const queue = Effect.runSync(Queue.unbounded());
|
|
320
322
|
const pump = Effect.runFork(Stream.runForEach(SubscriptionRef.changes(ref), (snapshot) => Queue.offer(queue, snapshot)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.mjs","names":[],"sources":["../../../../src/plugins/dashboard/schema/root.ts"],"sourcesContent":["// Dashboard root types — Query / Mutation / Subscription.\n//\n// Queries expose the live projection (`state`), relay node/connection\n// access over the snapshot arrays, and a liveness `ping`. Mutations map to\n// `EngineCommand`s. The single subscription streams the projection over the\n// SubscriptionRef→async-generator bridge. Dependencies (the `state` ref +\n// `publishCommand`) come from the GraphQL context (`ctx`), not closure — the\n// dashboard is a pure control plane (no chain reads).\n\nimport { Effect, Fiber, Queue, Stream, SubscriptionRef } from 'effect';\nimport { resolveArrayConnection } from '@pothos/plugin-relay';\nimport { builder } from './builder.ts';\nimport {\n\tAccount,\n\tCoinCap,\n\tDeepbookInfo,\n\tFundableCoin,\n\tLogFilterInput,\n\tLogRecordType,\n\tPackage,\n\tSealInfo,\n\tService,\n\tSnapshotEntry,\n\tStackState,\n\ttype ServiceSource,\n} from './types.ts';\nimport { StackMode } from './enums.ts';\nimport type { DashboardContext } from './builder.ts';\nimport type { PluginKey } from '../../../substrate/brand.ts';\nimport type { EngineCommand } from '../../../substrate/events.ts';\nimport type { SubscribableState } from '../../../substrate/projection.ts';\nimport type { LogFilter, LogLevel } from '../../../substrate/runtime/observability/index.ts';\n\nconst readSnapshot = (\n\tstate: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): Promise<SubscribableState> => Effect.runPromise(SubscriptionRef.get(state));\n\n// --- CommandResult ------------------------------------------------------\ninterface CommandResultShape {\n\treadonly ok: boolean;\n\treadonly command: string;\n\treadonly message?: string | null;\n}\n\nconst CommandResult = builder.objectRef<CommandResultShape>('CommandResult').implement({\n\tdescription: 'The outcome of dispatching an engine command.',\n\tfields: (t) => ({\n\t\tok: t.exposeBoolean('ok'),\n\t\tcommand: t.exposeString('command'),\n\t\tmessage: t.string({ nullable: true, resolve: (r) => r.message ?? null }),\n\t}),\n});\n\nconst run = async (\n\tctx: DashboardContext,\n\ttag: string,\n\tcommand: EngineCommand,\n): Promise<CommandResultShape> => {\n\tawait Effect.runPromise(ctx.publishCommand(command));\n\treturn { ok: true, command: tag };\n};\n\n// --- SnapshotActionResult -----------------------------------------------\n//\n// Restore/delete go through the control-plane `domain` (NOT the void\n// `publishCommand`), so the dashboard gets a real ok/detail outcome the\n// fire-and-forget command channel cannot carry.\ninterface SnapshotActionResultShape {\n\treadonly ok: boolean;\n\treadonly detail: string | null;\n}\n\nconst SnapshotActionResult = builder\n\t.objectRef<SnapshotActionResultShape>('SnapshotActionResult')\n\t.implement({\n\t\tdescription: 'The outcome of a snapshot restore/delete (real result, not fire-and-forget).',\n\t\tfields: (t) => ({\n\t\t\tok: t.exposeBoolean('ok'),\n\t\t\tdetail: t.string({ nullable: true, resolve: (r) => r.detail }),\n\t\t}),\n\t});\n\n// --- MintResult ---------------------------------------------------------\n//\n// The coin Mint action goes through the control-plane `domain` (NOT the\n// void `publishCommand`): the supervisor holds the treasury-cap-owning\n// signer in-process and returns a real ok/detail outcome plus the on-chain\n// tx `digest` on success.\ninterface MintResultShape {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\n}\n\nconst MintResult = builder.objectRef<MintResultShape>('MintResult').implement({\n\tdescription: 'The outcome of a coin mint (real result, with the on-chain tx digest on success).',\n\tfields: (t) => ({\n\t\tok: t.exposeBoolean('ok'),\n\t\tdetail: t.exposeString('detail'),\n\t\tdigest: t.string({ nullable: true, resolve: (r) => r.digest }),\n\t}),\n});\n\n// --- FundResult ---------------------------------------------------------\n//\n// The Faucet `fund` action routes through the control-plane `pluginDomain`,\n// reusing devstack's IN-PROCESS funding strategies (the same registry the\n// boot-time account funding pass uses): SUI via the chain faucet strategy\n// (fixed-amount), WAL/DEEP via the coin-specific account-signed swap. The\n// strategies return `void` (no digest), so the result carries only\n// `ok`/`detail`. `ok` reflects whether the strategy's `request(...)`\n// actually completed.\ninterface FundResultShape {\n\treadonly ok: boolean;\n\treadonly detail: string;\n}\n\nconst FundResult = builder.objectRef<FundResultShape>('FundResult').implement({\n\tdescription:\n\t\t'The outcome of a faucet fund request (real result — ok reflects whether the ' +\n\t\t'in-process funding strategy completed).',\n\tfields: (t) => ({\n\t\tok: t.exposeBoolean('ok'),\n\t\tdetail: t.exposeString('detail'),\n\t}),\n});\n\n// --- Query --------------------------------------------------------------\nbuilder.queryType({\n\tfields: (t) => ({\n\t\t/** Liveness probe. */\n\t\tping: t.string({ resolve: () => 'pong' }),\n\t\t/** Full live projection snapshot (status, services, endpoints, …). */\n\t\tstate: t.field({\n\t\t\ttype: StackState,\n\t\t\tresolve: (_parent, _args, ctx) => readSnapshot(ctx.state),\n\t\t}),\n\t\t/** Relay connection over the current snapshot's service rows. */\n\t\tservices: t.connection({\n\t\t\ttype: Service,\n\t\t\tresolve: async (_parent, args, ctx) => {\n\t\t\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\t\t\tconst sources: ServiceSource[] = snapshot.rows.map((row) => ({ row, snapshot }));\n\t\t\t\treturn resolveArrayConnection({ args }, sources);\n\t\t\t},\n\t\t}),\n\t\t/** Relay connection over the current snapshot's accounts. */\n\t\taccounts: t.connection({\n\t\t\ttype: Account,\n\t\t\tresolve: async (_parent, args, ctx) => {\n\t\t\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\t\t\treturn resolveArrayConnection({ args }, [...snapshot.accounts]);\n\t\t\t},\n\t\t}),\n\t\t/** Relay connection over the current snapshot's packages. */\n\t\tpackages: t.connection({\n\t\t\ttype: Package,\n\t\t\tresolve: async (_parent, args, ctx) => {\n\t\t\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\t\t\treturn resolveArrayConnection({ args }, [...snapshot.packages]);\n\t\t\t},\n\t\t}),\n\n\t\t// --- Plugin-domain queries (data the browser cannot reach) --------\n\t\t/** Fork-vs-local stack mode (advance-clock gating). `null` when no\n\t\t * sui plugin is present. */\n\t\tmode: t.field({\n\t\t\ttype: StackMode,\n\t\t\tnullable: true,\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.mode),\n\t\t}),\n\t\t/** Snapshot catalog: id/label/created/participants/containers. */\n\t\tsnapshots: t.field({\n\t\t\ttype: [SnapshotEntry],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.domain.snapshots),\n\t\t}),\n\t\t/** DeepBook deployments: registry/admin/pool ids + market-maker\n\t\t * state. (Pool prices / order books are chain-direct.) */\n\t\tdeepbookInfo: t.field({\n\t\t\ttype: [DeepbookInfo],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.deepbook),\n\t\t}),\n\t\t/** Seal key-server deployments: objectId/threshold/mode/keyServers. */\n\t\tsealInfo: t.field({\n\t\t\ttype: [SealInfo],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.seal),\n\t\t}),\n\t\t/** Coin treasury caps (drives Mint) + addressing facts. (Supply /\n\t\t * metadata are chain-direct.) */\n\t\tcoinCaps: t.field({\n\t\t\ttype: [CoinCap],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.coinCaps),\n\t\t}),\n\t\t/** Coins the faucet can actually fund right now (drives the Faucet\n\t\t * panel's coin pills + amount gating). SUI is always present when a\n\t\t * faucet strategy is registered; WAL/DEEP appear only when their\n\t\t * plugin contributed a funding strategy. */\n\t\tfundableCoins: t.field({\n\t\t\ttype: [FundableCoin],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.fundableCoins),\n\t\t}),\n\t\t// --- Observability (Console \"Logs\" tab) ---------------------------\n\t\t/** Cross-service queryable log history. Filterable server-side by\n\t\t * service / level / substring / time window; returns most-recent\n\t\t * first, capped by `filter.limit` (default = ring capacity). */\n\t\tlogs: t.field({\n\t\t\ttype: [LogRecordType],\n\t\t\targs: { filter: t.arg({ type: LogFilterInput, required: false }) },\n\t\t\tresolve: (_parent, args, ctx) => Effect.runPromise(ctx.domain.logs(toLogFilter(args.filter))),\n\t\t}),\n\t\t/** Distinct services currently in the log ring (filter dropdown). */\n\t\tlogServices: t.field({\n\t\t\ttype: ['String'],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.domain.logServices),\n\t\t}),\n\t}),\n});\n\n/** Closed log-level set used to narrow the String[] filter input back onto\n * the store's `LogLevel` union. Unknown strings are dropped (the store would\n * just never match them anyway). */\nconst LOG_LEVELS: ReadonlySet<LogLevel> = new Set<LogLevel>([\n\t'trace',\n\t'debug',\n\t'info',\n\t'warn',\n\t'error',\n\t'fatal',\n]);\n\nconst nonEmpty = (xs: readonly (string | null)[] | null | undefined): string[] | undefined => {\n\tif (xs == null) return undefined;\n\tconst out = xs.filter((x): x is string => x != null && x.length > 0);\n\treturn out.length > 0 ? out : undefined;\n};\n\n/** Map the nullable GraphQL `LogFilter` input onto the store's `LogFilter`,\n * dropping nulls and unknown levels. */\nconst toLogFilter = (\n\tinput:\n\t\t| {\n\t\t\t\tservices?: readonly (string | null)[] | null;\n\t\t\t\tlevels?: readonly (string | null)[] | null;\n\t\t\t\tsearch?: string | null;\n\t\t\t\tsinceMillis?: number | null;\n\t\t\t\tlimit?: number | null;\n\t\t }\n\t\t| null\n\t\t| undefined,\n): LogFilter | undefined => {\n\tif (input == null) return undefined;\n\tconst services = nonEmpty(input.services);\n\tconst levelStrings = nonEmpty(input.levels);\n\tconst levels = levelStrings?.filter((l): l is LogLevel => LOG_LEVELS.has(l as LogLevel));\n\treturn {\n\t\t...(services ? { services } : {}),\n\t\t...(levels && levels.length > 0 ? { levels } : {}),\n\t\t...(input.search != null ? { search: input.search } : {}),\n\t\t...(input.sinceMillis != null ? { sinceMillis: input.sinceMillis } : {}),\n\t\t...(input.limit != null ? { limit: input.limit } : {}),\n\t};\n};\n\n// --- Mutation -----------------------------------------------------------\nbuilder.mutationType({\n\tfields: (t) => ({\n\t\t/** Restart the whole stack. */\n\t\trestart: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'stack.restart', { tag: 'stack.restart' }),\n\t\t}),\n\t\t/** Selectively restart a single plugin subgraph. */\n\t\trestartPlugin: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { pluginKey: t.input.string({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'selective-restart.requested', {\n\t\t\t\t\ttag: 'selective-restart.requested',\n\t\t\t\t\tpluginKey: args.input.pluginKey as PluginKey,\n\t\t\t\t}),\n\t\t}),\n\t\t/** Capture a snapshot, optionally naming it. */\n\t\tcaptureSnapshot: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { name: t.input.string({ required: false }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'snapshot.capture', {\n\t\t\t\t\ttag: 'snapshot.capture',\n\t\t\t\t\t...(args.input.name == null ? {} : { name: args.input.name }),\n\t\t\t\t}),\n\t\t}),\n\t\t/** Re-run codegen against the live manifest. */\n\t\tcodegen: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'codegen.requested', { tag: 'codegen.requested' }),\n\t\t}),\n\t\t/** Re-apply the manifest, optionally scoped to a single plugin. */\n\t\tapply: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { pluginKey: t.input.string({ required: false }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'apply.requested', {\n\t\t\t\t\ttag: 'apply.requested',\n\t\t\t\t\t...(args.input.pluginKey == null ? {} : { pluginKey: args.input.pluginKey as PluginKey }),\n\t\t\t\t}),\n\t\t}),\n\t\t/** Wipe the live stack footprint (preserves the snapshot catalog). */\n\t\twipe: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'wipe.requested', { tag: 'wipe.requested' }),\n\t\t}),\n\t\t/** Prune the snapshot catalog + sweep byproduct images. */\n\t\tprune: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'prune.requested', { tag: 'prune.requested' }),\n\t\t}),\n\t\t/** Advance the (fork/local) chain clock to an absolute epoch-ms. */\n\t\tadvanceClock: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { toMillis: t.input.float({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'advance-clock.requested', {\n\t\t\t\t\ttag: 'advance-clock.requested',\n\t\t\t\t\ttoMillis: args.input.toMillis,\n\t\t\t\t}),\n\t\t}),\n\t\t/** Request a graceful stack shutdown. */\n\t\tshutdown: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) =>\n\t\t\t\trun(ctx, 'shutdown.requested', { tag: 'shutdown.requested' }),\n\t\t}),\n\t\t/** Restore a snapshot by id. Routes through the supervisor\n\t\t * command-loop via `submitCommand` (NOT the in-process\n\t\t * `domain.restoreSnapshot`): restore is destructive — it removes the\n\t\t * live managed containers and relies on a follow-on re-acquire to\n\t\t * rebuild them. Running it in-process against a live supervisor would\n\t\t * race the single command-queue consumer and leave services dead until\n\t\t * a manual Restart. The command-loop's `snapshot.restore` case applies\n\t\t * the restored tree, publishes `snapshot.restored`, THEN drains +\n\t\t * re-acquires every service (the manual-restart sequence) — and the\n\t\t * submitted-command completion deferred lets this mutation await the\n\t\t * real ok/detail outcome the void `publishCommand` could not carry. */\n\t\trestoreSnapshot: t.fieldWithInput({\n\t\t\ttype: SnapshotActionResult,\n\t\t\tinput: { id: t.input.string({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\tEffect.runPromise(\n\t\t\t\t\tctx.submitCommand({ tag: 'snapshot.restore', snapshotId: args.input.id }).pipe(\n\t\t\t\t\t\tEffect.as({ ok: true, detail: null as string | null }),\n\t\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\t\tEffect.succeed({ ok: false, detail: String(cause) as string | null }),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t}),\n\t\t/** Delete a snapshot by id (via the control-plane `domain`). */\n\t\tdeleteSnapshot: t.fieldWithInput({\n\t\t\ttype: SnapshotActionResult,\n\t\t\tinput: { id: t.input.string({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) => Effect.runPromise(ctx.domain.deleteSnapshot(args.input.id)),\n\t\t}),\n\t\t/** Mint a custom coin. Routes through the control-plane `domain`:\n\t\t * the supervisor holds the treasury-cap-owning publisher signer\n\t\t * in-process and returns a real ok/detail/digest result (the void\n\t\t * `publishCommand` could not carry the tx digest). `amountBaseUnits`\n\t\t * is the raw integer amount in the coin's smallest unit (string so\n\t\t * large u64 values survive the wire without precision loss). */\n\t\tmint: t.fieldWithInput({\n\t\t\ttype: MintResult,\n\t\t\tinput: {\n\t\t\t\tcoinType: t.input.string({ required: true }),\n\t\t\t\trecipient: t.input.string({ required: true }),\n\t\t\t\tamountBaseUnits: t.input.string({ required: true }),\n\t\t\t},\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\tEffect.runPromise(\n\t\t\t\t\tctx.pluginDomain.mintCoin({\n\t\t\t\t\t\tcoinType: args.input.coinType,\n\t\t\t\t\t\trecipient: args.input.recipient,\n\t\t\t\t\t\tamountBaseUnits: args.input.amountBaseUnits,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t\t/** Fund an account/address. Routes through the control-plane\n\t\t * `pluginDomain`, reusing devstack's in-process funding strategies:\n\t\t * SUI (absent / canonical `coinType`) via the chain faucet strategy\n\t\t * (fixed-amount — `amountBaseUnits` is ignored); WAL/DEEP via the\n\t\t * coin-specific account-signed swap (`amountBaseUnits` honored, and\n\t\t * the recipient must be a resolved account). Real result — `ok`\n\t\t * reflects whether the strategy completed. */\n\t\tfund: t.fieldWithInput({\n\t\t\ttype: FundResult,\n\t\t\tinput: {\n\t\t\t\trecipient: t.input.string({ required: true }),\n\t\t\t\tcoinType: t.input.string({ required: false }),\n\t\t\t\tamountBaseUnits: t.input.string({ required: false }),\n\t\t\t},\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\tEffect.runPromise(\n\t\t\t\t\tctx.pluginDomain.fundAccount({\n\t\t\t\t\t\trecipient: args.input.recipient,\n\t\t\t\t\t\tcoinType: args.input.coinType,\n\t\t\t\t\t\tamountBaseUnits: args.input.amountBaseUnits,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t}),\n});\n\n// --- Subscription -------------------------------------------------------\nbuilder.subscriptionType({\n\tfields: (t) => ({\n\t\t/** Stream the projection on every change (current value first). */\n\t\tstate: t.field({\n\t\t\ttype: StackState,\n\t\t\tsubscribe: (_parent, _args, ctx) => subscribeState(ctx.state),\n\t\t\tresolve: (payload) => payload,\n\t\t}),\n\t}),\n});\n\n/** Bridge an Effect `SubscriptionRef` to an async iterable for GraphQL\n * subscriptions. `SubscriptionRef.changes` emits the current value first,\n * then each subsequent update. The pump fiber is interrupted when the\n * consumer (yoga) stops iterating. */\nasync function* subscribeState(\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): AsyncGenerator<SubscribableState> {\n\tconst queue = Effect.runSync(Queue.unbounded<SubscribableState>());\n\tconst pump = Effect.runFork(\n\t\tStream.runForEach(SubscriptionRef.changes(ref), (snapshot) => Queue.offer(queue, snapshot)),\n\t);\n\ttry {\n\t\twhile (true) {\n\t\t\tyield await Effect.runPromise(Queue.take(queue));\n\t\t}\n\t} finally {\n\t\tEffect.runFork(Fiber.interrupt(pump));\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"root.mjs","names":[],"sources":["../../../../src/plugins/dashboard/schema/root.ts"],"sourcesContent":["// Dashboard root types — Query / Mutation / Subscription.\n//\n// Queries expose the live projection (`state`), relay node/connection\n// access over the snapshot arrays, and a liveness `ping`. Mutations map to\n// `EngineCommand`s. The single subscription streams the projection over the\n// SubscriptionRef→async-generator bridge. Dependencies (the `state` ref +\n// `publishCommand`) come from the GraphQL context (`ctx`), not closure — the\n// dashboard is a pure control plane (no chain reads).\n\nimport { Effect, Fiber, Queue, Stream, SubscriptionRef } from 'effect';\nimport { resolveArrayConnection } from '@pothos/plugin-relay';\nimport { builder } from './builder.ts';\nimport {\n\tAccount,\n\tCoinCap,\n\tDeepbookInfo,\n\tFundableCoin,\n\tLogFilterInput,\n\tLogRecordType,\n\tPackage,\n\tSealInfo,\n\tService,\n\tSnapshotEntry,\n\tStackState,\n\ttype ServiceSource,\n} from './types.ts';\nimport { StackMode } from './enums.ts';\nimport type { DashboardContext } from './builder.ts';\nimport type { PluginKey } from '../../../substrate/brand.ts';\nimport type { EngineCommand } from '../../../substrate/events.ts';\nimport type { SubscribableState } from '../../../substrate/projection.ts';\nimport type { LogFilter, LogLevel } from '../../../substrate/runtime/observability/index.ts';\n\nconst readSnapshot = (\n\tstate: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): Promise<SubscribableState> => Effect.runPromise(SubscriptionRef.get(state));\n\n// --- CommandResult ------------------------------------------------------\ninterface CommandResultShape {\n\treadonly ok: boolean;\n\treadonly command: string;\n\treadonly message?: string | null;\n}\n\nconst CommandResult = builder.objectRef<CommandResultShape>('CommandResult').implement({\n\tdescription: 'The outcome of dispatching an engine command.',\n\tfields: (t) => ({\n\t\tok: t.exposeBoolean('ok'),\n\t\tcommand: t.exposeString('command'),\n\t\tmessage: t.string({ nullable: true, resolve: (r) => r.message ?? null }),\n\t}),\n});\n\nconst run = async (\n\tctx: DashboardContext,\n\ttag: string,\n\tcommand: EngineCommand,\n): Promise<CommandResultShape> => {\n\tawait Effect.runPromise(ctx.publishCommand(command));\n\treturn { ok: true, command: tag };\n};\n\n// --- SnapshotActionResult -----------------------------------------------\n//\n// Restore/delete go through the control-plane `domain` (NOT the void\n// `publishCommand`), so the dashboard gets a real ok/detail outcome the\n// fire-and-forget command channel cannot carry.\ninterface SnapshotActionResultShape {\n\treadonly ok: boolean;\n\treadonly detail: string | null;\n}\n\nconst SnapshotActionResult = builder\n\t.objectRef<SnapshotActionResultShape>('SnapshotActionResult')\n\t.implement({\n\t\tdescription: 'The outcome of a snapshot restore/delete (real result, not fire-and-forget).',\n\t\tfields: (t) => ({\n\t\t\tok: t.exposeBoolean('ok'),\n\t\t\tdetail: t.string({ nullable: true, resolve: (r) => r.detail }),\n\t\t}),\n\t});\n\n// --- MintResult ---------------------------------------------------------\n//\n// The coin Mint action goes through the control-plane `domain` (NOT the\n// void `publishCommand`): the supervisor holds the treasury-cap-owning\n// signer in-process and returns a real ok/detail outcome plus the on-chain\n// tx `digest` on success.\ninterface MintResultShape {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\n}\n\nconst MintResult = builder.objectRef<MintResultShape>('MintResult').implement({\n\tdescription: 'The outcome of a coin mint (real result, with the on-chain tx digest on success).',\n\tfields: (t) => ({\n\t\tok: t.exposeBoolean('ok'),\n\t\tdetail: t.exposeString('detail'),\n\t\tdigest: t.string({ nullable: true, resolve: (r) => r.digest }),\n\t}),\n});\n\n// --- FundResult ---------------------------------------------------------\n//\n// The Faucet `fund` action routes through the control-plane `pluginDomain`,\n// reusing devstack's IN-PROCESS funding strategies (the same registry the\n// boot-time account funding pass uses): SUI via the chain faucet strategy\n// (fixed-amount), WAL/DEEP via the coin-specific account-signed swap. The\n// strategies return `void` (no digest), so the result carries only\n// `ok`/`detail`. `ok` reflects whether the strategy's `request(...)`\n// actually completed.\ninterface FundResultShape {\n\treadonly ok: boolean;\n\treadonly detail: string;\n}\n\nconst FundResult = builder.objectRef<FundResultShape>('FundResult').implement({\n\tdescription:\n\t\t'The outcome of a faucet fund request (real result — ok reflects whether the ' +\n\t\t'in-process funding strategy completed).',\n\tfields: (t) => ({\n\t\tok: t.exposeBoolean('ok'),\n\t\tdetail: t.exposeString('detail'),\n\t}),\n});\n\n// --- Query --------------------------------------------------------------\nbuilder.queryType({\n\tfields: (t) => ({\n\t\t/** Liveness probe. */\n\t\tping: t.string({ resolve: () => 'pong' }),\n\t\t/** Full live projection snapshot (status, services, endpoints, …). */\n\t\tstate: t.field({\n\t\t\ttype: StackState,\n\t\t\tresolve: (_parent, _args, ctx) => readSnapshot(ctx.state),\n\t\t}),\n\t\t/** Relay connection over the current snapshot's service rows. */\n\t\tservices: t.connection({\n\t\t\ttype: Service,\n\t\t\tresolve: async (_parent, args, ctx) => {\n\t\t\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\t\t\tconst sources: ServiceSource[] = snapshot.rows.map((row) => ({ row, snapshot }));\n\t\t\t\treturn resolveArrayConnection({ args }, sources);\n\t\t\t},\n\t\t}),\n\t\t/** Relay connection over the current snapshot's accounts. */\n\t\taccounts: t.connection({\n\t\t\ttype: Account,\n\t\t\tresolve: async (_parent, args, ctx) => {\n\t\t\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\t\t\treturn resolveArrayConnection({ args }, [...snapshot.accounts]);\n\t\t\t},\n\t\t}),\n\t\t/** Relay connection over the current snapshot's packages. */\n\t\tpackages: t.connection({\n\t\t\ttype: Package,\n\t\t\tresolve: async (_parent, args, ctx) => {\n\t\t\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\t\t\treturn resolveArrayConnection({ args }, [...snapshot.packages]);\n\t\t\t},\n\t\t}),\n\n\t\t// --- Plugin-domain queries (data the browser cannot reach) --------\n\t\t/** Fork-vs-local stack mode (advance-clock gating). `null` when no\n\t\t * sui plugin is present. */\n\t\tmode: t.field({\n\t\t\ttype: StackMode,\n\t\t\tnullable: true,\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.mode),\n\t\t}),\n\t\t/** Snapshot catalog: id/label/created/participants/containers. */\n\t\tsnapshots: t.field({\n\t\t\ttype: [SnapshotEntry],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.domain.snapshots),\n\t\t}),\n\t\t/** DeepBook deployments: registry/admin/pool ids + seed-liquidity\n\t\t * state + Pyth feeds. (Pool prices / order books are chain-direct.) */\n\t\tdeepbookInfo: t.field({\n\t\t\ttype: [DeepbookInfo],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.deepbook),\n\t\t}),\n\t\t/** Seal key-server deployments: objectId/threshold/mode/keyServers. */\n\t\tsealInfo: t.field({\n\t\t\ttype: [SealInfo],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.seal),\n\t\t}),\n\t\t/** Coin treasury caps (drives Mint) + addressing facts. (Supply /\n\t\t * metadata are chain-direct.) */\n\t\tcoinCaps: t.field({\n\t\t\ttype: [CoinCap],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.coinCaps),\n\t\t}),\n\t\t/** Coins the faucet can actually fund right now (drives the Faucet\n\t\t * panel's coin pills + amount gating). SUI is always present when a\n\t\t * faucet strategy is registered; WAL/DEEP appear only when their\n\t\t * plugin contributed a funding strategy. */\n\t\tfundableCoins: t.field({\n\t\t\ttype: [FundableCoin],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.pluginDomain.fundableCoins),\n\t\t}),\n\t\t// --- Observability (Console \"Logs\" tab) ---------------------------\n\t\t/** Cross-service queryable log history. Filterable server-side by\n\t\t * service / level / substring / time window; returns most-recent\n\t\t * first, capped by `filter.limit` (default = ring capacity). */\n\t\tlogs: t.field({\n\t\t\ttype: [LogRecordType],\n\t\t\targs: { filter: t.arg({ type: LogFilterInput, required: false }) },\n\t\t\tresolve: (_parent, args, ctx) => Effect.runPromise(ctx.domain.logs(toLogFilter(args.filter))),\n\t\t}),\n\t\t/** Distinct services currently in the log ring (filter dropdown). */\n\t\tlogServices: t.field({\n\t\t\ttype: ['String'],\n\t\t\tresolve: (_parent, _args, ctx) => Effect.runPromise(ctx.domain.logServices),\n\t\t}),\n\t}),\n});\n\n/** Closed log-level set used to narrow the String[] filter input back onto\n * the store's `LogLevel` union. Unknown strings are dropped (the store would\n * just never match them anyway). */\nconst LOG_LEVELS: ReadonlySet<LogLevel> = new Set<LogLevel>([\n\t'trace',\n\t'debug',\n\t'info',\n\t'warn',\n\t'error',\n\t'fatal',\n]);\n\nconst nonEmpty = (xs: readonly (string | null)[] | null | undefined): string[] | undefined => {\n\tif (xs == null) return undefined;\n\tconst out = xs.filter((x): x is string => x != null && x.length > 0);\n\treturn out.length > 0 ? out : undefined;\n};\n\n/** Map the nullable GraphQL `LogFilter` input onto the store's `LogFilter`,\n * dropping nulls and unknown levels. */\nconst toLogFilter = (\n\tinput:\n\t\t| {\n\t\t\t\tservices?: readonly (string | null)[] | null;\n\t\t\t\tlevels?: readonly (string | null)[] | null;\n\t\t\t\tsearch?: string | null;\n\t\t\t\tsinceMillis?: number | null;\n\t\t\t\tlimit?: number | null;\n\t\t }\n\t\t| null\n\t\t| undefined,\n): LogFilter | undefined => {\n\tif (input == null) return undefined;\n\tconst services = nonEmpty(input.services);\n\tconst levelStrings = nonEmpty(input.levels);\n\tconst levels = levelStrings?.filter((l): l is LogLevel => LOG_LEVELS.has(l as LogLevel));\n\treturn {\n\t\t...(services ? { services } : {}),\n\t\t...(levels && levels.length > 0 ? { levels } : {}),\n\t\t...(input.search != null ? { search: input.search } : {}),\n\t\t...(input.sinceMillis != null ? { sinceMillis: input.sinceMillis } : {}),\n\t\t...(input.limit != null ? { limit: input.limit } : {}),\n\t};\n};\n\n// --- Mutation -----------------------------------------------------------\nbuilder.mutationType({\n\tfields: (t) => ({\n\t\t/** Restart the whole stack. */\n\t\trestart: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'stack.restart', { tag: 'stack.restart' }),\n\t\t}),\n\t\t/** Selectively restart a single plugin subgraph. */\n\t\trestartPlugin: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { pluginKey: t.input.string({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'selective-restart.requested', {\n\t\t\t\t\ttag: 'selective-restart.requested',\n\t\t\t\t\tpluginKey: args.input.pluginKey as PluginKey,\n\t\t\t\t}),\n\t\t}),\n\t\t/** Capture a snapshot, optionally naming it. */\n\t\tcaptureSnapshot: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { name: t.input.string({ required: false }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'snapshot.capture', {\n\t\t\t\t\ttag: 'snapshot.capture',\n\t\t\t\t\t...(args.input.name == null ? {} : { name: args.input.name }),\n\t\t\t\t}),\n\t\t}),\n\t\t/** Re-run codegen against the live manifest. */\n\t\tcodegen: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'codegen.requested', { tag: 'codegen.requested' }),\n\t\t}),\n\t\t/** Re-apply the manifest, optionally scoped to a single plugin. */\n\t\tapply: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { pluginKey: t.input.string({ required: false }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'apply.requested', {\n\t\t\t\t\ttag: 'apply.requested',\n\t\t\t\t\t...(args.input.pluginKey == null ? {} : { pluginKey: args.input.pluginKey as PluginKey }),\n\t\t\t\t}),\n\t\t}),\n\t\t/** Wipe the live stack footprint (preserves the snapshot catalog). */\n\t\twipe: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'wipe.requested', { tag: 'wipe.requested' }),\n\t\t}),\n\t\t/** Prune the snapshot catalog + sweep byproduct images. */\n\t\tprune: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) => run(ctx, 'prune.requested', { tag: 'prune.requested' }),\n\t\t}),\n\t\t/** Advance the (fork/local) chain clock to an absolute epoch-ms. */\n\t\tadvanceClock: t.fieldWithInput({\n\t\t\ttype: CommandResult,\n\t\t\tinput: { toMillis: t.input.float({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\trun(ctx, 'advance-clock.requested', {\n\t\t\t\t\ttag: 'advance-clock.requested',\n\t\t\t\t\ttoMillis: args.input.toMillis,\n\t\t\t\t}),\n\t\t}),\n\t\t/** Request a graceful stack shutdown. */\n\t\tshutdown: t.field({\n\t\t\ttype: CommandResult,\n\t\t\tresolve: (_parent, _args, ctx) =>\n\t\t\t\trun(ctx, 'shutdown.requested', { tag: 'shutdown.requested' }),\n\t\t}),\n\t\t/** Restore a snapshot by id. Routes through the supervisor\n\t\t * command-loop via `submitCommand` (NOT the in-process\n\t\t * `domain.restoreSnapshot`): restore is destructive — it removes the\n\t\t * live managed containers and relies on a follow-on re-acquire to\n\t\t * rebuild them. Running it in-process against a live supervisor would\n\t\t * race the single command-queue consumer and leave services dead until\n\t\t * a manual Restart. The command-loop's `snapshot.restore` case applies\n\t\t * the restored tree, publishes `snapshot.restored`, THEN drains +\n\t\t * re-acquires every service (the manual-restart sequence) — and the\n\t\t * submitted-command completion deferred lets this mutation await the\n\t\t * real ok/detail outcome the void `publishCommand` could not carry. */\n\t\trestoreSnapshot: t.fieldWithInput({\n\t\t\ttype: SnapshotActionResult,\n\t\t\tinput: { id: t.input.string({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\tEffect.runPromise(\n\t\t\t\t\tctx.submitCommand({ tag: 'snapshot.restore', snapshotId: args.input.id }).pipe(\n\t\t\t\t\t\tEffect.as({ ok: true, detail: null as string | null }),\n\t\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\t\tEffect.succeed({ ok: false, detail: String(cause) as string | null }),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t}),\n\t\t/** Delete a snapshot by id (via the control-plane `domain`). */\n\t\tdeleteSnapshot: t.fieldWithInput({\n\t\t\ttype: SnapshotActionResult,\n\t\t\tinput: { id: t.input.string({ required: true }) },\n\t\t\tresolve: (_parent, args, ctx) => Effect.runPromise(ctx.domain.deleteSnapshot(args.input.id)),\n\t\t}),\n\t\t/** Mint a custom coin. Routes through the control-plane `domain`:\n\t\t * the supervisor holds the treasury-cap-owning publisher signer\n\t\t * in-process and returns a real ok/detail/digest result (the void\n\t\t * `publishCommand` could not carry the tx digest). `amountBaseUnits`\n\t\t * is the raw integer amount in the coin's smallest unit (string so\n\t\t * large u64 values survive the wire without precision loss). */\n\t\tmint: t.fieldWithInput({\n\t\t\ttype: MintResult,\n\t\t\tinput: {\n\t\t\t\tcoinType: t.input.string({ required: true }),\n\t\t\t\trecipient: t.input.string({ required: true }),\n\t\t\t\tamountBaseUnits: t.input.string({ required: true }),\n\t\t\t},\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\tEffect.runPromise(\n\t\t\t\t\tctx.pluginDomain.mintCoin({\n\t\t\t\t\t\tcoinType: args.input.coinType,\n\t\t\t\t\t\trecipient: args.input.recipient,\n\t\t\t\t\t\tamountBaseUnits: args.input.amountBaseUnits,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t\t/** Fund an account/address. Routes through the control-plane\n\t\t * `pluginDomain`, reusing devstack's in-process funding strategies:\n\t\t * SUI (absent / canonical `coinType`) via the chain faucet strategy\n\t\t * (fixed-amount — `amountBaseUnits` is ignored); WAL/DEEP via the\n\t\t * coin-specific account-signed swap (`amountBaseUnits` honored, and\n\t\t * the recipient must be a resolved account). Real result — `ok`\n\t\t * reflects whether the strategy completed. */\n\t\tfund: t.fieldWithInput({\n\t\t\ttype: FundResult,\n\t\t\tinput: {\n\t\t\t\trecipient: t.input.string({ required: true }),\n\t\t\t\tcoinType: t.input.string({ required: false }),\n\t\t\t\tamountBaseUnits: t.input.string({ required: false }),\n\t\t\t},\n\t\t\tresolve: (_parent, args, ctx) =>\n\t\t\t\tEffect.runPromise(\n\t\t\t\t\tctx.pluginDomain.fundAccount({\n\t\t\t\t\t\trecipient: args.input.recipient,\n\t\t\t\t\t\tcoinType: args.input.coinType,\n\t\t\t\t\t\tamountBaseUnits: args.input.amountBaseUnits,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t}),\n});\n\n// --- Subscription -------------------------------------------------------\nbuilder.subscriptionType({\n\tfields: (t) => ({\n\t\t/** Stream the projection on every change (current value first). */\n\t\tstate: t.field({\n\t\t\ttype: StackState,\n\t\t\tsubscribe: (_parent, _args, ctx) => subscribeState(ctx.state),\n\t\t\tresolve: (payload) => payload,\n\t\t}),\n\t}),\n});\n\n/** Bridge an Effect `SubscriptionRef` to an async iterable for GraphQL\n * subscriptions. `SubscriptionRef.changes` emits the current value first,\n * then each subsequent update. The pump fiber is interrupted when the\n * consumer (yoga) stops iterating.\n *\n * @yields {SubscribableState} the current subscribable state on each change */\nasync function* subscribeState(\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): AsyncGenerator<SubscribableState> {\n\tconst queue = Effect.runSync(Queue.unbounded<SubscribableState>());\n\tconst pump = Effect.runFork(\n\t\tStream.runForEach(SubscriptionRef.changes(ref), (snapshot) => Queue.offer(queue, snapshot)),\n\t);\n\ttry {\n\t\twhile (true) {\n\t\t\tyield await Effect.runPromise(Queue.take(queue));\n\t\t}\n\t} finally {\n\t\tEffect.runFork(Fiber.interrupt(pump));\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -287,8 +287,17 @@ const DeepbookPool = builder.objectRef("DeepbookPool").implement({
|
|
|
287
287
|
quoteCoinType: t.exposeString("quoteCoinType")
|
|
288
288
|
})
|
|
289
289
|
});
|
|
290
|
+
const PythPriceFeed = builder.objectRef("PythPriceFeed").implement({
|
|
291
|
+
description: "A Pyth price feed seeded inside DeepBook at boot. `price`/`expo` are FIXED boot-time mock values (static, not a live quote).",
|
|
292
|
+
fields: (t) => ({
|
|
293
|
+
symbol: t.exposeString("symbol"),
|
|
294
|
+
priceInfoObjectId: t.exposeString("priceInfoObjectId"),
|
|
295
|
+
price: t.exposeString("price"),
|
|
296
|
+
expo: t.exposeInt("expo")
|
|
297
|
+
})
|
|
298
|
+
});
|
|
290
299
|
const DeepbookInfo = builder.objectRef("DeepbookInfo").implement({
|
|
291
|
-
description: "A DeepBook deployment: registry/admin/pool ids +
|
|
300
|
+
description: "A DeepBook deployment: registry/admin/pool ids + seed-liquidity state + Pyth feeds.",
|
|
292
301
|
fields: (t) => ({
|
|
293
302
|
pluginKey: t.exposeString("pluginKey"),
|
|
294
303
|
name: t.exposeString("name"),
|
|
@@ -305,7 +314,11 @@ const DeepbookInfo = builder.objectRef("DeepbookInfo").implement({
|
|
|
305
314
|
type: [DeepbookPool],
|
|
306
315
|
resolve: (d) => d.pools
|
|
307
316
|
}),
|
|
308
|
-
|
|
317
|
+
pythFeeds: t.field({
|
|
318
|
+
type: [PythPriceFeed],
|
|
319
|
+
resolve: (d) => d.pythFeeds
|
|
320
|
+
}),
|
|
321
|
+
hasSeedLiquidity: t.exposeBoolean("hasSeedLiquidity"),
|
|
309
322
|
serverUrl: t.exposeString("serverUrl", { nullable: true }),
|
|
310
323
|
indexerUrl: t.exposeString("indexerUrl", { nullable: true }),
|
|
311
324
|
narrowingFault: t.exposeString("narrowingFault", { nullable: true })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","names":["HealthEnum"],"sources":["../../../../src/plugins/dashboard/schema/types.ts"],"sourcesContent":["// Dashboard object types — real Pothos object refs over the projection.\n//\n// Sources are the substrate projection shapes (Row, Endpoint,\n// AccountProjection, …). Service/Endpoint/Account/Package are registered\n// as relay Nodes via `builder.node`, with an opaque global id derived from\n// their natural key and a `loadOne` that re-finds them in the current\n// snapshot (read from the request's `ctx.state`) so the auto-generated\n// `node`/`nodes` queries resolve.\n//\n// `StackState` and `HealthSummary` are computed views over a snapshot —\n// `StackState` carries the snapshot itself as its source so nested\n// resolvers (e.g. Service.endpoints) can join against sibling arrays.\n\nimport { Effect, SubscriptionRef } from 'effect';\nimport { builder } from './builder.ts';\nimport {\n\tAccountScheme,\n\tAccountSource,\n\tDeepbookMode,\n\tErrorSeverity,\n\tFundingStatus,\n\tHealth as HealthEnum,\n\tLifecycleStatus,\n\tLogLevel,\n\tPackageKind,\n\tPluginRole,\n\tRowSection,\n\tWireProtocol,\n} from './enums.ts';\nimport type { Health } from './enums.ts';\nimport type { ControlPlaneSnapshotEntry } from '../../../substrate/runtime/control-plane/service.ts';\nimport type {\n\tDashboardCoinCap,\n\tDashboardDeepbookInfo,\n\tDashboardDeepbookPool,\n\tDashboardFundableCoin,\n\tDashboardSealInfo,\n\tDashboardSealKeyServer,\n} from '../domain.ts';\n// The surface-neutral health derivation lives in the TUI module\n// (`display-derivation.ts`) but is itself ink/react-free with type-only\n// substrate imports — so the web schema can reuse the SAME canonical\n// bucketing + named policies without acquiring any TUI/ink coupling.\nimport { deriveHealth, deriveStackViewModel } from '../../../surfaces/tui/display-derivation.ts';\nimport type { LogRecord } from '../../../substrate/runtime/observability/index.ts';\nimport type {\n\tAccountProjection,\n\tBuildEntry as BuildEntryShape,\n\tEndpoint as EndpointShape,\n\tLogTail as LogTailShape,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n} from '../../../substrate/projection.ts';\n\n/** A snapshot-carrying service row. The snapshot lets `endpoints` join the\n * row's endpoint keys against the projection's endpoint array. */\nexport interface ServiceSource {\n\treadonly row: Row;\n\treadonly snapshot: SubscribableState;\n}\n\ntype FundingEntrySource = NonNullable<AccountProjection['funding']['entries']>[number];\n\nexport interface HealthSummarySource {\n\treadonly total: number;\n\treadonly ready: number;\n\treadonly active: number;\n\treadonly failed: number;\n\treadonly waiting: number;\n\treadonly health: Health;\n}\n\n/** Compute the stack health summary from the projection rows. Delegates to\n * the surface-neutral `deriveStackViewModel` (the single canonical\n * bucketing) + `deriveHealth(counts, 'web')` (the named web policy), then\n * folds the ViewModel's discrete `stoppedRows` into this adapter's `ready`\n * field — preserving the web GraphQL stopped→ready contract. The fold lives\n * HERE, in the web adapter, not in the shared ViewModel, so the TUI policy\n * is unaffected. `active` counts rows mid-flight (acquiring/stopping);\n * `waiting` counts rows that have not started (pending). Overall `health`\n * is `failed`→blocked, any-active→active, all-(ready|stopped) (with ≥1\n * row)→ready, otherwise empty. */\nexport const computeHealthSummary = (rows: ReadonlyArray<Row>): HealthSummarySource => {\n\tconst vm = deriveStackViewModel({\n\t\trows,\n\t\tendpoints: [],\n\t\taccounts: [],\n\t\tpackages: [],\n\t\terrors: [],\n\t});\n\tconst health: Health = deriveHealth(vm, 'web');\n\treturn {\n\t\ttotal: vm.total,\n\t\t// Web GraphQL contract: `stopped` rows count toward `ready`.\n\t\tready: vm.readyRows + vm.stoppedRows,\n\t\tactive: vm.activeRows,\n\t\tfailed: vm.failedRows,\n\t\twaiting: vm.waitingRows,\n\t\thealth,\n\t};\n};\n\nconst readSnapshot = (\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): Promise<SubscribableState> => Effect.runPromise(SubscriptionRef.get(ref));\n\n// --- Identity / Cycle ---------------------------------------------------\nexport const Identity = builder.objectRef<SubscribableState['identity']>('Identity').implement({\n\tdescription: 'Stack identity triple (app/stack/network).',\n\tfields: (t) => ({\n\t\tapp: t.exposeString('app'),\n\t\tstack: t.exposeString('stack'),\n\t\tnetwork: t.exposeString('network'),\n\t}),\n});\n\nexport const Cycle = builder.objectRef<SubscribableState['cycle']>('Cycle').implement({\n\tdescription: 'The current boot/restart cycle.',\n\tfields: (t) => ({\n\t\tid: t.exposeInt('id'),\n\t\tstartedAt: t.exposeFloat('startedAt'),\n\t\t// Carried as String: the raw union ('booting'|…|'shutting-down') is the\n\t\t// wire contract, and 'shutting-down' is not a valid GraphQL enum name.\n\t\tphase: t.field({ type: 'String', resolve: (c) => c.phase }),\n\t}),\n});\n\n// --- Endpoint (Node) ----------------------------------------------------\nexport const Endpoint = builder.objectRef<EndpointShape>('Endpoint');\nbuilder.node(Endpoint, {\n\tdescription: 'A routed endpoint contributed by a plugin.',\n\tid: { resolve: (e) => e.endpointKey },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\treturn snapshot.endpoints.find((e) => e.endpointKey === id) ?? null;\n\t},\n\tfields: (t) => ({\n\t\tendpointKey: t.exposeString('endpointKey'),\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\tname: t.exposeString('name'),\n\t\turl: t.exposeString('url'),\n\t\tdisplayUrl: t.exposeString('displayUrl', { nullable: true }),\n\t\twireProtocol: t.field({ type: WireProtocol, resolve: (e) => e.wireProtocol }),\n\t\tregisteredAt: t.exposeFloat('registeredAt'),\n\t}),\n});\n\n// --- LogTail / StackError ----------------------------------------------\nexport const LogTail = builder.objectRef<LogTailShape>('LogTail').implement({\n\tdescription: 'The tail of a plugin log stream.',\n\tfields: (t) => ({\n\t\tlines: t.exposeStringList('lines'),\n\t\tlevel: t.field({ type: LogLevel, resolve: (l) => l.level }),\n\t\ttruncated: t.exposeBoolean('truncated'),\n\t}),\n});\n\nexport const StackError = builder.objectRef<StructuredError>('StackError').implement({\n\tdescription: 'A structured error reported by a plugin or the engine.',\n\tfields: (t) => ({\n\t\tat: t.exposeFloat('at'),\n\t\tpluginKey: t.exposeString('pluginKey', { nullable: true }),\n\t\ttag: t.exposeString('tag'),\n\t\tsummary: t.exposeString('summary'),\n\t\tchain: t.exposeStringList('chain'),\n\t\tseverity: t.field({ type: ErrorSeverity, resolve: (e) => e.severity }),\n\t}),\n});\n\n// --- Service (Node, wraps a Row) ---------------------------------------\nexport const Service = builder.objectRef<ServiceSource>('Service');\nbuilder.node(Service, {\n\tdescription: 'A visible plugin instance (one projection row).',\n\tid: { resolve: (s) => s.row.key },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\tconst row = snapshot.rows.find((r) => r.key === id);\n\t\treturn row ? { row, snapshot } : null;\n\t},\n\tfields: (t) => ({\n\t\tkey: t.string({ resolve: (s) => s.row.key }),\n\t\trole: t.field({ type: PluginRole, resolve: (s) => s.row.role }),\n\t\tstatus: t.field({ type: LifecycleStatus, resolve: (s) => s.row.status }),\n\t\tsection: t.field({ type: RowSection, resolve: (s) => s.row.section }),\n\t\tendpointSection: t.field({ type: RowSection, resolve: (s) => s.row.endpointSection }),\n\t\tphase: t.string({ nullable: true, resolve: (s) => s.row.phase }),\n\t\tselectiveRestartHighlight: t.boolean({\n\t\t\tresolve: (s) => s.row.selectiveRestartHighlight,\n\t\t}),\n\t\tlastError: t.field({\n\t\t\ttype: StackError,\n\t\t\tnullable: true,\n\t\t\tresolve: (s) => s.row.lastError,\n\t\t}),\n\t\tlogTail: t.field({ type: LogTail, resolve: (s) => s.row.logTail }),\n\t\tendpoints: t.field({\n\t\t\ttype: [Endpoint],\n\t\t\tdescription: \"The row's endpoints, joined from the snapshot by key + pluginKey.\",\n\t\t\tresolve: (s) => {\n\t\t\t\tconst keys = new Set<string>(s.row.endpoints);\n\t\t\t\treturn s.snapshot.endpoints.filter(\n\t\t\t\t\t(e) => keys.has(e.endpointKey) && e.pluginKey === s.row.key,\n\t\t\t\t);\n\t\t\t},\n\t\t}),\n\t}),\n});\n\n// --- Funding ------------------------------------------------------------\nexport const FundingEntry = builder.objectRef<FundingEntrySource>('FundingEntry').implement({\n\tdescription: 'One coin-type funding outcome for an account.',\n\tfields: (t) => ({\n\t\tcoin: t.exposeString('coin'),\n\t\tfullCoinType: t.exposeString('fullCoinType'),\n\t\tamount: t.exposeString('amount'),\n\t\t// String for the same reason as Cycle.phase: 'already-satisfied' is not\n\t\t// a valid GraphQL enum name; the raw union string is the wire contract.\n\t\tstatus: t.field({ type: 'String', resolve: (e) => e.status }),\n\t}),\n});\n\nexport const AccountFunding = builder\n\t.objectRef<AccountProjection['funding']>('AccountFunding')\n\t.implement({\n\t\tdescription: 'Funding state for an account.',\n\t\tfields: (t) => ({\n\t\t\tstatus: t.field({ type: FundingStatus, resolve: (f) => f.status }),\n\t\t\tbalanceMist: t.exposeString('balanceMist', { nullable: true }),\n\t\t\trequestedMist: t.exposeString('requestedMist', { nullable: true }),\n\t\t\tentries: t.field({\n\t\t\t\ttype: [FundingEntry],\n\t\t\t\tresolve: (f) => f.entries ?? [],\n\t\t\t}),\n\t\t}),\n\t});\n\n// --- Account (Node) -----------------------------------------------------\nexport const Account = builder.objectRef<AccountProjection>('Account');\nbuilder.node(Account, {\n\tdescription: 'A managed or impersonated account.',\n\tid: { resolve: (a) => a.key },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\treturn snapshot.accounts.find((a) => a.key === id) ?? null;\n\t},\n\tfields: (t) => ({\n\t\tkey: t.exposeString('key'),\n\t\trowKey: t.exposeString('rowKey', { nullable: true }),\n\t\tname: t.exposeString('name'),\n\t\taddress: t.exposeString('address', { nullable: true }),\n\t\tscheme: t.field({ type: AccountScheme, nullable: true, resolve: (a) => a.scheme }),\n\t\tsource: t.field({ type: AccountSource, nullable: true, resolve: (a) => a.source }),\n\t\twalletVisible: t.exposeBoolean('walletVisible'),\n\t\tupdatedAt: t.exposeFloat('updatedAt'),\n\t\tfunding: t.field({ type: AccountFunding, resolve: (a) => a.funding }),\n\t}),\n});\n\n// --- Package (Node) -----------------------------------------------------\nexport const Package = builder.objectRef<PackageProjection>('Package');\nbuilder.node(Package, {\n\tdescription: 'A local or known on-chain package.',\n\tid: { resolve: (p) => p.key },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\treturn snapshot.packages.find((p) => p.key === id) ?? null;\n\t},\n\tfields: (t) => ({\n\t\tkey: t.exposeString('key'),\n\t\trowKey: t.exposeString('rowKey', { nullable: true }),\n\t\tname: t.exposeString('name'),\n\t\tkind: t.field({ type: PackageKind, resolve: (p) => p.kind }),\n\t\tpackageId: t.exposeString('packageId'),\n\t\tupgradeCapId: t.exposeString('upgradeCapId', { nullable: true }),\n\t\tmvrPlaceholder: t.exposeString('mvrPlaceholder'),\n\t\tsourcePath: t.exposeString('sourcePath', { nullable: true }),\n\t\tupdatedAt: t.exposeFloat('updatedAt'),\n\t}),\n});\n\n// --- BuildEntry / LastEvent --------------------------------------------\nexport const BuildEntry = builder.objectRef<BuildEntryShape>('BuildEntry').implement({\n\tdescription: 'A stack build progress entry.',\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey', { nullable: true }),\n\t\tphase: t.exposeString('phase'),\n\t\tprogress: t.exposeString('progress'),\n\t\tstartedAt: t.exposeFloat('startedAt'),\n\t}),\n});\n\nexport const LastEvent = builder.objectRef<SubscribableState['lastEvent']>('LastEvent').implement({\n\tdescription: 'The most recent event seq/timestamp the engine emitted.',\n\tfields: (t) => ({\n\t\tseq: t.exposeInt('seq'),\n\t\tat: t.exposeFloat('at'),\n\t}),\n});\n\n// --- HealthSummary ------------------------------------------------------\nexport const HealthSummary = builder.objectRef<HealthSummarySource>('HealthSummary').implement({\n\tdescription: 'Derived stack health counts.',\n\tfields: (t) => ({\n\t\ttotal: t.exposeInt('total'),\n\t\tready: t.exposeInt('ready'),\n\t\tactive: t.exposeInt('active'),\n\t\tfailed: t.exposeInt('failed'),\n\t\twaiting: t.exposeInt('waiting'),\n\t\thealth: t.field({ type: HealthEnum, resolve: (h) => h.health }),\n\t}),\n});\n\n// --- Plugin-domain object types ----------------------------------------\n//\n// Sources are the app-agnostic `ControlPlane*` shapes the supervisor\n// populates from resolved plugin values. These cover only what the browser\n// cannot reach directly: codegen capability ids, in-process plugin state,\n// and the snapshot catalog. Numeric counts/sizes are carried as Float\n// (GraphQL Int caps at 2^31).\n\nexport const SnapshotEntry = builder\n\t.objectRef<ControlPlaneSnapshotEntry>('SnapshotEntry')\n\t.implement({\n\t\tdescription: 'A snapshot catalog entry (orchestrator `list`).',\n\t\tfields: (t) => ({\n\t\t\tid: t.exposeString('id'),\n\t\t\tlabel: t.exposeString('label', { nullable: true }),\n\t\t\tcreatedAt: t.exposeFloat('createdAt', { nullable: true }),\n\t\t\tapp: t.exposeString('app', { nullable: true }),\n\t\t\tstack: t.exposeString('stack', { nullable: true }),\n\t\t\tnetwork: t.exposeString('network', { nullable: true }),\n\t\t\tsnapshotGraphInputId: t.exposeString('snapshotGraphInputId', { nullable: true }),\n\t\t\tcurrentGraphInputId: t.exposeString('currentGraphInputId', { nullable: true }),\n\t\t\tgraphInputStatus: t.exposeString('graphInputStatus'),\n\t\t\tgraphInputWarning: t.exposeString('graphInputWarning', { nullable: true }),\n\t\t\tparticipants: t.exposeStringList('participants'),\n\t\t\tcontainerCount: t.exposeInt('containerCount'),\n\t\t\tsubtreeCount: t.exposeInt('subtreeCount'),\n\t\t\tcorrupt: t.exposeBoolean('corrupt'),\n\t\t}),\n\t});\n\nexport const DeepbookPool = builder.objectRef<DashboardDeepbookPool>('DeepbookPool').implement({\n\tdescription: 'A DeepBook pool object id + coin types (prices are chain-direct).',\n\tfields: (t) => ({\n\t\tname: t.exposeString('name'),\n\t\tpoolId: t.exposeString('poolId'),\n\t\tbaseCoinType: t.exposeString('baseCoinType'),\n\t\tquoteCoinType: t.exposeString('quoteCoinType'),\n\t}),\n});\n\nexport const DeepbookInfo = builder.objectRef<DashboardDeepbookInfo>('DeepbookInfo').implement({\n\tdescription: 'A DeepBook deployment: registry/admin/pool ids + market-maker state.',\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\tname: t.exposeString('name'),\n\t\tmode: t.field({ type: DeepbookMode, resolve: (d) => d.mode }),\n\t\tnetwork: t.exposeString('network'),\n\t\tpackageId: t.exposeString('packageId'),\n\t\tregistryId: t.exposeString('registryId'),\n\t\tadminCapId: t.exposeString('adminCapId', { nullable: true }),\n\t\tdeepTreasuryId: t.exposeString('deepTreasuryId', { nullable: true }),\n\t\tpools: t.field({ type: [DeepbookPool], resolve: (d) => d.pools }),\n\t\tmarketMakerRunning: t.exposeBoolean('marketMakerRunning'),\n\t\tserverUrl: t.exposeString('serverUrl', { nullable: true }),\n\t\tindexerUrl: t.exposeString('indexerUrl', { nullable: true }),\n\t\t// Fail-loud: non-null when a required field failed to narrow off the\n\t\t// opaque resolved value (schema drift surfaced, not silently degraded).\n\t\tnarrowingFault: t.exposeString('narrowingFault', { nullable: true }),\n\t}),\n});\n\nexport const SealKeyServer = builder.objectRef<DashboardSealKeyServer>('SealKeyServer').implement({\n\tdescription: 'One Seal key-server config (objectId + weight).',\n\tfields: (t) => ({\n\t\tobjectId: t.exposeString('objectId'),\n\t\tweight: t.exposeInt('weight'),\n\t}),\n});\n\nexport const SealInfo = builder.objectRef<DashboardSealInfo>('SealInfo').implement({\n\tdescription: 'A Seal key-server deployment (objectId/threshold/mode/keyServers).',\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\t// String, not enum: 'local-keygen'/'fork-known' are illegal GraphQL\n\t\t// enum value names (hyphens). The raw union string is the wire contract.\n\t\tmode: t.field({ type: 'String', resolve: (s) => s.mode }),\n\t\tobjectId: t.exposeString('objectId'),\n\t\tkeyServerUrl: t.exposeString('keyServerUrl'),\n\t\tkeyServers: t.field({ type: [SealKeyServer], resolve: (s) => s.keyServers }),\n\t\tthreshold: t.exposeInt('threshold'),\n\t\t// Fail-loud: non-null when a required field failed to narrow.\n\t\tnarrowingFault: t.exposeString('narrowingFault', { nullable: true }),\n\t}),\n});\n\nexport const CoinCap = builder.objectRef<DashboardCoinCap>('CoinCap').implement({\n\tdescription: \"A coin's treasury-cap id (drives Mint) + addressing facts.\",\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\tsymbol: t.exposeString('symbol', { nullable: true }),\n\t\tfullCoinType: t.exposeString('fullCoinType'),\n\t\tdecimals: t.exposeInt('decimals'),\n\t\t// String, not enum: 'on-chain' is an illegal GraphQL enum value name.\n\t\tsource: t.field({ type: 'String', resolve: (c) => c.source }),\n\t\ttreasuryCapId: t.exposeString('treasuryCapId', { nullable: true }),\n\t\tpackageId: t.exposeString('packageId', { nullable: true }),\n\t\t// Fail-loud: non-null when a required field failed to narrow.\n\t\tnarrowingFault: t.exposeString('narrowingFault', { nullable: true }),\n\t}),\n});\n\nexport const FundableCoin = builder.objectRef<DashboardFundableCoin>('FundableCoin').implement({\n\tdescription:\n\t\t'A coin the dashboard faucet can fund right now. SUI is fixed-amount; ' +\n\t\t'WAL/DEEP honor an amount and require the recipient to be a resolved account.',\n\tfields: (t) => ({\n\t\tsymbol: t.exposeString('symbol'),\n\t\tcoinType: t.exposeString('coinType'),\n\t\t/** True when the underlying strategy honors a caller-supplied amount\n\t\t * (WAL/DEEP swaps). SUI is fixed-amount (false). */\n\t\thonorsAmount: t.exposeBoolean('honorsAmount'),\n\t\t/** True when funding requires the recipient to BE a resolved account\n\t\t * (the swap spends that account's own SUI). SUI is false. */\n\t\trequiresAccountSigner: t.exposeBoolean('requiresAccountSigner'),\n\t}),\n});\n\n// --- Observability: LogRecord ------------------------------------------\n//\n// Source is the substrate observability log ring records. `level` is\n// carried as String, not a GraphQL enum: the log level vocabulary\n// (trace/debug/info/warn/error/fatal) is wider than the projection's\n// row-tail LogLevel enum, and keeping it String decouples the queryable\n// surface from the row-tail enum (same hyphen/illegal-enum-safe String\n// pattern used by SealMode/CoinSource above). Structured `fields` are\n// serialized to a JSON string — the schema has no JSON scalar and the\n// console renders them as a detail blob.\n\nconst fieldsJson = (fields: Readonly<Record<string, unknown>>): string => {\n\ttry {\n\t\treturn JSON.stringify(fields);\n\t} catch {\n\t\treturn '{}';\n\t}\n};\n\nexport const LogRecordType = builder.objectRef<LogRecord>('LogRecord').implement({\n\tdescription:\n\t\t'One cross-service log record (queryable Console \"Logs\" tab). Fed off the same logger path as the per-row projection tail.',\n\tfields: (t) => ({\n\t\tseq: t.exposeFloat('seq'),\n\t\ttimestampMillis: t.exposeFloat('timestampMillis'),\n\t\t// String: wider than the row-tail LogLevel enum (trace/debug/fatal).\n\t\tlevel: t.field({ type: 'String', resolve: (r) => r.level }),\n\t\tservice: t.exposeString('service'),\n\t\tmessage: t.exposeString('message'),\n\t\t/** Structured fields as a JSON string (no JSON scalar in this schema). */\n\t\tfieldsJson: t.field({ type: 'String', resolve: (r) => fieldsJson(r.fields) }),\n\t}),\n});\n\n// --- Observability filter inputs ---------------------------------------\n\nexport const LogFilterInput = builder.inputType('LogFilter', {\n\tfields: (t) => ({\n\t\tservices: t.stringList({ required: false }),\n\t\t/** Levels (trace/debug/info/warn/error/fatal). Strings, not an enum\n\t\t * (the level vocabulary is wider than the row-tail LogLevel enum). */\n\t\tlevels: t.stringList({ required: false }),\n\t\tsearch: t.string({ required: false }),\n\t\tsinceMillis: t.float({ required: false }),\n\t\tlimit: t.int({ required: false }),\n\t}),\n});\n\n// --- StackState (source = the snapshot itself) -------------------------\nexport const StackState = builder.objectRef<SubscribableState>('StackState').implement({\n\tdescription: 'A full live projection snapshot.',\n\tfields: (t) => ({\n\t\tidentity: t.field({ type: Identity, resolve: (s) => s.identity }),\n\t\tcycle: t.field({ type: Cycle, resolve: (s) => s.cycle }),\n\t\tsummary: t.field({ type: HealthSummary, resolve: (s) => computeHealthSummary(s.rows) }),\n\t\tservices: t.field({\n\t\t\ttype: [Service],\n\t\t\tresolve: (s) => s.rows.map((row) => ({ row, snapshot: s })),\n\t\t}),\n\t\tendpoints: t.field({ type: [Endpoint], resolve: (s) => s.endpoints }),\n\t\taccounts: t.field({ type: [Account], resolve: (s) => s.accounts }),\n\t\tpackages: t.field({ type: [Package], resolve: (s) => s.packages }),\n\t\terrors: t.field({ type: [StackError], resolve: (s) => s.errors }),\n\t\tstackBuild: t.field({ type: [BuildEntry], resolve: (s) => s.stackBuild }),\n\t\tlastEvent: t.field({ type: LastEvent, nullable: true, resolve: (s) => s.lastEvent }),\n\t}),\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.mjs","names":["HealthEnum"],"sources":["../../../../src/plugins/dashboard/schema/types.ts"],"sourcesContent":["// Dashboard object types — real Pothos object refs over the projection.\n//\n// Sources are the substrate projection shapes (Row, Endpoint,\n// AccountProjection, …). Service/Endpoint/Account/Package are registered\n// as relay Nodes via `builder.node`, with an opaque global id derived from\n// their natural key and a `loadOne` that re-finds them in the current\n// snapshot (read from the request's `ctx.state`) so the auto-generated\n// `node`/`nodes` queries resolve.\n//\n// `StackState` and `HealthSummary` are computed views over a snapshot —\n// `StackState` carries the snapshot itself as its source so nested\n// resolvers (e.g. Service.endpoints) can join against sibling arrays.\n\nimport { Effect, SubscriptionRef } from 'effect';\nimport { builder } from './builder.ts';\nimport {\n\tAccountScheme,\n\tAccountSource,\n\tDeepbookMode,\n\tErrorSeverity,\n\tFundingStatus,\n\tHealth as HealthEnum,\n\tLifecycleStatus,\n\tLogLevel,\n\tPackageKind,\n\tPluginRole,\n\tRowSection,\n\tWireProtocol,\n} from './enums.ts';\nimport type { Health } from './enums.ts';\nimport type { ControlPlaneSnapshotEntry } from '../../../substrate/runtime/control-plane/service.ts';\nimport type {\n\tDashboardCoinCap,\n\tDashboardDeepbookInfo,\n\tDashboardDeepbookPool,\n\tDashboardFundableCoin,\n\tDashboardPythFeed,\n\tDashboardSealInfo,\n\tDashboardSealKeyServer,\n} from '../domain.ts';\n// The surface-neutral health derivation lives in the TUI module\n// (`display-derivation.ts`) but is itself ink/react-free with type-only\n// substrate imports — so the web schema can reuse the SAME canonical\n// bucketing + named policies without acquiring any TUI/ink coupling.\nimport { deriveHealth, deriveStackViewModel } from '../../../surfaces/tui/display-derivation.ts';\nimport type { LogRecord } from '../../../substrate/runtime/observability/index.ts';\nimport type {\n\tAccountProjection,\n\tBuildEntry as BuildEntryShape,\n\tEndpoint as EndpointShape,\n\tLogTail as LogTailShape,\n\tPackageProjection,\n\tRow,\n\tStructuredError,\n\tSubscribableState,\n} from '../../../substrate/projection.ts';\n\n/** A snapshot-carrying service row. The snapshot lets `endpoints` join the\n * row's endpoint keys against the projection's endpoint array. */\nexport interface ServiceSource {\n\treadonly row: Row;\n\treadonly snapshot: SubscribableState;\n}\n\ntype FundingEntrySource = NonNullable<AccountProjection['funding']['entries']>[number];\n\nexport interface HealthSummarySource {\n\treadonly total: number;\n\treadonly ready: number;\n\treadonly active: number;\n\treadonly failed: number;\n\treadonly waiting: number;\n\treadonly health: Health;\n}\n\n/** Compute the stack health summary from the projection rows. Delegates to\n * the surface-neutral `deriveStackViewModel` (the single canonical\n * bucketing) + `deriveHealth(counts, 'web')` (the named web policy), then\n * folds the ViewModel's discrete `stoppedRows` into this adapter's `ready`\n * field — preserving the web GraphQL stopped→ready contract. The fold lives\n * HERE, in the web adapter, not in the shared ViewModel, so the TUI policy\n * is unaffected. `active` counts rows mid-flight (acquiring/stopping);\n * `waiting` counts rows that have not started (pending). Overall `health`\n * is `failed`→blocked, any-active→active, all-(ready|stopped) (with ≥1\n * row)→ready, otherwise empty. */\nexport const computeHealthSummary = (rows: ReadonlyArray<Row>): HealthSummarySource => {\n\tconst vm = deriveStackViewModel({\n\t\trows,\n\t\tendpoints: [],\n\t\taccounts: [],\n\t\tpackages: [],\n\t\terrors: [],\n\t});\n\tconst health: Health = deriveHealth(vm, 'web');\n\treturn {\n\t\ttotal: vm.total,\n\t\t// Web GraphQL contract: `stopped` rows count toward `ready`.\n\t\tready: vm.readyRows + vm.stoppedRows,\n\t\tactive: vm.activeRows,\n\t\tfailed: vm.failedRows,\n\t\twaiting: vm.waitingRows,\n\t\thealth,\n\t};\n};\n\nconst readSnapshot = (\n\tref: SubscriptionRef.SubscriptionRef<SubscribableState>,\n): Promise<SubscribableState> => Effect.runPromise(SubscriptionRef.get(ref));\n\n// --- Identity / Cycle ---------------------------------------------------\nexport const Identity = builder.objectRef<SubscribableState['identity']>('Identity').implement({\n\tdescription: 'Stack identity triple (app/stack/network).',\n\tfields: (t) => ({\n\t\tapp: t.exposeString('app'),\n\t\tstack: t.exposeString('stack'),\n\t\tnetwork: t.exposeString('network'),\n\t}),\n});\n\nexport const Cycle = builder.objectRef<SubscribableState['cycle']>('Cycle').implement({\n\tdescription: 'The current boot/restart cycle.',\n\tfields: (t) => ({\n\t\tid: t.exposeInt('id'),\n\t\tstartedAt: t.exposeFloat('startedAt'),\n\t\t// Carried as String: the raw union ('booting'|…|'shutting-down') is the\n\t\t// wire contract, and 'shutting-down' is not a valid GraphQL enum name.\n\t\tphase: t.field({ type: 'String', resolve: (c) => c.phase }),\n\t}),\n});\n\n// --- Endpoint (Node) ----------------------------------------------------\nexport const Endpoint = builder.objectRef<EndpointShape>('Endpoint');\nbuilder.node(Endpoint, {\n\tdescription: 'A routed endpoint contributed by a plugin.',\n\tid: { resolve: (e) => e.endpointKey },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\treturn snapshot.endpoints.find((e) => e.endpointKey === id) ?? null;\n\t},\n\tfields: (t) => ({\n\t\tendpointKey: t.exposeString('endpointKey'),\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\tname: t.exposeString('name'),\n\t\turl: t.exposeString('url'),\n\t\tdisplayUrl: t.exposeString('displayUrl', { nullable: true }),\n\t\twireProtocol: t.field({ type: WireProtocol, resolve: (e) => e.wireProtocol }),\n\t\tregisteredAt: t.exposeFloat('registeredAt'),\n\t}),\n});\n\n// --- LogTail / StackError ----------------------------------------------\nexport const LogTail = builder.objectRef<LogTailShape>('LogTail').implement({\n\tdescription: 'The tail of a plugin log stream.',\n\tfields: (t) => ({\n\t\tlines: t.exposeStringList('lines'),\n\t\tlevel: t.field({ type: LogLevel, resolve: (l) => l.level }),\n\t\ttruncated: t.exposeBoolean('truncated'),\n\t}),\n});\n\nexport const StackError = builder.objectRef<StructuredError>('StackError').implement({\n\tdescription: 'A structured error reported by a plugin or the engine.',\n\tfields: (t) => ({\n\t\tat: t.exposeFloat('at'),\n\t\tpluginKey: t.exposeString('pluginKey', { nullable: true }),\n\t\ttag: t.exposeString('tag'),\n\t\tsummary: t.exposeString('summary'),\n\t\tchain: t.exposeStringList('chain'),\n\t\tseverity: t.field({ type: ErrorSeverity, resolve: (e) => e.severity }),\n\t}),\n});\n\n// --- Service (Node, wraps a Row) ---------------------------------------\nexport const Service = builder.objectRef<ServiceSource>('Service');\nbuilder.node(Service, {\n\tdescription: 'A visible plugin instance (one projection row).',\n\tid: { resolve: (s) => s.row.key },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\tconst row = snapshot.rows.find((r) => r.key === id);\n\t\treturn row ? { row, snapshot } : null;\n\t},\n\tfields: (t) => ({\n\t\tkey: t.string({ resolve: (s) => s.row.key }),\n\t\trole: t.field({ type: PluginRole, resolve: (s) => s.row.role }),\n\t\tstatus: t.field({ type: LifecycleStatus, resolve: (s) => s.row.status }),\n\t\tsection: t.field({ type: RowSection, resolve: (s) => s.row.section }),\n\t\tendpointSection: t.field({ type: RowSection, resolve: (s) => s.row.endpointSection }),\n\t\tphase: t.string({ nullable: true, resolve: (s) => s.row.phase }),\n\t\tselectiveRestartHighlight: t.boolean({\n\t\t\tresolve: (s) => s.row.selectiveRestartHighlight,\n\t\t}),\n\t\tlastError: t.field({\n\t\t\ttype: StackError,\n\t\t\tnullable: true,\n\t\t\tresolve: (s) => s.row.lastError,\n\t\t}),\n\t\tlogTail: t.field({ type: LogTail, resolve: (s) => s.row.logTail }),\n\t\tendpoints: t.field({\n\t\t\ttype: [Endpoint],\n\t\t\tdescription: \"The row's endpoints, joined from the snapshot by key + pluginKey.\",\n\t\t\tresolve: (s) => {\n\t\t\t\tconst keys = new Set<string>(s.row.endpoints);\n\t\t\t\treturn s.snapshot.endpoints.filter(\n\t\t\t\t\t(e) => keys.has(e.endpointKey) && e.pluginKey === s.row.key,\n\t\t\t\t);\n\t\t\t},\n\t\t}),\n\t}),\n});\n\n// --- Funding ------------------------------------------------------------\nexport const FundingEntry = builder.objectRef<FundingEntrySource>('FundingEntry').implement({\n\tdescription: 'One coin-type funding outcome for an account.',\n\tfields: (t) => ({\n\t\tcoin: t.exposeString('coin'),\n\t\tfullCoinType: t.exposeString('fullCoinType'),\n\t\tamount: t.exposeString('amount'),\n\t\t// String for the same reason as Cycle.phase: 'already-satisfied' is not\n\t\t// a valid GraphQL enum name; the raw union string is the wire contract.\n\t\tstatus: t.field({ type: 'String', resolve: (e) => e.status }),\n\t}),\n});\n\nexport const AccountFunding = builder\n\t.objectRef<AccountProjection['funding']>('AccountFunding')\n\t.implement({\n\t\tdescription: 'Funding state for an account.',\n\t\tfields: (t) => ({\n\t\t\tstatus: t.field({ type: FundingStatus, resolve: (f) => f.status }),\n\t\t\tbalanceMist: t.exposeString('balanceMist', { nullable: true }),\n\t\t\trequestedMist: t.exposeString('requestedMist', { nullable: true }),\n\t\t\tentries: t.field({\n\t\t\t\ttype: [FundingEntry],\n\t\t\t\tresolve: (f) => f.entries ?? [],\n\t\t\t}),\n\t\t}),\n\t});\n\n// --- Account (Node) -----------------------------------------------------\nexport const Account = builder.objectRef<AccountProjection>('Account');\nbuilder.node(Account, {\n\tdescription: 'A managed or impersonated account.',\n\tid: { resolve: (a) => a.key },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\treturn snapshot.accounts.find((a) => a.key === id) ?? null;\n\t},\n\tfields: (t) => ({\n\t\tkey: t.exposeString('key'),\n\t\trowKey: t.exposeString('rowKey', { nullable: true }),\n\t\tname: t.exposeString('name'),\n\t\taddress: t.exposeString('address', { nullable: true }),\n\t\tscheme: t.field({ type: AccountScheme, nullable: true, resolve: (a) => a.scheme }),\n\t\tsource: t.field({ type: AccountSource, nullable: true, resolve: (a) => a.source }),\n\t\twalletVisible: t.exposeBoolean('walletVisible'),\n\t\tupdatedAt: t.exposeFloat('updatedAt'),\n\t\tfunding: t.field({ type: AccountFunding, resolve: (a) => a.funding }),\n\t}),\n});\n\n// --- Package (Node) -----------------------------------------------------\nexport const Package = builder.objectRef<PackageProjection>('Package');\nbuilder.node(Package, {\n\tdescription: 'A local or known on-chain package.',\n\tid: { resolve: (p) => p.key },\n\tloadOne: async (id, ctx) => {\n\t\tconst snapshot = await readSnapshot(ctx.state);\n\t\treturn snapshot.packages.find((p) => p.key === id) ?? null;\n\t},\n\tfields: (t) => ({\n\t\tkey: t.exposeString('key'),\n\t\trowKey: t.exposeString('rowKey', { nullable: true }),\n\t\tname: t.exposeString('name'),\n\t\tkind: t.field({ type: PackageKind, resolve: (p) => p.kind }),\n\t\tpackageId: t.exposeString('packageId'),\n\t\tupgradeCapId: t.exposeString('upgradeCapId', { nullable: true }),\n\t\tmvrPlaceholder: t.exposeString('mvrPlaceholder'),\n\t\tsourcePath: t.exposeString('sourcePath', { nullable: true }),\n\t\tupdatedAt: t.exposeFloat('updatedAt'),\n\t}),\n});\n\n// --- BuildEntry / LastEvent --------------------------------------------\nexport const BuildEntry = builder.objectRef<BuildEntryShape>('BuildEntry').implement({\n\tdescription: 'A stack build progress entry.',\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey', { nullable: true }),\n\t\tphase: t.exposeString('phase'),\n\t\tprogress: t.exposeString('progress'),\n\t\tstartedAt: t.exposeFloat('startedAt'),\n\t}),\n});\n\nexport const LastEvent = builder.objectRef<SubscribableState['lastEvent']>('LastEvent').implement({\n\tdescription: 'The most recent event seq/timestamp the engine emitted.',\n\tfields: (t) => ({\n\t\tseq: t.exposeInt('seq'),\n\t\tat: t.exposeFloat('at'),\n\t}),\n});\n\n// --- HealthSummary ------------------------------------------------------\nexport const HealthSummary = builder.objectRef<HealthSummarySource>('HealthSummary').implement({\n\tdescription: 'Derived stack health counts.',\n\tfields: (t) => ({\n\t\ttotal: t.exposeInt('total'),\n\t\tready: t.exposeInt('ready'),\n\t\tactive: t.exposeInt('active'),\n\t\tfailed: t.exposeInt('failed'),\n\t\twaiting: t.exposeInt('waiting'),\n\t\thealth: t.field({ type: HealthEnum, resolve: (h) => h.health }),\n\t}),\n});\n\n// --- Plugin-domain object types ----------------------------------------\n//\n// Sources are the app-agnostic `ControlPlane*` shapes the supervisor\n// populates from resolved plugin values. These cover only what the browser\n// cannot reach directly: codegen capability ids, in-process plugin state,\n// and the snapshot catalog. Numeric counts/sizes are carried as Float\n// (GraphQL Int caps at 2^31).\n\nexport const SnapshotEntry = builder\n\t.objectRef<ControlPlaneSnapshotEntry>('SnapshotEntry')\n\t.implement({\n\t\tdescription: 'A snapshot catalog entry (orchestrator `list`).',\n\t\tfields: (t) => ({\n\t\t\tid: t.exposeString('id'),\n\t\t\tlabel: t.exposeString('label', { nullable: true }),\n\t\t\tcreatedAt: t.exposeFloat('createdAt', { nullable: true }),\n\t\t\tapp: t.exposeString('app', { nullable: true }),\n\t\t\tstack: t.exposeString('stack', { nullable: true }),\n\t\t\tnetwork: t.exposeString('network', { nullable: true }),\n\t\t\tsnapshotGraphInputId: t.exposeString('snapshotGraphInputId', { nullable: true }),\n\t\t\tcurrentGraphInputId: t.exposeString('currentGraphInputId', { nullable: true }),\n\t\t\tgraphInputStatus: t.exposeString('graphInputStatus'),\n\t\t\tgraphInputWarning: t.exposeString('graphInputWarning', { nullable: true }),\n\t\t\tparticipants: t.exposeStringList('participants'),\n\t\t\tcontainerCount: t.exposeInt('containerCount'),\n\t\t\tsubtreeCount: t.exposeInt('subtreeCount'),\n\t\t\tcorrupt: t.exposeBoolean('corrupt'),\n\t\t}),\n\t});\n\nexport const DeepbookPool = builder.objectRef<DashboardDeepbookPool>('DeepbookPool').implement({\n\tdescription: 'A DeepBook pool object id + coin types (prices are chain-direct).',\n\tfields: (t) => ({\n\t\tname: t.exposeString('name'),\n\t\tpoolId: t.exposeString('poolId'),\n\t\tbaseCoinType: t.exposeString('baseCoinType'),\n\t\tquoteCoinType: t.exposeString('quoteCoinType'),\n\t}),\n});\n\nexport const PythPriceFeed = builder.objectRef<DashboardPythFeed>('PythPriceFeed').implement({\n\tdescription:\n\t\t'A Pyth price feed seeded inside DeepBook at boot. `price`/`expo` are FIXED ' +\n\t\t'boot-time mock values (static, not a live quote).',\n\tfields: (t) => ({\n\t\tsymbol: t.exposeString('symbol'),\n\t\tpriceInfoObjectId: t.exposeString('priceInfoObjectId'),\n\t\t// String (not Int/Float): the boot-time mock price is a signed integer in\n\t\t// feed-native scale carried as a string to survive the wire intact.\n\t\tprice: t.exposeString('price'),\n\t\texpo: t.exposeInt('expo'),\n\t}),\n});\n\nexport const DeepbookInfo = builder.objectRef<DashboardDeepbookInfo>('DeepbookInfo').implement({\n\tdescription:\n\t\t'A DeepBook deployment: registry/admin/pool ids + seed-liquidity state + Pyth feeds.',\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\tname: t.exposeString('name'),\n\t\tmode: t.field({ type: DeepbookMode, resolve: (d) => d.mode }),\n\t\tnetwork: t.exposeString('network'),\n\t\tpackageId: t.exposeString('packageId'),\n\t\tregistryId: t.exposeString('registryId'),\n\t\tadminCapId: t.exposeString('adminCapId', { nullable: true }),\n\t\tdeepTreasuryId: t.exposeString('deepTreasuryId', { nullable: true }),\n\t\tpools: t.field({ type: [DeepbookPool], resolve: (d) => d.pools }),\n\t\t// Pyth price feeds seeded inside this DeepBook deployment (boot-time mocks).\n\t\tpythFeeds: t.field({ type: [PythPriceFeed], resolve: (d) => d.pythFeeds }),\n\t\t// `true` when one or more pools placed seed orders at boot (NOT a running\n\t\t// market-maker process).\n\t\thasSeedLiquidity: t.exposeBoolean('hasSeedLiquidity'),\n\t\tserverUrl: t.exposeString('serverUrl', { nullable: true }),\n\t\tindexerUrl: t.exposeString('indexerUrl', { nullable: true }),\n\t\t// Fail-loud: non-null when a required field failed to narrow off the\n\t\t// opaque resolved value (schema drift surfaced, not silently degraded).\n\t\tnarrowingFault: t.exposeString('narrowingFault', { nullable: true }),\n\t}),\n});\n\nexport const SealKeyServer = builder.objectRef<DashboardSealKeyServer>('SealKeyServer').implement({\n\tdescription: 'One Seal key-server config (objectId + weight).',\n\tfields: (t) => ({\n\t\tobjectId: t.exposeString('objectId'),\n\t\tweight: t.exposeInt('weight'),\n\t}),\n});\n\nexport const SealInfo = builder.objectRef<DashboardSealInfo>('SealInfo').implement({\n\tdescription: 'A Seal key-server deployment (objectId/threshold/mode/keyServers).',\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\t// String, not enum: 'local-keygen'/'fork-known' are illegal GraphQL\n\t\t// enum value names (hyphens). The raw union string is the wire contract.\n\t\tmode: t.field({ type: 'String', resolve: (s) => s.mode }),\n\t\tobjectId: t.exposeString('objectId'),\n\t\tkeyServerUrl: t.exposeString('keyServerUrl'),\n\t\tkeyServers: t.field({ type: [SealKeyServer], resolve: (s) => s.keyServers }),\n\t\tthreshold: t.exposeInt('threshold'),\n\t\t// Fail-loud: non-null when a required field failed to narrow.\n\t\tnarrowingFault: t.exposeString('narrowingFault', { nullable: true }),\n\t}),\n});\n\nexport const CoinCap = builder.objectRef<DashboardCoinCap>('CoinCap').implement({\n\tdescription: \"A coin's treasury-cap id (drives Mint) + addressing facts.\",\n\tfields: (t) => ({\n\t\tpluginKey: t.exposeString('pluginKey'),\n\t\tsymbol: t.exposeString('symbol', { nullable: true }),\n\t\tfullCoinType: t.exposeString('fullCoinType'),\n\t\tdecimals: t.exposeInt('decimals'),\n\t\t// String, not enum: 'on-chain' is an illegal GraphQL enum value name.\n\t\tsource: t.field({ type: 'String', resolve: (c) => c.source }),\n\t\ttreasuryCapId: t.exposeString('treasuryCapId', { nullable: true }),\n\t\tpackageId: t.exposeString('packageId', { nullable: true }),\n\t\t// Fail-loud: non-null when a required field failed to narrow.\n\t\tnarrowingFault: t.exposeString('narrowingFault', { nullable: true }),\n\t}),\n});\n\nexport const FundableCoin = builder.objectRef<DashboardFundableCoin>('FundableCoin').implement({\n\tdescription:\n\t\t'A coin the dashboard faucet can fund right now. SUI is fixed-amount; ' +\n\t\t'WAL/DEEP honor an amount and require the recipient to be a resolved account.',\n\tfields: (t) => ({\n\t\tsymbol: t.exposeString('symbol'),\n\t\tcoinType: t.exposeString('coinType'),\n\t\t/** True when the underlying strategy honors a caller-supplied amount\n\t\t * (WAL/DEEP swaps). SUI is fixed-amount (false). */\n\t\thonorsAmount: t.exposeBoolean('honorsAmount'),\n\t\t/** True when funding requires the recipient to BE a resolved account\n\t\t * (the swap spends that account's own SUI). SUI is false. */\n\t\trequiresAccountSigner: t.exposeBoolean('requiresAccountSigner'),\n\t}),\n});\n\n// --- Observability: LogRecord ------------------------------------------\n//\n// Source is the substrate observability log ring records. `level` is\n// carried as String, not a GraphQL enum: the log level vocabulary\n// (trace/debug/info/warn/error/fatal) is wider than the projection's\n// row-tail LogLevel enum, and keeping it String decouples the queryable\n// surface from the row-tail enum (same hyphen/illegal-enum-safe String\n// pattern used by SealMode/CoinSource above). Structured `fields` are\n// serialized to a JSON string — the schema has no JSON scalar and the\n// console renders them as a detail blob.\n\nconst fieldsJson = (fields: Readonly<Record<string, unknown>>): string => {\n\ttry {\n\t\treturn JSON.stringify(fields);\n\t} catch {\n\t\treturn '{}';\n\t}\n};\n\nexport const LogRecordType = builder.objectRef<LogRecord>('LogRecord').implement({\n\tdescription:\n\t\t'One cross-service log record (queryable Console \"Logs\" tab). Fed off the same logger path as the per-row projection tail.',\n\tfields: (t) => ({\n\t\tseq: t.exposeFloat('seq'),\n\t\ttimestampMillis: t.exposeFloat('timestampMillis'),\n\t\t// String: wider than the row-tail LogLevel enum (trace/debug/fatal).\n\t\tlevel: t.field({ type: 'String', resolve: (r) => r.level }),\n\t\tservice: t.exposeString('service'),\n\t\tmessage: t.exposeString('message'),\n\t\t/** Structured fields as a JSON string (no JSON scalar in this schema). */\n\t\tfieldsJson: t.field({ type: 'String', resolve: (r) => fieldsJson(r.fields) }),\n\t}),\n});\n\n// --- Observability filter inputs ---------------------------------------\n\nexport const LogFilterInput = builder.inputType('LogFilter', {\n\tfields: (t) => ({\n\t\tservices: t.stringList({ required: false }),\n\t\t/** Levels (trace/debug/info/warn/error/fatal). Strings, not an enum\n\t\t * (the level vocabulary is wider than the row-tail LogLevel enum). */\n\t\tlevels: t.stringList({ required: false }),\n\t\tsearch: t.string({ required: false }),\n\t\tsinceMillis: t.float({ required: false }),\n\t\tlimit: t.int({ required: false }),\n\t}),\n});\n\n// --- StackState (source = the snapshot itself) -------------------------\nexport const StackState = builder.objectRef<SubscribableState>('StackState').implement({\n\tdescription: 'A full live projection snapshot.',\n\tfields: (t) => ({\n\t\tidentity: t.field({ type: Identity, resolve: (s) => s.identity }),\n\t\tcycle: t.field({ type: Cycle, resolve: (s) => s.cycle }),\n\t\tsummary: t.field({ type: HealthSummary, resolve: (s) => computeHealthSummary(s.rows) }),\n\t\tservices: t.field({\n\t\t\ttype: [Service],\n\t\t\tresolve: (s) => s.rows.map((row) => ({ row, snapshot: s })),\n\t\t}),\n\t\tendpoints: t.field({ type: [Endpoint], resolve: (s) => s.endpoints }),\n\t\taccounts: t.field({ type: [Account], resolve: (s) => s.accounts }),\n\t\tpackages: t.field({ type: [Package], resolve: (s) => s.packages }),\n\t\terrors: t.field({ type: [StackError], resolve: (s) => s.errors }),\n\t\tstackBuild: t.field({ type: [BuildEntry], resolve: (s) => s.stackBuild }),\n\t\tlastEvent: t.field({ type: LastEvent, nullable: true, resolve: (s) => s.lastEvent }),\n\t}),\n});\n"],"mappings":"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"}
|