@mysten-incubation/devstack 0.1.0 → 0.2.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 +7 -4
- package/dashboard-ui/assets/grpc-a4usE3Nk.js +3 -0
- package/dashboard-ui/assets/index-B82Bh84P.css +1 -0
- package/dashboard-ui/assets/index-CRYJ4pru.js +1277 -0
- package/dashboard-ui/index.html +2 -2
- package/dist/api/define-capabilities.d.mts +1 -20
- package/dist/api/define-capabilities.mjs +15 -22
- package/dist/api/define-capabilities.mjs.map +1 -1
- package/dist/api/define-devstack-with.d.mts +7 -1
- package/dist/api/define-devstack-with.mjs.map +1 -1
- package/dist/api/define-devstack.mjs.map +1 -1
- package/dist/api/define-plugin.d.mts +2 -1
- package/dist/api/inference-network.d.mts +31 -17
- package/dist/api/inference-network.mjs +40 -43
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/load-config.mjs +88 -0
- package/dist/api/load-config.mjs.map +1 -0
- package/dist/api/mode-narrowed-factory.d.mts +1 -1
- package/dist/api/mode-narrowed-factory.mjs.map +1 -1
- package/dist/api/run-stack-internal.mjs +202 -0
- package/dist/api/run-stack-internal.mjs.map +1 -0
- package/dist/api/run-stack.d.mts +82 -31
- package/dist/api/run-stack.mjs +22 -141
- package/dist/api/run-stack.mjs.map +1 -1
- package/dist/build-integrations/dapp-kit/index.d.mts +61 -0
- package/dist/build-integrations/dapp-kit/index.mjs +58 -0
- package/dist/build-integrations/dapp-kit/index.mjs.map +1 -0
- package/dist/build-integrations/playwright/config.d.mts +1 -30
- package/dist/build-integrations/playwright/config.mjs +1 -27
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +4 -7
- package/dist/build-integrations/playwright/errors.mjs.map +1 -1
- package/dist/build-integrations/playwright/global-setup.d.mts +42 -71
- package/dist/build-integrations/playwright/global-setup.mjs +142 -218
- package/dist/build-integrations/playwright/global-setup.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/stack-context.d.mts +3 -1
- package/dist/build-integrations/playwright/stack-context.mjs +4 -2
- package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
- package/dist/build-integrations/playwright/wallet-context.mjs +44 -19
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
- package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -1
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -1
- package/dist/build-integrations/runtime/discover.d.mts +6 -4
- package/dist/build-integrations/runtime/discover.mjs +15 -4
- package/dist/build-integrations/runtime/discover.mjs.map +1 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
- package/dist/build-integrations/runtime/errors.mjs.map +1 -1
- package/dist/build-integrations/runtime/read-stack-context.mjs +3 -3
- package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +23 -7
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs +25 -12
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -1
- package/dist/build-integrations/runtime/stack-context.d.mts +2 -2
- package/dist/build-integrations/vite/index.d.mts +84 -19
- package/dist/build-integrations/vite/index.mjs +203 -28
- package/dist/build-integrations/vite/index.mjs.map +1 -1
- package/dist/build-integrations/vitest/config.d.mts +20 -2
- package/dist/build-integrations/vitest/config.mjs +16 -4
- package/dist/build-integrations/vitest/config.mjs.map +1 -1
- package/dist/build-integrations/vitest/env.d.mts +18 -10
- package/dist/build-integrations/vitest/env.mjs +11 -10
- package/dist/build-integrations/vitest/env.mjs.map +1 -1
- package/dist/build-integrations/vitest/errors.d.mts +7 -11
- package/dist/build-integrations/vitest/errors.mjs +3 -4
- package/dist/build-integrations/vitest/errors.mjs.map +1 -1
- package/dist/build-integrations/vitest/global-setup.d.mts +35 -0
- package/dist/build-integrations/vitest/global-setup.mjs +156 -0
- package/dist/build-integrations/vitest/global-setup.mjs.map +1 -0
- package/dist/build-integrations/vitest/index.d.mts +3 -2
- package/dist/build-integrations/vitest/index.mjs +3 -2
- package/dist/build-integrations/vitest/setup.mjs +2 -2
- package/dist/build-integrations/vitest/setup.mjs.map +1 -1
- package/dist/build-integrations/vitest/stack-context.d.mts +5 -3
- package/dist/build-integrations/vitest/stack-context.mjs +3 -2
- package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
- package/dist/cli/bail.mjs.map +1 -1
- package/dist/cli/doctor-probes.mjs +1 -3
- package/dist/cli/doctor-probes.mjs.map +1 -1
- package/dist/cli/main.d.mts +23 -1
- package/dist/cli/main.mjs +63 -8
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/prune-direct.mjs.map +1 -1
- package/dist/cli/snapshot-reader.mjs.map +1 -1
- package/dist/cli/up-lifecycle.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +28 -21
- package/dist/cli/wirings/apply.mjs.map +1 -1
- package/dist/cli/wirings/codegen.mjs +108 -0
- package/dist/cli/wirings/codegen.mjs.map +1 -0
- package/dist/cli/wirings/config-loader.mjs +12 -62
- package/dist/cli/wirings/config-loader.mjs.map +1 -1
- package/dist/cli/wirings/dump-ids.mjs +86 -0
- package/dist/cli/wirings/dump-ids.mjs.map +1 -0
- package/dist/cli/wirings/engine-command.mjs +1 -1
- package/dist/cli/wirings/engine-command.mjs.map +1 -1
- package/dist/cli/wirings/identity.mjs +2 -2
- package/dist/cli/wirings/identity.mjs.map +1 -1
- package/dist/cli/wirings/provide-file-system.mjs.map +1 -1
- package/dist/cli/wirings/read-devstack-version.mjs +17 -0
- package/dist/cli/wirings/read-devstack-version.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +27 -34
- package/dist/cli/wirings/snapshot.mjs.map +1 -1
- package/dist/cli/wirings/up-ipc.mjs +147 -0
- package/dist/cli/wirings/up-ipc.mjs.map +1 -0
- package/dist/cli/wirings/up.mjs +218 -198
- package/dist/cli/wirings/up.mjs.map +1 -1
- package/dist/cli/wirings/wipe.mjs +1 -1
- package/dist/cli/wirings/wipe.mjs.map +1 -1
- package/dist/contracts/chain-probe.d.mts +1 -1
- package/dist/contracts/chain-probe.mjs +1 -1
- package/dist/contracts/chain-probe.mjs.map +1 -1
- package/dist/contracts/codegenable.d.mts +60 -6
- package/dist/contracts/codegenable.mjs +28 -0
- package/dist/contracts/codegenable.mjs.map +1 -0
- package/dist/contracts/config-bindings.mjs +162 -0
- package/dist/contracts/config-bindings.mjs.map +1 -0
- package/dist/contracts/container-runtime.d.mts +23 -17
- package/dist/contracts/plugin-expander.mjs.map +1 -1
- package/dist/contracts/snapshotable.d.mts +5 -7
- package/dist/contracts/wallet-protocol.d.mts +2 -5
- package/dist/contracts/wallet-protocol.mjs +2 -5
- package/dist/contracts/wallet-protocol.mjs.map +1 -1
- package/dist/index.d.mts +21 -26
- package/dist/index.mjs +8 -9
- package/dist/orchestrators/boot.d.mts +28 -0
- package/dist/orchestrators/boot.mjs +440 -0
- package/dist/orchestrators/boot.mjs.map +1 -0
- package/dist/orchestrators/codegen/bindings.d.mts +13 -1
- package/dist/orchestrators/codegen/bindings.mjs +23 -9
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/config-runtime.mjs +208 -0
- package/dist/orchestrators/codegen/config-runtime.mjs.map +1 -0
- package/dist/orchestrators/codegen/emit.mjs +1 -1
- package/dist/orchestrators/codegen/emit.mjs.map +1 -1
- package/dist/orchestrators/codegen/errors.mjs +21 -1
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +2 -0
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/gitignore.mjs +30 -11
- package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
- package/dist/orchestrators/codegen/id-config.mjs +107 -0
- package/dist/orchestrators/codegen/id-config.mjs.map +1 -0
- package/dist/orchestrators/codegen/output-location.mjs +23 -31
- package/dist/orchestrators/codegen/output-location.mjs.map +1 -1
- package/dist/orchestrators/codegen/paths.mjs +8 -1
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +286 -58
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/layers.mjs +31 -0
- package/dist/orchestrators/layers.mjs.map +1 -0
- package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -1
- package/dist/orchestrators/lifecycle-prune/index.mjs +8 -10
- package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -1
- package/dist/orchestrators/network-options.d.mts +52 -0
- package/dist/orchestrators/network-options.mjs +43 -0
- package/dist/orchestrators/network-options.mjs.map +1 -0
- package/dist/orchestrators/router/cleanup.mjs.map +1 -1
- package/dist/orchestrators/router/cors.mjs.map +1 -1
- package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
- package/dist/orchestrators/router/errors.mjs.map +1 -1
- package/dist/orchestrators/router/file-provider.mjs.map +1 -1
- package/dist/orchestrators/router/hostname.mjs.map +1 -1
- package/dist/orchestrators/router/profile.mjs +1 -1
- package/dist/orchestrators/router/profile.mjs.map +1 -1
- package/dist/orchestrators/router/service.d.mts +2 -2
- package/dist/orchestrators/router/service.mjs +12 -27
- package/dist/orchestrators/router/service.mjs.map +1 -1
- package/dist/orchestrators/router/traefik-container.mjs +1 -1
- package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
- package/dist/orchestrators/snapshot/capture.mjs +171 -195
- package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
- package/dist/orchestrators/snapshot/descriptor.d.mts +1 -1
- package/dist/orchestrators/snapshot/descriptor.mjs +53 -11
- package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
- package/dist/orchestrators/snapshot/identity-guard.mjs +3 -5
- package/dist/orchestrators/snapshot/identity-guard.mjs.map +1 -1
- package/dist/orchestrators/snapshot/image-bundle-tags.mjs +32 -101
- package/dist/orchestrators/snapshot/image-bundle-tags.mjs.map +1 -1
- package/dist/orchestrators/snapshot/index.mjs +1 -4
- package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
- package/dist/orchestrators/snapshot/interrupted-restore.mjs +116 -0
- package/dist/orchestrators/snapshot/interrupted-restore.mjs.map +1 -0
- package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -1
- package/dist/orchestrators/snapshot/prune.mjs +40 -31
- package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
- package/dist/orchestrators/snapshot/restore.mjs +221 -196
- package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
- package/dist/orchestrators/snapshot/service.mjs +72 -62
- package/dist/orchestrators/snapshot/service.mjs.map +1 -1
- package/dist/orchestrators/snapshot/wipe.mjs +67 -56
- package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
- package/dist/plugins/account/codegen.mjs +3 -0
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/errors.d.mts +2 -2
- package/dist/plugins/account/errors.mjs +1 -4
- package/dist/plugins/account/errors.mjs.map +1 -1
- package/dist/plugins/account/funding.mjs +3 -27
- package/dist/plugins/account/funding.mjs.map +1 -1
- package/dist/plugins/account/index.d.mts +3 -8
- package/dist/plugins/account/index.mjs +71 -35
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/account/keypair.d.mts +8 -7
- package/dist/plugins/account/keypair.mjs +5 -18
- package/dist/plugins/account/keypair.mjs.map +1 -1
- package/dist/plugins/account/lease.mjs.map +1 -1
- package/dist/plugins/account/registry.d.mts +1 -46
- package/dist/plugins/account/registry.mjs.map +1 -1
- package/dist/plugins/account/service.d.mts +43 -34
- package/dist/plugins/account/service.mjs +9 -54
- package/dist/plugins/account/service.mjs.map +1 -1
- package/dist/plugins/account/snapshot.mjs.map +1 -1
- package/dist/plugins/account/variants/ephemeral.mjs.map +1 -1
- package/dist/plugins/account/variants/impersonate.mjs.map +1 -1
- package/dist/plugins/account/variants/signer.mjs.map +1 -1
- package/dist/plugins/action/discriminator.mjs.map +1 -1
- package/dist/plugins/action/errors.mjs +1 -4
- package/dist/plugins/action/errors.mjs.map +1 -1
- package/dist/plugins/action/execute.mjs +3 -4
- package/dist/plugins/action/execute.mjs.map +1 -1
- package/dist/plugins/action/index.d.mts +2 -2
- package/dist/plugins/action/index.mjs +7 -11
- package/dist/plugins/action/index.mjs.map +1 -1
- package/dist/plugins/action/service.d.mts +5 -7
- package/dist/plugins/action/service.mjs +2 -16
- package/dist/plugins/action/service.mjs.map +1 -1
- package/dist/plugins/coin/address-resolution.mjs.map +1 -1
- package/dist/plugins/coin/codegen.mjs +97 -16
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/discovery.mjs.map +1 -1
- package/dist/plugins/coin/errors.mjs +1 -4
- package/dist/plugins/coin/errors.mjs.map +1 -1
- package/dist/plugins/coin/index.d.mts +4 -34
- package/dist/plugins/coin/index.mjs +47 -28
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/coin/metadata.d.mts +1 -0
- package/dist/plugins/coin/metadata.mjs +8 -9
- package/dist/plugins/coin/metadata.mjs.map +1 -1
- package/dist/plugins/coin/mint.mjs +7 -21
- package/dist/plugins/coin/mint.mjs.map +1 -1
- package/dist/plugins/coin/registry.mjs +33 -20
- package/dist/plugins/coin/registry.mjs.map +1 -1
- package/dist/plugins/coin/service.d.mts +1 -1
- package/dist/plugins/coin/service.mjs +1 -8
- package/dist/plugins/coin/service.mjs.map +1 -1
- package/dist/plugins/coin/snapshot.mjs.map +1 -1
- package/dist/plugins/coin/type-strings.mjs.map +1 -1
- package/dist/plugins/dashboard/domain.mjs +106 -167
- package/dist/plugins/dashboard/domain.mjs.map +1 -1
- package/dist/plugins/dashboard/index.mjs +13 -13
- package/dist/plugins/dashboard/index.mjs.map +1 -1
- package/dist/plugins/dashboard/origin-policy.mjs +3 -3
- package/dist/plugins/dashboard/origin-policy.mjs.map +1 -1
- package/dist/plugins/dashboard/routable.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/builder.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/enums.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/root.mjs +23 -44
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/types.mjs +37 -91
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -1
- package/dist/plugins/dashboard/schema.mjs.map +1 -1
- package/dist/plugins/dashboard/server.mjs.map +1 -1
- package/dist/plugins/deepbook/codegen.d.mts +12 -11
- package/dist/plugins/deepbook/codegen.mjs +108 -11
- package/dist/plugins/deepbook/codegen.mjs.map +1 -1
- package/dist/plugins/deepbook/deploy.mjs +7 -14
- package/dist/plugins/deepbook/deploy.mjs.map +1 -1
- package/dist/plugins/deepbook/errors.mjs +4 -2
- package/dist/plugins/deepbook/errors.mjs.map +1 -1
- package/dist/plugins/deepbook/faucet-strategy.mjs +4 -10
- package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/deepbook/hash.mjs.map +1 -1
- package/dist/plugins/deepbook/index.d.mts +38 -34
- package/dist/plugins/deepbook/index.mjs +133 -64
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/deepbook/plugin-key.mjs.map +1 -1
- package/dist/plugins/deepbook/pyth/index.mjs +4 -8
- package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
- package/dist/plugins/deepbook/snapshot.mjs +0 -1
- package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
- package/dist/plugins/deepbook/type-strings.mjs.map +1 -1
- package/dist/plugins/deepbook/types.d.mts +2 -1
- package/dist/plugins/deepbook/types.mjs.map +1 -1
- package/dist/plugins/faucet/dispatcher.d.mts +3 -3
- package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
- package/dist/plugins/faucet/errors.mjs.map +1 -1
- package/dist/plugins/faucet/http.mjs +2 -10
- package/dist/plugins/faucet/http.mjs.map +1 -1
- package/dist/plugins/faucet/index.mjs +0 -1
- package/dist/plugins/faucet/index.mjs.map +1 -1
- package/dist/plugins/host-service/errors.d.mts +1 -3
- package/dist/plugins/host-service/errors.mjs +1 -2
- package/dist/plugins/host-service/errors.mjs.map +1 -1
- package/dist/plugins/host-service/index.d.mts +1 -2
- package/dist/plugins/host-service/index.mjs +11 -11
- package/dist/plugins/host-service/index.mjs.map +1 -1
- package/dist/plugins/host-service/routable.mjs.map +1 -1
- package/dist/plugins/host-service/service.mjs +13 -13
- package/dist/plugins/host-service/service.mjs.map +1 -1
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -1
- package/dist/plugins/internal/codegen-helpers.mjs +2 -0
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -1
- package/dist/plugins/internal/funding-failure-error.mjs.map +1 -1
- package/dist/plugins/{postgres → internal/postgres-sidecar}/connection.mjs +1 -1
- package/dist/plugins/internal/postgres-sidecar/connection.mjs.map +1 -0
- package/dist/plugins/{postgres → internal/postgres-sidecar}/db-ensure.mjs +30 -16
- package/dist/plugins/internal/postgres-sidecar/db-ensure.mjs.map +1 -0
- package/dist/plugins/internal/postgres-sidecar/errors.mjs +21 -0
- package/dist/plugins/internal/postgres-sidecar/errors.mjs.map +1 -0
- package/dist/{substrate/runtime/scoped-multimap → plugins/internal/postgres-sidecar}/index.mjs +1 -0
- package/dist/plugins/internal/postgres-sidecar/service.mjs +121 -0
- package/dist/plugins/internal/postgres-sidecar/service.mjs.map +1 -0
- package/dist/plugins/package/build.mjs +2 -2
- package/dist/plugins/package/build.mjs.map +1 -1
- package/dist/plugins/package/codegen.d.mts +7 -14
- package/dist/plugins/package/codegen.mjs +187 -59
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/dep-resolution.mjs +51 -3
- package/dist/plugins/package/dep-resolution.mjs.map +1 -1
- package/dist/plugins/package/errors.mjs +1 -4
- package/dist/plugins/package/errors.mjs.map +1 -1
- package/dist/plugins/package/git-source.d.mts +18 -0
- package/dist/plugins/package/git-source.mjs +119 -0
- package/dist/plugins/package/git-source.mjs.map +1 -0
- package/dist/plugins/package/index.d.mts +28 -19
- package/dist/plugins/package/index.mjs +107 -32
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/package/mode-known.mjs +2 -2
- package/dist/plugins/package/mode-known.mjs.map +1 -1
- package/dist/plugins/package/mode-local.mjs +18 -35
- package/dist/plugins/package/mode-local.mjs.map +1 -1
- package/dist/plugins/package/publish-executor.mjs +13 -8
- package/dist/plugins/package/publish-executor.mjs.map +1 -1
- package/dist/plugins/package/publish-output.d.mts +1 -11
- package/dist/plugins/package/publish-output.mjs +1 -9
- package/dist/plugins/package/publish-output.mjs.map +1 -1
- package/dist/plugins/package/registry.d.mts +1 -1
- package/dist/plugins/package/registry.mjs +26 -14
- package/dist/plugins/package/registry.mjs.map +1 -1
- package/dist/plugins/package/service.mjs.map +1 -1
- package/dist/plugins/package/snapshot.mjs.map +1 -1
- package/dist/plugins/router-entrypoints.mjs +1 -3
- package/dist/plugins/router-entrypoints.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +1 -2
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +1 -6
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
- package/dist/plugins/seal/codegen.d.mts +1 -5
- package/dist/plugins/seal/codegen.mjs +83 -12
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/config-render.mjs +2 -6
- package/dist/plugins/seal/config-render.mjs.map +1 -1
- package/dist/plugins/seal/deploy.mjs +18 -29
- package/dist/plugins/seal/deploy.mjs.map +1 -1
- package/dist/plugins/seal/errors.d.mts +4 -5
- package/dist/plugins/seal/errors.mjs +1 -8
- package/dist/plugins/seal/errors.mjs.map +1 -1
- package/dist/plugins/seal/index.d.mts +7 -28
- package/dist/plugins/seal/index.mjs +69 -47
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/seal/key-manager.mjs.map +1 -1
- package/dist/plugins/seal/key-server.mjs +1 -6
- package/dist/plugins/seal/key-server.mjs.map +1 -1
- package/dist/plugins/seal/keygen.mjs +2 -3
- package/dist/plugins/seal/keygen.mjs.map +1 -1
- package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
- package/dist/plugins/seal/mode/live.mjs +1 -1
- package/dist/plugins/seal/mode/live.mjs.map +1 -1
- package/dist/plugins/seal/mode/local-keygen.mjs +4 -10
- package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
- package/dist/plugins/seal/plugin-key.mjs.map +1 -1
- package/dist/plugins/seal/registry-publish.mjs.map +1 -1
- package/dist/plugins/seal/routable.mjs.map +1 -1
- package/dist/plugins/seal/service.mjs.map +1 -1
- package/dist/plugins/seal/snapshot.mjs +1 -2
- package/dist/plugins/seal/snapshot.mjs.map +1 -1
- package/dist/plugins/sui/auto-tick.mjs +5 -5
- package/dist/plugins/sui/auto-tick.mjs.map +1 -1
- package/dist/plugins/sui/chain-build-container.mjs +2 -2
- package/dist/plugins/sui/chain-build-container.mjs.map +1 -1
- package/dist/plugins/sui/chain-probe.mjs +4 -4
- package/dist/plugins/sui/chain-probe.mjs.map +1 -1
- package/dist/plugins/sui/codegen.d.mts +9 -7
- package/dist/plugins/sui/codegen.mjs +49 -46
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/errors.d.mts +1 -1
- package/dist/plugins/sui/errors.mjs +1 -9
- package/dist/plugins/sui/errors.mjs.map +1 -1
- package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/index.d.mts +1 -1
- package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/index.mjs +3 -7
- package/dist/plugins/sui/exec/index.mjs.map +1 -0
- package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/sign-and-dispatch.mjs +1 -1
- package/dist/plugins/sui/exec/sign-and-dispatch.mjs.map +1 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs +2 -6
- package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -1
- package/dist/plugins/sui/fork-orchestration.mjs +13 -23
- package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
- package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +34 -83
- package/dist/plugins/sui/index.mjs +200 -68
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/{substrate/runtime/sui-ledger → plugins/sui/ledger}/object-ref.mjs +1 -1
- package/dist/plugins/sui/ledger/object-ref.mjs.map +1 -0
- package/dist/plugins/sui/local-faucet-strategy.mjs +1 -5
- package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -1
- package/dist/plugins/sui/log-attrs.mjs +11 -0
- package/dist/plugins/sui/log-attrs.mjs.map +1 -0
- package/dist/plugins/sui/mode/external.mjs +4 -12
- package/dist/plugins/sui/mode/external.mjs.map +1 -1
- package/dist/plugins/sui/mode/fork.mjs +19 -16
- package/dist/plugins/sui/mode/fork.mjs.map +1 -1
- package/dist/plugins/sui/mode/live.mjs +4 -17
- package/dist/plugins/sui/mode/live.mjs.map +1 -1
- package/dist/plugins/sui/mode/local.d.mts +1 -0
- package/dist/plugins/sui/mode/local.mjs +203 -61
- package/dist/plugins/sui/mode/local.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared-boot.mjs +18 -23
- package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared.d.mts +6 -7
- package/dist/plugins/sui/mode/shared.mjs.map +1 -1
- package/dist/plugins/sui/mode/spec.d.mts +23 -6
- package/dist/{substrate/runtime/sui-move-build → plugins/sui/move}/index.mjs +28 -30
- package/dist/plugins/sui/move/index.mjs.map +1 -0
- package/dist/plugins/sui/move-summary-runner.mjs +8 -4
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -1
- package/dist/{substrate/network.d.mts → plugins/sui/network-config.d.mts} +11 -10
- package/dist/plugins/sui/network-resolver.d.mts +6 -6
- package/dist/plugins/sui/routable.mjs.map +1 -1
- package/dist/plugins/sui/service.mjs +10 -6
- package/dist/plugins/sui/service.mjs.map +1 -1
- package/dist/plugins/sui/snapshot.mjs +10 -5
- package/dist/plugins/sui/snapshot.mjs.map +1 -1
- package/dist/plugins/wallet/codegen.d.mts +8 -6
- package/dist/plugins/wallet/codegen.mjs +4 -10
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/errors.mjs +1 -4
- package/dist/plugins/wallet/errors.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +3 -6
- package/dist/plugins/wallet/index.mjs +16 -21
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/origin-policy.mjs +3 -3
- package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
- package/dist/plugins/wallet/pairing.mjs +6 -24
- package/dist/plugins/wallet/pairing.mjs.map +1 -1
- package/dist/plugins/wallet/protocol.mjs.map +1 -1
- package/dist/plugins/wallet/routable.mjs.map +1 -1
- package/dist/plugins/wallet/server.mjs +17 -24
- package/dist/plugins/wallet/server.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +2 -2
- package/dist/plugins/wallet/service.mjs +4 -15
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/wallet/snapshot.mjs.map +1 -1
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +1 -5
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.d.mts +2 -13
- package/dist/plugins/walrus/codegen.mjs +93 -28
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/deploy-paths.mjs +2 -3
- package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
- package/dist/plugins/walrus/deploy.mjs +26 -19
- package/dist/plugins/walrus/deploy.mjs.map +1 -1
- package/dist/plugins/walrus/errors.mjs +1 -8
- package/dist/plugins/walrus/errors.mjs.map +1 -1
- package/dist/plugins/walrus/faucet-strategy.mjs +15 -1
- package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/walrus/index.d.mts +13 -44
- package/dist/plugins/walrus/index.mjs +119 -122
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/plugins/walrus/mode/known-deploy.mjs +6 -6
- package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
- package/dist/plugins/walrus/mode/local-cluster.d.mts +2 -2
- package/dist/plugins/walrus/mode/local-cluster.mjs +2 -10
- package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
- package/dist/plugins/walrus/plugin-key.mjs.map +1 -1
- package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
- package/dist/plugins/walrus/routable.mjs.map +1 -1
- package/dist/plugins/walrus/service.mjs.map +1 -1
- package/dist/plugins/walrus/snapshot.mjs +3 -3
- package/dist/plugins/walrus/snapshot.mjs.map +1 -1
- package/dist/plugins/walrus/storage-nodes.mjs +53 -14
- package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
- package/dist/plugins/walrus/wal-swap.mjs +4 -8
- package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
- package/dist/primitives/artifact-publisher.mjs.map +1 -1
- package/dist/primitives/cache.d.mts +1 -1
- package/dist/runtime/docker/client.mjs +47 -3
- package/dist/runtime/docker/client.mjs.map +1 -1
- package/dist/runtime/docker/container.mjs +37 -57
- package/dist/runtime/docker/container.mjs.map +1 -1
- package/dist/runtime/docker/errors.mjs.map +1 -1
- package/dist/runtime/docker/exec.mjs +2 -2
- package/dist/runtime/docker/exec.mjs.map +1 -1
- package/dist/runtime/docker/image.mjs +10 -11
- package/dist/runtime/docker/image.mjs.map +1 -1
- package/dist/runtime/docker/index.mjs +0 -1
- package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -1
- package/dist/runtime/docker/inventory.mjs +9 -9
- package/dist/runtime/docker/inventory.mjs.map +1 -1
- package/dist/runtime/docker/labels.mjs +12 -1
- package/dist/runtime/docker/labels.mjs.map +1 -1
- package/dist/runtime/docker/network.mjs +6 -6
- package/dist/runtime/docker/network.mjs.map +1 -1
- package/dist/runtime/docker/render-run-args.mjs.map +1 -1
- package/dist/runtime/docker/service.mjs +31 -45
- package/dist/runtime/docker/service.mjs.map +1 -1
- package/dist/runtime/docker/sweep.mjs +14 -64
- package/dist/runtime/docker/sweep.mjs.map +1 -1
- package/dist/runtime/docker/volume.mjs +1 -1
- package/dist/runtime/docker/volume.mjs.map +1 -1
- package/dist/runtime/docker/wrap.mjs +14 -2
- package/dist/runtime/docker/wrap.mjs.map +1 -1
- package/dist/substrate/brand.d.mts +2 -5
- package/dist/substrate/brand.mjs +3 -2
- package/dist/substrate/brand.mjs.map +1 -1
- package/dist/substrate/cross-process.mjs +2 -16
- package/dist/substrate/cross-process.mjs.map +1 -1
- package/dist/substrate/event-time.mjs +0 -2
- package/dist/substrate/event-time.mjs.map +1 -1
- package/dist/substrate/events.d.mts +46 -16
- package/dist/substrate/identity.d.mts +11 -5
- package/dist/substrate/manifest.d.mts +33 -26
- package/dist/substrate/manifest.mjs +8 -3
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/options.d.mts +33 -4
- package/dist/substrate/plugin-ctx.d.mts +70 -0
- package/dist/substrate/plugin-ctx.mjs +66 -0
- package/dist/substrate/plugin-ctx.mjs.map +1 -0
- package/dist/substrate/plugin.d.mts +46 -38
- package/dist/substrate/plugin.mjs +13 -9
- package/dist/substrate/plugin.mjs.map +1 -1
- package/dist/substrate/projection.d.mts +1 -1
- package/dist/substrate/runtime/atomic-write.mjs +3 -4
- package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
- package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
- package/dist/substrate/runtime/cache/service.mjs +50 -20
- package/dist/substrate/runtime/cache/service.mjs.map +1 -1
- package/dist/substrate/runtime/config-validation.mjs.map +1 -1
- package/dist/substrate/runtime/control-plane/domain.mjs +34 -12
- package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -1
- package/dist/substrate/runtime/control-plane/service.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +14 -17
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/index.mjs +0 -2
- package/dist/substrate/runtime/cross-process/live-clock.mjs +1 -1
- package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/liveness.mjs +11 -18
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +2 -2
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/roster.mjs +17 -127
- package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/stack-lock.mjs +29 -28
- package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
- package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
- package/dist/substrate/runtime/errors.mjs +1 -13
- package/dist/substrate/runtime/errors.mjs.map +1 -1
- package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -1
- package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -1
- package/dist/substrate/runtime/host-gateway.mjs.map +1 -1
- package/dist/substrate/runtime/host-tree-tar/index.mjs +15 -163
- package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
- package/dist/substrate/runtime/http-probe.d.mts +1 -3
- package/dist/substrate/runtime/http-probe.mjs.map +1 -1
- package/dist/substrate/runtime/index.mjs +1 -6
- package/dist/substrate/runtime/lease-broker/service.mjs +5 -23
- package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs +3 -3
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/graph-input-id.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/graph-input-id.mjs +133 -0
- package/dist/substrate/runtime/lifecycle/graph-input-id.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/index.mjs +2 -2
- package/dist/substrate/runtime/lifecycle/plugin-registry.d.mts +1 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +22 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/ready-gate.mjs +2 -15
- package/dist/substrate/runtime/lifecycle/ready-gate.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs +29 -25
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/state-machine.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/watch-attribution.d.mts +1 -1
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs +0 -1
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs.map +1 -1
- package/dist/substrate/runtime/managed-container.d.mts +5 -1
- package/dist/substrate/runtime/managed-container.mjs +8 -10
- package/dist/substrate/runtime/managed-container.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/manifest.mjs +8 -30
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/mode-errors.d.mts +1 -2
- package/dist/substrate/runtime/mode-errors.mjs.map +1 -1
- package/dist/substrate/runtime/observability/cascade-formatter.mjs +1 -11
- package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
- package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -1
- package/dist/substrate/runtime/observability/index.d.mts +1 -1
- package/dist/substrate/runtime/observability/index.mjs +4 -6
- package/dist/substrate/runtime/observability/log-attrs.mjs +46 -0
- package/dist/substrate/runtime/observability/log-attrs.mjs.map +1 -0
- package/dist/substrate/runtime/observability/log-store.mjs.map +1 -1
- package/dist/substrate/runtime/observability/logger.mjs +3 -3
- package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
- package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -1
- package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
- package/dist/substrate/runtime/observability/process-lines.mjs.map +1 -1
- package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
- package/dist/substrate/runtime/observability/subprocess-capture.mjs +2 -2
- package/dist/substrate/runtime/observability/subprocess-capture.mjs.map +1 -1
- package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -1
- package/dist/substrate/runtime/paths.mjs +27 -9
- package/dist/substrate/runtime/paths.mjs.map +1 -1
- package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -1
- package/dist/substrate/runtime/port-broker/service.mjs +10 -27
- package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/probes.d.mts +2 -3
- package/dist/substrate/runtime/probes.mjs.map +1 -1
- package/dist/substrate/runtime/process-supervisor.mjs.map +1 -1
- package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
- package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
- package/dist/substrate/runtime/projection/update.mjs +87 -11
- package/dist/substrate/runtime/projection/update.mjs.map +1 -1
- package/dist/substrate/runtime/random-suffix.mjs.map +1 -1
- package/dist/substrate/runtime/reconcile/fs-plan.mjs +146 -0
- package/dist/substrate/runtime/reconcile/fs-plan.mjs.map +1 -0
- package/dist/substrate/runtime/reconcile/graph.mjs +19 -0
- package/dist/substrate/runtime/reconcile/graph.mjs.map +1 -0
- package/dist/substrate/runtime/reconcile/index.mjs +5 -0
- package/dist/substrate/runtime/reconcile/label.mjs +41 -0
- package/dist/substrate/runtime/reconcile/label.mjs.map +1 -0
- package/dist/substrate/runtime/reconcile/spec.mjs +15 -0
- package/dist/substrate/runtime/reconcile/spec.mjs.map +1 -0
- package/dist/substrate/runtime/retry-policy.d.mts +2 -3
- package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
- package/dist/substrate/runtime/routed-url.mjs.map +1 -1
- package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
- package/dist/substrate/runtime/stage-and-swap/index.mjs +49 -12
- package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/service.mjs +29 -17
- package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
- package/dist/substrate/runtime/subnet-broker.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/acquire-node.mjs +188 -56
- package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/background-tasks.mjs +79 -65
- package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/command-loop.mjs +82 -23
- package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/contribution-dispatcher.mjs +16 -0
- package/dist/substrate/runtime/supervisor/contribution-dispatcher.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/errors.mjs +11 -2
- package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/index.mjs +2 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs +6 -6
- package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +60 -70
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/state.d.mts +1 -1
- package/dist/substrate/runtime/supervisor/state.mjs +1 -1
- package/dist/substrate/runtime/supervisor/state.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/teardown.mjs +10 -9
- package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/wiring.mjs +6 -20
- package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -1
- package/dist/substrate/runtime/tar/reader.mjs +216 -0
- package/dist/substrate/runtime/tar/reader.mjs.map +1 -0
- package/dist/substrate/runtime/typed-env.mjs.map +1 -1
- package/dist/substrate/versioned-doc-schema.mjs.map +1 -1
- package/dist/substrate/versioned-doc-sync.mjs +5 -5
- package/dist/substrate/versioned-doc-sync.mjs.map +1 -1
- package/dist/surfaces/cli/command-tree.mjs +49 -7
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/commands/config.mjs +1 -1
- package/dist/surfaces/cli/commands/config.mjs.map +1 -1
- package/dist/surfaces/cli/commands/confirm-node.mjs.map +1 -1
- package/dist/surfaces/cli/commands/confirm.mjs.map +1 -1
- package/dist/surfaces/cli/commands/doctor.mjs +1 -1
- package/dist/surfaces/cli/commands/doctor.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune.mjs +1 -1
- package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
- package/dist/surfaces/cli/commands/snapshot.mjs +1 -1
- package/dist/surfaces/cli/commands/snapshot.mjs.map +1 -1
- package/dist/surfaces/cli/commands/status.mjs +1 -1
- package/dist/surfaces/cli/commands/status.mjs.map +1 -1
- package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
- package/dist/surfaces/cli/commands/wipe.mjs +3 -4
- package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
- package/dist/surfaces/cli/envelope.mjs.map +1 -1
- package/dist/surfaces/cli/errors.mjs.map +1 -1
- package/dist/surfaces/cli/flags.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +45 -14
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/cli/output.mjs.map +1 -1
- package/dist/surfaces/cli/sysexits.mjs.map +1 -1
- package/dist/surfaces/tui/app.mjs +0 -21
- package/dist/surfaces/tui/app.mjs.map +1 -1
- package/dist/surfaces/tui/dashboard.mjs +0 -48
- package/dist/surfaces/tui/dashboard.mjs.map +1 -1
- package/dist/surfaces/tui/display-derivation.mjs +80 -16
- package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
- package/dist/surfaces/tui/errors.mjs.map +1 -1
- package/dist/surfaces/tui/event-log.mjs +0 -9
- package/dist/surfaces/tui/event-log.mjs.map +1 -1
- package/dist/surfaces/tui/heartbeat.mjs.map +1 -1
- package/dist/surfaces/tui/index.mjs +2 -2
- package/dist/surfaces/tui/index.mjs.map +1 -1
- package/dist/surfaces/tui/input.mjs.map +1 -1
- package/dist/surfaces/tui/mode-detect.mjs.map +1 -1
- package/dist/surfaces/tui/mount-ink.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs +26 -19
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/dist/surfaces/tui/resource-table.mjs +8 -10
- package/dist/surfaces/tui/resource-table.mjs.map +1 -1
- package/images/postgres/Dockerfile +0 -1
- package/images/sui/Dockerfile +27 -54
- package/images/sui/entrypoint.sh +17 -179
- package/package.json +23 -15
- package/dashboard-ui/assets/index-Bmi1UtAg.js +0 -1356
- package/dashboard-ui/assets/index-D5EShVt4.js +0 -3
- package/dashboard-ui/assets/index-Deml9drg.css +0 -1
- package/dist/api/plugin-errors.d.mts +0 -7
- package/dist/api/plugin-errors.mjs +0 -10
- package/dist/api/plugin-errors.mjs.map +0 -1
- package/dist/cli/wirings/build-verb-layers.mjs +0 -42
- package/dist/cli/wirings/build-verb-layers.mjs.map +0 -1
- package/dist/contracts/capability-decl.d.mts +0 -40
- package/dist/orchestrators/built-in-plugin-layers.mjs +0 -54
- package/dist/orchestrators/built-in-plugin-layers.mjs.map +0 -1
- package/dist/orchestrators/run.mjs +0 -91
- package/dist/orchestrators/run.mjs.map +0 -1
- package/dist/orchestrators/runtime-composition.d.mts +0 -10
- package/dist/orchestrators/runtime-composition.mjs +0 -252
- package/dist/orchestrators/runtime-composition.mjs.map +0 -1
- package/dist/orchestrators/snapshot/capture-command.d.mts +0 -1
- package/dist/orchestrators/snapshot/capture-command.mjs +0 -25
- package/dist/orchestrators/snapshot/capture-command.mjs.map +0 -1
- package/dist/orchestrators/snapshot/pending-marker.mjs +0 -99
- package/dist/orchestrators/snapshot/pending-marker.mjs.map +0 -1
- package/dist/orchestrators/snapshot/recover-pending.mjs +0 -223
- package/dist/orchestrators/snapshot/recover-pending.mjs.map +0 -1
- package/dist/orchestrators/snapshot/state-document.d.mts +0 -1
- package/dist/orchestrators/snapshot/state-document.mjs +0 -58
- package/dist/orchestrators/snapshot/state-document.mjs.map +0 -1
- package/dist/plugins/account/spans.mjs +0 -16
- package/dist/plugins/account/spans.mjs.map +0 -1
- package/dist/plugins/account/variants/env.mjs +0 -24
- package/dist/plugins/account/variants/env.mjs.map +0 -1
- package/dist/plugins/account/variants/inline.mjs +0 -13
- package/dist/plugins/account/variants/inline.mjs.map +0 -1
- package/dist/plugins/account/variants/keystore.mjs +0 -91
- package/dist/plugins/account/variants/keystore.mjs.map +0 -1
- package/dist/plugins/action/spans.mjs +0 -11
- package/dist/plugins/action/spans.mjs.map +0 -1
- package/dist/plugins/coin/spans.mjs +0 -20
- package/dist/plugins/coin/spans.mjs.map +0 -1
- package/dist/plugins/deepbook/spans.mjs +0 -18
- package/dist/plugins/deepbook/spans.mjs.map +0 -1
- package/dist/plugins/faucet/spans.mjs +0 -12
- package/dist/plugins/faucet/spans.mjs.map +0 -1
- package/dist/plugins/package/spans.mjs +0 -14
- package/dist/plugins/package/spans.mjs.map +0 -1
- package/dist/plugins/postgres/codegen.mjs +0 -42
- package/dist/plugins/postgres/codegen.mjs.map +0 -1
- package/dist/plugins/postgres/connection.d.mts +0 -33
- package/dist/plugins/postgres/connection.mjs.map +0 -1
- package/dist/plugins/postgres/db-ensure.mjs.map +0 -1
- package/dist/plugins/postgres/errors.d.mts +0 -60
- package/dist/plugins/postgres/errors.mjs +0 -29
- package/dist/plugins/postgres/errors.mjs.map +0 -1
- package/dist/plugins/postgres/index.d.mts +0 -37
- package/dist/plugins/postgres/index.mjs +0 -68
- package/dist/plugins/postgres/index.mjs.map +0 -1
- package/dist/plugins/postgres/routable.mjs +0 -33
- package/dist/plugins/postgres/routable.mjs.map +0 -1
- package/dist/plugins/postgres/service.d.mts +0 -50
- package/dist/plugins/postgres/service.mjs +0 -179
- package/dist/plugins/postgres/service.mjs.map +0 -1
- package/dist/plugins/postgres/snapshot.mjs +0 -32
- package/dist/plugins/postgres/snapshot.mjs.map +0 -1
- package/dist/plugins/postgres/spans.mjs +0 -11
- package/dist/plugins/postgres/spans.mjs.map +0 -1
- package/dist/plugins/seal/spans.mjs +0 -18
- package/dist/plugins/seal/spans.mjs.map +0 -1
- package/dist/plugins/sui/spans.mjs +0 -17
- package/dist/plugins/sui/spans.mjs.map +0 -1
- package/dist/plugins/wallet/spans.mjs +0 -22
- package/dist/plugins/wallet/spans.mjs.map +0 -1
- package/dist/plugins/walrus/registry-publish.d.mts +0 -24
- package/dist/plugins/walrus/spans.mjs +0 -18
- package/dist/plugins/walrus/spans.mjs.map +0 -1
- package/dist/runtime/docker/logs.d.mts +0 -1
- package/dist/runtime/docker/logs.mjs +0 -34
- package/dist/runtime/docker/logs.mjs.map +0 -1
- package/dist/substrate/runtime/artifact-publisher/index.mjs +0 -86
- package/dist/substrate/runtime/artifact-publisher/index.mjs.map +0 -1
- package/dist/substrate/runtime/capability-sinks/index.d.mts +0 -1
- package/dist/substrate/runtime/capability-sinks/index.mjs +0 -3
- package/dist/substrate/runtime/capability-sinks/layer.d.mts +0 -1
- package/dist/substrate/runtime/capability-sinks/layer.mjs +0 -31
- package/dist/substrate/runtime/capability-sinks/layer.mjs.map +0 -1
- package/dist/substrate/runtime/capability-sinks/service.d.mts +0 -95
- package/dist/substrate/runtime/capability-sinks/service.mjs +0 -69
- package/dist/substrate/runtime/capability-sinks/service.mjs.map +0 -1
- package/dist/substrate/runtime/cross-process/lock.d.mts +0 -1
- package/dist/substrate/runtime/cross-process/lock.mjs +0 -23
- package/dist/substrate/runtime/cross-process/lock.mjs.map +0 -1
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +0 -113
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +0 -1
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs +0 -31
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +0 -1
- package/dist/substrate/runtime/observability/formatter-registry.d.mts +0 -1
- package/dist/substrate/runtime/observability/formatter-registry.mjs +0 -48
- package/dist/substrate/runtime/observability/formatter-registry.mjs.map +0 -1
- package/dist/substrate/runtime/observability/span-store.d.mts +0 -1
- package/dist/substrate/runtime/observability/span-store.mjs +0 -110
- package/dist/substrate/runtime/observability/span-store.mjs.map +0 -1
- package/dist/substrate/runtime/observability/spans.d.mts +0 -1
- package/dist/substrate/runtime/observability/spans.mjs +0 -87
- package/dist/substrate/runtime/observability/spans.mjs.map +0 -1
- package/dist/substrate/runtime/projection/index.mjs +0 -4
- package/dist/substrate/runtime/projection/persisted.mjs +0 -213
- package/dist/substrate/runtime/projection/persisted.mjs.map +0 -1
- package/dist/substrate/runtime/scoped-multimap/service.mjs +0 -52
- package/dist/substrate/runtime/scoped-multimap/service.mjs.map +0 -1
- package/dist/substrate/runtime/scoped-ref-map/index.mjs +0 -2
- package/dist/substrate/runtime/scoped-ref-map/service.mjs +0 -83
- package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +0 -1
- package/dist/substrate/runtime/state-store/index.mjs +0 -3
- package/dist/substrate/runtime/state-store/schema.d.mts +0 -1
- package/dist/substrate/runtime/state-store/schema.mjs +0 -41
- package/dist/substrate/runtime/state-store/schema.mjs.map +0 -1
- package/dist/substrate/runtime/state-store/service.d.mts +0 -1
- package/dist/substrate/runtime/state-store/service.mjs +0 -145
- package/dist/substrate/runtime/state-store/service.mjs.map +0 -1
- package/dist/substrate/runtime/sui-execute/index.mjs.map +0 -1
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +0 -1
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +0 -1
- package/dist/substrate/runtime/sui-move-build/index.mjs.map +0 -1
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +0 -151
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +0 -1
- package/dist/substrate/state-store.d.mts +0 -1
- /package/dist/orchestrators/{snapshot/pending-marker.d.mts → codegen/id-config.d.mts} +0 -0
- /package/dist/orchestrators/snapshot/{recover-pending.d.mts → interrupted-restore.d.mts} +0 -0
- /package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/sign-and-dispatch.d.mts +0 -0
- /package/dist/plugins/{postgres/snapshot.d.mts → sui/ledger/object-ref.d.mts} +0 -0
- /package/dist/{substrate/runtime/sui-move-build → plugins/sui/move}/index.d.mts +0 -0
- /package/dist/substrate/runtime/{state-store/index.d.mts → reconcile/graph.d.mts} +0 -0
- /package/dist/substrate/runtime/{cross-process/snapshot-reservation.d.mts → supervisor/contribution-dispatcher.d.mts} +0 -0
|
@@ -58,78 +58,46 @@ const causeDetail = (cause) => {
|
|
|
58
58
|
};
|
|
59
59
|
const faucetCauseDetail = causeDetail;
|
|
60
60
|
const fundingCauseDetail = causeDetail;
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
const newFaults = () => [];
|
|
62
|
+
/** Collapse accumulated faults into a single nullable detail string for the
|
|
63
|
+
* GraphQL-visible result. `null` when nothing drifted. */
|
|
64
|
+
const faultDetail = (faults) => faults.length === 0 ? null : faults.join("; ");
|
|
65
|
+
/** Describe why a value failed to narrow to the expected type — distinguishing
|
|
66
|
+
* 'absent' from 'present but wrong type'. */
|
|
67
|
+
const typeFault = (field, expected, v) => {
|
|
68
|
+
if (v === void 0 || v === null) return `${field}: missing (expected ${expected})`;
|
|
69
|
+
return `${field}: expected ${expected}, got ${typeof v}`;
|
|
70
|
+
};
|
|
71
|
+
/** Required string. On mismatch records a fault and returns '' so the panel
|
|
72
|
+
* still renders a (degraded) cell. */
|
|
73
|
+
const reqStr = (v, field, faults) => {
|
|
74
|
+
if (typeof v === "string") return v;
|
|
75
|
+
faults.push(typeFault(field, "string", v));
|
|
76
|
+
return "";
|
|
77
|
+
};
|
|
78
|
+
/** Required finite number. On mismatch records a fault and returns the safe
|
|
79
|
+
* display fallback (`fallback`, default 0). */
|
|
80
|
+
const reqNum = (v, field, faults, fallback = 0) => {
|
|
81
|
+
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
82
|
+
faults.push(typeFault(field, "number", v));
|
|
83
|
+
return fallback;
|
|
84
|
+
};
|
|
85
|
+
/** Allow-list enum narrow. Records a fault for an out-of-enum value while
|
|
86
|
+
* still returning a safe display fallback so the panel renders. */
|
|
87
|
+
const narrowEnum = (raw, allowed, field, faults, fallback) => {
|
|
88
|
+
if (typeof raw === "string" && allowed.includes(raw)) return raw;
|
|
89
|
+
faults.push(raw === void 0 || raw === null ? `${field}: missing (expected one of ${allowed.join("|")})` : `${field}: '${String(raw)}' not in ${allowed.join("|")}`);
|
|
90
|
+
return fallback;
|
|
91
|
+
};
|
|
92
|
+
const optStr = (v) => typeof v === "string" ? v : null;
|
|
93
|
+
const optNum = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
64
94
|
const bool = (v) => v === true;
|
|
65
95
|
/** Filter the generic resolved values down to those whose resource id
|
|
66
96
|
* matches a predicate, in graph order. Returns the `{ pluginKey, value }`
|
|
67
97
|
* the shaping functions consume. */
|
|
68
98
|
const matching = (values, matches) => values.filter((v) => matches(v.id));
|
|
69
|
-
/** SQL that emits a single line of JSON the dashboard can parse without a
|
|
70
|
-
* PG client. Keeps the round trip to one exec. */
|
|
71
|
-
const PG_STATS_SQL = `SELECT json_build_object(
|
|
72
|
-
'db_bytes', pg_database_size(current_database()),
|
|
73
|
-
'connections', (SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()),
|
|
74
|
-
'tables', COALESCE((
|
|
75
|
-
SELECT json_agg(t) FROM (
|
|
76
|
-
SELECT schemaname AS schema, relname AS name,
|
|
77
|
-
n_live_tup AS row_estimate,
|
|
78
|
-
pg_total_relation_size(relid) AS total_bytes
|
|
79
|
-
FROM pg_stat_user_tables
|
|
80
|
-
ORDER BY pg_total_relation_size(relid) DESC
|
|
81
|
-
LIMIT 200
|
|
82
|
-
) t
|
|
83
|
-
), '[]'::json)
|
|
84
|
-
)`;
|
|
85
|
-
const parsePgStats = (pluginKey, pg, stdout) => {
|
|
86
|
-
const base = {
|
|
87
|
-
pluginKey,
|
|
88
|
-
database: strReq((pg.databases ?? [])[0]) || "postgres",
|
|
89
|
-
plainUrl: `postgres://${str(pg.networkAlias) ?? "postgres"}:${num(pg.port) ?? 5432}`
|
|
90
|
-
};
|
|
91
|
-
try {
|
|
92
|
-
const trimmed = stdout.trim();
|
|
93
|
-
const parsed = JSON.parse(trimmed);
|
|
94
|
-
const tables = (parsed.tables ?? []).map((t) => ({
|
|
95
|
-
schema: t.schema ?? "public",
|
|
96
|
-
name: t.name ?? "",
|
|
97
|
-
rowEstimate: num(t.row_estimate) ?? 0,
|
|
98
|
-
totalBytes: num(t.total_bytes) ?? 0
|
|
99
|
-
}));
|
|
100
|
-
return {
|
|
101
|
-
...base,
|
|
102
|
-
databaseBytes: num(parsed.db_bytes) ?? 0,
|
|
103
|
-
connectionCount: num(parsed.connections) ?? 0,
|
|
104
|
-
tables,
|
|
105
|
-
available: true,
|
|
106
|
-
detail: null
|
|
107
|
-
};
|
|
108
|
-
} catch (cause) {
|
|
109
|
-
return {
|
|
110
|
-
...base,
|
|
111
|
-
databaseBytes: 0,
|
|
112
|
-
connectionCount: 0,
|
|
113
|
-
tables: [],
|
|
114
|
-
available: false,
|
|
115
|
-
detail: `failed to parse psql output: ${String(cause)}`
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
const unavailablePgStats = (pluginKey, pg, detail) => {
|
|
120
|
-
return {
|
|
121
|
-
pluginKey,
|
|
122
|
-
database: strReq((pg.databases ?? [])[0]) || "postgres",
|
|
123
|
-
plainUrl: `postgres://${str(pg.networkAlias) ?? "postgres"}:${num(pg.port) ?? 5432}`,
|
|
124
|
-
databaseBytes: 0,
|
|
125
|
-
connectionCount: 0,
|
|
126
|
-
tables: [],
|
|
127
|
-
available: false,
|
|
128
|
-
detail
|
|
129
|
-
};
|
|
130
|
-
};
|
|
131
99
|
const buildDashboardDomain = (deps) => {
|
|
132
|
-
const { control,
|
|
100
|
+
const { control, strategyRegistry } = deps;
|
|
133
101
|
const mode = control.resolvedValues.pipe(Effect.map((values) => {
|
|
134
102
|
const sui = matching(values, (id) => id === "sui")[0];
|
|
135
103
|
if (sui === void 0) return null;
|
|
@@ -143,55 +111,72 @@ const buildDashboardDomain = (deps) => {
|
|
|
143
111
|
}));
|
|
144
112
|
const deepbook = control.resolvedValues.pipe(Effect.map((values) => matching(values, (id) => id.startsWith("deepbook/")).map(({ pluginKey, value }) => {
|
|
145
113
|
const v = value;
|
|
146
|
-
const
|
|
147
|
-
const dbMode =
|
|
114
|
+
const faults = newFaults();
|
|
115
|
+
const dbMode = narrowEnum(v.mode, [
|
|
116
|
+
"local",
|
|
117
|
+
"override",
|
|
118
|
+
"known"
|
|
119
|
+
], "deepbook.mode", faults, "local");
|
|
148
120
|
return {
|
|
149
121
|
pluginKey,
|
|
150
122
|
name: pluginKey.replace(/^deepbook:/, ""),
|
|
151
123
|
mode: dbMode,
|
|
152
|
-
|
|
153
|
-
packageId:
|
|
154
|
-
registryId:
|
|
155
|
-
adminCapId:
|
|
156
|
-
deepTreasuryId:
|
|
157
|
-
pools: (v.pools ?? []).map((p) => ({
|
|
158
|
-
name:
|
|
159
|
-
poolId:
|
|
160
|
-
baseCoinType:
|
|
161
|
-
quoteCoinType:
|
|
124
|
+
network: reqStr(v.network, "deepbook.network", faults),
|
|
125
|
+
packageId: reqStr(v.packageId, "deepbook.packageId", faults),
|
|
126
|
+
registryId: reqStr(v.registryId, "deepbook.registryId", faults),
|
|
127
|
+
adminCapId: optStr(v.adminCapId),
|
|
128
|
+
deepTreasuryId: optStr(v.deepTreasuryId),
|
|
129
|
+
pools: (v.pools ?? []).map((p, i) => ({
|
|
130
|
+
name: reqStr(p.name, `deepbook.pools[${i}].name`, faults),
|
|
131
|
+
poolId: reqStr(p.poolId, `deepbook.pools[${i}].poolId`, faults),
|
|
132
|
+
baseCoinType: reqStr(p.baseCoinType, `deepbook.pools[${i}].baseCoinType`, faults),
|
|
133
|
+
quoteCoinType: reqStr(p.quoteCoinType, `deepbook.pools[${i}].quoteCoinType`, faults)
|
|
162
134
|
})),
|
|
163
135
|
marketMakerRunning: bool(v.marketMakerRunning),
|
|
164
|
-
serverUrl:
|
|
165
|
-
indexerUrl:
|
|
136
|
+
serverUrl: optStr(v.serverUrl),
|
|
137
|
+
indexerUrl: optStr(v.indexerUrl),
|
|
138
|
+
narrowingFault: faultDetail(faults)
|
|
166
139
|
};
|
|
167
140
|
})));
|
|
168
141
|
const seal = control.resolvedValues.pipe(Effect.map((values) => matching(values, (id) => id.startsWith("seal:")).map(({ pluginKey, value }) => {
|
|
169
142
|
const v = value;
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
143
|
+
const faults = newFaults();
|
|
144
|
+
const sealMode = narrowEnum(v.mode, [
|
|
145
|
+
"local-keygen",
|
|
146
|
+
"live",
|
|
147
|
+
"fork-known"
|
|
148
|
+
], "seal.mode", faults, "local-keygen");
|
|
149
|
+
const keyServers = (v.serverConfigs ?? []).map((c, i) => ({
|
|
150
|
+
objectId: reqStr(c.objectId, `seal.serverConfigs[${i}].objectId`, faults),
|
|
151
|
+
weight: optNum(c.weight) ?? 1
|
|
174
152
|
}));
|
|
175
153
|
return {
|
|
176
154
|
pluginKey,
|
|
177
155
|
mode: sealMode,
|
|
178
|
-
objectId:
|
|
179
|
-
keyServerUrl:
|
|
156
|
+
objectId: reqStr(v.objectId, "seal.objectId", faults),
|
|
157
|
+
keyServerUrl: reqStr(v.keyServerUrl, "seal.keyServerUrl", faults),
|
|
180
158
|
keyServers,
|
|
181
|
-
threshold: keyServers.length
|
|
159
|
+
threshold: keyServers.length,
|
|
160
|
+
narrowingFault: faultDetail(faults)
|
|
182
161
|
};
|
|
183
162
|
})));
|
|
184
163
|
const coinCaps = control.resolvedValues.pipe(Effect.map((values) => matching(values, (id) => id.startsWith("coin:")).map(({ pluginKey, value }) => {
|
|
185
164
|
const v = value;
|
|
186
|
-
const
|
|
165
|
+
const faults = newFaults();
|
|
166
|
+
const source = narrowEnum(v.source, [
|
|
167
|
+
"registry",
|
|
168
|
+
"on-chain",
|
|
169
|
+
"builtin"
|
|
170
|
+
], "coin.source", faults, "on-chain");
|
|
187
171
|
return {
|
|
188
172
|
pluginKey,
|
|
189
|
-
symbol:
|
|
190
|
-
fullCoinType:
|
|
191
|
-
decimals:
|
|
173
|
+
symbol: optStr(v.symbol),
|
|
174
|
+
fullCoinType: reqStr(v.fullCoinType, "coin.fullCoinType", faults),
|
|
175
|
+
decimals: reqNum(v.decimals, "coin.decimals", faults, 0),
|
|
192
176
|
source,
|
|
193
|
-
treasuryCapId:
|
|
194
|
-
packageId:
|
|
177
|
+
treasuryCapId: optStr(v.treasuryCapId),
|
|
178
|
+
packageId: optStr(v.packageId),
|
|
179
|
+
narrowingFault: faultDetail(faults)
|
|
195
180
|
};
|
|
196
181
|
})));
|
|
197
182
|
const mintCoin = (input) => Effect.gen(function* () {
|
|
@@ -206,12 +191,17 @@ const buildDashboardDomain = (deps) => {
|
|
|
206
191
|
detail: `invalid amountBaseUnits '${input.amountBaseUnits}': expected a positive integer string`,
|
|
207
192
|
digest: null
|
|
208
193
|
};
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
194
|
+
const candidates = matching(yield* control.resolvedValues, (id) => id.startsWith("coin:")).map(({ value }) => value);
|
|
195
|
+
const matchFaults = newFaults();
|
|
196
|
+
const match = candidates.find((v) => reqStr(v.fullCoinType, "coin.fullCoinType", matchFaults) === input.coinType);
|
|
197
|
+
if (match === void 0) {
|
|
198
|
+
const fault = faultDetail(matchFaults);
|
|
199
|
+
return {
|
|
200
|
+
ok: false,
|
|
201
|
+
detail: fault === null ? `no resolved coin found for type '${input.coinType}'` : `no resolved coin found for type '${input.coinType}' (${fault})`,
|
|
202
|
+
digest: null
|
|
203
|
+
};
|
|
204
|
+
}
|
|
215
205
|
if (typeof match.mintFromCap !== "function") return {
|
|
216
206
|
ok: false,
|
|
217
207
|
detail: `coin '${input.coinType}' has no in-process treasury cap signer — mint is only available for local-package coins whose publisher still owns the TreasuryCap`,
|
|
@@ -235,10 +225,10 @@ const buildDashboardDomain = (deps) => {
|
|
|
235
225
|
})));
|
|
236
226
|
});
|
|
237
227
|
/** The chain id the SUI funding path keys on, read from the resolved sui
|
|
238
|
-
* value (same `
|
|
228
|
+
* value (same `chainId` field the sui codegen/snapshot decls stamp). */
|
|
239
229
|
const readChainId = control.resolvedValues.pipe(Effect.map((values) => {
|
|
240
230
|
const sui = matching(values, (id) => id === "sui")[0];
|
|
241
|
-
return sui === void 0 ? null :
|
|
231
|
+
return sui === void 0 ? null : optStr(sui.value.chainId);
|
|
242
232
|
}));
|
|
243
233
|
const fundableCoins = Effect.gen(function* () {
|
|
244
234
|
const out = [];
|
|
@@ -269,28 +259,24 @@ const buildDashboardDomain = (deps) => {
|
|
|
269
259
|
const recipient = input.recipient.trim();
|
|
270
260
|
if (!SUI_ADDRESS_RE.test(recipient)) return {
|
|
271
261
|
ok: false,
|
|
272
|
-
detail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address
|
|
273
|
-
digest: null
|
|
262
|
+
detail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`
|
|
274
263
|
};
|
|
275
264
|
if (strategyRegistry === null) return {
|
|
276
265
|
ok: false,
|
|
277
|
-
detail: "funding unavailable: no strategy registry wired"
|
|
278
|
-
digest: null
|
|
266
|
+
detail: "funding unavailable: no strategy registry wired"
|
|
279
267
|
};
|
|
280
268
|
const coinType = input.coinType?.trim() ?? "";
|
|
281
269
|
if (coinType === "" || coinType === SUI_FULL_COIN_TYPE) {
|
|
282
270
|
const chain = yield* readChainId;
|
|
283
271
|
if (chain === null) return {
|
|
284
272
|
ok: false,
|
|
285
|
-
detail: "cannot fund SUI: no resolved sui plugin / chain id in this stack"
|
|
286
|
-
digest: null
|
|
273
|
+
detail: "cannot fund SUI: no resolved sui plugin / chain id in this stack"
|
|
287
274
|
};
|
|
288
275
|
const key = faucetCapabilityKeyFor(chain);
|
|
289
276
|
const strategy = yield* strategyRegistry.get(key).pipe(Effect.catchTag("StrategyNotFoundError", () => Effect.succeed(null)));
|
|
290
277
|
if (strategy === null) return {
|
|
291
278
|
ok: false,
|
|
292
|
-
detail: `no SUI faucet strategy registered for chain '${chain}'
|
|
293
|
-
digest: null
|
|
279
|
+
detail: `no SUI faucet strategy registered for chain '${chain}'`
|
|
294
280
|
};
|
|
295
281
|
const amount = parseAmount(input.amountBaseUnits) ?? 1000000000n;
|
|
296
282
|
return yield* strategy.request({
|
|
@@ -298,36 +284,30 @@ const buildDashboardDomain = (deps) => {
|
|
|
298
284
|
amount
|
|
299
285
|
}).pipe(Effect.map(() => ({
|
|
300
286
|
ok: true,
|
|
301
|
-
detail: `requested SUI for ${recipient} (fixed-amount faucet grant)
|
|
302
|
-
digest: null
|
|
287
|
+
detail: `requested SUI for ${recipient} (fixed-amount faucet grant)`
|
|
303
288
|
})), Effect.catch((cause) => Effect.succeed({
|
|
304
289
|
ok: false,
|
|
305
|
-
detail: `SUI faucet request failed: ${faucetCauseDetail(cause)}
|
|
306
|
-
digest: null
|
|
290
|
+
detail: `SUI faucet request failed: ${faucetCauseDetail(cause)}`
|
|
307
291
|
})), Effect.catchCause((cause) => Effect.succeed({
|
|
308
292
|
ok: false,
|
|
309
|
-
detail: `SUI faucet request crashed: ${String(cause)}
|
|
310
|
-
digest: null
|
|
293
|
+
detail: `SUI faucet request crashed: ${String(cause)}`
|
|
311
294
|
})));
|
|
312
295
|
}
|
|
313
296
|
const amount = parseAmount(input.amountBaseUnits);
|
|
314
297
|
if (amount === null) return {
|
|
315
298
|
ok: false,
|
|
316
|
-
detail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ""}': expected a positive integer string
|
|
317
|
-
digest: null
|
|
299
|
+
detail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ""}': expected a positive integer string`
|
|
318
300
|
};
|
|
319
301
|
const key = `coinType:${coinType}`;
|
|
320
302
|
const strategy = yield* strategyRegistry.get(key).pipe(Effect.catchTag("StrategyNotFoundError", () => Effect.succeed(null)));
|
|
321
303
|
if (strategy === null) return {
|
|
322
304
|
ok: false,
|
|
323
|
-
detail: `no funding strategy registered for coin '${coinType}' — WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin
|
|
324
|
-
digest: null
|
|
305
|
+
detail: `no funding strategy registered for coin '${coinType}' — WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin`
|
|
325
306
|
};
|
|
326
|
-
const account = matching(yield* control.resolvedValues, (id) => id.startsWith("account/")).map(({ value }) => value).find((v) =>
|
|
307
|
+
const account = matching(yield* control.resolvedValues, (id) => id.startsWith("account/")).map(({ value }) => value).find((v) => optStr(v.address) === recipient);
|
|
327
308
|
if (strategy.requiresRecipientAccount === true && account === void 0) return {
|
|
328
309
|
ok: false,
|
|
329
|
-
detail: `coin '${coinType}' is funded by an account-signed swap, but '${recipient}' is not a resolved account in this stack — fund a configured account (the swap spends its SUI)
|
|
330
|
-
digest: null
|
|
310
|
+
detail: `coin '${coinType}' is funded by an account-signed swap, but '${recipient}' is not a resolved account in this stack — fund a configured account (the swap spends its SUI)`
|
|
331
311
|
};
|
|
332
312
|
return yield* strategy.request({
|
|
333
313
|
address: recipient,
|
|
@@ -335,16 +315,13 @@ const buildDashboardDomain = (deps) => {
|
|
|
335
315
|
...account === void 0 ? {} : { account }
|
|
336
316
|
}).pipe(Effect.map(() => ({
|
|
337
317
|
ok: true,
|
|
338
|
-
detail: `funded ${amount} base units of ${coinType} to ${recipient}
|
|
339
|
-
digest: null
|
|
318
|
+
detail: `funded ${amount} base units of ${coinType} to ${recipient}`
|
|
340
319
|
})), Effect.catch((cause) => Effect.succeed({
|
|
341
320
|
ok: false,
|
|
342
|
-
detail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}
|
|
343
|
-
digest: null
|
|
321
|
+
detail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}`
|
|
344
322
|
})), Effect.catchCause((cause) => Effect.succeed({
|
|
345
323
|
ok: false,
|
|
346
|
-
detail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}
|
|
347
|
-
digest: null
|
|
324
|
+
detail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}`
|
|
348
325
|
})));
|
|
349
326
|
});
|
|
350
327
|
return {
|
|
@@ -352,50 +329,12 @@ const buildDashboardDomain = (deps) => {
|
|
|
352
329
|
deepbook,
|
|
353
330
|
seal,
|
|
354
331
|
coinCaps,
|
|
355
|
-
postgresStats: Effect.gen(function* () {
|
|
356
|
-
const instances = matching(yield* control.resolvedValues, (id) => id === "postgres");
|
|
357
|
-
if (instances.length === 0) return [];
|
|
358
|
-
const out = [];
|
|
359
|
-
for (const { pluginKey, value } of instances) {
|
|
360
|
-
const pg = value;
|
|
361
|
-
if (containerRuntime === null) {
|
|
362
|
-
out.push(unavailablePgStats(pluginKey, pg, "container runtime unavailable"));
|
|
363
|
-
continue;
|
|
364
|
-
}
|
|
365
|
-
const database = strReq((pg.databases ?? [])[0]) || "postgres";
|
|
366
|
-
const pgUser = str(pg.user) ?? "postgres";
|
|
367
|
-
const role = str(pg.name) ?? "postgres";
|
|
368
|
-
const stats = yield* Effect.gen(function* () {
|
|
369
|
-
const handles = yield* containerRuntime.inspectByLabels({
|
|
370
|
-
app: String(identity.app),
|
|
371
|
-
stack: String(identity.stack),
|
|
372
|
-
plugin: "postgres",
|
|
373
|
-
role
|
|
374
|
-
});
|
|
375
|
-
const running = handles.find((h) => h.status === "running") ?? handles[0];
|
|
376
|
-
if (running === void 0) return unavailablePgStats(pluginKey, pg, "no running postgres container found");
|
|
377
|
-
const result = yield* containerRuntime.exec(running, [
|
|
378
|
-
"psql",
|
|
379
|
-
"-U",
|
|
380
|
-
pgUser,
|
|
381
|
-
"-d",
|
|
382
|
-
database,
|
|
383
|
-
"-tAc",
|
|
384
|
-
PG_STATS_SQL
|
|
385
|
-
]);
|
|
386
|
-
if (result.exitCode !== 0) return unavailablePgStats(pluginKey, pg, `psql exited ${result.exitCode}: ${result.stderr.trim().slice(0, 200)}`);
|
|
387
|
-
return parsePgStats(pluginKey, pg, result.stdout);
|
|
388
|
-
}).pipe(Effect.catchCause((cause) => Effect.succeed(unavailablePgStats(pluginKey, pg, String(cause)))));
|
|
389
|
-
out.push(stats);
|
|
390
|
-
}
|
|
391
|
-
return out;
|
|
392
|
-
}),
|
|
393
332
|
mintCoin,
|
|
394
333
|
fundableCoins,
|
|
395
334
|
fundAccount
|
|
396
335
|
};
|
|
397
336
|
};
|
|
398
|
-
Effect.succeed(null), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]), Effect.succeed([])
|
|
337
|
+
Effect.succeed(null), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]);
|
|
399
338
|
//#endregion
|
|
400
339
|
export { buildDashboardDomain };
|
|
401
340
|
|
|
@@ -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,\n// `id === 'sui'`, `id === 'postgres'`) and projects them into the\n// app-agnostic shapes the\n// GraphQL schema renders. It also owns the `mode` derivation, the coin\n// `mint` action, and the Postgres `psql`-exec wire-protocol stats.\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 === 'postgres'`, `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 { ContainerRuntime } from '../../contracts/container-runtime.ts';\nimport type { Identity } from '../../substrate/identity.ts';\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 chain: 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}\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}\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}\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 `digest` is always `null` here — kept\n * for shape-parity with `DashboardMintResult`. `ok:true` means the\n * strategy's `request(...)` completed (the faucet POST landed / the swap\n * executed on-chain); `detail` carries the reason on failure. */\nexport interface DashboardFundResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\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\nexport interface DashboardPostgresTable {\n\treadonly schema: string;\n\treadonly name: string;\n\treadonly rowEstimate: number;\n\treadonly totalBytes: number;\n}\n\nexport interface DashboardPostgresStats {\n\treadonly pluginKey: string;\n\treadonly database: string;\n\t/** Plain (password-less) DSN — the credentialed form NEVER leaves the\n\t * backend. */\n\treadonly plainUrl: string;\n\treadonly databaseBytes: number;\n\treadonly connectionCount: number;\n\treadonly tables: ReadonlyArray<DashboardPostgresTable>;\n\t/** `false` when stats could not be gathered (container down, exec\n\t * failure). The dashboard renders a degraded state rather than\n\t * failing the whole query. */\n\treadonly available: boolean;\n\treadonly detail: string | null;\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/** Postgres wire-protocol stats per postgres plugin instance. */\n\treadonly postgresStats: Effect.Effect<ReadonlyArray<DashboardPostgresStats>>;\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 chain?: 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 PostgresShape {\n\treadonly name?: unknown;\n\treadonly user?: unknown;\n\treadonly databases?: ReadonlyArray<unknown>;\n\treadonly plainEndpoint?: unknown;\n\treadonly networkAlias?: unknown;\n\treadonly port?: unknown;\n}\n\ninterface SuiShape {\n\treadonly mode?: unknown;\n\t/** Substrate-level 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 chain?: 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\nconst str = (v: unknown): string | null => (typeof v === 'string' ? v : null);\nconst strReq = (v: unknown): string => (typeof v === 'string' ? v : '');\nconst num = (v: unknown): number | null => (typeof 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// Postgres wire-protocol stats via `psql` exec inside the container\n// -----------------------------------------------------------------------------\n\n/** SQL that emits a single line of JSON the dashboard can parse without a\n * PG client. Keeps the round trip to one exec. */\nconst PG_STATS_SQL = `SELECT json_build_object(\n 'db_bytes', pg_database_size(current_database()),\n 'connections', (SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()),\n 'tables', COALESCE((\n SELECT json_agg(t) FROM (\n SELECT schemaname AS schema, relname AS name,\n n_live_tup AS row_estimate,\n pg_total_relation_size(relid) AS total_bytes\n FROM pg_stat_user_tables\n ORDER BY pg_total_relation_size(relid) DESC\n LIMIT 200\n ) t\n ), '[]'::json)\n)`;\n\nconst parsePgStats = (\n\tpluginKey: string,\n\tpg: PostgresShape,\n\tstdout: string,\n): DashboardPostgresStats => {\n\tconst database = strReq((pg.databases ?? [])[0]) || 'postgres';\n\tconst host = str(pg.networkAlias) ?? 'postgres';\n\tconst port = num(pg.port) ?? 5432;\n\tconst plainUrl = `postgres://${host}:${port}`;\n\tconst base = {\n\t\tpluginKey,\n\t\tdatabase,\n\t\tplainUrl,\n\t} as const;\n\ttry {\n\t\tconst trimmed = stdout.trim();\n\t\tconst parsed = JSON.parse(trimmed) as {\n\t\t\tdb_bytes?: number;\n\t\t\tconnections?: number;\n\t\t\ttables?: ReadonlyArray<{\n\t\t\t\tschema?: string;\n\t\t\t\tname?: string;\n\t\t\t\trow_estimate?: number;\n\t\t\t\ttotal_bytes?: number;\n\t\t\t}>;\n\t\t};\n\t\tconst tables: DashboardPostgresTable[] = (parsed.tables ?? []).map((t) => ({\n\t\t\tschema: t.schema ?? 'public',\n\t\t\tname: t.name ?? '',\n\t\t\trowEstimate: num(t.row_estimate) ?? 0,\n\t\t\ttotalBytes: num(t.total_bytes) ?? 0,\n\t\t}));\n\t\treturn {\n\t\t\t...base,\n\t\t\tdatabaseBytes: num(parsed.db_bytes) ?? 0,\n\t\t\tconnectionCount: num(parsed.connections) ?? 0,\n\t\t\ttables,\n\t\t\tavailable: true,\n\t\t\tdetail: null,\n\t\t};\n\t} catch (cause) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tdatabaseBytes: 0,\n\t\t\tconnectionCount: 0,\n\t\t\ttables: [],\n\t\t\tavailable: false,\n\t\t\tdetail: `failed to parse psql output: ${String(cause)}`,\n\t\t};\n\t}\n};\n\nconst unavailablePgStats = (\n\tpluginKey: string,\n\tpg: PostgresShape,\n\tdetail: string,\n): DashboardPostgresStats => {\n\tconst database = strReq((pg.databases ?? [])[0]) || 'postgres';\n\tconst host = str(pg.networkAlias) ?? 'postgres';\n\tconst port = num(pg.port) ?? 5432;\n\treturn {\n\t\tpluginKey,\n\t\tdatabase,\n\t\tplainUrl: `postgres://${host}:${port}`,\n\t\tdatabaseBytes: 0,\n\t\tconnectionCount: 0,\n\t\ttables: [],\n\t\tavailable: false,\n\t\tdetail,\n\t};\n};\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/** Stack identity, used for the postgres container label probe. */\n\treadonly identity: Identity;\n\t/** Container runtime for the Postgres `psql` exec-probe. `null` in bare\n\t * test paths; `postgresStats` degrades to an unavailable entry then. */\n\treadonly containerRuntime: ContainerRuntime | null;\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, identity, containerRuntime, 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 modeRaw = v.mode;\n\t\t\t\t\tconst dbMode =\n\t\t\t\t\t\tmodeRaw === 'override' ? 'override' : modeRaw === 'known' ? 'known' : 'local';\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\tchain: strReq(v.chain),\n\t\t\t\t\t\tpackageId: strReq(v.packageId),\n\t\t\t\t\t\tregistryId: strReq(v.registryId),\n\t\t\t\t\t\tadminCapId: str(v.adminCapId),\n\t\t\t\t\t\tdeepTreasuryId: str(v.deepTreasuryId),\n\t\t\t\t\t\tpools: (v.pools ?? []).map((p) => ({\n\t\t\t\t\t\t\tname: strReq(p.name),\n\t\t\t\t\t\t\tpoolId: strReq(p.poolId),\n\t\t\t\t\t\t\tbaseCoinType: strReq(p.baseCoinType),\n\t\t\t\t\t\t\tquoteCoinType: strReq(p.quoteCoinType),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tmarketMakerRunning: bool(v.marketMakerRunning),\n\t\t\t\t\t\tserverUrl: str(v.serverUrl),\n\t\t\t\t\t\tindexerUrl: str(v.indexerUrl),\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 sealMode =\n\t\t\t\t\t\tv.mode === 'live' ? 'live' : v.mode === 'fork-known' ? 'fork-known' : 'local-keygen';\n\t\t\t\t\tconst keyServers = (v.serverConfigs ?? []).map((c) => ({\n\t\t\t\t\t\tobjectId: strReq(c.objectId),\n\t\t\t\t\t\tweight: num(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: strReq(v.objectId),\n\t\t\t\t\t\tkeyServerUrl: strReq(v.keyServerUrl),\n\t\t\t\t\t\tkeyServers,\n\t\t\t\t\t\tthreshold: keyServers.length,\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 source =\n\t\t\t\t\t\tv.source === 'registry' ? 'registry' : v.source === 'builtin' ? 'builtin' : 'on-chain';\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tsymbol: str(v.symbol),\n\t\t\t\t\t\tfullCoinType: strReq(v.fullCoinType),\n\t\t\t\t\t\tdecimals: num(v.decimals) ?? 0,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\ttreasuryCapId: str(v.treasuryCapId),\n\t\t\t\t\t\tpackageId: str(v.packageId),\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.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst match = matching(values, (id) => id.startsWith('coin:'))\n\t\t\t\t.map(({ value }) => value as CoinShape)\n\t\t\t\t.find((v) => strReq(v.fullCoinType) === input.coinType);\n\n\t\t\tif (match === undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `no resolved coin found for type '${input.coinType}'`,\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 `chain` 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 : str((sui.value as SuiShape).chain);\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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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) => str(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\tdigest: null,\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\tdigest: null,\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\tdigest: null,\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\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\tconst postgresStats: DashboardDomain['postgresStats'] = Effect.gen(function* () {\n\t\tconst values = yield* control.resolvedValues;\n\t\tconst instances = matching(values, (id) => id === 'postgres');\n\t\tif (instances.length === 0) return [];\n\t\tconst out: DashboardPostgresStats[] = [];\n\t\tfor (const { pluginKey, value } of instances) {\n\t\t\tconst pg = value as PostgresShape;\n\t\t\tif (containerRuntime === null) {\n\t\t\t\tout.push(unavailablePgStats(pluginKey, pg, 'container runtime unavailable'));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst database = strReq((pg.databases ?? [])[0]) || 'postgres';\n\t\t\tconst pgUser = str(pg.user) ?? 'postgres';\n\t\t\tconst role = str(pg.name) ?? 'postgres';\n\t\t\tconst probe = Effect.gen(function* () {\n\t\t\t\tconst handles = yield* containerRuntime.inspectByLabels({\n\t\t\t\t\tapp: String(identity.app),\n\t\t\t\t\tstack: String(identity.stack),\n\t\t\t\t\tplugin: 'postgres',\n\t\t\t\t\trole,\n\t\t\t\t});\n\t\t\t\tconst running = handles.find((h) => h.status === 'running') ?? handles[0];\n\t\t\t\tif (running === undefined) {\n\t\t\t\t\treturn unavailablePgStats(pluginKey, pg, 'no running postgres container found');\n\t\t\t\t}\n\t\t\t\tconst result = yield* containerRuntime.exec(running, [\n\t\t\t\t\t'psql',\n\t\t\t\t\t'-U',\n\t\t\t\t\tpgUser,\n\t\t\t\t\t'-d',\n\t\t\t\t\tdatabase,\n\t\t\t\t\t'-tAc',\n\t\t\t\t\tPG_STATS_SQL,\n\t\t\t\t]);\n\t\t\t\tif (result.exitCode !== 0) {\n\t\t\t\t\treturn unavailablePgStats(\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tpg,\n\t\t\t\t\t\t`psql exited ${result.exitCode}: ${result.stderr.trim().slice(0, 200)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn parsePgStats(pluginKey, pg, result.stdout);\n\t\t\t});\n\t\t\tconst stats = yield* probe.pipe(\n\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\tEffect.succeed(unavailablePgStats(pluginKey, pg, String(cause))),\n\t\t\t\t),\n\t\t\t);\n\t\t\tout.push(stats);\n\t\t}\n\t\treturn out;\n\t});\n\n\treturn {\n\t\tmode,\n\t\tdeepbook,\n\t\tseal,\n\t\tcoinCaps,\n\t\tpostgresStats,\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\tpostgresStats: Effect.succeed([]),\n\tmintCoin: () => Effect.succeed({ ok: false, detail: 'unavailable', digest: null }),\n\tfundableCoins: Effect.succeed([]),\n\tfundAccount: () => Effect.succeed({ ok: false, detail: 'unavailable', digest: null }),\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\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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"}
|