@mysten-incubation/devstack 0.4.0 → 0.6.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.
Files changed (61) hide show
  1. package/README.md +9 -10
  2. package/dashboard-ui/assets/{grpc-CpkDu4SA.js → grpc-s7Ztk9wv.js} +1 -1
  3. package/dashboard-ui/assets/{index-jLPRmjst.js → index-DrOd0m4F.js} +2 -2
  4. package/dashboard-ui/index.html +1 -1
  5. package/dist/contracts/routable.d.mts +1 -1
  6. package/dist/index.d.mts +3 -3
  7. package/dist/orchestrators/boot.mjs +2 -1
  8. package/dist/orchestrators/boot.mjs.map +1 -1
  9. package/dist/orchestrators/router/file-provider.mjs +11 -8
  10. package/dist/orchestrators/router/file-provider.mjs.map +1 -1
  11. package/dist/orchestrators/router/service.mjs +2 -2
  12. package/dist/orchestrators/router/service.mjs.map +1 -1
  13. package/dist/plugins/deepbook/index.d.mts +36 -6
  14. package/dist/plugins/deepbook/index.mjs +52 -16
  15. package/dist/plugins/deepbook/index.mjs.map +1 -1
  16. package/dist/plugins/seal/codegen.d.mts +5 -0
  17. package/dist/plugins/seal/codegen.mjs +53 -10
  18. package/dist/plugins/seal/codegen.mjs.map +1 -1
  19. package/dist/plugins/seal/index.d.mts +64 -19
  20. package/dist/plugins/seal/index.mjs +26 -36
  21. package/dist/plugins/seal/index.mjs.map +1 -1
  22. package/dist/plugins/seal/mode/fork-known.d.mts +0 -2
  23. package/dist/plugins/seal/mode/fork-known.mjs +11 -22
  24. package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
  25. package/dist/plugins/seal/mode/live.d.mts +36 -13
  26. package/dist/plugins/seal/mode/live.mjs +104 -43
  27. package/dist/plugins/seal/mode/live.mjs.map +1 -1
  28. package/dist/plugins/seal/mode/local-keygen.mjs +2 -1
  29. package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
  30. package/dist/plugins/seal/registry-publish.d.mts +15 -3
  31. package/dist/plugins/seal/registry-publish.mjs.map +1 -1
  32. package/dist/plugins/sui/index.d.mts +10 -10
  33. package/dist/plugins/walrus/client-services.d.mts +1 -0
  34. package/dist/plugins/walrus/client-services.mjs +115 -0
  35. package/dist/plugins/walrus/client-services.mjs.map +1 -0
  36. package/dist/plugins/walrus/deploy.mjs +11 -5
  37. package/dist/plugins/walrus/deploy.mjs.map +1 -1
  38. package/dist/plugins/walrus/errors.d.mts +1 -1
  39. package/dist/plugins/walrus/errors.mjs.map +1 -1
  40. package/dist/plugins/walrus/index.d.mts +138 -9
  41. package/dist/plugins/walrus/index.mjs +72 -20
  42. package/dist/plugins/walrus/index.mjs.map +1 -1
  43. package/dist/plugins/walrus/mode/known-deploy.d.mts +5 -1
  44. package/dist/plugins/walrus/mode/known-deploy.mjs +14 -11
  45. package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
  46. package/dist/plugins/walrus/mode/local-cluster.d.mts +14 -1
  47. package/dist/plugins/walrus/mode/local-cluster.mjs +54 -12
  48. package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
  49. package/dist/plugins/walrus/routable.mjs +12 -15
  50. package/dist/plugins/walrus/routable.mjs.map +1 -1
  51. package/dist/plugins/walrus/snapshot.mjs +3 -2
  52. package/dist/plugins/walrus/snapshot.mjs.map +1 -1
  53. package/dist/plugins/walrus/storage-nodes.mjs +31 -33
  54. package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
  55. package/dist/substrate/runtime/config-validation.mjs +1 -1
  56. package/images/walrus/Dockerfile +17 -4
  57. package/images/walrus/deploy-walrus.sh +7 -4
  58. package/images/walrus/run-walrus-client-service.sh +103 -0
  59. package/package.json +2 -2
  60. package/dist/plugins/seal/service.mjs +0 -17
  61. package/dist/plugins/seal/service.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/plugins/walrus/errors.ts"],"sourcesContent":["// Walrus plugin — typed errors.\n//\n// Errors raised and consumed inside the Walrus plugin live here.\n// Cross-service errors that Walrus *consumes* but the substrate\n// raises (e.g. `ArtifactPublishError`) come from the substrate's\n// primitive — we don't redeclare those.\n//\n// `ForkIncompatibleError` is a cross-cutting mode-refusal shape\n// owned by `substrate/runtime/mode-errors.ts`; walrus contributes\n// the `walrusLocalCluster` variant via the factory below.\n//\n// Effect v4: plain interfaces with `_tag` discriminator (per\n// surrounding subsystem style). `Effect.catchTag` matches on `_tag`.\n\nimport { ForkIncompatibleError } from '../../substrate/runtime/mode-errors.ts';\nimport { defineConfigError, type ConfigIssue } from '../../substrate/runtime/config-validation.ts';\n\nexport { ForkIncompatibleError };\n\n/** Phases for `WalrusError`. Closed sum — keeps the cause-walker's\n * display table small. Matches the closed `WalrusPhases` from the\n * distilled doc §\"Cross-component references\" except `'network'`\n * is dropped (the substrate's `ContainerRuntime` owns docker network\n * creation now, so its errors surface as `ContainerRuntimeError`\n * upstream — we narrate the *phase* as `'cluster-network'` but the\n * fault tags through the substrate). */\nexport type WalrusPhase =\n\t| 'image-build'\n\t| 'cluster-network'\n\t| 'deploy'\n\t| 'exchange'\n\t| 'storage-node'\n\t| 'proxy'\n\t| 'fund-wal'\n\t| 'register-known';\n\n/** Generic Walrus plugin error. Raised by the plugin's acquire\n * body, WAL funding strategy, and the per-mode builders. */\nexport interface WalrusPluginError {\n\treadonly _tag: 'WalrusPluginError';\n\treadonly phase: WalrusPhase;\n\treadonly message: string;\n\treadonly cause?: unknown;\n\t/** Optional sub-process capture envelope — populated for deploy\n\t * one-shot + per-node container failures. */\n\treadonly stderr?: string;\n\treadonly stdout?: string;\n\treadonly exitCode?: number;\n}\n\nexport const walrusPluginError = (\n\tphase: WalrusPhase,\n\tmessage: string,\n\tparts: Omit<WalrusPluginError, '_tag' | 'phase' | 'message'> = {},\n): WalrusPluginError => ({ _tag: 'WalrusPluginError', phase, message, ...parts });\n\n/** Configuration error — synchronous factory-time guards\n * (`nodeCount >= 1`, `shards >= nodeCount`, missing required\n * fields on `.known(...)`). Surfaces as a thrown `Error` shaped\n * like this in the factory, mirroring the distilled-doc behavior\n * of synchronous configuration faults. */\nexport interface WalrusConfigError extends ConfigIssue {\n\treadonly _tag: 'WalrusConfigError';\n}\n\nconst makeWalrusConfigError = defineConfigError('WalrusConfigError');\n\nexport const walrusConfigError = (\n\tfield: string,\n\tmessage: string,\n\thint?: string,\n\tcause?: unknown,\n): WalrusConfigError => makeWalrusConfigError({ field, message, hint, cause });\n\n/** Union of every error a Walrus-plugin caller may encounter. */\nexport type WalrusError = WalrusPluginError | ForkIncompatibleError | WalrusConfigError;\n\n/** The catchable error tags this plugin exposes. Pinned against the\n * user-facing error catalog by the error-catalog-parity test. */\nexport const WALRUS_ERROR_TAGS: ReadonlyArray<WalrusError['_tag']> = [\n\t'WalrusPluginError',\n\t'ForkIncompatibleError',\n\t'WalrusConfigError',\n] as const;\n"],"mappings":";;;AAkDA,MAAa,qBACZ,OACA,SACA,QAA+D,CAAC,OACxC;CAAE,MAAM;CAAqB;CAAO;CAAS,GAAG;AAAM;AAW/E,MAAM,wBAAwB,kBAAkB,mBAAmB;AAEnE,MAAa,qBACZ,OACA,SACA,MACA,UACuB,sBAAsB;CAAE;CAAO;CAAS;CAAM;AAAM,CAAC"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/plugins/walrus/errors.ts"],"sourcesContent":["// Walrus plugin — typed errors.\n//\n// Errors raised and consumed inside the Walrus plugin live here.\n// Cross-service errors that Walrus *consumes* but the substrate\n// raises (e.g. `ArtifactPublishError`) come from the substrate's\n// primitive — we don't redeclare those.\n//\n// `ForkIncompatibleError` is a cross-cutting mode-refusal shape\n// owned by `substrate/runtime/mode-errors.ts`; walrus contributes\n// the `walrusLocalCluster` variant via the factory below.\n//\n// Effect v4: plain interfaces with `_tag` discriminator (per\n// surrounding subsystem style). `Effect.catchTag` matches on `_tag`.\n\nimport { ForkIncompatibleError } from '../../substrate/runtime/mode-errors.ts';\nimport { defineConfigError, type ConfigIssue } from '../../substrate/runtime/config-validation.ts';\n\nexport { ForkIncompatibleError };\n\n/** Phases for `WalrusError`. Closed sum — keeps the cause-walker's\n * display table small. Matches the closed `WalrusPhases` from the\n * distilled doc §\"Cross-component references\" except `'network'`\n * is dropped (the substrate's `ContainerRuntime` owns docker network\n * creation now, so its errors surface as `ContainerRuntimeError`\n * upstream — we narrate the *phase* as `'cluster-network'` but the\n * fault tags through the substrate). */\nexport type WalrusPhase =\n\t| 'image-build'\n\t| 'cluster-network'\n\t| 'deploy'\n\t| 'aggregator'\n\t| 'publisher'\n\t| 'exchange'\n\t| 'storage-node'\n\t| 'proxy'\n\t| 'fund-wal'\n\t| 'register-known';\n\n/** Generic Walrus plugin error. Raised by the plugin's acquire\n * body, WAL funding strategy, and the per-mode builders. */\nexport interface WalrusPluginError {\n\treadonly _tag: 'WalrusPluginError';\n\treadonly phase: WalrusPhase;\n\treadonly message: string;\n\treadonly cause?: unknown;\n\t/** Optional sub-process capture envelope — populated for deploy\n\t * one-shot + per-node container failures. */\n\treadonly stderr?: string;\n\treadonly stdout?: string;\n\treadonly exitCode?: number;\n}\n\nexport const walrusPluginError = (\n\tphase: WalrusPhase,\n\tmessage: string,\n\tparts: Omit<WalrusPluginError, '_tag' | 'phase' | 'message'> = {},\n): WalrusPluginError => ({ _tag: 'WalrusPluginError', phase, message, ...parts });\n\n/** Configuration error — synchronous factory-time guards\n * (`nodeCount >= 1`, `shards >= nodeCount`, missing required\n * fields on `.known(...)`). Surfaces as a thrown `Error` shaped\n * like this in the factory, mirroring the distilled-doc behavior\n * of synchronous configuration faults. */\nexport interface WalrusConfigError extends ConfigIssue {\n\treadonly _tag: 'WalrusConfigError';\n}\n\nconst makeWalrusConfigError = defineConfigError('WalrusConfigError');\n\nexport const walrusConfigError = (\n\tfield: string,\n\tmessage: string,\n\thint?: string,\n\tcause?: unknown,\n): WalrusConfigError => makeWalrusConfigError({ field, message, hint, cause });\n\n/** Union of every error a Walrus-plugin caller may encounter. */\nexport type WalrusError = WalrusPluginError | ForkIncompatibleError | WalrusConfigError;\n\n/** The catchable error tags this plugin exposes. Pinned against the\n * user-facing error catalog by the error-catalog-parity test. */\nexport const WALRUS_ERROR_TAGS: ReadonlyArray<WalrusError['_tag']> = [\n\t'WalrusPluginError',\n\t'ForkIncompatibleError',\n\t'WalrusConfigError',\n] as const;\n"],"mappings":";;;AAoDA,MAAa,qBACZ,OACA,SACA,QAA+D,CAAC,OACxC;CAAE,MAAM;CAAqB;CAAO;CAAS,GAAG;AAAM;AAW/E,MAAM,wBAAwB,kBAAkB,mBAAmB;AAEnE,MAAa,qBACZ,OACA,SACA,MACA,UACuB,sBAAsB;CAAE;CAAO;CAAS;CAAM;AAAM,CAAC"}
