@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.
Files changed (838) hide show
  1. package/README.md +7 -3
  2. package/dashboard-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  3. package/dashboard-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  4. package/dashboard-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  5. package/dashboard-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  6. package/dashboard-ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
  7. package/dashboard-ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
  8. package/dashboard-ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
  9. package/dashboard-ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
  10. package/dashboard-ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
  11. package/dashboard-ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
  12. package/dashboard-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  13. package/dashboard-ui/assets/index-Bmi1UtAg.js +1356 -0
  14. package/dashboard-ui/assets/index-D5EShVt4.js +3 -0
  15. package/dashboard-ui/assets/index-Deml9drg.css +1 -0
  16. package/dashboard-ui/index.html +13 -0
  17. package/dist/api/define-capabilities.d.mts +14 -3
  18. package/dist/api/define-capabilities.mjs +18 -1
  19. package/dist/api/define-capabilities.mjs.map +1 -1
  20. package/dist/api/define-devstack.d.mts +1 -1
  21. package/dist/api/define-devstack.mjs +6 -26
  22. package/dist/api/define-devstack.mjs.map +1 -1
  23. package/dist/api/define-plugin.d.mts +1 -0
  24. package/dist/api/define-plugin.mjs +2 -0
  25. package/dist/api/inference-network.d.mts +132 -0
  26. package/dist/api/inference-network.mjs +105 -16
  27. package/dist/api/inference-network.mjs.map +1 -1
  28. package/dist/api/plugin-errors.d.mts +7 -0
  29. package/dist/api/run-stack.d.mts +20 -9
  30. package/dist/api/run-stack.mjs +56 -29
  31. package/dist/api/run-stack.mjs.map +1 -1
  32. package/dist/build-integrations/playwright/config.d.mts +6 -4
  33. package/dist/build-integrations/playwright/config.mjs +5 -3
  34. package/dist/build-integrations/playwright/config.mjs.map +1 -1
  35. package/dist/build-integrations/playwright/errors.d.mts +1 -1
  36. package/dist/build-integrations/playwright/global-setup.d.mts +43 -17
  37. package/dist/build-integrations/playwright/global-setup.mjs +250 -13
  38. package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
  39. package/dist/build-integrations/playwright/index.d.mts +5 -3
  40. package/dist/build-integrations/playwright/index.mjs +4 -2
  41. package/dist/build-integrations/playwright/stack-context.d.mts +0 -1
  42. package/dist/build-integrations/playwright/stack-context.mjs +24 -63
  43. package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
  44. package/dist/build-integrations/playwright/wallet-context.d.mts +7 -10
  45. package/dist/build-integrations/playwright/wallet-context.mjs +8 -13
  46. package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
  47. package/dist/build-integrations/runtime/cold-start-url.d.mts +5 -0
  48. package/dist/build-integrations/runtime/cold-start-url.mjs +4 -3
  49. package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
  50. package/dist/build-integrations/runtime/conventional-routes.d.mts +51 -0
  51. package/dist/build-integrations/runtime/conventional-routes.mjs +92 -0
  52. package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -0
  53. package/dist/build-integrations/runtime/discover.d.mts +38 -30
  54. package/dist/build-integrations/runtime/discover.mjs +73 -70
  55. package/dist/build-integrations/runtime/discover.mjs.map +1 -1
  56. package/dist/build-integrations/runtime/endpoint-registry.d.mts +3 -1
  57. package/dist/build-integrations/runtime/endpoint-registry.mjs +3 -1
  58. package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
  59. package/dist/build-integrations/runtime/index.d.mts +7 -2
  60. package/dist/build-integrations/runtime/index.mjs +9 -2
  61. package/dist/build-integrations/runtime/manifest-types.d.mts +2 -0
  62. package/dist/build-integrations/runtime/manifest-types.mjs +3 -0
  63. package/dist/build-integrations/runtime/playwright-stack-context-slot.d.mts +29 -0
  64. package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs +10 -0
  65. package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs.map +1 -0
  66. package/dist/build-integrations/runtime/read-stack-context.d.mts +1 -1
  67. package/dist/build-integrations/runtime/read-stack-context.mjs +10 -4
  68. package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
  69. package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +48 -0
  70. package/dist/build-integrations/runtime/resolve-discovery-env.mjs +42 -0
  71. package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -0
  72. package/dist/build-integrations/runtime/stack-context.d.mts +1 -1
  73. package/dist/build-integrations/runtime/wallet-paths.mjs +2 -0
  74. package/dist/build-integrations/vite/index.d.mts +51 -0
  75. package/dist/build-integrations/vite/index.mjs +73 -0
  76. package/dist/build-integrations/vite/index.mjs.map +1 -0
  77. package/dist/build-integrations/vitest/env.d.mts +4 -3
  78. package/dist/build-integrations/vitest/env.mjs +6 -4
  79. package/dist/build-integrations/vitest/env.mjs.map +1 -1
  80. package/dist/build-integrations/vitest/errors.d.mts +25 -4
  81. package/dist/build-integrations/vitest/errors.mjs +15 -2
  82. package/dist/build-integrations/vitest/errors.mjs.map +1 -1
  83. package/dist/build-integrations/vitest/index.d.mts +2 -2
  84. package/dist/build-integrations/vitest/index.mjs +3 -3
  85. package/dist/build-integrations/vitest/setup.d.mts +4 -2
  86. package/dist/build-integrations/vitest/setup.mjs +2 -2
  87. package/dist/build-integrations/vitest/setup.mjs.map +1 -1
  88. package/dist/build-integrations/vitest/stack-context.d.mts +0 -1
  89. package/dist/build-integrations/vitest/stack-context.mjs +33 -13
  90. package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
  91. package/dist/cli/bail.mjs +23 -0
  92. package/dist/cli/bail.mjs.map +1 -0
  93. package/dist/{surfaces/cli/commands → cli}/doctor-probes.mjs +26 -16
  94. package/dist/cli/doctor-probes.mjs.map +1 -0
  95. package/dist/cli/main.d.mts +15 -1
  96. package/dist/cli/main.mjs +166 -482
  97. package/dist/cli/main.mjs.map +1 -1
  98. package/dist/cli/prune-direct.mjs +31 -201
  99. package/dist/cli/prune-direct.mjs.map +1 -1
  100. package/dist/cli/snapshot-reader.mjs +14 -11
  101. package/dist/cli/snapshot-reader.mjs.map +1 -1
  102. package/dist/cli/up-lifecycle.mjs +4 -1
  103. package/dist/cli/up-lifecycle.mjs.map +1 -1
  104. package/dist/cli/wirings/apply.mjs +95 -0
  105. package/dist/cli/wirings/apply.mjs.map +1 -0
  106. package/dist/cli/wirings/build-verb-layers.mjs +42 -0
  107. package/dist/cli/wirings/build-verb-layers.mjs.map +1 -0
  108. package/dist/cli/wirings/config-loader.mjs +69 -0
  109. package/dist/cli/wirings/config-loader.mjs.map +1 -0
  110. package/dist/cli/wirings/engine-command.mjs +30 -0
  111. package/dist/cli/wirings/engine-command.mjs.map +1 -0
  112. package/dist/cli/wirings/identity.mjs +72 -0
  113. package/dist/cli/wirings/identity.mjs.map +1 -0
  114. package/dist/cli/wirings/provide-file-system.mjs +7 -0
  115. package/dist/cli/wirings/provide-file-system.mjs.map +1 -0
  116. package/dist/cli/wirings/snapshot.mjs +177 -0
  117. package/dist/cli/wirings/snapshot.mjs.map +1 -0
  118. package/dist/cli/wirings/up.mjs +287 -0
  119. package/dist/cli/wirings/up.mjs.map +1 -0
  120. package/dist/cli/wirings/wipe.mjs +40 -0
  121. package/dist/cli/wirings/wipe.mjs.map +1 -0
  122. package/dist/contracts/capability-decl.d.mts +0 -2
  123. package/dist/contracts/codegenable.d.mts +43 -0
  124. package/dist/contracts/container-runtime.d.mts +26 -1
  125. package/dist/contracts/faucet-strategy.d.mts +25 -0
  126. package/dist/contracts/funding-strategy.d.mts +42 -0
  127. package/dist/contracts/plugin-expander.mjs +60 -0
  128. package/dist/contracts/plugin-expander.mjs.map +1 -0
  129. package/dist/contracts/projection.d.mts +5 -3
  130. package/dist/contracts/renderer.d.mts +23 -0
  131. package/dist/contracts/routable.d.mts +14 -1
  132. package/dist/contracts/snapshotable.d.mts +25 -3
  133. package/dist/contracts/wallet-protocol.d.mts +52 -0
  134. package/dist/contracts/wallet-protocol.mjs +52 -0
  135. package/dist/contracts/wallet-protocol.mjs.map +1 -0
  136. package/dist/index.d.mts +26 -25
  137. package/dist/index.mjs +20 -13
  138. package/dist/{runtime → orchestrators}/built-in-plugin-layers.mjs +10 -5
  139. package/dist/orchestrators/built-in-plugin-layers.mjs.map +1 -0
  140. package/dist/orchestrators/codegen/bindings.d.mts +1 -2
  141. package/dist/orchestrators/codegen/bindings.mjs +52 -186
  142. package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
  143. package/dist/orchestrators/codegen/emit.mjs +19 -1
  144. package/dist/orchestrators/codegen/emit.mjs.map +1 -1
  145. package/dist/orchestrators/codegen/errors.mjs +8 -3
  146. package/dist/orchestrators/codegen/errors.mjs.map +1 -1
  147. package/dist/orchestrators/codegen/format.mjs +47 -39
  148. package/dist/orchestrators/codegen/format.mjs.map +1 -1
  149. package/dist/orchestrators/codegen/gitignore.mjs +3 -1
  150. package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
  151. package/dist/orchestrators/codegen/output-location.mjs +40 -0
  152. package/dist/orchestrators/codegen/output-location.mjs.map +1 -0
  153. package/dist/orchestrators/codegen/paths.d.mts +1 -1
  154. package/dist/orchestrators/codegen/paths.mjs +40 -14
  155. package/dist/orchestrators/codegen/paths.mjs.map +1 -1
  156. package/dist/orchestrators/codegen/permissions.mjs +3 -1
  157. package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
  158. package/dist/orchestrators/codegen/service.mjs +157 -105
  159. package/dist/orchestrators/codegen/service.mjs.map +1 -1
  160. package/dist/orchestrators/lifecycle-prune/errors.mjs +31 -0
  161. package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -0
  162. package/dist/orchestrators/lifecycle-prune/index.mjs +350 -0
  163. package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -0
  164. package/dist/orchestrators/router/cleanup.mjs +26 -27
  165. package/dist/orchestrators/router/cleanup.mjs.map +1 -1
  166. package/dist/orchestrators/router/entrypoints.mjs +2 -2
  167. package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
  168. package/dist/orchestrators/router/file-provider.mjs +14 -5
  169. package/dist/orchestrators/router/file-provider.mjs.map +1 -1
  170. package/dist/orchestrators/router/hostname.mjs +19 -55
  171. package/dist/orchestrators/router/hostname.mjs.map +1 -1
  172. package/dist/orchestrators/router/index.mjs +11 -0
  173. package/dist/orchestrators/router/profile.mjs +2 -2
  174. package/dist/orchestrators/router/sentinels.mjs +26 -0
  175. package/dist/orchestrators/router/sentinels.mjs.map +1 -0
  176. package/dist/orchestrators/router/service.mjs +40 -37
  177. package/dist/orchestrators/router/service.mjs.map +1 -1
  178. package/dist/orchestrators/router/traefik-container.mjs +27 -16
  179. package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
  180. package/dist/{substrate/runtime → orchestrators}/run.mjs +26 -21
  181. package/dist/orchestrators/run.mjs.map +1 -0
  182. package/dist/orchestrators/runtime-composition.d.mts +1 -1
  183. package/dist/orchestrators/runtime-composition.mjs +123 -39
  184. package/dist/orchestrators/runtime-composition.mjs.map +1 -1
  185. package/dist/orchestrators/snapshot/capture-command.d.mts +1 -0
  186. package/dist/orchestrators/snapshot/capture-command.mjs +25 -0
  187. package/dist/orchestrators/snapshot/capture-command.mjs.map +1 -0
  188. package/dist/orchestrators/snapshot/capture.mjs +42 -28
  189. package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
  190. package/dist/orchestrators/snapshot/descriptor.mjs +35 -10
  191. package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
  192. package/dist/orchestrators/snapshot/identity-guard.mjs +1 -1
  193. package/dist/orchestrators/snapshot/index.mjs +13 -0
  194. package/dist/orchestrators/snapshot/integrity.d.mts +1 -1
  195. package/dist/orchestrators/snapshot/integrity.mjs +73 -17
  196. package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
  197. package/dist/orchestrators/snapshot/pending-marker.d.mts +1 -0
  198. package/dist/orchestrators/snapshot/pending-marker.mjs +99 -0
  199. package/dist/orchestrators/snapshot/pending-marker.mjs.map +1 -0
  200. package/dist/orchestrators/snapshot/phase-error.mjs +23 -0
  201. package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -0
  202. package/dist/orchestrators/snapshot/prune.mjs +20 -55
  203. package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
  204. package/dist/orchestrators/snapshot/recover-pending.d.mts +1 -0
  205. package/dist/orchestrators/snapshot/recover-pending.mjs +223 -0
  206. package/dist/orchestrators/snapshot/recover-pending.mjs.map +1 -0
  207. package/dist/orchestrators/snapshot/restore.mjs +118 -84
  208. package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
  209. package/dist/orchestrators/snapshot/service.mjs +53 -56
  210. package/dist/orchestrators/snapshot/service.mjs.map +1 -1
  211. package/dist/orchestrators/snapshot/state-document.d.mts +1 -0
  212. package/dist/orchestrators/snapshot/state-document.mjs +47 -7
  213. package/dist/orchestrators/snapshot/state-document.mjs.map +1 -1
  214. package/dist/orchestrators/snapshot/wipe.mjs +67 -10
  215. package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
  216. package/dist/plugins/account/codegen.mjs +9 -8
  217. package/dist/plugins/account/codegen.mjs.map +1 -1
  218. package/dist/plugins/account/errors.d.mts +33 -6
  219. package/dist/plugins/account/errors.mjs.map +1 -1
  220. package/dist/plugins/account/funding.d.mts +29 -19
  221. package/dist/plugins/account/funding.mjs +84 -66
  222. package/dist/plugins/account/funding.mjs.map +1 -1
  223. package/dist/plugins/account/index.d.mts +2 -4
  224. package/dist/plugins/account/index.mjs +64 -31
  225. package/dist/plugins/account/index.mjs.map +1 -1
  226. package/dist/plugins/account/keypair.mjs +6 -9
  227. package/dist/plugins/account/keypair.mjs.map +1 -1
  228. package/dist/plugins/account/lease.mjs +1 -0
  229. package/dist/plugins/account/lease.mjs.map +1 -1
  230. package/dist/plugins/account/registry.d.mts +14 -1
  231. package/dist/plugins/account/registry.mjs +18 -18
  232. package/dist/plugins/account/registry.mjs.map +1 -1
  233. package/dist/plugins/account/service.d.mts +23 -4
  234. package/dist/plugins/account/service.mjs +83 -45
  235. package/dist/plugins/account/service.mjs.map +1 -1
  236. package/dist/plugins/account/snapshot.mjs +2 -5
  237. package/dist/plugins/account/snapshot.mjs.map +1 -1
  238. package/dist/plugins/account/spans.mjs +16 -0
  239. package/dist/plugins/account/spans.mjs.map +1 -0
  240. package/dist/plugins/account/variants/keystore.mjs +6 -8
  241. package/dist/plugins/account/variants/keystore.mjs.map +1 -1
  242. package/dist/plugins/action/build-context.d.mts +3 -2
  243. package/dist/plugins/action/errors.d.mts +16 -12
  244. package/dist/plugins/action/errors.mjs.map +1 -1
  245. package/dist/plugins/action/execute.mjs +65 -103
  246. package/dist/plugins/action/execute.mjs.map +1 -1
  247. package/dist/plugins/action/index.d.mts +0 -2
  248. package/dist/plugins/action/index.mjs +17 -13
  249. package/dist/plugins/action/index.mjs.map +1 -1
  250. package/dist/plugins/action/service.mjs +38 -35
  251. package/dist/plugins/action/service.mjs.map +1 -1
  252. package/dist/plugins/action/spans.mjs +11 -0
  253. package/dist/plugins/action/spans.mjs.map +1 -0
  254. package/dist/plugins/coin/codegen.mjs +9 -8
  255. package/dist/plugins/coin/codegen.mjs.map +1 -1
  256. package/dist/plugins/coin/discovery.mjs +8 -4
  257. package/dist/plugins/coin/discovery.mjs.map +1 -1
  258. package/dist/plugins/coin/index.d.mts +11 -29
  259. package/dist/plugins/coin/index.mjs +56 -27
  260. package/dist/plugins/coin/index.mjs.map +1 -1
  261. package/dist/plugins/coin/metadata.mjs +8 -15
  262. package/dist/plugins/coin/metadata.mjs.map +1 -1
  263. package/dist/plugins/coin/mint.d.mts +30 -11
  264. package/dist/plugins/coin/mint.mjs +78 -74
  265. package/dist/plugins/coin/mint.mjs.map +1 -1
  266. package/dist/plugins/coin/registry.mjs +4 -7
  267. package/dist/plugins/coin/registry.mjs.map +1 -1
  268. package/dist/plugins/coin/service.d.mts +39 -1
  269. package/dist/plugins/coin/service.mjs +11 -4
  270. package/dist/plugins/coin/service.mjs.map +1 -1
  271. package/dist/plugins/coin/spans.mjs +20 -0
  272. package/dist/plugins/coin/spans.mjs.map +1 -0
  273. package/dist/plugins/dashboard/domain.mjs +402 -0
  274. package/dist/plugins/dashboard/domain.mjs.map +1 -0
  275. package/dist/plugins/dashboard/index.d.mts +29 -0
  276. package/dist/plugins/dashboard/index.mjs +91 -0
  277. package/dist/plugins/dashboard/index.mjs.map +1 -0
  278. package/dist/plugins/dashboard/origin-policy.mjs +36 -0
  279. package/dist/plugins/dashboard/origin-policy.mjs.map +1 -0
  280. package/dist/plugins/dashboard/routable.mjs +27 -0
  281. package/dist/plugins/dashboard/routable.mjs.map +1 -0
  282. package/dist/plugins/dashboard/schema/builder.mjs +21 -0
  283. package/dist/plugins/dashboard/schema/builder.mjs.map +1 -0
  284. package/dist/plugins/dashboard/schema/enums.mjs +72 -0
  285. package/dist/plugins/dashboard/schema/enums.mjs.map +1 -0
  286. package/dist/plugins/dashboard/schema/root.mjs +351 -0
  287. package/dist/plugins/dashboard/schema/root.mjs.map +1 -0
  288. package/dist/plugins/dashboard/schema/types.mjs +508 -0
  289. package/dist/plugins/dashboard/schema/types.mjs.map +1 -0
  290. package/dist/plugins/dashboard/schema.mjs +11 -0
  291. package/dist/plugins/dashboard/schema.mjs.map +1 -0
  292. package/dist/plugins/dashboard/server.mjs +166 -0
  293. package/dist/plugins/dashboard/server.mjs.map +1 -0
  294. package/dist/plugins/deepbook/deploy.mjs +53 -115
  295. package/dist/plugins/deepbook/deploy.mjs.map +1 -1
  296. package/dist/plugins/deepbook/errors.mjs +1 -0
  297. package/dist/plugins/deepbook/errors.mjs.map +1 -1
  298. package/dist/plugins/deepbook/faucet-strategy.mjs +47 -34
  299. package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
  300. package/dist/plugins/deepbook/hash.mjs +9 -0
  301. package/dist/plugins/deepbook/hash.mjs.map +1 -0
  302. package/dist/plugins/deepbook/index.d.mts +1 -10
  303. package/dist/plugins/deepbook/index.mjs +25 -22
  304. package/dist/plugins/deepbook/index.mjs.map +1 -1
  305. package/dist/plugins/deepbook/pyth/index.mjs +26 -55
  306. package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
  307. package/dist/plugins/deepbook/snapshot.mjs +17 -29
  308. package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
  309. package/dist/plugins/deepbook/spans.mjs +18 -0
  310. package/dist/plugins/deepbook/spans.mjs.map +1 -0
  311. package/dist/plugins/deepbook/type-strings.mjs +65 -0
  312. package/dist/plugins/deepbook/type-strings.mjs.map +1 -0
  313. package/dist/plugins/deepbook/types.d.mts +2 -3
  314. package/dist/plugins/deepbook/types.mjs.map +1 -1
  315. package/dist/plugins/faucet/dispatcher.d.mts +21 -2
  316. package/dist/plugins/faucet/dispatcher.mjs +1 -2
  317. package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
  318. package/dist/plugins/faucet/errors.d.mts +11 -24
  319. package/dist/plugins/faucet/errors.mjs.map +1 -1
  320. package/dist/plugins/faucet/http.mjs +33 -14
  321. package/dist/plugins/faucet/http.mjs.map +1 -1
  322. package/dist/plugins/faucet/index.d.mts +15 -5
  323. package/dist/plugins/faucet/index.mjs +3 -0
  324. package/dist/plugins/faucet/index.mjs.map +1 -1
  325. package/dist/plugins/faucet/spans.mjs +12 -0
  326. package/dist/plugins/faucet/spans.mjs.map +1 -0
  327. package/dist/plugins/host-service/errors.d.mts +1 -1
  328. package/dist/plugins/host-service/index.mjs +34 -8
  329. package/dist/plugins/host-service/index.mjs.map +1 -1
  330. package/dist/plugins/host-service/routable.mjs +2 -1
  331. package/dist/plugins/host-service/routable.mjs.map +1 -1
  332. package/dist/plugins/host-service/service.d.mts +21 -0
  333. package/dist/plugins/host-service/service.mjs +136 -81
  334. package/dist/plugins/host-service/service.mjs.map +1 -1
  335. package/dist/plugins/internal/acquire-on-chain-artifact.mjs +23 -0
  336. package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -0
  337. package/dist/plugins/internal/codegen-helpers.mjs +18 -0
  338. package/dist/plugins/internal/codegen-helpers.mjs.map +1 -0
  339. package/dist/plugins/internal/funding-failure-error.mjs +32 -0
  340. package/dist/plugins/internal/funding-failure-error.mjs.map +1 -0
  341. package/dist/plugins/package/build.mjs +1 -1
  342. package/dist/plugins/package/build.mjs.map +1 -1
  343. package/dist/plugins/package/codegen.mjs +26 -0
  344. package/dist/plugins/package/codegen.mjs.map +1 -1
  345. package/dist/plugins/package/errors.d.mts +16 -6
  346. package/dist/plugins/package/errors.mjs.map +1 -1
  347. package/dist/plugins/package/index.d.mts +0 -4
  348. package/dist/plugins/package/index.mjs +27 -21
  349. package/dist/plugins/package/index.mjs.map +1 -1
  350. package/dist/plugins/package/mode-known.mjs +26 -12
  351. package/dist/plugins/package/mode-known.mjs.map +1 -1
  352. package/dist/plugins/package/mode-local.mjs +47 -41
  353. package/dist/plugins/package/mode-local.mjs.map +1 -1
  354. package/dist/plugins/package/publish-executor.mjs +55 -114
  355. package/dist/plugins/package/publish-executor.mjs.map +1 -1
  356. package/dist/plugins/package/registry.mjs +2 -1
  357. package/dist/plugins/package/registry.mjs.map +1 -1
  358. package/dist/plugins/package/service.mjs.map +1 -1
  359. package/dist/plugins/package/spans.mjs +14 -0
  360. package/dist/plugins/package/spans.mjs.map +1 -0
  361. package/dist/plugins/postgres/db-ensure.mjs +19 -12
  362. package/dist/plugins/postgres/db-ensure.mjs.map +1 -1
  363. package/dist/plugins/postgres/errors.d.mts +5 -0
  364. package/dist/plugins/postgres/errors.mjs.map +1 -1
  365. package/dist/plugins/postgres/index.mjs +10 -17
  366. package/dist/plugins/postgres/index.mjs.map +1 -1
  367. package/dist/plugins/postgres/service.mjs +58 -24
  368. package/dist/plugins/postgres/service.mjs.map +1 -1
  369. package/dist/plugins/postgres/snapshot.mjs.map +1 -1
  370. package/dist/plugins/postgres/spans.mjs +11 -0
  371. package/dist/plugins/postgres/spans.mjs.map +1 -0
  372. package/dist/plugins/router-entrypoints.mjs +4 -4
  373. package/dist/plugins/router-entrypoints.mjs.map +1 -1
  374. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +15 -13
  375. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
  376. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +15 -19
  377. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
  378. package/dist/plugins/seal/codegen.d.mts +2 -3
  379. package/dist/plugins/seal/codegen.mjs.map +1 -1
  380. package/dist/plugins/seal/config-render.mjs +35 -8
  381. package/dist/plugins/seal/config-render.mjs.map +1 -1
  382. package/dist/plugins/seal/deploy.mjs +31 -39
  383. package/dist/plugins/seal/deploy.mjs.map +1 -1
  384. package/dist/plugins/seal/errors.d.mts +1 -3
  385. package/dist/plugins/seal/errors.mjs +7 -1
  386. package/dist/plugins/seal/errors.mjs.map +1 -1
  387. package/dist/plugins/seal/index.d.mts +1 -6
  388. package/dist/plugins/seal/index.mjs +40 -14
  389. package/dist/plugins/seal/index.mjs.map +1 -1
  390. package/dist/plugins/seal/key-manager.d.mts +1 -9
  391. package/dist/plugins/seal/key-manager.mjs +2 -18
  392. package/dist/plugins/seal/key-manager.mjs.map +1 -1
  393. package/dist/plugins/seal/key-server.mjs +37 -36
  394. package/dist/plugins/seal/key-server.mjs.map +1 -1
  395. package/dist/plugins/seal/keygen.mjs +16 -17
  396. package/dist/plugins/seal/keygen.mjs.map +1 -1
  397. package/dist/plugins/seal/mode/fork-known.mjs +36 -14
  398. package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
  399. package/dist/plugins/seal/mode/live.d.mts +6 -4
  400. package/dist/plugins/seal/mode/live.mjs +14 -21
  401. package/dist/plugins/seal/mode/live.mjs.map +1 -1
  402. package/dist/plugins/seal/mode/local-keygen.mjs +57 -21
  403. package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
  404. package/dist/plugins/seal/registry-publish.mjs +1 -0
  405. package/dist/plugins/seal/registry-publish.mjs.map +1 -1
  406. package/dist/plugins/seal/routable.mjs.map +1 -1
  407. package/dist/plugins/seal/service.mjs.map +1 -1
  408. package/dist/plugins/seal/spans.mjs +18 -0
  409. package/dist/plugins/seal/spans.mjs.map +1 -0
  410. package/dist/plugins/sui/auto-tick.mjs +17 -23
  411. package/dist/plugins/sui/auto-tick.mjs.map +1 -1
  412. package/dist/plugins/sui/chain-build-container.mjs +18 -0
  413. package/dist/plugins/sui/chain-build-container.mjs.map +1 -0
  414. package/dist/plugins/sui/chain-probe.d.mts +5 -5
  415. package/dist/plugins/sui/chain-probe.mjs +28 -58
  416. package/dist/plugins/sui/chain-probe.mjs.map +1 -1
  417. package/dist/plugins/sui/codegen.mjs +26 -0
  418. package/dist/plugins/sui/codegen.mjs.map +1 -1
  419. package/dist/plugins/sui/errors.d.mts +2 -29
  420. package/dist/plugins/sui/errors.mjs +1 -3
  421. package/dist/plugins/sui/errors.mjs.map +1 -1
  422. package/dist/plugins/sui/fork-faucet-strategy.d.mts +1 -0
  423. package/dist/plugins/sui/fork-faucet-strategy.mjs +55 -0
  424. package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -0
  425. package/dist/plugins/sui/fork-orchestration.d.mts +1 -0
  426. package/dist/plugins/sui/fork-orchestration.mjs +170 -2
  427. package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
  428. package/dist/plugins/sui/fork-transaction.d.mts +2 -0
  429. package/dist/plugins/sui/fork-transaction.mjs +92 -28
  430. package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
  431. package/dist/plugins/sui/index.d.mts +33 -70
  432. package/dist/plugins/sui/index.mjs +58 -35
  433. package/dist/plugins/sui/index.mjs.map +1 -1
  434. package/dist/plugins/{faucet/strategies/sui-local.mjs → sui/local-faucet-strategy.mjs} +10 -7
  435. package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -0
  436. package/dist/plugins/sui/mode/external.mjs +7 -13
  437. package/dist/plugins/sui/mode/external.mjs.map +1 -1
  438. package/dist/plugins/sui/mode/fork.mjs +136 -59
  439. package/dist/plugins/sui/mode/fork.mjs.map +1 -1
  440. package/dist/plugins/sui/mode/live.mjs +10 -16
  441. package/dist/plugins/sui/mode/live.mjs.map +1 -1
  442. package/dist/plugins/sui/mode/local.mjs +37 -36
  443. package/dist/plugins/sui/mode/local.mjs.map +1 -1
  444. package/dist/plugins/sui/mode/shared-boot.mjs +38 -115
  445. package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
  446. package/dist/plugins/sui/mode/shared.d.mts +1 -5
  447. package/dist/plugins/sui/mode/shared.mjs.map +1 -1
  448. package/dist/plugins/sui/mode/spec.d.mts +18 -0
  449. package/dist/plugins/sui/move-summary-runner.mjs +207 -0
  450. package/dist/plugins/sui/move-summary-runner.mjs.map +1 -0
  451. package/dist/plugins/sui/network-resolver.d.mts +4 -3
  452. package/dist/plugins/sui/service.mjs.map +1 -1
  453. package/dist/plugins/sui/snapshot.mjs +3 -0
  454. package/dist/plugins/sui/snapshot.mjs.map +1 -1
  455. package/dist/plugins/sui/spans.mjs +17 -0
  456. package/dist/plugins/sui/spans.mjs.map +1 -0
  457. package/dist/plugins/wallet/codegen.d.mts +0 -1
  458. package/dist/plugins/wallet/codegen.mjs +8 -9
  459. package/dist/plugins/wallet/codegen.mjs.map +1 -1
  460. package/dist/plugins/wallet/index.d.mts +6 -8
  461. package/dist/plugins/wallet/index.mjs +46 -35
  462. package/dist/plugins/wallet/index.mjs.map +1 -1
  463. package/dist/plugins/wallet/origin-policy.mjs +12 -28
  464. package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
  465. package/dist/plugins/wallet/pairing.mjs +6 -4
  466. package/dist/plugins/wallet/pairing.mjs.map +1 -1
  467. package/dist/plugins/wallet/protocol.d.mts +1 -0
  468. package/dist/plugins/wallet/protocol.mjs +5 -44
  469. package/dist/plugins/wallet/protocol.mjs.map +1 -1
  470. package/dist/plugins/wallet/routable.mjs +2 -8
  471. package/dist/plugins/wallet/routable.mjs.map +1 -1
  472. package/dist/plugins/wallet/server.mjs +36 -44
  473. package/dist/plugins/wallet/server.mjs.map +1 -1
  474. package/dist/plugins/wallet/service.d.mts +1 -5
  475. package/dist/plugins/wallet/service.mjs +22 -18
  476. package/dist/plugins/wallet/service.mjs.map +1 -1
  477. package/dist/plugins/wallet/spans.mjs +22 -0
  478. package/dist/plugins/wallet/spans.mjs.map +1 -0
  479. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +33 -8
  480. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
  481. package/dist/plugins/walrus/codegen.d.mts +3 -3
  482. package/dist/plugins/walrus/codegen.mjs.map +1 -1
  483. package/dist/plugins/walrus/deploy-paths.mjs +21 -5
  484. package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
  485. package/dist/plugins/walrus/deploy.mjs +67 -69
  486. package/dist/plugins/walrus/deploy.mjs.map +1 -1
  487. package/dist/plugins/walrus/errors.mjs +1 -0
  488. package/dist/plugins/walrus/errors.mjs.map +1 -1
  489. package/dist/plugins/walrus/faucet-strategy.mjs +12 -7
  490. package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
  491. package/dist/plugins/walrus/index.d.mts +2 -13
  492. package/dist/plugins/walrus/index.mjs +18 -23
  493. package/dist/plugins/walrus/index.mjs.map +1 -1
  494. package/dist/plugins/walrus/mode/known-deploy.mjs +7 -5
  495. package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
  496. package/dist/plugins/walrus/mode/local-cluster.mjs +26 -7
  497. package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
  498. package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
  499. package/dist/plugins/walrus/routable.mjs +7 -23
  500. package/dist/plugins/walrus/routable.mjs.map +1 -1
  501. package/dist/plugins/walrus/service.mjs.map +1 -1
  502. package/dist/plugins/walrus/spans.mjs +18 -0
  503. package/dist/plugins/walrus/spans.mjs.map +1 -0
  504. package/dist/plugins/walrus/storage-nodes.d.mts +6 -2
  505. package/dist/plugins/walrus/storage-nodes.mjs +15 -8
  506. package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
  507. package/dist/plugins/walrus/wal-swap.mjs +58 -15
  508. package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
  509. package/dist/primitives/artifact-publisher.d.mts +1 -1
  510. package/dist/primitives/artifact-publisher.mjs +15 -0
  511. package/dist/primitives/artifact-publisher.mjs.map +1 -0
  512. package/dist/runtime/docker/client.mjs +17 -4
  513. package/dist/runtime/docker/client.mjs.map +1 -1
  514. package/dist/runtime/docker/container.mjs +219 -132
  515. package/dist/runtime/docker/container.mjs.map +1 -1
  516. package/dist/runtime/docker/errors.mjs +0 -6
  517. package/dist/runtime/docker/errors.mjs.map +1 -1
  518. package/dist/runtime/docker/exec.mjs +21 -18
  519. package/dist/runtime/docker/exec.mjs.map +1 -1
  520. package/dist/runtime/docker/image.mjs +36 -13
  521. package/dist/runtime/docker/image.mjs.map +1 -1
  522. package/dist/runtime/docker/index.mjs +14 -0
  523. package/dist/runtime/docker/inspect-and-decode.mjs +51 -0
  524. package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -0
  525. package/dist/runtime/docker/inventory.mjs +14 -11
  526. package/dist/runtime/docker/inventory.mjs.map +1 -1
  527. package/dist/runtime/docker/labels.mjs +38 -5
  528. package/dist/runtime/docker/labels.mjs.map +1 -1
  529. package/dist/runtime/docker/logs.d.mts +1 -1
  530. package/dist/runtime/docker/logs.mjs.map +1 -1
  531. package/dist/runtime/docker/network.mjs +83 -47
  532. package/dist/runtime/docker/network.mjs.map +1 -1
  533. package/dist/runtime/docker/render-run-args.mjs +82 -0
  534. package/dist/runtime/docker/render-run-args.mjs.map +1 -0
  535. package/dist/runtime/docker/service.d.mts +1 -1
  536. package/dist/runtime/docker/service.mjs +12 -7
  537. package/dist/runtime/docker/service.mjs.map +1 -1
  538. package/dist/runtime/docker/sweep.mjs +118 -43
  539. package/dist/runtime/docker/sweep.mjs.map +1 -1
  540. package/dist/runtime/docker/volume.mjs +2 -0
  541. package/dist/runtime/docker/volume.mjs.map +1 -1
  542. package/dist/runtime/docker/wrap.mjs +30 -1
  543. package/dist/runtime/docker/wrap.mjs.map +1 -1
  544. package/dist/substrate/cross-process.mjs +14 -8
  545. package/dist/substrate/cross-process.mjs.map +1 -1
  546. package/dist/substrate/event-time.mjs +33 -0
  547. package/dist/substrate/event-time.mjs.map +1 -0
  548. package/dist/substrate/events.d.mts +28 -8
  549. package/dist/substrate/identity.d.mts +2 -1
  550. package/dist/substrate/manifest.d.mts +68 -5
  551. package/dist/substrate/manifest.mjs +34 -5
  552. package/dist/substrate/manifest.mjs.map +1 -1
  553. package/dist/substrate/network.d.mts +3 -5
  554. package/dist/substrate/options.d.mts +0 -2
  555. package/dist/substrate/plugin.d.mts +13 -0
  556. package/dist/substrate/plugin.mjs +4 -2
  557. package/dist/substrate/plugin.mjs.map +1 -1
  558. package/dist/substrate/projection.d.mts +35 -3
  559. package/dist/substrate/runtime/artifact-publisher/index.mjs +19 -9
  560. package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -1
  561. package/dist/substrate/runtime/atomic-write.mjs +97 -32
  562. package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
  563. package/dist/substrate/runtime/cache/index.mjs +3 -0
  564. package/dist/substrate/runtime/cache/schema.mjs +2 -2
  565. package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
  566. package/dist/substrate/runtime/cache/service.mjs +9 -7
  567. package/dist/substrate/runtime/cache/service.mjs.map +1 -1
  568. package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -1
  569. package/dist/substrate/runtime/capability-sinks/index.mjs +3 -0
  570. package/dist/substrate/runtime/capability-sinks/layer.mjs +1 -1
  571. package/dist/substrate/runtime/capability-sinks/service.d.mts +61 -2
  572. package/dist/substrate/runtime/capability-sinks/service.mjs +21 -26
  573. package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -1
  574. package/dist/substrate/runtime/config-validation.d.mts +1 -13
  575. package/dist/substrate/runtime/config-validation.mjs +2 -91
  576. package/dist/substrate/runtime/config-validation.mjs.map +1 -1
  577. package/dist/substrate/runtime/container-runtime.d.mts +1 -0
  578. package/dist/substrate/runtime/container-runtime.mjs +2 -0
  579. package/dist/substrate/runtime/control-plane/domain.mjs +101 -0
  580. package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -0
  581. package/dist/substrate/runtime/control-plane/service.mjs +7 -0
  582. package/dist/substrate/runtime/control-plane/service.mjs.map +1 -0
  583. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +46 -19
  584. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
  585. package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +30 -12
  586. package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
  587. package/dist/substrate/runtime/cross-process/command-channel/index.mjs +5 -0
  588. package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +11 -2
  589. package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
  590. package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs +1 -1
  591. package/dist/substrate/runtime/cross-process/index.mjs +11 -0
  592. package/dist/substrate/runtime/cross-process/live-clock.mjs +34 -0
  593. package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -0
  594. package/dist/substrate/runtime/cross-process/liveness.mjs +52 -10
  595. package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
  596. package/dist/substrate/runtime/cross-process/lock.d.mts +1 -0
  597. package/dist/substrate/runtime/cross-process/lock.mjs +23 -0
  598. package/dist/substrate/runtime/cross-process/lock.mjs.map +1 -0
  599. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +64 -0
  600. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -0
  601. package/dist/substrate/runtime/cross-process/roster.mjs +97 -83
  602. package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
  603. package/dist/substrate/runtime/cross-process/self-pid.mjs +8 -0
  604. package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -0
  605. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +24 -28
  606. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -1
  607. package/dist/substrate/runtime/cross-process/stack-lock.mjs +41 -20
  608. package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
  609. package/dist/substrate/runtime/current-plugin.mjs +2 -2
  610. package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
  611. package/dist/substrate/runtime/errors.mjs +12 -6
  612. package/dist/substrate/runtime/errors.mjs.map +1 -1
  613. package/dist/substrate/runtime/format-unknown-error.mjs +30 -0
  614. package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -0
  615. package/dist/substrate/runtime/host-bind-mount-owner.mjs +10 -0
  616. package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -0
  617. package/dist/substrate/runtime/host-gateway.mjs +20 -0
  618. package/dist/substrate/runtime/host-gateway.mjs.map +1 -0
  619. package/dist/substrate/runtime/host-tree-tar/index.mjs +61 -50
  620. package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
  621. package/dist/substrate/runtime/http-probe.d.mts +1 -1
  622. package/dist/substrate/runtime/index.mjs +14 -0
  623. package/dist/substrate/runtime/lease-broker/index.d.mts +1 -1
  624. package/dist/substrate/runtime/lease-broker/index.mjs +2 -0
  625. package/dist/substrate/runtime/lease-broker/service.d.mts +1 -64
  626. package/dist/substrate/runtime/lease-broker/service.mjs +1 -1
  627. package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
  628. package/dist/substrate/runtime/lifecycle/dep-graph.mjs +22 -3
  629. package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
  630. package/dist/substrate/runtime/lifecycle/index.mjs +9 -0
  631. package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -1
  632. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +20 -3
  633. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
  634. package/dist/substrate/runtime/lifecycle/selective-restart.mjs +1 -1
  635. package/dist/substrate/runtime/lifecycle/signals.mjs +5 -5
  636. package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
  637. package/dist/substrate/runtime/lifecycle/state-machine.mjs +1 -1
  638. package/dist/substrate/runtime/managed-container.d.mts +19 -1
  639. package/dist/substrate/runtime/managed-container.mjs +20 -1
  640. package/dist/substrate/runtime/managed-container.mjs.map +1 -1
  641. package/dist/substrate/runtime/manifest/index.mjs +3 -0
  642. package/dist/substrate/runtime/manifest/manifest.mjs +15 -11
  643. package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
  644. package/dist/substrate/runtime/mode-errors.mjs +20 -0
  645. package/dist/substrate/runtime/mode-errors.mjs.map +1 -0
  646. package/dist/substrate/runtime/observability/cascade-formatter.mjs +9 -13
  647. package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
  648. package/dist/substrate/runtime/observability/formatter-registry.mjs +19 -36
  649. package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -1
  650. package/dist/substrate/runtime/observability/ignore-with-log.d.mts +1 -0
  651. package/dist/substrate/runtime/observability/ignore-with-log.mjs +17 -0
  652. package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -0
  653. package/dist/substrate/runtime/observability/index.d.mts +1 -1
  654. package/dist/substrate/runtime/observability/index.mjs +13 -0
  655. package/dist/substrate/runtime/observability/log-store.d.mts +1 -0
  656. package/dist/substrate/runtime/observability/log-store.mjs +175 -0
  657. package/dist/substrate/runtime/observability/log-store.mjs.map +1 -0
  658. package/dist/substrate/runtime/observability/logger.d.mts +2 -1
  659. package/dist/substrate/runtime/observability/logger.mjs +5 -9
  660. package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
  661. package/dist/substrate/runtime/observability/output-truncate.mjs +35 -0
  662. package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -0
  663. package/dist/substrate/runtime/observability/pretty-error.mjs +9 -12
  664. package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
  665. package/dist/substrate/runtime/observability/redaction.d.mts +2 -13
  666. package/dist/substrate/runtime/observability/redaction.mjs +8 -14
  667. package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
  668. package/dist/substrate/runtime/observability/span-store.d.mts +1 -0
  669. package/dist/substrate/runtime/observability/span-store.mjs +110 -0
  670. package/dist/substrate/runtime/observability/span-store.mjs.map +1 -0
  671. package/dist/substrate/runtime/observability/spans.mjs +14 -14
  672. package/dist/substrate/runtime/observability/spans.mjs.map +1 -1
  673. package/dist/substrate/runtime/observability/subprocess-capture.mjs +1 -1
  674. package/dist/substrate/runtime/passthrough-or-wrap.mjs +33 -0
  675. package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -0
  676. package/dist/substrate/runtime/paths.d.mts +1 -1
  677. package/dist/substrate/runtime/paths.mjs +4 -3
  678. package/dist/substrate/runtime/paths.mjs.map +1 -1
  679. package/dist/substrate/runtime/phase-preserving-produce.mjs +40 -0
  680. package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -0
  681. package/dist/substrate/runtime/port-broker/index.mjs +3 -0
  682. package/dist/substrate/runtime/port-broker/service.mjs +170 -126
  683. package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
  684. package/dist/substrate/runtime/post-acquire-tasks.mjs +1 -1
  685. package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
  686. package/dist/substrate/runtime/probes.d.mts +7 -5
  687. package/dist/substrate/runtime/probes.mjs +3 -1
  688. package/dist/substrate/runtime/probes.mjs.map +1 -1
  689. package/dist/substrate/runtime/projection/index.mjs +4 -0
  690. package/dist/substrate/runtime/projection/operational-endpoints.mjs +1 -2
  691. package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
  692. package/dist/substrate/runtime/projection/persisted.mjs +33 -15
  693. package/dist/substrate/runtime/projection/persisted.mjs.map +1 -1
  694. package/dist/substrate/runtime/projection/state-ref.mjs +26 -2
  695. package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
  696. package/dist/substrate/runtime/projection/update.mjs +88 -24
  697. package/dist/substrate/runtime/projection/update.mjs.map +1 -1
  698. package/dist/substrate/runtime/random-suffix.mjs +11 -0
  699. package/dist/substrate/runtime/random-suffix.mjs.map +1 -0
  700. package/dist/substrate/runtime/retry-policy.d.mts +59 -1
  701. package/dist/substrate/runtime/retry-policy.mjs +66 -1
  702. package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
  703. package/dist/substrate/runtime/routed-url.d.mts +1 -0
  704. package/dist/substrate/runtime/routed-url.mjs +79 -0
  705. package/dist/substrate/runtime/routed-url.mjs.map +1 -0
  706. package/dist/substrate/runtime/runtime-decode.d.mts +1 -1
  707. package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
  708. package/dist/substrate/runtime/scoped-http-server.mjs +2 -3
  709. package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
  710. package/dist/substrate/runtime/scoped-multimap/index.mjs +2 -0
  711. package/dist/substrate/runtime/scoped-multimap/service.mjs +52 -0
  712. package/dist/substrate/runtime/scoped-multimap/service.mjs.map +1 -0
  713. package/dist/substrate/runtime/scoped-ref-map/index.mjs +2 -0
  714. package/dist/substrate/runtime/scoped-ref-map/service.mjs +2 -2
  715. package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -1
  716. package/dist/substrate/runtime/stage-and-swap/index.mjs +72 -4
  717. package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
  718. package/dist/substrate/runtime/state-store/index.d.mts +1 -0
  719. package/dist/substrate/runtime/state-store/index.mjs +3 -0
  720. package/dist/substrate/runtime/state-store/schema.d.mts +1 -0
  721. package/dist/substrate/runtime/state-store/schema.mjs +19 -14
  722. package/dist/substrate/runtime/state-store/schema.mjs.map +1 -1
  723. package/dist/substrate/runtime/state-store/service.d.mts +1 -0
  724. package/dist/substrate/runtime/state-store/service.mjs +145 -0
  725. package/dist/substrate/runtime/state-store/service.mjs.map +1 -0
  726. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.d.mts +1 -0
  727. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs +33 -0
  728. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -0
  729. package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +1 -1
  730. package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
  731. package/dist/substrate/runtime/strategy-registry/index.mjs +4 -0
  732. package/dist/substrate/runtime/strategy-registry/service.mjs +19 -33
  733. package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
  734. package/dist/substrate/runtime/subnet-broker.mjs +60 -0
  735. package/dist/substrate/runtime/subnet-broker.mjs.map +1 -0
  736. package/dist/substrate/runtime/sui-execute/index.d.mts +21 -1
  737. package/dist/substrate/runtime/sui-execute/index.mjs +84 -20
  738. package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -1
  739. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.d.mts +1 -0
  740. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs +32 -0
  741. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +1 -0
  742. package/dist/substrate/runtime/sui-ledger/object-ref.mjs +32 -0
  743. package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +1 -0
  744. package/dist/substrate/runtime/sui-move-build/index.mjs +93 -19
  745. package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -1
  746. package/dist/substrate/runtime/supervisor/acquire-node.mjs +181 -0
  747. package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -0
  748. package/dist/substrate/runtime/supervisor/background-tasks.mjs +144 -0
  749. package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -0
  750. package/dist/substrate/runtime/supervisor/command-loop.mjs +68 -0
  751. package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -0
  752. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +151 -0
  753. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +1 -0
  754. package/dist/substrate/runtime/supervisor/errors.d.mts +1 -0
  755. package/dist/substrate/runtime/supervisor/errors.mjs +9 -0
  756. package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -0
  757. package/dist/substrate/runtime/supervisor/index.d.mts +1 -0
  758. package/dist/substrate/runtime/supervisor/index.mjs +3 -0
  759. package/dist/substrate/runtime/supervisor/shutdown.mjs +51 -0
  760. package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -0
  761. package/dist/substrate/runtime/supervisor/start-supervisor.d.mts +1 -0
  762. package/dist/substrate/runtime/supervisor/start-supervisor.mjs +250 -0
  763. package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -0
  764. package/dist/substrate/runtime/supervisor/state.d.mts +1 -0
  765. package/dist/substrate/runtime/supervisor/state.mjs +22 -0
  766. package/dist/substrate/runtime/supervisor/state.mjs.map +1 -0
  767. package/dist/substrate/runtime/supervisor/teardown.mjs +57 -0
  768. package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -0
  769. package/dist/substrate/runtime/supervisor/types.d.mts +1 -0
  770. package/dist/substrate/runtime/supervisor/wiring.mjs +133 -0
  771. package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -0
  772. package/dist/substrate/runtime/typed-env.mjs +8 -0
  773. package/dist/substrate/runtime/typed-env.mjs.map +1 -0
  774. package/dist/substrate/state-store.d.mts +1 -0
  775. package/dist/substrate/versioned-doc-schema.mjs +17 -0
  776. package/dist/substrate/versioned-doc-schema.mjs.map +1 -0
  777. package/dist/substrate/versioned-doc-sync.mjs +94 -0
  778. package/dist/substrate/versioned-doc-sync.mjs.map +1 -0
  779. package/dist/surfaces/cli/command-tree.mjs.map +1 -1
  780. package/dist/surfaces/cli/commands/index.mjs +9 -0
  781. package/dist/surfaces/cli/commands/prune-picker-entry.mjs +13 -0
  782. package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -0
  783. package/dist/surfaces/cli/commands/prune-picker.mjs +3 -2
  784. package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
  785. package/dist/surfaces/cli/commands/prune.mjs +34 -17
  786. package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
  787. package/dist/surfaces/cli/commands/status.mjs +2 -2
  788. package/dist/surfaces/cli/commands/status.mjs.map +1 -1
  789. package/dist/surfaces/cli/commands/supervisor-presence.mjs +5 -3
  790. package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
  791. package/dist/surfaces/cli/commands/wipe.mjs +38 -4
  792. package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
  793. package/dist/surfaces/cli/errors.mjs +1 -1
  794. package/dist/surfaces/cli/errors.mjs.map +1 -1
  795. package/dist/surfaces/cli/flags.mjs +0 -1
  796. package/dist/surfaces/cli/flags.mjs.map +1 -1
  797. package/dist/surfaces/cli/index.mjs +98 -18
  798. package/dist/surfaces/cli/index.mjs.map +1 -1
  799. package/dist/surfaces/cli/output.mjs +1 -0
  800. package/dist/surfaces/cli/output.mjs.map +1 -1
  801. package/dist/surfaces/cli/sysexits.mjs +2 -1
  802. package/dist/surfaces/cli/sysexits.mjs.map +1 -1
  803. package/dist/surfaces/tui/app.mjs +25 -3
  804. package/dist/surfaces/tui/app.mjs.map +1 -1
  805. package/dist/surfaces/tui/display-derivation.mjs +23 -74
  806. package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
  807. package/dist/surfaces/tui/event-log.mjs +35 -23
  808. package/dist/surfaces/tui/event-log.mjs.map +1 -1
  809. package/dist/surfaces/tui/input.mjs +5 -1
  810. package/dist/surfaces/tui/input.mjs.map +1 -1
  811. package/dist/surfaces/tui/plain-renderer.mjs +70 -34
  812. package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
  813. package/package.json +24 -4
  814. package/dist/contracts/liveness-classifier.d.mts +0 -19
  815. package/dist/contracts/network-resolver.d.mts +0 -15
  816. package/dist/contracts/network-resolver.mjs +0 -7
  817. package/dist/contracts/network-resolver.mjs.map +0 -1
  818. package/dist/orchestrators/codegen/extras.mjs +0 -16
  819. package/dist/orchestrators/codegen/extras.mjs.map +0 -1
  820. package/dist/plugins/deepbook/routable.mjs +0 -21
  821. package/dist/plugins/deepbook/routable.mjs.map +0 -1
  822. package/dist/plugins/faucet/service.d.mts +0 -20
  823. package/dist/plugins/faucet/strategies/sui-local.d.mts +0 -23
  824. package/dist/plugins/faucet/strategies/sui-local.mjs.map +0 -1
  825. package/dist/plugins/sui/seed-objects.d.mts +0 -18
  826. package/dist/plugins/sui/seed-objects.mjs +0 -25
  827. package/dist/plugins/sui/seed-objects.mjs.map +0 -1
  828. package/dist/runtime/built-in-plugin-layers.mjs.map +0 -1
  829. package/dist/substrate/runtime/context-helpers.mjs +0 -32
  830. package/dist/substrate/runtime/context-helpers.mjs.map +0 -1
  831. package/dist/substrate/runtime/run.mjs.map +0 -1
  832. package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +0 -30
  833. package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +0 -1
  834. package/dist/substrate/runtime/supervisor.d.mts +0 -1
  835. package/dist/substrate/runtime/supervisor.mjs +0 -831
  836. package/dist/substrate/runtime/supervisor.mjs.map +0 -1
  837. package/dist/surfaces/cli/commands/doctor-probes.mjs.map +0 -1
  838. /package/dist/{substrate/runtime/strategy-registry/faucet-capability-for.d.mts → plugins/faucet/http.d.mts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"fork.mjs","names":["sharedFetchChainId"],"sources":["../../../../src/plugins/sui/mode/fork.ts"],"sourcesContent":["// Sui plugin — fork mode.\n\nimport { createHash } from 'node:crypto';\nimport { mkdir } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\nimport { normalizeSuiAddress, normalizeSuiObjectId } from '@mysten/sui/utils';\n\nimport type {\n\tContainerHandle,\n\tContainerPortPublish,\n\tContainerRuntime,\n\tContainerRuntimeError,\n\tImageRef,\n\tPortBindingReconciliation,\n} from '../../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../../contracts/snapshotable.ts';\nimport type { Identity } from '../../../substrate/identity.ts';\nimport { ensureManagedContainer } from '../../../substrate/runtime/managed-container.ts';\nimport type { StackPaths } from '../../../substrate/runtime/paths.ts';\nimport type { AllocatedPort, PortBroker } from '../../../substrate/runtime/port-broker/index.ts';\nimport { ProbeTimeoutError, waitForProbe } from '../../../substrate/runtime/probes.ts';\nimport { renderUrl, routerHostname } from '../../../orchestrators/router/hostname.ts';\nimport { resolveAutoTickIntervalMs, runAutoTickClock } from '../auto-tick.ts';\nimport { suiPluginError, type SeedManifestMismatchError, type SuiPluginError } from '../errors.ts';\nimport type { ResolvedSuiNetwork } from '../network-resolver.ts';\nimport { SUI_RPC_ENDPOINT_NAME, SUI_RPC_ENTRYPOINT_PORT } from '../routable.ts';\nimport { wrapWithForkGuard } from '../fork-orchestration.ts';\nimport { verifyForkImpersonationSender } from '../fork-transaction.ts';\nimport { DEFAULT_SUI_CLI_VERSION } from '../../../substrate/runtime/sui-move-build/index.ts';\nimport type { ForkAdminSurface, SuiClient } from './shared.ts';\nimport { toDockerHostGatewayUrl } from './shared.ts';\nimport {\n\tassembleSuiClient,\n\tfetchChainId as sharedFetchChainId,\n\tmakeResolvedNetwork,\n\tnoopWaitForTransactionsReady,\n} from './shared-boot.ts';\nimport type { SuiForkOptions } from './spec.ts';\n\n/** Default ready-probe timeout for fork-mode cold start. */\nexport const DEFAULT_FORK_READY_TIMEOUT = Duration.seconds(180);\n\n/** Default Sui repository revision used by the bundled `sui-fork` image build. */\nexport const DEFAULT_SUI_FORK_REV = '62ee6ada958cd61b3c8a4466dd33c9aba3cdff8a';\n\n/** Map upstream literal to the canonical \"live\" chain id known by wallet-standard / MVR. */\nexport const FORK_UPSTREAM_TO_KNOWN_NETWORK = {\n\tmainnet: 'sui:mainnet',\n\ttestnet: 'sui:testnet',\n\tdevnet: 'sui:devnet',\n} as const;\n\nexport const DEFAULT_FORK_HOST_RPC_PORT = 51002;\nexport const FORK_VALIDATOR_STOP_GRACE_SECONDS = 30;\n\nconst DOCKER_PUBLISH_HOST = '0.0.0.0' as const;\nconst CONTAINER_RPC_PORT = SUI_RPC_ENTRYPOINT_PORT;\nconst FORK_CONTAINER_DATA_DIR = '/var/lib/sui-fork';\nconst PROBE_ATTEMPT_TIMEOUT_MS = 3_000;\n\n/** Resolved fork-mode boot artifacts. */\nexport interface ForkModeBootResult {\n\treadonly resolved: ResolvedSuiNetwork;\n\treadonly client: SuiClient;\n\treadonly autoTickIntervalMs: number | undefined;\n}\n\nexport const bootForkMode = (\n\truntime: ContainerRuntime,\n\tidentity: Identity,\n\tportBroker: PortBroker,\n\tpaths: StackPaths,\n\topts: SuiForkOptions,\n): Effect.Effect<ForkModeBootResult, SuiPluginError | SeedManifestMismatchError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst autoTickIntervalMs = resolveAutoTickIntervalMs(opts.autoTick);\n\t\tconst image = yield* resolveForkImage(runtime, opts);\n\t\tconst dataDir = yield* ensureForkDataDir(paths, opts);\n\n\t\tconst labels: ContainerLabelTuple = {\n\t\t\tapp: identity.app,\n\t\t\tstack: identity.stack,\n\t\t\tplugin: 'sui',\n\t\t\trole: 'fork-validator',\n\t\t};\n\t\tconst containerName = `devstack-${identity.app}-${identity.stack}-sui-fork`;\n\t\tconst { handle, ports } = yield* ensureForkContainer({\n\t\t\truntime,\n\t\t\tportBroker,\n\t\t\timage,\n\t\t\tlabels,\n\t\t\tcontainerName,\n\t\t\tdataDir,\n\t\t\topts,\n\t\t});\n\n\t\tconst published = pickPublishedPort(ports, handle.ports);\n\t\tconst directRpcUrl = `http://127.0.0.1:${published.hostPort}`;\n\t\tconst rpcUrl = yield* routedSuiRpcUrl(identity);\n\t\tconst sdkClient = new SuiGrpcClient({ baseUrl: directRpcUrl, network: opts.upstream });\n\t\tconst readyTimeout = opts.readyTimeout ?? DEFAULT_FORK_READY_TIMEOUT;\n\n\t\tconst status = yield* waitForForkReady(sdkClient, readyTimeout).pipe(\n\t\t\tEffect.annotateLogs({ 'sui.container': handle.name }),\n\t\t);\n\t\tconst chain = yield* sharedFetchChainId(sdkClient, {\n\t\t\tspan: 'devstack.plugin.sui.fork.fetchChainId',\n\t\t});\n\n\t\tconst fork = makeForkAdminSurface(sdkClient);\n\t\tconst assembled = assembleSuiClient({\n\t\t\tsdkClient,\n\t\t\tchain,\n\t\t\trpcUrl,\n\t\t\twaitForTransactionsReady: noopWaitForTransactionsReady,\n\t\t\tbuildImage: image,\n\t\t\thostGateway: {\n\t\t\t\trpcUrl: toDockerHostGatewayUrl(directRpcUrl),\n\t\t\t\tfaucetUrl: null,\n\t\t\t\tgraphqlUrl: null,\n\t\t\t},\n\t\t});\n\t\tconst client: SuiClient = {\n\t\t\t...assembled.client,\n\t\t\tsdk: wrapWithForkGuard(assembled.sdkShim),\n\t\t\tfork,\n\t\t};\n\n\t\tif (autoTickIntervalMs !== undefined) {\n\t\t\tyield* runAutoTickClock(fork, autoTickIntervalMs);\n\t\t}\n\n\t\treturn {\n\t\t\tresolved: makeResolvedNetwork({\n\t\t\t\tmode: 'fork',\n\t\t\t\tchain,\n\t\t\t\trpc: rpcUrl,\n\t\t\t\tsource: 'default',\n\t\t\t\tcheckpoint: status.forkedAtCheckpoint,\n\t\t\t\tforkUpstream: opts.upstream,\n\t\t\t}),\n\t\t\tclient,\n\t\t\tautoTickIntervalMs,\n\t\t};\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.sui.fork.boot', { attributes: { 'devstack.plugin': 'sui' } }),\n\t);\n\nexport const suiForkImageBuildContext = (rev = DEFAULT_SUI_FORK_REV) => ({\n\tcontextPath: new URL('../../../../images/', import.meta.url).pathname,\n\tdockerfile: 'sui-fork/Dockerfile',\n\tbuildArgs: { SUI_FORK_REV: rev, SUI_CLI_VERSION: DEFAULT_SUI_CLI_VERSION },\n});\n\nexport const resolveForkImage = (\n\truntime: ContainerRuntime,\n\topts: SuiForkOptions,\n): Effect.Effect<ImageRef, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tif (opts.image && 'pull' in opts.image) {\n\t\t\tconst pullRef = opts.image.pull;\n\t\t\tif (runtime.pullImage === undefined) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t`sui fork mode cannot pull image '${pullRef}' because the configured container runtime does not expose image pulls.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn yield* runtime\n\t\t\t\t.pullImage(pullRef)\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t\t`sui fork mode failed to pull image '${pullRef}': ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t}\n\t\tconst rev = opts.version ?? DEFAULT_SUI_FORK_REV;\n\t\tconst buildCtx =\n\t\t\topts.image && 'build' in opts.image\n\t\t\t\t? {\n\t\t\t\t\t\tcontextPath: opts.image.build.context,\n\t\t\t\t\t\tdockerfile: opts.image.build.dockerfile ?? 'Dockerfile',\n\t\t\t\t\t\tbuildArgs: { SUI_FORK_REV: rev, SUI_CLI_VERSION: DEFAULT_SUI_CLI_VERSION },\n\t\t\t\t\t}\n\t\t\t\t: suiForkImageBuildContext(rev);\n\t\treturn yield* runtime\n\t\t\t.ensureImage(buildCtx)\n\t\t\t.pipe(\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t`sui fork image build failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.fork.resolveImage'));\n\ninterface ForkContainerResult {\n\treadonly handle: ContainerHandle;\n\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n}\n\nconst ensureForkContainer = (params: {\n\treadonly runtime: ContainerRuntime;\n\treadonly portBroker: PortBroker;\n\treadonly image: ImageRef;\n\treadonly labels: ContainerLabelTuple;\n\treadonly containerName: string;\n\treadonly dataDir: string;\n\treadonly opts: SuiForkOptions;\n}): Effect.Effect<ForkContainerResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst reusable =\n\t\t\tparams.opts.ports === undefined\n\t\t\t\t? yield* findReusableForkPort(params.runtime, params.labels, params.containerName)\n\t\t\t\t: undefined;\n\t\tconst ports =\n\t\t\treusable === undefined\n\t\t\t\t? [yield* allocateForkRpcPort(params.portBroker, params.opts.ports)]\n\t\t\t\t: [reusable];\n\t\tconst reconciliation: PortBindingReconciliation =\n\t\t\treusable === undefined && params.opts.ports !== undefined ? 'exact' : 'adopt-existing';\n\t\tconst command = forkStartCommand(params.opts);\n\t\tconst handle = yield* ensureManagedContainer({\n\t\t\truntime: params.runtime,\n\t\t\tlabels: params.labels,\n\t\t\tspec: {\n\t\t\t\tname: params.containerName,\n\t\t\t\timage: params.image,\n\t\t\t\trecreate: 'on-config-change',\n\t\t\t\tconfigHash: forkContainerConfigHash(params.opts, params.dataDir, command),\n\t\t\t\tstopGraceSeconds: FORK_VALIDATOR_STOP_GRACE_SECONDS,\n\t\t\t\tports,\n\t\t\t\tportBindingReconciliation: reconciliation,\n\t\t\t\tmounts: [{ source: params.dataDir, target: FORK_CONTAINER_DATA_DIR }],\n\t\t\t\tcommand,\n\t\t\t},\n\t\t\tmapError: (cause) => cause,\n\t\t}).pipe(\n\t\t\tEffect.mapError((cause: ContainerRuntimeError) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'container-start',\n\t\t\t\t\t`sui-fork container failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\treturn { handle, ports };\n\t});\n\nexport const forkStartCommand = (opts: SuiForkOptions): ReadonlyArray<string> => {\n\tconst seed = normalizeForkSeed(opts);\n\tconst command = [\n\t\t'start',\n\t\t'--network',\n\t\topts.upstream,\n\t\t'--data-dir',\n\t\tFORK_CONTAINER_DATA_DIR,\n\t\t'--rpc-addr',\n\t\t`0.0.0.0:${CONTAINER_RPC_PORT}`,\n\t];\n\tif (opts.checkpoint !== undefined) {\n\t\tcommand.push('--checkpoint', String(opts.checkpoint));\n\t}\n\tfor (const address of seed.addresses) {\n\t\tcommand.push('--address', address);\n\t}\n\tfor (const objectId of seed.objects) {\n\t\tcommand.push('--object', objectId);\n\t}\n\treturn command;\n};\n\nconst normalizeForkSeed = (opts: SuiForkOptions) => ({\n\taddresses: [\n\t\t...new Set((opts.seed?.addresses ?? []).map((address) => normalizeSuiAddress(address))),\n\t].sort(),\n\tobjects: [\n\t\t...new Set((opts.seed?.objects ?? []).map((objectId) => normalizeSuiObjectId(objectId))),\n\t].sort(),\n});\n\nconst forkContainerConfigHash = (\n\topts: SuiForkOptions,\n\tdataDir: string,\n\tcommand: ReadonlyArray<string>,\n): string =>\n\tcreateHash('sha256')\n\t\t.update(\n\t\t\tJSON.stringify({\n\t\t\t\tdataDir,\n\t\t\t\tcommand,\n\t\t\t\tversion: opts.version ?? DEFAULT_SUI_FORK_REV,\n\t\t\t\tports: opts.ports ?? null,\n\t\t\t}),\n\t\t)\n\t\t.digest('hex');\n\nconst allocateForkRpcPort = (\n\tportBroker: PortBroker,\n\toverride: Readonly<Record<number, number>> | undefined,\n): Effect.Effect<ContainerPortPublish, SuiPluginError, Scope.Scope> => {\n\tconst overridePort = override?.[CONTAINER_RPC_PORT];\n\tif (overridePort !== undefined) {\n\t\treturn Effect.succeed(portPublish(CONTAINER_RPC_PORT, overridePort));\n\t}\n\treturn portBroker\n\t\t.allocate({\n\t\t\tkind: 'rpc',\n\t\t\tpreferredPort: DEFAULT_FORK_HOST_RPC_PORT,\n\t\t\tprobeHost: DOCKER_PUBLISH_HOST,\n\t\t})\n\t\t.pipe(\n\t\t\tEffect.catchTag('PortBrokerError', (cause) =>\n\t\t\t\tcause.reason === 'preferred-busy'\n\t\t\t\t\t? portBroker.allocate({ kind: 'rpc', probeHost: DOCKER_PUBLISH_HOST })\n\t\t\t\t\t: Effect.fail(cause),\n\t\t\t),\n\t\t\tEffect.map((allocated: AllocatedPort) => portPublish(CONTAINER_RPC_PORT, allocated.port)),\n\t\t\tEffect.mapError((cause) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'port-allocate',\n\t\t\t\t\t`sui fork mode: failed to allocate RPC host port: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n};\n\nconst findReusableForkPort = (\n\truntime: ContainerRuntime,\n\tlabels: ContainerLabelTuple,\n\tcontainerName: string,\n): Effect.Effect<ContainerPortPublish | undefined, SuiPluginError> =>\n\truntime.inspectByLabels(labels).pipe(\n\t\tEffect.map((handles) =>\n\t\t\thandles\n\t\t\t\t.find((handle) => handle.name === containerName)\n\t\t\t\t?.ports?.find((port) => port.containerPort === CONTAINER_RPC_PORT),\n\t\t),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui fork mode: failed to inspect existing fork container: ${cause.reason}: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\n\nconst pickPublishedPort = (\n\trequested: ReadonlyArray<ContainerPortPublish>,\n\tactual: ReadonlyArray<ContainerPortPublish> | undefined,\n): ContainerPortPublish =>\n\tactual?.find((port) => port.containerPort === CONTAINER_RPC_PORT) ??\n\trequested.find((port) => port.containerPort === CONTAINER_RPC_PORT) ??\n\tportPublish(CONTAINER_RPC_PORT, DEFAULT_FORK_HOST_RPC_PORT);\n\nconst portPublish = (containerPort: number, hostPort: number): ContainerPortPublish => ({\n\tcontainerPort,\n\thostPort,\n\thostIp: DOCKER_PUBLISH_HOST,\n});\n\nexport const forkDataDirKey = (opts: SuiForkOptions): string =>\n\tcreateHash('sha256')\n\t\t.update(\n\t\t\tJSON.stringify({\n\t\t\t\tupstream: opts.upstream,\n\t\t\t\tcheckpoint: opts.checkpoint ?? null,\n\t\t\t\tversion: opts.version ?? DEFAULT_SUI_FORK_REV,\n\t\t\t\tseed: normalizeForkSeed(opts),\n\t\t\t}),\n\t\t)\n\t\t.digest('hex')\n\t\t.slice(0, 16);\n\nconst ensureForkDataDir = (\n\tpaths: StackPaths,\n\topts: SuiForkOptions,\n): Effect.Effect<string, SuiPluginError> => {\n\tconst dataDir = resolve(join(paths.stackRoot, 'sui-fork', forkDataDirKey(opts)));\n\treturn Effect.tryPromise({\n\t\ttry: async () => {\n\t\t\tawait mkdir(dataDir, { recursive: true, mode: 0o700 });\n\t\t\treturn dataDir;\n\t\t},\n\t\tcatch: (cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'fork-data-dir',\n\t\t\t\t`sui fork mode: failed to create data directory ${dataDir}: ${stringifyCause(cause)}`,\n\t\t\t\tcause,\n\t\t\t),\n\t});\n};\n\ninterface ForkStatus {\n\treadonly checkpoint: string;\n\treadonly clock: number;\n\treadonly forkedAtCheckpoint: string;\n}\n\nconst waitForForkReady = (\n\tsdkClient: SuiGrpcClient,\n\treadyTimeout: Duration.Duration,\n): Effect.Effect<ForkStatus, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tconst readyTimeoutMs = Duration.toMillis(readyTimeout);\n\t\tyield* waitForProbe({\n\t\t\tlabel: 'sui.fork.rpc',\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\tattemptTimeoutMs: PROBE_ATTEMPT_TIMEOUT_MS,\n\t\t\tprobe: () => readForkStatus(sdkClient).pipe(Effect.as(true)),\n\t\t}).pipe(\n\t\t\tEffect.mapError((cause) =>\n\t\t\t\tcause instanceof ProbeTimeoutError\n\t\t\t\t\t? suiPluginError(\n\t\t\t\t\t\t\t'fork-status-probe',\n\t\t\t\t\t\t\t`sui fork mode: ForkingService.GetStatus did not become ready within ${readyTimeoutMs}ms.`,\n\t\t\t\t\t\t\tcause.lastError ?? cause.lastNotReady ?? cause,\n\t\t\t\t\t\t)\n\t\t\t\t\t: suiPluginError(\n\t\t\t\t\t\t\t'fork-status-probe',\n\t\t\t\t\t\t\t`sui fork mode: ForkingService.GetStatus probe failed: ${stringifyCause(cause)}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\treturn yield* readForkStatus(sdkClient);\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.fork.waitForReady'));\n\nconst makeForkAdminSurface = (sdkClient: SuiGrpcClient): ForkAdminSurface => ({\n\tstatus: readForkStatus(sdkClient).pipe(\n\t\tEffect.map(({ checkpoint, clock }) => ({ checkpoint, clock })),\n\t),\n\tadvanceClock: (intervalMs) =>\n\t\tEffect.tryPromise({\n\t\t\ttry: () => sdkClient.forkingService.advanceClock({ durationMs: BigInt(intervalMs) }).response,\n\t\t\tcatch: (cause) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'fork-advance-clock',\n\t\t\t\t\t`sui fork mode: advanceClock(${intervalMs}) failed: ${stringifyCause(cause)}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t}).pipe(Effect.asVoid),\n\tadvanceCheckpoint: Effect.tryPromise({\n\t\ttry: () => sdkClient.forkingService.advanceCheckpoint({}).response,\n\t\tcatch: (cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'fork-advance-checkpoint',\n\t\t\t\t`sui fork mode: advanceCheckpoint failed: ${stringifyCause(cause)}`,\n\t\t\t\tcause,\n\t\t\t),\n\t}).pipe(Effect.asVoid),\n\timpersonate: (sender, tx) =>\n\t\tEffect.gen(function* () {\n\t\t\tif (!(tx instanceof Uint8Array)) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'fork-impersonate',\n\t\t\t\t\t\t`sui fork mode: impersonate(${sender}) expected serialized transaction bytes.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tyield* verifyForkImpersonationSender(sender, tx);\n\t\t\tconst raw = yield* Effect.tryPromise({\n\t\t\t\ttry: () =>\n\t\t\t\t\tsdkClient.executeTransaction({\n\t\t\t\t\t\ttransaction: tx,\n\t\t\t\t\t\tsignatures: [],\n\t\t\t\t\t\tinclude: { effects: true, objectTypes: true },\n\t\t\t\t\t}),\n\t\t\t\tcatch: (cause) =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'fork-impersonate',\n\t\t\t\t\t\t`sui fork mode: impersonate(${sender}) failed: ${stringifyCause(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t});\n\t\t\tconst digest = extractExecuteDigest(raw);\n\t\t\tif (digest === undefined) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'fork-impersonate',\n\t\t\t\t\t\t`sui fork mode: impersonate(${sender}) returned no transaction digest.`,\n\t\t\t\t\t\traw,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn { digest, success: !isFailedTransaction(raw), raw };\n\t\t}),\n});\n\nconst readForkStatus = (sdkClient: SuiGrpcClient): Effect.Effect<ForkStatus, SuiPluginError> =>\n\tEffect.tryPromise({\n\t\ttry: async () => {\n\t\t\tconst response = await sdkClient.forkingService.getStatus({}).response;\n\t\t\treturn {\n\t\t\t\tcheckpoint: response.checkpointSequenceNumber.toString(),\n\t\t\t\tclock: Number(response.timestampMs),\n\t\t\t\tforkedAtCheckpoint: response.forkedAtCheckpoint.toString(),\n\t\t\t};\n\t\t},\n\t\tcatch: (cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'fork-status-probe',\n\t\t\t\t`sui fork mode: GetStatus failed: ${stringifyCause(cause)}`,\n\t\t\t\tcause,\n\t\t\t),\n\t});\n\nconst routedSuiRpcUrl = (identity: Identity): Effect.Effect<string, SuiPluginError> =>\n\trouterHostname(identity, SUI_RPC_ENDPOINT_NAME).pipe(\n\t\tEffect.map((hostname) =>\n\t\t\trenderUrl({ protocol: 'http', hostname, port: SUI_RPC_ENTRYPOINT_PORT }),\n\t\t),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui fork mode: failed to construct router RPC URL: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\n\nconst extractExecuteDigest = (raw: unknown): string | undefined => {\n\tconst env = raw as {\n\t\treadonly $kind?: 'Transaction' | 'FailedTransaction';\n\t\treadonly Transaction?: { readonly digest?: string };\n\t\treadonly FailedTransaction?: { readonly digest?: string };\n\t};\n\treturn env.$kind === 'FailedTransaction'\n\t\t? env.FailedTransaction?.digest\n\t\t: env.Transaction?.digest;\n};\n\nconst isFailedTransaction = (raw: unknown): boolean =>\n\t(raw as { readonly $kind?: string }).$kind === 'FailedTransaction';\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":"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"}
1
+ {"version":3,"file":"fork.mjs","names":["sharedFetchChainId"],"sources":["../../../../src/plugins/sui/mode/fork.ts"],"sourcesContent":["// Sui plugin — fork mode.\n\nimport { createHash } from 'node:crypto';\nimport { mkdir } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\nimport { normalizeSuiAddress, normalizeSuiObjectId } from '@mysten/sui/utils';\n\nimport type {\n\tContainerHandle,\n\tContainerPortPublish,\n\tContainerRuntime,\n\tContainerRuntimeError,\n\tImageRef,\n\tPortBindingReconciliation,\n} from '../../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../../contracts/snapshotable.ts';\nimport type { Identity } from '../../../substrate/identity.ts';\nimport { ensureManagedContainer } from '../../../substrate/runtime/managed-container.ts';\nimport { SpanAttr } from '../../../substrate/runtime/observability/spans.ts';\nimport type { StackPaths } from '../../../substrate/runtime/paths.ts';\nimport type { AllocatedPort, PortBroker } from '../../../substrate/runtime/port-broker/index.ts';\nimport { ProbeTimeoutError, waitForProbe } from '../../../substrate/runtime/probes.ts';\nimport { formatUnknownError } from '../../../substrate/runtime/format-unknown-error.ts';\nimport { setCurrentPluginPhase } from '../../../substrate/runtime/current-plugin.ts';\nimport { renderUrl, routedHostname } from '../../../substrate/runtime/routed-url.ts';\nimport { extractExecuteDigest } from '../../../substrate/runtime/sui-execute/index.ts';\nimport { resolveAutoTickIntervalMs, runAutoTickClock } from '../auto-tick.ts';\nimport { suiPluginError, type SuiConfigError, type SuiPluginError } from '../errors.ts';\nimport type { ResolvedSuiNetwork } from '../network-resolver.ts';\nimport { SUI_RPC_ENDPOINT_NAME, SUI_RPC_ENTRYPOINT_PORT } from '../routable.ts';\nimport { SuiSpans } from '../spans.ts';\nimport { acquireForkDataDirHolder, wrapWithForkGuard } from '../fork-orchestration.ts';\nimport {\n\tFORK_IMPERSONATION_GAS_BUDGET,\n\tverifyForkImpersonationSender,\n} from '../fork-transaction.ts';\nimport { DEFAULT_SUI_CLI_VERSION } from '../../../substrate/runtime/sui-move-build/index.ts';\nimport type { ForkAdminSurface, SuiClient } from './shared.ts';\nimport { toDockerHostGatewayUrl } from './shared.ts';\nimport {\n\tassembleSuiClient,\n\tfetchChainId as sharedFetchChainId,\n\tmakeResolvedNetwork,\n\tnoopWaitForTransactionsReady,\n} from './shared-boot.ts';\nimport type { SuiForkOptions } from './spec.ts';\n\n/** Default ready-probe timeout for fork-mode cold start. */\nexport const DEFAULT_FORK_READY_TIMEOUT = Duration.seconds(180);\n\n/** Default Sui repository revision used by the bundled `sui-fork` image build. */\nexport const DEFAULT_SUI_FORK_REV = '62ee6ada958cd61b3c8a4466dd33c9aba3cdff8a';\n\n/** Published prebuilt `sui-fork` image to pull instead of compiling from\n * source. `undefined` until CI publishes one (e.g. `ghcr.io/mysten/sui-fork:<rev>`);\n * overridable per-run via `DEVSTACK_SUI_FORK_IMAGE`. When set and the\n * runtime can pull, `resolveForkImage` tries it first and falls back to a\n * source build, sparing users the ~10-minute cold compile. */\nexport const DEFAULT_FORK_IMAGE_REF: string | undefined = undefined;\n\n/** Env var that overrides {@link DEFAULT_FORK_IMAGE_REF} for a single run. */\nexport const FORK_IMAGE_ENV_VAR = 'DEVSTACK_SUI_FORK_IMAGE';\n\nconst prebuiltForkImageRef = (): string | undefined => {\n\tconst fromEnv = process.env[FORK_IMAGE_ENV_VAR]?.trim();\n\treturn fromEnv !== undefined && fromEnv.length > 0 ? fromEnv : DEFAULT_FORK_IMAGE_REF;\n};\n\n/** Map upstream literal to the canonical \"live\" chain id known by wallet-standard / MVR. */\nexport const FORK_UPSTREAM_TO_KNOWN_NETWORK = {\n\tmainnet: 'sui:mainnet',\n\ttestnet: 'sui:testnet',\n\tdevnet: 'sui:devnet',\n} as const;\n\nexport const DEFAULT_FORK_HOST_RPC_PORT = 51002;\nexport const FORK_VALIDATOR_STOP_GRACE_SECONDS = 30;\n\n/** Default impersonation \"whale\" per upstream — a large-reserve address\n * known to hold a big single SUI coin in the upstream's state, used as\n * the fork faucet funding source when `faucet.whale` is omitted. `null`\n * means no default is known (the faucet then requires an explicit\n * `faucet.whale`). Validated at boot via `selectSufficientForkCoin`. */\nexport const FORK_DEFAULT_WHALE: Record<'mainnet' | 'testnet' | 'devnet', string | null> = {\n\t// Long-lived validator addresses each holding a large single SUI coin\n\t// (validated 2026-05-28). `selectSufficientForkCoin` re-queries the address\n\t// at the fork checkpoint at runtime, so a rotated coin self-heals; a\n\t// drained/retired address degrades gracefully — boot validation warns and\n\t// disables the default faucet. Override any of these with `faucet.whale`.\n\tmainnet: '0xbc7e7537564bd939b62e5b24477ac00ba8cef33ccec72d63090a080a1253b725', // ~273k SUI\n\ttestnet: '0xc397477d8b445e6295bc34e593b9a95d5d233cec1a8fe3740d0ab86012a460f6', // ~127k SUI\n\t// devnet resets periodically; this genesis validator may go stale after a\n\t// reset, at which point the default faucet disables itself until a\n\t// `faucet.whale` is supplied.\n\tdevnet: '0x4296747d0bd91c41b668702bdca0bf769a0e32db66982d986101e7975db55cbe', // ~30M SUI\n};\n\n/** The common per-account fund the fork faucet must be able to cover. Mirrors\n * the account plugin's `DEFAULT_EPHEMERAL_FUND_MIST` (1 SUI) — kept local\n * because account → sui already, so importing it here would cycle; a test\n * pins the two together. */\nexport const FORK_FAUCET_DEFAULT_FUND_MIST = 1_000_000_000n;\n\n/** Floor a single whale SUI coin must clear at boot to enable the fork faucet:\n * a default ephemeral fund (1 SUI) plus the impersonation gas budget. Set to\n * match the per-request requirement for the default fund so a whale that\n * passes boot can actually satisfy the first auto-fund. */\nexport const FORK_FAUCET_WHALE_MIN_COIN_MIST =\n\tFORK_FAUCET_DEFAULT_FUND_MIST + FORK_IMPERSONATION_GAS_BUDGET;\n\n/** Default per-request funding cap (MIST) — 1000 SUI. */\nexport const DEFAULT_FORK_FAUCET_PER_REQUEST_CAP_MIST = 1_000_000_000_000n;\n\n/** Resolved fork faucet funding source. */\nexport interface ResolvedForkWhale {\n\treadonly whale: string;\n\treadonly perRequestCapMist: bigint;\n\t/** `true` when the user set `faucet.whale` explicitly — a validation\n\t * failure then hard-fails boot; a default whale only warns + disables\n\t * the faucet so the fork still boots. */\n\treadonly explicit: boolean;\n}\n\n/** Resolve the fork faucet whale from options + per-upstream defaults,\n * or `null` when the faucet is disabled / no whale is known. */\nexport const resolveForkWhale = (opts: SuiForkOptions): ResolvedForkWhale | null => {\n\tif (opts.faucet?.enabled === false) {\n\t\treturn null;\n\t}\n\tconst perRequestCapMist =\n\t\topts.faucet?.perRequestCapMist ?? DEFAULT_FORK_FAUCET_PER_REQUEST_CAP_MIST;\n\tconst explicit = opts.faucet?.whale?.trim();\n\tif (explicit !== undefined && explicit.length > 0) {\n\t\treturn { whale: normalizeSuiAddress(explicit), perRequestCapMist, explicit: true };\n\t}\n\tconst fallback = FORK_DEFAULT_WHALE[opts.upstream];\n\treturn fallback === null\n\t\t? null\n\t\t: { whale: normalizeSuiAddress(fallback), perRequestCapMist, explicit: false };\n};\n\n/** Inject the resolved faucet whale into the fork seed so its coins exist\n * in fork state. MUST run before the data-dir key / container config\n * hash are computed (both fold the seed) so enabling the faucet doesn't\n * silently reuse a whale-less fork data dir. */\nexport const withForkFaucetSeed = (opts: SuiForkOptions): SuiForkOptions => {\n\tconst resolved = resolveForkWhale(opts);\n\tif (resolved === null) {\n\t\treturn opts;\n\t}\n\treturn {\n\t\t...opts,\n\t\tseed: {\n\t\t\t...(opts.seed ?? {}),\n\t\t\taddresses: [...(opts.seed?.addresses ?? []), resolved.whale],\n\t\t},\n\t};\n};\n\nconst DOCKER_PUBLISH_HOST = '0.0.0.0' as const;\nconst CONTAINER_RPC_PORT = SUI_RPC_ENTRYPOINT_PORT;\nconst FORK_CONTAINER_DATA_DIR = '/var/lib/sui-fork';\nconst PROBE_ATTEMPT_TIMEOUT_MS = 3_000;\n\n/** Resolved fork-mode boot artifacts. */\nexport interface ForkModeBootResult {\n\treadonly resolved: ResolvedSuiNetwork;\n\treadonly client: SuiClient;\n\treadonly autoTickIntervalMs: number | undefined;\n}\n\nexport const bootForkMode = (\n\truntime: ContainerRuntime,\n\tidentity: Identity,\n\tportBroker: PortBroker,\n\tpaths: StackPaths,\n\topts: SuiForkOptions,\n): Effect.Effect<ForkModeBootResult, SuiPluginError | SuiConfigError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst autoTickIntervalMs = yield* resolveAutoTickIntervalMs(opts.autoTick);\n\t\t// Fold the faucet whale into the seed BEFORE the data-dir key /\n\t\t// container config hash are derived, so enabling the faucet keys a\n\t\t// distinct fork state rather than reusing a whale-less data dir.\n\t\tconst seededOpts = withForkFaucetSeed(opts);\n\t\tconst image = yield* resolveForkImage(runtime, identity, opts);\n\t\tconst dataDir = yield* ensureForkDataDir(paths, seededOpts);\n\n\t\tconst labels: ContainerLabelTuple = {\n\t\t\tapp: identity.app,\n\t\t\tstack: identity.stack,\n\t\t\tplugin: 'sui',\n\t\t\trole: 'fork-validator',\n\t\t};\n\t\tconst containerName = `devstack-${identity.app}-${identity.stack}-sui-fork`;\n\t\tconst { handle, ports } = yield* ensureForkContainer({\n\t\t\truntime,\n\t\t\tportBroker,\n\t\t\timage,\n\t\t\tlabels,\n\t\t\tcontainerName,\n\t\t\tdataDir,\n\t\t\topts: seededOpts,\n\t\t});\n\n\t\tconst published = pickPublishedPort(ports, handle.ports);\n\t\tconst directRpcUrl = `http://127.0.0.1:${published.hostPort}`;\n\t\tconst rpcUrl = yield* routedSuiRpcUrl(identity);\n\t\tconst sdkClient = new SuiGrpcClient({ baseUrl: directRpcUrl, network: opts.upstream });\n\t\tconst readyTimeout = opts.readyTimeout ?? DEFAULT_FORK_READY_TIMEOUT;\n\n\t\tconst status = yield* waitForForkReady(sdkClient, readyTimeout).pipe(\n\t\t\tEffect.annotateLogs({ [SuiSpans.container]: handle.name }),\n\t\t);\n\t\tconst chain = yield* sharedFetchChainId(sdkClient, {\n\t\t\tspan: 'devstack.plugin.sui.fork.fetchChainId',\n\t\t});\n\n\t\tconst fork = makeForkAdminSurface(sdkClient);\n\t\tconst assembled = yield* assembleSuiClient({\n\t\t\tsdkClient,\n\t\t\tchain,\n\t\t\trpcUrl,\n\t\t\twaitForTransactionsReady: noopWaitForTransactionsReady,\n\t\t\tbuildImage: image,\n\t\t\thostGateway: {\n\t\t\t\trpcUrl: toDockerHostGatewayUrl(directRpcUrl),\n\t\t\t\tfaucetUrl: null,\n\t\t\t\tgraphqlUrl: null,\n\t\t\t},\n\t\t});\n\t\tconst client: SuiClient = {\n\t\t\t...assembled.client,\n\t\t\tsdk: wrapWithForkGuard(assembled.sdkShim),\n\t\t\tfork,\n\t\t};\n\n\t\tif (autoTickIntervalMs !== undefined) {\n\t\t\tyield* runAutoTickClock(fork, autoTickIntervalMs);\n\t\t}\n\n\t\treturn {\n\t\t\tresolved: makeResolvedNetwork({\n\t\t\t\tmode: 'fork',\n\t\t\t\tchain,\n\t\t\t\trpc: rpcUrl,\n\t\t\t\tsource: 'default',\n\t\t\t\tcheckpoint: status.forkedAtCheckpoint,\n\t\t\t\tforkUpstream: opts.upstream,\n\t\t\t}),\n\t\t\tclient,\n\t\t\tautoTickIntervalMs,\n\t\t};\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.sui.fork.boot', { attributes: { [SpanAttr.plugin]: 'sui' } }),\n\t);\n\nexport const suiForkImageBuildContext = (rev = DEFAULT_SUI_FORK_REV) => ({\n\t// `fileURLToPath` normalises the URL → host-path conversion across\n\t// platforms (Windows `file:///C:/...` → `C:\\...`). Reading\n\t// `.pathname` directly leaves the leading `/` on Windows drive paths.\n\tcontextPath: fileURLToPath(new URL('../../../../images/', import.meta.url)),\n\tdockerfile: 'sui-fork/Dockerfile',\n\tbuildArgs: { SUI_FORK_REV: rev, SUI_CLI_VERSION: DEFAULT_SUI_CLI_VERSION },\n});\n\n/** Pull a prebuilt fork image, narrating progress on the supervisor row.\n * Fails with a `SuiPluginError` if the runtime can't pull or the pull errors. */\nconst pullForkImage = (\n\truntime: ContainerRuntime,\n\tpullRef: string,\n): Effect.Effect<ImageRef, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tif (runtime.pullImage === undefined) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'image-build',\n\t\t\t\t\t`sui fork mode cannot pull image '${pullRef}' because the configured container runtime does not expose image pulls.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tyield* setCurrentPluginPhase(`pulling sui-fork image ${pullRef}…`);\n\t\treturn yield* runtime.pullImage(pullRef).pipe(\n\t\t\tEffect.mapError((cause) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'image-build',\n\t\t\t\t\t`sui fork mode failed to pull image '${pullRef}': ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.ensuring(setCurrentPluginPhase(null)),\n\t\t);\n\t});\n\n/** Build the bundled `sui-fork` image from source, narrating the cold\n * compile so the row doesn't look hung for ~10 minutes on first run. */\nconst buildForkImage = (\n\truntime: ContainerRuntime,\n\tbuildCtx: Parameters<ContainerRuntime['ensureImage']>[0],\n): Effect.Effect<ImageRef, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tyield* setCurrentPluginPhase(\n\t\t\t'building sui-fork image — first run compiles sui-fork from source (~10+ min); cached after',\n\t\t);\n\t\treturn yield* runtime.ensureImage(buildCtx).pipe(\n\t\t\tEffect.mapError((cause) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'image-build',\n\t\t\t\t\t`sui fork image build failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.ensuring(setCurrentPluginPhase(null)),\n\t\t);\n\t});\n\nexport const resolveForkImage = (\n\truntime: ContainerRuntime,\n\tidentity: Identity,\n\topts: SuiForkOptions,\n): Effect.Effect<ImageRef, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\t// Explicit image override always wins.\n\t\tif (opts.image && 'pull' in opts.image) {\n\t\t\treturn yield* pullForkImage(runtime, opts.image.pull);\n\t\t}\n\t\tconst rev = opts.version ?? DEFAULT_SUI_FORK_REV;\n\t\tconst owner = {\n\t\t\tapp: identity.app,\n\t\t\tstack: identity.stack,\n\t\t\tplugin: 'sui',\n\t\t\trole: 'validator',\n\t\t} as const;\n\t\tif (opts.image && 'build' in opts.image) {\n\t\t\treturn yield* buildForkImage(runtime, {\n\t\t\t\tcontextPath: opts.image.build.context,\n\t\t\t\tdockerfile: opts.image.build.dockerfile ?? 'Dockerfile',\n\t\t\t\tbuildArgs: { SUI_FORK_REV: rev, SUI_CLI_VERSION: DEFAULT_SUI_CLI_VERSION },\n\t\t\t\towner,\n\t\t\t});\n\t\t}\n\t\t// No explicit image: prefer a prebuilt ref (env / published default) to\n\t\t// skip the cold source compile, falling back to building on any miss.\n\t\tconst prebuilt = prebuiltForkImageRef();\n\t\tif (prebuilt !== undefined && runtime.pullImage !== undefined) {\n\t\t\treturn yield* pullForkImage(runtime, prebuilt).pipe(\n\t\t\t\tEffect.catchTag('SuiPluginError', (cause) =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t\t`sui fork mode: prebuilt image '${prebuilt}' unavailable (${cause.message}); building from source.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn yield* buildForkImage(runtime, { ...suiForkImageBuildContext(rev), owner });\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn yield* buildForkImage(runtime, { ...suiForkImageBuildContext(rev), owner });\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.fork.resolveImage'));\n\ninterface ForkContainerResult {\n\treadonly handle: ContainerHandle;\n\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n}\n\nconst ensureForkContainer = (params: {\n\treadonly runtime: ContainerRuntime;\n\treadonly portBroker: PortBroker;\n\treadonly image: ImageRef;\n\treadonly labels: ContainerLabelTuple;\n\treadonly containerName: string;\n\treadonly dataDir: string;\n\treadonly opts: SuiForkOptions;\n}): Effect.Effect<ForkContainerResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst reusable =\n\t\t\tparams.opts.ports === undefined\n\t\t\t\t? yield* findReusableForkPort(params.runtime, params.labels, params.containerName)\n\t\t\t\t: undefined;\n\t\tconst ports =\n\t\t\treusable === undefined\n\t\t\t\t? [yield* allocateForkRpcPort(params.portBroker, params.opts.ports)]\n\t\t\t\t: [reusable];\n\t\tconst reconciliation: PortBindingReconciliation =\n\t\t\treusable === undefined && params.opts.ports !== undefined ? 'exact' : 'adopt-existing';\n\t\tconst command = forkStartCommand(params.opts);\n\t\tconst handle = yield* ensureManagedContainer({\n\t\t\truntime: params.runtime,\n\t\t\tlabels: params.labels,\n\t\t\tspec: {\n\t\t\t\tname: params.containerName,\n\t\t\t\timage: params.image,\n\t\t\t\trecreate: 'on-config-change',\n\t\t\t\tconfigHash: forkContainerConfigHash(params.opts, params.dataDir, command),\n\t\t\t\tstopGraceSeconds: FORK_VALIDATOR_STOP_GRACE_SECONDS,\n\t\t\t\tports,\n\t\t\t\tportBindingReconciliation: reconciliation,\n\t\t\t\tmounts: [{ source: params.dataDir, target: FORK_CONTAINER_DATA_DIR }],\n\t\t\t\tcommand,\n\t\t\t},\n\t\t\tmapError: (cause) => cause,\n\t\t}).pipe(\n\t\t\tEffect.mapError((cause: ContainerRuntimeError) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'container-start',\n\t\t\t\t\t`sui-fork container failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\treturn { handle, ports };\n\t});\n\nexport const forkStartCommand = (opts: SuiForkOptions): ReadonlyArray<string> => {\n\tconst seed = normalizeForkSeed(opts);\n\tconst command = [\n\t\t'start',\n\t\t'--network',\n\t\topts.upstream,\n\t\t'--data-dir',\n\t\tFORK_CONTAINER_DATA_DIR,\n\t\t'--rpc-addr',\n\t\t`0.0.0.0:${CONTAINER_RPC_PORT}`,\n\t];\n\tif (opts.checkpoint !== undefined) {\n\t\tcommand.push('--checkpoint', String(opts.checkpoint));\n\t}\n\tfor (const address of seed.addresses) {\n\t\tcommand.push('--address', address);\n\t}\n\tfor (const objectId of seed.objects) {\n\t\tcommand.push('--object', objectId);\n\t}\n\treturn command;\n};\n\nconst normalizeForkSeed = (opts: SuiForkOptions) => ({\n\taddresses: [\n\t\t...new Set((opts.seed?.addresses ?? []).map((address) => normalizeSuiAddress(address))),\n\t].sort(),\n\tobjects: [\n\t\t...new Set((opts.seed?.objects ?? []).map((objectId) => normalizeSuiObjectId(objectId))),\n\t].sort(),\n});\n\nconst forkContainerConfigHash = (\n\topts: SuiForkOptions,\n\tdataDir: string,\n\tcommand: ReadonlyArray<string>,\n): string =>\n\tcreateHash('sha256')\n\t\t.update(\n\t\t\tJSON.stringify({\n\t\t\t\tdataDir,\n\t\t\t\tcommand,\n\t\t\t\tversion: opts.version ?? DEFAULT_SUI_FORK_REV,\n\t\t\t\tports: opts.ports ?? null,\n\t\t\t}),\n\t\t)\n\t\t.digest('hex');\n\nconst allocateForkRpcPort = (\n\tportBroker: PortBroker,\n\toverride: Readonly<Record<number, number>> | undefined,\n): Effect.Effect<ContainerPortPublish, SuiPluginError, Scope.Scope> => {\n\tconst overridePort = override?.[CONTAINER_RPC_PORT];\n\tif (overridePort !== undefined) {\n\t\treturn Effect.succeed(portPublish(CONTAINER_RPC_PORT, overridePort));\n\t}\n\treturn portBroker\n\t\t.allocate({\n\t\t\towner: 'sui:fork-rpc',\n\t\t\tpreferredPort: DEFAULT_FORK_HOST_RPC_PORT,\n\t\t\tprobeHost: DOCKER_PUBLISH_HOST,\n\t\t})\n\t\t.pipe(\n\t\t\tEffect.catchTag('PortBrokerError', (cause) =>\n\t\t\t\tcause.reason === 'preferred-busy'\n\t\t\t\t\t? portBroker.allocate({ owner: 'sui:fork-rpc', probeHost: DOCKER_PUBLISH_HOST })\n\t\t\t\t\t: Effect.fail(cause),\n\t\t\t),\n\t\t\tEffect.map((allocated: AllocatedPort) => portPublish(CONTAINER_RPC_PORT, allocated.port)),\n\t\t\tEffect.mapError((cause) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'port-allocate',\n\t\t\t\t\t`sui fork mode: failed to allocate RPC host port: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n};\n\nconst findReusableForkPort = (\n\truntime: ContainerRuntime,\n\tlabels: ContainerLabelTuple,\n\tcontainerName: string,\n): Effect.Effect<ContainerPortPublish | undefined, SuiPluginError> =>\n\truntime.inspectByLabels(labels).pipe(\n\t\tEffect.map((handles) =>\n\t\t\thandles\n\t\t\t\t.find((handle) => handle.name === containerName)\n\t\t\t\t?.ports?.find((port) => port.containerPort === CONTAINER_RPC_PORT),\n\t\t),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui fork mode: failed to inspect existing fork container: ${cause.reason}: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\n\nconst pickPublishedPort = (\n\trequested: ReadonlyArray<ContainerPortPublish>,\n\tactual: ReadonlyArray<ContainerPortPublish> | undefined,\n): ContainerPortPublish =>\n\tactual?.find((port) => port.containerPort === CONTAINER_RPC_PORT) ??\n\trequested.find((port) => port.containerPort === CONTAINER_RPC_PORT) ??\n\tportPublish(CONTAINER_RPC_PORT, DEFAULT_FORK_HOST_RPC_PORT);\n\nconst portPublish = (containerPort: number, hostPort: number): ContainerPortPublish => ({\n\tcontainerPort,\n\thostPort,\n\thostIp: DOCKER_PUBLISH_HOST,\n});\n\nexport const forkDataDirKey = (opts: SuiForkOptions): string =>\n\tcreateHash('sha256')\n\t\t.update(\n\t\t\tJSON.stringify({\n\t\t\t\tupstream: opts.upstream,\n\t\t\t\tcheckpoint: opts.checkpoint ?? null,\n\t\t\t\tversion: opts.version ?? DEFAULT_SUI_FORK_REV,\n\t\t\t\tseed: normalizeForkSeed(opts),\n\t\t\t}),\n\t\t)\n\t\t.digest('hex')\n\t\t.slice(0, 16);\n\n/** Bring the data dir into being and claim it against concurrent\n * stacks via the holder protocol. The holder claim is scope-bound —\n * it heartbeats for the stack's lifetime and releases on teardown. */\nconst ensureForkDataDir = (\n\tpaths: StackPaths,\n\topts: SuiForkOptions,\n): Effect.Effect<string, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst dataDir = resolve(join(paths.stackRoot, 'sui-fork', forkDataDirKey(opts)));\n\t\tyield* Effect.tryPromise({\n\t\t\ttry: () => mkdir(dataDir, { recursive: true, mode: 0o700 }),\n\t\t\tcatch: (cause) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'fork-data-dir',\n\t\t\t\t\t`sui fork mode: failed to create data directory ${dataDir}: ${formatUnknownError(cause)}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t});\n\t\tyield* acquireForkDataDirHolder(paths.stackLockFile, dataDir);\n\t\treturn dataDir;\n\t});\n\ninterface ForkStatus {\n\treadonly checkpoint: string;\n\treadonly clock: number;\n\treadonly forkedAtCheckpoint: string;\n}\n\nconst waitForForkReady = (\n\tsdkClient: SuiGrpcClient,\n\treadyTimeout: Duration.Duration,\n): Effect.Effect<ForkStatus, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tconst readyTimeoutMs = Duration.toMillis(readyTimeout);\n\t\tyield* waitForProbe({\n\t\t\tlabel: 'sui.fork.rpc',\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\tattemptTimeoutMs: PROBE_ATTEMPT_TIMEOUT_MS,\n\t\t\tprobe: () => readForkStatus(sdkClient).pipe(Effect.as(true)),\n\t\t}).pipe(\n\t\t\tEffect.mapError((cause) =>\n\t\t\t\tcause instanceof ProbeTimeoutError\n\t\t\t\t\t? suiPluginError(\n\t\t\t\t\t\t\t'fork-status-probe',\n\t\t\t\t\t\t\t`sui fork mode: ForkingService.GetStatus did not become ready within ${readyTimeoutMs}ms. ` +\n\t\t\t\t\t\t\t\t`Inspect the sui-fork container logs (\\`docker logs\\`); if the image is still ` +\n\t\t\t\t\t\t\t\t`building or the upstream checkpoint is large, raise the \\`readyTimeout\\` option.`,\n\t\t\t\t\t\t\tcause.lastError ?? cause.lastNotReady ?? cause,\n\t\t\t\t\t\t)\n\t\t\t\t\t: suiPluginError(\n\t\t\t\t\t\t\t'fork-status-probe',\n\t\t\t\t\t\t\t`sui fork mode: ForkingService.GetStatus probe failed: ${formatUnknownError(cause)}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\treturn yield* readForkStatus(sdkClient);\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.fork.waitForReady'));\n\nconst makeForkAdminSurface = (sdkClient: SuiGrpcClient): ForkAdminSurface => ({\n\tstatus: readForkStatus(sdkClient).pipe(\n\t\tEffect.map(({ checkpoint, clock }) => ({ checkpoint, clock })),\n\t),\n\tadvanceClock: (intervalMs) =>\n\t\tEffect.tryPromise({\n\t\t\ttry: () => sdkClient.forkingService.advanceClock({ durationMs: BigInt(intervalMs) }).response,\n\t\t\tcatch: (cause) =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'fork-advance-clock',\n\t\t\t\t\t`sui fork mode: advanceClock(${intervalMs}) failed: ${formatUnknownError(cause)}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t}).pipe(Effect.asVoid),\n\tadvanceCheckpoint: Effect.tryPromise({\n\t\ttry: () => sdkClient.forkingService.advanceCheckpoint({}).response,\n\t\tcatch: (cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'fork-advance-checkpoint',\n\t\t\t\t`sui fork mode: advanceCheckpoint failed: ${formatUnknownError(cause)}`,\n\t\t\t\tcause,\n\t\t\t),\n\t}).pipe(Effect.asVoid),\n\timpersonate: (sender, tx) =>\n\t\tEffect.gen(function* () {\n\t\t\tif (!(tx instanceof Uint8Array)) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'fork-impersonate',\n\t\t\t\t\t\t`sui fork mode: impersonate(${sender}) expected serialized transaction bytes.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tyield* verifyForkImpersonationSender(sender, tx);\n\t\t\tconst raw = yield* Effect.tryPromise({\n\t\t\t\ttry: () =>\n\t\t\t\t\tsdkClient.core.executeTransaction({\n\t\t\t\t\t\ttransaction: tx,\n\t\t\t\t\t\tsignatures: [],\n\t\t\t\t\t\tinclude: { effects: true, objectTypes: true },\n\t\t\t\t\t}),\n\t\t\t\tcatch: (cause) =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'fork-impersonate',\n\t\t\t\t\t\t`sui fork mode: impersonate(${sender}) failed: ${formatUnknownError(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t});\n\t\t\tconst digest = extractExecuteDigest(raw);\n\t\t\tif (digest === undefined) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'fork-impersonate',\n\t\t\t\t\t\t`sui fork mode: impersonate(${sender}) returned no transaction digest.`,\n\t\t\t\t\t\traw,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn { digest, success: !isFailedTransaction(raw), raw };\n\t\t}),\n});\n\nconst readForkStatus = (sdkClient: SuiGrpcClient): Effect.Effect<ForkStatus, SuiPluginError> =>\n\tEffect.tryPromise({\n\t\ttry: async () => {\n\t\t\tconst response = await sdkClient.forkingService.getStatus({}).response;\n\t\t\treturn {\n\t\t\t\tcheckpoint: response.checkpointSequenceNumber.toString(),\n\t\t\t\tclock: Number(response.timestampMs),\n\t\t\t\tforkedAtCheckpoint: response.forkedAtCheckpoint.toString(),\n\t\t\t};\n\t\t},\n\t\tcatch: (cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'fork-status-probe',\n\t\t\t\t`sui fork mode: GetStatus failed: ${formatUnknownError(cause)}`,\n\t\t\t\tcause,\n\t\t\t),\n\t});\n\nconst routedSuiRpcUrl = (identity: Identity): Effect.Effect<string, SuiPluginError> =>\n\troutedHostname(identity, SUI_RPC_ENDPOINT_NAME).pipe(\n\t\tEffect.map((hostname) =>\n\t\t\trenderUrl({ protocol: 'http', hostname, port: SUI_RPC_ENTRYPOINT_PORT }),\n\t\t),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui fork mode: failed to construct router RPC URL: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\n\nconst isFailedTransaction = (raw: unknown): boolean =>\n\t(raw as { readonly $kind?: string }).$kind === 'FailedTransaction';\n"],"mappings":"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"}
@@ -1,4 +1,7 @@
1
+ import { SpanAttr } from "../../../substrate/runtime/observability/spans.mjs";
1
2
  import { suiPluginError } from "../errors.mjs";
3
+ import { formatUnknownError } from "../../../substrate/runtime/format-unknown-error.mjs";
4
+ import { SuiSpans } from "../spans.mjs";
2
5
  import { assembleSuiClient, buildWaitForTransactionsReady, fetchChainId, makeResolvedNetwork, noopWaitForTransactionsReady } from "./shared-boot.mjs";
3
6
  import { Duration, Effect } from "effect";
4
7
  import { SuiGrpcClient } from "@mysten/sui/grpc";
@@ -49,23 +52,23 @@ const resolveEndpoints = (opts) => {
49
52
  const bootLiveMode = (opts) => Effect.gen(function* () {
50
53
  const endpoints = yield* resolveEndpoints(opts);
51
54
  yield* Effect.annotateCurrentSpan({
52
- "sui.live.network": opts.network,
53
- "sui.live.rpcUrl": endpoints.rpcUrl,
54
- "sui.live.faucetUrl": endpoints.faucetUrl ?? "<none>"
55
+ [SuiSpans.liveNetwork]: opts.network,
56
+ [SuiSpans.liveRpcUrl]: endpoints.rpcUrl,
57
+ ...endpoints.faucetUrl !== void 0 ? { [SuiSpans.liveFaucetUrl]: endpoints.faucetUrl } : {}
55
58
  });
56
59
  const sdkClient = yield* Effect.try({
57
60
  try: () => new SuiGrpcClient({
58
61
  baseUrl: endpoints.rpcUrl,
59
62
  network: endpoints.sdkNetwork
60
63
  }),
61
- catch: (cause) => suiPluginError("chain-id-fetch", `sui live mode: SuiGrpcClient construction failed for rpcUrl=${endpoints.rpcUrl}: ${stringifyCause(cause)}`, cause)
64
+ catch: (cause) => suiPluginError("chain-id-fetch", `sui live mode: SuiGrpcClient construction failed for rpcUrl=${endpoints.rpcUrl}: ${formatUnknownError(cause)}`, cause)
62
65
  });
63
66
  const chain = opts.chain ?? (yield* fetchChainId(sdkClient, {
64
67
  timeout: opts.readyTimeout ?? DEFAULT_LIVE_CHAIN_ID_TIMEOUT,
65
68
  span: "devstack.plugin.sui.live.fetchChainId"
66
69
  }));
67
70
  const waitForTransactionsReady = endpoints.faucetUrl !== void 0 ? yield* buildWaitForTransactionsReady(endpoints.faucetUrl) : noopWaitForTransactionsReady;
68
- const { client } = assembleSuiClient({
71
+ const { client } = yield* assembleSuiClient({
69
72
  sdkClient,
70
73
  chain,
71
74
  rpcUrl: endpoints.rpcUrl,
@@ -85,18 +88,9 @@ const bootLiveMode = (opts) => Effect.gen(function* () {
85
88
  client
86
89
  };
87
90
  }).pipe(Effect.withSpan("devstack.plugin.sui.live.boot", { attributes: {
88
- "devstack.plugin": "sui",
89
- "sui.mode": "live"
91
+ [SpanAttr.plugin]: "sui",
92
+ [SuiSpans.mode]: "live"
90
93
  } }));
91
- const stringifyCause = (cause) => {
92
- if (cause instanceof Error) return cause.message;
93
- if (typeof cause === "string") return cause;
94
- try {
95
- return JSON.stringify(cause);
96
- } catch {
97
- return String(cause);
98
- }
99
- };
100
94
  //#endregion
101
95
  export { bootLiveMode };
102
96
 
@@ -1 +1 @@
1
- {"version":3,"file":"live.mjs","names":[],"sources":["../../../../src/plugins/sui/mode/live.ts"],"sourcesContent":["// Sui plugin — live mode (testnet / mainnet / devnet / custom).\n//\n// Wraps a public or caller-provided Sui RPC. Testnet has a faucet;\n// mainnet has none; custom may or may not.\n//\n// What's hard:\n// - No ready probe is meaningful (the public chain is always\n// up); chain-id fetch IS the only sentinel with a bounded\n// timeout.\n// - Faucet-less networks (mainnet) need a \"no-op\" funds-ready\n// gate so downstream callers don't have to branch.\n// - The KnownPackage substrate contributions are wired here so\n// wallet-standard / MVR / known-deployment lookups find the\n// right published ids.\n//\n// Live mode contributes a `NetworkResolver`, a `ChainProbe`, and a\n// `Codegenable` — but NO managed container, NO `Routable`, and the\n// build container is forced to the host CLI path (no in-stack\n// build image). The latter is flagged in the distilled-doc Open\n// questions as a candidate to revisit.\n//\n// Boot sequence:\n//\n// 1. Resolve `rpcUrl` / `faucetUrl` / `graphqlUrl` from caller\n// overrides, then fall back to `LIVE_DEFAULTS` for known nets.\n// `custom` requires `rpcUrl` — surface a typed refusal if\n// omitted.\n// 2. Construct `SuiGrpcClient` against the resolved URL with the\n// matching `network:` discriminator (so MVR / wallet-standard\n// hints route correctly).\n// 3. Fetch chain id (the only readiness sentinel for live).\n// 4. Build `waitForTransactionsReady`:\n// - mainnet: trivially-succeeding no-op (no faucet exists).\n// - testnet/devnet/custom-with-faucet: real HTTP probe.\n// - custom-without-faucet: no-op.\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\n\nimport { suiPluginError, type SuiPluginError } from '../errors.ts';\nimport type { ResolvedSuiNetwork } from '../network-resolver.ts';\nimport type { SuiClient } from './shared.ts';\nimport {\n\tassembleSuiClient,\n\tbuildWaitForTransactionsReady,\n\tfetchChainId,\n\tmakeResolvedNetwork,\n\tnoopWaitForTransactionsReady,\n} from './shared-boot.ts';\nimport type { SuiLiveOptions } from './spec.ts';\n\n/** Default chain-id fetch timeout for live RPCs. */\nexport const DEFAULT_LIVE_CHAIN_ID_TIMEOUT = Duration.seconds(30);\n\n/** Default RPC endpoints per known network. `custom` requires the\n * caller to supply `rpcUrl`. */\nexport const LIVE_DEFAULTS = {\n\ttestnet: {\n\t\trpcUrl: 'https://fullnode.testnet.sui.io:443',\n\t\tfaucetUrl: 'https://faucet.testnet.sui.io',\n\t\tgraphqlUrl: 'https://sui-testnet.mystenlabs.com/graphql',\n\t},\n\tmainnet: {\n\t\trpcUrl: 'https://fullnode.mainnet.sui.io:443',\n\t\tfaucetUrl: undefined as string | undefined,\n\t\tgraphqlUrl: 'https://sui-mainnet.mystenlabs.com/graphql',\n\t},\n\tdevnet: {\n\t\trpcUrl: 'https://fullnode.devnet.sui.io:443',\n\t\tfaucetUrl: 'https://faucet.devnet.sui.io',\n\t\tgraphqlUrl: undefined as string | undefined,\n\t},\n} as const;\n\n/** Resolved live-mode boot artifacts. */\nexport interface LiveModeBootResult {\n\treadonly resolved: ResolvedSuiNetwork;\n\treadonly client: SuiClient;\n}\n\ninterface ResolvedLiveEndpoints {\n\treadonly rpcUrl: string;\n\treadonly faucetUrl: string | undefined;\n\treadonly graphqlUrl: string | undefined;\n\treadonly sdkNetwork: 'mainnet' | 'testnet' | 'devnet' | 'localnet';\n}\n\n/** Resolve endpoints from caller overrides + the known-network table.\n * Order: caller-provided wins; otherwise the LIVE_DEFAULTS row for\n * the requested network. `custom` MUST carry an explicit `rpcUrl`. */\nconst resolveEndpoints = (\n\topts: SuiLiveOptions,\n): Effect.Effect<ResolvedLiveEndpoints, SuiPluginError> => {\n\tif (opts.network === 'custom') {\n\t\tif (opts.rpcUrl === undefined) {\n\t\t\treturn Effect.fail(\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'chain-id-fetch',\n\t\t\t\t\t`sui live mode: network='custom' requires opts.rpcUrl. ` +\n\t\t\t\t\t\t`Use suiFor(network).live.custom({rpcUrl: ...}) or pass network='testnet'|'mainnet'|'devnet' to use the built-in defaults.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn Effect.succeed({\n\t\t\trpcUrl: opts.rpcUrl,\n\t\t\tfaucetUrl: opts.faucetUrl,\n\t\t\tgraphqlUrl: opts.graphqlUrl,\n\t\t\t// SDK accepts arbitrary strings under the `(string & {})`\n\t\t\t// branch; `localnet` is the closest semantic for a custom\n\t\t\t// caller-defined live target.\n\t\t\tsdkNetwork: 'localnet',\n\t\t});\n\t}\n\tconst defaults = LIVE_DEFAULTS[opts.network];\n\treturn Effect.succeed({\n\t\trpcUrl: opts.rpcUrl ?? defaults.rpcUrl,\n\t\tfaucetUrl: opts.faucetUrl ?? defaults.faucetUrl,\n\t\tgraphqlUrl: opts.graphqlUrl ?? defaults.graphqlUrl,\n\t\tsdkNetwork: opts.network,\n\t});\n};\n\n/** Build the live-mode boot Effect. */\nexport const bootLiveMode = (\n\topts: SuiLiveOptions,\n): Effect.Effect<LiveModeBootResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\t// ----- 1. Resolve endpoints ------------------------------------------\n\t\tconst endpoints = yield* resolveEndpoints(opts);\n\n\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t'sui.live.network': opts.network,\n\t\t\t'sui.live.rpcUrl': endpoints.rpcUrl,\n\t\t\t'sui.live.faucetUrl': endpoints.faucetUrl ?? '<none>',\n\t\t});\n\n\t\t// ----- 2. Construct the grpc client ----------------------------------\n\t\tconst sdkClient = yield* Effect.try({\n\t\t\ttry: () =>\n\t\t\t\tnew SuiGrpcClient({\n\t\t\t\t\tbaseUrl: endpoints.rpcUrl,\n\t\t\t\t\tnetwork: endpoints.sdkNetwork,\n\t\t\t\t}),\n\t\t\tcatch: (cause): SuiPluginError =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'chain-id-fetch',\n\t\t\t\t\t`sui live mode: SuiGrpcClient construction failed for rpcUrl=${endpoints.rpcUrl}: ${stringifyCause(cause)}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t});\n\n\t\t// ----- 3. Resolve chain id -------------------------------------------\n\t\tconst chain =\n\t\t\topts.chain ??\n\t\t\t(yield* fetchChainId(sdkClient, {\n\t\t\t\ttimeout: opts.readyTimeout ?? DEFAULT_LIVE_CHAIN_ID_TIMEOUT,\n\t\t\t\tspan: 'devstack.plugin.sui.live.fetchChainId',\n\t\t\t}));\n\n\t\t// ----- 4. Build waitForTransactionsReady -----------------------------\n\t\t// Mainnet: no faucet exists, gate is a no-op. testnet/devnet/\n\t\t// custom-with-faucet: real HTTP probe (rate-limited by upstream,\n\t\t// but the wire shape is identical to localnet).\n\t\tconst waitForTransactionsReady =\n\t\t\tendpoints.faucetUrl !== undefined\n\t\t\t\t? yield* buildWaitForTransactionsReady(endpoints.faucetUrl)\n\t\t\t\t: noopWaitForTransactionsReady;\n\n\t\t// ----- 5. Assemble + return ------------------------------------------\n\t\tconst { client } = assembleSuiClient({\n\t\t\tsdkClient,\n\t\t\tchain,\n\t\t\trpcUrl: endpoints.rpcUrl,\n\t\t\t...(endpoints.faucetUrl !== undefined ? { faucetUrl: endpoints.faucetUrl } : {}),\n\t\t\t...(endpoints.graphqlUrl !== undefined ? { graphqlUrl: endpoints.graphqlUrl } : {}),\n\t\t\twaitForTransactionsReady,\n\t\t});\n\t\tconst resolved = makeResolvedNetwork({\n\t\t\tmode: 'live',\n\t\t\tchain,\n\t\t\trpc: endpoints.rpcUrl,\n\t\t\t// `source: 'default'` when we pulled from LIVE_DEFAULTS;\n\t\t\t// `'config'` when the caller passed an override. The\n\t\t\t// distinction matters for the doctor's \"where did this\n\t\t\t// value come from\" surface.\n\t\t\tsource:\n\t\t\t\topts.rpcUrl === undefined && opts.faucetUrl === undefined && opts.graphqlUrl === undefined\n\t\t\t\t\t? 'default'\n\t\t\t\t\t: 'config',\n\t\t\t...(endpoints.faucetUrl !== undefined ? { faucet: endpoints.faucetUrl } : {}),\n\t\t\t...(endpoints.graphqlUrl !== undefined ? { graphql: endpoints.graphqlUrl } : {}),\n\t\t});\n\n\t\treturn { resolved, client };\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.sui.live.boot', {\n\t\t\tattributes: { 'devstack.plugin': 'sui', 'sui.mode': 'live' },\n\t\t}),\n\t);\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":";;;;;;AAqDA,MAAa,gCAAgC,SAAS,QAAQ,GAAG;;;AAIjE,MAAa,gBAAgB;CAC5B,SAAS;EACR,QAAQ;EACR,WAAW;EACX,YAAY;EACZ;CACD,SAAS;EACR,QAAQ;EACR,WAAW,KAAA;EACX,YAAY;EACZ;CACD,QAAQ;EACP,QAAQ;EACR,WAAW;EACX,YAAY,KAAA;EACZ;CACD;;;;AAkBD,MAAM,oBACL,SAC0D;AAC1D,KAAI,KAAK,YAAY,UAAU;AAC9B,MAAI,KAAK,WAAW,KAAA,EACnB,QAAO,OAAO,KACb,eACC,kBACA,kLAEA,CACD;AAEF,SAAO,OAAO,QAAQ;GACrB,QAAQ,KAAK;GACb,WAAW,KAAK;GAChB,YAAY,KAAK;GAIjB,YAAY;GACZ,CAAC;;CAEH,MAAM,WAAW,cAAc,KAAK;AACpC,QAAO,OAAO,QAAQ;EACrB,QAAQ,KAAK,UAAU,SAAS;EAChC,WAAW,KAAK,aAAa,SAAS;EACtC,YAAY,KAAK,cAAc,SAAS;EACxC,YAAY,KAAK;EACjB,CAAC;;;AAIH,MAAa,gBACZ,SAEA,OAAO,IAAI,aAAa;CAEvB,MAAM,YAAY,OAAO,iBAAiB,KAAK;AAE/C,QAAO,OAAO,oBAAoB;EACjC,oBAAoB,KAAK;EACzB,mBAAmB,UAAU;EAC7B,sBAAsB,UAAU,aAAa;EAC7C,CAAC;CAGF,MAAM,YAAY,OAAO,OAAO,IAAI;EACnC,WACC,IAAI,cAAc;GACjB,SAAS,UAAU;GACnB,SAAS,UAAU;GACnB,CAAC;EACH,QAAQ,UACP,eACC,kBACA,+DAA+D,UAAU,OAAO,IAAI,eAAe,MAAM,IACzG,MACA;EACF,CAAC;CAGF,MAAM,QACL,KAAK,UACJ,OAAO,aAAa,WAAW;EAC/B,SAAS,KAAK,gBAAgB;EAC9B,MAAM;EACN,CAAC;CAMH,MAAM,2BACL,UAAU,cAAc,KAAA,IACrB,OAAO,8BAA8B,UAAU,UAAU,GACzD;CAGJ,MAAM,EAAE,WAAW,kBAAkB;EACpC;EACA;EACA,QAAQ,UAAU;EAClB,GAAI,UAAU,cAAc,KAAA,IAAY,EAAE,WAAW,UAAU,WAAW,GAAG,EAAE;EAC/E,GAAI,UAAU,eAAe,KAAA,IAAY,EAAE,YAAY,UAAU,YAAY,GAAG,EAAE;EAClF;EACA,CAAC;AAiBF,QAAO;EAAE,UAhBQ,oBAAoB;GACpC,MAAM;GACN;GACA,KAAK,UAAU;GAKf,QACC,KAAK,WAAW,KAAA,KAAa,KAAK,cAAc,KAAA,KAAa,KAAK,eAAe,KAAA,IAC9E,YACA;GACJ,GAAI,UAAU,cAAc,KAAA,IAAY,EAAE,QAAQ,UAAU,WAAW,GAAG,EAAE;GAC5E,GAAI,UAAU,eAAe,KAAA,IAAY,EAAE,SAAS,UAAU,YAAY,GAAG,EAAE;GAC/E,CAEgB;EAAE;EAAQ;EAC1B,CAAC,KACF,OAAO,SAAS,iCAAiC,EAChD,YAAY;CAAE,mBAAmB;CAAO,YAAY;CAAQ,EAC5D,CAAC,CACF;AAEF,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":"live.mjs","names":[],"sources":["../../../../src/plugins/sui/mode/live.ts"],"sourcesContent":["// Sui plugin — live mode (testnet / mainnet / devnet / custom).\n//\n// Wraps a public or caller-provided Sui RPC. Testnet has a faucet;\n// mainnet has none; custom may or may not.\n//\n// What's hard:\n// - No ready probe is meaningful (the public chain is always\n// up); chain-id fetch IS the only sentinel with a bounded\n// timeout.\n// - Faucet-less networks (mainnet) need a \"no-op\" funds-ready\n// gate so downstream callers don't have to branch.\n// - The KnownPackage substrate contributions are wired here so\n// wallet-standard / MVR / known-deployment lookups find the\n// right published ids.\n//\n// Live mode contributes a `ChainProbe` and a `Codegenable` — but NO\n// managed container, NO `Routable`, and the\n// build container is forced to the host CLI path (no in-stack\n// build image). The latter is flagged in the distilled-doc Open\n// questions as a candidate to revisit.\n//\n// Boot sequence:\n//\n// 1. Resolve `rpcUrl` / `faucetUrl` / `graphqlUrl` from caller\n// overrides, then fall back to `LIVE_DEFAULTS` for known nets.\n// `custom` requires `rpcUrl` — surface a typed refusal if\n// omitted.\n// 2. Construct `SuiGrpcClient` against the resolved URL with the\n// matching `network:` discriminator (so MVR / wallet-standard\n// hints route correctly).\n// 3. Fetch chain id (the only readiness sentinel for live).\n// 4. Build `waitForTransactionsReady`:\n// - mainnet: trivially-succeeding no-op (no faucet exists).\n// - testnet/devnet/custom-with-faucet: real HTTP probe.\n// - custom-without-faucet: no-op.\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\n\nimport { SpanAttr } from '../../../substrate/runtime/observability/spans.ts';\nimport { suiPluginError, type SuiConfigError, type SuiPluginError } from '../errors.ts';\nimport { formatUnknownError } from '../../../substrate/runtime/format-unknown-error.ts';\nimport type { ResolvedSuiNetwork } from '../network-resolver.ts';\nimport { SuiSpans } from '../spans.ts';\nimport type { SuiClient } from './shared.ts';\nimport {\n\tassembleSuiClient,\n\tbuildWaitForTransactionsReady,\n\tfetchChainId,\n\tmakeResolvedNetwork,\n\tnoopWaitForTransactionsReady,\n} from './shared-boot.ts';\nimport type { SuiLiveOptions } from './spec.ts';\n\n/** Default chain-id fetch timeout for live RPCs. */\nexport const DEFAULT_LIVE_CHAIN_ID_TIMEOUT = Duration.seconds(30);\n\n/** Default RPC endpoints per known network. `custom` requires the\n * caller to supply `rpcUrl`. */\nexport const LIVE_DEFAULTS = {\n\ttestnet: {\n\t\trpcUrl: 'https://fullnode.testnet.sui.io:443',\n\t\tfaucetUrl: 'https://faucet.testnet.sui.io',\n\t\tgraphqlUrl: 'https://sui-testnet.mystenlabs.com/graphql',\n\t},\n\tmainnet: {\n\t\trpcUrl: 'https://fullnode.mainnet.sui.io:443',\n\t\tfaucetUrl: undefined as string | undefined,\n\t\tgraphqlUrl: 'https://sui-mainnet.mystenlabs.com/graphql',\n\t},\n\tdevnet: {\n\t\trpcUrl: 'https://fullnode.devnet.sui.io:443',\n\t\tfaucetUrl: 'https://faucet.devnet.sui.io',\n\t\tgraphqlUrl: undefined as string | undefined,\n\t},\n} as const;\n\n/** Resolved live-mode boot artifacts. */\nexport interface LiveModeBootResult {\n\treadonly resolved: ResolvedSuiNetwork;\n\treadonly client: SuiClient;\n}\n\ninterface ResolvedLiveEndpoints {\n\treadonly rpcUrl: string;\n\treadonly faucetUrl: string | undefined;\n\treadonly graphqlUrl: string | undefined;\n\treadonly sdkNetwork: 'mainnet' | 'testnet' | 'devnet' | 'localnet';\n}\n\n/** Resolve endpoints from caller overrides + the known-network table.\n * Order: caller-provided wins; otherwise the LIVE_DEFAULTS row for\n * the requested network. `custom` MUST carry an explicit `rpcUrl`. */\nconst resolveEndpoints = (\n\topts: SuiLiveOptions,\n): Effect.Effect<ResolvedLiveEndpoints, SuiPluginError> => {\n\tif (opts.network === 'custom') {\n\t\tif (opts.rpcUrl === undefined) {\n\t\t\treturn Effect.fail(\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'chain-id-fetch',\n\t\t\t\t\t`sui live mode: network='custom' requires opts.rpcUrl. ` +\n\t\t\t\t\t\t`Use suiFor(network).live.custom({rpcUrl: ...}) or pass network='testnet'|'mainnet'|'devnet' to use the built-in defaults.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn Effect.succeed({\n\t\t\trpcUrl: opts.rpcUrl,\n\t\t\tfaucetUrl: opts.faucetUrl,\n\t\t\tgraphqlUrl: opts.graphqlUrl,\n\t\t\t// SDK accepts arbitrary strings under the `(string & {})`\n\t\t\t// branch; `localnet` is the closest semantic for a custom\n\t\t\t// caller-defined live target.\n\t\t\tsdkNetwork: 'localnet',\n\t\t});\n\t}\n\tconst defaults = LIVE_DEFAULTS[opts.network];\n\treturn Effect.succeed({\n\t\trpcUrl: opts.rpcUrl ?? defaults.rpcUrl,\n\t\tfaucetUrl: opts.faucetUrl ?? defaults.faucetUrl,\n\t\tgraphqlUrl: opts.graphqlUrl ?? defaults.graphqlUrl,\n\t\tsdkNetwork: opts.network,\n\t});\n};\n\n/** Build the live-mode boot Effect. */\nexport const bootLiveMode = (\n\topts: SuiLiveOptions,\n): Effect.Effect<LiveModeBootResult, SuiPluginError | SuiConfigError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\t// ----- 1. Resolve endpoints ------------------------------------------\n\t\tconst endpoints = yield* resolveEndpoints(opts);\n\n\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t[SuiSpans.liveNetwork]: opts.network,\n\t\t\t[SuiSpans.liveRpcUrl]: endpoints.rpcUrl,\n\t\t\t...(endpoints.faucetUrl !== undefined\n\t\t\t\t? { [SuiSpans.liveFaucetUrl]: endpoints.faucetUrl }\n\t\t\t\t: {}),\n\t\t});\n\n\t\t// ----- 2. Construct the grpc client ----------------------------------\n\t\tconst sdkClient = yield* Effect.try({\n\t\t\ttry: () =>\n\t\t\t\tnew SuiGrpcClient({\n\t\t\t\t\tbaseUrl: endpoints.rpcUrl,\n\t\t\t\t\tnetwork: endpoints.sdkNetwork,\n\t\t\t\t}),\n\t\t\tcatch: (cause): SuiPluginError =>\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'chain-id-fetch',\n\t\t\t\t\t`sui live mode: SuiGrpcClient construction failed for rpcUrl=${endpoints.rpcUrl}: ${formatUnknownError(cause)}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t});\n\n\t\t// ----- 3. Resolve chain id -------------------------------------------\n\t\tconst chain =\n\t\t\topts.chain ??\n\t\t\t(yield* fetchChainId(sdkClient, {\n\t\t\t\ttimeout: opts.readyTimeout ?? DEFAULT_LIVE_CHAIN_ID_TIMEOUT,\n\t\t\t\tspan: 'devstack.plugin.sui.live.fetchChainId',\n\t\t\t}));\n\n\t\t// ----- 4. Build waitForTransactionsReady -----------------------------\n\t\t// Mainnet: no faucet exists, gate is a no-op. testnet/devnet/\n\t\t// custom-with-faucet: real HTTP probe (rate-limited by upstream,\n\t\t// but the wire shape is identical to localnet).\n\t\tconst waitForTransactionsReady =\n\t\t\tendpoints.faucetUrl !== undefined\n\t\t\t\t? yield* buildWaitForTransactionsReady(endpoints.faucetUrl)\n\t\t\t\t: noopWaitForTransactionsReady;\n\n\t\t// ----- 5. Assemble + return ------------------------------------------\n\t\tconst { client } = yield* assembleSuiClient({\n\t\t\tsdkClient,\n\t\t\tchain,\n\t\t\trpcUrl: endpoints.rpcUrl,\n\t\t\t...(endpoints.faucetUrl !== undefined ? { faucetUrl: endpoints.faucetUrl } : {}),\n\t\t\t...(endpoints.graphqlUrl !== undefined ? { graphqlUrl: endpoints.graphqlUrl } : {}),\n\t\t\twaitForTransactionsReady,\n\t\t});\n\t\tconst resolved = makeResolvedNetwork({\n\t\t\tmode: 'live',\n\t\t\tchain,\n\t\t\trpc: endpoints.rpcUrl,\n\t\t\t// `source: 'default'` when we pulled from LIVE_DEFAULTS;\n\t\t\t// `'config'` when the caller passed an override. The\n\t\t\t// distinction matters for the doctor's \"where did this\n\t\t\t// value come from\" surface.\n\t\t\tsource:\n\t\t\t\topts.rpcUrl === undefined && opts.faucetUrl === undefined && opts.graphqlUrl === undefined\n\t\t\t\t\t? 'default'\n\t\t\t\t\t: 'config',\n\t\t\t...(endpoints.faucetUrl !== undefined ? { faucet: endpoints.faucetUrl } : {}),\n\t\t\t...(endpoints.graphqlUrl !== undefined ? { graphql: endpoints.graphqlUrl } : {}),\n\t\t});\n\n\t\treturn { resolved, client };\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.sui.live.boot', {\n\t\t\tattributes: { [SpanAttr.plugin]: 'sui', [SuiSpans.mode]: 'live' },\n\t\t}),\n\t);\n"],"mappings":";;;;;;;;;AAwDA,MAAa,gCAAgC,SAAS,QAAQ,GAAG;;;AAIjE,MAAa,gBAAgB;CAC5B,SAAS;EACR,QAAQ;EACR,WAAW;EACX,YAAY;EACZ;CACD,SAAS;EACR,QAAQ;EACR,WAAW,KAAA;EACX,YAAY;EACZ;CACD,QAAQ;EACP,QAAQ;EACR,WAAW;EACX,YAAY,KAAA;EACZ;CACD;;;;AAkBD,MAAM,oBACL,SAC0D;AAC1D,KAAI,KAAK,YAAY,UAAU;AAC9B,MAAI,KAAK,WAAW,KAAA,EACnB,QAAO,OAAO,KACb,eACC,kBACA,kLAEA,CACD;AAEF,SAAO,OAAO,QAAQ;GACrB,QAAQ,KAAK;GACb,WAAW,KAAK;GAChB,YAAY,KAAK;GAIjB,YAAY;GACZ,CAAC;;CAEH,MAAM,WAAW,cAAc,KAAK;AACpC,QAAO,OAAO,QAAQ;EACrB,QAAQ,KAAK,UAAU,SAAS;EAChC,WAAW,KAAK,aAAa,SAAS;EACtC,YAAY,KAAK,cAAc,SAAS;EACxC,YAAY,KAAK;EACjB,CAAC;;;AAIH,MAAa,gBACZ,SAEA,OAAO,IAAI,aAAa;CAEvB,MAAM,YAAY,OAAO,iBAAiB,KAAK;AAE/C,QAAO,OAAO,oBAAoB;GAChC,SAAS,cAAc,KAAK;GAC5B,SAAS,aAAa,UAAU;EACjC,GAAI,UAAU,cAAc,KAAA,IACzB,GAAG,SAAS,gBAAgB,UAAU,WAAW,GACjD,EAAE;EACL,CAAC;CAGF,MAAM,YAAY,OAAO,OAAO,IAAI;EACnC,WACC,IAAI,cAAc;GACjB,SAAS,UAAU;GACnB,SAAS,UAAU;GACnB,CAAC;EACH,QAAQ,UACP,eACC,kBACA,+DAA+D,UAAU,OAAO,IAAI,mBAAmB,MAAM,IAC7G,MACA;EACF,CAAC;CAGF,MAAM,QACL,KAAK,UACJ,OAAO,aAAa,WAAW;EAC/B,SAAS,KAAK,gBAAgB;EAC9B,MAAM;EACN,CAAC;CAMH,MAAM,2BACL,UAAU,cAAc,KAAA,IACrB,OAAO,8BAA8B,UAAU,UAAU,GACzD;CAGJ,MAAM,EAAE,WAAW,OAAO,kBAAkB;EAC3C;EACA;EACA,QAAQ,UAAU;EAClB,GAAI,UAAU,cAAc,KAAA,IAAY,EAAE,WAAW,UAAU,WAAW,GAAG,EAAE;EAC/E,GAAI,UAAU,eAAe,KAAA,IAAY,EAAE,YAAY,UAAU,YAAY,GAAG,EAAE;EAClF;EACA,CAAC;AAiBF,QAAO;EAAE,UAhBQ,oBAAoB;GACpC,MAAM;GACN;GACA,KAAK,UAAU;GAKf,QACC,KAAK,WAAW,KAAA,KAAa,KAAK,cAAc,KAAA,KAAa,KAAK,eAAe,KAAA,IAC9E,YACA;GACJ,GAAI,UAAU,cAAc,KAAA,IAAY,EAAE,QAAQ,UAAU,WAAW,GAAG,EAAE;GAC5E,GAAI,UAAU,eAAe,KAAA,IAAY,EAAE,SAAS,UAAU,YAAY,GAAG,EAAE;GAC/E,CAEgB;EAAE;EAAQ;EAC1B,CAAC,KACF,OAAO,SAAS,iCAAiC,EAChD,YAAY;EAAG,SAAS,SAAS;EAAQ,SAAS,OAAO;CAAQ,EACjE,CAAC,CACF"}
@@ -1,13 +1,15 @@
1
- import { renderUrl, routerHostname } from "../../../orchestrators/router/hostname.mjs";
2
- import { suiPluginError } from "../errors.mjs";
1
+ import { SpanAttr } from "../../../substrate/runtime/observability/spans.mjs";
2
+ import { setCurrentPluginPhase } from "../../../substrate/runtime/current-plugin.mjs";
3
+ import { DEFAULT_SUI_CLI_VERSION, suiCliImageBuildContext } from "../../../substrate/runtime/sui-move-build/index.mjs";
4
+ import { renderUrl, routedHostname } from "../../../substrate/runtime/routed-url.mjs";
3
5
  import { waitForHttpEndpoint } from "../../../substrate/runtime/http-probe.mjs";
6
+ import { SUI_FAUCET_ENDPOINT_NAME, SUI_FAUCET_ENTRYPOINT_PORT, SUI_GRAPHQL_ENDPOINT_NAME, SUI_GRAPHQL_ENTRYPOINT_PORT, SUI_RPC_ENTRYPOINT_PORT } from "../routable.mjs";
7
+ import { ensureManagedContainer } from "../../../substrate/runtime/managed-container.mjs";
8
+ import { suiPluginError } from "../errors.mjs";
9
+ import { formatUnknownError } from "../../../substrate/runtime/format-unknown-error.mjs";
10
+ import { SuiSpans } from "../spans.mjs";
4
11
  import { toDockerHostGatewayUrl } from "./shared.mjs";
5
12
  import { assembleSuiClient, buildWaitForTransactionsReady, fetchChainId, makeResolvedNetwork } from "./shared-boot.mjs";
6
- import { ensureManagedContainer } from "../../../substrate/runtime/managed-container.mjs";
7
- import { noopClockAdvancer } from "../auto-tick.mjs";
8
- import { SUI_FAUCET_ENDPOINT_NAME, SUI_FAUCET_ENTRYPOINT_PORT, SUI_GRAPHQL_ENDPOINT_NAME, SUI_GRAPHQL_ENTRYPOINT_PORT, SUI_RPC_ENTRYPOINT_PORT } from "../routable.mjs";
9
- import { DEFAULT_SUI_CLI_VERSION, suiCliImageBuildContext } from "../../../substrate/runtime/sui-move-build/index.mjs";
10
- import { setCurrentPluginPhase } from "../../../substrate/runtime/current-plugin.mjs";
11
13
  import { Duration, Effect } from "effect";
12
14
  import { SuiGrpcClient } from "@mysten/sui/grpc";
13
15
  //#region src/plugins/sui/mode/local.ts
@@ -43,7 +45,7 @@ const PROBE_FETCH_TIMEOUT_MS = 3e3;
43
45
  */
44
46
  const bootLocalMode = (runtime, identity, portBroker, opts) => Effect.gen(function* () {
45
47
  yield* setCurrentPluginPhase("resolving Sui local image");
46
- const image = yield* resolveImage(runtime, opts);
48
+ const image = yield* resolveImage(runtime, identity, opts);
47
49
  yield* setCurrentPluginPhase("creating Sui validator container");
48
50
  const { handle, ports } = yield* ensureLocalValidatorContainer(runtime, portBroker, image, {
49
51
  app: identity.app,
@@ -60,7 +62,7 @@ const bootLocalMode = (runtime, identity, portBroker, opts) => Effect.gen(functi
60
62
  const graphqlUrl = yield* routedSuiUrl(identity, SUI_GRAPHQL_ENDPOINT_NAME, SUI_GRAPHQL_ENTRYPOINT_PORT);
61
63
  const readyTimeout = opts.readyTimeout ?? DEFAULT_LOCAL_READY_TIMEOUT;
62
64
  yield* setCurrentPluginPhase("waiting for Sui RPC, faucet, and GraphQL");
63
- yield* waitForReady(directRpcUrl, directFaucetUrl, directGraphqlUrl, readyTimeout).pipe(Effect.annotateLogs({ "sui.container": handle.name }));
65
+ yield* waitForReady(directRpcUrl, directFaucetUrl, directGraphqlUrl, readyTimeout).pipe(Effect.annotateLogs({ [SuiSpans.container]: handle.name }));
64
66
  const sdkClient = new SuiGrpcClient({
65
67
  baseUrl: directRpcUrl,
66
68
  network: "localnet"
@@ -68,11 +70,10 @@ const bootLocalMode = (runtime, identity, portBroker, opts) => Effect.gen(functi
68
70
  yield* setCurrentPluginPhase("fetching Sui chain id");
69
71
  const chain = yield* fetchChainId(sdkClient, { span: "devstack.plugin.sui.local.fetchChainId" });
70
72
  yield* setCurrentPluginPhase("preparing Sui funds-ready gate");
71
- const { client } = assembleSuiClient({
73
+ const { client } = yield* assembleSuiClient({
72
74
  sdkClient,
73
75
  chain,
74
76
  rpcUrl,
75
- sdkRpcUrl: directRpcUrl,
76
77
  faucetUrl,
77
78
  fundingFaucetUrl: directFaucetUrl,
78
79
  graphqlUrl,
@@ -93,22 +94,31 @@ const bootLocalMode = (runtime, identity, portBroker, opts) => Effect.gen(functi
93
94
  graphql: graphqlUrl,
94
95
  source: "default"
95
96
  }),
96
- client,
97
- clockAdvancer: noopClockAdvancer
97
+ client
98
98
  };
99
- }).pipe(Effect.withSpan("devstack.plugin.sui.local.boot", { attributes: { "devstack.plugin": "sui" } }));
100
- const resolveImage = (runtime, opts) => Effect.gen(function* () {
99
+ }).pipe(Effect.withSpan("devstack.plugin.sui.local.boot", { attributes: { [SpanAttr.plugin]: "sui" } }));
100
+ const resolveImage = (runtime, identity, opts) => Effect.gen(function* () {
101
101
  if (opts.image && "pull" in opts.image) {
102
102
  const pullRef = opts.image.pull;
103
103
  if (runtime.pullImage === void 0) return yield* Effect.fail(suiPluginError("image-build", `sui local mode cannot pull image '${pullRef}' because the configured container runtime does not expose image pulls.`));
104
104
  return yield* runtime.pullImage(pullRef).pipe(Effect.mapError((cause) => suiPluginError("image-build", `sui local mode failed to pull image '${pullRef}': ${cause.reason}: ${cause.detail}`, cause)));
105
105
  }
106
106
  const version = opts.version ?? DEFAULT_SUI_VERSION;
107
+ const owner = {
108
+ app: identity.app,
109
+ stack: identity.stack,
110
+ plugin: "sui",
111
+ role: "validator"
112
+ };
107
113
  const buildCtx = opts.image && "build" in opts.image ? {
108
114
  contextPath: opts.image.build.context,
109
115
  dockerfile: opts.image.build.dockerfile ?? "Dockerfile",
110
- buildArgs: { SUI_VERSION: version }
111
- } : suiCliImageBuildContext(version);
116
+ buildArgs: { SUI_VERSION: version },
117
+ owner
118
+ } : {
119
+ ...suiCliImageBuildContext(version),
120
+ owner
121
+ };
112
122
  return yield* runtime.ensureImage(buildCtx).pipe(Effect.mapError((cause) => suiPluginError("image-build", `sui image build failed: ${cause.reason}: ${cause.detail}`, cause)));
113
123
  }).pipe(Effect.withSpan("devstack.plugin.sui.local.resolveImage"));
114
124
  const ensureLocalValidatorContainer = (runtime, portBroker, image, labels, containerName, opts) => Effect.gen(function* () {
@@ -181,9 +191,9 @@ const resolvePortMappingWithRelease = (portBroker, override) => {
181
191
  release: Effect.void
182
192
  });
183
193
  return Effect.gen(function* () {
184
- const rpc = yield* allocatePort(portBroker, "rpc", DEFAULT_HOST_RPC_PORT, "rpc");
185
- const faucet = yield* allocatePort(portBroker, "http", DEFAULT_HOST_FAUCET_PORT, "faucet");
186
- const graphql = yield* allocatePort(portBroker, "rpc", DEFAULT_HOST_GRAPHQL_PORT, "graphql");
194
+ const rpc = yield* allocatePort(portBroker, "sui:rpc", DEFAULT_HOST_RPC_PORT, "rpc");
195
+ const faucet = yield* allocatePort(portBroker, "sui:faucet", DEFAULT_HOST_FAUCET_PORT, "faucet");
196
+ const graphql = yield* allocatePort(portBroker, "sui:graphql", DEFAULT_HOST_GRAPHQL_PORT, "graphql");
187
197
  return {
188
198
  ports: [
189
199
  portPublish(CONTAINER_RPC_PORT, rpc.port),
@@ -216,13 +226,13 @@ const portPublish = (containerPort, hostPort) => ({
216
226
  hostPort,
217
227
  hostIp: DOCKER_PUBLISH_HOST
218
228
  });
219
- const allocatePort = (portBroker, kind, preferredPort, label) => {
229
+ const allocatePort = (portBroker, owner, preferredPort, label) => {
220
230
  const allocate = (hint) => portBroker.allocate({
221
- kind,
231
+ owner,
222
232
  ...hint === void 0 ? {} : { preferredPort: hint },
223
233
  probeHost: DOCKER_PUBLISH_HOST
224
234
  }).pipe(Effect.catchTag("PortBrokerError", (cause) => hint !== void 0 && cause.reason === "preferred-busy" ? portBroker.allocate({
225
- kind,
235
+ owner,
226
236
  probeHost: DOCKER_PUBLISH_HOST
227
237
  }) : Effect.fail(cause)), Effect.mapError((cause) => suiPluginError("port-allocate", `sui local mode: failed to allocate ${label} host port (preferred ${hint ?? "auto"}): ${cause.detail}`, cause)));
228
238
  return allocate(preferredPort);
@@ -252,41 +262,32 @@ const waitForReady = (rpcUrl, faucetUrl, graphqlUrl, readyTimeout) => Effect.gen
252
262
  const body = await response.json();
253
263
  return typeof body.result === "string" || typeof body.result === "number";
254
264
  }
255
- }).pipe(Effect.mapError((cause) => suiPluginError("rpc-probe", `sui local mode: RPC endpoint ${rpcUrl} did not become ready within ${readyTimeoutMs}ms: ${stringifyCause(cause)}`, cause)), Effect.withSpan("devstack.plugin.sui.local.probe.rpc"));
265
+ }).pipe(Effect.mapError((cause) => suiPluginError("rpc-probe", `sui local mode: RPC endpoint ${rpcUrl} did not become ready within ${readyTimeoutMs}ms: ${formatUnknownError(cause)}`, cause)), Effect.withSpan("devstack.plugin.sui.local.probe.rpc"));
256
266
  const faucetProbe = waitForHttpEndpoint({
257
267
  endpoint: faucetUrl,
258
268
  timeoutMs: readyTimeoutMs,
259
269
  intervalMs: 1e3,
260
270
  requestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,
261
271
  validate: (response) => response.status < 500
262
- }).pipe(Effect.mapError((cause) => suiPluginError("faucet-probe", `sui local mode: faucet endpoint ${faucetUrl} did not become ready within ${readyTimeoutMs}ms: ${stringifyCause(cause)}`, cause)), Effect.withSpan("devstack.plugin.sui.local.probe.faucet"));
272
+ }).pipe(Effect.mapError((cause) => suiPluginError("faucet-probe", `sui local mode: faucet endpoint ${faucetUrl} did not become ready within ${readyTimeoutMs}ms: ${formatUnknownError(cause)}`, cause)), Effect.withSpan("devstack.plugin.sui.local.probe.faucet"));
263
273
  const graphqlProbe = waitForHttpEndpoint({
264
274
  endpoint: graphqlUrl,
265
275
  timeoutMs: readyTimeoutMs,
266
276
  intervalMs: 1e3,
267
277
  requestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,
268
278
  validate: (response) => response.status < 500
269
- }).pipe(Effect.mapError((cause) => suiPluginError("graphql-probe", `sui local mode: GraphQL endpoint ${graphqlUrl} did not become ready within ${readyTimeoutMs}ms: ${stringifyCause(cause)}`, cause)), Effect.withSpan("devstack.plugin.sui.local.probe.graphql"));
279
+ }).pipe(Effect.mapError((cause) => suiPluginError("graphql-probe", `sui local mode: GraphQL endpoint ${graphqlUrl} did not become ready within ${readyTimeoutMs}ms: ${formatUnknownError(cause)}`, cause)), Effect.withSpan("devstack.plugin.sui.local.probe.graphql"));
270
280
  yield* Effect.all([
271
281
  rpcProbe,
272
282
  faucetProbe,
273
283
  graphqlProbe
274
284
  ], { concurrency: "unbounded" }).pipe(Effect.asVoid);
275
285
  }).pipe(Effect.withSpan("devstack.plugin.sui.local.waitForReady"));
276
- const routedSuiUrl = (identity, endpointName, port) => routerHostname(identity, endpointName).pipe(Effect.map((hostname) => renderUrl({
286
+ const routedSuiUrl = (identity, endpointName, port) => routedHostname(identity, endpointName).pipe(Effect.map((hostname) => renderUrl({
277
287
  protocol: "http",
278
288
  hostname,
279
289
  port
280
290
  })), Effect.mapError((cause) => suiPluginError("container-start", `sui local mode: failed to construct router URL for ${endpointName}: ${cause.detail}`, cause)));
281
- const stringifyCause = (cause) => {
282
- if (cause instanceof Error) return cause.message;
283
- if (typeof cause === "string") return cause;
284
- try {
285
- return JSON.stringify(cause);
286
- } catch {
287
- return String(cause);
288
- }
289
- };
290
291
  //#endregion
291
292
  export { bootLocalMode };
292
293
 
@@ -1 +1 @@
1
- {"version":3,"file":"local.mjs","names":["sharedFetchChainId"],"sources":["../../../../src/plugins/sui/mode/local.ts"],"sourcesContent":["// Sui plugin — local-container mode.\n//\n// In-stack Sui validator + faucet, running in the supervised docker\n// stack. Used during normal dev loops when the developer wants fresh,\n// fast, throwaway chain state with a working faucet.\n//\n// Boot sequence (load-bearing order):\n//\n// 1. Resolve image — vendored Dockerfile build via the\n// ContainerRuntime contract (caller `image` override honoured for\n// `{build}`; `{pull}` is deferred — see stub list in the README).\n// 2. Allocate + ensure container — `sui start --with-faucet=0.0.0.0:9123\n// --with-graphql=0.0.0.0:9125` with direct host port-publishing\n// for internal boot probes. User-facing URLs are router-fronted\n// named hosts; the direct host ports intentionally live in the\n// high private windows so they do not collide with router\n// entrypoints.\n// RecreatePolicy is `on-failure` so the writable layer (chain\n// state at `/root/.sui`) survives clean stop/start cycles, but an\n// unclean SIGKILL/137 exit recreates instead of resuming a suspect\n// RocksDB/checkpoint state. The image's entrypoint forwards SIGINT\n// to a non-PID-1 sui child so clean shutdown (RocksDB checkpoint\n// drain → exit 0/130) is the normal case.\n// 3. Ready probe — RPC `getChainIdentifier`, faucet `GET /`, and\n// GraphQL HTTP liveness. Per-fetch deadline + outer deadline.\n// 4. Fetch chain id from the now-responsive client (bounded timeout).\n// 5. Build `waitForTransactionsReady` — `Effect.cached` against a\n// real faucet funding tx; first failure caches for the scope.\n// Manual `invalidate` clears the memo.\n// 6. Return resolved `SuiClient`. Auto-tick is the no-op advancer\n// (localnet drives its own consensus).\n//\n// Faucet socket-level readiness does NOT imply funds-transferability.\n// The first `waitForTransactionsReady.wait` POSTs a real funding tx,\n// retrying on body-level `{Failure}` responses during the post-RPC /\n// pre-fund window.\n//\n// What this body deliberately defers:\n// - Postgres indexer sidecar — GraphQL is enabled by `sui start` and\n// routed as a first-class endpoint, but no separate postgres\n// lifecycle is supervised here.\n// - Snapshot capture — the framework exists in the plugin's\n// snapshot.ts; this body produces the running container that the\n// orchestrator captures.\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\n\nimport type {\n\tContainerHandle,\n\tContainerRuntime,\n\tContainerRuntimeError,\n\tImageRef,\n\tContainerPortPublish,\n\tPortBindingReconciliation,\n} from '../../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../../contracts/snapshotable.ts';\nimport type { Identity } from '../../../substrate/identity.ts';\nimport type {\n\tAllocatedPort,\n\tPortBroker,\n\tPortKind,\n} from '../../../substrate/runtime/port-broker/index.ts';\nimport { waitForHttpEndpoint } from '../../../substrate/runtime/http-probe.ts';\nimport { setCurrentPluginPhase } from '../../../substrate/runtime/current-plugin.ts';\nimport { ensureManagedContainer } from '../../../substrate/runtime/managed-container.ts';\nimport { renderUrl, routerHostname } from '../../../orchestrators/router/hostname.ts';\nimport {\n\tDEFAULT_SUI_CLI_VERSION,\n\tsuiCliImageBuildContext,\n} from '../../../substrate/runtime/sui-move-build/index.ts';\nimport { noopClockAdvancer } from '../auto-tick.ts';\nimport { suiPluginError, type SuiPluginError } from '../errors.ts';\nimport type { ResolvedSuiNetwork } from '../network-resolver.ts';\nimport {\n\tSUI_FAUCET_ENTRYPOINT_PORT,\n\tSUI_FAUCET_ENDPOINT_NAME,\n\tSUI_GRAPHQL_ENDPOINT_NAME,\n\tSUI_GRAPHQL_ENTRYPOINT_PORT,\n\tSUI_RPC_ENDPOINT_NAME,\n\tSUI_RPC_ENTRYPOINT_PORT,\n} from '../routable.ts';\nimport type { SuiClient } from './shared.ts';\nimport { toDockerHostGatewayUrl } from './shared.ts';\nimport {\n\tassembleSuiClient,\n\tbuildWaitForTransactionsReady,\n\tfetchChainId as sharedFetchChainId,\n\tmakeResolvedNetwork,\n} from './shared-boot.ts';\nimport type { SuiLocalOptions } from './spec.ts';\n\n/** Default ready-probe timeout for localnet. The validator's cold\n * start runs genesis + faucet bootstrap; 60 s is the documented\n * ceiling. */\nexport const DEFAULT_LOCAL_READY_TIMEOUT = Duration.seconds(60);\n\n/** Default sui validator binary version pinned by the vendored\n * `images/sui/` Dockerfile. The build arg `SUI_VERSION` is threaded\n * through to the release-tarball URL. Bump in lockstep with matching\n * Walrus / Seal versions (else the Move package ABIs drift). */\nexport const DEFAULT_SUI_VERSION = DEFAULT_SUI_CLI_VERSION;\n\n// In-container ports the sui binary binds on. These match the router\n// entrypoint ports; direct host publishes below use different high\n// ports so Traefik owns the public listener ports.\nconst CONTAINER_RPC_PORT = SUI_RPC_ENTRYPOINT_PORT;\nconst CONTAINER_FAUCET_PORT = SUI_FAUCET_ENTRYPOINT_PORT;\nconst CONTAINER_GRAPHQL_PORT = SUI_GRAPHQL_ENTRYPOINT_PORT;\n\n// Default host ports. Without `opts.ports`, these are preferences\n// brokered against the kernel before Docker publishes them.\nexport const DEFAULT_HOST_RPC_PORT = 51000;\nexport const DEFAULT_HOST_FAUCET_PORT = 50000;\nexport const DEFAULT_HOST_GRAPHQL_PORT = 51001;\nconst DOCKER_PUBLISH_HOST = '0.0.0.0' as const;\nexport const MAX_DOCKER_PUBLISH_PORT_RETRIES = 3;\nexport const LOCAL_VALIDATOR_STOP_GRACE_SECONDS = 30;\n\n/** Per-fetch deadline for the ready-probe HTTP calls. Without it a\n * hung fetch would block the outer ready deadline with no signal\n * about which probe wedged. */\nconst PROBE_FETCH_TIMEOUT_MS = 3000;\n\n/** Resolved local-mode boot artifacts. */\nexport interface LocalModeBootResult {\n\treadonly resolved: ResolvedSuiNetwork;\n\treadonly client: SuiClient;\n\treadonly clockAdvancer: typeof noopClockAdvancer;\n}\n\n/**\n * Build the local-mode boot Effect.\n *\n * `identity` is threaded in by the caller (the plugin barrel's acquire\n * body, which has access to the substrate's `IdentityContext` via the\n * outer composition layer); the body uses it to stamp the canonical\n * container label tuple so sweep / inventory are name-blind.\n *\n * `{pull}`, `{build}`, and vendored-build image branches are wired.\n */\nexport const bootLocalMode = (\n\truntime: ContainerRuntime,\n\tidentity: Identity,\n\tportBroker: PortBroker,\n\topts: SuiLocalOptions,\n): Effect.Effect<LocalModeBootResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\t// ----- 1. Resolve image ---------------------------------------------\n\t\tyield* setCurrentPluginPhase('resolving Sui local image');\n\t\tconst image = yield* resolveImage(runtime, opts);\n\n\t\t// ----- 2. Allocate ports + ensure container --------------------------\n\t\tyield* setCurrentPluginPhase('creating Sui validator container');\n\t\tconst labels: ContainerLabelTuple = {\n\t\t\tapp: identity.app,\n\t\t\tstack: identity.stack,\n\t\t\tplugin: 'sui',\n\t\t\trole: 'validator',\n\t\t};\n\t\tconst containerName = `devstack-${identity.app}-${identity.stack}-sui-validator`;\n\t\tconst { handle, ports } = yield* ensureLocalValidatorContainer(\n\t\t\truntime,\n\t\t\tportBroker,\n\t\t\timage,\n\t\t\tlabels,\n\t\t\tcontainerName,\n\t\t\topts,\n\t\t);\n\n\t\t// ----- 3. Ready probes ----------------------------------------------\n\t\tconst publishedPorts = resolvePublishedPortMapping(ports, handle.ports);\n\t\tconst directRpcUrl = `http://127.0.0.1:${publishedPorts[0]!.hostPort}`;\n\t\tconst directFaucetUrl = `http://127.0.0.1:${publishedPorts[1]!.hostPort}`;\n\t\tconst directGraphqlUrl = `http://127.0.0.1:${publishedPorts[2]!.hostPort}`;\n\t\tconst rpcUrl = yield* routedSuiUrl(identity, SUI_RPC_ENDPOINT_NAME, SUI_RPC_ENTRYPOINT_PORT);\n\t\tconst faucetUrl = yield* routedSuiUrl(\n\t\t\tidentity,\n\t\t\tSUI_FAUCET_ENDPOINT_NAME,\n\t\t\tSUI_FAUCET_ENTRYPOINT_PORT,\n\t\t);\n\t\tconst graphqlUrl = yield* routedSuiUrl(\n\t\t\tidentity,\n\t\t\tSUI_GRAPHQL_ENDPOINT_NAME,\n\t\t\tSUI_GRAPHQL_ENTRYPOINT_PORT,\n\t\t);\n\t\tconst readyTimeout = opts.readyTimeout ?? DEFAULT_LOCAL_READY_TIMEOUT;\n\n\t\tyield* setCurrentPluginPhase('waiting for Sui RPC, faucet, and GraphQL');\n\t\tyield* waitForReady(directRpcUrl, directFaucetUrl, directGraphqlUrl, readyTimeout).pipe(\n\t\t\tEffect.annotateLogs({ 'sui.container': handle.name }),\n\t\t);\n\n\t\tconst sdkClient = new SuiGrpcClient({ baseUrl: directRpcUrl, network: 'localnet' });\n\n\t\t// ----- 4. Resolve chain id ------------------------------------------\n\t\tyield* setCurrentPluginPhase('fetching Sui chain id');\n\t\tconst chain = yield* sharedFetchChainId(sdkClient, {\n\t\t\tspan: 'devstack.plugin.sui.local.fetchChainId',\n\t\t});\n\n\t\t// ----- 5. waitForTransactionsReady (memoised) -----------------------\n\t\tyield* setCurrentPluginPhase('preparing Sui funds-ready gate');\n\t\tconst waitForTransactionsReady = yield* buildWaitForTransactionsReady(directFaucetUrl);\n\n\t\t// ----- 6. Assemble resolved SuiClient -------------------------------\n\t\t// Surface `buildImage` so package's path-(b) `docker run --rm`\n\t\t// build path can spawn a one-shot sui-cli container using the\n\t\t// SAME image we built/resolved here. Without this the package\n\t\t// plugin would have to re-resolve the image, doubling the\n\t\t// build-context hash work and risking digest drift.\n\t\tconst { client } = assembleSuiClient({\n\t\t\tsdkClient,\n\t\t\tchain,\n\t\t\trpcUrl,\n\t\t\tsdkRpcUrl: directRpcUrl,\n\t\t\tfaucetUrl,\n\t\t\tfundingFaucetUrl: directFaucetUrl,\n\t\t\tgraphqlUrl,\n\t\t\twaitForTransactionsReady,\n\t\t\tbuildImage: image,\n\t\t\thostGateway: {\n\t\t\t\trpcUrl: toDockerHostGatewayUrl(directRpcUrl),\n\t\t\t\tfaucetUrl: toDockerHostGatewayUrl(directFaucetUrl),\n\t\t\t\tgraphqlUrl: toDockerHostGatewayUrl(directGraphqlUrl),\n\t\t\t},\n\t\t});\n\t\tconst resolved = makeResolvedNetwork({\n\t\t\tmode: 'local',\n\t\t\tchain,\n\t\t\trpc: rpcUrl,\n\t\t\tfaucet: faucetUrl,\n\t\t\tgraphql: graphqlUrl,\n\t\t\tsource: 'default',\n\t\t});\n\t\treturn {\n\t\t\tresolved,\n\t\t\tclient,\n\t\t\tclockAdvancer: noopClockAdvancer,\n\t\t};\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.sui.local.boot', { attributes: { 'devstack.plugin': 'sui' } }),\n\t);\n\n// ---------------------------------------------------------------------------\n// Image resolution — vendored Dockerfile build via `ContainerRuntime`\n// ---------------------------------------------------------------------------\n\nexport const resolveImage = (\n\truntime: ContainerRuntime,\n\topts: SuiLocalOptions,\n): Effect.Effect<ImageRef, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tif (opts.image && 'pull' in opts.image) {\n\t\t\tconst pullRef = opts.image.pull;\n\t\t\tif (runtime.pullImage === undefined) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t`sui local mode cannot pull image '${pullRef}' because the configured container runtime does not expose image pulls.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn yield* runtime\n\t\t\t\t.pullImage(pullRef)\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t\t`sui local mode failed to pull image '${pullRef}': ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t}\n\t\tconst version = opts.version ?? DEFAULT_SUI_VERSION;\n\t\tconst buildCtx =\n\t\t\topts.image && 'build' in opts.image\n\t\t\t\t? {\n\t\t\t\t\t\tcontextPath: opts.image.build.context,\n\t\t\t\t\t\tdockerfile: opts.image.build.dockerfile ?? 'Dockerfile',\n\t\t\t\t\t\tbuildArgs: { SUI_VERSION: version },\n\t\t\t\t\t}\n\t\t\t\t: suiCliImageBuildContext(version);\n\t\treturn yield* runtime\n\t\t\t.ensureImage(buildCtx)\n\t\t\t.pipe(\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t`sui image build failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.local.resolveImage'));\n\ninterface LocalValidatorContainerResult {\n\treadonly handle: ContainerHandle;\n\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n}\n\ninterface ResolvedPortMapping {\n\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n\treadonly release: Effect.Effect<void>;\n}\n\nexport const ensureLocalValidatorContainer = (\n\truntime: ContainerRuntime,\n\tportBroker: PortBroker,\n\timage: ImageRef,\n\tlabels: ContainerLabelTuple,\n\tcontainerName: string,\n\topts: SuiLocalOptions,\n): Effect.Effect<LocalValidatorContainerResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst reusablePorts =\n\t\t\topts.ports === undefined\n\t\t\t\t? yield* findReusablePortMapping(runtime, labels, containerName)\n\t\t\t\t: undefined;\n\t\tif (reusablePorts !== undefined) {\n\t\t\treturn yield* ensureLocalValidatorContainerAttempt({\n\t\t\t\truntime,\n\t\t\t\tportBroker,\n\t\t\t\timage,\n\t\t\t\tlabels,\n\t\t\t\tcontainerName,\n\t\t\t\topts,\n\t\t\t\tports: reusablePorts,\n\t\t\t\tattempt: 0,\n\t\t\t\treconciliation: 'adopt-existing',\n\t\t\t});\n\t\t}\n\t\treturn yield* ensureLocalValidatorContainerWithFreshPorts({\n\t\t\truntime,\n\t\t\tportBroker,\n\t\t\timage,\n\t\t\tlabels,\n\t\t\tcontainerName,\n\t\t\topts,\n\t\t\tattempt: 0,\n\t\t\treconciliation: opts.ports ? 'exact' : 'adopt-existing',\n\t\t});\n\t});\n\ninterface EnsureLocalValidatorContainerBase {\n\treadonly runtime: ContainerRuntime;\n\treadonly portBroker: PortBroker;\n\treadonly image: ImageRef;\n\treadonly labels: ContainerLabelTuple;\n\treadonly containerName: string;\n\treadonly opts: SuiLocalOptions;\n}\n\nconst ensureLocalValidatorContainerWithFreshPorts = (\n\tparams: EnsureLocalValidatorContainerBase & {\n\t\treadonly attempt: number;\n\t\treadonly reconciliation: PortBindingReconciliation;\n\t},\n): Effect.Effect<LocalValidatorContainerResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst mapping = yield* resolvePortMappingWithRelease(params.portBroker, params.opts.ports);\n\t\treturn yield* ensureLocalValidatorContainerAttempt({\n\t\t\t...params,\n\t\t\tports: mapping.ports,\n\t\t\treleasePorts: mapping.release,\n\t\t});\n\t});\n\nconst ensureLocalValidatorContainerAttempt = (\n\tparams: EnsureLocalValidatorContainerBase & {\n\t\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n\t\treadonly releasePorts?: Effect.Effect<void>;\n\t\treadonly attempt: number;\n\t\treadonly reconciliation: PortBindingReconciliation;\n\t},\n): Effect.Effect<LocalValidatorContainerResult, SuiPluginError, Scope.Scope> =>\n\tensureManagedContainer({\n\t\truntime: params.runtime,\n\t\tlabels: params.labels,\n\t\tspec: {\n\t\t\tname: params.containerName,\n\t\t\timage: params.image,\n\t\t\t// Keep the writable layer only after clean exits. If Docker\n\t\t\t// escalates a previous stop to SIGKILL (137), resume can hang\n\t\t\t// in RocksDB/checkpoint recovery with no RPC/faucet probes.\n\t\t\t// `on-failure` routes that stale layer to recreate while still\n\t\t\t// warm-resuming normal exit 0 / 130 stops. The longer grace\n\t\t\t// gives the entrypoint's SIGINT forwarding time to drain.\n\t\t\trecreate: 'on-failure',\n\t\t\tstopGraceSeconds: LOCAL_VALIDATOR_STOP_GRACE_SECONDS,\n\t\t\tports: params.ports,\n\t\t\tportBindingReconciliation: params.reconciliation,\n\t\t},\n\t\tmapError: (cause) => cause,\n\t}).pipe(\n\t\tEffect.map((handle) => ({ handle, ports: params.ports })),\n\t\tEffect.catch((cause: ContainerRuntimeError) => {\n\t\t\tif (\n\t\t\t\tparams.opts.ports === undefined &&\n\t\t\t\tcause.reason === 'publish-port-conflict' &&\n\t\t\t\tparams.attempt < MAX_DOCKER_PUBLISH_PORT_RETRIES\n\t\t\t) {\n\t\t\t\treturn (params.releasePorts ?? Effect.void).pipe(\n\t\t\t\t\tEffect.andThen(\n\t\t\t\t\t\tensureLocalValidatorContainerWithFreshPorts({\n\t\t\t\t\t\t\t...params,\n\t\t\t\t\t\t\tattempt: params.attempt + 1,\n\t\t\t\t\t\t\treconciliation: 'exact',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Effect.fail(\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'container-start',\n\t\t\t\t\t`sui-validator container failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t);\n\t\t}),\n\t);\n\n// ---------------------------------------------------------------------------\n// Port mapping — host:container pairs\n// ---------------------------------------------------------------------------\n\nexport const resolvePortMapping = (\n\tportBroker: PortBroker,\n\toverride: Readonly<Record<number, number>> | undefined,\n): Effect.Effect<ReadonlyArray<ContainerPortPublish>, SuiPluginError, Scope.Scope> =>\n\tresolvePortMappingWithRelease(portBroker, override).pipe(Effect.map((mapping) => mapping.ports));\n\nconst resolvePortMappingWithRelease = (\n\tportBroker: PortBroker,\n\toverride: Readonly<Record<number, number>> | undefined,\n): Effect.Effect<ResolvedPortMapping, SuiPluginError, Scope.Scope> => {\n\tconst pick = (containerPort: number, fallback: number): number => {\n\t\tif (!override) return fallback;\n\t\tconst hit = override[containerPort];\n\t\treturn typeof hit === 'number' ? hit : fallback;\n\t};\n\tif (override) {\n\t\treturn Effect.succeed({\n\t\t\tports: [\n\t\t\t\tportPublish(CONTAINER_RPC_PORT, pick(CONTAINER_RPC_PORT, DEFAULT_HOST_RPC_PORT)),\n\t\t\t\tportPublish(CONTAINER_FAUCET_PORT, pick(CONTAINER_FAUCET_PORT, DEFAULT_HOST_FAUCET_PORT)),\n\t\t\t\tportPublish(\n\t\t\t\t\tCONTAINER_GRAPHQL_PORT,\n\t\t\t\t\tpick(CONTAINER_GRAPHQL_PORT, DEFAULT_HOST_GRAPHQL_PORT),\n\t\t\t\t),\n\t\t\t],\n\t\t\trelease: Effect.void,\n\t\t});\n\t}\n\treturn Effect.gen(function* () {\n\t\tconst rpc = yield* allocatePort(portBroker, 'rpc', DEFAULT_HOST_RPC_PORT, 'rpc');\n\t\tconst faucet = yield* allocatePort(portBroker, 'http', DEFAULT_HOST_FAUCET_PORT, 'faucet');\n\t\tconst graphql = yield* allocatePort(portBroker, 'rpc', DEFAULT_HOST_GRAPHQL_PORT, 'graphql');\n\t\treturn {\n\t\t\tports: [\n\t\t\t\tportPublish(CONTAINER_RPC_PORT, rpc.port),\n\t\t\t\tportPublish(CONTAINER_FAUCET_PORT, faucet.port),\n\t\t\t\tportPublish(CONTAINER_GRAPHQL_PORT, graphql.port),\n\t\t\t],\n\t\t\trelease: Effect.all([rpc.release, faucet.release, graphql.release], { discard: true }),\n\t\t};\n\t});\n};\n\nexport const resolvePublishedPortMapping = (\n\trequested: ReadonlyArray<ContainerPortPublish>,\n\tactual: ReadonlyArray<ContainerPortPublish> | undefined,\n): ReadonlyArray<ContainerPortPublish> => [\n\tpickPublishedPort(requested, actual, CONTAINER_RPC_PORT, DEFAULT_HOST_RPC_PORT),\n\tpickPublishedPort(requested, actual, CONTAINER_FAUCET_PORT, DEFAULT_HOST_FAUCET_PORT),\n\tpickPublishedPort(requested, actual, CONTAINER_GRAPHQL_PORT, DEFAULT_HOST_GRAPHQL_PORT),\n];\n\nconst pickPublishedPort = (\n\trequested: ReadonlyArray<ContainerPortPublish>,\n\tactual: ReadonlyArray<ContainerPortPublish> | undefined,\n\tcontainerPort: number,\n\tfallbackHostPort: number,\n): ContainerPortPublish =>\n\tactual?.find((port) => port.containerPort === containerPort) ??\n\trequested.find((port) => port.containerPort === containerPort) ??\n\tportPublish(containerPort, fallbackHostPort);\n\nexport const selectReusablePortMapping = (\n\thandles: ReadonlyArray<ContainerHandle>,\n\tcontainerName: string,\n): ReadonlyArray<ContainerPortPublish> | undefined => {\n\tconst ports = handles.find((handle) => handle.name === containerName)?.ports;\n\tif (!hasSuiPortMapping(ports)) return undefined;\n\treturn resolvePublishedPortMapping([], ports);\n};\n\nconst findReusablePortMapping = (\n\truntime: ContainerRuntime,\n\tlabels: ContainerLabelTuple,\n\tcontainerName: string,\n): Effect.Effect<ReadonlyArray<ContainerPortPublish> | undefined, SuiPluginError> =>\n\truntime.inspectByLabels(labels).pipe(\n\t\tEffect.map((handles) => selectReusablePortMapping(handles, containerName)),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui local mode: failed to inspect existing validator container: ${cause.reason}: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\n\nconst hasSuiPortMapping = (\n\tports: ReadonlyArray<ContainerPortPublish> | undefined,\n): ports is ReadonlyArray<ContainerPortPublish> =>\n\tports !== undefined &&\n\tports.some((port) => port.containerPort === CONTAINER_RPC_PORT) &&\n\tports.some((port) => port.containerPort === CONTAINER_FAUCET_PORT) &&\n\tports.some((port) => port.containerPort === CONTAINER_GRAPHQL_PORT);\n\nconst portPublish = (containerPort: number, hostPort: number): ContainerPortPublish => ({\n\tcontainerPort,\n\thostPort,\n\thostIp: DOCKER_PUBLISH_HOST,\n});\n\nconst allocatePort = (\n\tportBroker: PortBroker,\n\tkind: PortKind,\n\tpreferredPort: number | undefined,\n\tlabel: 'rpc' | 'faucet' | 'graphql',\n): Effect.Effect<AllocatedPort, SuiPluginError, Scope.Scope> => {\n\tconst allocate = (\n\t\thint: number | undefined,\n\t): Effect.Effect<AllocatedPort, SuiPluginError, Scope.Scope> =>\n\t\tportBroker\n\t\t\t.allocate({\n\t\t\t\tkind,\n\t\t\t\t...(hint === undefined ? {} : { preferredPort: hint }),\n\t\t\t\tprobeHost: DOCKER_PUBLISH_HOST,\n\t\t\t})\n\t\t\t.pipe(\n\t\t\t\tEffect.catchTag('PortBrokerError', (cause) =>\n\t\t\t\t\thint !== undefined && cause.reason === 'preferred-busy'\n\t\t\t\t\t\t? portBroker.allocate({ kind, probeHost: DOCKER_PUBLISH_HOST })\n\t\t\t\t\t\t: Effect.fail(cause),\n\t\t\t\t),\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'port-allocate',\n\t\t\t\t\t\t`sui local mode: failed to allocate ${label} host port ` +\n\t\t\t\t\t\t\t`(preferred ${hint ?? 'auto'}): ${cause.detail}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\treturn allocate(preferredPort);\n};\n\n// ---------------------------------------------------------------------------\n// Ready-probe coordination\n// ---------------------------------------------------------------------------\n\n/** Coordinated readiness gate. Both RPC + faucet must respond within\n * the outer deadline; each probe has its own per-fetch deadline so a\n * wedged endpoint surfaces by name. */\nconst waitForReady = (\n\trpcUrl: string,\n\tfaucetUrl: string,\n\tgraphqlUrl: string,\n\treadyTimeout: Duration.Duration,\n): Effect.Effect<void, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tconst readyTimeoutMs = Duration.toMillis(readyTimeout);\n\t\tconst rpcProbe: Effect.Effect<void, SuiPluginError> = waitForHttpEndpoint({\n\t\t\tendpoint: rpcUrl,\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\trequestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,\n\t\t\trequestInit: {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'content-type': 'application/json' },\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tjsonrpc: '2.0',\n\t\t\t\t\tid: 1,\n\t\t\t\t\tmethod: 'sui_getLatestCheckpointSequenceNumber',\n\t\t\t\t\tparams: [],\n\t\t\t\t}),\n\t\t\t},\n\t\t\tvalidate: async (response) => {\n\t\t\t\tif (!response.ok) return false;\n\t\t\t\tconst body = (await response.json()) as { readonly result?: unknown };\n\t\t\t\treturn typeof body.result === 'string' || typeof body.result === 'number';\n\t\t\t},\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause): SuiPluginError =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'rpc-probe',\n\t\t\t\t\t\t`sui local mode: RPC endpoint ${rpcUrl} did not become ready within ` +\n\t\t\t\t\t\t\t`${readyTimeoutMs}ms: ${stringifyCause(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.withSpan('devstack.plugin.sui.local.probe.rpc'),\n\t\t);\n\n\t\t// Faucet socket-level liveness — `GET /` returns \"OK\" as soon as\n\t\t// the HTTP server is bound. We do NOT POST `/v2/gas` here; that's\n\t\t// the funds-ready probe, which is paid for lazily on first call.\n\t\tconst faucetProbe: Effect.Effect<void, SuiPluginError> = waitForHttpEndpoint({\n\t\t\tendpoint: faucetUrl,\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\trequestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,\n\t\t\tvalidate: (response) => response.status < 500,\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause): SuiPluginError =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'faucet-probe',\n\t\t\t\t\t\t`sui local mode: faucet endpoint ${faucetUrl} did not become ready within ` +\n\t\t\t\t\t\t\t`${readyTimeoutMs}ms: ${stringifyCause(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.withSpan('devstack.plugin.sui.local.probe.faucet'),\n\t\t);\n\n\t\tconst graphqlProbe: Effect.Effect<void, SuiPluginError> = waitForHttpEndpoint({\n\t\t\tendpoint: graphqlUrl,\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\trequestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,\n\t\t\tvalidate: (response) => response.status < 500,\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause): SuiPluginError =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'graphql-probe',\n\t\t\t\t\t\t`sui local mode: GraphQL endpoint ${graphqlUrl} did not become ready within ` +\n\t\t\t\t\t\t\t`${readyTimeoutMs}ms: ${stringifyCause(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.withSpan('devstack.plugin.sui.local.probe.graphql'),\n\t\t);\n\n\t\tyield* Effect.all([rpcProbe, faucetProbe, graphqlProbe], { concurrency: 'unbounded' }).pipe(\n\t\t\tEffect.asVoid,\n\t\t);\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.local.waitForReady'));\n\n// Chain-id fetch + waitForTransactionsReady builders live in\n// `shared-boot.ts` — see imports at the top of this file.\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst routedSuiUrl = (\n\tidentity: Identity,\n\tendpointName: string,\n\tport: number,\n): Effect.Effect<string, SuiPluginError> =>\n\trouterHostname(identity, endpointName).pipe(\n\t\tEffect.map((hostname) => renderUrl({ protocol: 'http', hostname, port })),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui local mode: failed to construct router URL for ${endpointName}: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\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":"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"}
1
+ {"version":3,"file":"local.mjs","names":["sharedFetchChainId"],"sources":["../../../../src/plugins/sui/mode/local.ts"],"sourcesContent":["// Sui plugin — local-container mode.\n//\n// In-stack Sui validator + faucet, running in the supervised docker\n// stack. Used during normal dev loops when the developer wants fresh,\n// fast, throwaway chain state with a working faucet.\n//\n// Boot sequence (load-bearing order):\n//\n// 1. Resolve image — vendored Dockerfile build via the\n// ContainerRuntime contract (caller `image` override honoured for\n// `{build}`; `{pull}` is deferred — see stub list in the README).\n// 2. Allocate + ensure container — `sui start --with-faucet=0.0.0.0:9123\n// --with-graphql=0.0.0.0:9125` with direct host port-publishing\n// for internal boot probes. User-facing URLs are router-fronted\n// named hosts; the direct host ports intentionally live in the\n// high private windows so they do not collide with router\n// entrypoints.\n// RecreatePolicy is `on-failure` so the writable layer (chain\n// state at `/root/.sui`) survives clean stop/start cycles, but an\n// unclean SIGKILL/137 exit recreates instead of resuming a suspect\n// RocksDB/checkpoint state. The image's entrypoint forwards SIGINT\n// to a non-PID-1 sui child so clean shutdown (RocksDB checkpoint\n// drain → exit 0/130) is the normal case.\n// 3. Ready probe — RPC `getChainIdentifier`, faucet `GET /`, and\n// GraphQL HTTP liveness. Per-fetch deadline + outer deadline.\n// 4. Fetch chain id from the now-responsive client (bounded timeout).\n// 5. Build `waitForTransactionsReady` — `Effect.cached` against a\n// real faucet funding tx; first failure caches for the scope.\n// Manual `invalidate` clears the memo.\n// 6. Return resolved `SuiClient`. Auto-tick is the no-op advancer\n// (localnet drives its own consensus).\n//\n// Faucet socket-level readiness does NOT imply funds-transferability.\n// The first `waitForTransactionsReady.wait` POSTs a real funding tx,\n// retrying on body-level `{Failure}` responses during the post-RPC /\n// pre-fund window.\n//\n// What this body deliberately defers:\n// - Postgres indexer sidecar — GraphQL is enabled by `sui start` and\n// routed as a first-class endpoint, but no separate postgres\n// lifecycle is supervised here.\n// - Snapshot capture — the framework exists in the plugin's\n// snapshot.ts; this body produces the running container that the\n// orchestrator captures.\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\n\nimport type {\n\tContainerHandle,\n\tContainerRuntime,\n\tContainerRuntimeError,\n\tImageRef,\n\tContainerPortPublish,\n\tPortBindingReconciliation,\n} from '../../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../../contracts/snapshotable.ts';\nimport type { Identity } from '../../../substrate/identity.ts';\nimport type { AllocatedPort, PortBroker } from '../../../substrate/runtime/port-broker/index.ts';\nimport { waitForHttpEndpoint } from '../../../substrate/runtime/http-probe.ts';\nimport { setCurrentPluginPhase } from '../../../substrate/runtime/current-plugin.ts';\nimport { ensureManagedContainer } from '../../../substrate/runtime/managed-container.ts';\nimport { SpanAttr } from '../../../substrate/runtime/observability/spans.ts';\nimport { renderUrl, routedHostname } from '../../../substrate/runtime/routed-url.ts';\nimport {\n\tDEFAULT_SUI_CLI_VERSION,\n\tsuiCliImageBuildContext,\n} from '../../../substrate/runtime/sui-move-build/index.ts';\nimport { suiPluginError, type SuiConfigError, type SuiPluginError } from '../errors.ts';\nimport { formatUnknownError } from '../../../substrate/runtime/format-unknown-error.ts';\nimport type { ResolvedSuiNetwork } from '../network-resolver.ts';\nimport { SuiSpans } from '../spans.ts';\nimport {\n\tSUI_FAUCET_ENTRYPOINT_PORT,\n\tSUI_FAUCET_ENDPOINT_NAME,\n\tSUI_GRAPHQL_ENDPOINT_NAME,\n\tSUI_GRAPHQL_ENTRYPOINT_PORT,\n\tSUI_RPC_ENDPOINT_NAME,\n\tSUI_RPC_ENTRYPOINT_PORT,\n} from '../routable.ts';\nimport type { SuiClient } from './shared.ts';\nimport { toDockerHostGatewayUrl } from './shared.ts';\nimport {\n\tassembleSuiClient,\n\tbuildWaitForTransactionsReady,\n\tfetchChainId as sharedFetchChainId,\n\tmakeResolvedNetwork,\n} from './shared-boot.ts';\nimport type { SuiLocalOptions } from './spec.ts';\n\n/** Default ready-probe timeout for localnet. The validator's cold\n * start runs genesis + faucet bootstrap; 60 s is the documented\n * ceiling. */\nexport const DEFAULT_LOCAL_READY_TIMEOUT = Duration.seconds(60);\n\n/** Default sui validator binary version pinned by the vendored\n * `images/sui/` Dockerfile. The build arg `SUI_VERSION` is threaded\n * through to the release-tarball URL. Bump in lockstep with matching\n * Walrus / Seal versions (else the Move package ABIs drift). */\nexport const DEFAULT_SUI_VERSION = DEFAULT_SUI_CLI_VERSION;\n\n// In-container ports the sui binary binds on. These match the router\n// entrypoint ports; direct host publishes below use different high\n// ports so Traefik owns the public listener ports.\nconst CONTAINER_RPC_PORT = SUI_RPC_ENTRYPOINT_PORT;\nconst CONTAINER_FAUCET_PORT = SUI_FAUCET_ENTRYPOINT_PORT;\nconst CONTAINER_GRAPHQL_PORT = SUI_GRAPHQL_ENTRYPOINT_PORT;\n\n// Default host ports. Without `opts.ports`, these are preferences\n// brokered against the kernel before Docker publishes them.\nexport const DEFAULT_HOST_RPC_PORT = 51000;\nexport const DEFAULT_HOST_FAUCET_PORT = 50000;\nexport const DEFAULT_HOST_GRAPHQL_PORT = 51001;\nconst DOCKER_PUBLISH_HOST = '0.0.0.0' as const;\nexport const MAX_DOCKER_PUBLISH_PORT_RETRIES = 3;\nexport const LOCAL_VALIDATOR_STOP_GRACE_SECONDS = 30;\n\n/** Per-fetch deadline for the ready-probe HTTP calls. Without it a\n * hung fetch would block the outer ready deadline with no signal\n * about which probe wedged. */\nconst PROBE_FETCH_TIMEOUT_MS = 3000;\n\n/** Resolved local-mode boot artifacts. */\nexport interface LocalModeBootResult {\n\treadonly resolved: ResolvedSuiNetwork;\n\treadonly client: SuiClient;\n}\n\n/**\n * Build the local-mode boot Effect.\n *\n * `identity` is threaded in by the caller (the plugin barrel's acquire\n * body, which has access to the substrate's `IdentityContext` via the\n * outer composition layer); the body uses it to stamp the canonical\n * container label tuple so sweep / inventory are name-blind.\n *\n * `{pull}`, `{build}`, and vendored-build image branches are wired.\n */\nexport const bootLocalMode = (\n\truntime: ContainerRuntime,\n\tidentity: Identity,\n\tportBroker: PortBroker,\n\topts: SuiLocalOptions,\n): Effect.Effect<LocalModeBootResult, SuiPluginError | SuiConfigError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\t// ----- 1. Resolve image ---------------------------------------------\n\t\tyield* setCurrentPluginPhase('resolving Sui local image');\n\t\tconst image = yield* resolveImage(runtime, identity, opts);\n\n\t\t// ----- 2. Allocate ports + ensure container --------------------------\n\t\tyield* setCurrentPluginPhase('creating Sui validator container');\n\t\tconst labels: ContainerLabelTuple = {\n\t\t\tapp: identity.app,\n\t\t\tstack: identity.stack,\n\t\t\tplugin: 'sui',\n\t\t\trole: 'validator',\n\t\t};\n\t\tconst containerName = `devstack-${identity.app}-${identity.stack}-sui-validator`;\n\t\tconst { handle, ports } = yield* ensureLocalValidatorContainer(\n\t\t\truntime,\n\t\t\tportBroker,\n\t\t\timage,\n\t\t\tlabels,\n\t\t\tcontainerName,\n\t\t\topts,\n\t\t);\n\n\t\t// ----- 3. Ready probes ----------------------------------------------\n\t\tconst publishedPorts = resolvePublishedPortMapping(ports, handle.ports);\n\t\tconst directRpcUrl = `http://127.0.0.1:${publishedPorts[0]!.hostPort}`;\n\t\tconst directFaucetUrl = `http://127.0.0.1:${publishedPorts[1]!.hostPort}`;\n\t\tconst directGraphqlUrl = `http://127.0.0.1:${publishedPorts[2]!.hostPort}`;\n\t\tconst rpcUrl = yield* routedSuiUrl(identity, SUI_RPC_ENDPOINT_NAME, SUI_RPC_ENTRYPOINT_PORT);\n\t\tconst faucetUrl = yield* routedSuiUrl(\n\t\t\tidentity,\n\t\t\tSUI_FAUCET_ENDPOINT_NAME,\n\t\t\tSUI_FAUCET_ENTRYPOINT_PORT,\n\t\t);\n\t\tconst graphqlUrl = yield* routedSuiUrl(\n\t\t\tidentity,\n\t\t\tSUI_GRAPHQL_ENDPOINT_NAME,\n\t\t\tSUI_GRAPHQL_ENTRYPOINT_PORT,\n\t\t);\n\t\tconst readyTimeout = opts.readyTimeout ?? DEFAULT_LOCAL_READY_TIMEOUT;\n\n\t\tyield* setCurrentPluginPhase('waiting for Sui RPC, faucet, and GraphQL');\n\t\tyield* waitForReady(directRpcUrl, directFaucetUrl, directGraphqlUrl, readyTimeout).pipe(\n\t\t\tEffect.annotateLogs({ [SuiSpans.container]: handle.name }),\n\t\t);\n\n\t\tconst sdkClient = new SuiGrpcClient({ baseUrl: directRpcUrl, network: 'localnet' });\n\n\t\t// ----- 4. Resolve chain id ------------------------------------------\n\t\tyield* setCurrentPluginPhase('fetching Sui chain id');\n\t\tconst chain = yield* sharedFetchChainId(sdkClient, {\n\t\t\tspan: 'devstack.plugin.sui.local.fetchChainId',\n\t\t});\n\n\t\t// ----- 5. waitForTransactionsReady (memoised) -----------------------\n\t\tyield* setCurrentPluginPhase('preparing Sui funds-ready gate');\n\t\tconst waitForTransactionsReady = yield* buildWaitForTransactionsReady(directFaucetUrl);\n\n\t\t// ----- 6. Assemble resolved SuiClient -------------------------------\n\t\t// Surface `buildImage` so package's path-(b) `docker run --rm`\n\t\t// build path can spawn a one-shot sui-cli container using the\n\t\t// SAME image we built/resolved here. Without this the package\n\t\t// plugin would have to re-resolve the image, doubling the\n\t\t// build-context hash work and risking digest drift.\n\t\tconst { client } = yield* assembleSuiClient({\n\t\t\tsdkClient,\n\t\t\tchain,\n\t\t\trpcUrl,\n\t\t\tfaucetUrl,\n\t\t\tfundingFaucetUrl: directFaucetUrl,\n\t\t\tgraphqlUrl,\n\t\t\twaitForTransactionsReady,\n\t\t\tbuildImage: image,\n\t\t\thostGateway: {\n\t\t\t\trpcUrl: toDockerHostGatewayUrl(directRpcUrl),\n\t\t\t\tfaucetUrl: toDockerHostGatewayUrl(directFaucetUrl),\n\t\t\t\tgraphqlUrl: toDockerHostGatewayUrl(directGraphqlUrl),\n\t\t\t},\n\t\t});\n\t\tconst resolved = makeResolvedNetwork({\n\t\t\tmode: 'local',\n\t\t\tchain,\n\t\t\trpc: rpcUrl,\n\t\t\tfaucet: faucetUrl,\n\t\t\tgraphql: graphqlUrl,\n\t\t\tsource: 'default',\n\t\t});\n\t\treturn {\n\t\t\tresolved,\n\t\t\tclient,\n\t\t};\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.sui.local.boot', { attributes: { [SpanAttr.plugin]: 'sui' } }),\n\t);\n\n// ---------------------------------------------------------------------------\n// Image resolution — vendored Dockerfile build via `ContainerRuntime`\n// ---------------------------------------------------------------------------\n\nexport const resolveImage = (\n\truntime: ContainerRuntime,\n\tidentity: Identity,\n\topts: SuiLocalOptions,\n): Effect.Effect<ImageRef, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tif (opts.image && 'pull' in opts.image) {\n\t\t\tconst pullRef = opts.image.pull;\n\t\t\tif (runtime.pullImage === undefined) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t`sui local mode cannot pull image '${pullRef}' because the configured container runtime does not expose image pulls.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn yield* runtime\n\t\t\t\t.pullImage(pullRef)\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t\t`sui local mode failed to pull image '${pullRef}': ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t}\n\t\tconst version = opts.version ?? DEFAULT_SUI_VERSION;\n\t\tconst owner = {\n\t\t\tapp: identity.app,\n\t\t\tstack: identity.stack,\n\t\t\tplugin: 'sui',\n\t\t\trole: 'validator',\n\t\t} as const;\n\t\tconst buildCtx =\n\t\t\topts.image && 'build' in opts.image\n\t\t\t\t? {\n\t\t\t\t\t\tcontextPath: opts.image.build.context,\n\t\t\t\t\t\tdockerfile: opts.image.build.dockerfile ?? 'Dockerfile',\n\t\t\t\t\t\tbuildArgs: { SUI_VERSION: version },\n\t\t\t\t\t\towner,\n\t\t\t\t\t}\n\t\t\t\t: { ...suiCliImageBuildContext(version), owner };\n\t\treturn yield* runtime\n\t\t\t.ensureImage(buildCtx)\n\t\t\t.pipe(\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'image-build',\n\t\t\t\t\t\t`sui image build failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.local.resolveImage'));\n\ninterface LocalValidatorContainerResult {\n\treadonly handle: ContainerHandle;\n\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n}\n\ninterface ResolvedPortMapping {\n\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n\treadonly release: Effect.Effect<void>;\n}\n\nexport const ensureLocalValidatorContainer = (\n\truntime: ContainerRuntime,\n\tportBroker: PortBroker,\n\timage: ImageRef,\n\tlabels: ContainerLabelTuple,\n\tcontainerName: string,\n\topts: SuiLocalOptions,\n): Effect.Effect<LocalValidatorContainerResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst reusablePorts =\n\t\t\topts.ports === undefined\n\t\t\t\t? yield* findReusablePortMapping(runtime, labels, containerName)\n\t\t\t\t: undefined;\n\t\tif (reusablePorts !== undefined) {\n\t\t\treturn yield* ensureLocalValidatorContainerAttempt({\n\t\t\t\truntime,\n\t\t\t\tportBroker,\n\t\t\t\timage,\n\t\t\t\tlabels,\n\t\t\t\tcontainerName,\n\t\t\t\topts,\n\t\t\t\tports: reusablePorts,\n\t\t\t\tattempt: 0,\n\t\t\t\treconciliation: 'adopt-existing',\n\t\t\t});\n\t\t}\n\t\treturn yield* ensureLocalValidatorContainerWithFreshPorts({\n\t\t\truntime,\n\t\t\tportBroker,\n\t\t\timage,\n\t\t\tlabels,\n\t\t\tcontainerName,\n\t\t\topts,\n\t\t\tattempt: 0,\n\t\t\treconciliation: opts.ports ? 'exact' : 'adopt-existing',\n\t\t});\n\t});\n\ninterface EnsureLocalValidatorContainerBase {\n\treadonly runtime: ContainerRuntime;\n\treadonly portBroker: PortBroker;\n\treadonly image: ImageRef;\n\treadonly labels: ContainerLabelTuple;\n\treadonly containerName: string;\n\treadonly opts: SuiLocalOptions;\n}\n\nconst ensureLocalValidatorContainerWithFreshPorts = (\n\tparams: EnsureLocalValidatorContainerBase & {\n\t\treadonly attempt: number;\n\t\treadonly reconciliation: PortBindingReconciliation;\n\t},\n): Effect.Effect<LocalValidatorContainerResult, SuiPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst mapping = yield* resolvePortMappingWithRelease(params.portBroker, params.opts.ports);\n\t\treturn yield* ensureLocalValidatorContainerAttempt({\n\t\t\t...params,\n\t\t\tports: mapping.ports,\n\t\t\treleasePorts: mapping.release,\n\t\t});\n\t});\n\nconst ensureLocalValidatorContainerAttempt = (\n\tparams: EnsureLocalValidatorContainerBase & {\n\t\treadonly ports: ReadonlyArray<ContainerPortPublish>;\n\t\treadonly releasePorts?: Effect.Effect<void>;\n\t\treadonly attempt: number;\n\t\treadonly reconciliation: PortBindingReconciliation;\n\t},\n): Effect.Effect<LocalValidatorContainerResult, SuiPluginError, Scope.Scope> =>\n\tensureManagedContainer({\n\t\truntime: params.runtime,\n\t\tlabels: params.labels,\n\t\tspec: {\n\t\t\tname: params.containerName,\n\t\t\timage: params.image,\n\t\t\t// Keep the writable layer only after clean exits. If Docker\n\t\t\t// escalates a previous stop to SIGKILL (137), resume can hang\n\t\t\t// in RocksDB/checkpoint recovery with no RPC/faucet probes.\n\t\t\t// `on-failure` routes that stale layer to recreate while still\n\t\t\t// warm-resuming normal exit 0 / 130 stops. The longer grace\n\t\t\t// gives the entrypoint's SIGINT forwarding time to drain.\n\t\t\trecreate: 'on-failure',\n\t\t\tstopGraceSeconds: LOCAL_VALIDATOR_STOP_GRACE_SECONDS,\n\t\t\tports: params.ports,\n\t\t\tportBindingReconciliation: params.reconciliation,\n\t\t},\n\t\tmapError: (cause) => cause,\n\t}).pipe(\n\t\tEffect.map((handle) => ({ handle, ports: params.ports })),\n\t\tEffect.catch((cause: ContainerRuntimeError) => {\n\t\t\tif (\n\t\t\t\tparams.opts.ports === undefined &&\n\t\t\t\tcause.reason === 'publish-port-conflict' &&\n\t\t\t\tparams.attempt < MAX_DOCKER_PUBLISH_PORT_RETRIES\n\t\t\t) {\n\t\t\t\treturn (params.releasePorts ?? Effect.void).pipe(\n\t\t\t\t\tEffect.andThen(\n\t\t\t\t\t\tensureLocalValidatorContainerWithFreshPorts({\n\t\t\t\t\t\t\t...params,\n\t\t\t\t\t\t\tattempt: params.attempt + 1,\n\t\t\t\t\t\t\treconciliation: 'exact',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Effect.fail(\n\t\t\t\tsuiPluginError(\n\t\t\t\t\t'container-start',\n\t\t\t\t\t`sui-validator container failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t),\n\t\t\t);\n\t\t}),\n\t);\n\n// ---------------------------------------------------------------------------\n// Port mapping — host:container pairs\n// ---------------------------------------------------------------------------\n\n// Exported test entry point: resolves the host:container port pairs\n// without surfacing the release handle (the live boot path uses\n// `resolvePortMappingWithRelease` directly to retain the release).\nexport const resolvePortMapping = (\n\tportBroker: PortBroker,\n\toverride: Readonly<Record<number, number>> | undefined,\n): Effect.Effect<ReadonlyArray<ContainerPortPublish>, SuiPluginError, Scope.Scope> =>\n\tresolvePortMappingWithRelease(portBroker, override).pipe(Effect.map((mapping) => mapping.ports));\n\nconst resolvePortMappingWithRelease = (\n\tportBroker: PortBroker,\n\toverride: Readonly<Record<number, number>> | undefined,\n): Effect.Effect<ResolvedPortMapping, SuiPluginError, Scope.Scope> => {\n\tconst pick = (containerPort: number, fallback: number): number => {\n\t\tif (!override) return fallback;\n\t\tconst hit = override[containerPort];\n\t\treturn typeof hit === 'number' ? hit : fallback;\n\t};\n\tif (override) {\n\t\treturn Effect.succeed({\n\t\t\tports: [\n\t\t\t\tportPublish(CONTAINER_RPC_PORT, pick(CONTAINER_RPC_PORT, DEFAULT_HOST_RPC_PORT)),\n\t\t\t\tportPublish(CONTAINER_FAUCET_PORT, pick(CONTAINER_FAUCET_PORT, DEFAULT_HOST_FAUCET_PORT)),\n\t\t\t\tportPublish(\n\t\t\t\t\tCONTAINER_GRAPHQL_PORT,\n\t\t\t\t\tpick(CONTAINER_GRAPHQL_PORT, DEFAULT_HOST_GRAPHQL_PORT),\n\t\t\t\t),\n\t\t\t],\n\t\t\trelease: Effect.void,\n\t\t});\n\t}\n\treturn Effect.gen(function* () {\n\t\tconst rpc = yield* allocatePort(portBroker, 'sui:rpc', DEFAULT_HOST_RPC_PORT, 'rpc');\n\t\tconst faucet = yield* allocatePort(\n\t\t\tportBroker,\n\t\t\t'sui:faucet',\n\t\t\tDEFAULT_HOST_FAUCET_PORT,\n\t\t\t'faucet',\n\t\t);\n\t\tconst graphql = yield* allocatePort(\n\t\t\tportBroker,\n\t\t\t'sui:graphql',\n\t\t\tDEFAULT_HOST_GRAPHQL_PORT,\n\t\t\t'graphql',\n\t\t);\n\t\treturn {\n\t\t\tports: [\n\t\t\t\tportPublish(CONTAINER_RPC_PORT, rpc.port),\n\t\t\t\tportPublish(CONTAINER_FAUCET_PORT, faucet.port),\n\t\t\t\tportPublish(CONTAINER_GRAPHQL_PORT, graphql.port),\n\t\t\t],\n\t\t\trelease: Effect.all([rpc.release, faucet.release, graphql.release], { discard: true }),\n\t\t};\n\t});\n};\n\nexport const resolvePublishedPortMapping = (\n\trequested: ReadonlyArray<ContainerPortPublish>,\n\tactual: ReadonlyArray<ContainerPortPublish> | undefined,\n): ReadonlyArray<ContainerPortPublish> => [\n\tpickPublishedPort(requested, actual, CONTAINER_RPC_PORT, DEFAULT_HOST_RPC_PORT),\n\tpickPublishedPort(requested, actual, CONTAINER_FAUCET_PORT, DEFAULT_HOST_FAUCET_PORT),\n\tpickPublishedPort(requested, actual, CONTAINER_GRAPHQL_PORT, DEFAULT_HOST_GRAPHQL_PORT),\n];\n\nconst pickPublishedPort = (\n\trequested: ReadonlyArray<ContainerPortPublish>,\n\tactual: ReadonlyArray<ContainerPortPublish> | undefined,\n\tcontainerPort: number,\n\tfallbackHostPort: number,\n): ContainerPortPublish =>\n\tactual?.find((port) => port.containerPort === containerPort) ??\n\trequested.find((port) => port.containerPort === containerPort) ??\n\tportPublish(containerPort, fallbackHostPort);\n\nexport const selectReusablePortMapping = (\n\thandles: ReadonlyArray<ContainerHandle>,\n\tcontainerName: string,\n): ReadonlyArray<ContainerPortPublish> | undefined => {\n\tconst ports = handles.find((handle) => handle.name === containerName)?.ports;\n\tif (!hasSuiPortMapping(ports)) return undefined;\n\treturn resolvePublishedPortMapping([], ports);\n};\n\nconst findReusablePortMapping = (\n\truntime: ContainerRuntime,\n\tlabels: ContainerLabelTuple,\n\tcontainerName: string,\n): Effect.Effect<ReadonlyArray<ContainerPortPublish> | undefined, SuiPluginError> =>\n\truntime.inspectByLabels(labels).pipe(\n\t\tEffect.map((handles) => selectReusablePortMapping(handles, containerName)),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui local mode: failed to inspect existing validator container: ${cause.reason}: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\n\nconst hasSuiPortMapping = (\n\tports: ReadonlyArray<ContainerPortPublish> | undefined,\n): ports is ReadonlyArray<ContainerPortPublish> =>\n\tports !== undefined &&\n\tports.some((port) => port.containerPort === CONTAINER_RPC_PORT) &&\n\tports.some((port) => port.containerPort === CONTAINER_FAUCET_PORT) &&\n\tports.some((port) => port.containerPort === CONTAINER_GRAPHQL_PORT);\n\nconst portPublish = (containerPort: number, hostPort: number): ContainerPortPublish => ({\n\tcontainerPort,\n\thostPort,\n\thostIp: DOCKER_PUBLISH_HOST,\n});\n\nconst allocatePort = (\n\tportBroker: PortBroker,\n\towner: string,\n\tpreferredPort: number | undefined,\n\tlabel: 'rpc' | 'faucet' | 'graphql',\n): Effect.Effect<AllocatedPort, SuiPluginError, Scope.Scope> => {\n\tconst allocate = (\n\t\thint: number | undefined,\n\t): Effect.Effect<AllocatedPort, SuiPluginError, Scope.Scope> =>\n\t\tportBroker\n\t\t\t.allocate({\n\t\t\t\towner,\n\t\t\t\t...(hint === undefined ? {} : { preferredPort: hint }),\n\t\t\t\tprobeHost: DOCKER_PUBLISH_HOST,\n\t\t\t})\n\t\t\t.pipe(\n\t\t\t\tEffect.catchTag('PortBrokerError', (cause) =>\n\t\t\t\t\thint !== undefined && cause.reason === 'preferred-busy'\n\t\t\t\t\t\t? portBroker.allocate({ owner, probeHost: DOCKER_PUBLISH_HOST })\n\t\t\t\t\t\t: Effect.fail(cause),\n\t\t\t\t),\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'port-allocate',\n\t\t\t\t\t\t`sui local mode: failed to allocate ${label} host port ` +\n\t\t\t\t\t\t\t`(preferred ${hint ?? 'auto'}): ${cause.detail}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\treturn allocate(preferredPort);\n};\n\n// ---------------------------------------------------------------------------\n// Ready-probe coordination\n// ---------------------------------------------------------------------------\n\n/** Coordinated readiness gate. Both RPC + faucet must respond within\n * the outer deadline; each probe has its own per-fetch deadline so a\n * wedged endpoint surfaces by name. */\nconst waitForReady = (\n\trpcUrl: string,\n\tfaucetUrl: string,\n\tgraphqlUrl: string,\n\treadyTimeout: Duration.Duration,\n): Effect.Effect<void, SuiPluginError> =>\n\tEffect.gen(function* () {\n\t\tconst readyTimeoutMs = Duration.toMillis(readyTimeout);\n\t\tconst rpcProbe: Effect.Effect<void, SuiPluginError> = waitForHttpEndpoint({\n\t\t\tendpoint: rpcUrl,\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\trequestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,\n\t\t\trequestInit: {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'content-type': 'application/json' },\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tjsonrpc: '2.0',\n\t\t\t\t\tid: 1,\n\t\t\t\t\tmethod: 'sui_getLatestCheckpointSequenceNumber',\n\t\t\t\t\tparams: [],\n\t\t\t\t}),\n\t\t\t},\n\t\t\tvalidate: async (response) => {\n\t\t\t\tif (!response.ok) return false;\n\t\t\t\tconst body = (await response.json()) as { readonly result?: unknown };\n\t\t\t\treturn typeof body.result === 'string' || typeof body.result === 'number';\n\t\t\t},\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause): SuiPluginError =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'rpc-probe',\n\t\t\t\t\t\t`sui local mode: RPC endpoint ${rpcUrl} did not become ready within ` +\n\t\t\t\t\t\t\t`${readyTimeoutMs}ms: ${formatUnknownError(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.withSpan('devstack.plugin.sui.local.probe.rpc'),\n\t\t);\n\n\t\t// Faucet socket-level liveness — `GET /` returns \"OK\" as soon as\n\t\t// the HTTP server is bound. We do NOT POST `/v2/gas` here; that's\n\t\t// the funds-ready probe, which is paid for lazily on first call.\n\t\tconst faucetProbe: Effect.Effect<void, SuiPluginError> = waitForHttpEndpoint({\n\t\t\tendpoint: faucetUrl,\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\trequestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,\n\t\t\tvalidate: (response) => response.status < 500,\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause): SuiPluginError =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'faucet-probe',\n\t\t\t\t\t\t`sui local mode: faucet endpoint ${faucetUrl} did not become ready within ` +\n\t\t\t\t\t\t\t`${readyTimeoutMs}ms: ${formatUnknownError(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.withSpan('devstack.plugin.sui.local.probe.faucet'),\n\t\t);\n\n\t\tconst graphqlProbe: Effect.Effect<void, SuiPluginError> = waitForHttpEndpoint({\n\t\t\tendpoint: graphqlUrl,\n\t\t\ttimeoutMs: readyTimeoutMs,\n\t\t\tintervalMs: 1_000,\n\t\t\trequestTimeoutMs: PROBE_FETCH_TIMEOUT_MS,\n\t\t\tvalidate: (response) => response.status < 500,\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(cause): SuiPluginError =>\n\t\t\t\t\tsuiPluginError(\n\t\t\t\t\t\t'graphql-probe',\n\t\t\t\t\t\t`sui local mode: GraphQL endpoint ${graphqlUrl} did not become ready within ` +\n\t\t\t\t\t\t\t`${readyTimeoutMs}ms: ${formatUnknownError(cause)}`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.withSpan('devstack.plugin.sui.local.probe.graphql'),\n\t\t);\n\n\t\tyield* Effect.all([rpcProbe, faucetProbe, graphqlProbe], { concurrency: 'unbounded' }).pipe(\n\t\t\tEffect.asVoid,\n\t\t);\n\t}).pipe(Effect.withSpan('devstack.plugin.sui.local.waitForReady'));\n\n// Chain-id fetch + waitForTransactionsReady builders live in\n// `shared-boot.ts` — see imports at the top of this file.\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst routedSuiUrl = (\n\tidentity: Identity,\n\tendpointName: string,\n\tport: number,\n): Effect.Effect<string, SuiPluginError> =>\n\troutedHostname(identity, endpointName).pipe(\n\t\tEffect.map((hostname) => renderUrl({ protocol: 'http', hostname, port })),\n\t\tEffect.mapError((cause) =>\n\t\t\tsuiPluginError(\n\t\t\t\t'container-start',\n\t\t\t\t`sui local mode: failed to construct router URL for ${endpointName}: ${cause.detail}`,\n\t\t\t\tcause,\n\t\t\t),\n\t\t),\n\t);\n"],"mappings":"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"}