@mysten-incubation/devstack 0.0.1 → 0.1.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 -3
- package/dashboard-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dashboard-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
- package/dashboard-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dashboard-ui/assets/index-Bmi1UtAg.js +1356 -0
- package/dashboard-ui/assets/index-D5EShVt4.js +3 -0
- package/dashboard-ui/assets/index-Deml9drg.css +1 -0
- package/dashboard-ui/index.html +13 -0
- package/dist/api/define-capabilities.d.mts +14 -3
- package/dist/api/define-capabilities.mjs +18 -1
- package/dist/api/define-capabilities.mjs.map +1 -1
- package/dist/api/define-devstack.d.mts +1 -1
- package/dist/api/define-devstack.mjs +6 -26
- package/dist/api/define-devstack.mjs.map +1 -1
- package/dist/api/define-plugin.d.mts +1 -0
- package/dist/api/define-plugin.mjs +2 -0
- package/dist/api/inference-network.d.mts +132 -0
- package/dist/api/inference-network.mjs +105 -16
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/plugin-errors.d.mts +7 -0
- package/dist/api/run-stack.d.mts +20 -9
- package/dist/api/run-stack.mjs +56 -29
- package/dist/api/run-stack.mjs.map +1 -1
- package/dist/build-integrations/playwright/config.d.mts +6 -4
- package/dist/build-integrations/playwright/config.mjs +5 -3
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +1 -1
- package/dist/build-integrations/playwright/global-setup.d.mts +43 -17
- package/dist/build-integrations/playwright/global-setup.mjs +250 -13
- package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
- package/dist/build-integrations/playwright/index.d.mts +5 -3
- package/dist/build-integrations/playwright/index.mjs +4 -2
- package/dist/build-integrations/playwright/stack-context.d.mts +0 -1
- package/dist/build-integrations/playwright/stack-context.mjs +24 -63
- package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
- package/dist/build-integrations/playwright/wallet-context.d.mts +7 -10
- package/dist/build-integrations/playwright/wallet-context.mjs +8 -13
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/cold-start-url.d.mts +5 -0
- package/dist/build-integrations/runtime/cold-start-url.mjs +4 -3
- package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
- package/dist/build-integrations/runtime/conventional-routes.d.mts +51 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs +92 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -0
- package/dist/build-integrations/runtime/discover.d.mts +38 -30
- package/dist/build-integrations/runtime/discover.mjs +73 -70
- package/dist/build-integrations/runtime/discover.mjs.map +1 -1
- package/dist/build-integrations/runtime/endpoint-registry.d.mts +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
- package/dist/build-integrations/runtime/index.d.mts +7 -2
- package/dist/build-integrations/runtime/index.mjs +9 -2
- package/dist/build-integrations/runtime/manifest-types.d.mts +2 -0
- package/dist/build-integrations/runtime/manifest-types.mjs +3 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.d.mts +29 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs +10 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs.map +1 -0
- package/dist/build-integrations/runtime/read-stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/read-stack-context.mjs +10 -4
- package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +48 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs +42 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -0
- package/dist/build-integrations/runtime/stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/wallet-paths.mjs +2 -0
- package/dist/build-integrations/vite/index.d.mts +51 -0
- package/dist/build-integrations/vite/index.mjs +73 -0
- package/dist/build-integrations/vite/index.mjs.map +1 -0
- package/dist/build-integrations/vitest/env.d.mts +4 -3
- package/dist/build-integrations/vitest/env.mjs +6 -4
- package/dist/build-integrations/vitest/env.mjs.map +1 -1
- package/dist/build-integrations/vitest/errors.d.mts +25 -4
- package/dist/build-integrations/vitest/errors.mjs +15 -2
- package/dist/build-integrations/vitest/errors.mjs.map +1 -1
- package/dist/build-integrations/vitest/index.d.mts +2 -2
- package/dist/build-integrations/vitest/index.mjs +3 -3
- package/dist/build-integrations/vitest/setup.d.mts +4 -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 +0 -1
- package/dist/build-integrations/vitest/stack-context.mjs +33 -13
- package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
- package/dist/cli/bail.mjs +23 -0
- package/dist/cli/bail.mjs.map +1 -0
- package/dist/{surfaces/cli/commands → cli}/doctor-probes.mjs +26 -16
- package/dist/cli/doctor-probes.mjs.map +1 -0
- package/dist/cli/main.d.mts +15 -1
- package/dist/cli/main.mjs +166 -482
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/prune-direct.mjs +31 -201
- package/dist/cli/prune-direct.mjs.map +1 -1
- package/dist/cli/snapshot-reader.mjs +14 -11
- package/dist/cli/snapshot-reader.mjs.map +1 -1
- package/dist/cli/up-lifecycle.mjs +4 -1
- package/dist/cli/up-lifecycle.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +95 -0
- package/dist/cli/wirings/apply.mjs.map +1 -0
- package/dist/cli/wirings/build-verb-layers.mjs +42 -0
- package/dist/cli/wirings/build-verb-layers.mjs.map +1 -0
- package/dist/cli/wirings/config-loader.mjs +69 -0
- package/dist/cli/wirings/config-loader.mjs.map +1 -0
- package/dist/cli/wirings/engine-command.mjs +30 -0
- package/dist/cli/wirings/engine-command.mjs.map +1 -0
- package/dist/cli/wirings/identity.mjs +72 -0
- package/dist/cli/wirings/identity.mjs.map +1 -0
- package/dist/cli/wirings/provide-file-system.mjs +7 -0
- package/dist/cli/wirings/provide-file-system.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +177 -0
- package/dist/cli/wirings/snapshot.mjs.map +1 -0
- package/dist/cli/wirings/up.mjs +287 -0
- package/dist/cli/wirings/up.mjs.map +1 -0
- package/dist/cli/wirings/wipe.mjs +40 -0
- package/dist/cli/wirings/wipe.mjs.map +1 -0
- package/dist/contracts/capability-decl.d.mts +0 -2
- package/dist/contracts/codegenable.d.mts +43 -0
- package/dist/contracts/container-runtime.d.mts +26 -1
- package/dist/contracts/faucet-strategy.d.mts +25 -0
- package/dist/contracts/funding-strategy.d.mts +42 -0
- package/dist/contracts/plugin-expander.mjs +60 -0
- package/dist/contracts/plugin-expander.mjs.map +1 -0
- package/dist/contracts/projection.d.mts +5 -3
- package/dist/contracts/renderer.d.mts +23 -0
- package/dist/contracts/routable.d.mts +14 -1
- package/dist/contracts/snapshotable.d.mts +25 -3
- package/dist/contracts/wallet-protocol.d.mts +52 -0
- package/dist/contracts/wallet-protocol.mjs +52 -0
- package/dist/contracts/wallet-protocol.mjs.map +1 -0
- package/dist/index.d.mts +26 -25
- package/dist/index.mjs +20 -13
- package/dist/{runtime → orchestrators}/built-in-plugin-layers.mjs +10 -5
- package/dist/orchestrators/built-in-plugin-layers.mjs.map +1 -0
- package/dist/orchestrators/codegen/bindings.d.mts +1 -2
- package/dist/orchestrators/codegen/bindings.mjs +52 -186
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/emit.mjs +19 -1
- package/dist/orchestrators/codegen/emit.mjs.map +1 -1
- package/dist/orchestrators/codegen/errors.mjs +8 -3
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +47 -39
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/gitignore.mjs +3 -1
- package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
- package/dist/orchestrators/codegen/output-location.mjs +40 -0
- package/dist/orchestrators/codegen/output-location.mjs.map +1 -0
- package/dist/orchestrators/codegen/paths.d.mts +1 -1
- package/dist/orchestrators/codegen/paths.mjs +40 -14
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/permissions.mjs +3 -1
- package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +157 -105
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/lifecycle-prune/errors.mjs +31 -0
- package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs +350 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -0
- package/dist/orchestrators/router/cleanup.mjs +26 -27
- package/dist/orchestrators/router/cleanup.mjs.map +1 -1
- package/dist/orchestrators/router/entrypoints.mjs +2 -2
- package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
- package/dist/orchestrators/router/file-provider.mjs +14 -5
- package/dist/orchestrators/router/file-provider.mjs.map +1 -1
- package/dist/orchestrators/router/hostname.mjs +19 -55
- package/dist/orchestrators/router/hostname.mjs.map +1 -1
- package/dist/orchestrators/router/index.mjs +11 -0
- package/dist/orchestrators/router/profile.mjs +2 -2
- package/dist/orchestrators/router/sentinels.mjs +26 -0
- package/dist/orchestrators/router/sentinels.mjs.map +1 -0
- package/dist/orchestrators/router/service.mjs +40 -37
- package/dist/orchestrators/router/service.mjs.map +1 -1
- package/dist/orchestrators/router/traefik-container.mjs +27 -16
- package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
- package/dist/{substrate/runtime → orchestrators}/run.mjs +26 -21
- package/dist/orchestrators/run.mjs.map +1 -0
- package/dist/orchestrators/runtime-composition.d.mts +1 -1
- package/dist/orchestrators/runtime-composition.mjs +123 -39
- package/dist/orchestrators/runtime-composition.mjs.map +1 -1
- package/dist/orchestrators/snapshot/capture-command.d.mts +1 -0
- package/dist/orchestrators/snapshot/capture-command.mjs +25 -0
- package/dist/orchestrators/snapshot/capture-command.mjs.map +1 -0
- package/dist/orchestrators/snapshot/capture.mjs +42 -28
- package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
- package/dist/orchestrators/snapshot/descriptor.mjs +35 -10
- package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
- package/dist/orchestrators/snapshot/identity-guard.mjs +1 -1
- package/dist/orchestrators/snapshot/index.mjs +13 -0
- package/dist/orchestrators/snapshot/integrity.d.mts +1 -1
- package/dist/orchestrators/snapshot/integrity.mjs +73 -17
- package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
- package/dist/orchestrators/snapshot/pending-marker.d.mts +1 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs +99 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs.map +1 -0
- package/dist/orchestrators/snapshot/phase-error.mjs +23 -0
- package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -0
- package/dist/orchestrators/snapshot/prune.mjs +20 -55
- package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
- package/dist/orchestrators/snapshot/recover-pending.d.mts +1 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs +223 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs.map +1 -0
- package/dist/orchestrators/snapshot/restore.mjs +118 -84
- package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
- package/dist/orchestrators/snapshot/service.mjs +53 -56
- package/dist/orchestrators/snapshot/service.mjs.map +1 -1
- package/dist/orchestrators/snapshot/state-document.d.mts +1 -0
- package/dist/orchestrators/snapshot/state-document.mjs +47 -7
- package/dist/orchestrators/snapshot/state-document.mjs.map +1 -1
- package/dist/orchestrators/snapshot/wipe.mjs +67 -10
- package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
- package/dist/plugins/account/codegen.mjs +9 -8
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/errors.d.mts +33 -6
- package/dist/plugins/account/errors.mjs.map +1 -1
- package/dist/plugins/account/funding.d.mts +29 -19
- package/dist/plugins/account/funding.mjs +84 -66
- package/dist/plugins/account/funding.mjs.map +1 -1
- package/dist/plugins/account/index.d.mts +2 -4
- package/dist/plugins/account/index.mjs +64 -31
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/account/keypair.mjs +6 -9
- package/dist/plugins/account/keypair.mjs.map +1 -1
- package/dist/plugins/account/lease.mjs +1 -0
- package/dist/plugins/account/lease.mjs.map +1 -1
- package/dist/plugins/account/registry.d.mts +14 -1
- package/dist/plugins/account/registry.mjs +18 -18
- package/dist/plugins/account/registry.mjs.map +1 -1
- package/dist/plugins/account/service.d.mts +23 -4
- package/dist/plugins/account/service.mjs +83 -45
- package/dist/plugins/account/service.mjs.map +1 -1
- package/dist/plugins/account/snapshot.mjs +2 -5
- package/dist/plugins/account/snapshot.mjs.map +1 -1
- package/dist/plugins/account/spans.mjs +16 -0
- package/dist/plugins/account/spans.mjs.map +1 -0
- package/dist/plugins/account/variants/keystore.mjs +6 -8
- package/dist/plugins/account/variants/keystore.mjs.map +1 -1
- package/dist/plugins/action/build-context.d.mts +3 -2
- package/dist/plugins/action/errors.d.mts +16 -12
- package/dist/plugins/action/errors.mjs.map +1 -1
- package/dist/plugins/action/execute.mjs +65 -103
- package/dist/plugins/action/execute.mjs.map +1 -1
- package/dist/plugins/action/index.d.mts +0 -2
- package/dist/plugins/action/index.mjs +17 -13
- package/dist/plugins/action/index.mjs.map +1 -1
- package/dist/plugins/action/service.mjs +38 -35
- package/dist/plugins/action/service.mjs.map +1 -1
- package/dist/plugins/action/spans.mjs +11 -0
- package/dist/plugins/action/spans.mjs.map +1 -0
- package/dist/plugins/coin/codegen.mjs +9 -8
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/discovery.mjs +8 -4
- package/dist/plugins/coin/discovery.mjs.map +1 -1
- package/dist/plugins/coin/index.d.mts +11 -29
- package/dist/plugins/coin/index.mjs +56 -27
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/coin/metadata.mjs +8 -15
- package/dist/plugins/coin/metadata.mjs.map +1 -1
- package/dist/plugins/coin/mint.d.mts +30 -11
- package/dist/plugins/coin/mint.mjs +78 -74
- package/dist/plugins/coin/mint.mjs.map +1 -1
- package/dist/plugins/coin/registry.mjs +4 -7
- package/dist/plugins/coin/registry.mjs.map +1 -1
- package/dist/plugins/coin/service.d.mts +39 -1
- package/dist/plugins/coin/service.mjs +11 -4
- package/dist/plugins/coin/service.mjs.map +1 -1
- package/dist/plugins/coin/spans.mjs +20 -0
- package/dist/plugins/coin/spans.mjs.map +1 -0
- package/dist/plugins/dashboard/domain.mjs +402 -0
- package/dist/plugins/dashboard/domain.mjs.map +1 -0
- package/dist/plugins/dashboard/index.d.mts +29 -0
- package/dist/plugins/dashboard/index.mjs +91 -0
- package/dist/plugins/dashboard/index.mjs.map +1 -0
- package/dist/plugins/dashboard/origin-policy.mjs +36 -0
- package/dist/plugins/dashboard/origin-policy.mjs.map +1 -0
- package/dist/plugins/dashboard/routable.mjs +27 -0
- package/dist/plugins/dashboard/routable.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/builder.mjs +21 -0
- package/dist/plugins/dashboard/schema/builder.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/enums.mjs +72 -0
- package/dist/plugins/dashboard/schema/enums.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/root.mjs +351 -0
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/types.mjs +508 -0
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -0
- package/dist/plugins/dashboard/schema.mjs +11 -0
- package/dist/plugins/dashboard/schema.mjs.map +1 -0
- package/dist/plugins/dashboard/server.mjs +166 -0
- package/dist/plugins/dashboard/server.mjs.map +1 -0
- package/dist/plugins/deepbook/deploy.mjs +53 -115
- package/dist/plugins/deepbook/deploy.mjs.map +1 -1
- package/dist/plugins/deepbook/errors.mjs +1 -0
- package/dist/plugins/deepbook/errors.mjs.map +1 -1
- package/dist/plugins/deepbook/faucet-strategy.mjs +47 -34
- package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/deepbook/hash.mjs +9 -0
- package/dist/plugins/deepbook/hash.mjs.map +1 -0
- package/dist/plugins/deepbook/index.d.mts +1 -10
- package/dist/plugins/deepbook/index.mjs +25 -22
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/deepbook/pyth/index.mjs +26 -55
- package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
- package/dist/plugins/deepbook/snapshot.mjs +17 -29
- package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
- package/dist/plugins/deepbook/spans.mjs +18 -0
- package/dist/plugins/deepbook/spans.mjs.map +1 -0
- package/dist/plugins/deepbook/type-strings.mjs +65 -0
- package/dist/plugins/deepbook/type-strings.mjs.map +1 -0
- package/dist/plugins/deepbook/types.d.mts +2 -3
- package/dist/plugins/deepbook/types.mjs.map +1 -1
- package/dist/plugins/faucet/dispatcher.d.mts +21 -2
- package/dist/plugins/faucet/dispatcher.mjs +1 -2
- package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
- package/dist/plugins/faucet/errors.d.mts +11 -24
- package/dist/plugins/faucet/errors.mjs.map +1 -1
- package/dist/plugins/faucet/http.mjs +33 -14
- package/dist/plugins/faucet/http.mjs.map +1 -1
- package/dist/plugins/faucet/index.d.mts +15 -5
- package/dist/plugins/faucet/index.mjs +3 -0
- package/dist/plugins/faucet/index.mjs.map +1 -1
- package/dist/plugins/faucet/spans.mjs +12 -0
- package/dist/plugins/faucet/spans.mjs.map +1 -0
- package/dist/plugins/host-service/errors.d.mts +1 -1
- package/dist/plugins/host-service/index.mjs +34 -8
- package/dist/plugins/host-service/index.mjs.map +1 -1
- package/dist/plugins/host-service/routable.mjs +2 -1
- package/dist/plugins/host-service/routable.mjs.map +1 -1
- package/dist/plugins/host-service/service.d.mts +21 -0
- package/dist/plugins/host-service/service.mjs +136 -81
- package/dist/plugins/host-service/service.mjs.map +1 -1
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs +23 -0
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -0
- package/dist/plugins/internal/codegen-helpers.mjs +18 -0
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -0
- package/dist/plugins/internal/funding-failure-error.mjs +32 -0
- package/dist/plugins/internal/funding-failure-error.mjs.map +1 -0
- package/dist/plugins/package/build.mjs +1 -1
- package/dist/plugins/package/build.mjs.map +1 -1
- package/dist/plugins/package/codegen.mjs +26 -0
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/errors.d.mts +16 -6
- package/dist/plugins/package/errors.mjs.map +1 -1
- package/dist/plugins/package/index.d.mts +0 -4
- package/dist/plugins/package/index.mjs +27 -21
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/package/mode-known.mjs +26 -12
- package/dist/plugins/package/mode-known.mjs.map +1 -1
- package/dist/plugins/package/mode-local.mjs +47 -41
- package/dist/plugins/package/mode-local.mjs.map +1 -1
- package/dist/plugins/package/publish-executor.mjs +55 -114
- package/dist/plugins/package/publish-executor.mjs.map +1 -1
- package/dist/plugins/package/registry.mjs +2 -1
- package/dist/plugins/package/registry.mjs.map +1 -1
- package/dist/plugins/package/service.mjs.map +1 -1
- package/dist/plugins/package/spans.mjs +14 -0
- package/dist/plugins/package/spans.mjs.map +1 -0
- package/dist/plugins/postgres/db-ensure.mjs +19 -12
- package/dist/plugins/postgres/db-ensure.mjs.map +1 -1
- package/dist/plugins/postgres/errors.d.mts +5 -0
- package/dist/plugins/postgres/errors.mjs.map +1 -1
- package/dist/plugins/postgres/index.mjs +10 -17
- package/dist/plugins/postgres/index.mjs.map +1 -1
- package/dist/plugins/postgres/service.mjs +58 -24
- package/dist/plugins/postgres/service.mjs.map +1 -1
- package/dist/plugins/postgres/snapshot.mjs.map +1 -1
- package/dist/plugins/postgres/spans.mjs +11 -0
- package/dist/plugins/postgres/spans.mjs.map +1 -0
- package/dist/plugins/router-entrypoints.mjs +4 -4
- package/dist/plugins/router-entrypoints.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +15 -13
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +15 -19
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
- package/dist/plugins/seal/codegen.d.mts +2 -3
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/config-render.mjs +35 -8
- package/dist/plugins/seal/config-render.mjs.map +1 -1
- package/dist/plugins/seal/deploy.mjs +31 -39
- package/dist/plugins/seal/deploy.mjs.map +1 -1
- package/dist/plugins/seal/errors.d.mts +1 -3
- package/dist/plugins/seal/errors.mjs +7 -1
- package/dist/plugins/seal/errors.mjs.map +1 -1
- package/dist/plugins/seal/index.d.mts +1 -6
- package/dist/plugins/seal/index.mjs +40 -14
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/seal/key-manager.d.mts +1 -9
- package/dist/plugins/seal/key-manager.mjs +2 -18
- package/dist/plugins/seal/key-manager.mjs.map +1 -1
- package/dist/plugins/seal/key-server.mjs +37 -36
- package/dist/plugins/seal/key-server.mjs.map +1 -1
- package/dist/plugins/seal/keygen.mjs +16 -17
- package/dist/plugins/seal/keygen.mjs.map +1 -1
- package/dist/plugins/seal/mode/fork-known.mjs +36 -14
- package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
- package/dist/plugins/seal/mode/live.d.mts +6 -4
- package/dist/plugins/seal/mode/live.mjs +14 -21
- package/dist/plugins/seal/mode/live.mjs.map +1 -1
- package/dist/plugins/seal/mode/local-keygen.mjs +57 -21
- package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
- package/dist/plugins/seal/registry-publish.mjs +1 -0
- 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/spans.mjs +18 -0
- package/dist/plugins/seal/spans.mjs.map +1 -0
- package/dist/plugins/sui/auto-tick.mjs +17 -23
- package/dist/plugins/sui/auto-tick.mjs.map +1 -1
- package/dist/plugins/sui/chain-build-container.mjs +18 -0
- package/dist/plugins/sui/chain-build-container.mjs.map +1 -0
- package/dist/plugins/sui/chain-probe.d.mts +5 -5
- package/dist/plugins/sui/chain-probe.mjs +28 -58
- package/dist/plugins/sui/chain-probe.mjs.map +1 -1
- package/dist/plugins/sui/codegen.mjs +26 -0
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/errors.d.mts +2 -29
- package/dist/plugins/sui/errors.mjs +1 -3
- package/dist/plugins/sui/errors.mjs.map +1 -1
- package/dist/plugins/sui/fork-faucet-strategy.d.mts +1 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs +55 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/fork-orchestration.d.mts +1 -0
- package/dist/plugins/sui/fork-orchestration.mjs +170 -2
- package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
- package/dist/plugins/sui/fork-transaction.d.mts +2 -0
- package/dist/plugins/sui/fork-transaction.mjs +92 -28
- package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +33 -70
- package/dist/plugins/sui/index.mjs +58 -35
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/plugins/{faucet/strategies/sui-local.mjs → sui/local-faucet-strategy.mjs} +10 -7
- package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/mode/external.mjs +7 -13
- package/dist/plugins/sui/mode/external.mjs.map +1 -1
- package/dist/plugins/sui/mode/fork.mjs +136 -59
- package/dist/plugins/sui/mode/fork.mjs.map +1 -1
- package/dist/plugins/sui/mode/live.mjs +10 -16
- package/dist/plugins/sui/mode/live.mjs.map +1 -1
- package/dist/plugins/sui/mode/local.mjs +37 -36
- package/dist/plugins/sui/mode/local.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared-boot.mjs +38 -115
- package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared.d.mts +1 -5
- package/dist/plugins/sui/mode/shared.mjs.map +1 -1
- package/dist/plugins/sui/mode/spec.d.mts +18 -0
- package/dist/plugins/sui/move-summary-runner.mjs +207 -0
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -0
- package/dist/plugins/sui/network-resolver.d.mts +4 -3
- package/dist/plugins/sui/service.mjs.map +1 -1
- package/dist/plugins/sui/snapshot.mjs +3 -0
- package/dist/plugins/sui/snapshot.mjs.map +1 -1
- package/dist/plugins/sui/spans.mjs +17 -0
- package/dist/plugins/sui/spans.mjs.map +1 -0
- package/dist/plugins/wallet/codegen.d.mts +0 -1
- package/dist/plugins/wallet/codegen.mjs +8 -9
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +6 -8
- package/dist/plugins/wallet/index.mjs +46 -35
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/origin-policy.mjs +12 -28
- package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
- package/dist/plugins/wallet/pairing.mjs +6 -4
- package/dist/plugins/wallet/pairing.mjs.map +1 -1
- package/dist/plugins/wallet/protocol.d.mts +1 -0
- package/dist/plugins/wallet/protocol.mjs +5 -44
- package/dist/plugins/wallet/protocol.mjs.map +1 -1
- package/dist/plugins/wallet/routable.mjs +2 -8
- package/dist/plugins/wallet/routable.mjs.map +1 -1
- package/dist/plugins/wallet/server.mjs +36 -44
- package/dist/plugins/wallet/server.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +1 -5
- package/dist/plugins/wallet/service.mjs +22 -18
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/wallet/spans.mjs +22 -0
- package/dist/plugins/wallet/spans.mjs.map +1 -0
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +33 -8
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.d.mts +3 -3
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/deploy-paths.mjs +21 -5
- package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
- package/dist/plugins/walrus/deploy.mjs +67 -69
- package/dist/plugins/walrus/deploy.mjs.map +1 -1
- package/dist/plugins/walrus/errors.mjs +1 -0
- package/dist/plugins/walrus/errors.mjs.map +1 -1
- package/dist/plugins/walrus/faucet-strategy.mjs +12 -7
- package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/walrus/index.d.mts +2 -13
- package/dist/plugins/walrus/index.mjs +18 -23
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/plugins/walrus/mode/known-deploy.mjs +7 -5
- package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
- package/dist/plugins/walrus/mode/local-cluster.mjs +26 -7
- package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
- package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
- package/dist/plugins/walrus/routable.mjs +7 -23
- package/dist/plugins/walrus/routable.mjs.map +1 -1
- package/dist/plugins/walrus/service.mjs.map +1 -1
- package/dist/plugins/walrus/spans.mjs +18 -0
- package/dist/plugins/walrus/spans.mjs.map +1 -0
- package/dist/plugins/walrus/storage-nodes.d.mts +6 -2
- package/dist/plugins/walrus/storage-nodes.mjs +15 -8
- package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
- package/dist/plugins/walrus/wal-swap.mjs +58 -15
- package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
- package/dist/primitives/artifact-publisher.d.mts +1 -1
- package/dist/primitives/artifact-publisher.mjs +15 -0
- package/dist/primitives/artifact-publisher.mjs.map +1 -0
- package/dist/runtime/docker/client.mjs +17 -4
- package/dist/runtime/docker/client.mjs.map +1 -1
- package/dist/runtime/docker/container.mjs +219 -132
- package/dist/runtime/docker/container.mjs.map +1 -1
- package/dist/runtime/docker/errors.mjs +0 -6
- package/dist/runtime/docker/errors.mjs.map +1 -1
- package/dist/runtime/docker/exec.mjs +21 -18
- package/dist/runtime/docker/exec.mjs.map +1 -1
- package/dist/runtime/docker/image.mjs +36 -13
- package/dist/runtime/docker/image.mjs.map +1 -1
- package/dist/runtime/docker/index.mjs +14 -0
- package/dist/runtime/docker/inspect-and-decode.mjs +51 -0
- package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -0
- package/dist/runtime/docker/inventory.mjs +14 -11
- package/dist/runtime/docker/inventory.mjs.map +1 -1
- package/dist/runtime/docker/labels.mjs +38 -5
- package/dist/runtime/docker/labels.mjs.map +1 -1
- package/dist/runtime/docker/logs.d.mts +1 -1
- package/dist/runtime/docker/logs.mjs.map +1 -1
- package/dist/runtime/docker/network.mjs +83 -47
- package/dist/runtime/docker/network.mjs.map +1 -1
- package/dist/runtime/docker/render-run-args.mjs +82 -0
- package/dist/runtime/docker/render-run-args.mjs.map +1 -0
- package/dist/runtime/docker/service.d.mts +1 -1
- package/dist/runtime/docker/service.mjs +12 -7
- package/dist/runtime/docker/service.mjs.map +1 -1
- package/dist/runtime/docker/sweep.mjs +118 -43
- package/dist/runtime/docker/sweep.mjs.map +1 -1
- package/dist/runtime/docker/volume.mjs +2 -0
- package/dist/runtime/docker/volume.mjs.map +1 -1
- package/dist/runtime/docker/wrap.mjs +30 -1
- package/dist/runtime/docker/wrap.mjs.map +1 -1
- package/dist/substrate/cross-process.mjs +14 -8
- package/dist/substrate/cross-process.mjs.map +1 -1
- package/dist/substrate/event-time.mjs +33 -0
- package/dist/substrate/event-time.mjs.map +1 -0
- package/dist/substrate/events.d.mts +28 -8
- package/dist/substrate/identity.d.mts +2 -1
- package/dist/substrate/manifest.d.mts +68 -5
- package/dist/substrate/manifest.mjs +34 -5
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/network.d.mts +3 -5
- package/dist/substrate/options.d.mts +0 -2
- package/dist/substrate/plugin.d.mts +13 -0
- package/dist/substrate/plugin.mjs +4 -2
- package/dist/substrate/plugin.mjs.map +1 -1
- package/dist/substrate/projection.d.mts +35 -3
- package/dist/substrate/runtime/artifact-publisher/index.mjs +19 -9
- package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -1
- package/dist/substrate/runtime/atomic-write.mjs +97 -32
- package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
- package/dist/substrate/runtime/cache/index.mjs +3 -0
- package/dist/substrate/runtime/cache/schema.mjs +2 -2
- package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
- package/dist/substrate/runtime/cache/service.mjs +9 -7
- package/dist/substrate/runtime/cache/service.mjs.map +1 -1
- package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -1
- package/dist/substrate/runtime/capability-sinks/index.mjs +3 -0
- package/dist/substrate/runtime/capability-sinks/layer.mjs +1 -1
- package/dist/substrate/runtime/capability-sinks/service.d.mts +61 -2
- package/dist/substrate/runtime/capability-sinks/service.mjs +21 -26
- package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -1
- package/dist/substrate/runtime/config-validation.d.mts +1 -13
- package/dist/substrate/runtime/config-validation.mjs +2 -91
- package/dist/substrate/runtime/config-validation.mjs.map +1 -1
- package/dist/substrate/runtime/container-runtime.d.mts +1 -0
- package/dist/substrate/runtime/container-runtime.mjs +2 -0
- package/dist/substrate/runtime/control-plane/domain.mjs +101 -0
- package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -0
- package/dist/substrate/runtime/control-plane/service.mjs +7 -0
- package/dist/substrate/runtime/control-plane/service.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +46 -19
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +30 -12
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/index.mjs +5 -0
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +11 -2
- 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 +1 -1
- package/dist/substrate/runtime/cross-process/index.mjs +11 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs +34 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/liveness.mjs +52 -10
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/lock.d.mts +1 -0
- package/dist/substrate/runtime/cross-process/lock.mjs +23 -0
- package/dist/substrate/runtime/cross-process/lock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +64 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/roster.mjs +97 -83
- package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/self-pid.mjs +8 -0
- package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +24 -28
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/stack-lock.mjs +41 -20
- package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
- package/dist/substrate/runtime/current-plugin.mjs +2 -2
- package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
- package/dist/substrate/runtime/errors.mjs +12 -6
- package/dist/substrate/runtime/errors.mjs.map +1 -1
- package/dist/substrate/runtime/format-unknown-error.mjs +30 -0
- package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs +10 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -0
- package/dist/substrate/runtime/host-gateway.mjs +20 -0
- package/dist/substrate/runtime/host-gateway.mjs.map +1 -0
- package/dist/substrate/runtime/host-tree-tar/index.mjs +61 -50
- package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
- package/dist/substrate/runtime/http-probe.d.mts +1 -1
- package/dist/substrate/runtime/index.mjs +14 -0
- package/dist/substrate/runtime/lease-broker/index.d.mts +1 -1
- package/dist/substrate/runtime/lease-broker/index.mjs +2 -0
- package/dist/substrate/runtime/lease-broker/service.d.mts +1 -64
- package/dist/substrate/runtime/lease-broker/service.mjs +1 -1
- package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs +22 -3
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/index.mjs +9 -0
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +20 -3
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs +5 -5
- package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/state-machine.mjs +1 -1
- package/dist/substrate/runtime/managed-container.d.mts +19 -1
- package/dist/substrate/runtime/managed-container.mjs +20 -1
- package/dist/substrate/runtime/managed-container.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/index.mjs +3 -0
- package/dist/substrate/runtime/manifest/manifest.mjs +15 -11
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/mode-errors.mjs +20 -0
- package/dist/substrate/runtime/mode-errors.mjs.map +1 -0
- package/dist/substrate/runtime/observability/cascade-formatter.mjs +9 -13
- package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
- package/dist/substrate/runtime/observability/formatter-registry.mjs +19 -36
- package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -1
- package/dist/substrate/runtime/observability/ignore-with-log.d.mts +1 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs +17 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -0
- package/dist/substrate/runtime/observability/index.d.mts +1 -1
- package/dist/substrate/runtime/observability/index.mjs +13 -0
- package/dist/substrate/runtime/observability/log-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/log-store.mjs +175 -0
- package/dist/substrate/runtime/observability/log-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/logger.d.mts +2 -1
- package/dist/substrate/runtime/observability/logger.mjs +5 -9
- package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
- package/dist/substrate/runtime/observability/output-truncate.mjs +35 -0
- package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -0
- package/dist/substrate/runtime/observability/pretty-error.mjs +9 -12
- package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
- package/dist/substrate/runtime/observability/redaction.d.mts +2 -13
- package/dist/substrate/runtime/observability/redaction.mjs +8 -14
- package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
- package/dist/substrate/runtime/observability/span-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/span-store.mjs +110 -0
- package/dist/substrate/runtime/observability/span-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/spans.mjs +14 -14
- package/dist/substrate/runtime/observability/spans.mjs.map +1 -1
- package/dist/substrate/runtime/observability/subprocess-capture.mjs +1 -1
- package/dist/substrate/runtime/passthrough-or-wrap.mjs +33 -0
- package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -0
- package/dist/substrate/runtime/paths.d.mts +1 -1
- package/dist/substrate/runtime/paths.mjs +4 -3
- package/dist/substrate/runtime/paths.mjs.map +1 -1
- package/dist/substrate/runtime/phase-preserving-produce.mjs +40 -0
- package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -0
- package/dist/substrate/runtime/port-broker/index.mjs +3 -0
- package/dist/substrate/runtime/port-broker/service.mjs +170 -126
- package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/probes.d.mts +7 -5
- package/dist/substrate/runtime/probes.mjs +3 -1
- package/dist/substrate/runtime/probes.mjs.map +1 -1
- package/dist/substrate/runtime/projection/index.mjs +4 -0
- package/dist/substrate/runtime/projection/operational-endpoints.mjs +1 -2
- package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
- package/dist/substrate/runtime/projection/persisted.mjs +33 -15
- package/dist/substrate/runtime/projection/persisted.mjs.map +1 -1
- package/dist/substrate/runtime/projection/state-ref.mjs +26 -2
- package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
- package/dist/substrate/runtime/projection/update.mjs +88 -24
- package/dist/substrate/runtime/projection/update.mjs.map +1 -1
- package/dist/substrate/runtime/random-suffix.mjs +11 -0
- package/dist/substrate/runtime/random-suffix.mjs.map +1 -0
- package/dist/substrate/runtime/retry-policy.d.mts +59 -1
- package/dist/substrate/runtime/retry-policy.mjs +66 -1
- package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
- package/dist/substrate/runtime/routed-url.d.mts +1 -0
- package/dist/substrate/runtime/routed-url.mjs +79 -0
- package/dist/substrate/runtime/routed-url.mjs.map +1 -0
- package/dist/substrate/runtime/runtime-decode.d.mts +1 -1
- package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-http-server.mjs +2 -3
- package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-multimap/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs +52 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs.map +1 -0
- package/dist/substrate/runtime/scoped-ref-map/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-ref-map/service.mjs +2 -2
- package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -1
- package/dist/substrate/runtime/stage-and-swap/index.mjs +72 -4
- package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/index.d.mts +1 -0
- package/dist/substrate/runtime/state-store/index.mjs +3 -0
- package/dist/substrate/runtime/state-store/schema.d.mts +1 -0
- package/dist/substrate/runtime/state-store/schema.mjs +19 -14
- package/dist/substrate/runtime/state-store/schema.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/service.d.mts +1 -0
- package/dist/substrate/runtime/state-store/service.mjs +145 -0
- package/dist/substrate/runtime/state-store/service.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs +33 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/index.mjs +4 -0
- package/dist/substrate/runtime/strategy-registry/service.mjs +19 -33
- package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
- package/dist/substrate/runtime/subnet-broker.mjs +60 -0
- package/dist/substrate/runtime/subnet-broker.mjs.map +1 -0
- package/dist/substrate/runtime/sui-execute/index.d.mts +21 -1
- package/dist/substrate/runtime/sui-execute/index.mjs +84 -20
- package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -1
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.d.mts +1 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs +32 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +1 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs +32 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +1 -0
- package/dist/substrate/runtime/sui-move-build/index.mjs +93 -19
- package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/acquire-node.mjs +181 -0
- package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs +144 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs +68 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +151 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/errors.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/errors.mjs +9 -0
- package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/index.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/index.mjs +3 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs +51 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +250 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/state.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/state.mjs +22 -0
- package/dist/substrate/runtime/supervisor/state.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs +57 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/types.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs +133 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -0
- package/dist/substrate/runtime/typed-env.mjs +8 -0
- package/dist/substrate/runtime/typed-env.mjs.map +1 -0
- package/dist/substrate/state-store.d.mts +1 -0
- package/dist/substrate/versioned-doc-schema.mjs +17 -0
- package/dist/substrate/versioned-doc-schema.mjs.map +1 -0
- package/dist/substrate/versioned-doc-sync.mjs +94 -0
- package/dist/substrate/versioned-doc-sync.mjs.map +1 -0
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/commands/index.mjs +9 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs +13 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -0
- package/dist/surfaces/cli/commands/prune-picker.mjs +3 -2
- package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune.mjs +34 -17
- package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
- package/dist/surfaces/cli/commands/status.mjs +2 -2
- package/dist/surfaces/cli/commands/status.mjs.map +1 -1
- package/dist/surfaces/cli/commands/supervisor-presence.mjs +5 -3
- package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
- package/dist/surfaces/cli/commands/wipe.mjs +38 -4
- package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
- package/dist/surfaces/cli/errors.mjs +1 -1
- package/dist/surfaces/cli/errors.mjs.map +1 -1
- package/dist/surfaces/cli/flags.mjs +0 -1
- package/dist/surfaces/cli/flags.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +98 -18
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/cli/output.mjs +1 -0
- package/dist/surfaces/cli/output.mjs.map +1 -1
- package/dist/surfaces/cli/sysexits.mjs +2 -1
- package/dist/surfaces/cli/sysexits.mjs.map +1 -1
- package/dist/surfaces/tui/app.mjs +25 -3
- package/dist/surfaces/tui/app.mjs.map +1 -1
- package/dist/surfaces/tui/display-derivation.mjs +23 -74
- package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
- package/dist/surfaces/tui/event-log.mjs +35 -23
- package/dist/surfaces/tui/event-log.mjs.map +1 -1
- package/dist/surfaces/tui/input.mjs +5 -1
- package/dist/surfaces/tui/input.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs +70 -34
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/package.json +24 -4
- package/dist/contracts/liveness-classifier.d.mts +0 -19
- package/dist/contracts/network-resolver.d.mts +0 -15
- package/dist/contracts/network-resolver.mjs +0 -7
- package/dist/contracts/network-resolver.mjs.map +0 -1
- package/dist/orchestrators/codegen/extras.mjs +0 -16
- package/dist/orchestrators/codegen/extras.mjs.map +0 -1
- package/dist/plugins/deepbook/routable.mjs +0 -21
- package/dist/plugins/deepbook/routable.mjs.map +0 -1
- package/dist/plugins/faucet/service.d.mts +0 -20
- package/dist/plugins/faucet/strategies/sui-local.d.mts +0 -23
- package/dist/plugins/faucet/strategies/sui-local.mjs.map +0 -1
- package/dist/plugins/sui/seed-objects.d.mts +0 -18
- package/dist/plugins/sui/seed-objects.mjs +0 -25
- package/dist/plugins/sui/seed-objects.mjs.map +0 -1
- package/dist/runtime/built-in-plugin-layers.mjs.map +0 -1
- package/dist/substrate/runtime/context-helpers.mjs +0 -32
- package/dist/substrate/runtime/context-helpers.mjs.map +0 -1
- package/dist/substrate/runtime/run.mjs.map +0 -1
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +0 -30
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +0 -1
- package/dist/substrate/runtime/supervisor.d.mts +0 -1
- package/dist/substrate/runtime/supervisor.mjs +0 -831
- package/dist/substrate/runtime/supervisor.mjs.map +0 -1
- package/dist/surfaces/cli/commands/doctor-probes.mjs.map +0 -1
- /package/dist/{substrate/runtime/strategy-registry/faucet-capability-for.d.mts → plugins/faucet/http.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.mjs","names":[],"sources":["../../../src/plugins/coin/metadata.ts"],"sourcesContent":["// CoinMetadata fetch + soft-degradation.\n//\n// Distilled-doc 13-coin.md Invariant 8: `getCoinMetadata` failures\n// degrade, do not throw. A timeout or RPC error after one retry\n// returns `null` (logged as a warning); the discovery pipeline keeps\n// going. The next supervisor cycle picks the missing record up.\n//\n// Per-attempt timeout 5s, ONE retry at 250ms backoff (matches the v3\n// `RETRY_SCHEDULE` exactly — distilled-doc 13-coin.md §Configuration).\n//\n// In-process per-Layer-invocation cache keyed by fullCoinType. The\n// fullCoinType folds the packageId, so a fresh chain (new genesis)\n// means new packageIds, which means the cache misses naturally —\n// persistence across restart is unnecessary.\n\nimport { Effect, Ref, Schema } from 'effect';\n\nimport { decodeUnknown } from '../../substrate/runtime/runtime-decode.ts';\nimport { SpanAttr } from '../../substrate/runtime/observability/spans.ts';\nimport { makeSpacedRetrySchedule } from '../../substrate/runtime/retry-policy.ts';\nimport { coinError, type CoinError } from './errors.ts';\n\n/** Per-attempt timeout (5 seconds) — distilled-doc invariant. */\nexport const METADATA_FETCH_TIMEOUT_MS = 5_000;\n\n/** Retry schedule — ONE retry at 250ms backoff. Matches the v3\n * `RETRY_SCHEDULE` (250ms spaced, bounded to one retry). */\nexport const METADATA_RETRY_SCHEDULE = makeSpacedRetrySchedule(250, 1);\n\n/** On-chain CoinMetadata projection — narrowed to the columns the\n * registry needs. The SDK's full shape carries more (description,\n * raw bytes); we don't.\n *\n * IMPORTANT (chain-probe schema constraint from the last sweep):\n * this Schema MUST NOT depend on any services. `Schema.Schema<T>` is\n * parameterized `<Type, Encoded, R, RD>`; we constrain `R` and `RD`\n * to `never` via `Schema.Codec<T, unknown, never, never>` at the\n * consumer boundary, but the schema literal itself uses ONLY\n * service-free combinators (`Schema.String`, `Schema.Number`,\n * `Schema.optional`). */\nexport const OnchainCoinMetadataShape = Schema.Struct({\n\tid: Schema.String,\n\tdecimals: Schema.Number,\n\tname: Schema.String,\n\tsymbol: Schema.String,\n\tdescription: Schema.optional(Schema.String),\n\ticonUrl: Schema.optional(Schema.String),\n});\n\nexport type OnchainCoinMetadata = typeof OnchainCoinMetadataShape.Type;\n\n/** SDK shim — the surface the discovery pass calls. The Sui plugin's\n * resolved client exposes this via `sdk.core.getCoinMetadata`. Kept\n * narrow (no `@mysten/sui` type import) so this module stays\n * layering-neutral; the consumer hands in the resolved client. */\nexport interface MetadataSdkShim {\n\treadonly core: {\n\t\treadonly getCoinMetadata: (args: { readonly coinType: string }) => Promise<unknown>;\n\t};\n}\n\n/** Per-Layer-invocation cache. `null` means \"we tried and the RPC\n * said the coin had no CoinMetadata\"; `undefined` means \"we haven't\n * asked yet\". */\nexport interface CoinMetadataCache {\n\treadonly get: (fullCoinType: string) => Effect.Effect<OnchainCoinMetadata | null | undefined>;\n\treadonly put: (fullCoinType: string, value: OnchainCoinMetadata | null) => Effect.Effect<void>;\n}\n\n/** Build an empty cache. */\nexport const makeCoinMetadataCache = (): Effect.Effect<CoinMetadataCache> =>\n\tEffect.gen(function* () {\n\t\tconst ref = yield* Ref.make<Record<string, OnchainCoinMetadata | null>>({});\n\t\treturn {\n\t\t\tget: (fullCoinType) =>\n\t\t\t\tRef.get(ref).pipe(Effect.map((m) => (fullCoinType in m ? m[fullCoinType] : undefined))),\n\t\t\tput: (fullCoinType, value) => Ref.update(ref, (m) => ({ ...m, [fullCoinType]: value })),\n\t\t};\n\t});\n\n/** Fetch CoinMetadata for one coin type. Soft-degrades on RPC\n * failure / timeout: returns `null` after the retry budget is\n * exhausted, AND logs a warning.\n *\n * Distilled-doc 13-coin.md Invariant 8: this is intentional. The\n * publish-discovery pass must not fail the whole supervisor cycle on\n * a flaky RPC blip. */\nexport const fetchCoinMetadataOnce = (\n\tsdk: MetadataSdkShim,\n\tfullCoinType: string,\n): Effect.Effect<OnchainCoinMetadata | null> =>\n\tEffect.gen(function* () {\n\t\tconst raw: unknown = yield* Effect.tryPromise({\n\t\t\ttry: () => sdk.core.getCoinMetadata({ coinType: fullCoinType }),\n\t\t\tcatch: (cause): { readonly _tag: 'rpc'; readonly cause: unknown } => ({\n\t\t\t\t_tag: 'rpc',\n\t\t\t\tcause,\n\t\t\t}),\n\t\t}).pipe(\n\t\t\t// Effect v4: `timeoutOrElse` (not `timeoutFail`). The\n\t\t\t// `orElse` branch is the new value (Effect), not just an\n\t\t\t// error constructor — we surface a tagged failure that the\n\t\t\t// downstream `Effect.catch` swallows into `null`.\n\t\t\tEffect.timeoutOrElse({\n\t\t\t\tduration: `${METADATA_FETCH_TIMEOUT_MS} millis`,\n\t\t\t\torElse: () => Effect.fail({ _tag: 'rpc' as const, cause: 'timeout' }),\n\t\t\t}),\n\t\t\tEffect.retry(METADATA_RETRY_SCHEDULE),\n\t\t\tEffect.catch((err): Effect.Effect<unknown> => {\n\t\t\t\treturn Effect.logWarning('coin metadata fetch failed; soft-degrading to null').pipe(\n\t\t\t\t\tEffect.annotateLogs({\n\t\t\t\t\t\t[SpanAttr.coinType]: fullCoinType,\n\t\t\t\t\t\t[SpanAttr.errorCause]: stringifyCause(err.cause),\n\t\t\t\t\t}),\n\t\t\t\t\tEffect.as(null),\n\t\t\t\t);\n\t\t\t}),\n\t\t);\n\t\tif (raw === null || raw === undefined) return null;\n\t\treturn yield* decodeUnknown(OnchainCoinMetadataShape, raw, {\n\t\t\tsource: 'coin metadata RPC response',\n\t\t\tmkError: (issue) => issue,\n\t\t}).pipe(\n\t\t\tEffect.catch((issue) =>\n\t\t\t\tEffect.logWarning(\n\t\t\t\t\t'coin metadata response had non-conforming shape; degrading to null',\n\t\t\t\t).pipe(\n\t\t\t\t\tEffect.annotateLogs({\n\t\t\t\t\t\t[SpanAttr.coinType]: fullCoinType,\n\t\t\t\t\t\t[SpanAttr.errorCause]: stringifyCause(issue.cause ?? issue),\n\t\t\t\t\t}),\n\t\t\t\t\tEffect.as(null as OnchainCoinMetadata | null),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}).pipe(Effect.withSpan('coin.metadata.fetch', { attributes: { fullCoinType } }));\n\n/** Batch-fetch with cache. Each fullCoinType is asked at most once\n * per Layer-invocation. The fetches run concurrently — distilled-doc\n * opportunity (\"Coin discovery is naturally batchable\"). */\nexport const fetchCoinMetadataMany = (\n\tsdk: MetadataSdkShim,\n\tfullCoinTypes: ReadonlyArray<string>,\n\tcache: CoinMetadataCache,\n): Effect.Effect<ReadonlyMap<string, OnchainCoinMetadata | null>> =>\n\tEffect.gen(function* () {\n\t\tconst result = new Map<string, OnchainCoinMetadata | null>();\n\t\tyield* Effect.forEach(\n\t\t\tfullCoinTypes,\n\t\t\t(fullCoinType) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst cached = yield* cache.get(fullCoinType);\n\t\t\t\t\tif (cached !== undefined) {\n\t\t\t\t\t\tresult.set(fullCoinType, cached);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst fetched = yield* fetchCoinMetadataOnce(sdk, fullCoinType);\n\t\t\t\t\tyield* cache.put(fullCoinType, fetched);\n\t\t\t\t\tresult.set(fullCoinType, fetched);\n\t\t\t\t}),\n\t\t\t{ concurrency: 'unbounded' },\n\t\t);\n\t\treturn result;\n\t});\n\n/** Bare-coin-type heuristic — distilled-doc 13-coin.md Invariant 3.\n *\n * MUST agree with what `getCoinMetadata` accepts as a coin-type\n * argument: `0xHEX::module::Witness`. Anything else (symbol, witness\n * alone) falls through to the registry path. */\nexport const isBareCoinType = (s: string): boolean => {\n\tif (!s.startsWith('0x')) return false;\n\tif (!s.includes('::')) return false;\n\tif (s.split('::').length !== 3) return false;\n\t// Distilled-doc invariant 7: nested generics rejected at the\n\t// bare-string boundary too. The check fires before the RPC so\n\t// callers see a typed error rather than a downstream decode\n\t// failure.\n\tif (s.includes('<') || s.includes('>')) return false;\n\treturn true;\n};\n\n/** Project a coin-type validation failure to `CoinError`. Surfaces\n * the nested-generic case at the user-facing factory boundary. */\nexport const validateBareCoinType = (identifier: string): CoinError | null => {\n\tif (identifier.includes('<') || identifier.includes('>')) {\n\t\treturn coinError('nested-generic', {\n\t\t\tidentifier,\n\t\t\tmessage: `coin('${identifier}'): nested generics not supported.`,\n\t\t});\n\t}\n\treturn null;\n};\n\nconst stringifyCause = (cause: unknown): string => {\n\tif (cause instanceof Error) return cause.message;\n\tif (typeof cause === 'string') return cause;\n\ttry {\n\t\treturn JSON.stringify(cause);\n\t} catch {\n\t\treturn String(cause);\n\t}\n};\n"],"mappings":";;;;;;;AAuBA,MAAa,4BAA4B;;;AAIzC,MAAa,0BAA0B,wBAAwB,KAAK,EAAE;;;;;;;;;;;;AAatE,MAAa,2BAA2B,OAAO,OAAO;CACrD,IAAI,OAAO;CACX,UAAU,OAAO;CACjB,MAAM,OAAO;CACb,QAAQ,OAAO;CACf,aAAa,OAAO,SAAS,OAAO,OAAO;CAC3C,SAAS,OAAO,SAAS,OAAO,OAAO;CACvC,CAAC;;;;;;;;AAwCF,MAAa,yBACZ,KACA,iBAEA,OAAO,IAAI,aAAa;CACvB,MAAM,MAAe,OAAO,OAAO,WAAW;EAC7C,WAAW,IAAI,KAAK,gBAAgB,EAAE,UAAU,cAAc,CAAC;EAC/D,QAAQ,WAA8D;GACrE,MAAM;GACN;GACA;EACD,CAAC,CAAC,KAKF,OAAO,cAAc;EACpB,UAAU,GAAG,0BAA0B;EACvC,cAAc,OAAO,KAAK;GAAE,MAAM;GAAgB,OAAO;GAAW,CAAC;EACrE,CAAC,EACF,OAAO,MAAM,wBAAwB,EACrC,OAAO,OAAO,QAAgC;AAC7C,SAAO,OAAO,WAAW,qDAAqD,CAAC,KAC9E,OAAO,aAAa;IAClB,SAAS,WAAW;IACpB,SAAS,aAAa,eAAe,IAAI,MAAM;GAChD,CAAC,EACF,OAAO,GAAG,KAAK,CACf;GACA,CACF;AACD,KAAI,QAAQ,QAAQ,QAAQ,KAAA,EAAW,QAAO;AAC9C,QAAO,OAAO,cAAc,0BAA0B,KAAK;EAC1D,QAAQ;EACR,UAAU,UAAU;EACpB,CAAC,CAAC,KACF,OAAO,OAAO,UACb,OAAO,WACN,qEACA,CAAC,KACD,OAAO,aAAa;GAClB,SAAS,WAAW;GACpB,SAAS,aAAa,eAAe,MAAM,SAAS,MAAM;EAC3D,CAAC,EACF,OAAO,GAAG,KAAmC,CAC7C,CACD,CACD;EACA,CAAC,KAAK,OAAO,SAAS,uBAAuB,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC,CAAC;;;;;;AAmClF,MAAa,kBAAkB,MAAuB;AACrD,KAAI,CAAC,EAAE,WAAW,KAAK,CAAE,QAAO;AAChC,KAAI,CAAC,EAAE,SAAS,KAAK,CAAE,QAAO;AAC9B,KAAI,EAAE,MAAM,KAAK,CAAC,WAAW,EAAG,QAAO;AAKvC,KAAI,EAAE,SAAS,IAAI,IAAI,EAAE,SAAS,IAAI,CAAE,QAAO;AAC/C,QAAO;;;;AAKR,MAAa,wBAAwB,eAAyC;AAC7E,KAAI,WAAW,SAAS,IAAI,IAAI,WAAW,SAAS,IAAI,CACvD,QAAO,UAAU,kBAAkB;EAClC;EACA,SAAS,SAAS,WAAW;EAC7B,CAAC;AAEH,QAAO;;AAGR,MAAM,kBAAkB,UAA2B;AAClD,KAAI,iBAAiB,MAAO,QAAO,MAAM;AACzC,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI;AACH,SAAO,KAAK,UAAU,MAAM;SACrB;AACP,SAAO,OAAO,MAAM"}
|
|
1
|
+
{"version":3,"file":"metadata.mjs","names":[],"sources":["../../../src/plugins/coin/metadata.ts"],"sourcesContent":["// CoinMetadata fetch + soft-degradation.\n//\n// Distilled-doc 13-coin.md Invariant 8: `getCoinMetadata` failures\n// degrade, do not throw. A timeout or RPC error after one retry\n// returns `null` (logged as a warning); the discovery pipeline keeps\n// going. The next supervisor cycle picks the missing record up.\n//\n// Per-attempt timeout 5s, ONE retry at 250ms backoff (matches the v3\n// `RETRY_SCHEDULE` exactly — distilled-doc 13-coin.md §Configuration).\n//\n// In-process per-Layer-invocation cache keyed by fullCoinType. The\n// fullCoinType folds the packageId, so a fresh chain (new genesis)\n// means new packageIds, which means the cache misses naturally —\n// persistence across restart is unnecessary.\n\nimport { Effect, Ref, Schema } from 'effect';\n\nimport { decodeUnknown } from '../../substrate/runtime/runtime-decode.ts';\nimport { SpanAttr } from '../../substrate/runtime/observability/spans.ts';\nimport { makeSpacedRetrySchedule } from '../../substrate/runtime/retry-policy.ts';\nimport { formatUnknownError } from '../../substrate/runtime/format-unknown-error.ts';\nimport { coinError, type CoinError } from './errors.ts';\nimport { CoinSpans } from './spans.ts';\n\n/** Per-attempt timeout (5 seconds) — distilled-doc invariant. */\nexport const METADATA_FETCH_TIMEOUT_MS = 5_000;\n\n/** Retry schedule — ONE retry at 250ms backoff. Matches the v3\n * `RETRY_SCHEDULE` (250ms spaced, bounded to one retry). */\nexport const METADATA_RETRY_SCHEDULE = makeSpacedRetrySchedule(250, 1);\n\n/** On-chain CoinMetadata projection — narrowed to the columns the\n * registry needs. The SDK's full shape carries more (description,\n * raw bytes); we don't.\n *\n * IMPORTANT (chain-probe schema constraint from the last sweep):\n * this Schema MUST NOT depend on any services. `Schema.Schema<T>` is\n * parameterized `<Type, Encoded, R, RD>`; we constrain `R` and `RD`\n * to `never` via `Schema.Codec<T, unknown, never, never>` at the\n * consumer boundary, but the schema literal itself uses ONLY\n * service-free combinators (`Schema.String`, `Schema.Number`,\n * `Schema.optional`). */\nexport const OnchainCoinMetadataShape = Schema.Struct({\n\tid: Schema.String,\n\tdecimals: Schema.Number,\n\tname: Schema.String,\n\tsymbol: Schema.String,\n\tdescription: Schema.optional(Schema.String),\n\ticonUrl: Schema.optional(Schema.String),\n});\n\nexport type OnchainCoinMetadata = typeof OnchainCoinMetadataShape.Type;\n\n/** SDK shim — the surface the discovery pass calls. The Sui plugin's\n * resolved client exposes this via `sdk.core.getCoinMetadata`. Kept\n * narrow (no `@mysten/sui` type import) so this module stays\n * layering-neutral; the consumer hands in the resolved client. */\nexport interface MetadataSdkShim {\n\treadonly core: {\n\t\treadonly getCoinMetadata: (args: { readonly coinType: string }) => Promise<unknown>;\n\t};\n}\n\n/** Per-Layer-invocation cache. `null` means \"we tried and the RPC\n * said the coin had no CoinMetadata\"; `undefined` means \"we haven't\n * asked yet\". */\nexport interface CoinMetadataCache {\n\treadonly get: (fullCoinType: string) => Effect.Effect<OnchainCoinMetadata | null | undefined>;\n\treadonly put: (fullCoinType: string, value: OnchainCoinMetadata | null) => Effect.Effect<void>;\n}\n\n/** Build an empty cache. */\nexport const makeCoinMetadataCache = (): Effect.Effect<CoinMetadataCache> =>\n\tEffect.gen(function* () {\n\t\tconst ref = yield* Ref.make<Record<string, OnchainCoinMetadata | null>>({});\n\t\treturn {\n\t\t\tget: (fullCoinType) =>\n\t\t\t\tRef.get(ref).pipe(Effect.map((m) => (fullCoinType in m ? m[fullCoinType] : undefined))),\n\t\t\tput: (fullCoinType, value) => Ref.update(ref, (m) => ({ ...m, [fullCoinType]: value })),\n\t\t};\n\t});\n\n/** Fetch CoinMetadata for one coin type. Soft-degrades on RPC\n * failure / timeout: returns `null` after the retry budget is\n * exhausted, AND logs a warning.\n *\n * Distilled-doc 13-coin.md Invariant 8: this is intentional. The\n * publish-discovery pass must not fail the whole supervisor cycle on\n * a flaky RPC blip. */\nexport const fetchCoinMetadataOnce = (\n\tsdk: MetadataSdkShim,\n\tfullCoinType: string,\n): Effect.Effect<OnchainCoinMetadata | null> =>\n\tEffect.gen(function* () {\n\t\tconst raw: unknown = yield* Effect.tryPromise({\n\t\t\ttry: () => sdk.core.getCoinMetadata({ coinType: fullCoinType }),\n\t\t\tcatch: (cause): { readonly _tag: 'rpc'; readonly cause: unknown } => ({\n\t\t\t\t_tag: 'rpc',\n\t\t\t\tcause,\n\t\t\t}),\n\t\t}).pipe(\n\t\t\t// Effect v4: `timeoutOrElse` (not `timeoutFail`). The\n\t\t\t// `orElse` branch is the new value (Effect), not just an\n\t\t\t// error constructor — we surface a tagged failure that the\n\t\t\t// downstream `Effect.catch` swallows into `null`.\n\t\t\tEffect.timeoutOrElse({\n\t\t\t\tduration: `${METADATA_FETCH_TIMEOUT_MS} millis`,\n\t\t\t\torElse: () => Effect.fail({ _tag: 'rpc' as const, cause: 'timeout' }),\n\t\t\t}),\n\t\t\tEffect.retry(METADATA_RETRY_SCHEDULE),\n\t\t\tEffect.catch((err): Effect.Effect<unknown> => {\n\t\t\t\treturn Effect.logWarning('coin metadata fetch failed; soft-degrading to null').pipe(\n\t\t\t\t\tEffect.annotateLogs({\n\t\t\t\t\t\t[CoinSpans.type]: fullCoinType,\n\t\t\t\t\t\t[SpanAttr.errorCause]: formatUnknownError(err.cause),\n\t\t\t\t\t}),\n\t\t\t\t\tEffect.as(null),\n\t\t\t\t);\n\t\t\t}),\n\t\t);\n\t\tif (raw === null || raw === undefined) return null;\n\t\treturn yield* decodeUnknown(OnchainCoinMetadataShape, raw, {\n\t\t\tsource: 'coin metadata RPC response',\n\t\t\tmkError: (issue) => issue,\n\t\t}).pipe(\n\t\t\tEffect.catch((issue) =>\n\t\t\t\tEffect.logWarning(\n\t\t\t\t\t'coin metadata response had non-conforming shape; degrading to null',\n\t\t\t\t).pipe(\n\t\t\t\t\tEffect.annotateLogs({\n\t\t\t\t\t\t[CoinSpans.type]: fullCoinType,\n\t\t\t\t\t\t[SpanAttr.errorCause]: formatUnknownError(issue.cause ?? issue),\n\t\t\t\t\t}),\n\t\t\t\t\tEffect.as(null as OnchainCoinMetadata | null),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.coin.metadata.fetch', {\n\t\t\tattributes: { [CoinSpans.metadata.fullCoinType]: fullCoinType },\n\t\t}),\n\t);\n\n/** Batch-fetch with cache. Each fullCoinType is asked at most once\n * per Layer-invocation. The fetches run concurrently — distilled-doc\n * opportunity (\"Coin discovery is naturally batchable\"). */\nexport const fetchCoinMetadataMany = (\n\tsdk: MetadataSdkShim,\n\tfullCoinTypes: ReadonlyArray<string>,\n\tcache: CoinMetadataCache,\n): Effect.Effect<ReadonlyMap<string, OnchainCoinMetadata | null>> =>\n\tEffect.gen(function* () {\n\t\tconst result = new Map<string, OnchainCoinMetadata | null>();\n\t\tyield* Effect.forEach(\n\t\t\tfullCoinTypes,\n\t\t\t(fullCoinType) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst cached = yield* cache.get(fullCoinType);\n\t\t\t\t\tif (cached !== undefined) {\n\t\t\t\t\t\tresult.set(fullCoinType, cached);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst fetched = yield* fetchCoinMetadataOnce(sdk, fullCoinType);\n\t\t\t\t\tyield* cache.put(fullCoinType, fetched);\n\t\t\t\t\tresult.set(fullCoinType, fetched);\n\t\t\t\t}),\n\t\t\t{ concurrency: 'unbounded' },\n\t\t);\n\t\treturn result;\n\t});\n\n/** Bare-coin-type heuristic — distilled-doc 13-coin.md Invariant 3.\n *\n * MUST agree with what `getCoinMetadata` accepts as a coin-type\n * argument: `0xHEX::module::Witness`. Anything else (symbol, witness\n * alone) falls through to the registry path. */\nexport const isBareCoinType = (s: string): boolean => {\n\tif (!s.startsWith('0x')) return false;\n\tif (!s.includes('::')) return false;\n\tif (s.split('::').length !== 3) return false;\n\t// Distilled-doc invariant 7: nested generics rejected at the\n\t// bare-string boundary too. The check fires before the RPC so\n\t// callers see a typed error rather than a downstream decode\n\t// failure.\n\tif (s.includes('<') || s.includes('>')) return false;\n\treturn true;\n};\n\n/** Project a coin-type validation failure to `CoinError`. Surfaces\n * the nested-generic case at the user-facing factory boundary. */\nexport const validateBareCoinType = (identifier: string): CoinError | null => {\n\tif (identifier.includes('<') || identifier.includes('>')) {\n\t\treturn coinError('nested-generic', {\n\t\t\tidentifier,\n\t\t\tmessage: `coin('${identifier}'): nested generics not supported.`,\n\t\t});\n\t}\n\treturn null;\n};\n"],"mappings":";;;;;;;;;AAyBA,MAAa,4BAA4B;;;AAIzC,MAAa,0BAA0B,wBAAwB,KAAK,EAAE;;;;;;;;;;;;AAatE,MAAa,2BAA2B,OAAO,OAAO;CACrD,IAAI,OAAO;CACX,UAAU,OAAO;CACjB,MAAM,OAAO;CACb,QAAQ,OAAO;CACf,aAAa,OAAO,SAAS,OAAO,OAAO;CAC3C,SAAS,OAAO,SAAS,OAAO,OAAO;CACvC,CAAC;;;;;;;;AAwCF,MAAa,yBACZ,KACA,iBAEA,OAAO,IAAI,aAAa;CACvB,MAAM,MAAe,OAAO,OAAO,WAAW;EAC7C,WAAW,IAAI,KAAK,gBAAgB,EAAE,UAAU,cAAc,CAAC;EAC/D,QAAQ,WAA8D;GACrE,MAAM;GACN;GACA;EACD,CAAC,CAAC,KAKF,OAAO,cAAc;EACpB,UAAU,GAAG,0BAA0B;EACvC,cAAc,OAAO,KAAK;GAAE,MAAM;GAAgB,OAAO;GAAW,CAAC;EACrE,CAAC,EACF,OAAO,MAAM,wBAAwB,EACrC,OAAO,OAAO,QAAgC;AAC7C,SAAO,OAAO,WAAW,qDAAqD,CAAC,KAC9E,OAAO,aAAa;IAClB,UAAU,OAAO;IACjB,SAAS,aAAa,mBAAmB,IAAI,MAAM;GACpD,CAAC,EACF,OAAO,GAAG,KAAK,CACf;GACA,CACF;AACD,KAAI,QAAQ,QAAQ,QAAQ,KAAA,EAAW,QAAO;AAC9C,QAAO,OAAO,cAAc,0BAA0B,KAAK;EAC1D,QAAQ;EACR,UAAU,UAAU;EACpB,CAAC,CAAC,KACF,OAAO,OAAO,UACb,OAAO,WACN,qEACA,CAAC,KACD,OAAO,aAAa;GAClB,UAAU,OAAO;GACjB,SAAS,aAAa,mBAAmB,MAAM,SAAS,MAAM;EAC/D,CAAC,EACF,OAAO,GAAG,KAAmC,CAC7C,CACD,CACD;EACA,CAAC,KACF,OAAO,SAAS,uCAAuC,EACtD,YAAY,GAAG,UAAU,SAAS,eAAe,cAAc,EAC/D,CAAC,CACF;;;;;;AAmCF,MAAa,kBAAkB,MAAuB;AACrD,KAAI,CAAC,EAAE,WAAW,KAAK,CAAE,QAAO;AAChC,KAAI,CAAC,EAAE,SAAS,KAAK,CAAE,QAAO;AAC9B,KAAI,EAAE,MAAM,KAAK,CAAC,WAAW,EAAG,QAAO;AAKvC,KAAI,EAAE,SAAS,IAAI,IAAI,EAAE,SAAS,IAAI,CAAE,QAAO;AAC/C,QAAO;;;;AAKR,MAAa,wBAAwB,eAAyC;AAC7E,KAAI,WAAW,SAAS,IAAI,IAAI,WAAW,SAAS,IAAI,CACvD,QAAO,UAAU,kBAAkB;EAClC;EACA,SAAS,SAAS,WAAW;EAC7B,CAAC;AAEH,QAAO"}
|
|
@@ -2,14 +2,34 @@ import { Effect, Schema, Scope } from "effect";
|
|
|
2
2
|
|
|
3
3
|
//#region src/plugins/coin/mint.d.ts
|
|
4
4
|
/** Sign+execute surface narrowed from `AccountValue.signAndExecute`.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
* Mirrors the SDK's discriminated `TransactionResult` return shape —
|
|
6
|
+
* on-chain failures are a return variant (`$kind: 'FailedTransaction'`),
|
|
7
|
+
* not an error.
|
|
8
|
+
*
|
|
9
|
+
* Modelled as a proper $kind-discriminated union (not both-optional
|
|
10
|
+
* fields) so consumers do not need non-null assertions after the
|
|
11
|
+
* `result.$kind === 'FailedTransaction'` narrow. We don't import
|
|
12
|
+
* `SignAndExecuteResult` from the Account plugin barrel directly
|
|
13
|
+
* because the success transaction shape consumed here is narrower
|
|
14
|
+
* (only `digest` + `objectChanges`) than the Account plugin's
|
|
15
|
+
* `TxResult` (which adds `effects` + `balanceChanges` — fields the
|
|
16
|
+
* mint produce body does not surface). The shape is structurally
|
|
17
|
+
* compatible — Account's `signAndExecute` widens to this surface. */
|
|
18
|
+
type MintSignAndExecuteResult = {
|
|
19
|
+
readonly $kind: 'Transaction';
|
|
20
|
+
readonly Transaction: {
|
|
10
21
|
readonly digest: string;
|
|
11
22
|
readonly objectChanges: ReadonlyArray<unknown>;
|
|
12
|
-
}
|
|
23
|
+
};
|
|
24
|
+
} | {
|
|
25
|
+
readonly $kind: 'FailedTransaction';
|
|
26
|
+
readonly FailedTransaction: {
|
|
27
|
+
readonly digest: string;
|
|
28
|
+
readonly executionError?: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
interface MintTransactionSigner {
|
|
32
|
+
readonly signAndExecute: (tx: Uint8Array) => Effect.Effect<MintSignAndExecuteResult, {
|
|
13
33
|
readonly _tag: 'AccountSignError';
|
|
14
34
|
readonly message: string;
|
|
15
35
|
}>;
|
|
@@ -19,11 +39,10 @@ interface MintSigner extends MintTransactionSigner {
|
|
|
19
39
|
readonly withTransactionSigner: <A, E, R>(body: (signer: MintTransactionSigner) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
20
40
|
}
|
|
21
41
|
interface MintResult {
|
|
22
|
-
/** Tx digest of the producing mint.
|
|
23
|
-
* the
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
readonly digest: string | null;
|
|
42
|
+
/** Tx digest of the producing mint. Surfaces the cached digest on
|
|
43
|
+
* verify-hit (the substrate hands back the decoded `CachedMint`
|
|
44
|
+
* payload, which carries it). */
|
|
45
|
+
readonly digest: string;
|
|
27
46
|
readonly mintedCoinId: string;
|
|
28
47
|
readonly recipient: string;
|
|
29
48
|
readonly amount: bigint;
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { decodeUnknown } from "../../substrate/runtime/runtime-decode.mjs";
|
|
2
1
|
import { contentHash } from "../../substrate/brand.mjs";
|
|
2
|
+
import { decodeUnknown } from "../../substrate/runtime/runtime-decode.mjs";
|
|
3
3
|
import { isSuiFrameworkObjectForCoin } from "./type-strings.mjs";
|
|
4
|
+
import { formatUnknownError } from "../../substrate/runtime/format-unknown-error.mjs";
|
|
5
|
+
import { signAndDispatch } from "../../substrate/runtime/sui-execute/sign-and-dispatch.mjs";
|
|
6
|
+
import { formatExecutedFailure } from "../../substrate/runtime/sui-execute/index.mjs";
|
|
7
|
+
import { buildForkImpersonationTransactionBytes } from "../sui/fork-transaction.mjs";
|
|
8
|
+
import "../sui/index.mjs";
|
|
9
|
+
import { artifactPublishError } from "../../primitives/artifact-publisher.mjs";
|
|
4
10
|
import { coinError } from "./errors.mjs";
|
|
11
|
+
import { CoinSpans } from "./spans.mjs";
|
|
12
|
+
import { acquireOnChainArtifact } from "../internal/acquire-on-chain-artifact.mjs";
|
|
5
13
|
import { Effect, Schema } from "effect";
|
|
6
14
|
import { Transaction } from "@mysten/sui/transactions";
|
|
7
15
|
//#region src/plugins/coin/mint.ts
|
|
@@ -14,10 +22,17 @@ const MintedCoinVerifyShape = Schema.Struct({
|
|
|
14
22
|
});
|
|
15
23
|
/** Build the cache-key content hash. Distilled-doc 13-coin.md
|
|
16
24
|
* §"Persistence model": key shape is
|
|
17
|
-
* `coin/mint/<chainId>/<treasuryCapId>/<recipient>/<amount>`.
|
|
18
|
-
* substrate's artifact publisher folds in chainId via the
|
|
19
|
-
* fold the remaining columns into `contentHash`.
|
|
20
|
-
|
|
25
|
+
* `coin/mint/<chainId>/<treasuryCapId>/<signerAddress>/<recipient>/<amount>`.
|
|
26
|
+
* The substrate's artifact publisher folds in chainId via the
|
|
27
|
+
* `chain` parameter; we fold the remaining columns into `contentHash`.
|
|
28
|
+
*
|
|
29
|
+
* `signerAddress` is folded in because the producing signer is part
|
|
30
|
+
* of the cache identity — reusing the same `(treasuryCap, recipient,
|
|
31
|
+
* amount)` under a different signer MUST miss the cache so the new
|
|
32
|
+
* signer actually re-executes the mint. Mirrors the symmetric
|
|
33
|
+
* `publisherAddress` fold in `plugins/package/mode-local.ts:149-152`.
|
|
34
|
+
* Backlog #6. */
|
|
35
|
+
const buildMintContentHash = (parts) => contentHash(`mint/${parts.treasuryCapId}/${parts.signerAddress}/${parts.recipient}/${parts.amount.toString()}`);
|
|
21
36
|
/** Verify probe — checks the cached minted-coin still exists. Lenient:
|
|
22
37
|
* returns `null` for both not-found AND transient failure (distilled-
|
|
23
38
|
* doc invariant: the next cycle re-derives).
|
|
@@ -72,87 +87,76 @@ const isCreatedObjectChange = (raw) => {
|
|
|
72
87
|
* procedures; the substrate handles best-effort cache writes per
|
|
73
88
|
* Invariant 2.
|
|
74
89
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
90
|
+
* The substrate's `publish` returns the `CachedMint` payload on every
|
|
91
|
+
* path (decoded cached payload on verify-hit, fresh produce on miss);
|
|
92
|
+
* we project it directly to `MintResult`. */
|
|
78
93
|
const performMint = (publisher, chain, signer, sdk, inputs) => Effect.gen(function* () {
|
|
79
|
-
const
|
|
80
|
-
const verified = yield* publisher.publish({
|
|
94
|
+
const cached = yield* acquireOnChainArtifact(publisher, {
|
|
81
95
|
namespace: "coin-mint",
|
|
82
96
|
chain,
|
|
83
|
-
contentHash:
|
|
84
|
-
|
|
97
|
+
contentHash: buildMintContentHash({
|
|
98
|
+
treasuryCapId: inputs.treasuryCapId,
|
|
99
|
+
recipient: inputs.recipient,
|
|
100
|
+
amount: inputs.amount,
|
|
101
|
+
signerAddress: signer.address
|
|
102
|
+
}),
|
|
85
103
|
verify: (cached) => buildVerifyProbe(sdk, cached.mintedCoinId),
|
|
86
104
|
produce: Effect.gen(function* () {
|
|
87
105
|
yield* Effect.annotateCurrentSpan({
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
106
|
+
[CoinSpans.mint.recipient]: inputs.recipient,
|
|
107
|
+
[CoinSpans.mint.fullCoinType]: inputs.fullCoinType,
|
|
108
|
+
[CoinSpans.mint.amount]: inputs.amount.toString()
|
|
91
109
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
110
|
+
return yield* signAndDispatch({
|
|
111
|
+
signerSource: signer,
|
|
112
|
+
buildTxBytes: () => Effect.gen(function* () {
|
|
113
|
+
const tx = new Transaction();
|
|
114
|
+
if (inputs.gasBudget !== void 0) tx.setGasBudget(inputs.gasBudget);
|
|
115
|
+
tx.setSender(signer.address);
|
|
116
|
+
tx.moveCall({
|
|
117
|
+
target: "0x2::coin::mint_and_transfer",
|
|
118
|
+
typeArguments: [inputs.fullCoinType],
|
|
119
|
+
arguments: [
|
|
120
|
+
tx.object(inputs.treasuryCapId),
|
|
121
|
+
tx.pure.u64(inputs.amount),
|
|
122
|
+
tx.pure.address(inputs.recipient)
|
|
123
|
+
]
|
|
124
|
+
});
|
|
125
|
+
return sdk.forkMode === true ? yield* buildForkImpersonationTransactionBytes(tx, signer.address, sdk.core).pipe(Effect.mapError((cause) => artifactPublishError("produce-failed", `coin.mint(${inputs.fullCoinType}): fork Transaction.build failed — ${cause.message}`))) : yield* Effect.tryPromise({
|
|
126
|
+
try: () => tx.build({ client: sdk.client }),
|
|
127
|
+
catch: (cause) => artifactPublishError("produce-failed", `coin.mint(${inputs.fullCoinType}): Transaction.build failed — ${formatUnknownError(cause)}`)
|
|
128
|
+
});
|
|
129
|
+
}),
|
|
130
|
+
mapSignError: (cause) => artifactPublishError("produce-failed", `coin.mint(${inputs.fullCoinType}): signAndExecute failed — ` + cause.message),
|
|
131
|
+
onFailed: (failed) => Effect.fail(artifactPublishError("produce-failed", `coin.mint(${inputs.fullCoinType}): transaction execution failed on-chain ` + formatExecutedFailure(failed))),
|
|
132
|
+
onSuccess: (ok) => Effect.gen(function* () {
|
|
133
|
+
const mintedCoinId = pickCreatedCoin(ok.objectChanges, inputs.fullCoinType);
|
|
134
|
+
if (mintedCoinId === null) return yield* Effect.fail(artifactPublishError("produce-failed", `coin.mint(${inputs.fullCoinType}): minted Coin<T> not found in objectChanges (digest=${ok.digest}). ` + mintParseError(inputs.fullCoinType, "minted Coin<T> absent in objectChanges").message));
|
|
135
|
+
yield* Effect.annotateCurrentSpan({
|
|
136
|
+
[CoinSpans.mint.digest]: ok.digest,
|
|
137
|
+
[CoinSpans.mint.mintedCoinId]: mintedCoinId
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
digest: ok.digest,
|
|
141
|
+
mintedCoinId,
|
|
142
|
+
recipient: inputs.recipient,
|
|
143
|
+
amount: inputs.amount.toString()
|
|
144
|
+
};
|
|
145
|
+
})
|
|
124
146
|
});
|
|
125
|
-
|
|
126
|
-
"coin.mint.digest": result.digest,
|
|
127
|
-
"coin.mint.mintedCoinId": mintedCoinId
|
|
128
|
-
});
|
|
129
|
-
return {
|
|
130
|
-
digest: result.digest,
|
|
131
|
-
mintedCoinId,
|
|
132
|
-
recipient: inputs.recipient,
|
|
133
|
-
amount: inputs.amount.toString()
|
|
134
|
-
};
|
|
135
|
-
}),
|
|
136
|
-
register: () => Effect.void
|
|
147
|
+
})
|
|
137
148
|
});
|
|
138
|
-
if ("mintedCoinId" in verified) return {
|
|
139
|
-
digest: verified.digest,
|
|
140
|
-
mintedCoinId: verified.mintedCoinId,
|
|
141
|
-
recipient: verified.recipient,
|
|
142
|
-
amount: BigInt(verified.amount),
|
|
143
|
-
fullCoinType: inputs.fullCoinType
|
|
144
|
-
};
|
|
145
149
|
return {
|
|
146
|
-
digest:
|
|
147
|
-
mintedCoinId:
|
|
148
|
-
recipient:
|
|
149
|
-
amount:
|
|
150
|
+
digest: cached.digest,
|
|
151
|
+
mintedCoinId: cached.mintedCoinId,
|
|
152
|
+
recipient: cached.recipient,
|
|
153
|
+
amount: BigInt(cached.amount),
|
|
150
154
|
fullCoinType: inputs.fullCoinType
|
|
151
155
|
};
|
|
152
|
-
}).pipe(Effect.withSpan("coin.mint", { attributes: {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
}).pipe(Effect.withSpan("devstack.plugin.coin.mint", { attributes: {
|
|
157
|
+
[CoinSpans.mint.recipient]: inputs.recipient,
|
|
158
|
+
[CoinSpans.mint.fullCoinType]: inputs.fullCoinType,
|
|
159
|
+
[CoinSpans.mint.amount]: inputs.amount.toString()
|
|
156
160
|
} }));
|
|
157
161
|
const mintParseError = (fullCoinType, message) => coinError("mint-parse", {
|
|
158
162
|
identifier: fullCoinType,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mint.mjs","names":["brandContentHash"],"sources":["../../../src/plugins/coin/mint.ts"],"sourcesContent":["// Generic mint — wraps `0x2::coin::mint_and_transfer<T>` in the\n// `ArtifactPublisher` substrate primitive.\n//\n// Distilled-doc 13-coin.md §\"Lifecycle\" §\"mintFromTreasury\":\n//\n// - Cache key: (chainId, treasuryCapId, recipient, amount)\n// - Verify: lenient probe on the cached minted-coin id\n// (Invariant 1 — vanish-detection)\n// - Produce: sign + execute the `mint_and_transfer<T>` tx,\n// find the minted `Coin<T>` in objectChanges\n// - Register: in-memory note of the mint (no global registry —\n// the resolved value carries everything callers\n// need).\n//\n// Best-effort cache writes (distilled-doc Invariant 2): the mint\n// already settled on chain; a state-store IO defect just means the\n// next supervisor cycle re-mints. Don't let a StateStore failure\n// roll back the mint.\n//\n// Substrate constraint: the `ArtifactPublisher.publish` shape\n// already covers cache + verify + produce + register-on-every-cycle.\n// We compose its spec; the substrate dispatches.\n\nimport { Effect, Schema, type Scope } from 'effect';\nimport { Transaction } from '@mysten/sui/transactions';\n\nimport type { ChainId, ContentHash } from '../../substrate/brand.ts';\nimport { contentHash as brandContentHash } from '../../substrate/brand.ts';\nimport { decodeUnknown } from '../../substrate/runtime/runtime-decode.ts';\nimport type {\n\tArtifactPublishError,\n\tArtifactPublisher,\n} from '../../primitives/artifact-publisher.ts';\nimport { coinError, type CoinError } from './errors.ts';\nimport { isSuiFrameworkObjectForCoin } from './type-strings.ts';\n\n/** Sign+execute surface narrowed from `AccountValue.signAndExecute`.\n * We don't import `AccountValue` directly to avoid a layering cycle —\n * the Account plugin imports nothing from coin, so coin re-publishes\n * the structural shape. */\nexport interface MintTransactionSigner {\n\treadonly signAndExecute: (tx: Uint8Array) => Effect.Effect<\n\t\t{\n\t\t\treadonly digest: string;\n\t\t\treadonly objectChanges: ReadonlyArray<unknown>;\n\t\t},\n\t\t{ readonly _tag: 'AccountSignError'; readonly message: string }\n\t>;\n}\n\nexport interface MintSigner extends MintTransactionSigner {\n\treadonly address: string;\n\treadonly withTransactionSigner: <A, E, R>(\n\t\tbody: (signer: MintTransactionSigner) => Effect.Effect<A, E, R>,\n\t) => Effect.Effect<A, E, R>;\n}\n\n/** Cached payload — the stable id verify re-confirms on every cycle.\n * Distilled-doc invariant: the probe MUST consume a STABLE on-chain\n * identifier (the minted Coin<T>'s objectId), NOT a derived hash. */\nexport interface CachedMint {\n\treadonly digest: string;\n\treadonly mintedCoinId: string;\n\treadonly recipient: string;\n\t/** `amount.toString()` — bigint isn't serializable. */\n\treadonly amount: string;\n}\n\n/** Verify-schema: what we expect when probing the minted coin.\n * IMPORTANT (chain-probe schema constraint from the last sweep):\n * schema literal uses ONLY service-free combinators. */\nexport const MintedCoinVerifyShape = Schema.Struct({\n\tobjectId: Schema.String,\n\ttype: Schema.String,\n});\n\n/** Build the cache-key content hash. Distilled-doc 13-coin.md\n * §\"Persistence model\": key shape is\n * `coin/mint/<chainId>/<treasuryCapId>/<recipient>/<amount>`. The\n * substrate's artifact publisher folds in chainId via the `chain` parameter; we\n * fold the remaining columns into `contentHash`. */\nconst buildMintContentHash = (parts: {\n\treadonly treasuryCapId: string;\n\treadonly recipient: string;\n\treadonly amount: bigint;\n}): ContentHash =>\n\tbrandContentHash(`mint/${parts.treasuryCapId}/${parts.recipient}/${parts.amount.toString()}`);\n\nexport interface MintInputs {\n\treadonly fullCoinType: string;\n\treadonly treasuryCapId: string;\n\treadonly recipient: string;\n\treadonly amount: bigint;\n\treadonly gasBudget?: bigint;\n}\n\nexport interface MintResult {\n\t/** Tx digest of the producing mint. `null` on the verify-hit path:\n\t * the artifact publisher's cache-hit verify returns the decoded probe shape\n\t * (which doesn't carry the digest); callers that need the digest\n\t * on cache hit consult the artifact publisher cache directly. */\n\treadonly digest: string | null;\n\treadonly mintedCoinId: string;\n\treadonly recipient: string;\n\treadonly amount: bigint;\n\treadonly fullCoinType: string;\n}\n\n/** Sui SDK shim for the verify probe + transaction build.\n *\n * Narrowed-but-not-too-narrow: the produce body needs to serialize a\n * `Transaction` to BCS bytes, which the Sui SDK's\n * `Transaction.build({ client })` resolves via the client. We accept\n * the full client opaquely (typed `unknown` here — the runtime check\n * is \"does `Transaction.build` accept it\"). The barrel wires the\n * resolved `SuiGrpcClient` through.\n *\n * Why `unknown` rather than `ClientWithCoreApi`: keeps this module\n * free of a direct `@mysten/sui/client` type import — the produce body\n * passes it through opaquely to `Transaction.build`, which validates\n * the shape at runtime.\n *\n * The `core.getObject` field is the verify-probe surface; the\n * `client` field is the build-target. */\nexport interface MintSdkShim {\n\treadonly core: {\n\t\treadonly getObject: (args: { readonly objectId: string }) => Promise<unknown>;\n\t};\n\t/** Opaque client reference for `Transaction.build({ client })`. The\n\t * shim layer doesn't type-narrow this; the Sui barrel hands in the\n\t * resolved `SuiGrpcClient`. */\n\treadonly client: unknown;\n}\n\n/** Verify probe — checks the cached minted-coin still exists. Lenient:\n * returns `null` for both not-found AND transient failure (distilled-\n * doc invariant: the next cycle re-derives).\n *\n * IMPORTANT (chain-probe schema constraint): the probe pipeline\n * cannot inject services from the caller. We construct the schema\n * literal at module scope (above) and call `decodeUnknownEffect` —\n * which the substrate's `ChainProbe.get` does internally. This local\n * verify mirrors the call-shape so the constraint is honored.\n *\n * We model the verify here as an inline Effect because the cached\n * minted-coin id is known only AFTER cache lookup — the substrate's\n * `verify` Effect closes over the cached id. */\nconst buildVerifyProbe = (\n\tsdk: MintSdkShim,\n\tmintedCoinIdOpt: string | null,\n): Effect.Effect<typeof MintedCoinVerifyShape.Type | null, never> =>\n\tEffect.gen(function* () {\n\t\tif (mintedCoinIdOpt === null) return null;\n\t\tconst raw: unknown = yield* Effect.tryPromise({\n\t\t\ttry: () => sdk.core.getObject({ objectId: mintedCoinIdOpt }),\n\t\t\tcatch: () => 'transient' as const,\n\t\t}).pipe(\n\t\t\t// Lenient: not-found AND transient both coerce to null. The\n\t\t\t// artifact publisher's cache layer will then re-run produce.\n\t\t\tEffect.catch(() => Effect.succeed(null)),\n\t\t);\n\t\tif (raw === null || raw === undefined) return null;\n\t\t// Best-effort decode. A decode failure on the verify path is\n\t\t// treated as \"object exists but shape changed unexpectedly\" —\n\t\t// still null so the substrate re-mints rather than carry stale\n\t\t// data forward.\n\t\treturn yield* decodeUnknown(MintedCoinVerifyShape, raw, {\n\t\t\tsource: 'minted coin verify response',\n\t\t\tmkError: (issue) => issue,\n\t\t}).pipe(Effect.catch(() => Effect.succeed(null as typeof MintedCoinVerifyShape.Type | null)));\n\t});\n\n/** Object-change shape narrowed for `pickCreatedCoin`. The gRPC\n * client emits `objectType` as a fully-qualified Sui type string on\n * `created` entries; we sniff for the `Coin<T>` substring (inner\n * generic carries the full coin type, so the match is unambiguous —\n * distilled-doc 13-coin.md Invariant 9). */\ninterface CreatedObjectChange {\n\treadonly type: 'created';\n\treadonly objectId: string;\n\treadonly objectType?: string;\n}\n\n/** Find the minted `Coin<T>` in a result's objectChanges. Returns the\n * objectId of the first `created` entry whose `objectType` matches\n * `0x2::coin::Coin<${fullCoinType}>` (or its address-normalized equivalent).\n *\n * Returns `null` on no match — the caller maps that to a typed parse\n * error.\n *\n * The SDK can report the Sui framework address as compact `0x2` or\n * fully padded `0x000...0002`, so this uses the shared type-string\n * normalizer instead of substring matching. */\nexport const pickCreatedCoin = (\n\tchanges: ReadonlyArray<unknown>,\n\tfullCoinType: string,\n): string | null => {\n\tfor (const change of changes) {\n\t\tif (!isCreatedObjectChange(change)) continue;\n\t\tif (\n\t\t\ttypeof change.objectType === 'string' &&\n\t\t\tisSuiFrameworkObjectForCoin(change.objectType, 'Coin', fullCoinType)\n\t\t) {\n\t\t\treturn change.objectId;\n\t\t}\n\t}\n\treturn null;\n};\n\nconst isCreatedObjectChange = (raw: unknown): raw is CreatedObjectChange => {\n\tif (raw === null || typeof raw !== 'object') return false;\n\tconst r = raw as { type?: unknown; objectId?: unknown };\n\treturn r.type === 'created' && typeof r.objectId === 'string';\n};\n\n/** Build the `ArtifactPublisher` spec for one mint round.\n *\n * Substrate dispatches: cache lookup, verify-on-hit, produce-on-\n * miss-or-verify-fail, register-on-every-cycle. We hand it the\n * procedures; the substrate handles best-effort cache writes per\n * Invariant 2.\n *\n * Note on the `Produced | Verified` union: the artifact publisher's `publish`\n * returns one OR the other shape; both are `CachedMint`-compatible\n * for our purposes, so we collapse downstream. */\nexport const performMint = (\n\tpublisher: ArtifactPublisher,\n\tchain: ChainId,\n\tsigner: MintSigner,\n\tsdk: MintSdkShim,\n\tinputs: MintInputs,\n): Effect.Effect<MintResult, CoinError | ArtifactPublishError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst cacheHash = buildMintContentHash(inputs);\n\n\t\tconst verified: CachedMint | { readonly objectId: string; readonly type: string } =\n\t\t\tyield* publisher.publish<CachedMint, typeof MintedCoinVerifyShape.Type>({\n\t\t\t\tnamespace: 'coin-mint',\n\t\t\t\tchain,\n\t\t\t\tcontentHash: cacheHash,\n\t\t\t\tverifySchema: MintedCoinVerifyShape,\n\t\t\t\t// Verify probe runs on cache hit. The artifact publisher threads the\n\t\t\t\t// cached payload through to its internal probe — our\n\t\t\t\t// closure here just hands back a \"null = miss\" signal\n\t\t\t\t// when the cached id has vanished on chain.\n\t\t\t\t//\n\t\t\t\t// The artifact publisher substrate now threads the decoded\n\t\t\t\t// `CachedMint` into `verify(cached)`; we pull\n\t\t\t\t// `mintedCoinId` off it and probe the chain. Lenient\n\t\t\t\t// mode masks transient + not-found → null → substrate\n\t\t\t\t// re-mints rather than carry a stale digest forward.\n\t\t\t\tverify: (cached) => buildVerifyProbe(sdk, cached.mintedCoinId),\n\t\t\t\tproduce: Effect.gen(function* () {\n\t\t\t\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t\t\t\t'coin.mint.recipient': inputs.recipient,\n\t\t\t\t\t\t'coin.mint.fullCoinType': inputs.fullCoinType,\n\t\t\t\t\t\t'coin.mint.amount': inputs.amount.toString(),\n\t\t\t\t\t});\n\n\t\t\t\t\tconst result = yield* signer.withTransactionSigner((lockedSigner) =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t// 1. Build the Move tx — distilled-doc 13-coin.md\n\t\t\t\t\t\t\t// Invariant 9 pins the call shape:\n\t\t\t\t\t\t\t// `0x2::coin::mint_and_transfer<T>(cap, amount, recipient)`.\n\t\t\t\t\t\t\tconst tx = new Transaction();\n\t\t\t\t\t\t\tif (inputs.gasBudget !== undefined) {\n\t\t\t\t\t\t\t\ttx.setGasBudget(inputs.gasBudget);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttx.setSender(signer.address);\n\t\t\t\t\t\t\ttx.moveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::mint_and_transfer',\n\t\t\t\t\t\t\t\ttypeArguments: [inputs.fullCoinType],\n\t\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\t\ttx.object(inputs.treasuryCapId),\n\t\t\t\t\t\t\t\t\ttx.pure.u64(inputs.amount),\n\t\t\t\t\t\t\t\t\ttx.pure.address(inputs.recipient),\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// 2. Serialize the tx to BCS bytes while the account lease\n\t\t\t\t\t\t\t// is held. `Transaction.build` resolves gas + object-version\n\t\t\t\t\t\t\t// placeholders via the client.\n\t\t\t\t\t\t\tconst txBytes = yield* Effect.tryPromise({\n\t\t\t\t\t\t\t\ttry: () =>\n\t\t\t\t\t\t\t\t\ttx.build({\n\t\t\t\t\t\t\t\t\t\t// The shim exposes the client opaquely; @mysten/sui\n\t\t\t\t\t\t\t\t\t\t// validates the shape at runtime.\n\t\t\t\t\t\t\t\t\t\tclient: sdk.client as Parameters<typeof tx.build>[0] extends\n\t\t\t\t\t\t\t\t\t\t\t| { client?: infer C }\n\t\t\t\t\t\t\t\t\t\t\t| undefined\n\t\t\t\t\t\t\t\t\t\t\t? C\n\t\t\t\t\t\t\t\t\t\t\t: never,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tcatch: (cause): ArtifactPublishError => ({\n\t\t\t\t\t\t\t\t\t_tag: 'ArtifactPublishError',\n\t\t\t\t\t\t\t\t\treason: 'produce-failed',\n\t\t\t\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): Transaction.build failed — ` +\n\t\t\t\t\t\t\t\t\t\t`${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// 3. Sign + execute via the Account-supplied signer. Map\n\t\t\t\t\t\t\t// `AccountSignError` → `ArtifactPublishError`. The\n\t\t\t\t\t\t\t// Account plugin's signer handles waitForTransaction internally.\n\t\t\t\t\t\t\treturn yield* lockedSigner.signAndExecute(txBytes).pipe(\n\t\t\t\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t\t\t\t(cause): ArtifactPublishError => ({\n\t\t\t\t\t\t\t\t\t\t_tag: 'ArtifactPublishError',\n\t\t\t\t\t\t\t\t\t\treason: 'produce-failed',\n\t\t\t\t\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): signAndExecute failed — ` + cause.message,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\n\t\t\t\t\t// 4. Find the minted `Coin<T>` in objectChanges via the\n\t\t\t\t\t// inner-generic match (distilled-doc Invariant 9).\n\t\t\t\t\t// `mint_and_transfer` emits a fresh `Coin<T>` owned by\n\t\t\t\t\t// the recipient; look it up by the\n\t\t\t\t\t// `0x2::coin::Coin<${fullCoinType}>` substring.\n\t\t\t\t\tconst mintedCoinId = pickCreatedCoin(result.objectChanges, inputs.fullCoinType);\n\t\t\t\t\tif (mintedCoinId === null) {\n\t\t\t\t\t\treturn yield* Effect.fail({\n\t\t\t\t\t\t\t_tag: 'ArtifactPublishError' as const,\n\t\t\t\t\t\t\treason: 'produce-failed' as const,\n\t\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): minted Coin<T> not found in ` +\n\t\t\t\t\t\t\t\t`objectChanges (digest=${result.digest}). ` +\n\t\t\t\t\t\t\t\tmintParseError(inputs.fullCoinType, 'minted Coin<T> absent in objectChanges')\n\t\t\t\t\t\t\t\t\t.message,\n\t\t\t\t\t\t} satisfies ArtifactPublishError);\n\t\t\t\t\t}\n\n\t\t\t\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t\t\t\t'coin.mint.digest': result.digest,\n\t\t\t\t\t\t'coin.mint.mintedCoinId': mintedCoinId,\n\t\t\t\t\t});\n\n\t\t\t\t\t// 5. Return the cached payload. The artifact publisher caches it under\n\t\t\t\t\t// the content hash; the next cycle's verify probe (on\n\t\t\t\t\t// cache hit) will lenient-probe `mintedCoinId`.\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdigest: result.digest,\n\t\t\t\t\t\tmintedCoinId,\n\t\t\t\t\t\trecipient: inputs.recipient,\n\t\t\t\t\t\tamount: inputs.amount.toString(),\n\t\t\t\t\t} satisfies CachedMint;\n\t\t\t\t}),\n\t\t\t\t// Register on EVERY cycle (hit AND miss). Distilled-doc\n\t\t\t\t// Invariant 6. Coin mint has no global registry to feed —\n\t\t\t\t// the resolved-value carries everything; this is a no-op.\n\t\t\t\tregister: () => Effect.void,\n\t\t\t});\n\n\t\t// Project the union back to MintResult. Both arms carry enough\n\t\t// to reconstruct: produce returns CachedMint; verify returns\n\t\t// the decoded `{ objectId, type }`.\n\t\tif ('mintedCoinId' in verified) {\n\t\t\treturn {\n\t\t\t\tdigest: verified.digest,\n\t\t\t\tmintedCoinId: verified.mintedCoinId,\n\t\t\t\trecipient: verified.recipient,\n\t\t\t\tamount: BigInt(verified.amount),\n\t\t\t\tfullCoinType: inputs.fullCoinType,\n\t\t\t};\n\t\t}\n\t\t// Verify-hit path — the artifact publisher returned the decoded probe shape.\n\t\t// The producing-tx digest lives only in the artifact publisher cache layer (not on\n\t\t// the probe response), so we surface `null` here. Callers that need\n\t\t// the producing digest on a cache hit consult the artifact publisher cache directly.\n\t\treturn {\n\t\t\tdigest: null,\n\t\t\tmintedCoinId: verified.objectId,\n\t\t\trecipient: inputs.recipient,\n\t\t\tamount: inputs.amount,\n\t\t\tfullCoinType: inputs.fullCoinType,\n\t\t};\n\t}).pipe(\n\t\tEffect.withSpan('coin.mint', {\n\t\t\tattributes: {\n\t\t\t\t'coin.mint.recipient': inputs.recipient,\n\t\t\t\t'coin.mint.fullCoinType': inputs.fullCoinType,\n\t\t\t\t'coin.mint.amount': inputs.amount.toString(),\n\t\t\t},\n\t\t}),\n\t);\n\n/** Project an artifact publisher-wire error back to a CoinError when the consumer\n * wants a coin-side tagged shape. The artifact publisher boundary is generic; this\n * helper recovers the typed `mint-tx` / `mint-parse` phase the cause\n * walker uses. */\nexport const mintTxError = (fullCoinType: string, message: string, cause?: unknown): CoinError =>\n\tcoinError('mint-tx', {\n\t\tidentifier: fullCoinType,\n\t\tmessage,\n\t\t...(cause !== undefined ? { cause } : {}),\n\t});\n\nexport const mintParseError = (fullCoinType: string, message: string): CoinError =>\n\tcoinError('mint-parse', {\n\t\tidentifier: fullCoinType,\n\t\tmessage,\n\t});\n"],"mappings":";;;;;;;;;;AAuEA,MAAa,wBAAwB,OAAO,OAAO;CAClD,UAAU,OAAO;CACjB,MAAM,OAAO;CACb,CAAC;;;;;;AAOF,MAAM,wBAAwB,UAK7BA,YAAiB,QAAQ,MAAM,cAAc,GAAG,MAAM,UAAU,GAAG,MAAM,OAAO,UAAU,GAAG;;;;;;;;;;;;;;AA6D9F,MAAM,oBACL,KACA,oBAEA,OAAO,IAAI,aAAa;AACvB,KAAI,oBAAoB,KAAM,QAAO;CACrC,MAAM,MAAe,OAAO,OAAO,WAAW;EAC7C,WAAW,IAAI,KAAK,UAAU,EAAE,UAAU,iBAAiB,CAAC;EAC5D,aAAa;EACb,CAAC,CAAC,KAGF,OAAO,YAAY,OAAO,QAAQ,KAAK,CAAC,CACxC;AACD,KAAI,QAAQ,QAAQ,QAAQ,KAAA,EAAW,QAAO;AAK9C,QAAO,OAAO,cAAc,uBAAuB,KAAK;EACvD,QAAQ;EACR,UAAU,UAAU;EACpB,CAAC,CAAC,KAAK,OAAO,YAAY,OAAO,QAAQ,KAAiD,CAAC,CAAC;EAC5F;;;;;;;;;;;AAuBH,MAAa,mBACZ,SACA,iBACmB;AACnB,MAAK,MAAM,UAAU,SAAS;AAC7B,MAAI,CAAC,sBAAsB,OAAO,CAAE;AACpC,MACC,OAAO,OAAO,eAAe,YAC7B,4BAA4B,OAAO,YAAY,QAAQ,aAAa,CAEpE,QAAO,OAAO;;AAGhB,QAAO;;AAGR,MAAM,yBAAyB,QAA6C;AAC3E,KAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAU,QAAO;CACpD,MAAM,IAAI;AACV,QAAO,EAAE,SAAS,aAAa,OAAO,EAAE,aAAa;;;;;;;;;;;;AAatD,MAAa,eACZ,WACA,OACA,QACA,KACA,WAEA,OAAO,IAAI,aAAa;CACvB,MAAM,YAAY,qBAAqB,OAAO;CAE9C,MAAM,WACL,OAAO,UAAU,QAAuD;EACvE,WAAW;EACX;EACA,aAAa;EACb,cAAc;EAWd,SAAS,WAAW,iBAAiB,KAAK,OAAO,aAAa;EAC9D,SAAS,OAAO,IAAI,aAAa;AAChC,UAAO,OAAO,oBAAoB;IACjC,uBAAuB,OAAO;IAC9B,0BAA0B,OAAO;IACjC,oBAAoB,OAAO,OAAO,UAAU;IAC5C,CAAC;GAEF,MAAM,SAAS,OAAO,OAAO,uBAAuB,iBACnD,OAAO,IAAI,aAAa;IAIvB,MAAM,KAAK,IAAI,aAAa;AAC5B,QAAI,OAAO,cAAc,KAAA,EACxB,IAAG,aAAa,OAAO,UAAU;AAElC,OAAG,UAAU,OAAO,QAAQ;AAC5B,OAAG,SAAS;KACX,QAAQ;KACR,eAAe,CAAC,OAAO,aAAa;KACpC,WAAW;MACV,GAAG,OAAO,OAAO,cAAc;MAC/B,GAAG,KAAK,IAAI,OAAO,OAAO;MAC1B,GAAG,KAAK,QAAQ,OAAO,UAAU;MACjC;KACD,CAAC;IAKF,MAAM,UAAU,OAAO,OAAO,WAAW;KACxC,WACC,GAAG,MAAM,EAGR,QAAQ,IAAI,QAKZ,CAAC;KACH,QAAQ,WAAiC;MACxC,MAAM;MACN,QAAQ;MACR,QACC,aAAa,OAAO,aAAa,gCAC9B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;MAC1D;KACD,CAAC;AAKF,WAAO,OAAO,aAAa,eAAe,QAAQ,CAAC,KAClD,OAAO,UACL,WAAiC;KACjC,MAAM;KACN,QAAQ;KACR,QACC,aAAa,OAAO,aAAa,+BAA+B,MAAM;KACvE,EACD,CACD;KACA,CACF;GAOD,MAAM,eAAe,gBAAgB,OAAO,eAAe,OAAO,aAAa;AAC/E,OAAI,iBAAiB,KACpB,QAAO,OAAO,OAAO,KAAK;IACzB,MAAM;IACN,QAAQ;IACR,QACC,aAAa,OAAO,aAAa,uDACR,OAAO,OAAO,OACvC,eAAe,OAAO,cAAc,yCAAyC,CAC3E;IACH,CAAgC;AAGlC,UAAO,OAAO,oBAAoB;IACjC,oBAAoB,OAAO;IAC3B,0BAA0B;IAC1B,CAAC;AAKF,UAAO;IACN,QAAQ,OAAO;IACf;IACA,WAAW,OAAO;IAClB,QAAQ,OAAO,OAAO,UAAU;IAChC;IACA;EAIF,gBAAgB,OAAO;EACvB,CAAC;AAKH,KAAI,kBAAkB,SACrB,QAAO;EACN,QAAQ,SAAS;EACjB,cAAc,SAAS;EACvB,WAAW,SAAS;EACpB,QAAQ,OAAO,SAAS,OAAO;EAC/B,cAAc,OAAO;EACrB;AAMF,QAAO;EACN,QAAQ;EACR,cAAc,SAAS;EACvB,WAAW,OAAO;EAClB,QAAQ,OAAO;EACf,cAAc,OAAO;EACrB;EACA,CAAC,KACF,OAAO,SAAS,aAAa,EAC5B,YAAY;CACX,uBAAuB,OAAO;CAC9B,0BAA0B,OAAO;CACjC,oBAAoB,OAAO,OAAO,UAAU;CAC5C,EACD,CAAC,CACF;AAaF,MAAa,kBAAkB,cAAsB,YACpD,UAAU,cAAc;CACvB,YAAY;CACZ;CACA,CAAC"}
|
|
1
|
+
{"version":3,"file":"mint.mjs","names":["brandContentHash"],"sources":["../../../src/plugins/coin/mint.ts"],"sourcesContent":["// Generic mint — wraps `0x2::coin::mint_and_transfer<T>` in the\n// `ArtifactPublisher` substrate primitive.\n//\n// Distilled-doc 13-coin.md §\"Lifecycle\" §\"mintFromTreasury\":\n//\n// - Cache key: (chainId, treasuryCapId, recipient, amount)\n// - Verify: lenient probe on the cached minted-coin id\n// (Invariant 1 — vanish-detection)\n// - Produce: sign + execute the `mint_and_transfer<T>` tx,\n// find the minted `Coin<T>` in objectChanges\n// - Register: in-memory note of the mint (no global registry —\n// the resolved value carries everything callers\n// need).\n//\n// Best-effort cache writes (distilled-doc Invariant 2): the mint\n// already settled on chain; a state-store IO defect just means the\n// next supervisor cycle re-mints. Don't let a StateStore failure\n// roll back the mint.\n//\n// Substrate constraint: the `ArtifactPublisher.publish` shape\n// already covers cache + verify + produce + register-on-every-cycle.\n// We compose its spec; the substrate dispatches.\n\nimport { Effect, Schema, type Scope } from 'effect';\nimport { Transaction } from '@mysten/sui/transactions';\n\nimport type { ChainId, ContentHash } from '../../substrate/brand.ts';\nimport { contentHash as brandContentHash } from '../../substrate/brand.ts';\nimport { decodeUnknown } from '../../substrate/runtime/runtime-decode.ts';\nimport {\n\tartifactPublishError,\n\ttype ArtifactPublishError,\n\ttype ArtifactPublisher,\n} from '../../primitives/artifact-publisher.ts';\nimport { acquireOnChainArtifact } from '../internal/acquire-on-chain-artifact.ts';\nimport { formatUnknownError } from '../../substrate/runtime/format-unknown-error.ts';\nimport { formatExecutedFailure } from '../../substrate/runtime/sui-execute/index.ts';\nimport { signAndDispatch } from '../../substrate/runtime/sui-execute/sign-and-dispatch.ts';\nimport {\n\tbuildForkImpersonationTransactionBytes,\n\ttype ClientWithCoreApi,\n\ttype ForkImpersonationGasClient,\n} from '../sui/index.ts';\nimport { coinError, type CoinError } from './errors.ts';\nimport { CoinSpans } from './spans.ts';\nimport { isSuiFrameworkObjectForCoin } from './type-strings.ts';\n\n/** Sign+execute surface narrowed from `AccountValue.signAndExecute`.\n * Mirrors the SDK's discriminated `TransactionResult` return shape —\n * on-chain failures are a return variant (`$kind: 'FailedTransaction'`),\n * not an error.\n *\n * Modelled as a proper $kind-discriminated union (not both-optional\n * fields) so consumers do not need non-null assertions after the\n * `result.$kind === 'FailedTransaction'` narrow. We don't import\n * `SignAndExecuteResult` from the Account plugin barrel directly\n * because the success transaction shape consumed here is narrower\n * (only `digest` + `objectChanges`) than the Account plugin's\n * `TxResult` (which adds `effects` + `balanceChanges` — fields the\n * mint produce body does not surface). The shape is structurally\n * compatible — Account's `signAndExecute` widens to this surface. */\nexport type MintSignAndExecuteResult =\n\t| {\n\t\t\treadonly $kind: 'Transaction';\n\t\t\treadonly Transaction: {\n\t\t\t\treadonly digest: string;\n\t\t\t\treadonly objectChanges: ReadonlyArray<unknown>;\n\t\t\t};\n\t }\n\t| {\n\t\t\treadonly $kind: 'FailedTransaction';\n\t\t\treadonly FailedTransaction: {\n\t\t\t\treadonly digest: string;\n\t\t\t\treadonly executionError?: string;\n\t\t\t};\n\t };\n\nexport interface MintTransactionSigner {\n\treadonly signAndExecute: (\n\t\ttx: Uint8Array,\n\t) => Effect.Effect<\n\t\tMintSignAndExecuteResult,\n\t\t{ readonly _tag: 'AccountSignError'; readonly message: string }\n\t>;\n}\n\nexport interface MintSigner extends MintTransactionSigner {\n\treadonly address: string;\n\treadonly withTransactionSigner: <A, E, R>(\n\t\tbody: (signer: MintTransactionSigner) => Effect.Effect<A, E, R>,\n\t) => Effect.Effect<A, E, R>;\n}\n\n/** Cached payload — the stable id verify re-confirms on every cycle.\n * Distilled-doc invariant: the probe MUST consume a STABLE on-chain\n * identifier (the minted Coin<T>'s objectId), NOT a derived hash. */\nexport interface CachedMint {\n\treadonly digest: string;\n\treadonly mintedCoinId: string;\n\treadonly recipient: string;\n\t/** `amount.toString()` — bigint isn't serializable. */\n\treadonly amount: string;\n}\n\n/** Verify-schema: what we expect when probing the minted coin.\n * IMPORTANT (chain-probe schema constraint from the last sweep):\n * schema literal uses ONLY service-free combinators. */\nexport const MintedCoinVerifyShape = Schema.Struct({\n\tobjectId: Schema.String,\n\ttype: Schema.String,\n});\n\n/** Build the cache-key content hash. Distilled-doc 13-coin.md\n * §\"Persistence model\": key shape is\n * `coin/mint/<chainId>/<treasuryCapId>/<signerAddress>/<recipient>/<amount>`.\n * The substrate's artifact publisher folds in chainId via the\n * `chain` parameter; we fold the remaining columns into `contentHash`.\n *\n * `signerAddress` is folded in because the producing signer is part\n * of the cache identity — reusing the same `(treasuryCap, recipient,\n * amount)` under a different signer MUST miss the cache so the new\n * signer actually re-executes the mint. Mirrors the symmetric\n * `publisherAddress` fold in `plugins/package/mode-local.ts:149-152`.\n * Backlog #6. */\nexport const buildMintContentHash = (parts: {\n\treadonly treasuryCapId: string;\n\treadonly recipient: string;\n\treadonly amount: bigint;\n\treadonly signerAddress: string;\n}): ContentHash =>\n\tbrandContentHash(\n\t\t`mint/${parts.treasuryCapId}/${parts.signerAddress}/${parts.recipient}/${parts.amount.toString()}`,\n\t);\n\nexport interface MintInputs {\n\treadonly fullCoinType: string;\n\treadonly treasuryCapId: string;\n\treadonly recipient: string;\n\treadonly amount: bigint;\n\treadonly gasBudget?: bigint;\n}\n\nexport interface MintResult {\n\t/** Tx digest of the producing mint. Surfaces the cached digest on\n\t * verify-hit (the substrate hands back the decoded `CachedMint`\n\t * payload, which carries it). */\n\treadonly digest: string;\n\treadonly mintedCoinId: string;\n\treadonly recipient: string;\n\treadonly amount: bigint;\n\treadonly fullCoinType: string;\n}\n\n/** Sui SDK shim for the verify probe + transaction build.\n *\n * The `core.getObject` field is the verify-probe surface; the\n * `client` field is the build-target the produce body hands to\n * `Transaction.build({ client })`. */\nexport interface MintSdkShim {\n\treadonly core: {\n\t\treadonly getObject: (args: { readonly objectId: string }) => Promise<unknown>;\n\t\t/** Coin selection for the fork-mode offline build (gas + input\n\t\t * resolution). Reuses the fork impersonation gas client's paginating\n\t\t * signature so `sdk.core` satisfies it exactly — selection walks the\n\t\t * coin set via `cursor`/`hasNextPage`, not a single page. */\n\t\treadonly listCoins: ForkImpersonationGasClient['listCoins'];\n\t};\n\t/** Client reference for `Transaction.build({ client })`. The Sui\n\t * barrel hands in the resolved `SuiGrpcClient`. */\n\treadonly client: ClientWithCoreApi;\n\t/** Fork mode — build offline with explicit gas (the sui-fork binary has\n\t * no `simulate_transaction` for the SDK's gas-estimating `tx.build`). */\n\treadonly forkMode?: boolean;\n}\n\n/** Verify probe — checks the cached minted-coin still exists. Lenient:\n * returns `null` for both not-found AND transient failure (distilled-\n * doc invariant: the next cycle re-derives).\n *\n * IMPORTANT (chain-probe schema constraint): the probe pipeline\n * cannot inject services from the caller. We construct the schema\n * literal at module scope (above) and call `decodeUnknownEffect` —\n * which the substrate's `ChainProbe.get` does internally. This local\n * verify mirrors the call-shape so the constraint is honored.\n *\n * We model the verify here as an inline Effect because the cached\n * minted-coin id is known only AFTER cache lookup — the substrate's\n * `verify` Effect closes over the cached id. */\nconst buildVerifyProbe = (\n\tsdk: MintSdkShim,\n\tmintedCoinIdOpt: string | null,\n): Effect.Effect<typeof MintedCoinVerifyShape.Type | null, never> =>\n\tEffect.gen(function* () {\n\t\tif (mintedCoinIdOpt === null) return null;\n\t\tconst raw: unknown = yield* Effect.tryPromise({\n\t\t\ttry: () => sdk.core.getObject({ objectId: mintedCoinIdOpt }),\n\t\t\tcatch: () => 'transient' as const,\n\t\t}).pipe(\n\t\t\t// Lenient: not-found AND transient both coerce to null. The\n\t\t\t// artifact publisher's cache layer will then re-run produce.\n\t\t\tEffect.catch(() => Effect.succeed(null)),\n\t\t);\n\t\tif (raw === null || raw === undefined) return null;\n\t\t// Best-effort decode. A decode failure on the verify path is\n\t\t// treated as \"object exists but shape changed unexpectedly\" —\n\t\t// still null so the substrate re-mints rather than carry stale\n\t\t// data forward.\n\t\treturn yield* decodeUnknown(MintedCoinVerifyShape, raw, {\n\t\t\tsource: 'minted coin verify response',\n\t\t\tmkError: (issue) => issue,\n\t\t}).pipe(Effect.catch(() => Effect.succeed(null as typeof MintedCoinVerifyShape.Type | null)));\n\t});\n\n/** Object-change shape narrowed for `pickCreatedCoin`. The gRPC\n * client emits `objectType` as a fully-qualified Sui type string on\n * `created` entries; we sniff for the `Coin<T>` substring (inner\n * generic carries the full coin type, so the match is unambiguous —\n * distilled-doc 13-coin.md Invariant 9). */\ninterface CreatedObjectChange {\n\treadonly type: 'created';\n\treadonly objectId: string;\n\treadonly objectType?: string;\n}\n\n/** Find the minted `Coin<T>` in a result's objectChanges. Returns the\n * objectId of the first `created` entry whose `objectType` matches\n * `0x2::coin::Coin<${fullCoinType}>` (or its address-normalized equivalent).\n *\n * Returns `null` on no match — the caller maps that to a typed parse\n * error.\n *\n * The SDK can report the Sui framework address as compact `0x2` or\n * fully padded `0x000...0002`, so this uses the shared type-string\n * normalizer instead of substring matching. */\nexport const pickCreatedCoin = (\n\tchanges: ReadonlyArray<unknown>,\n\tfullCoinType: string,\n): string | null => {\n\tfor (const change of changes) {\n\t\tif (!isCreatedObjectChange(change)) continue;\n\t\tif (\n\t\t\ttypeof change.objectType === 'string' &&\n\t\t\tisSuiFrameworkObjectForCoin(change.objectType, 'Coin', fullCoinType)\n\t\t) {\n\t\t\treturn change.objectId;\n\t\t}\n\t}\n\treturn null;\n};\n\nconst isCreatedObjectChange = (raw: unknown): raw is CreatedObjectChange => {\n\tif (raw === null || typeof raw !== 'object') return false;\n\tconst r = raw as { type?: unknown; objectId?: unknown };\n\treturn r.type === 'created' && typeof r.objectId === 'string';\n};\n\n/** Build the `ArtifactPublisher` spec for one mint round.\n *\n * Substrate dispatches: cache lookup, verify-on-hit, produce-on-\n * miss-or-verify-fail, register-on-every-cycle. We hand it the\n * procedures; the substrate handles best-effort cache writes per\n * Invariant 2.\n *\n * The substrate's `publish` returns the `CachedMint` payload on every\n * path (decoded cached payload on verify-hit, fresh produce on miss);\n * we project it directly to `MintResult`. */\nexport const performMint = (\n\tpublisher: ArtifactPublisher,\n\tchain: ChainId,\n\tsigner: MintSigner,\n\tsdk: MintSdkShim,\n\tinputs: MintInputs,\n): Effect.Effect<MintResult, CoinError | ArtifactPublishError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst cacheHash = buildMintContentHash({\n\t\t\ttreasuryCapId: inputs.treasuryCapId,\n\t\t\trecipient: inputs.recipient,\n\t\t\tamount: inputs.amount,\n\t\t\tsignerAddress: signer.address,\n\t\t});\n\n\t\tconst cached: CachedMint = yield* acquireOnChainArtifact<\n\t\t\tCachedMint,\n\t\t\ttypeof MintedCoinVerifyShape.Type\n\t\t>(publisher, {\n\t\t\tnamespace: 'coin-mint',\n\t\t\tchain,\n\t\t\tcontentHash: cacheHash,\n\t\t\t// Verify probe runs on cache hit. The artifact publisher threads the\n\t\t\t// cached payload through to its internal probe — our\n\t\t\t// closure here just hands back a \"null = miss\" signal\n\t\t\t// when the cached id has vanished on chain.\n\t\t\t//\n\t\t\t// The artifact publisher substrate now threads the decoded\n\t\t\t// `CachedMint` into `verify(cached)`; we pull\n\t\t\t// `mintedCoinId` off it and probe the chain. Lenient\n\t\t\t// mode masks transient + not-found → null → substrate\n\t\t\t// re-mints rather than carry a stale digest forward.\n\t\t\tverify: (cached) => buildVerifyProbe(sdk, cached.mintedCoinId),\n\t\t\tproduce: Effect.gen(function* () {\n\t\t\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t\t\t[CoinSpans.mint.recipient]: inputs.recipient,\n\t\t\t\t\t[CoinSpans.mint.fullCoinType]: inputs.fullCoinType,\n\t\t\t\t\t[CoinSpans.mint.amount]: inputs.amount.toString(),\n\t\t\t\t});\n\n\t\t\t\t// Drive build → sign → execute → dispatch via the shared\n\t\t\t\t// `signAndDispatch` helper. On-chain `FailedTransaction`\n\t\t\t\t// is a return value (not an error) — surfaced as a\n\t\t\t\t// `produce-failed` artifact error so the cache treats\n\t\t\t\t// this as a re-run candidate. Successful dispatch\n\t\t\t\t// projects to the cached payload.\n\t\t\t\treturn yield* signAndDispatch({\n\t\t\t\t\tsignerSource: signer,\n\t\t\t\t\tbuildTxBytes: () =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t// 1. Build the Move tx — distilled-doc 13-coin.md\n\t\t\t\t\t\t\t// Invariant 9 pins the call shape:\n\t\t\t\t\t\t\t// `0x2::coin::mint_and_transfer<T>(cap, amount, recipient)`.\n\t\t\t\t\t\t\tconst tx = new Transaction();\n\t\t\t\t\t\t\tif (inputs.gasBudget !== undefined) {\n\t\t\t\t\t\t\t\ttx.setGasBudget(inputs.gasBudget);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttx.setSender(signer.address);\n\t\t\t\t\t\t\ttx.moveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::mint_and_transfer',\n\t\t\t\t\t\t\t\ttypeArguments: [inputs.fullCoinType],\n\t\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\t\ttx.object(inputs.treasuryCapId),\n\t\t\t\t\t\t\t\t\ttx.pure.u64(inputs.amount),\n\t\t\t\t\t\t\t\t\ttx.pure.address(inputs.recipient),\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t// 2. Serialize the tx to BCS bytes while the account lease is\n\t\t\t\t\t\t\t// held. Fork mode must build offline with explicit gas (the\n\t\t\t\t\t\t\t// sui-fork binary has no simulate_transaction); other modes\n\t\t\t\t\t\t\t// use the SDK resolver, which fills gas + object versions.\n\t\t\t\t\t\t\treturn sdk.forkMode === true\n\t\t\t\t\t\t\t\t? yield* buildForkImpersonationTransactionBytes(\n\t\t\t\t\t\t\t\t\t\ttx,\n\t\t\t\t\t\t\t\t\t\tsigner.address,\n\t\t\t\t\t\t\t\t\t\tsdk.core,\n\t\t\t\t\t\t\t\t\t).pipe(\n\t\t\t\t\t\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t\t\t\t\t\t(cause): ArtifactPublishError =>\n\t\t\t\t\t\t\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): fork Transaction.build failed — ${cause.message}`,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: yield* Effect.tryPromise({\n\t\t\t\t\t\t\t\t\t\ttry: () => tx.build({ client: sdk.client }),\n\t\t\t\t\t\t\t\t\t\tcatch: (cause): ArtifactPublishError =>\n\t\t\t\t\t\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): Transaction.build failed — ${formatUnknownError(cause)}`,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}),\n\t\t\t\t\t// 3. Sign + execute via the Account-supplied signer. Map\n\t\t\t\t\t// `AccountSignError` → `ArtifactPublishError`. The\n\t\t\t\t\t// Account plugin's signer handles waitForTransaction internally.\n\t\t\t\t\tmapSignError: (cause): ArtifactPublishError =>\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): signAndExecute failed — ` + cause.message,\n\t\t\t\t\t\t),\n\t\t\t\t\t// 4a. On-chain failure dispatch.\n\t\t\t\t\tonFailed: (failed) =>\n\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): transaction execution failed on-chain ` +\n\t\t\t\t\t\t\t\t\tformatExecutedFailure(failed),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t// 4b. On success, find the minted `Coin<T>` in objectChanges via the\n\t\t\t\t\t// inner-generic match (distilled-doc Invariant 9).\n\t\t\t\t\t// `mint_and_transfer` emits a fresh `Coin<T>` owned by\n\t\t\t\t\t// the recipient; look it up by the\n\t\t\t\t\t// `0x2::coin::Coin<${fullCoinType}>` substring.\n\t\t\t\t\tonSuccess: (ok) =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tconst mintedCoinId = pickCreatedCoin(ok.objectChanges, inputs.fullCoinType);\n\t\t\t\t\t\t\tif (mintedCoinId === null) {\n\t\t\t\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t\t\t\t`coin.mint(${inputs.fullCoinType}): minted Coin<T> not found in ` +\n\t\t\t\t\t\t\t\t\t\t\t`objectChanges (digest=${ok.digest}). ` +\n\t\t\t\t\t\t\t\t\t\t\tmintParseError(inputs.fullCoinType, 'minted Coin<T> absent in objectChanges')\n\t\t\t\t\t\t\t\t\t\t\t\t.message,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t\t\t\t\t\t[CoinSpans.mint.digest]: ok.digest,\n\t\t\t\t\t\t\t\t[CoinSpans.mint.mintedCoinId]: mintedCoinId,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// 5. Return the cached payload. The artifact publisher caches it under\n\t\t\t\t\t\t\t// the content hash; the next cycle's verify probe (on\n\t\t\t\t\t\t\t// cache hit) will lenient-probe `mintedCoinId`.\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tdigest: ok.digest,\n\t\t\t\t\t\t\t\tmintedCoinId,\n\t\t\t\t\t\t\t\trecipient: inputs.recipient,\n\t\t\t\t\t\t\t\tamount: inputs.amount.toString(),\n\t\t\t\t\t\t\t} satisfies CachedMint;\n\t\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t}),\n\t\t});\n\n\t\t// Project the cached payload to MintResult. The substrate\n\t\t// hands back the decoded `CachedMint` on every path.\n\t\treturn {\n\t\t\tdigest: cached.digest,\n\t\t\tmintedCoinId: cached.mintedCoinId,\n\t\t\trecipient: cached.recipient,\n\t\t\tamount: BigInt(cached.amount),\n\t\t\tfullCoinType: inputs.fullCoinType,\n\t\t};\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.coin.mint', {\n\t\t\tattributes: {\n\t\t\t\t[CoinSpans.mint.recipient]: inputs.recipient,\n\t\t\t\t[CoinSpans.mint.fullCoinType]: inputs.fullCoinType,\n\t\t\t\t[CoinSpans.mint.amount]: inputs.amount.toString(),\n\t\t\t},\n\t\t}),\n\t);\n\n/** Project an artifact publisher-wire error back to a CoinError when the consumer\n * wants a coin-side tagged shape. The artifact publisher boundary is generic; this\n * helper recovers the typed `mint-tx` / `mint-parse` phase the cause\n * walker uses. */\nexport const mintTxError = (fullCoinType: string, message: string, cause?: unknown): CoinError =>\n\tcoinError('mint-tx', {\n\t\tidentifier: fullCoinType,\n\t\tmessage,\n\t\t...(cause !== undefined ? { cause } : {}),\n\t});\n\nexport const mintParseError = (fullCoinType: string, message: string): CoinError =>\n\tcoinError('mint-parse', {\n\t\tidentifier: fullCoinType,\n\t\tmessage,\n\t});\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2GA,MAAa,wBAAwB,OAAO,OAAO;CAClD,UAAU,OAAO;CACjB,MAAM,OAAO;CACb,CAAC;;;;;;;;;;;;;AAcF,MAAa,wBAAwB,UAMpCA,YACC,QAAQ,MAAM,cAAc,GAAG,MAAM,cAAc,GAAG,MAAM,UAAU,GAAG,MAAM,OAAO,UAAU,GAChG;;;;;;;;;;;;;;AAwDF,MAAM,oBACL,KACA,oBAEA,OAAO,IAAI,aAAa;AACvB,KAAI,oBAAoB,KAAM,QAAO;CACrC,MAAM,MAAe,OAAO,OAAO,WAAW;EAC7C,WAAW,IAAI,KAAK,UAAU,EAAE,UAAU,iBAAiB,CAAC;EAC5D,aAAa;EACb,CAAC,CAAC,KAGF,OAAO,YAAY,OAAO,QAAQ,KAAK,CAAC,CACxC;AACD,KAAI,QAAQ,QAAQ,QAAQ,KAAA,EAAW,QAAO;AAK9C,QAAO,OAAO,cAAc,uBAAuB,KAAK;EACvD,QAAQ;EACR,UAAU,UAAU;EACpB,CAAC,CAAC,KAAK,OAAO,YAAY,OAAO,QAAQ,KAAiD,CAAC,CAAC;EAC5F;;;;;;;;;;;AAuBH,MAAa,mBACZ,SACA,iBACmB;AACnB,MAAK,MAAM,UAAU,SAAS;AAC7B,MAAI,CAAC,sBAAsB,OAAO,CAAE;AACpC,MACC,OAAO,OAAO,eAAe,YAC7B,4BAA4B,OAAO,YAAY,QAAQ,aAAa,CAEpE,QAAO,OAAO;;AAGhB,QAAO;;AAGR,MAAM,yBAAyB,QAA6C;AAC3E,KAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAU,QAAO;CACpD,MAAM,IAAI;AACV,QAAO,EAAE,SAAS,aAAa,OAAO,EAAE,aAAa;;;;;;;;;;;;AAatD,MAAa,eACZ,WACA,OACA,QACA,KACA,WAEA,OAAO,IAAI,aAAa;CAQvB,MAAM,SAAqB,OAAO,uBAGhC,WAAW;EACZ,WAAW;EACX;EACA,aAbiB,qBAAqB;GACtC,eAAe,OAAO;GACtB,WAAW,OAAO;GAClB,QAAQ,OAAO;GACf,eAAe,OAAO;GACtB,CAQsB;EAWtB,SAAS,WAAW,iBAAiB,KAAK,OAAO,aAAa;EAC9D,SAAS,OAAO,IAAI,aAAa;AAChC,UAAO,OAAO,oBAAoB;KAChC,UAAU,KAAK,YAAY,OAAO;KAClC,UAAU,KAAK,eAAe,OAAO;KACrC,UAAU,KAAK,SAAS,OAAO,OAAO,UAAU;IACjD,CAAC;AAQF,UAAO,OAAO,gBAAgB;IAC7B,cAAc;IACd,oBACC,OAAO,IAAI,aAAa;KAIvB,MAAM,KAAK,IAAI,aAAa;AAC5B,SAAI,OAAO,cAAc,KAAA,EACxB,IAAG,aAAa,OAAO,UAAU;AAElC,QAAG,UAAU,OAAO,QAAQ;AAC5B,QAAG,SAAS;MACX,QAAQ;MACR,eAAe,CAAC,OAAO,aAAa;MACpC,WAAW;OACV,GAAG,OAAO,OAAO,cAAc;OAC/B,GAAG,KAAK,IAAI,OAAO,OAAO;OAC1B,GAAG,KAAK,QAAQ,OAAO,UAAU;OACjC;MACD,CAAC;AAKF,YAAO,IAAI,aAAa,OACrB,OAAO,uCACP,IACA,OAAO,SACP,IAAI,KACJ,CAAC,KACD,OAAO,UACL,UACA,qBACC,kBACA,aAAa,OAAO,aAAa,qCAAqC,MAAM,UAC5E,CACF,CACD,GACA,OAAO,OAAO,WAAW;MACzB,WAAW,GAAG,MAAM,EAAE,QAAQ,IAAI,QAAQ,CAAC;MAC3C,QAAQ,UACP,qBACC,kBACA,aAAa,OAAO,aAAa,gCAAgC,mBAAmB,MAAM,GAC1F;MACF,CAAC;MACH;IAIH,eAAe,UACd,qBACC,kBACA,aAAa,OAAO,aAAa,+BAA+B,MAAM,QACtE;IAEF,WAAW,WACV,OAAO,KACN,qBACC,kBACA,aAAa,OAAO,aAAa,6CAChC,sBAAsB,OAAO,CAC9B,CACD;IAMF,YAAY,OACX,OAAO,IAAI,aAAa;KACvB,MAAM,eAAe,gBAAgB,GAAG,eAAe,OAAO,aAAa;AAC3E,SAAI,iBAAiB,KACpB,QAAO,OAAO,OAAO,KACpB,qBACC,kBACA,aAAa,OAAO,aAAa,uDACP,GAAG,OAAO,OACnC,eAAe,OAAO,cAAc,yCAAyC,CAC3E,QACH,CACD;AAGF,YAAO,OAAO,oBAAoB;OAChC,UAAU,KAAK,SAAS,GAAG;OAC3B,UAAU,KAAK,eAAe;MAC/B,CAAC;AAKF,YAAO;MACN,QAAQ,GAAG;MACX;MACA,WAAW,OAAO;MAClB,QAAQ,OAAO,OAAO,UAAU;MAChC;MACA;IACH,CAAC;IACD;EACF,CAAC;AAIF,QAAO;EACN,QAAQ,OAAO;EACf,cAAc,OAAO;EACrB,WAAW,OAAO;EAClB,QAAQ,OAAO,OAAO,OAAO;EAC7B,cAAc,OAAO;EACrB;EACA,CAAC,KACF,OAAO,SAAS,6BAA6B,EAC5C,YAAY;EACV,UAAU,KAAK,YAAY,OAAO;EAClC,UAAU,KAAK,eAAe,OAAO;EACrC,UAAU,KAAK,SAAS,OAAO,OAAO,UAAU;CACjD,EACD,CAAC,CACF;AAaF,MAAa,kBAAkB,cAAsB,YACpD,UAAU,cAAc;CACvB,YAAY;CACZ;CACA,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineScopedRefMap } from "../../substrate/runtime/scoped-ref-map/service.mjs";
|
|
2
|
+
import "../../substrate/runtime/scoped-ref-map/index.mjs";
|
|
2
3
|
import { Context, Effect, Layer } from "effect";
|
|
3
4
|
//#region src/plugins/coin/registry.ts
|
|
4
5
|
const coinKey = (fullCoinType) => fullCoinType;
|
|
@@ -18,20 +19,16 @@ const wrapRefMap = (refMap) => ({
|
|
|
18
19
|
});
|
|
19
20
|
/** Context.Service tag for the per-stack `CoinRegistry`. Plugins
|
|
20
21
|
* yield this in their acquire body. */
|
|
21
|
-
var CoinRegistryService = class extends Context.Service()("@devstack
|
|
22
|
+
var CoinRegistryService = class extends Context.Service()("@devstack/plugins/coin/CoinRegistry") {};
|
|
22
23
|
/** Scope-bound Layer materializing one `CoinRegistry` per stack
|
|
23
24
|
* scope. Boot wiring (CLI / e2e) provides this once per stack;
|
|
24
25
|
* every coin/package/wallet/faucet plugin in the stack yields the
|
|
25
26
|
* SAME instance via Context. */
|
|
26
|
-
const
|
|
27
|
+
const layerCoinRegistry = Layer.effect(CoinRegistryService, Effect.gen(function* () {
|
|
27
28
|
const refMap = yield* CoinRefMap.Service;
|
|
28
29
|
return CoinRegistryService.of(wrapRefMap(refMap));
|
|
29
30
|
})).pipe(Layer.provide(CoinRefMap.layer));
|
|
30
|
-
/** Capability-key constant for the per-stack registry — siblings
|
|
31
|
-
* (Wallet, Faucet's treasury-cap mint strategy, Manifest emitter)
|
|
32
|
-
* look it up through the StrategyContributor registry. */
|
|
33
|
-
const COIN_REGISTRY_CAPABILITY_KEY = "coin-registry";
|
|
34
31
|
//#endregion
|
|
35
|
-
export {
|
|
32
|
+
export { CoinRegistryService, layerCoinRegistry };
|
|
36
33
|
|
|
37
34
|
//# sourceMappingURL=registry.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.mjs","names":[],"sources":["../../../src/plugins/coin/registry.ts"],"sourcesContent":["// Per-stack CoinRegistry — owned by the L2 Coin plugin.\n//\n// Architecture (ARCHITECTURE.md § Substrate name-blindness): the\n// substrate exposes ONLY the generic `ScopedRefMap<K, V>` primitive;\n// each L2 plugin instantiates it with its own domain shape. The\n// `CoinRecord` shape below carries Sui/Move-coin concepts\n// (`witness`, `treasuryCapId`, `metadataId`, `packageId`,\n// `mvrPlaceholder`, `publishingPackageName`, `moduleName`) — those\n// are L2 concerns, not substrate.\n//\n// The five Sui-specific lookup shapes (`bySymbol`, `byWitness`,\n// `byType`, `list`, `register`) live on the L2 `CoinRegistry`\n// wrapper. The underlying generic primitive only knows `K -> V`;\n// the wrapper iterates the snapshot for the symbol / witness /\n// type-based queries (cardinality is bounded by declared coins\n// per stack, typically < 10).\n//\n// Lifetime: one instance per stack scope (the generic primitive's\n// `layer` is scope-bound). Plugins yield `CoinRegistryService`\n// from their `acquire` body; the boot wiring (CLI / e2e) provides\n// the resolved instance once per stack.\n\nimport { Context, Effect, Layer } from 'effect';\n\nimport {\n\tdefineScopedRefMap,\n\ttype ScopedRefMap,\n} from '../../substrate/runtime/scoped-ref-map/index.ts';\n\n/** Discovered-coin record — the value-shape stored in the registry.\n * Superset of the published-coin shape with discovery-populated\n * metadata fields. */\nexport interface CoinRecord {\n\t/** Registry key — the discovered CoinMetadata symbol, falling\n\t * back to the witness name when metadata is absent. Always\n\t * lower-cased for case-insensitive lookups (the original-case\n\t * `symbol` field carries the display form). */\n\treadonly key: string;\n\t/** Fully-qualified on-chain type — `0xPKG::module::Witness`. */\n\treadonly type: string;\n\t/** Lower-cased witness identifier (e.g. `mock_usdc`). Used for\n\t * the `coin.fromPackage(pkg, 'MOCK_USDC')` lookup. */\n\treadonly witness: string;\n\t/** Lower-cased module name. */\n\treadonly moduleName: string;\n\t/** `0` when CoinMetadata absent. */\n\treadonly decimals: number;\n\t/** Display-case symbol from CoinMetadata. Absent when metadata\n\t * fetch failed / coin had no CoinMetadata. */\n\treadonly symbol?: string;\n\treadonly displayName?: string;\n\treadonly iconUrl?: string;\n\t/** Present when the publisher held the cap at publish time AND\n\t * the cap is still address-owned. */\n\treadonly treasuryCapId?: string;\n\treadonly metadataId?: string;\n\t/** The publishing package's id — load-bearing for the\n\t * package-scoped witness lookup. */\n\treadonly packageId: string;\n\t/** Source-of-truth name of the publishing package (the Package\n\t * plugin's symbolic name, NOT the on-chain packageId). Used to\n\t * format error messages and drive the codegen emitter's\n\t * per-package grouping. */\n\treadonly publishingPackageName: string;\n}\n\n/** Registry key — the fully-qualified on-chain coin type. Branded so\n * the generic primitive's `K extends string` constraint applies\n * without leaking the brand to substrate. */\nexport type CoinKey = string & { readonly _brand: 'CoinKey' };\n\nconst coinKey = (fullCoinType: string): CoinKey => fullCoinType as CoinKey;\n\n/** Per-stack registry of all discovered coins. The five lookup\n * shapes are Sui-specific projections over a generic `K -> V`\n * scope-bound ref-map. */\nexport interface CoinRegistry {\n\treadonly register: (record: CoinRecord) => Effect.Effect<void>;\n\treadonly bySymbol: (symbol: string) => Effect.Effect<ReadonlyArray<CoinRecord>>;\n\treadonly byWitness: (packageName: string, witness: string) => Effect.Effect<CoinRecord | null>;\n\treadonly byType: (fullCoinType: string) => Effect.Effect<CoinRecord | null>;\n\treadonly list: () => Effect.Effect<ReadonlyArray<CoinRecord>>;\n}\n\n// Generic substrate primitive — instantiated once per logical\n// registry. The service identity is namespaced by the `name`\n// argument; substrate stays name-blind (it sees only `K` and `V`).\nconst CoinRefMap = defineScopedRefMap<CoinKey, CoinRecord>('CoinRegistry');\n\nconst wrapRefMap = (refMap: ScopedRefMap<CoinKey, CoinRecord>): CoinRegistry => ({\n\tregister: (record) => refMap.set(coinKey(record.type), record),\n\tbySymbol: (symbol) =>\n\t\trefMap.entries().pipe(\n\t\t\tEffect.map((entries) => {\n\t\t\t\tconst lowered = symbol.toLowerCase();\n\t\t\t\treturn entries\n\t\t\t\t\t.map(([, r]) => r)\n\t\t\t\t\t.filter((r) => r.key === lowered || r.symbol?.toLowerCase() === lowered);\n\t\t\t}),\n\t\t),\n\tbyWitness: (packageName, witness) =>\n\t\trefMap.entries().pipe(\n\t\t\tEffect.map((entries) => {\n\t\t\t\tconst lowered = witness.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tentries\n\t\t\t\t\t\t.map(([, r]) => r)\n\t\t\t\t\t\t.find(\n\t\t\t\t\t\t\t(r) =>\n\t\t\t\t\t\t\t\tr.publishingPackageName === packageName &&\n\t\t\t\t\t\t\t\t(r.witness === lowered || r.symbol?.toLowerCase() === lowered),\n\t\t\t\t\t\t) ?? null\n\t\t\t\t);\n\t\t\t}),\n\t\t),\n\tbyType: (fullCoinType) =>\n\t\trefMap.find(coinKey(fullCoinType)).pipe(Effect.map((hit) => hit ?? null)),\n\tlist: () => refMap.entries().pipe(Effect.map((entries) => entries.map(([, r]) => r))),\n});\n\n/** Context.Service tag for the per-stack `CoinRegistry`. Plugins\n * yield this in their acquire body. */\nexport class CoinRegistryService extends Context.Service<CoinRegistryService, CoinRegistry>()(\n\t'@devstack
|
|
1
|
+
{"version":3,"file":"registry.mjs","names":[],"sources":["../../../src/plugins/coin/registry.ts"],"sourcesContent":["// Per-stack CoinRegistry — owned by the L2 Coin plugin.\n//\n// Architecture (ARCHITECTURE.md § Substrate name-blindness): the\n// substrate exposes ONLY the generic `ScopedRefMap<K, V>` primitive;\n// each L2 plugin instantiates it with its own domain shape. The\n// `CoinRecord` shape below carries Sui/Move-coin concepts\n// (`witness`, `treasuryCapId`, `metadataId`, `packageId`,\n// `mvrPlaceholder`, `publishingPackageName`, `moduleName`) — those\n// are L2 concerns, not substrate.\n//\n// The five Sui-specific lookup shapes (`bySymbol`, `byWitness`,\n// `byType`, `list`, `register`) live on the L2 `CoinRegistry`\n// wrapper. The underlying generic primitive only knows `K -> V`;\n// the wrapper iterates the snapshot for the symbol / witness /\n// type-based queries (cardinality is bounded by declared coins\n// per stack, typically < 10).\n//\n// Lifetime: one instance per stack scope (the generic primitive's\n// `layer` is scope-bound). Plugins yield `CoinRegistryService`\n// from their `acquire` body; the boot wiring (CLI / e2e) provides\n// the resolved instance once per stack.\n\nimport { Context, Effect, Layer } from 'effect';\n\nimport {\n\tdefineScopedRefMap,\n\ttype ScopedRefMap,\n} from '../../substrate/runtime/scoped-ref-map/index.ts';\n\n/** Discovered-coin record — the value-shape stored in the registry.\n * Superset of the published-coin shape with discovery-populated\n * metadata fields. */\nexport interface CoinRecord {\n\t/** Registry key — the discovered CoinMetadata symbol, falling\n\t * back to the witness name when metadata is absent. Always\n\t * lower-cased for case-insensitive lookups (the original-case\n\t * `symbol` field carries the display form). */\n\treadonly key: string;\n\t/** Fully-qualified on-chain type — `0xPKG::module::Witness`. */\n\treadonly type: string;\n\t/** Lower-cased witness identifier (e.g. `mock_usdc`). Used for\n\t * the `coin.fromPackage(pkg, 'MOCK_USDC')` lookup. */\n\treadonly witness: string;\n\t/** Lower-cased module name. */\n\treadonly moduleName: string;\n\t/** `0` when CoinMetadata absent. */\n\treadonly decimals: number;\n\t/** Display-case symbol from CoinMetadata. Absent when metadata\n\t * fetch failed / coin had no CoinMetadata. */\n\treadonly symbol?: string;\n\treadonly displayName?: string;\n\treadonly iconUrl?: string;\n\t/** Present when the publisher held the cap at publish time AND\n\t * the cap is still address-owned. */\n\treadonly treasuryCapId?: string;\n\treadonly metadataId?: string;\n\t/** The publishing package's id — load-bearing for the\n\t * package-scoped witness lookup. */\n\treadonly packageId: string;\n\t/** Source-of-truth name of the publishing package (the Package\n\t * plugin's symbolic name, NOT the on-chain packageId). Used to\n\t * format error messages and drive the codegen emitter's\n\t * per-package grouping. */\n\treadonly publishingPackageName: string;\n}\n\n/** Registry key — the fully-qualified on-chain coin type. Branded so\n * the generic primitive's `K extends string` constraint applies\n * without leaking the brand to substrate. */\nexport type CoinKey = string & { readonly _brand: 'CoinKey' };\n\nconst coinKey = (fullCoinType: string): CoinKey => fullCoinType as CoinKey;\n\n/** Per-stack registry of all discovered coins. The five lookup\n * shapes are Sui-specific projections over a generic `K -> V`\n * scope-bound ref-map. */\nexport interface CoinRegistry {\n\treadonly register: (record: CoinRecord) => Effect.Effect<void>;\n\treadonly bySymbol: (symbol: string) => Effect.Effect<ReadonlyArray<CoinRecord>>;\n\treadonly byWitness: (packageName: string, witness: string) => Effect.Effect<CoinRecord | null>;\n\treadonly byType: (fullCoinType: string) => Effect.Effect<CoinRecord | null>;\n\treadonly list: () => Effect.Effect<ReadonlyArray<CoinRecord>>;\n}\n\n// Generic substrate primitive — instantiated once per logical\n// registry. The service identity is namespaced by the `name`\n// argument; substrate stays name-blind (it sees only `K` and `V`).\nconst CoinRefMap = defineScopedRefMap<CoinKey, CoinRecord>('CoinRegistry');\n\nconst wrapRefMap = (refMap: ScopedRefMap<CoinKey, CoinRecord>): CoinRegistry => ({\n\tregister: (record) => refMap.set(coinKey(record.type), record),\n\tbySymbol: (symbol) =>\n\t\trefMap.entries().pipe(\n\t\t\tEffect.map((entries) => {\n\t\t\t\tconst lowered = symbol.toLowerCase();\n\t\t\t\treturn entries\n\t\t\t\t\t.map(([, r]) => r)\n\t\t\t\t\t.filter((r) => r.key === lowered || r.symbol?.toLowerCase() === lowered);\n\t\t\t}),\n\t\t),\n\tbyWitness: (packageName, witness) =>\n\t\trefMap.entries().pipe(\n\t\t\tEffect.map((entries) => {\n\t\t\t\tconst lowered = witness.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tentries\n\t\t\t\t\t\t.map(([, r]) => r)\n\t\t\t\t\t\t.find(\n\t\t\t\t\t\t\t(r) =>\n\t\t\t\t\t\t\t\tr.publishingPackageName === packageName &&\n\t\t\t\t\t\t\t\t(r.witness === lowered || r.symbol?.toLowerCase() === lowered),\n\t\t\t\t\t\t) ?? null\n\t\t\t\t);\n\t\t\t}),\n\t\t),\n\tbyType: (fullCoinType) =>\n\t\trefMap.find(coinKey(fullCoinType)).pipe(Effect.map((hit) => hit ?? null)),\n\tlist: () => refMap.entries().pipe(Effect.map((entries) => entries.map(([, r]) => r))),\n});\n\n/** Context.Service tag for the per-stack `CoinRegistry`. Plugins\n * yield this in their acquire body. */\nexport class CoinRegistryService extends Context.Service<CoinRegistryService, CoinRegistry>()(\n\t'@devstack/plugins/coin/CoinRegistry',\n) {}\n\n/** Scope-bound Layer materializing one `CoinRegistry` per stack\n * scope. Boot wiring (CLI / e2e) provides this once per stack;\n * every coin/package/wallet/faucet plugin in the stack yields the\n * SAME instance via Context. */\nexport const layerCoinRegistry: Layer.Layer<CoinRegistryService> = Layer.effect(\n\tCoinRegistryService,\n\tEffect.gen(function* () {\n\t\tconst refMap = yield* CoinRefMap.Service;\n\t\treturn CoinRegistryService.of(wrapRefMap(refMap));\n\t}),\n).pipe(Layer.provide(CoinRefMap.layer));\n"],"mappings":";;;;AAuEA,MAAM,WAAW,iBAAkC;AAgBnD,MAAM,aAAa,mBAAwC,eAAe;AAE1E,MAAM,cAAc,YAA6D;CAChF,WAAW,WAAW,OAAO,IAAI,QAAQ,OAAO,KAAK,EAAE,OAAO;CAC9D,WAAW,WACV,OAAO,SAAS,CAAC,KAChB,OAAO,KAAK,YAAY;EACvB,MAAM,UAAU,OAAO,aAAa;AACpC,SAAO,QACL,KAAK,GAAG,OAAO,EAAE,CACjB,QAAQ,MAAM,EAAE,QAAQ,WAAW,EAAE,QAAQ,aAAa,KAAK,QAAQ;GACxE,CACF;CACF,YAAY,aAAa,YACxB,OAAO,SAAS,CAAC,KAChB,OAAO,KAAK,YAAY;EACvB,MAAM,UAAU,QAAQ,aAAa;AACrC,SACC,QACE,KAAK,GAAG,OAAO,EAAE,CACjB,MACC,MACA,EAAE,0BAA0B,gBAC3B,EAAE,YAAY,WAAW,EAAE,QAAQ,aAAa,KAAK,SACvD,IAAI;GAEN,CACF;CACF,SAAS,iBACR,OAAO,KAAK,QAAQ,aAAa,CAAC,CAAC,KAAK,OAAO,KAAK,QAAQ,OAAO,KAAK,CAAC;CAC1E,YAAY,OAAO,SAAS,CAAC,KAAK,OAAO,KAAK,YAAY,QAAQ,KAAK,GAAG,OAAO,EAAE,CAAC,CAAC;CACrF;;;AAID,IAAa,sBAAb,cAAyC,QAAQ,SAA4C,CAC5F,sCACA,CAAC;;;;;AAMF,MAAa,oBAAsD,MAAM,OACxE,qBACA,OAAO,IAAI,aAAa;CACvB,MAAM,SAAS,OAAO,WAAW;AACjC,QAAO,oBAAoB,GAAG,WAAW,OAAO,CAAC;EAChD,CACF,CAAC,KAAK,MAAM,QAAQ,WAAW,MAAM,CAAC"}
|
|
@@ -31,10 +31,48 @@ interface CoinValue extends ResolvedCoin {
|
|
|
31
31
|
readonly amount: bigint;
|
|
32
32
|
readonly treasuryCapId?: string;
|
|
33
33
|
}) => Effect.Effect<MintResult, CoinError | ArtifactPublishError, Scope.Scope>;
|
|
34
|
+
/** Self-contained mint that needs NO external signer — present
|
|
35
|
+
* exactly when `fundingStrategy` is (witness-form coins whose
|
|
36
|
+
* publisher still owns the TreasuryCap). Captures the publisher
|
|
37
|
+
* `MintSigner` + the resolved `treasuryCapId` internally and returns
|
|
38
|
+
* the full `MintResult` (digest + minted-coin id), unlike
|
|
39
|
+
* `fundingStrategy.request` which discards the result.
|
|
40
|
+
*
|
|
41
|
+
* This is the seam the control-plane dashboard mint ACTION drives:
|
|
42
|
+
* the supervisor reads the resolved `CoinValue` and calls this with
|
|
43
|
+
* `{to, amount}` — no signer threading needed, because the
|
|
44
|
+
* treasury-cap-owning publisher signer is already in-process here
|
|
45
|
+
* (the same lease-owning path `fundingStrategy` uses). The Effect is
|
|
46
|
+
* self-scoping (wraps `Effect.scoped` over the artifact-publisher
|
|
47
|
+
* round), so callers run it directly without a surrounding Scope. */
|
|
48
|
+
readonly mintFromCap?: (opts: {
|
|
49
|
+
readonly to: string;
|
|
50
|
+
readonly amount: bigint;
|
|
51
|
+
}) => Effect.Effect<MintResult, CoinError | ArtifactPublishError>;
|
|
34
52
|
/** Centralized funding strategy, present for local package coins
|
|
35
53
|
* whose publisher still owns the TreasuryCap. The coin barrel
|
|
36
54
|
* publishes it under `coinType:<fullCoinType>` so Account funding
|
|
37
|
-
* can mint arbitrary local coins without bespoke example actions.
|
|
55
|
+
* can mint arbitrary local coins without bespoke example actions.
|
|
56
|
+
*
|
|
57
|
+
* The request shape is a NARROWED projection of
|
|
58
|
+
* `AccountFundingRequest` (`{address, amount}` only — the coin
|
|
59
|
+
* strategy doesn't need the resolved account handle since the
|
|
60
|
+
* TreasuryCap-owning publisher signs the mint via its own lease
|
|
61
|
+
* inside `mint → signAndDispatch`). Direct consumers (deepbook
|
|
62
|
+
* seed funding) call `.request({address, amount})` against this
|
|
63
|
+
* narrowed shape; the coin barrel projects the value to the wider
|
|
64
|
+
* `AccountFundingStrategy` cross-plugin contract at the
|
|
65
|
+
* `strategy-contributor` capability boundary (see
|
|
66
|
+
* `coin/index.ts → buildCapabilities`), wrapping the narrow
|
|
67
|
+
* request fn so the account bus's `{address, amount, account}`
|
|
68
|
+
* shape is satisfied honestly at the boundary.
|
|
69
|
+
*
|
|
70
|
+
* The E channel preserves the tagged vocabulary
|
|
71
|
+
* (`CoinError | ArtifactPublishError`) rather than collapsing to
|
|
72
|
+
* `unknown`, so direct consumers can catchTag on the typed
|
|
73
|
+
* errors. The account-side dispatcher's registry lookup narrows
|
|
74
|
+
* the channel to `unknown` at the registry boundary and reads
|
|
75
|
+
* `_tag` defensively. */
|
|
38
76
|
readonly fundingStrategy?: {
|
|
39
77
|
readonly request: (req: {
|
|
40
78
|
readonly address: string;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { coinError } from "./errors.mjs";
|
|
2
|
+
import { CoinSpans } from "./spans.mjs";
|
|
2
3
|
import { resolveBuiltin, resolveByBareType, resolveByWitness } from "./address-resolution.mjs";
|
|
3
4
|
import { performMint } from "./mint.mjs";
|
|
4
5
|
import { Effect } from "effect";
|
|
5
6
|
//#region src/plugins/coin/service.ts
|
|
6
7
|
/** Resolve a coin instance to the tag's resolved value. */
|
|
7
8
|
const acquireCoin = (form, ctx) => Effect.gen(function* () {
|
|
8
|
-
yield* Effect.annotateCurrentSpan({
|
|
9
|
+
yield* Effect.annotateCurrentSpan({ [CoinSpans.form]: form.kind });
|
|
9
10
|
const resolved = yield* (() => {
|
|
10
11
|
switch (form.kind) {
|
|
11
12
|
case "witness": return resolveByWitness(ctx.registry, form.publishingPackageName, form.witness);
|
|
@@ -14,9 +15,9 @@ const acquireCoin = (form, ctx) => Effect.gen(function* () {
|
|
|
14
15
|
}
|
|
15
16
|
})();
|
|
16
17
|
yield* Effect.annotateCurrentSpan({
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
[CoinSpans.fullCoinType]: resolved.fullCoinType,
|
|
19
|
+
[CoinSpans.decimals]: resolved.decimals,
|
|
20
|
+
[CoinSpans.source]: resolved.source
|
|
20
21
|
});
|
|
21
22
|
const mint = (signer, opts) => {
|
|
22
23
|
const capId = opts.treasuryCapId ?? resolved.treasuryCapId;
|
|
@@ -34,6 +35,11 @@ const acquireCoin = (form, ctx) => Effect.gen(function* () {
|
|
|
34
35
|
};
|
|
35
36
|
const fundingSigner = form.kind === "witness" ? form.fundingSigner : void 0;
|
|
36
37
|
const fundingTreasuryCapId = resolved.treasuryCapId;
|
|
38
|
+
const mintFromCap = fundingSigner !== void 0 && fundingTreasuryCapId !== void 0 ? (opts) => Effect.scoped(mint(fundingSigner, {
|
|
39
|
+
to: opts.to,
|
|
40
|
+
amount: opts.amount,
|
|
41
|
+
treasuryCapId: fundingTreasuryCapId
|
|
42
|
+
})) : void 0;
|
|
37
43
|
const fundingStrategy = fundingSigner !== void 0 && fundingTreasuryCapId !== void 0 ? { request: (req) => Effect.scoped(mint(fundingSigner, {
|
|
38
44
|
to: req.address,
|
|
39
45
|
amount: req.amount,
|
|
@@ -42,6 +48,7 @@ const acquireCoin = (form, ctx) => Effect.gen(function* () {
|
|
|
42
48
|
return {
|
|
43
49
|
...resolved,
|
|
44
50
|
mint,
|
|
51
|
+
...mintFromCap === void 0 ? {} : { mintFromCap },
|
|
45
52
|
...fundingStrategy === void 0 ? {} : { fundingStrategy }
|
|
46
53
|
};
|
|
47
54
|
});
|