@@ -6,7 +6,7 @@ import { AccountFundingCoinValue } from "../account/funding.mjs";
6
6
  import { WalrusConfigError, WalrusError, WalrusPhase, WalrusPluginError } from "./errors.mjs";
7
7
  import { WalFaucetStrategy } from "./faucet-strategy.mjs";
8
8
  import { WalrusStorageNode } from "./storage-nodes.mjs";
9
- import { WalrusLocalClusterOptions } from "./mode/local-cluster.mjs";
9
+ import { WalrusLocalClusterOptions, WalrusLocalPublisherOptions, WalrusLocalServiceOptions } from "./mode/local-cluster.mjs";
10
10
  import { WalrusKnownDeploymentOptions, WalrusKnownNetwork } from "./mode/known-deploy.mjs";
11
11
  import { WalrusBindings, WalrusNodeBinding } from "./codegen.mjs";
12
12
  //#region src/plugins/walrus/index.d.ts
@@ -45,21 +45,36 @@ interface WalCoinValue extends AccountFundingCoinValue {
45
45
  * The funding strategy itself is contributed by the Walrus service
46
46
  * once its local exchange exists. */
47
47
  declare const walCoin: (walrusMember: ResourceRef<"walrus", WalrusResolved>) => Plugin<"coin:wal", WalCoinValue, readonly [ResourceRef<"walrus", WalrusResolved>]>;
48
- /** Local-cluster shorthand. Known deployments are selected through
49
- * `walrusFor(network).known(...)` so network choice stays explicit. */
48
+ /** Local-cluster shorthand. Known deployments are selected through the
49
+ * per-network methods `walrusFor(network).testnet(...)` /
50
+ * `.mainnet(...)` so network choice stays explicit; `.known(...)` is the
51
+ * raw-id override form. */
50
52
  declare const walrus: (opts?: {
51
53
  readonly local?: WalrusLocalClusterOptions;
52
54
  }) => Plugin<"walrus", WalrusResolved, readonly [ResourceRef<"sui", SuiClient & {
53
55
  readonly mode: SuiOptions["mode"];
54
56
  }>]>;
57
+ /** Per-network factory options for `walrusFor(net).testnet()`/`.mainnet()`.
58
+ * The `network` is injected by the namespace method, so the caller only
59
+ * supplies the (still-required) `nodes` committee plus optional per-field
60
+ * overrides — the on-chain ids default from the `@mysten/walrus` SDK package
61
+ * config. Plugin-INTERNAL — deliberately NOT re-exported from `src/index.ts`. */
62
+ type WalrusKnownByNetworkOptions = Omit<WalrusKnownDeploymentOptions, 'network'>;
55
63
  /** Mode-narrowed factory namespace.
56
64
  *
57
65
  * Usage:
58
66
  * const network = { mode: 'local', network: 'localnet' } as const;
59
- * walrusFor(network).local({...}) // OK
60
- * walrusFor(network).known({...}) // type error: 'known' not in 'local' branch
67
+ * walrusFor(network).local({...}) // OK
68
+ * walrusFor(liveNet).testnet({ nodes }) // OK network injected
69
+ * walrusFor(forkNet).local({...}) // compile error: no `.local` on fork
61
70
  *
62
- * Critically, the fork branch exposes ONLY `.known` — calling
71
+ * Per-network methods (`.testnet`/`.mainnet`) inject the network into
72
+ * `buildKnownPlugin`; `nodes` is still REQUIRED, so `.testnet({ nodes })` is
73
+ * the minimal call. `.known(...)` is now the raw-id explicit-override form only
74
+ * (`systemObjectId`/`stakingPoolId`/`nodes`) — the `network`-in-`.known()` path
75
+ * was HARD CUT.
76
+ *
77
+ * Critically, the fork branch exposes NO `.local` — calling
63
78
  * `.local` on a fork-mode network is a **compile error** at the
64
79
  * call site (distilled-doc invariant 12 — type-level refusal). */
65
80
  declare const walrusFor: ModeNamespace<{
@@ -67,7 +82,45 @@ declare const walrusFor: ModeNamespace<{
67
82
  local: (opts?: WalrusLocalClusterOptions) => Plugin<"walrus", WalrusResolved, readonly [ResourceRef<"sui", SuiClient & {
68
83
  readonly mode: SuiOptions["mode"];
69
84
  }>]>;
70
- known: (opts: WalrusKnownDeploymentOptions) => Plugin<"walrus", {
85
+ known: (opts: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
86
+ mode: "known";
87
+ network: string;
88
+ walrusPackageId: null;
89
+ walPackageId: null;
90
+ packageConfig: {
91
+ systemObjectId: string;
92
+ stakingPoolId: string;
93
+ exchangeIds: readonly string[] | undefined;
94
+ };
95
+ nodes: readonly WalrusStorageNode[];
96
+ proxyUrl: string | null;
97
+ aggregatorUrl: string | null;
98
+ publisherUrl: string | null;
99
+ walFaucetStrategy: null;
100
+ walCoinType: null;
101
+ }, readonly [ResourceRef<"sui", SuiClient & {
102
+ readonly mode: SuiOptions["mode"];
103
+ }>]>;
104
+ testnet: (opts?: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
105
+ mode: "known";
106
+ network: string;
107
+ walrusPackageId: null;
108
+ walPackageId: null;
109
+ packageConfig: {
110
+ systemObjectId: string;
111
+ stakingPoolId: string;
112
+ exchangeIds: readonly string[] | undefined;
113
+ };
114
+ nodes: readonly WalrusStorageNode[];
115
+ proxyUrl: string | null;
116
+ aggregatorUrl: string | null;
117
+ publisherUrl: string | null;
118
+ walFaucetStrategy: null;
119
+ walCoinType: null;
120
+ }, readonly [ResourceRef<"sui", SuiClient & {
121
+ readonly mode: SuiOptions["mode"];
122
+ }>]>;
123
+ mainnet: (opts?: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
71
124
  mode: "known";
72
125
  network: string;
73
126
  walrusPackageId: null;
@@ -88,7 +141,45 @@ declare const walrusFor: ModeNamespace<{
88
141
  }>]>;
89
142
  };
90
143
  live: {
91
- known: (opts: WalrusKnownDeploymentOptions) => Plugin<"walrus", {
144
+ known: (opts: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
145
+ mode: "known";
146
+ network: string;
147
+ walrusPackageId: null;
148
+ walPackageId: null;
149
+ packageConfig: {
150
+ systemObjectId: string;
151
+ stakingPoolId: string;
152
+ exchangeIds: readonly string[] | undefined;
153
+ };
154
+ nodes: readonly WalrusStorageNode[];
155
+ proxyUrl: string | null;
156
+ aggregatorUrl: string | null;
157
+ publisherUrl: string | null;
158
+ walFaucetStrategy: null;
159
+ walCoinType: null;
160
+ }, readonly [ResourceRef<"sui", SuiClient & {
161
+ readonly mode: SuiOptions["mode"];
162
+ }>]>;
163
+ testnet: (opts?: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
164
+ mode: "known";
165
+ network: string;
166
+ walrusPackageId: null;
167
+ walPackageId: null;
168
+ packageConfig: {
169
+ systemObjectId: string;
170
+ stakingPoolId: string;
171
+ exchangeIds: readonly string[] | undefined;
172
+ };
173
+ nodes: readonly WalrusStorageNode[];
174
+ proxyUrl: string | null;
175
+ aggregatorUrl: string | null;
176
+ publisherUrl: string | null;
177
+ walFaucetStrategy: null;
178
+ walCoinType: null;
179
+ }, readonly [ResourceRef<"sui", SuiClient & {
180
+ readonly mode: SuiOptions["mode"];
181
+ }>]>;
182
+ mainnet: (opts?: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
92
183
  mode: "known";
93
184
  network: string;
94
185
  walrusPackageId: null;
@@ -109,7 +200,45 @@ declare const walrusFor: ModeNamespace<{
109
200
  }>]>;
110
201
  };
111
202
  fork: {
112
- known: (opts: WalrusKnownDeploymentOptions) => Plugin<"walrus", {
203
+ known: (opts: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
204
+ mode: "known";
205
+ network: string;
206
+ walrusPackageId: null;
207
+ walPackageId: null;
208
+ packageConfig: {
209
+ systemObjectId: string;
210
+ stakingPoolId: string;
211
+ exchangeIds: readonly string[] | undefined;
212
+ };
213
+ nodes: readonly WalrusStorageNode[];
214
+ proxyUrl: string | null;
215
+ aggregatorUrl: string | null;
216
+ publisherUrl: string | null;
217
+ walFaucetStrategy: null;
218
+ walCoinType: null;
219
+ }, readonly [ResourceRef<"sui", SuiClient & {
220
+ readonly mode: SuiOptions["mode"];
221
+ }>]>;
222
+ testnet: (opts?: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
223
+ mode: "known";
224
+ network: string;
225
+ walrusPackageId: null;
226
+ walPackageId: null;
227
+ packageConfig: {
228
+ systemObjectId: string;
229
+ stakingPoolId: string;
230
+ exchangeIds: readonly string[] | undefined;
231
+ };
232
+ nodes: readonly WalrusStorageNode[];
233
+ proxyUrl: string | null;
234
+ aggregatorUrl: string | null;
235
+ publisherUrl: string | null;
236
+ walFaucetStrategy: null;
237
+ walCoinType: null;
238
+ }, readonly [ResourceRef<"sui", SuiClient & {
239
+ readonly mode: SuiOptions["mode"];
240
+ }>]>;
241
+ mainnet: (opts?: WalrusKnownByNetworkOptions) => Plugin<"walrus", {
113
242
  mode: "known";
114
243
  network: string;
115
244
  walrusPackageId: null;
@@ -8,9 +8,10 @@ import { PluginContext, emitContributions } from "../../substrate/plugin-ctx.mjs
8
8
  import { chainProbeFor } from "../../substrate/runtime/strategy-registry/chain-probe-for.mjs";
9
9
  import "../../substrate/runtime/strategy-registry/index.mjs";
10
10
  import { LOCAL_NETWORK_NAME } from "../../api/inference-network.mjs";
11
+ import { renderUrl, routedHostname } from "../../substrate/runtime/routed-url.mjs";
11
12
  import { walrusPluginError } from "./errors.mjs";
12
- import { buildWalrusNetworkName } from "./storage-nodes.mjs";
13
- import { makeLocalRoutables } from "./routable.mjs";
13
+ import { WALRUS_ROUTER_PORT, buildWalrusNetworkName } from "./storage-nodes.mjs";
14
+ import { WALRUS_AGGREGATOR_ENDPOINT_NAME, WALRUS_PUBLISHER_ENDPOINT_NAME, makeLocalRoutables } from "./routable.mjs";
14
15
  import { defineModeNamespace } from "../../api/mode-narrowed-factory.mjs";
15
16
  import { suiResource } from "../sui/index.mjs";
16
17
  import { coinResourceId } from "../coin/index.mjs";
@@ -94,26 +95,38 @@ const buildLocalPlugin = (opts) => {
94
95
  stackRoot: stackPaths.stackRoot
95
96
  }, mode);
96
97
  if (boot.mode !== "local") return yield* Effect.die("walrus: mode mismatch in local plugin");
98
+ const packageConfig = boot.exchangeObjectId === void 0 ? {
99
+ systemObjectId: boot.deploy.systemObject,
100
+ stakingPoolId: boot.deploy.stakingObject
101
+ } : {
102
+ systemObjectId: boot.deploy.systemObject,
103
+ stakingPoolId: boot.deploy.stakingObject,
104
+ exchangeIds: [boot.exchangeObjectId]
105
+ };
106
+ const serviceUrl = (role) => routedHostname(identity, role).pipe(Effect.map((hostname) => renderUrl({
107
+ protocol: "http",
108
+ hostname,
109
+ port: WALRUS_ROUTER_PORT
110
+ })), Effect.mapError((cause) => walrusPluginError("proxy", `walrus route URL assembly failed for ${role}: ${cause.detail}`, { cause })));
111
+ const aggregatorUrl = boot.clientServices.aggregator === null ? null : yield* serviceUrl(WALRUS_AGGREGATOR_ENDPOINT_NAME);
112
+ const publisherUrl = boot.clientServices.publisher === null ? null : yield* serviceUrl(WALRUS_PUBLISHER_ENDPOINT_NAME);
97
113
  const resolvedValue = {
98
114
  mode: "local",
99
115
  network: identity.network,
100
116
  walrusPackageId: boot.walrusPackageId,
101
117
  walPackageId: boot.walPackageId,
102
- packageConfig: {
103
- systemObjectId: boot.deploy.systemObject,
104
- stakingPoolId: boot.deploy.stakingObject,
105
- exchangeIds: boot.exchangeObjectId ? [boot.exchangeObjectId] : void 0
106
- },
118
+ packageConfig,
107
119
  nodes: boot.nodes,
108
- proxyUrl: boot.proxyUrl,
109
- aggregatorUrl: boot.aggregatorUrl,
110
- publisherUrl: boot.publisherUrl,
120
+ proxyUrl: aggregatorUrl,
121
+ aggregatorUrl,
122
+ publisherUrl,
111
123
  walFaucetStrategy: boot.walFaucetStrategy,
112
124
  walCoinType: boot.walCoinType
113
125
  };
114
126
  const walFaucetContribution = resolvedValue.walFaucetStrategy === null || resolvedValue.walCoinType === null ? [] : [makeWalFaucetContribution(resolvedValue.walFaucetStrategy, resolvedValue.walCoinType)];
127
+ const clientServiceRoles = [...boot.clientServices.aggregator === null ? [] : ["aggregator"], ...boot.clientServices.publisher === null ? [] : ["publisher"]];
115
128
  emitContributions(ctx, [
116
- makeSnapshotable("local", identity.app, identity.stack, resolved.name, resolvedValue.network, resolved.nodeCount),
129
+ makeSnapshotable("local", identity.app, identity.stack, resolved.name, resolvedValue.network, resolved.nodeCount, clientServiceRoles),
117
130
  makeCodegenable({
118
131
  mode: "local",
119
132
  network: resolvedValue.network,
@@ -141,7 +154,9 @@ const buildLocalPlugin = (opts) => {
141
154
  walrusName: resolved.name,
142
155
  serviceKey: String(walrusKey),
143
156
  nodeCount: resolved.nodeCount,
144
- containerApiPort: resolved.containerApiPort
157
+ containerApiPort: resolved.containerApiPort,
158
+ aggregator: boot.clientServices.aggregator,
159
+ publisher: boot.clientServices.publisher
145
160
  })
146
161
  ]);
147
162
  return resolvedValue;
@@ -247,8 +262,10 @@ const walCoin = (walrusMember) => {
247
262
  })
248
263
  });
249
264
  };
250
- /** Local-cluster shorthand. Known deployments are selected through
251
- * `walrusFor(network).known(...)` so network choice stays explicit. */
265
+ /** Local-cluster shorthand. Known deployments are selected through the
266
+ * per-network methods `walrusFor(network).testnet(...)` /
267
+ * `.mainnet(...)` so network choice stays explicit; `.known(...)` is the
268
+ * raw-id override form. */
252
269
  const walrus = (opts) => {
253
270
  return buildLocalPlugin(opts?.local ?? {});
254
271
  };
@@ -256,19 +273,54 @@ const walrus = (opts) => {
256
273
  *
257
274
  * Usage:
258
275
  * const network = { mode: 'local', network: 'localnet' } as const;
259
- * walrusFor(network).local({...}) // OK
260
- * walrusFor(network).known({...}) // type error: 'known' not in 'local' branch
276
+ * walrusFor(network).local({...}) // OK
277
+ * walrusFor(liveNet).testnet({ nodes }) // OK network injected
278
+ * walrusFor(forkNet).local({...}) // compile error: no `.local` on fork
279
+ *
280
+ * Per-network methods (`.testnet`/`.mainnet`) inject the network into
281
+ * `buildKnownPlugin`; `nodes` is still REQUIRED, so `.testnet({ nodes })` is
282
+ * the minimal call. `.known(...)` is now the raw-id explicit-override form only
283
+ * (`systemObjectId`/`stakingPoolId`/`nodes`) — the `network`-in-`.known()` path
284
+ * was HARD CUT.
261
285
  *
262
- * Critically, the fork branch exposes ONLY `.known` — calling
286
+ * Critically, the fork branch exposes NO `.local` — calling
263
287
  * `.local` on a fork-mode network is a **compile error** at the
264
288
  * call site (distilled-doc invariant 12 — type-level refusal). */
265
289
  const walrusFor = defineModeNamespace({
266
290
  local: {
267
291
  local: (opts = {}) => buildLocalPlugin(opts),
268
- known: (opts) => buildKnownPlugin(opts)
292
+ known: (opts) => buildKnownPlugin(opts),
293
+ testnet: (opts = {}) => buildKnownPlugin({
294
+ network: "testnet",
295
+ ...opts
296
+ }),
297
+ mainnet: (opts = {}) => buildKnownPlugin({
298
+ network: "mainnet",
299
+ ...opts
300
+ })
301
+ },
302
+ live: {
303
+ known: (opts) => buildKnownPlugin(opts),
304
+ testnet: (opts = {}) => buildKnownPlugin({
305
+ network: "testnet",
306
+ ...opts
307
+ }),
308
+ mainnet: (opts = {}) => buildKnownPlugin({
309
+ network: "mainnet",
310
+ ...opts
311
+ })
269
312
  },
270
- live: { known: (opts) => buildKnownPlugin(opts) },
271
- fork: { known: (opts) => buildKnownPlugin(opts) }
313
+ fork: {
314
+ known: (opts) => buildKnownPlugin(opts),
315
+ testnet: (opts = {}) => buildKnownPlugin({
316
+ network: "testnet",
317
+ ...opts
318
+ }),
319
+ mainnet: (opts = {}) => buildKnownPlugin({
320
+ network: "mainnet",
321
+ ...opts
322
+ })
323
+ }
272
324
  });
273
325
  //#endregion
274
326
  export { walCoin, walrus, walrusFor };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/walrus/index.ts"],"sourcesContent":["// Walrus plugin — barrel + factories.\n//\n// Architecture: Walrus is a service plugin that owns a local cluster\n// or describes a known deployment. The factory at this file folds the\n// four modes behind:\n//\n// - `walrus(opts?)` — local-cluster shorthand. No env\n// defaulting; use `walrusFor(...)`\n// for known deployments.\n// - `walrusFor(network)` — mode-narrowed factory namespace\n// (architecture Tension 11). Returns\n// `{ local: …, known: … }` narrowed\n// to the network's mode. Crucially,\n// the fork branch exposes ONLY\n// `.known` — `.local` is a compile\n// error on a fork-mode network.\n//\n// During `start`, the plugin emits (via the typed `ctx.*` verbs, per mode):\n//\n// Local mode (full local cluster):\n// 1. `ctx.snapshotExtra` — runtime/walrus/<name>/deploy/ subtree\n// + storage-node managed containers.\n// 2. `ctx.codegen` — `walrus-network` bindings.\n// 3. `ctx.endpoint` × (N+2) — per-node + aggregator + publisher.\n// 4. `ctx.provides` walrus-state-registry — local entry.\n// 5. `ctx.provides` endpoint-registry — N+2 entries.\n// 6. `ctx.provides` package-registry — `walrus.<name>`.\n// 7. `ctx.provides` coinType:<WAL fullCoinType> — WAL faucet\n// strategy\n// (when exchange exists).\n//\n// Known mode (read-only deployment):\n// 1. `ctx.snapshotExtra` — identity-guard only; no subtrees.\n// 2. `ctx.codegen` — `walrus-network` bindings (mode='known').\n// 3. `ctx.provides` walrus-state-registry — known entry.\n//\n// Resource id: `'walrus'` (singular). The plugin's substrate-level\n// plugin key is the same string.\n\nimport { Effect, Path } from 'effect';\n\nimport { defineModeNamespace } from '../../api/mode-narrowed-factory.ts';\nimport { definePlugin, resource, type ResourceRef } from '../../api/define-plugin.ts';\nimport type { ContainerRuntime } from '../../contracts/container-runtime.ts';\nimport type { RoutableDecl } from '../../contracts/routable.ts';\nimport type { StrategyContributorDecl } from '../../contracts/strategy-contributor.ts';\nimport { emitContributions, PluginContext } from '../../substrate/plugin-ctx.ts';\nimport { ContainerRuntimeService } from '../../runtime/docker/service.ts';\nimport { IdentityContext, StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { CacheService } from '../../substrate/runtime/cache/index.ts';\nimport { deriveSubnetPrefix, withSubnetAddressing } from '../../substrate/runtime/subnet-broker.ts';\nimport type { AccountFundingCoinValue } from '../account/index.ts';\nimport { coinResourceId, type CoinResourceId } from '../coin/index.ts';\nimport { suiResource, type SuiProbeKey } from '../sui/index.ts';\n\nimport { chainProbeFor } from '../../substrate/runtime/strategy-registry/index.ts';\n\nimport { makeCodegenable, makeWalrusStaticCodegen } from './codegen.ts';\nimport { LOCAL_NETWORK_NAME } from '../../api/inference-network.ts';\nimport { walrusPluginKey } from './plugin-key.ts';\nimport { walrusPluginError, type WalrusPluginError } from './errors.ts';\nimport { makeWalFaucetContribution, type WalFaucetStrategy } from './faucet-strategy.ts';\nimport { bootWalrusService, type WalrusMode } from './service.ts';\nimport {\n\tresolveLocalClusterOptions,\n\ttype WalrusLocalClusterOptions,\n} from './mode/local-cluster.ts';\nimport {\n\tresolveKnownDeploymentOptions,\n\ttype WalrusKnownDeploymentOptions,\n} from './mode/known-deploy.ts';\nimport { makeSnapshotable, type WalrusSnapshotMode } from './snapshot.ts';\nimport { makeLocalRoutables } from './routable.ts';\nimport { WALRUS_STATE_REGISTRY_KEY, type WalrusStateEntry } from './registry-publish.ts';\nimport { buildWalrusNetworkName, type WalrusStorageNode } from './storage-nodes.ts';\n\n// ---------------------------------------------------------------------------\n// Resource — the resolved value all consumers read\n// ---------------------------------------------------------------------------\n\n/** The Walrus resolved value carried by the resource. */\nexport interface WalrusResolved {\n\treadonly mode: 'local' | 'known';\n\t/** Network name the walrus deployment targets (`localnet`/`testnet`/…). */\n\treadonly network: string;\n\treadonly walrusPackageId: string | null;\n\treadonly walPackageId: string | null;\n\t/** SDK-ready `packageConfig` — structurally compatible with\n\t * `@mysten/walrus`'s `WalrusPackageConfig`. */\n\treadonly packageConfig: {\n\t\treadonly systemObjectId: string;\n\t\treadonly stakingPoolId: string;\n\t\treadonly exchangeIds?: ReadonlyArray<string>;\n\t};\n\treadonly nodes: ReadonlyArray<WalrusStorageNode>;\n\treadonly proxyUrl: string | null;\n\treadonly aggregatorUrl: string | null;\n\treadonly publisherUrl: string | null;\n\treadonly walFaucetStrategy: WalFaucetStrategy | null;\n\treadonly walCoinType: string | null;\n}\n\n/** Walrus plugin resource. */\nexport const walrusResource = resource<'walrus', WalrusResolved>('walrus');\n\nexport interface WalrusNetworkIdentity {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly walrusName: string;\n}\n\n/** Walrus deploy records storage-node listening IPs under this /24.\n * Docker network create requests the matching subnet explicitly, with\n * the prefix derived from the Walrus network identity so parallel\n * stacks don't all claim the same Docker IPAM range. Walrus claims\n * the `10.64.*` – `10.127.*` band; see substrate/runtime/subnet-broker.ts\n * for the algorithm and band coordination with seal. */\nexport const deriveWalrusSubnetPrefix = (identity: WalrusNetworkIdentity): string =>\n\tderiveSubnetPrefix(`${identity.app}\\0${identity.stack}\\0${identity.walrusName}`, 64);\n\nconst withWalrusNetworkAddressing = (\n\truntime: ContainerRuntime,\n\twalrusNetworkName: string,\n\tsubnetPrefix: string,\n): ContainerRuntime => ({\n\t...runtime,\n\tensureNetwork: (spec) =>\n\t\truntime.ensureNetwork(\n\t\t\tspec.name === walrusNetworkName ? withSubnetAddressing(spec, subnetPrefix) : spec,\n\t\t),\n});\n\n// ---------------------------------------------------------------------------\n// Plugin construction (internal — used by walrus() + walrusFor())\n// ---------------------------------------------------------------------------\n\nconst buildLocalPlugin = (opts: WalrusLocalClusterOptions) => {\n\t// Synchronous factory-time validation (distilled-doc invariants\n\t// 11 — `nodeCount >= 1` + `shards >= nodeCount`).\n\tconst resolved = resolveLocalClusterOptions(opts);\n\n\tconst walrusKey = walrusPluginKey(resolved.name);\n\n\treturn definePlugin({\n\t\tid: walrusResource.id,\n\t\tdependsOn: [suiResource] as const,\n\t\trole: 'service',\n\t\tsection: 'service',\n\t\tpluginKey: walrusKey,\n\t\t// Stack-free codegen: a local walrus cluster's deploy ids / endpoint\n\t\t// URLs are LOADED CONFIG DATA -- the committed `walrus.ts` stub emits\n\t\t// `requireValue(dep, 'walrus', '<key>')`, never a baked object id / URL.\n\t\tstaticCodegen: () => [makeWalrusStaticCodegen({ mode: 'local', network: LOCAL_NETWORK_NAME })],\n\t\t// `deps` auto-infers the resolved `[sui]` tuple from the\n\t\t// `[suiResource] as const` dependency. `ctx` arrives via the\n\t\t// `PluginContext` service.\n\t\tstart: (deps) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst ctx = yield* PluginContext;\n\t\t\t\tconst [sui] = deps;\n\n\t\t\t\t// Substrate-context primitives:\n\t\t\t\t// - `ContainerRuntimeService` + `IdentityContext` arrive\n\t\t\t\t// via the supervisor's plugin runtime context.\n\t\t\t\t// - `ArtifactPublisher` is the substrate-level\n\t\t\t\t// publisher (cache → verify → produce → register cycle).\n\t\t\t\t// - `ChainProbe<SuiProbeKey>` is looked up via the\n\t\t\t\t// StrategyRegistry under `chain-probe:<chainId>`;\n\t\t\t\t// Sui registered itself there at its own acquire.\n\t\t\t\t// - `StackPathsService` resolves the per-stack on-disk\n\t\t\t\t// root so the deploy-output bind-mount source is a\n\t\t\t\t// real path (not the `<runtime>/...` template).\n\t\t\t\tconst runtime = yield* ContainerRuntimeService;\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst stackPaths = yield* StackPathsService;\n\t\t\t\tconst path = yield* Path.Path;\n\t\t\t\tconst publisher = yield* CacheService;\n\t\t\t\tconst probe = yield* chainProbeFor<SuiProbeKey>(sui.chainId);\n\n\t\t\t\t// Resolve the deploy-output bind-mount source from the\n\t\t\t\t// per-stack paths bundle. The deploy one-shot owns preparing\n\t\t\t\t// the directory immediately before its Docker bind mount.\n\t\t\t\tconst deployHostMountPath = path.join(\n\t\t\t\t\tstackPaths.stackRoot,\n\t\t\t\t\t'walrus',\n\t\t\t\t\tresolved.name,\n\t\t\t\t\t'deploy',\n\t\t\t\t);\n\n\t\t\t\t// Cross-container DNS: walrus containers (deploy one-shot\n\t\t\t\t// + N storage nodes) dial sui RPC + faucet via\n\t\t\t\t// `host.docker.internal`. The sui plugin binds brokered\n\t\t\t\t// host ports — no shared docker network needed.\n\t\t\t\t//\n\t\t\t\t// Architectural decision (B5): walrus owns its OWN docker\n\t\t\t\t// network for storage-node ↔ deploy connectivity; sui-side\n\t\t\t\t// hops go through the host gateway.\n\t\t\t\t// On Linux this requires Docker Desktop or the\n\t\t\t\t// `host.docker.internal:host-gateway` runtime hint (the\n\t\t\t\t// established devstack convention — see plugins/deepbook\n\t\t\t\t// which uses the same pattern).\n\t\t\t\tconst walrusNetworkName = buildWalrusNetworkName(\n\t\t\t\t\tidentity.app,\n\t\t\t\t\tidentity.stack,\n\t\t\t\t\tresolved.name,\n\t\t\t\t);\n\t\t\t\tconst walrusSubnetPrefix = deriveWalrusSubnetPrefix({\n\t\t\t\t\tapp: identity.app,\n\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\twalrusName: resolved.name,\n\t\t\t\t});\n\t\t\t\tconst walrusRuntime = withWalrusNetworkAddressing(\n\t\t\t\t\truntime,\n\t\t\t\t\twalrusNetworkName,\n\t\t\t\t\twalrusSubnetPrefix,\n\t\t\t\t);\n\t\t\t\tconst suiRpcUrlInNetwork = sui.hostGateway.rpcUrl;\n\t\t\t\t// sui-faucet v2 endpoint — `/v2/gas` is the supported path\n\t\t\t\t// on devnet-v1.71.0+.\n\t\t\t\tconst suiFaucetUrlInNetwork = sui.hostGateway.faucetUrl;\n\t\t\t\tif (suiFaucetUrlInNetwork === null) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t'deploy',\n\t\t\t\t\t\t\t'walrus local-cluster requires a Sui faucet URL for deploy funding.',\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst walrusFaucetUrlInNetwork = `${suiFaucetUrlInNetwork}/v2/gas`;\n\n\t\t\t\tconst mode: WalrusMode = { mode: 'local', opts: resolved };\n\t\t\t\tconst boot = yield* bootWalrusService(\n\t\t\t\t\t{\n\t\t\t\t\t\truntime: walrusRuntime,\n\t\t\t\t\t\tpublisher,\n\t\t\t\t\t\tprobe,\n\t\t\t\t\t\tsuiSdk: sui.sdk,\n\t\t\t\t\t\tsuiChainId: sui.chainId,\n\t\t\t\t\t\tsuiRpcUrlInNetwork,\n\t\t\t\t\t\twalrusFaucetUrlInNetwork,\n\t\t\t\t\t\twaitForFundsReady: sui.waitForTransactionsReady.wait,\n\t\t\t\t\t\tapp: identity.app,\n\t\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\t\tsubnetPrefix: walrusSubnetPrefix,\n\t\t\t\t\t\twalrusNetworkName,\n\t\t\t\t\t\t// Walrus has no `sui-net` to attach to (sui binds\n\t\t\t\t\t\t// host ports). Reuse the walrus network so the\n\t\t\t\t\t\t// deploy one-shot + storage nodes land on a single\n\t\t\t\t\t\t// network and reach sui via `host.docker.internal`.\n\t\t\t\t\t\tsuiNetworkName: walrusNetworkName,\n\t\t\t\t\t\tdeployHostMountPath,\n\t\t\t\t\t\tstackRoot: stackPaths.stackRoot,\n\t\t\t\t\t},\n\t\t\t\t\tmode,\n\t\t\t\t);\n\n\t\t\t\tif (boot.mode !== 'local') {\n\t\t\t\t\t// Should be unreachable — dispatch is by mode. Defense.\n\t\t\t\t\treturn yield* Effect.die('walrus: mode mismatch in local plugin');\n\t\t\t\t}\n\n\t\t\t\tconst resolvedValue: WalrusResolved = {\n\t\t\t\t\tmode: 'local',\n\t\t\t\t\tnetwork: identity.network,\n\t\t\t\t\twalrusPackageId: boot.walrusPackageId,\n\t\t\t\t\twalPackageId: boot.walPackageId,\n\t\t\t\t\tpackageConfig: {\n\t\t\t\t\t\tsystemObjectId: boot.deploy.systemObject,\n\t\t\t\t\t\tstakingPoolId: boot.deploy.stakingObject,\n\t\t\t\t\t\texchangeIds: boot.exchangeObjectId ? [boot.exchangeObjectId] : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tnodes: boot.nodes,\n\t\t\t\t\tproxyUrl: boot.proxyUrl,\n\t\t\t\t\taggregatorUrl: boot.aggregatorUrl,\n\t\t\t\t\tpublisherUrl: boot.publisherUrl,\n\t\t\t\t\twalFaucetStrategy: boot.walFaucetStrategy,\n\t\t\t\t\twalCoinType: boot.walCoinType,\n\t\t\t\t};\n\t\t\t\t// Emit the resolved contributions inline: snapshot → codegen →\n\t\t\t\t// state-registry → (optional WAL faucet) → routables. `identity`\n\t\t\t\t// (from `IdentityContext`) stamps the snapshot + routable\n\t\t\t\t// container names. ID-stability surfaces (deploy/blob ids via\n\t\t\t\t// ArtifactPublisher) live OUTSIDE this emission and are untouched.\n\t\t\t\tconst walFaucetContribution: ReadonlyArray<StrategyContributorDecl> =\n\t\t\t\t\tresolvedValue.walFaucetStrategy === null || resolvedValue.walCoinType === null\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tmakeWalFaucetContribution(\n\t\t\t\t\t\t\t\t\tresolvedValue.walFaucetStrategy,\n\t\t\t\t\t\t\t\t\tresolvedValue.walCoinType,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t];\n\t\t\t\temitContributions(ctx, [\n\t\t\t\t\tmakeSnapshotable(\n\t\t\t\t\t\t'local' satisfies WalrusSnapshotMode,\n\t\t\t\t\t\tidentity.app,\n\t\t\t\t\t\tidentity.stack,\n\t\t\t\t\t\tresolved.name,\n\t\t\t\t\t\tresolvedValue.network,\n\t\t\t\t\t\tresolved.nodeCount,\n\t\t\t\t\t),\n\t\t\t\t\tmakeCodegenable({\n\t\t\t\t\t\tmode: 'local',\n\t\t\t\t\t\tnetwork: resolvedValue.network,\n\t\t\t\t\t\twalrusPackageId: resolvedValue.walrusPackageId,\n\t\t\t\t\t\twalPackageId: resolvedValue.walPackageId,\n\t\t\t\t\t\twalCoinType: resolvedValue.walCoinType,\n\t\t\t\t\t\tsystemObjectId: resolvedValue.packageConfig.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolvedValue.packageConfig.stakingPoolId,\n\t\t\t\t\t\texchangeIds: resolvedValue.packageConfig.exchangeIds\n\t\t\t\t\t\t\t? [...resolvedValue.packageConfig.exchangeIds]\n\t\t\t\t\t\t\t: [],\n\t\t\t\t\t\tproxyUrl: resolvedValue.proxyUrl,\n\t\t\t\t\t\taggregatorUrl: resolvedValue.aggregatorUrl,\n\t\t\t\t\t\tpublisherUrl: resolvedValue.publisherUrl,\n\t\t\t\t\t\tnodes: resolvedValue.nodes,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: 'strategy-contributor',\n\t\t\t\t\t\tcapabilityKey: WALRUS_STATE_REGISTRY_KEY,\n\t\t\t\t\t\tstrategy: { noteName: resolved.name },\n\t\t\t\t\t\tautoMounted: true,\n\t\t\t\t\t} satisfies StrategyContributorDecl<\n\t\t\t\t\t\ttypeof WALRUS_STATE_REGISTRY_KEY,\n\t\t\t\t\t\t{ readonly noteName: string }\n\t\t\t\t\t>,\n\t\t\t\t\t...walFaucetContribution,\n\t\t\t\t\t...(makeLocalRoutables({\n\t\t\t\t\t\tapp: identity.app,\n\t\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\t\twalrusName: resolved.name,\n\t\t\t\t\t\tserviceKey: String(walrusKey),\n\t\t\t\t\t\tnodeCount: resolved.nodeCount,\n\t\t\t\t\t\tcontainerApiPort: resolved.containerApiPort,\n\t\t\t\t\t}) as readonly RoutableDecl[]),\n\t\t\t\t]);\n\t\t\t\treturn resolvedValue;\n\t\t\t}),\n\t});\n};\n\nconst buildKnownPlugin = (opts: WalrusKnownDeploymentOptions) => {\n\t// Synchronous factory-time validation for required deployment ids.\n\tconst resolved = resolveKnownDeploymentOptions(opts);\n\n\treturn definePlugin({\n\t\tid: walrusResource.id,\n\t\tdependsOn: [suiResource] as const,\n\t\t// Known deployment is a pure value-producer — no containers,\n\t\t// no long-running children.\n\t\trole: 'task',\n\t\tsection: 'service',\n\t\t// Stack-free codegen: a known deployment's ids / URLs are DECLARED\n\t\t// config (not loaded-at-runtime data) — bake them as literals in the\n\t\t// committed `walrus.ts` (mirrors `knownPackage`). `walrusPackageId` /\n\t\t// `walPackageId` / `walCoinType` are null for a known deployment.\n\t\tstaticCodegen: () => [\n\t\t\tmakeWalrusStaticCodegen({\n\t\t\t\tmode: 'known',\n\t\t\t\tnetwork: resolved.network,\n\t\t\t\tknown: {\n\t\t\t\t\twalrusPackageId: null,\n\t\t\t\t\twalPackageId: null,\n\t\t\t\t\twalCoinType: null,\n\t\t\t\t\tpackageConfig: {\n\t\t\t\t\t\tsystemObjectId: resolved.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolved.stakingPoolId,\n\t\t\t\t\t\t...(resolved.exchangeIds.length > 0 ? { exchangeIds: [...resolved.exchangeIds] } : {}),\n\t\t\t\t\t},\n\t\t\t\t\tproxyUrl: resolved.proxyUrl,\n\t\t\t\t\taggregatorUrl: resolved.aggregatorUrl,\n\t\t\t\t\tpublisherUrl: resolved.publisherUrl,\n\t\t\t\t\tnodes: resolved.nodes,\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t\t// Known mode is a pure value-producer — `sui` is unused (the value\n\t\t// reads `resolved.network` from the deployment options) but the\n\t\t// `dependsOn` edge still orders boot, so `start` is zero-arg.\n\t\t// `ctx` arrives via the `PluginContext` service.\n\t\tstart: () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst ctx = yield* PluginContext;\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst resolvedValue = {\n\t\t\t\t\tmode: 'known',\n\t\t\t\t\tnetwork: resolved.network,\n\t\t\t\t\twalrusPackageId: null,\n\t\t\t\t\twalPackageId: null,\n\t\t\t\t\tpackageConfig: {\n\t\t\t\t\t\tsystemObjectId: resolved.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolved.stakingPoolId,\n\t\t\t\t\t\texchangeIds: resolved.exchangeIds.length > 0 ? resolved.exchangeIds : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tnodes: resolved.nodes,\n\t\t\t\t\tproxyUrl: resolved.proxyUrl,\n\t\t\t\t\taggregatorUrl: resolved.aggregatorUrl,\n\t\t\t\t\tpublisherUrl: resolved.publisherUrl,\n\t\t\t\t\twalFaucetStrategy: null,\n\t\t\t\t\twalCoinType: null,\n\t\t\t\t} satisfies WalrusResolved;\n\t\t\t\t// Emit inline: snapshot → codegen → state-registry. Known mode\n\t\t\t\t// emits no routable. `identity` (from `IdentityContext`) stamps\n\t\t\t\t// the snapshot scoping.\n\t\t\t\tctx.snapshotExtra(\n\t\t\t\t\tmakeSnapshotable(\n\t\t\t\t\t\t'known' satisfies WalrusSnapshotMode,\n\t\t\t\t\t\tidentity.app,\n\t\t\t\t\t\tidentity.stack,\n\t\t\t\t\t\t'walrusKnownDeployment',\n\t\t\t\t\t\tresolvedValue.network,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tctx.codegen(\n\t\t\t\t\tmakeCodegenable({\n\t\t\t\t\t\tmode: 'known',\n\t\t\t\t\t\tnetwork: resolvedValue.network,\n\t\t\t\t\t\twalrusPackageId: resolvedValue.walrusPackageId,\n\t\t\t\t\t\twalPackageId: resolvedValue.walPackageId,\n\t\t\t\t\t\twalCoinType: resolvedValue.walCoinType,\n\t\t\t\t\t\tsystemObjectId: resolvedValue.packageConfig.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolvedValue.packageConfig.stakingPoolId,\n\t\t\t\t\t\texchangeIds: resolvedValue.packageConfig.exchangeIds\n\t\t\t\t\t\t\t? [...resolvedValue.packageConfig.exchangeIds]\n\t\t\t\t\t\t\t: [],\n\t\t\t\t\t\tproxyUrl: resolvedValue.proxyUrl,\n\t\t\t\t\t\taggregatorUrl: resolvedValue.aggregatorUrl,\n\t\t\t\t\t\tpublisherUrl: resolvedValue.publisherUrl,\n\t\t\t\t\t\tnodes: resolvedValue.nodes,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tctx.provides({\n\t\t\t\t\tkind: 'strategy-contributor',\n\t\t\t\t\tcapabilityKey: WALRUS_STATE_REGISTRY_KEY,\n\t\t\t\t\tstrategy: {\n\t\t\t\t\t\tname: 'walrusKnownDeployment',\n\t\t\t\t\t\tsystemObjectId: resolvedValue.packageConfig.systemObjectId,\n\t\t\t\t\t\tstakingObjectId: resolvedValue.packageConfig.stakingPoolId,\n\t\t\t\t\t\tnetwork: resolvedValue.network,\n\t\t\t\t\t},\n\t\t\t\t\tautoMounted: true,\n\t\t\t\t} satisfies StrategyContributorDecl<typeof WALRUS_STATE_REGISTRY_KEY, WalrusStateEntry>);\n\t\t\t\treturn resolvedValue;\n\t\t\t}),\n\t});\n};\n\nexport interface WalCoinValue extends AccountFundingCoinValue {\n\treadonly symbol: 'WAL';\n\treadonly fullCoinType: `${string}::wal::WAL`;\n\treadonly decimals: 9;\n\treadonly source: 'walrus';\n}\n\n/** Resolve the local Walrus deployment's WAL coin as an account-funding\n * coin ref. Accounts that need WAL should use:\n *\n * funding: [{ coin: walCoin(localWalrus), amount }]\n *\n * The funding strategy itself is contributed by the Walrus service\n * once its local exchange exists. */\nexport const walCoin = (walrusMember: ResourceRef<'walrus', WalrusResolved>) => {\n\tconst coinRef = resource<CoinResourceId<'wal'>, WalCoinValue>(coinResourceId('wal'));\n\n\treturn definePlugin({\n\t\tid: coinRef.id,\n\t\tdependsOn: walrusMember,\n\t\trole: 'task',\n\t\tsection: 'action',\n\t\tstart: (resolved): Effect.Effect<WalCoinValue, WalrusPluginError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tif (resolved.walCoinType === null) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t'exchange',\n\t\t\t\t\t\t\t'walCoin(...) requires a local Walrus deployment with a WAL package.',\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsymbol: 'WAL',\n\t\t\t\t\tfullCoinType: resolved.walCoinType as `${string}::wal::WAL`,\n\t\t\t\t\tdecimals: 9,\n\t\t\t\t\tsource: 'walrus',\n\t\t\t\t} satisfies WalCoinValue;\n\t\t\t}),\n\t});\n};\n\n// ---------------------------------------------------------------------------\n// User-facing factories\n// ---------------------------------------------------------------------------\n\n/** Local-cluster shorthand. Known deployments are selected through\n * `walrusFor(network).known(...)` so network choice stays explicit. */\nexport const walrus = (opts?: { readonly local?: WalrusLocalClusterOptions }) => {\n\treturn buildLocalPlugin(opts?.local ?? {});\n};\n\n/** Mode-narrowed factory namespace.\n *\n * Usage:\n * const network = { mode: 'local', network: 'localnet' } as const;\n * walrusFor(network).local({...}) // OK\n * walrusFor(network).known({...}) // type error: 'known' not in 'local' branch\n *\n * Critically, the fork branch exposes ONLY `.known` — calling\n * `.local` on a fork-mode network is a **compile error** at the\n * call site (distilled-doc invariant 12 — type-level refusal). */\nexport const walrusFor = defineModeNamespace({\n\tlocal: {\n\t\tlocal: (opts: WalrusLocalClusterOptions = {}) => buildLocalPlugin(opts),\n\t\tknown: (opts: WalrusKnownDeploymentOptions) => buildKnownPlugin(opts),\n\t},\n\tlive: {\n\t\tknown: (opts: WalrusKnownDeploymentOptions) => buildKnownPlugin(opts),\n\t},\n\tfork: {\n\t\t// `.local` is intentionally absent — calling\n\t\t// `walrusFor(forkNetwork).local(...)` is a compile error.\n\t\tknown: (opts: WalrusKnownDeploymentOptions) => buildKnownPlugin(opts),\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// Re-exports for advanced callers\n// ---------------------------------------------------------------------------\n\nexport type { WalrusLocalClusterOptions } from './mode/local-cluster.ts';\nexport type { WalrusKnownDeploymentOptions, WalrusKnownNetwork } from './mode/known-deploy.ts';\nexport type { WalrusStorageNode } from './storage-nodes.ts';\nexport type { WalrusBindings, WalrusNodeBinding } from './codegen.ts';\nexport type { WalrusError, WalrusPluginError, WalrusConfigError, WalrusPhase } from './errors.ts';\nexport { walCoinType, walFaucetStrategyKey, type WalFaucetStrategy } from './faucet-strategy.ts';\nexport {\n\tWALRUS_STATE_REGISTRY_KEY,\n\ttype WalrusStateEntry,\n\ttype WalrusLocalStateEntry,\n\ttype WalrusKnownStateEntry,\n} from './registry-publish.ts';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/walrus/index.ts"],"sourcesContent":["// Walrus plugin — barrel + factories.\n//\n// Architecture: Walrus is a service plugin that owns a local cluster\n// or describes a known deployment. The factory at this file folds the\n// four modes behind:\n//\n// - `walrus(opts?)` — local-cluster shorthand. No env\n// defaulting; use `walrusFor(...)`\n// for known deployments.\n// - `walrusFor(network)` — mode-narrowed factory namespace\n// (architecture Tension 11). Returns\n// `{ local: …, known: … }` narrowed\n// to the network's mode. Crucially,\n// the fork branch exposes ONLY\n// `.known` — `.local` is a compile\n// error on a fork-mode network.\n//\n// During `start`, the plugin emits (via the typed `ctx.*` verbs, per mode):\n//\n// Local mode (full local cluster):\n// 1. `ctx.snapshotExtra` — runtime/walrus/<name>/deploy/ subtree\n// + storage-node managed containers.\n// 2. `ctx.codegen` — `walrus-network` bindings.\n// 3. `ctx.endpoint` × (N+2) — per-node + aggregator + publisher.\n// 4. `ctx.provides` walrus-state-registry — local entry.\n// 5. `ctx.provides` endpoint-registry — N+2 entries.\n// 6. `ctx.provides` package-registry — `walrus.<name>`.\n// 7. `ctx.provides` coinType:<WAL fullCoinType> — WAL faucet\n// strategy\n// (when exchange exists).\n//\n// Known mode (read-only deployment):\n// 1. `ctx.snapshotExtra` — identity-guard only; no subtrees.\n// 2. `ctx.codegen` — `walrus-network` bindings (mode='known').\n// 3. `ctx.provides` walrus-state-registry — known entry.\n//\n// Resource id: `'walrus'` (singular). The plugin's substrate-level\n// plugin key is the same string.\n\nimport { Effect, Path } from 'effect';\n\nimport { defineModeNamespace } from '../../api/mode-narrowed-factory.ts';\nimport { definePlugin, resource, type ResourceRef } from '../../api/define-plugin.ts';\nimport type { ContainerRuntime } from '../../contracts/container-runtime.ts';\nimport type { RoutableDecl } from '../../contracts/routable.ts';\nimport type { StrategyContributorDecl } from '../../contracts/strategy-contributor.ts';\nimport { emitContributions, PluginContext } from '../../substrate/plugin-ctx.ts';\nimport { ContainerRuntimeService } from '../../runtime/docker/service.ts';\nimport { IdentityContext, StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { CacheService } from '../../substrate/runtime/cache/index.ts';\nimport { deriveSubnetPrefix, withSubnetAddressing } from '../../substrate/runtime/subnet-broker.ts';\nimport { renderUrl, routedHostname } from '../../substrate/runtime/routed-url.ts';\nimport type { AccountFundingCoinValue } from '../account/index.ts';\nimport { coinResourceId, type CoinResourceId } from '../coin/index.ts';\nimport { suiResource, type SuiProbeKey } from '../sui/index.ts';\n\nimport { chainProbeFor } from '../../substrate/runtime/strategy-registry/index.ts';\n\nimport { makeCodegenable, makeWalrusStaticCodegen } from './codegen.ts';\nimport { LOCAL_NETWORK_NAME } from '../../api/inference-network.ts';\nimport { walrusPluginKey } from './plugin-key.ts';\nimport { walrusPluginError, type WalrusPluginError } from './errors.ts';\nimport { makeWalFaucetContribution, type WalFaucetStrategy } from './faucet-strategy.ts';\nimport { bootWalrusService, type WalrusMode } from './service.ts';\nimport {\n\tresolveLocalClusterOptions,\n\ttype WalrusLocalClusterOptions,\n} from './mode/local-cluster.ts';\nimport {\n\tresolveKnownDeploymentOptions,\n\ttype WalrusKnownDeploymentOptions,\n} from './mode/known-deploy.ts';\nimport { makeSnapshotable, type WalrusSnapshotMode } from './snapshot.ts';\nimport {\n\tWALRUS_AGGREGATOR_ENDPOINT_NAME,\n\tWALRUS_PUBLISHER_ENDPOINT_NAME,\n\tmakeLocalRoutables,\n} from './routable.ts';\nimport { WALRUS_STATE_REGISTRY_KEY, type WalrusStateEntry } from './registry-publish.ts';\nimport {\n\tWALRUS_ROUTER_PORT,\n\tbuildWalrusNetworkName,\n\ttype WalrusStorageNode,\n} from './storage-nodes.ts';\n\n// ---------------------------------------------------------------------------\n// Resource — the resolved value all consumers read\n// ---------------------------------------------------------------------------\n\n/** The Walrus resolved value carried by the resource. */\nexport interface WalrusResolved {\n\treadonly mode: 'local' | 'known';\n\t/** Network name the walrus deployment targets (`localnet`/`testnet`/…). */\n\treadonly network: string;\n\treadonly walrusPackageId: string | null;\n\treadonly walPackageId: string | null;\n\t/** SDK-ready `packageConfig` — structurally compatible with\n\t * `@mysten/walrus`'s `WalrusPackageConfig`. */\n\treadonly packageConfig: {\n\t\treadonly systemObjectId: string;\n\t\treadonly stakingPoolId: string;\n\t\treadonly exchangeIds?: ReadonlyArray<string>;\n\t};\n\treadonly nodes: ReadonlyArray<WalrusStorageNode>;\n\treadonly proxyUrl: string | null;\n\treadonly aggregatorUrl: string | null;\n\treadonly publisherUrl: string | null;\n\treadonly walFaucetStrategy: WalFaucetStrategy | null;\n\treadonly walCoinType: string | null;\n}\n\n/** Walrus plugin resource. */\nexport const walrusResource = resource<'walrus', WalrusResolved>('walrus');\n\nexport interface WalrusNetworkIdentity {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly walrusName: string;\n}\n\n/** Walrus deploy records storage-node listening IPs under this /24.\n * Docker network create requests the matching subnet explicitly, with\n * the prefix derived from the Walrus network identity so parallel\n * stacks don't all claim the same Docker IPAM range. Walrus claims\n * the `10.64.*` – `10.127.*` band; see substrate/runtime/subnet-broker.ts\n * for the algorithm and band coordination with seal. */\nexport const deriveWalrusSubnetPrefix = (identity: WalrusNetworkIdentity): string =>\n\tderiveSubnetPrefix(`${identity.app}\\0${identity.stack}\\0${identity.walrusName}`, 64);\n\nconst withWalrusNetworkAddressing = (\n\truntime: ContainerRuntime,\n\twalrusNetworkName: string,\n\tsubnetPrefix: string,\n): ContainerRuntime => ({\n\t...runtime,\n\tensureNetwork: (spec) =>\n\t\truntime.ensureNetwork(\n\t\t\tspec.name === walrusNetworkName ? withSubnetAddressing(spec, subnetPrefix) : spec,\n\t\t),\n});\n\n// ---------------------------------------------------------------------------\n// Plugin construction (internal — used by walrus() + walrusFor())\n// ---------------------------------------------------------------------------\n\nconst buildLocalPlugin = (opts: WalrusLocalClusterOptions) => {\n\t// Synchronous factory-time validation (distilled-doc invariants\n\t// 11 — `nodeCount >= 1` + `shards >= nodeCount`).\n\tconst resolved = resolveLocalClusterOptions(opts);\n\n\tconst walrusKey = walrusPluginKey(resolved.name);\n\n\treturn definePlugin({\n\t\tid: walrusResource.id,\n\t\tdependsOn: [suiResource] as const,\n\t\trole: 'service',\n\t\tsection: 'service',\n\t\tpluginKey: walrusKey,\n\t\t// Stack-free codegen: a local walrus cluster's deploy ids / endpoint\n\t\t// URLs are LOADED CONFIG DATA -- the committed `walrus.ts` stub emits\n\t\t// `requireValue(dep, 'walrus', '<key>')`, never a baked object id / URL.\n\t\tstaticCodegen: () => [makeWalrusStaticCodegen({ mode: 'local', network: LOCAL_NETWORK_NAME })],\n\t\t// `deps` auto-infers the resolved `[sui]` tuple from the\n\t\t// `[suiResource] as const` dependency. `ctx` arrives via the\n\t\t// `PluginContext` service.\n\t\tstart: (deps) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst ctx = yield* PluginContext;\n\t\t\t\tconst [sui] = deps;\n\n\t\t\t\t// Substrate-context primitives:\n\t\t\t\t// - `ContainerRuntimeService` + `IdentityContext` arrive\n\t\t\t\t// via the supervisor's plugin runtime context.\n\t\t\t\t// - `ArtifactPublisher` is the substrate-level\n\t\t\t\t// publisher (cache → verify → produce → register cycle).\n\t\t\t\t// - `ChainProbe<SuiProbeKey>` is looked up via the\n\t\t\t\t// StrategyRegistry under `chain-probe:<chainId>`;\n\t\t\t\t// Sui registered itself there at its own acquire.\n\t\t\t\t// - `StackPathsService` resolves the per-stack on-disk\n\t\t\t\t// root so the deploy-output bind-mount source is a\n\t\t\t\t// real path (not the `<runtime>/...` template).\n\t\t\t\tconst runtime = yield* ContainerRuntimeService;\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst stackPaths = yield* StackPathsService;\n\t\t\t\tconst path = yield* Path.Path;\n\t\t\t\tconst publisher = yield* CacheService;\n\t\t\t\tconst probe = yield* chainProbeFor<SuiProbeKey>(sui.chainId);\n\n\t\t\t\t// Resolve the deploy-output bind-mount source from the\n\t\t\t\t// per-stack paths bundle. The deploy one-shot owns preparing\n\t\t\t\t// the directory immediately before its Docker bind mount.\n\t\t\t\tconst deployHostMountPath = path.join(\n\t\t\t\t\tstackPaths.stackRoot,\n\t\t\t\t\t'walrus',\n\t\t\t\t\tresolved.name,\n\t\t\t\t\t'deploy',\n\t\t\t\t);\n\n\t\t\t\t// Cross-container DNS: walrus containers (deploy one-shot\n\t\t\t\t// + N storage nodes) dial sui RPC + faucet via\n\t\t\t\t// `host.docker.internal`. The sui plugin binds brokered\n\t\t\t\t// host ports — no shared docker network needed.\n\t\t\t\t//\n\t\t\t\t// Architectural decision (B5): walrus owns its OWN docker\n\t\t\t\t// network for storage-node ↔ deploy connectivity; sui-side\n\t\t\t\t// hops go through the host gateway.\n\t\t\t\t// On Linux this requires Docker Desktop or the\n\t\t\t\t// `host.docker.internal:host-gateway` runtime hint (the\n\t\t\t\t// established devstack convention — see plugins/deepbook\n\t\t\t\t// which uses the same pattern).\n\t\t\t\tconst walrusNetworkName = buildWalrusNetworkName(\n\t\t\t\t\tidentity.app,\n\t\t\t\t\tidentity.stack,\n\t\t\t\t\tresolved.name,\n\t\t\t\t);\n\t\t\t\tconst walrusSubnetPrefix = deriveWalrusSubnetPrefix({\n\t\t\t\t\tapp: identity.app,\n\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\twalrusName: resolved.name,\n\t\t\t\t});\n\t\t\t\tconst walrusRuntime = withWalrusNetworkAddressing(\n\t\t\t\t\truntime,\n\t\t\t\t\twalrusNetworkName,\n\t\t\t\t\twalrusSubnetPrefix,\n\t\t\t\t);\n\t\t\t\tconst suiRpcUrlInNetwork = sui.hostGateway.rpcUrl;\n\t\t\t\t// sui-faucet v2 endpoint — `/v2/gas` is the supported path\n\t\t\t\t// on devnet-v1.71.0+.\n\t\t\t\tconst suiFaucetUrlInNetwork = sui.hostGateway.faucetUrl;\n\t\t\t\tif (suiFaucetUrlInNetwork === null) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t'deploy',\n\t\t\t\t\t\t\t'walrus local-cluster requires a Sui faucet URL for deploy funding.',\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst walrusFaucetUrlInNetwork = `${suiFaucetUrlInNetwork}/v2/gas`;\n\n\t\t\t\tconst mode: WalrusMode = { mode: 'local', opts: resolved };\n\t\t\t\tconst boot = yield* bootWalrusService(\n\t\t\t\t\t{\n\t\t\t\t\t\truntime: walrusRuntime,\n\t\t\t\t\t\tpublisher,\n\t\t\t\t\t\tprobe,\n\t\t\t\t\t\tsuiSdk: sui.sdk,\n\t\t\t\t\t\tsuiChainId: sui.chainId,\n\t\t\t\t\t\tsuiRpcUrlInNetwork,\n\t\t\t\t\t\twalrusFaucetUrlInNetwork,\n\t\t\t\t\t\twaitForFundsReady: sui.waitForTransactionsReady.wait,\n\t\t\t\t\t\tapp: identity.app,\n\t\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\t\tsubnetPrefix: walrusSubnetPrefix,\n\t\t\t\t\t\twalrusNetworkName,\n\t\t\t\t\t\t// Walrus has no `sui-net` to attach to (sui binds\n\t\t\t\t\t\t// host ports). Reuse the walrus network so the\n\t\t\t\t\t\t// deploy one-shot + storage nodes land on a single\n\t\t\t\t\t\t// network and reach sui via `host.docker.internal`.\n\t\t\t\t\t\tsuiNetworkName: walrusNetworkName,\n\t\t\t\t\t\tdeployHostMountPath,\n\t\t\t\t\t\tstackRoot: stackPaths.stackRoot,\n\t\t\t\t\t},\n\t\t\t\t\tmode,\n\t\t\t\t);\n\n\t\t\t\tif (boot.mode !== 'local') {\n\t\t\t\t\t// Should be unreachable — dispatch is by mode. Defense.\n\t\t\t\t\treturn yield* Effect.die('walrus: mode mismatch in local plugin');\n\t\t\t\t}\n\n\t\t\t\tconst packageConfig: WalrusResolved['packageConfig'] =\n\t\t\t\t\tboot.exchangeObjectId === undefined\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tsystemObjectId: boot.deploy.systemObject,\n\t\t\t\t\t\t\t\tstakingPoolId: boot.deploy.stakingObject,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tsystemObjectId: boot.deploy.systemObject,\n\t\t\t\t\t\t\t\tstakingPoolId: boot.deploy.stakingObject,\n\t\t\t\t\t\t\t\texchangeIds: [boot.exchangeObjectId],\n\t\t\t\t\t\t\t};\n\t\t\t\tconst serviceUrl = (role: string) =>\n\t\t\t\t\troutedHostname(identity, role).pipe(\n\t\t\t\t\t\tEffect.map((hostname) =>\n\t\t\t\t\t\t\trenderUrl({\n\t\t\t\t\t\t\t\tprotocol: 'http',\n\t\t\t\t\t\t\t\thostname,\n\t\t\t\t\t\t\t\tport: WALRUS_ROUTER_PORT,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t\t'proxy',\n\t\t\t\t\t\t\t\t`walrus route URL assembly failed for ${role}: ${cause.detail}`,\n\t\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\tconst aggregatorUrl =\n\t\t\t\t\tboot.clientServices.aggregator === null\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: yield* serviceUrl(WALRUS_AGGREGATOR_ENDPOINT_NAME);\n\t\t\t\tconst publisherUrl =\n\t\t\t\t\tboot.clientServices.publisher === null\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: yield* serviceUrl(WALRUS_PUBLISHER_ENDPOINT_NAME);\n\n\t\t\t\tconst resolvedValue: WalrusResolved = {\n\t\t\t\t\tmode: 'local',\n\t\t\t\t\tnetwork: identity.network,\n\t\t\t\t\twalrusPackageId: boot.walrusPackageId,\n\t\t\t\t\twalPackageId: boot.walPackageId,\n\t\t\t\t\tpackageConfig,\n\t\t\t\t\tnodes: boot.nodes,\n\t\t\t\t\tproxyUrl: aggregatorUrl,\n\t\t\t\t\taggregatorUrl,\n\t\t\t\t\tpublisherUrl,\n\t\t\t\t\twalFaucetStrategy: boot.walFaucetStrategy,\n\t\t\t\t\twalCoinType: boot.walCoinType,\n\t\t\t\t};\n\t\t\t\t// Emit the resolved contributions inline: snapshot → codegen →\n\t\t\t\t// state-registry → (optional WAL faucet) → routables. `identity`\n\t\t\t\t// (from `IdentityContext`) stamps the snapshot + routable\n\t\t\t\t// container names. ID-stability surfaces (deploy/blob ids via\n\t\t\t\t// ArtifactPublisher) live OUTSIDE this emission and are untouched.\n\t\t\t\tconst walFaucetContribution: ReadonlyArray<StrategyContributorDecl> =\n\t\t\t\t\tresolvedValue.walFaucetStrategy === null || resolvedValue.walCoinType === null\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tmakeWalFaucetContribution(\n\t\t\t\t\t\t\t\t\tresolvedValue.walFaucetStrategy,\n\t\t\t\t\t\t\t\t\tresolvedValue.walCoinType,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t];\n\t\t\t\tconst clientServiceRoles = [\n\t\t\t\t\t...(boot.clientServices.aggregator === null ? [] : ['aggregator' as const]),\n\t\t\t\t\t...(boot.clientServices.publisher === null ? [] : ['publisher' as const]),\n\t\t\t\t];\n\t\t\t\temitContributions(ctx, [\n\t\t\t\t\tmakeSnapshotable(\n\t\t\t\t\t\t'local' satisfies WalrusSnapshotMode,\n\t\t\t\t\t\tidentity.app,\n\t\t\t\t\t\tidentity.stack,\n\t\t\t\t\t\tresolved.name,\n\t\t\t\t\t\tresolvedValue.network,\n\t\t\t\t\t\tresolved.nodeCount,\n\t\t\t\t\t\tclientServiceRoles,\n\t\t\t\t\t),\n\t\t\t\t\tmakeCodegenable({\n\t\t\t\t\t\tmode: 'local',\n\t\t\t\t\t\tnetwork: resolvedValue.network,\n\t\t\t\t\t\twalrusPackageId: resolvedValue.walrusPackageId,\n\t\t\t\t\t\twalPackageId: resolvedValue.walPackageId,\n\t\t\t\t\t\twalCoinType: resolvedValue.walCoinType,\n\t\t\t\t\t\tsystemObjectId: resolvedValue.packageConfig.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolvedValue.packageConfig.stakingPoolId,\n\t\t\t\t\t\texchangeIds: resolvedValue.packageConfig.exchangeIds\n\t\t\t\t\t\t\t? [...resolvedValue.packageConfig.exchangeIds]\n\t\t\t\t\t\t\t: [],\n\t\t\t\t\t\tproxyUrl: resolvedValue.proxyUrl,\n\t\t\t\t\t\taggregatorUrl: resolvedValue.aggregatorUrl,\n\t\t\t\t\t\tpublisherUrl: resolvedValue.publisherUrl,\n\t\t\t\t\t\tnodes: resolvedValue.nodes,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: 'strategy-contributor',\n\t\t\t\t\t\tcapabilityKey: WALRUS_STATE_REGISTRY_KEY,\n\t\t\t\t\t\tstrategy: { noteName: resolved.name },\n\t\t\t\t\t\tautoMounted: true,\n\t\t\t\t\t} satisfies StrategyContributorDecl<\n\t\t\t\t\t\ttypeof WALRUS_STATE_REGISTRY_KEY,\n\t\t\t\t\t\t{ readonly noteName: string }\n\t\t\t\t\t>,\n\t\t\t\t\t...walFaucetContribution,\n\t\t\t\t\t...(makeLocalRoutables({\n\t\t\t\t\t\tapp: identity.app,\n\t\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\t\twalrusName: resolved.name,\n\t\t\t\t\t\tserviceKey: String(walrusKey),\n\t\t\t\t\t\tnodeCount: resolved.nodeCount,\n\t\t\t\t\t\tcontainerApiPort: resolved.containerApiPort,\n\t\t\t\t\t\taggregator: boot.clientServices.aggregator,\n\t\t\t\t\t\tpublisher: boot.clientServices.publisher,\n\t\t\t\t\t}) as readonly RoutableDecl[]),\n\t\t\t\t]);\n\t\t\t\treturn resolvedValue;\n\t\t\t}),\n\t});\n};\n\nconst buildKnownPlugin = (opts: WalrusKnownDeploymentOptions) => {\n\t// Synchronous factory-time validation for required deployment ids.\n\tconst resolved = resolveKnownDeploymentOptions(opts);\n\n\treturn definePlugin({\n\t\tid: walrusResource.id,\n\t\tdependsOn: [suiResource] as const,\n\t\t// Known deployment is a pure value-producer — no containers,\n\t\t// no long-running children.\n\t\trole: 'task',\n\t\tsection: 'service',\n\t\t// Stack-free codegen: a known deployment's ids / URLs are DECLARED\n\t\t// config (not loaded-at-runtime data) — bake them as literals in the\n\t\t// committed `walrus.ts` (mirrors `knownPackage`). `walrusPackageId` /\n\t\t// `walPackageId` / `walCoinType` are null for a known deployment.\n\t\tstaticCodegen: () => [\n\t\t\tmakeWalrusStaticCodegen({\n\t\t\t\tmode: 'known',\n\t\t\t\tnetwork: resolved.network,\n\t\t\t\tknown: {\n\t\t\t\t\twalrusPackageId: null,\n\t\t\t\t\twalPackageId: null,\n\t\t\t\t\twalCoinType: null,\n\t\t\t\t\tpackageConfig: {\n\t\t\t\t\t\tsystemObjectId: resolved.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolved.stakingPoolId,\n\t\t\t\t\t\t...(resolved.exchangeIds.length > 0 ? { exchangeIds: [...resolved.exchangeIds] } : {}),\n\t\t\t\t\t},\n\t\t\t\t\tproxyUrl: resolved.proxyUrl,\n\t\t\t\t\taggregatorUrl: resolved.aggregatorUrl,\n\t\t\t\t\tpublisherUrl: resolved.publisherUrl,\n\t\t\t\t\tnodes: resolved.nodes,\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t\t// Known mode is a pure value-producer — `sui` is unused (the value\n\t\t// reads `resolved.network` from the deployment options) but the\n\t\t// `dependsOn` edge still orders boot, so `start` is zero-arg.\n\t\t// `ctx` arrives via the `PluginContext` service.\n\t\tstart: () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst ctx = yield* PluginContext;\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst resolvedValue = {\n\t\t\t\t\tmode: 'known',\n\t\t\t\t\tnetwork: resolved.network,\n\t\t\t\t\twalrusPackageId: null,\n\t\t\t\t\twalPackageId: null,\n\t\t\t\t\tpackageConfig: {\n\t\t\t\t\t\tsystemObjectId: resolved.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolved.stakingPoolId,\n\t\t\t\t\t\texchangeIds: resolved.exchangeIds.length > 0 ? resolved.exchangeIds : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tnodes: resolved.nodes,\n\t\t\t\t\tproxyUrl: resolved.proxyUrl,\n\t\t\t\t\taggregatorUrl: resolved.aggregatorUrl,\n\t\t\t\t\tpublisherUrl: resolved.publisherUrl,\n\t\t\t\t\twalFaucetStrategy: null,\n\t\t\t\t\twalCoinType: null,\n\t\t\t\t} satisfies WalrusResolved;\n\t\t\t\t// Emit inline: snapshot → codegen → state-registry. Known mode\n\t\t\t\t// emits no routable. `identity` (from `IdentityContext`) stamps\n\t\t\t\t// the snapshot scoping.\n\t\t\t\tctx.snapshotExtra(\n\t\t\t\t\tmakeSnapshotable(\n\t\t\t\t\t\t'known' satisfies WalrusSnapshotMode,\n\t\t\t\t\t\tidentity.app,\n\t\t\t\t\t\tidentity.stack,\n\t\t\t\t\t\t'walrusKnownDeployment',\n\t\t\t\t\t\tresolvedValue.network,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tctx.codegen(\n\t\t\t\t\tmakeCodegenable({\n\t\t\t\t\t\tmode: 'known',\n\t\t\t\t\t\tnetwork: resolvedValue.network,\n\t\t\t\t\t\twalrusPackageId: resolvedValue.walrusPackageId,\n\t\t\t\t\t\twalPackageId: resolvedValue.walPackageId,\n\t\t\t\t\t\twalCoinType: resolvedValue.walCoinType,\n\t\t\t\t\t\tsystemObjectId: resolvedValue.packageConfig.systemObjectId,\n\t\t\t\t\t\tstakingPoolId: resolvedValue.packageConfig.stakingPoolId,\n\t\t\t\t\t\texchangeIds: resolvedValue.packageConfig.exchangeIds\n\t\t\t\t\t\t\t? [...resolvedValue.packageConfig.exchangeIds]\n\t\t\t\t\t\t\t: [],\n\t\t\t\t\t\tproxyUrl: resolvedValue.proxyUrl,\n\t\t\t\t\t\taggregatorUrl: resolvedValue.aggregatorUrl,\n\t\t\t\t\t\tpublisherUrl: resolvedValue.publisherUrl,\n\t\t\t\t\t\tnodes: resolvedValue.nodes,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tctx.provides({\n\t\t\t\t\tkind: 'strategy-contributor',\n\t\t\t\t\tcapabilityKey: WALRUS_STATE_REGISTRY_KEY,\n\t\t\t\t\tstrategy: {\n\t\t\t\t\t\tname: 'walrusKnownDeployment',\n\t\t\t\t\t\tsystemObjectId: resolvedValue.packageConfig.systemObjectId,\n\t\t\t\t\t\tstakingObjectId: resolvedValue.packageConfig.stakingPoolId,\n\t\t\t\t\t\tnetwork: resolvedValue.network,\n\t\t\t\t\t},\n\t\t\t\t\tautoMounted: true,\n\t\t\t\t} satisfies StrategyContributorDecl<typeof WALRUS_STATE_REGISTRY_KEY, WalrusStateEntry>);\n\t\t\t\treturn resolvedValue;\n\t\t\t}),\n\t});\n};\n\nexport interface WalCoinValue extends AccountFundingCoinValue {\n\treadonly symbol: 'WAL';\n\treadonly fullCoinType: `${string}::wal::WAL`;\n\treadonly decimals: 9;\n\treadonly source: 'walrus';\n}\n\n/** Resolve the local Walrus deployment's WAL coin as an account-funding\n * coin ref. Accounts that need WAL should use:\n *\n * funding: [{ coin: walCoin(localWalrus), amount }]\n *\n * The funding strategy itself is contributed by the Walrus service\n * once its local exchange exists. */\nexport const walCoin = (walrusMember: ResourceRef<'walrus', WalrusResolved>) => {\n\tconst coinRef = resource<CoinResourceId<'wal'>, WalCoinValue>(coinResourceId('wal'));\n\n\treturn definePlugin({\n\t\tid: coinRef.id,\n\t\tdependsOn: walrusMember,\n\t\trole: 'task',\n\t\tsection: 'action',\n\t\tstart: (resolved): Effect.Effect<WalCoinValue, WalrusPluginError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tif (resolved.walCoinType === null) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t'exchange',\n\t\t\t\t\t\t\t'walCoin(...) requires a local Walrus deployment with a WAL package.',\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tsymbol: 'WAL',\n\t\t\t\t\tfullCoinType: resolved.walCoinType as `${string}::wal::WAL`,\n\t\t\t\t\tdecimals: 9,\n\t\t\t\t\tsource: 'walrus',\n\t\t\t\t} satisfies WalCoinValue;\n\t\t\t}),\n\t});\n};\n\n// ---------------------------------------------------------------------------\n// User-facing factories\n// ---------------------------------------------------------------------------\n\n/** Local-cluster shorthand. Known deployments are selected through the\n * per-network methods `walrusFor(network).testnet(...)` /\n * `.mainnet(...)` so network choice stays explicit; `.known(...)` is the\n * raw-id override form. */\nexport const walrus = (opts?: { readonly local?: WalrusLocalClusterOptions }) => {\n\treturn buildLocalPlugin(opts?.local ?? {});\n};\n\n/** Per-network factory options for `walrusFor(net).testnet()`/`.mainnet()`.\n * The `network` is injected by the namespace method, so the caller only\n * supplies the (still-required) `nodes` committee plus optional per-field\n * overrides — the on-chain ids default from the `@mysten/walrus` SDK package\n * config. Plugin-INTERNAL — deliberately NOT re-exported from `src/index.ts`. */\ntype WalrusKnownByNetworkOptions = Omit<WalrusKnownDeploymentOptions, 'network'>;\n\n/** Mode-narrowed factory namespace.\n *\n * Usage:\n * const network = { mode: 'local', network: 'localnet' } as const;\n * walrusFor(network).local({...}) // OK\n * walrusFor(liveNet).testnet({ nodes }) // OK — network injected\n * walrusFor(forkNet).local({...}) // compile error: no `.local` on fork\n *\n * Per-network methods (`.testnet`/`.mainnet`) inject the network into\n * `buildKnownPlugin`; `nodes` is still REQUIRED, so `.testnet({ nodes })` is\n * the minimal call. `.known(...)` is now the raw-id explicit-override form only\n * (`systemObjectId`/`stakingPoolId`/`nodes`) — the `network`-in-`.known()` path\n * was HARD CUT.\n *\n * Critically, the fork branch exposes NO `.local` — calling\n * `.local` on a fork-mode network is a **compile error** at the\n * call site (distilled-doc invariant 12 — type-level refusal). */\nexport const walrusFor = defineModeNamespace({\n\tlocal: {\n\t\tlocal: (opts: WalrusLocalClusterOptions = {}) => buildLocalPlugin(opts),\n\t\tknown: (opts: WalrusKnownByNetworkOptions) => buildKnownPlugin(opts),\n\t\ttestnet: (opts: WalrusKnownByNetworkOptions = {}) =>\n\t\t\tbuildKnownPlugin({ network: 'testnet', ...opts }),\n\t\tmainnet: (opts: WalrusKnownByNetworkOptions = {}) =>\n\t\t\tbuildKnownPlugin({ network: 'mainnet', ...opts }),\n\t},\n\tlive: {\n\t\tknown: (opts: WalrusKnownByNetworkOptions) => buildKnownPlugin(opts),\n\t\ttestnet: (opts: WalrusKnownByNetworkOptions = {}) =>\n\t\t\tbuildKnownPlugin({ network: 'testnet', ...opts }),\n\t\tmainnet: (opts: WalrusKnownByNetworkOptions = {}) =>\n\t\t\tbuildKnownPlugin({ network: 'mainnet', ...opts }),\n\t},\n\tfork: {\n\t\t// `.local` is intentionally absent — calling\n\t\t// `walrusFor(forkNetwork).local(...)` is a compile error.\n\t\tknown: (opts: WalrusKnownByNetworkOptions) => buildKnownPlugin(opts),\n\t\ttestnet: (opts: WalrusKnownByNetworkOptions = {}) =>\n\t\t\tbuildKnownPlugin({ network: 'testnet', ...opts }),\n\t\tmainnet: (opts: WalrusKnownByNetworkOptions = {}) =>\n\t\t\tbuildKnownPlugin({ network: 'mainnet', ...opts }),\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// Re-exports for advanced callers\n// ---------------------------------------------------------------------------\n\nexport type {\n\tWalrusLocalClusterOptions,\n\tWalrusLocalPublisherOptions,\n\tWalrusLocalServiceOptions,\n} from './mode/local-cluster.ts';\nexport type { WalrusKnownDeploymentOptions, WalrusKnownNetwork } from './mode/known-deploy.ts';\nexport type { WalrusStorageNode } from './storage-nodes.ts';\nexport type { WalrusBindings, WalrusNodeBinding } from './codegen.ts';\nexport type { WalrusError, WalrusPluginError, WalrusConfigError, WalrusPhase } from './errors.ts';\nexport { walCoinType, walFaucetStrategyKey, type WalFaucetStrategy } from './faucet-strategy.ts';\nexport {\n\tWALRUS_STATE_REGISTRY_KEY,\n\ttype WalrusStateEntry,\n\ttype WalrusLocalStateEntry,\n\ttype WalrusKnownStateEntry,\n} from './registry-publish.ts';\n"],"mappings":"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"}
@@ -9,7 +9,11 @@ interface WalrusKnownDeploymentOptions {
9
9
  /** Network shortcut — looks up per-field defaults from a registry
10
10
  * baked into this package. */
11
11
  readonly network?: WalrusKnownNetwork;
12
- /** Per-field overrides. Required when `network` is omitted. */
12
+ /** Per-field overrides for the on-chain ids. For `testnet`/`mainnet`
13
+ * these default from the `@mysten/walrus` SDK package config, so
14
+ * they're optional; for `devnet` (or when `network` is omitted)
15
+ * `systemObjectId`/`stakingPoolId` are required. An explicit value
16
+ * here always wins over the registry default. */
13
17
  readonly systemObjectId?: string;
14
18
  readonly stakingPoolId?: string;
15
19
  readonly exchangeIds?: ReadonlyArray<string>;
@@ -1,25 +1,28 @@
1
1
  import { expectNonEmptyString } from "../../../substrate/runtime/config-validation.mjs";
2
2
  import { walrusConfigError } from "../errors.mjs";
3
3
  import { Effect } from "effect";
4
+ import { MAINNET_WALRUS_PACKAGE_CONFIG, TESTNET_WALRUS_PACKAGE_CONFIG } from "@mysten/walrus";
4
5
  //#region src/plugins/walrus/mode/known-deploy.ts
5
6
  /** Known-deployment registry — baked-in record per network. The
6
- * values here are the `knownDeployments.walrus.{testnet, mainnet}`
7
- * entries. Devnet has no canonical record today. */
7
+ * on-chain ids default from the `@mysten/walrus` SDK package config
8
+ * (`{TESTNET,MAINNET}_WALRUS_PACKAGE_CONFIG`) so a caller only needs
9
+ * to supply `nodes`; the aggregator/publisher/proxy URLs are
10
+ * devstack-owned (the SDK ships none). Devnet has no canonical SDK
11
+ * record today, so it keeps no id defaults. */
8
12
  const KNOWN_DEPLOYMENT_REGISTRY = {
9
13
  testnet: {
10
14
  network: "testnet",
11
- systemObjectId: void 0,
12
- stakingPoolId: void 0,
13
- exchangeIds: [],
15
+ systemObjectId: TESTNET_WALRUS_PACKAGE_CONFIG.systemObjectId,
16
+ stakingPoolId: TESTNET_WALRUS_PACKAGE_CONFIG.stakingPoolId,
17
+ exchangeIds: TESTNET_WALRUS_PACKAGE_CONFIG.exchangeIds,
14
18
  aggregatorUrl: "https://aggregator.walrus-testnet.walrus.space",
15
19
  publisherUrl: "https://publisher.walrus-testnet.walrus.space",
16
20
  proxyUrl: "https://aggregator.walrus-testnet.walrus.space"
17
21
  },
18
22
  mainnet: {
19
23
  network: "mainnet",
20
- systemObjectId: void 0,
21
- stakingPoolId: void 0,
22
- exchangeIds: [],
24
+ systemObjectId: MAINNET_WALRUS_PACKAGE_CONFIG.systemObjectId,
25
+ stakingPoolId: MAINNET_WALRUS_PACKAGE_CONFIG.stakingPoolId,
23
26
  aggregatorUrl: "https://aggregator.walrus.space",
24
27
  publisherUrl: "https://publisher.walrus.space",
25
28
  proxyUrl: "https://aggregator.walrus.space"
@@ -34,17 +37,17 @@ const resolveKnownDeploymentOptions = (opts) => {
34
37
  const reg = opts.network ? KNOWN_DEPLOYMENT_REGISTRY[opts.network] : void 0;
35
38
  const systemObjectId = expectNonEmptyString(opts.systemObjectId ?? reg?.systemObjectId, {
36
39
  field: "systemObjectId",
37
- mkError: ({ field }) => walrusConfigError(field, `walrusKnownDeployment: 'systemObjectId' is required (pass it explicitly, or pass network with a registered entry)`)
40
+ mkError: ({ field }) => walrusConfigError(field, `walrusKnownDeployment: 'systemObjectId' is required (testnet/mainnet default from the @mysten/walrus SDK; pass it explicitly for devnet or networks without an SDK record)`)
38
41
  });
39
42
  const stakingPoolId = expectNonEmptyString(opts.stakingPoolId ?? reg?.stakingPoolId, {
40
43
  field: "stakingPoolId",
41
- mkError: ({ field }) => walrusConfigError(field, `walrusKnownDeployment: 'stakingPoolId' is required (pass it explicitly, or pass network with a registered entry)`)
44
+ mkError: ({ field }) => walrusConfigError(field, `walrusKnownDeployment: 'stakingPoolId' is required (testnet/mainnet default from the @mysten/walrus SDK; pass it explicitly for devnet or networks without an SDK record)`)
42
45
  });
43
46
  const nodes = opts.nodes;
44
47
  if (!nodes) throw walrusConfigError("nodes", `walrusKnownDeployment: explicit 'nodes' committee is required — Walrus ${opts.network ?? "custom"} has nodes fetched dynamically by the SDK`, "pass an empty array if you accept the SDK-driven committee lookup, or use walrus()/walrusFor(network).local({...}) for a local self-hosted cluster");
45
48
  const aggregatorUrl = opts.aggregatorUrl ?? reg?.aggregatorUrl ?? null;
46
49
  const publisherUrl = opts.publisherUrl ?? reg?.publisherUrl ?? null;
47
- const proxyUrl = opts.proxyUrl ?? reg?.proxyUrl ?? aggregatorUrl ?? publisherUrl ?? null;
50
+ const proxyUrl = opts.proxyUrl ?? reg?.proxyUrl ?? aggregatorUrl ?? null;
48
51
  return {
49
52
  mode: "known",
50
53
  network: reg?.network ?? "custom",