@mysten-incubation/devstack 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (858) hide show
  1. package/README.md +6 -3
  2. package/dashboard-ui/assets/grpc-a4usE3Nk.js +3 -0
  3. package/dashboard-ui/assets/index-B82Bh84P.css +1 -0
  4. package/dashboard-ui/assets/index-CRYJ4pru.js +1277 -0
  5. package/dashboard-ui/index.html +2 -2
  6. package/dist/api/define-capabilities.d.mts +1 -20
  7. package/dist/api/define-capabilities.mjs +15 -22
  8. package/dist/api/define-capabilities.mjs.map +1 -1
  9. package/dist/api/define-devstack-with.d.mts +7 -1
  10. package/dist/api/define-devstack-with.mjs.map +1 -1
  11. package/dist/api/define-devstack.mjs.map +1 -1
  12. package/dist/api/define-plugin.d.mts +2 -1
  13. package/dist/api/inference-network.d.mts +31 -17
  14. package/dist/api/inference-network.mjs +40 -43
  15. package/dist/api/inference-network.mjs.map +1 -1
  16. package/dist/api/load-config.mjs +88 -0
  17. package/dist/api/load-config.mjs.map +1 -0
  18. package/dist/api/mode-narrowed-factory.d.mts +1 -1
  19. package/dist/api/mode-narrowed-factory.mjs.map +1 -1
  20. package/dist/api/run-stack-internal.mjs +202 -0
  21. package/dist/api/run-stack-internal.mjs.map +1 -0
  22. package/dist/api/run-stack.d.mts +82 -31
  23. package/dist/api/run-stack.mjs +22 -141
  24. package/dist/api/run-stack.mjs.map +1 -1
  25. package/dist/build-integrations/dapp-kit/index.d.mts +61 -0
  26. package/dist/build-integrations/dapp-kit/index.mjs +58 -0
  27. package/dist/build-integrations/dapp-kit/index.mjs.map +1 -0
  28. package/dist/build-integrations/playwright/config.d.mts +1 -30
  29. package/dist/build-integrations/playwright/config.mjs +1 -27
  30. package/dist/build-integrations/playwright/config.mjs.map +1 -1
  31. package/dist/build-integrations/playwright/errors.d.mts +4 -7
  32. package/dist/build-integrations/playwright/errors.mjs.map +1 -1
  33. package/dist/build-integrations/playwright/global-setup.d.mts +42 -71
  34. package/dist/build-integrations/playwright/global-setup.mjs +142 -218
  35. package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
  36. package/dist/build-integrations/playwright/index.d.mts +2 -2
  37. package/dist/build-integrations/playwright/index.mjs +2 -2
  38. package/dist/build-integrations/playwright/stack-context.d.mts +3 -1
  39. package/dist/build-integrations/playwright/stack-context.mjs +4 -2
  40. package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
  41. package/dist/build-integrations/playwright/wallet-context.mjs +44 -19
  42. package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
  43. package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
  44. package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -1
  45. package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -1
  46. package/dist/build-integrations/runtime/discover.d.mts +6 -4
  47. package/dist/build-integrations/runtime/discover.mjs +15 -4
  48. package/dist/build-integrations/runtime/discover.mjs.map +1 -1
  49. package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
  50. package/dist/build-integrations/runtime/errors.mjs.map +1 -1
  51. package/dist/build-integrations/runtime/read-stack-context.mjs +3 -3
  52. package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
  53. package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +23 -7
  54. package/dist/build-integrations/runtime/resolve-discovery-env.mjs +25 -12
  55. package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -1
  56. package/dist/build-integrations/runtime/stack-context.d.mts +2 -2
  57. package/dist/build-integrations/vite/index.d.mts +84 -19
  58. package/dist/build-integrations/vite/index.mjs +203 -28
  59. package/dist/build-integrations/vite/index.mjs.map +1 -1
  60. package/dist/build-integrations/vitest/config.d.mts +20 -2
  61. package/dist/build-integrations/vitest/config.mjs +16 -4
  62. package/dist/build-integrations/vitest/config.mjs.map +1 -1
  63. package/dist/build-integrations/vitest/env.d.mts +18 -10
  64. package/dist/build-integrations/vitest/env.mjs +11 -10
  65. package/dist/build-integrations/vitest/env.mjs.map +1 -1
  66. package/dist/build-integrations/vitest/errors.d.mts +7 -11
  67. package/dist/build-integrations/vitest/errors.mjs +3 -4
  68. package/dist/build-integrations/vitest/errors.mjs.map +1 -1
  69. package/dist/build-integrations/vitest/global-setup.d.mts +35 -0
  70. package/dist/build-integrations/vitest/global-setup.mjs +156 -0
  71. package/dist/build-integrations/vitest/global-setup.mjs.map +1 -0
  72. package/dist/build-integrations/vitest/index.d.mts +3 -2
  73. package/dist/build-integrations/vitest/index.mjs +3 -2
  74. package/dist/build-integrations/vitest/setup.mjs +2 -2
  75. package/dist/build-integrations/vitest/setup.mjs.map +1 -1
  76. package/dist/build-integrations/vitest/stack-context.d.mts +5 -3
  77. package/dist/build-integrations/vitest/stack-context.mjs +3 -2
  78. package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
  79. package/dist/cli/bail.mjs.map +1 -1
  80. package/dist/cli/doctor-probes.mjs +1 -3
  81. package/dist/cli/doctor-probes.mjs.map +1 -1
  82. package/dist/cli/main.d.mts +23 -1
  83. package/dist/cli/main.mjs +63 -8
  84. package/dist/cli/main.mjs.map +1 -1
  85. package/dist/cli/prune-direct.mjs.map +1 -1
  86. package/dist/cli/snapshot-reader.mjs.map +1 -1
  87. package/dist/cli/up-lifecycle.mjs.map +1 -1
  88. package/dist/cli/wirings/apply.mjs +28 -21
  89. package/dist/cli/wirings/apply.mjs.map +1 -1
  90. package/dist/cli/wirings/codegen.mjs +108 -0
  91. package/dist/cli/wirings/codegen.mjs.map +1 -0
  92. package/dist/cli/wirings/config-loader.mjs +12 -62
  93. package/dist/cli/wirings/config-loader.mjs.map +1 -1
  94. package/dist/cli/wirings/dump-ids.mjs +86 -0
  95. package/dist/cli/wirings/dump-ids.mjs.map +1 -0
  96. package/dist/cli/wirings/engine-command.mjs +1 -1
  97. package/dist/cli/wirings/engine-command.mjs.map +1 -1
  98. package/dist/cli/wirings/identity.mjs +2 -2
  99. package/dist/cli/wirings/identity.mjs.map +1 -1
  100. package/dist/cli/wirings/provide-file-system.mjs.map +1 -1
  101. package/dist/cli/wirings/read-devstack-version.mjs +17 -0
  102. package/dist/cli/wirings/read-devstack-version.mjs.map +1 -0
  103. package/dist/cli/wirings/snapshot.mjs +27 -34
  104. package/dist/cli/wirings/snapshot.mjs.map +1 -1
  105. package/dist/cli/wirings/up-ipc.mjs +147 -0
  106. package/dist/cli/wirings/up-ipc.mjs.map +1 -0
  107. package/dist/cli/wirings/up.mjs +218 -198
  108. package/dist/cli/wirings/up.mjs.map +1 -1
  109. package/dist/cli/wirings/wipe.mjs +1 -1
  110. package/dist/cli/wirings/wipe.mjs.map +1 -1
  111. package/dist/contracts/chain-probe.d.mts +1 -1
  112. package/dist/contracts/chain-probe.mjs +1 -1
  113. package/dist/contracts/chain-probe.mjs.map +1 -1
  114. package/dist/contracts/codegenable.d.mts +60 -6
  115. package/dist/contracts/codegenable.mjs +28 -0
  116. package/dist/contracts/codegenable.mjs.map +1 -0
  117. package/dist/contracts/config-bindings.mjs +162 -0
  118. package/dist/contracts/config-bindings.mjs.map +1 -0
  119. package/dist/contracts/container-runtime.d.mts +23 -17
  120. package/dist/contracts/plugin-expander.mjs.map +1 -1
  121. package/dist/contracts/snapshotable.d.mts +5 -7
  122. package/dist/contracts/wallet-protocol.d.mts +2 -5
  123. package/dist/contracts/wallet-protocol.mjs +2 -5
  124. package/dist/contracts/wallet-protocol.mjs.map +1 -1
  125. package/dist/index.d.mts +21 -26
  126. package/dist/index.mjs +8 -9
  127. package/dist/orchestrators/boot.d.mts +28 -0
  128. package/dist/orchestrators/boot.mjs +440 -0
  129. package/dist/orchestrators/boot.mjs.map +1 -0
  130. package/dist/orchestrators/codegen/bindings.d.mts +13 -1
  131. package/dist/orchestrators/codegen/bindings.mjs +23 -9
  132. package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
  133. package/dist/orchestrators/codegen/config-runtime.mjs +208 -0
  134. package/dist/orchestrators/codegen/config-runtime.mjs.map +1 -0
  135. package/dist/orchestrators/codegen/emit.mjs +1 -1
  136. package/dist/orchestrators/codegen/emit.mjs.map +1 -1
  137. package/dist/orchestrators/codegen/errors.mjs +21 -1
  138. package/dist/orchestrators/codegen/errors.mjs.map +1 -1
  139. package/dist/orchestrators/codegen/format.mjs +2 -0
  140. package/dist/orchestrators/codegen/format.mjs.map +1 -1
  141. package/dist/orchestrators/codegen/gitignore.mjs +30 -11
  142. package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
  143. package/dist/orchestrators/codegen/id-config.mjs +107 -0
  144. package/dist/orchestrators/codegen/id-config.mjs.map +1 -0
  145. package/dist/orchestrators/codegen/output-location.mjs +23 -32
  146. package/dist/orchestrators/codegen/output-location.mjs.map +1 -1
  147. package/dist/orchestrators/codegen/paths.mjs +8 -1
  148. package/dist/orchestrators/codegen/paths.mjs.map +1 -1
  149. package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
  150. package/dist/orchestrators/codegen/service.mjs +286 -58
  151. package/dist/orchestrators/codegen/service.mjs.map +1 -1
  152. package/dist/orchestrators/layers.mjs +31 -0
  153. package/dist/orchestrators/layers.mjs.map +1 -0
  154. package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -1
  155. package/dist/orchestrators/lifecycle-prune/index.mjs +8 -10
  156. package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -1
  157. package/dist/orchestrators/network-options.d.mts +52 -0
  158. package/dist/orchestrators/network-options.mjs +43 -0
  159. package/dist/orchestrators/network-options.mjs.map +1 -0
  160. package/dist/orchestrators/router/cleanup.mjs.map +1 -1
  161. package/dist/orchestrators/router/cors.mjs.map +1 -1
  162. package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
  163. package/dist/orchestrators/router/errors.mjs.map +1 -1
  164. package/dist/orchestrators/router/file-provider.mjs.map +1 -1
  165. package/dist/orchestrators/router/hostname.mjs.map +1 -1
  166. package/dist/orchestrators/router/profile.mjs +1 -1
  167. package/dist/orchestrators/router/profile.mjs.map +1 -1
  168. package/dist/orchestrators/router/service.d.mts +2 -2
  169. package/dist/orchestrators/router/service.mjs +12 -27
  170. package/dist/orchestrators/router/service.mjs.map +1 -1
  171. package/dist/orchestrators/router/traefik-container.mjs +1 -1
  172. package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
  173. package/dist/orchestrators/snapshot/capture.mjs +171 -195
  174. package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
  175. package/dist/orchestrators/snapshot/descriptor.d.mts +1 -1
  176. package/dist/orchestrators/snapshot/descriptor.mjs +53 -11
  177. package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
  178. package/dist/orchestrators/snapshot/identity-guard.mjs +3 -5
  179. package/dist/orchestrators/snapshot/identity-guard.mjs.map +1 -1
  180. package/dist/orchestrators/snapshot/image-bundle-tags.mjs +32 -101
  181. package/dist/orchestrators/snapshot/image-bundle-tags.mjs.map +1 -1
  182. package/dist/orchestrators/snapshot/index.mjs +1 -4
  183. package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
  184. package/dist/orchestrators/snapshot/interrupted-restore.mjs +116 -0
  185. package/dist/orchestrators/snapshot/interrupted-restore.mjs.map +1 -0
  186. package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -1
  187. package/dist/orchestrators/snapshot/prune.mjs +40 -31
  188. package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
  189. package/dist/orchestrators/snapshot/restore.mjs +221 -196
  190. package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
  191. package/dist/orchestrators/snapshot/service.mjs +72 -62
  192. package/dist/orchestrators/snapshot/service.mjs.map +1 -1
  193. package/dist/orchestrators/snapshot/wipe.mjs +67 -56
  194. package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
  195. package/dist/plugins/account/codegen.mjs +3 -0
  196. package/dist/plugins/account/codegen.mjs.map +1 -1
  197. package/dist/plugins/account/errors.d.mts +2 -2
  198. package/dist/plugins/account/errors.mjs +1 -4
  199. package/dist/plugins/account/errors.mjs.map +1 -1
  200. package/dist/plugins/account/funding.mjs +3 -27
  201. package/dist/plugins/account/funding.mjs.map +1 -1
  202. package/dist/plugins/account/index.d.mts +3 -8
  203. package/dist/plugins/account/index.mjs +71 -35
  204. package/dist/plugins/account/index.mjs.map +1 -1
  205. package/dist/plugins/account/keypair.d.mts +8 -7
  206. package/dist/plugins/account/keypair.mjs +5 -18
  207. package/dist/plugins/account/keypair.mjs.map +1 -1
  208. package/dist/plugins/account/lease.mjs.map +1 -1
  209. package/dist/plugins/account/registry.d.mts +1 -46
  210. package/dist/plugins/account/registry.mjs.map +1 -1
  211. package/dist/plugins/account/service.d.mts +43 -34
  212. package/dist/plugins/account/service.mjs +9 -54
  213. package/dist/plugins/account/service.mjs.map +1 -1
  214. package/dist/plugins/account/snapshot.mjs.map +1 -1
  215. package/dist/plugins/account/variants/ephemeral.mjs.map +1 -1
  216. package/dist/plugins/account/variants/impersonate.mjs.map +1 -1
  217. package/dist/plugins/account/variants/signer.mjs.map +1 -1
  218. package/dist/plugins/action/discriminator.mjs.map +1 -1
  219. package/dist/plugins/action/errors.mjs +1 -4
  220. package/dist/plugins/action/errors.mjs.map +1 -1
  221. package/dist/plugins/action/execute.mjs +3 -4
  222. package/dist/plugins/action/execute.mjs.map +1 -1
  223. package/dist/plugins/action/index.d.mts +2 -2
  224. package/dist/plugins/action/index.mjs +7 -11
  225. package/dist/plugins/action/index.mjs.map +1 -1
  226. package/dist/plugins/action/service.d.mts +5 -7
  227. package/dist/plugins/action/service.mjs +2 -16
  228. package/dist/plugins/action/service.mjs.map +1 -1
  229. package/dist/plugins/coin/address-resolution.mjs.map +1 -1
  230. package/dist/plugins/coin/codegen.mjs +97 -16
  231. package/dist/plugins/coin/codegen.mjs.map +1 -1
  232. package/dist/plugins/coin/discovery.mjs.map +1 -1
  233. package/dist/plugins/coin/errors.mjs +1 -4
  234. package/dist/plugins/coin/errors.mjs.map +1 -1
  235. package/dist/plugins/coin/index.d.mts +4 -34
  236. package/dist/plugins/coin/index.mjs +47 -28
  237. package/dist/plugins/coin/index.mjs.map +1 -1
  238. package/dist/plugins/coin/metadata.d.mts +1 -0
  239. package/dist/plugins/coin/metadata.mjs +8 -9
  240. package/dist/plugins/coin/metadata.mjs.map +1 -1
  241. package/dist/plugins/coin/mint.mjs +7 -21
  242. package/dist/plugins/coin/mint.mjs.map +1 -1
  243. package/dist/plugins/coin/registry.mjs +33 -20
  244. package/dist/plugins/coin/registry.mjs.map +1 -1
  245. package/dist/plugins/coin/service.d.mts +1 -1
  246. package/dist/plugins/coin/service.mjs +1 -8
  247. package/dist/plugins/coin/service.mjs.map +1 -1
  248. package/dist/plugins/coin/snapshot.mjs.map +1 -1
  249. package/dist/plugins/coin/type-strings.mjs.map +1 -1
  250. package/dist/plugins/dashboard/domain.mjs +106 -167
  251. package/dist/plugins/dashboard/domain.mjs.map +1 -1
  252. package/dist/plugins/dashboard/index.mjs +13 -13
  253. package/dist/plugins/dashboard/index.mjs.map +1 -1
  254. package/dist/plugins/dashboard/origin-policy.mjs +3 -3
  255. package/dist/plugins/dashboard/origin-policy.mjs.map +1 -1
  256. package/dist/plugins/dashboard/routable.mjs.map +1 -1
  257. package/dist/plugins/dashboard/schema/builder.mjs.map +1 -1
  258. package/dist/plugins/dashboard/schema/enums.mjs.map +1 -1
  259. package/dist/plugins/dashboard/schema/root.mjs +23 -44
  260. package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
  261. package/dist/plugins/dashboard/schema/types.mjs +37 -91
  262. package/dist/plugins/dashboard/schema/types.mjs.map +1 -1
  263. package/dist/plugins/dashboard/schema.mjs.map +1 -1
  264. package/dist/plugins/dashboard/server.mjs.map +1 -1
  265. package/dist/plugins/deepbook/codegen.d.mts +12 -11
  266. package/dist/plugins/deepbook/codegen.mjs +108 -11
  267. package/dist/plugins/deepbook/codegen.mjs.map +1 -1
  268. package/dist/plugins/deepbook/deploy.mjs +7 -14
  269. package/dist/plugins/deepbook/deploy.mjs.map +1 -1
  270. package/dist/plugins/deepbook/errors.mjs +4 -2
  271. package/dist/plugins/deepbook/errors.mjs.map +1 -1
  272. package/dist/plugins/deepbook/faucet-strategy.mjs +4 -10
  273. package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
  274. package/dist/plugins/deepbook/hash.mjs.map +1 -1
  275. package/dist/plugins/deepbook/index.d.mts +38 -34
  276. package/dist/plugins/deepbook/index.mjs +133 -64
  277. package/dist/plugins/deepbook/index.mjs.map +1 -1
  278. package/dist/plugins/deepbook/plugin-key.mjs.map +1 -1
  279. package/dist/plugins/deepbook/pyth/index.mjs +4 -8
  280. package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
  281. package/dist/plugins/deepbook/snapshot.mjs +0 -1
  282. package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
  283. package/dist/plugins/deepbook/type-strings.mjs.map +1 -1
  284. package/dist/plugins/deepbook/types.d.mts +2 -1
  285. package/dist/plugins/deepbook/types.mjs.map +1 -1
  286. package/dist/plugins/faucet/dispatcher.d.mts +3 -3
  287. package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
  288. package/dist/plugins/faucet/errors.mjs.map +1 -1
  289. package/dist/plugins/faucet/http.mjs +2 -10
  290. package/dist/plugins/faucet/http.mjs.map +1 -1
  291. package/dist/plugins/faucet/index.mjs +0 -1
  292. package/dist/plugins/faucet/index.mjs.map +1 -1
  293. package/dist/plugins/host-service/errors.d.mts +1 -3
  294. package/dist/plugins/host-service/errors.mjs +1 -2
  295. package/dist/plugins/host-service/errors.mjs.map +1 -1
  296. package/dist/plugins/host-service/index.d.mts +1 -2
  297. package/dist/plugins/host-service/index.mjs +11 -11
  298. package/dist/plugins/host-service/index.mjs.map +1 -1
  299. package/dist/plugins/host-service/routable.mjs.map +1 -1
  300. package/dist/plugins/host-service/service.mjs +13 -13
  301. package/dist/plugins/host-service/service.mjs.map +1 -1
  302. package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -1
  303. package/dist/plugins/internal/codegen-helpers.mjs +2 -0
  304. package/dist/plugins/internal/codegen-helpers.mjs.map +1 -1
  305. package/dist/plugins/internal/funding-failure-error.mjs.map +1 -1
  306. package/dist/plugins/{postgres → internal/postgres-sidecar}/connection.mjs +1 -1
  307. package/dist/plugins/internal/postgres-sidecar/connection.mjs.map +1 -0
  308. package/dist/plugins/{postgres → internal/postgres-sidecar}/db-ensure.mjs +30 -16
  309. package/dist/plugins/internal/postgres-sidecar/db-ensure.mjs.map +1 -0
  310. package/dist/plugins/internal/postgres-sidecar/errors.mjs +21 -0
  311. package/dist/plugins/internal/postgres-sidecar/errors.mjs.map +1 -0
  312. package/dist/{substrate/runtime/scoped-multimap → plugins/internal/postgres-sidecar}/index.mjs +1 -0
  313. package/dist/plugins/internal/postgres-sidecar/service.mjs +121 -0
  314. package/dist/plugins/internal/postgres-sidecar/service.mjs.map +1 -0
  315. package/dist/plugins/package/build.mjs +2 -2
  316. package/dist/plugins/package/build.mjs.map +1 -1
  317. package/dist/plugins/package/codegen.d.mts +7 -14
  318. package/dist/plugins/package/codegen.mjs +187 -59
  319. package/dist/plugins/package/codegen.mjs.map +1 -1
  320. package/dist/plugins/package/dep-resolution.mjs +51 -3
  321. package/dist/plugins/package/dep-resolution.mjs.map +1 -1
  322. package/dist/plugins/package/errors.mjs +1 -4
  323. package/dist/plugins/package/errors.mjs.map +1 -1
  324. package/dist/plugins/package/git-source.d.mts +18 -0
  325. package/dist/plugins/package/git-source.mjs +119 -0
  326. package/dist/plugins/package/git-source.mjs.map +1 -0
  327. package/dist/plugins/package/index.d.mts +28 -19
  328. package/dist/plugins/package/index.mjs +107 -32
  329. package/dist/plugins/package/index.mjs.map +1 -1
  330. package/dist/plugins/package/mode-known.mjs +2 -2
  331. package/dist/plugins/package/mode-known.mjs.map +1 -1
  332. package/dist/plugins/package/mode-local.mjs +18 -35
  333. package/dist/plugins/package/mode-local.mjs.map +1 -1
  334. package/dist/plugins/package/publish-executor.mjs +13 -8
  335. package/dist/plugins/package/publish-executor.mjs.map +1 -1
  336. package/dist/plugins/package/publish-output.d.mts +1 -11
  337. package/dist/plugins/package/publish-output.mjs +1 -9
  338. package/dist/plugins/package/publish-output.mjs.map +1 -1
  339. package/dist/plugins/package/registry.d.mts +1 -1
  340. package/dist/plugins/package/registry.mjs +26 -14
  341. package/dist/plugins/package/registry.mjs.map +1 -1
  342. package/dist/plugins/package/service.mjs.map +1 -1
  343. package/dist/plugins/package/snapshot.mjs.map +1 -1
  344. package/dist/plugins/router-entrypoints.mjs +1 -3
  345. package/dist/plugins/router-entrypoints.mjs.map +1 -1
  346. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +1 -2
  347. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
  348. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +1 -6
  349. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
  350. package/dist/plugins/seal/codegen.d.mts +1 -5
  351. package/dist/plugins/seal/codegen.mjs +83 -12
  352. package/dist/plugins/seal/codegen.mjs.map +1 -1
  353. package/dist/plugins/seal/config-render.mjs +2 -6
  354. package/dist/plugins/seal/config-render.mjs.map +1 -1
  355. package/dist/plugins/seal/deploy.mjs +18 -29
  356. package/dist/plugins/seal/deploy.mjs.map +1 -1
  357. package/dist/plugins/seal/errors.d.mts +4 -5
  358. package/dist/plugins/seal/errors.mjs +1 -8
  359. package/dist/plugins/seal/errors.mjs.map +1 -1
  360. package/dist/plugins/seal/index.d.mts +7 -28
  361. package/dist/plugins/seal/index.mjs +69 -47
  362. package/dist/plugins/seal/index.mjs.map +1 -1
  363. package/dist/plugins/seal/key-manager.mjs.map +1 -1
  364. package/dist/plugins/seal/key-server.mjs +1 -6
  365. package/dist/plugins/seal/key-server.mjs.map +1 -1
  366. package/dist/plugins/seal/keygen.mjs +2 -3
  367. package/dist/plugins/seal/keygen.mjs.map +1 -1
  368. package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
  369. package/dist/plugins/seal/mode/live.mjs +1 -1
  370. package/dist/plugins/seal/mode/live.mjs.map +1 -1
  371. package/dist/plugins/seal/mode/local-keygen.mjs +4 -10
  372. package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
  373. package/dist/plugins/seal/plugin-key.mjs.map +1 -1
  374. package/dist/plugins/seal/registry-publish.mjs.map +1 -1
  375. package/dist/plugins/seal/routable.mjs.map +1 -1
  376. package/dist/plugins/seal/service.mjs.map +1 -1
  377. package/dist/plugins/seal/snapshot.mjs +1 -2
  378. package/dist/plugins/seal/snapshot.mjs.map +1 -1
  379. package/dist/plugins/sui/auto-tick.mjs +5 -5
  380. package/dist/plugins/sui/auto-tick.mjs.map +1 -1
  381. package/dist/plugins/sui/chain-build-container.mjs +2 -2
  382. package/dist/plugins/sui/chain-build-container.mjs.map +1 -1
  383. package/dist/plugins/sui/chain-probe.mjs +4 -4
  384. package/dist/plugins/sui/chain-probe.mjs.map +1 -1
  385. package/dist/plugins/sui/codegen.d.mts +9 -7
  386. package/dist/plugins/sui/codegen.mjs +49 -46
  387. package/dist/plugins/sui/codegen.mjs.map +1 -1
  388. package/dist/plugins/sui/errors.d.mts +1 -1
  389. package/dist/plugins/sui/errors.mjs +1 -9
  390. package/dist/plugins/sui/errors.mjs.map +1 -1
  391. package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/index.d.mts +1 -1
  392. package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/index.mjs +3 -7
  393. package/dist/plugins/sui/exec/index.mjs.map +1 -0
  394. package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/sign-and-dispatch.mjs +1 -1
  395. package/dist/plugins/sui/exec/sign-and-dispatch.mjs.map +1 -0
  396. package/dist/plugins/sui/fork-faucet-strategy.mjs +2 -6
  397. package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -1
  398. package/dist/plugins/sui/fork-orchestration.mjs +13 -23
  399. package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
  400. package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
  401. package/dist/plugins/sui/index.d.mts +34 -83
  402. package/dist/plugins/sui/index.mjs +200 -68
  403. package/dist/plugins/sui/index.mjs.map +1 -1
  404. package/dist/{substrate/runtime/sui-ledger → plugins/sui/ledger}/object-ref.mjs +1 -1
  405. package/dist/plugins/sui/ledger/object-ref.mjs.map +1 -0
  406. package/dist/plugins/sui/local-faucet-strategy.mjs +1 -5
  407. package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -1
  408. package/dist/plugins/sui/log-attrs.mjs +11 -0
  409. package/dist/plugins/sui/log-attrs.mjs.map +1 -0
  410. package/dist/plugins/sui/mode/external.mjs +4 -12
  411. package/dist/plugins/sui/mode/external.mjs.map +1 -1
  412. package/dist/plugins/sui/mode/fork.mjs +19 -16
  413. package/dist/plugins/sui/mode/fork.mjs.map +1 -1
  414. package/dist/plugins/sui/mode/live.mjs +4 -17
  415. package/dist/plugins/sui/mode/live.mjs.map +1 -1
  416. package/dist/plugins/sui/mode/local.d.mts +1 -0
  417. package/dist/plugins/sui/mode/local.mjs +203 -61
  418. package/dist/plugins/sui/mode/local.mjs.map +1 -1
  419. package/dist/plugins/sui/mode/shared-boot.mjs +18 -23
  420. package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
  421. package/dist/plugins/sui/mode/shared.d.mts +6 -7
  422. package/dist/plugins/sui/mode/shared.mjs.map +1 -1
  423. package/dist/plugins/sui/mode/spec.d.mts +23 -6
  424. package/dist/{substrate/runtime/sui-move-build → plugins/sui/move}/index.mjs +28 -30
  425. package/dist/plugins/sui/move/index.mjs.map +1 -0
  426. package/dist/plugins/sui/move-summary-runner.mjs +8 -4
  427. package/dist/plugins/sui/move-summary-runner.mjs.map +1 -1
  428. package/dist/{substrate/network.d.mts → plugins/sui/network-config.d.mts} +11 -10
  429. package/dist/plugins/sui/network-resolver.d.mts +6 -6
  430. package/dist/plugins/sui/routable.mjs.map +1 -1
  431. package/dist/plugins/sui/service.mjs +10 -6
  432. package/dist/plugins/sui/service.mjs.map +1 -1
  433. package/dist/plugins/sui/snapshot.mjs +10 -5
  434. package/dist/plugins/sui/snapshot.mjs.map +1 -1
  435. package/dist/plugins/wallet/codegen.d.mts +8 -6
  436. package/dist/plugins/wallet/codegen.mjs +4 -10
  437. package/dist/plugins/wallet/codegen.mjs.map +1 -1
  438. package/dist/plugins/wallet/errors.mjs +1 -4
  439. package/dist/plugins/wallet/errors.mjs.map +1 -1
  440. package/dist/plugins/wallet/index.d.mts +3 -6
  441. package/dist/plugins/wallet/index.mjs +16 -21
  442. package/dist/plugins/wallet/index.mjs.map +1 -1
  443. package/dist/plugins/wallet/origin-policy.mjs +3 -3
  444. package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
  445. package/dist/plugins/wallet/pairing.mjs +6 -24
  446. package/dist/plugins/wallet/pairing.mjs.map +1 -1
  447. package/dist/plugins/wallet/protocol.mjs.map +1 -1
  448. package/dist/plugins/wallet/routable.mjs.map +1 -1
  449. package/dist/plugins/wallet/server.mjs +17 -24
  450. package/dist/plugins/wallet/server.mjs.map +1 -1
  451. package/dist/plugins/wallet/service.d.mts +2 -2
  452. package/dist/plugins/wallet/service.mjs +4 -15
  453. package/dist/plugins/wallet/service.mjs.map +1 -1
  454. package/dist/plugins/wallet/snapshot.mjs.map +1 -1
  455. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +1 -5
  456. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
  457. package/dist/plugins/walrus/codegen.d.mts +2 -13
  458. package/dist/plugins/walrus/codegen.mjs +93 -28
  459. package/dist/plugins/walrus/codegen.mjs.map +1 -1
  460. package/dist/plugins/walrus/deploy-paths.mjs +2 -3
  461. package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
  462. package/dist/plugins/walrus/deploy.mjs +26 -19
  463. package/dist/plugins/walrus/deploy.mjs.map +1 -1
  464. package/dist/plugins/walrus/errors.mjs +1 -8
  465. package/dist/plugins/walrus/errors.mjs.map +1 -1
  466. package/dist/plugins/walrus/faucet-strategy.mjs +15 -1
  467. package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
  468. package/dist/plugins/walrus/index.d.mts +13 -44
  469. package/dist/plugins/walrus/index.mjs +119 -122
  470. package/dist/plugins/walrus/index.mjs.map +1 -1
  471. package/dist/plugins/walrus/mode/known-deploy.mjs +6 -6
  472. package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
  473. package/dist/plugins/walrus/mode/local-cluster.d.mts +2 -2
  474. package/dist/plugins/walrus/mode/local-cluster.mjs +2 -10
  475. package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
  476. package/dist/plugins/walrus/plugin-key.mjs.map +1 -1
  477. package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
  478. package/dist/plugins/walrus/routable.mjs.map +1 -1
  479. package/dist/plugins/walrus/service.mjs.map +1 -1
  480. package/dist/plugins/walrus/snapshot.mjs +3 -3
  481. package/dist/plugins/walrus/snapshot.mjs.map +1 -1
  482. package/dist/plugins/walrus/storage-nodes.mjs +53 -14
  483. package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
  484. package/dist/plugins/walrus/wal-swap.mjs +4 -8
  485. package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
  486. package/dist/primitives/artifact-publisher.mjs.map +1 -1
  487. package/dist/primitives/cache.d.mts +1 -1
  488. package/dist/runtime/docker/client.mjs +47 -3
  489. package/dist/runtime/docker/client.mjs.map +1 -1
  490. package/dist/runtime/docker/container.mjs +37 -57
  491. package/dist/runtime/docker/container.mjs.map +1 -1
  492. package/dist/runtime/docker/errors.mjs.map +1 -1
  493. package/dist/runtime/docker/exec.mjs +2 -2
  494. package/dist/runtime/docker/exec.mjs.map +1 -1
  495. package/dist/runtime/docker/image.mjs +10 -11
  496. package/dist/runtime/docker/image.mjs.map +1 -1
  497. package/dist/runtime/docker/index.mjs +0 -1
  498. package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -1
  499. package/dist/runtime/docker/inventory.mjs +9 -9
  500. package/dist/runtime/docker/inventory.mjs.map +1 -1
  501. package/dist/runtime/docker/labels.mjs +12 -1
  502. package/dist/runtime/docker/labels.mjs.map +1 -1
  503. package/dist/runtime/docker/network.mjs +6 -6
  504. package/dist/runtime/docker/network.mjs.map +1 -1
  505. package/dist/runtime/docker/render-run-args.mjs.map +1 -1
  506. package/dist/runtime/docker/service.mjs +31 -45
  507. package/dist/runtime/docker/service.mjs.map +1 -1
  508. package/dist/runtime/docker/sweep.mjs +14 -64
  509. package/dist/runtime/docker/sweep.mjs.map +1 -1
  510. package/dist/runtime/docker/volume.mjs +1 -1
  511. package/dist/runtime/docker/volume.mjs.map +1 -1
  512. package/dist/runtime/docker/wrap.mjs +14 -2
  513. package/dist/runtime/docker/wrap.mjs.map +1 -1
  514. package/dist/substrate/brand.d.mts +2 -5
  515. package/dist/substrate/brand.mjs +3 -2
  516. package/dist/substrate/brand.mjs.map +1 -1
  517. package/dist/substrate/cross-process.mjs +2 -16
  518. package/dist/substrate/cross-process.mjs.map +1 -1
  519. package/dist/substrate/event-time.mjs +0 -2
  520. package/dist/substrate/event-time.mjs.map +1 -1
  521. package/dist/substrate/events.d.mts +46 -16
  522. package/dist/substrate/identity.d.mts +11 -5
  523. package/dist/substrate/manifest.d.mts +33 -26
  524. package/dist/substrate/manifest.mjs +8 -3
  525. package/dist/substrate/manifest.mjs.map +1 -1
  526. package/dist/substrate/options.d.mts +33 -4
  527. package/dist/substrate/plugin-ctx.d.mts +70 -0
  528. package/dist/substrate/plugin-ctx.mjs +66 -0
  529. package/dist/substrate/plugin-ctx.mjs.map +1 -0
  530. package/dist/substrate/plugin.d.mts +46 -38
  531. package/dist/substrate/plugin.mjs +13 -9
  532. package/dist/substrate/plugin.mjs.map +1 -1
  533. package/dist/substrate/projection.d.mts +1 -1
  534. package/dist/substrate/runtime/atomic-write.mjs +3 -4
  535. package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
  536. package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
  537. package/dist/substrate/runtime/cache/service.mjs +50 -20
  538. package/dist/substrate/runtime/cache/service.mjs.map +1 -1
  539. package/dist/substrate/runtime/config-validation.mjs.map +1 -1
  540. package/dist/substrate/runtime/control-plane/domain.mjs +34 -12
  541. package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -1
  542. package/dist/substrate/runtime/control-plane/service.mjs.map +1 -1
  543. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +14 -17
  544. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
  545. package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
  546. package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
  547. package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs.map +1 -1
  548. package/dist/substrate/runtime/cross-process/index.mjs +0 -2
  549. package/dist/substrate/runtime/cross-process/live-clock.mjs +1 -1
  550. package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -1
  551. package/dist/substrate/runtime/cross-process/liveness.mjs +11 -18
  552. package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
  553. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +2 -2
  554. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -1
  555. package/dist/substrate/runtime/cross-process/roster.mjs +17 -127
  556. package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
  557. package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -1
  558. package/dist/substrate/runtime/cross-process/stack-lock.mjs +29 -28
  559. package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
  560. package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
  561. package/dist/substrate/runtime/errors.mjs +1 -13
  562. package/dist/substrate/runtime/errors.mjs.map +1 -1
  563. package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -1
  564. package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -1
  565. package/dist/substrate/runtime/host-gateway.mjs.map +1 -1
  566. package/dist/substrate/runtime/host-tree-tar/index.mjs +15 -163
  567. package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
  568. package/dist/substrate/runtime/http-probe.d.mts +1 -3
  569. package/dist/substrate/runtime/http-probe.mjs.map +1 -1
  570. package/dist/substrate/runtime/index.mjs +1 -6
  571. package/dist/substrate/runtime/lease-broker/service.mjs +5 -23
  572. package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
  573. package/dist/substrate/runtime/lifecycle/dep-graph.mjs +3 -3
  574. package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
  575. package/dist/substrate/runtime/lifecycle/graph-input-id.d.mts +1 -0
  576. package/dist/substrate/runtime/lifecycle/graph-input-id.mjs +133 -0
  577. package/dist/substrate/runtime/lifecycle/graph-input-id.mjs.map +1 -0
  578. package/dist/substrate/runtime/lifecycle/index.mjs +2 -2
  579. package/dist/substrate/runtime/lifecycle/plugin-registry.d.mts +1 -1
  580. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +22 -1
  581. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
  582. package/dist/substrate/runtime/lifecycle/ready-gate.mjs +2 -15
  583. package/dist/substrate/runtime/lifecycle/ready-gate.mjs.map +1 -1
  584. package/dist/substrate/runtime/lifecycle/selective-restart.mjs +29 -25
  585. package/dist/substrate/runtime/lifecycle/selective-restart.mjs.map +1 -1
  586. package/dist/substrate/runtime/lifecycle/signals.mjs +1 -1
  587. package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
  588. package/dist/substrate/runtime/lifecycle/state-machine.mjs.map +1 -1
  589. package/dist/substrate/runtime/lifecycle/watch-attribution.d.mts +1 -1
  590. package/dist/substrate/runtime/lifecycle/watch-attribution.mjs +0 -1
  591. package/dist/substrate/runtime/lifecycle/watch-attribution.mjs.map +1 -1
  592. package/dist/substrate/runtime/managed-container.d.mts +5 -1
  593. package/dist/substrate/runtime/managed-container.mjs +8 -10
  594. package/dist/substrate/runtime/managed-container.mjs.map +1 -1
  595. package/dist/substrate/runtime/manifest/manifest.mjs +8 -30
  596. package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
  597. package/dist/substrate/runtime/mode-errors.d.mts +1 -2
  598. package/dist/substrate/runtime/mode-errors.mjs.map +1 -1
  599. package/dist/substrate/runtime/observability/cascade-formatter.mjs +1 -11
  600. package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
  601. package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -1
  602. package/dist/substrate/runtime/observability/index.d.mts +1 -1
  603. package/dist/substrate/runtime/observability/index.mjs +4 -6
  604. package/dist/substrate/runtime/observability/log-attrs.mjs +46 -0
  605. package/dist/substrate/runtime/observability/log-attrs.mjs.map +1 -0
  606. package/dist/substrate/runtime/observability/log-store.mjs.map +1 -1
  607. package/dist/substrate/runtime/observability/logger.mjs +3 -3
  608. package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
  609. package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -1
  610. package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
  611. package/dist/substrate/runtime/observability/process-lines.mjs.map +1 -1
  612. package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
  613. package/dist/substrate/runtime/observability/subprocess-capture.mjs +2 -2
  614. package/dist/substrate/runtime/observability/subprocess-capture.mjs.map +1 -1
  615. package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -1
  616. package/dist/substrate/runtime/paths.mjs +27 -9
  617. package/dist/substrate/runtime/paths.mjs.map +1 -1
  618. package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -1
  619. package/dist/substrate/runtime/port-broker/service.mjs +10 -27
  620. package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
  621. package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
  622. package/dist/substrate/runtime/probes.d.mts +2 -3
  623. package/dist/substrate/runtime/probes.mjs.map +1 -1
  624. package/dist/substrate/runtime/process-supervisor.mjs.map +1 -1
  625. package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
  626. package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
  627. package/dist/substrate/runtime/projection/update.mjs +87 -11
  628. package/dist/substrate/runtime/projection/update.mjs.map +1 -1
  629. package/dist/substrate/runtime/random-suffix.mjs.map +1 -1
  630. package/dist/substrate/runtime/reconcile/fs-plan.mjs +146 -0
  631. package/dist/substrate/runtime/reconcile/fs-plan.mjs.map +1 -0
  632. package/dist/substrate/runtime/reconcile/graph.mjs +19 -0
  633. package/dist/substrate/runtime/reconcile/graph.mjs.map +1 -0
  634. package/dist/substrate/runtime/reconcile/index.mjs +5 -0
  635. package/dist/substrate/runtime/reconcile/label.mjs +41 -0
  636. package/dist/substrate/runtime/reconcile/label.mjs.map +1 -0
  637. package/dist/substrate/runtime/reconcile/spec.mjs +15 -0
  638. package/dist/substrate/runtime/reconcile/spec.mjs.map +1 -0
  639. package/dist/substrate/runtime/retry-policy.d.mts +2 -3
  640. package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
  641. package/dist/substrate/runtime/routed-url.mjs.map +1 -1
  642. package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
  643. package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
  644. package/dist/substrate/runtime/stage-and-swap/index.mjs +49 -12
  645. package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
  646. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -1
  647. package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
  648. package/dist/substrate/runtime/strategy-registry/service.mjs +29 -17
  649. package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
  650. package/dist/substrate/runtime/subnet-broker.mjs.map +1 -1
  651. package/dist/substrate/runtime/supervisor/acquire-node.mjs +188 -56
  652. package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -1
  653. package/dist/substrate/runtime/supervisor/background-tasks.mjs +79 -65
  654. package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -1
  655. package/dist/substrate/runtime/supervisor/command-loop.mjs +82 -23
  656. package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -1
  657. package/dist/substrate/runtime/supervisor/contribution-dispatcher.mjs +16 -0
  658. package/dist/substrate/runtime/supervisor/contribution-dispatcher.mjs.map +1 -0
  659. package/dist/substrate/runtime/supervisor/errors.mjs +11 -2
  660. package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -1
  661. package/dist/substrate/runtime/supervisor/index.mjs +2 -0
  662. package/dist/substrate/runtime/supervisor/shutdown.mjs +6 -6
  663. package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -1
  664. package/dist/substrate/runtime/supervisor/start-supervisor.mjs +60 -70
  665. package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -1
  666. package/dist/substrate/runtime/supervisor/state.d.mts +1 -1
  667. package/dist/substrate/runtime/supervisor/state.mjs +1 -1
  668. package/dist/substrate/runtime/supervisor/state.mjs.map +1 -1
  669. package/dist/substrate/runtime/supervisor/teardown.mjs +10 -9
  670. package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -1
  671. package/dist/substrate/runtime/supervisor/wiring.mjs +6 -20
  672. package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -1
  673. package/dist/substrate/runtime/tar/reader.mjs +216 -0
  674. package/dist/substrate/runtime/tar/reader.mjs.map +1 -0
  675. package/dist/substrate/runtime/typed-env.mjs.map +1 -1
  676. package/dist/substrate/versioned-doc-schema.mjs.map +1 -1
  677. package/dist/substrate/versioned-doc-sync.mjs +5 -5
  678. package/dist/substrate/versioned-doc-sync.mjs.map +1 -1
  679. package/dist/surfaces/cli/command-tree.mjs +49 -7
  680. package/dist/surfaces/cli/command-tree.mjs.map +1 -1
  681. package/dist/surfaces/cli/commands/config.mjs +1 -1
  682. package/dist/surfaces/cli/commands/config.mjs.map +1 -1
  683. package/dist/surfaces/cli/commands/confirm-node.mjs.map +1 -1
  684. package/dist/surfaces/cli/commands/confirm.mjs.map +1 -1
  685. package/dist/surfaces/cli/commands/doctor.mjs +1 -1
  686. package/dist/surfaces/cli/commands/doctor.mjs.map +1 -1
  687. package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -1
  688. package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
  689. package/dist/surfaces/cli/commands/prune.mjs +1 -1
  690. package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
  691. package/dist/surfaces/cli/commands/snapshot.mjs +1 -1
  692. package/dist/surfaces/cli/commands/snapshot.mjs.map +1 -1
  693. package/dist/surfaces/cli/commands/status.mjs +1 -1
  694. package/dist/surfaces/cli/commands/status.mjs.map +1 -1
  695. package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
  696. package/dist/surfaces/cli/commands/wipe.mjs +3 -4
  697. package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
  698. package/dist/surfaces/cli/envelope.mjs.map +1 -1
  699. package/dist/surfaces/cli/errors.mjs.map +1 -1
  700. package/dist/surfaces/cli/flags.mjs.map +1 -1
  701. package/dist/surfaces/cli/index.mjs +45 -14
  702. package/dist/surfaces/cli/index.mjs.map +1 -1
  703. package/dist/surfaces/cli/output.mjs.map +1 -1
  704. package/dist/surfaces/cli/sysexits.mjs.map +1 -1
  705. package/dist/surfaces/tui/app.mjs +0 -21
  706. package/dist/surfaces/tui/app.mjs.map +1 -1
  707. package/dist/surfaces/tui/dashboard.mjs +0 -48
  708. package/dist/surfaces/tui/dashboard.mjs.map +1 -1
  709. package/dist/surfaces/tui/display-derivation.mjs +80 -16
  710. package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
  711. package/dist/surfaces/tui/errors.mjs.map +1 -1
  712. package/dist/surfaces/tui/event-log.mjs +0 -9
  713. package/dist/surfaces/tui/event-log.mjs.map +1 -1
  714. package/dist/surfaces/tui/heartbeat.mjs.map +1 -1
  715. package/dist/surfaces/tui/index.mjs +2 -2
  716. package/dist/surfaces/tui/index.mjs.map +1 -1
  717. package/dist/surfaces/tui/input.mjs.map +1 -1
  718. package/dist/surfaces/tui/mode-detect.mjs.map +1 -1
  719. package/dist/surfaces/tui/mount-ink.mjs.map +1 -1
  720. package/dist/surfaces/tui/plain-renderer.mjs +26 -19
  721. package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
  722. package/dist/surfaces/tui/resource-table.mjs +8 -10
  723. package/dist/surfaces/tui/resource-table.mjs.map +1 -1
  724. package/images/postgres/Dockerfile +0 -1
  725. package/images/sui/Dockerfile +27 -54
  726. package/images/sui/entrypoint.sh +17 -179
  727. package/package.json +23 -15
  728. package/dashboard-ui/assets/index-Bmi1UtAg.js +0 -1356
  729. package/dashboard-ui/assets/index-D5EShVt4.js +0 -3
  730. package/dashboard-ui/assets/index-Deml9drg.css +0 -1
  731. package/dist/api/plugin-errors.d.mts +0 -7
  732. package/dist/api/plugin-errors.mjs +0 -10
  733. package/dist/api/plugin-errors.mjs.map +0 -1
  734. package/dist/cli/wirings/build-verb-layers.mjs +0 -42
  735. package/dist/cli/wirings/build-verb-layers.mjs.map +0 -1
  736. package/dist/contracts/capability-decl.d.mts +0 -40
  737. package/dist/orchestrators/built-in-plugin-layers.mjs +0 -54
  738. package/dist/orchestrators/built-in-plugin-layers.mjs.map +0 -1
  739. package/dist/orchestrators/run.mjs +0 -91
  740. package/dist/orchestrators/run.mjs.map +0 -1
  741. package/dist/orchestrators/runtime-composition.d.mts +0 -10
  742. package/dist/orchestrators/runtime-composition.mjs +0 -252
  743. package/dist/orchestrators/runtime-composition.mjs.map +0 -1
  744. package/dist/orchestrators/snapshot/capture-command.d.mts +0 -1
  745. package/dist/orchestrators/snapshot/capture-command.mjs +0 -25
  746. package/dist/orchestrators/snapshot/capture-command.mjs.map +0 -1
  747. package/dist/orchestrators/snapshot/pending-marker.mjs +0 -99
  748. package/dist/orchestrators/snapshot/pending-marker.mjs.map +0 -1
  749. package/dist/orchestrators/snapshot/recover-pending.mjs +0 -223
  750. package/dist/orchestrators/snapshot/recover-pending.mjs.map +0 -1
  751. package/dist/orchestrators/snapshot/state-document.d.mts +0 -1
  752. package/dist/orchestrators/snapshot/state-document.mjs +0 -58
  753. package/dist/orchestrators/snapshot/state-document.mjs.map +0 -1
  754. package/dist/plugins/account/spans.mjs +0 -16
  755. package/dist/plugins/account/spans.mjs.map +0 -1
  756. package/dist/plugins/account/variants/env.mjs +0 -24
  757. package/dist/plugins/account/variants/env.mjs.map +0 -1
  758. package/dist/plugins/account/variants/inline.mjs +0 -13
  759. package/dist/plugins/account/variants/inline.mjs.map +0 -1
  760. package/dist/plugins/account/variants/keystore.mjs +0 -91
  761. package/dist/plugins/account/variants/keystore.mjs.map +0 -1
  762. package/dist/plugins/action/spans.mjs +0 -11
  763. package/dist/plugins/action/spans.mjs.map +0 -1
  764. package/dist/plugins/coin/spans.mjs +0 -20
  765. package/dist/plugins/coin/spans.mjs.map +0 -1
  766. package/dist/plugins/deepbook/spans.mjs +0 -18
  767. package/dist/plugins/deepbook/spans.mjs.map +0 -1
  768. package/dist/plugins/faucet/spans.mjs +0 -12
  769. package/dist/plugins/faucet/spans.mjs.map +0 -1
  770. package/dist/plugins/package/spans.mjs +0 -14
  771. package/dist/plugins/package/spans.mjs.map +0 -1
  772. package/dist/plugins/postgres/codegen.mjs +0 -42
  773. package/dist/plugins/postgres/codegen.mjs.map +0 -1
  774. package/dist/plugins/postgres/connection.d.mts +0 -33
  775. package/dist/plugins/postgres/connection.mjs.map +0 -1
  776. package/dist/plugins/postgres/db-ensure.mjs.map +0 -1
  777. package/dist/plugins/postgres/errors.d.mts +0 -60
  778. package/dist/plugins/postgres/errors.mjs +0 -29
  779. package/dist/plugins/postgres/errors.mjs.map +0 -1
  780. package/dist/plugins/postgres/index.d.mts +0 -37
  781. package/dist/plugins/postgres/index.mjs +0 -68
  782. package/dist/plugins/postgres/index.mjs.map +0 -1
  783. package/dist/plugins/postgres/routable.mjs +0 -33
  784. package/dist/plugins/postgres/routable.mjs.map +0 -1
  785. package/dist/plugins/postgres/service.d.mts +0 -50
  786. package/dist/plugins/postgres/service.mjs +0 -179
  787. package/dist/plugins/postgres/service.mjs.map +0 -1
  788. package/dist/plugins/postgres/snapshot.mjs +0 -32
  789. package/dist/plugins/postgres/snapshot.mjs.map +0 -1
  790. package/dist/plugins/postgres/spans.mjs +0 -11
  791. package/dist/plugins/postgres/spans.mjs.map +0 -1
  792. package/dist/plugins/seal/spans.mjs +0 -18
  793. package/dist/plugins/seal/spans.mjs.map +0 -1
  794. package/dist/plugins/sui/spans.mjs +0 -17
  795. package/dist/plugins/sui/spans.mjs.map +0 -1
  796. package/dist/plugins/wallet/spans.mjs +0 -22
  797. package/dist/plugins/wallet/spans.mjs.map +0 -1
  798. package/dist/plugins/walrus/registry-publish.d.mts +0 -24
  799. package/dist/plugins/walrus/spans.mjs +0 -18
  800. package/dist/plugins/walrus/spans.mjs.map +0 -1
  801. package/dist/runtime/docker/logs.d.mts +0 -1
  802. package/dist/runtime/docker/logs.mjs +0 -34
  803. package/dist/runtime/docker/logs.mjs.map +0 -1
  804. package/dist/substrate/runtime/artifact-publisher/index.mjs +0 -86
  805. package/dist/substrate/runtime/artifact-publisher/index.mjs.map +0 -1
  806. package/dist/substrate/runtime/capability-sinks/index.d.mts +0 -1
  807. package/dist/substrate/runtime/capability-sinks/index.mjs +0 -3
  808. package/dist/substrate/runtime/capability-sinks/layer.d.mts +0 -1
  809. package/dist/substrate/runtime/capability-sinks/layer.mjs +0 -31
  810. package/dist/substrate/runtime/capability-sinks/layer.mjs.map +0 -1
  811. package/dist/substrate/runtime/capability-sinks/service.d.mts +0 -95
  812. package/dist/substrate/runtime/capability-sinks/service.mjs +0 -69
  813. package/dist/substrate/runtime/capability-sinks/service.mjs.map +0 -1
  814. package/dist/substrate/runtime/cross-process/lock.d.mts +0 -1
  815. package/dist/substrate/runtime/cross-process/lock.mjs +0 -23
  816. package/dist/substrate/runtime/cross-process/lock.mjs.map +0 -1
  817. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +0 -113
  818. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +0 -1
  819. package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs +0 -31
  820. package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +0 -1
  821. package/dist/substrate/runtime/observability/formatter-registry.d.mts +0 -1
  822. package/dist/substrate/runtime/observability/formatter-registry.mjs +0 -48
  823. package/dist/substrate/runtime/observability/formatter-registry.mjs.map +0 -1
  824. package/dist/substrate/runtime/observability/span-store.d.mts +0 -1
  825. package/dist/substrate/runtime/observability/span-store.mjs +0 -110
  826. package/dist/substrate/runtime/observability/span-store.mjs.map +0 -1
  827. package/dist/substrate/runtime/observability/spans.d.mts +0 -1
  828. package/dist/substrate/runtime/observability/spans.mjs +0 -87
  829. package/dist/substrate/runtime/observability/spans.mjs.map +0 -1
  830. package/dist/substrate/runtime/projection/index.mjs +0 -4
  831. package/dist/substrate/runtime/projection/persisted.mjs +0 -213
  832. package/dist/substrate/runtime/projection/persisted.mjs.map +0 -1
  833. package/dist/substrate/runtime/scoped-multimap/service.mjs +0 -52
  834. package/dist/substrate/runtime/scoped-multimap/service.mjs.map +0 -1
  835. package/dist/substrate/runtime/scoped-ref-map/index.mjs +0 -2
  836. package/dist/substrate/runtime/scoped-ref-map/service.mjs +0 -83
  837. package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +0 -1
  838. package/dist/substrate/runtime/state-store/index.mjs +0 -3
  839. package/dist/substrate/runtime/state-store/schema.d.mts +0 -1
  840. package/dist/substrate/runtime/state-store/schema.mjs +0 -41
  841. package/dist/substrate/runtime/state-store/schema.mjs.map +0 -1
  842. package/dist/substrate/runtime/state-store/service.d.mts +0 -1
  843. package/dist/substrate/runtime/state-store/service.mjs +0 -145
  844. package/dist/substrate/runtime/state-store/service.mjs.map +0 -1
  845. package/dist/substrate/runtime/sui-execute/index.mjs.map +0 -1
  846. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +0 -1
  847. package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +0 -1
  848. package/dist/substrate/runtime/sui-move-build/index.mjs.map +0 -1
  849. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +0 -151
  850. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +0 -1
  851. package/dist/substrate/state-store.d.mts +0 -1
  852. /package/dist/orchestrators/{snapshot/pending-marker.d.mts → codegen/id-config.d.mts} +0 -0
  853. /package/dist/orchestrators/snapshot/{recover-pending.d.mts → interrupted-restore.d.mts} +0 -0
  854. /package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/sign-and-dispatch.d.mts +0 -0
  855. /package/dist/plugins/{postgres/snapshot.d.mts → sui/ledger/object-ref.d.mts} +0 -0
  856. /package/dist/{substrate/runtime/sui-move-build → plugins/sui/move}/index.d.mts +0 -0
  857. /package/dist/substrate/runtime/{state-store/index.d.mts → reconcile/graph.d.mts} +0 -0
  858. /package/dist/substrate/runtime/{cross-process/snapshot-reservation.d.mts → supervisor/contribution-dispatcher.d.mts} +0 -0
@@ -58,78 +58,46 @@ const causeDetail = (cause) => {
58
58
  };
59
59
  const faucetCauseDetail = causeDetail;
60
60
  const fundingCauseDetail = causeDetail;
61
- const str = (v) => typeof v === "string" ? v : null;
62
- const strReq = (v) => typeof v === "string" ? v : "";
63
- const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
61
+ const newFaults = () => [];
62
+ /** Collapse accumulated faults into a single nullable detail string for the
63
+ * GraphQL-visible result. `null` when nothing drifted. */
64
+ const faultDetail = (faults) => faults.length === 0 ? null : faults.join("; ");
65
+ /** Describe why a value failed to narrow to the expected type — distinguishing
66
+ * 'absent' from 'present but wrong type'. */
67
+ const typeFault = (field, expected, v) => {
68
+ if (v === void 0 || v === null) return `${field}: missing (expected ${expected})`;
69
+ return `${field}: expected ${expected}, got ${typeof v}`;
70
+ };
71
+ /** Required string. On mismatch records a fault and returns '' so the panel
72
+ * still renders a (degraded) cell. */
73
+ const reqStr = (v, field, faults) => {
74
+ if (typeof v === "string") return v;
75
+ faults.push(typeFault(field, "string", v));
76
+ return "";
77
+ };
78
+ /** Required finite number. On mismatch records a fault and returns the safe
79
+ * display fallback (`fallback`, default 0). */
80
+ const reqNum = (v, field, faults, fallback = 0) => {
81
+ if (typeof v === "number" && Number.isFinite(v)) return v;
82
+ faults.push(typeFault(field, "number", v));
83
+ return fallback;
84
+ };
85
+ /** Allow-list enum narrow. Records a fault for an out-of-enum value while
86
+ * still returning a safe display fallback so the panel renders. */
87
+ const narrowEnum = (raw, allowed, field, faults, fallback) => {
88
+ if (typeof raw === "string" && allowed.includes(raw)) return raw;
89
+ faults.push(raw === void 0 || raw === null ? `${field}: missing (expected one of ${allowed.join("|")})` : `${field}: '${String(raw)}' not in ${allowed.join("|")}`);
90
+ return fallback;
91
+ };
92
+ const optStr = (v) => typeof v === "string" ? v : null;
93
+ const optNum = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
64
94
  const bool = (v) => v === true;
65
95
  /** Filter the generic resolved values down to those whose resource id
66
96
  * matches a predicate, in graph order. Returns the `{ pluginKey, value }`
67
97
  * the shaping functions consume. */
68
98
  const matching = (values, matches) => values.filter((v) => matches(v.id));
69
- /** SQL that emits a single line of JSON the dashboard can parse without a
70
- * PG client. Keeps the round trip to one exec. */
71
- const PG_STATS_SQL = `SELECT json_build_object(
72
- 'db_bytes', pg_database_size(current_database()),
73
- 'connections', (SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()),
74
- 'tables', COALESCE((
75
- SELECT json_agg(t) FROM (
76
- SELECT schemaname AS schema, relname AS name,
77
- n_live_tup AS row_estimate,
78
- pg_total_relation_size(relid) AS total_bytes
79
- FROM pg_stat_user_tables
80
- ORDER BY pg_total_relation_size(relid) DESC
81
- LIMIT 200
82
- ) t
83
- ), '[]'::json)
84
- )`;
85
- const parsePgStats = (pluginKey, pg, stdout) => {
86
- const base = {
87
- pluginKey,
88
- database: strReq((pg.databases ?? [])[0]) || "postgres",
89
- plainUrl: `postgres://${str(pg.networkAlias) ?? "postgres"}:${num(pg.port) ?? 5432}`
90
- };
91
- try {
92
- const trimmed = stdout.trim();
93
- const parsed = JSON.parse(trimmed);
94
- const tables = (parsed.tables ?? []).map((t) => ({
95
- schema: t.schema ?? "public",
96
- name: t.name ?? "",
97
- rowEstimate: num(t.row_estimate) ?? 0,
98
- totalBytes: num(t.total_bytes) ?? 0
99
- }));
100
- return {
101
- ...base,
102
- databaseBytes: num(parsed.db_bytes) ?? 0,
103
- connectionCount: num(parsed.connections) ?? 0,
104
- tables,
105
- available: true,
106
- detail: null
107
- };
108
- } catch (cause) {
109
- return {
110
- ...base,
111
- databaseBytes: 0,
112
- connectionCount: 0,
113
- tables: [],
114
- available: false,
115
- detail: `failed to parse psql output: ${String(cause)}`
116
- };
117
- }
118
- };
119
- const unavailablePgStats = (pluginKey, pg, detail) => {
120
- return {
121
- pluginKey,
122
- database: strReq((pg.databases ?? [])[0]) || "postgres",
123
- plainUrl: `postgres://${str(pg.networkAlias) ?? "postgres"}:${num(pg.port) ?? 5432}`,
124
- databaseBytes: 0,
125
- connectionCount: 0,
126
- tables: [],
127
- available: false,
128
- detail
129
- };
130
- };
131
99
  const buildDashboardDomain = (deps) => {
132
- const { control, identity, containerRuntime, strategyRegistry } = deps;
100
+ const { control, strategyRegistry } = deps;
133
101
  const mode = control.resolvedValues.pipe(Effect.map((values) => {
134
102
  const sui = matching(values, (id) => id === "sui")[0];
135
103
  if (sui === void 0) return null;
@@ -143,55 +111,72 @@ const buildDashboardDomain = (deps) => {
143
111
  }));
144
112
  const deepbook = control.resolvedValues.pipe(Effect.map((values) => matching(values, (id) => id.startsWith("deepbook/")).map(({ pluginKey, value }) => {
145
113
  const v = value;
146
- const modeRaw = v.mode;
147
- const dbMode = modeRaw === "override" ? "override" : modeRaw === "known" ? "known" : "local";
114
+ const faults = newFaults();
115
+ const dbMode = narrowEnum(v.mode, [
116
+ "local",
117
+ "override",
118
+ "known"
119
+ ], "deepbook.mode", faults, "local");
148
120
  return {
149
121
  pluginKey,
150
122
  name: pluginKey.replace(/^deepbook:/, ""),
151
123
  mode: dbMode,
152
- chain: strReq(v.chain),
153
- packageId: strReq(v.packageId),
154
- registryId: strReq(v.registryId),
155
- adminCapId: str(v.adminCapId),
156
- deepTreasuryId: str(v.deepTreasuryId),
157
- pools: (v.pools ?? []).map((p) => ({
158
- name: strReq(p.name),
159
- poolId: strReq(p.poolId),
160
- baseCoinType: strReq(p.baseCoinType),
161
- quoteCoinType: strReq(p.quoteCoinType)
124
+ network: reqStr(v.network, "deepbook.network", faults),
125
+ packageId: reqStr(v.packageId, "deepbook.packageId", faults),
126
+ registryId: reqStr(v.registryId, "deepbook.registryId", faults),
127
+ adminCapId: optStr(v.adminCapId),
128
+ deepTreasuryId: optStr(v.deepTreasuryId),
129
+ pools: (v.pools ?? []).map((p, i) => ({
130
+ name: reqStr(p.name, `deepbook.pools[${i}].name`, faults),
131
+ poolId: reqStr(p.poolId, `deepbook.pools[${i}].poolId`, faults),
132
+ baseCoinType: reqStr(p.baseCoinType, `deepbook.pools[${i}].baseCoinType`, faults),
133
+ quoteCoinType: reqStr(p.quoteCoinType, `deepbook.pools[${i}].quoteCoinType`, faults)
162
134
  })),
163
135
  marketMakerRunning: bool(v.marketMakerRunning),
164
- serverUrl: str(v.serverUrl),
165
- indexerUrl: str(v.indexerUrl)
136
+ serverUrl: optStr(v.serverUrl),
137
+ indexerUrl: optStr(v.indexerUrl),
138
+ narrowingFault: faultDetail(faults)
166
139
  };
167
140
  })));
168
141
  const seal = control.resolvedValues.pipe(Effect.map((values) => matching(values, (id) => id.startsWith("seal:")).map(({ pluginKey, value }) => {
169
142
  const v = value;
170
- const sealMode = v.mode === "live" ? "live" : v.mode === "fork-known" ? "fork-known" : "local-keygen";
171
- const keyServers = (v.serverConfigs ?? []).map((c) => ({
172
- objectId: strReq(c.objectId),
173
- weight: num(c.weight) ?? 1
143
+ const faults = newFaults();
144
+ const sealMode = narrowEnum(v.mode, [
145
+ "local-keygen",
146
+ "live",
147
+ "fork-known"
148
+ ], "seal.mode", faults, "local-keygen");
149
+ const keyServers = (v.serverConfigs ?? []).map((c, i) => ({
150
+ objectId: reqStr(c.objectId, `seal.serverConfigs[${i}].objectId`, faults),
151
+ weight: optNum(c.weight) ?? 1
174
152
  }));
175
153
  return {
176
154
  pluginKey,
177
155
  mode: sealMode,
178
- objectId: strReq(v.objectId),
179
- keyServerUrl: strReq(v.keyServerUrl),
156
+ objectId: reqStr(v.objectId, "seal.objectId", faults),
157
+ keyServerUrl: reqStr(v.keyServerUrl, "seal.keyServerUrl", faults),
180
158
  keyServers,
181
- threshold: keyServers.length
159
+ threshold: keyServers.length,
160
+ narrowingFault: faultDetail(faults)
182
161
  };
183
162
  })));
184
163
  const coinCaps = control.resolvedValues.pipe(Effect.map((values) => matching(values, (id) => id.startsWith("coin:")).map(({ pluginKey, value }) => {
185
164
  const v = value;
186
- const source = v.source === "registry" ? "registry" : v.source === "builtin" ? "builtin" : "on-chain";
165
+ const faults = newFaults();
166
+ const source = narrowEnum(v.source, [
167
+ "registry",
168
+ "on-chain",
169
+ "builtin"
170
+ ], "coin.source", faults, "on-chain");
187
171
  return {
188
172
  pluginKey,
189
- symbol: str(v.symbol),
190
- fullCoinType: strReq(v.fullCoinType),
191
- decimals: num(v.decimals) ?? 0,
173
+ symbol: optStr(v.symbol),
174
+ fullCoinType: reqStr(v.fullCoinType, "coin.fullCoinType", faults),
175
+ decimals: reqNum(v.decimals, "coin.decimals", faults, 0),
192
176
  source,
193
- treasuryCapId: str(v.treasuryCapId),
194
- packageId: str(v.packageId)
177
+ treasuryCapId: optStr(v.treasuryCapId),
178
+ packageId: optStr(v.packageId),
179
+ narrowingFault: faultDetail(faults)
195
180
  };
196
181
  })));
197
182
  const mintCoin = (input) => Effect.gen(function* () {
@@ -206,12 +191,17 @@ const buildDashboardDomain = (deps) => {
206
191
  detail: `invalid amountBaseUnits '${input.amountBaseUnits}': expected a positive integer string`,
207
192
  digest: null
208
193
  };
209
- const match = matching(yield* control.resolvedValues, (id) => id.startsWith("coin:")).map(({ value }) => value).find((v) => strReq(v.fullCoinType) === input.coinType);
210
- if (match === void 0) return {
211
- ok: false,
212
- detail: `no resolved coin found for type '${input.coinType}'`,
213
- digest: null
214
- };
194
+ const candidates = matching(yield* control.resolvedValues, (id) => id.startsWith("coin:")).map(({ value }) => value);
195
+ const matchFaults = newFaults();
196
+ const match = candidates.find((v) => reqStr(v.fullCoinType, "coin.fullCoinType", matchFaults) === input.coinType);
197
+ if (match === void 0) {
198
+ const fault = faultDetail(matchFaults);
199
+ return {
200
+ ok: false,
201
+ detail: fault === null ? `no resolved coin found for type '${input.coinType}'` : `no resolved coin found for type '${input.coinType}' (${fault})`,
202
+ digest: null
203
+ };
204
+ }
215
205
  if (typeof match.mintFromCap !== "function") return {
216
206
  ok: false,
217
207
  detail: `coin '${input.coinType}' has no in-process treasury cap signer — mint is only available for local-package coins whose publisher still owns the TreasuryCap`,
@@ -235,10 +225,10 @@ const buildDashboardDomain = (deps) => {
235
225
  })));
236
226
  });
237
227
  /** The chain id the SUI funding path keys on, read from the resolved sui
238
- * value (same `chain` field the sui codegen/snapshot decls stamp). */
228
+ * value (same `chainId` field the sui codegen/snapshot decls stamp). */
239
229
  const readChainId = control.resolvedValues.pipe(Effect.map((values) => {
240
230
  const sui = matching(values, (id) => id === "sui")[0];
241
- return sui === void 0 ? null : str(sui.value.chain);
231
+ return sui === void 0 ? null : optStr(sui.value.chainId);
242
232
  }));
243
233
  const fundableCoins = Effect.gen(function* () {
244
234
  const out = [];
@@ -269,28 +259,24 @@ const buildDashboardDomain = (deps) => {
269
259
  const recipient = input.recipient.trim();
270
260
  if (!SUI_ADDRESS_RE.test(recipient)) return {
271
261
  ok: false,
272
- detail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,
273
- digest: null
262
+ detail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`
274
263
  };
275
264
  if (strategyRegistry === null) return {
276
265
  ok: false,
277
- detail: "funding unavailable: no strategy registry wired",
278
- digest: null
266
+ detail: "funding unavailable: no strategy registry wired"
279
267
  };
280
268
  const coinType = input.coinType?.trim() ?? "";
281
269
  if (coinType === "" || coinType === SUI_FULL_COIN_TYPE) {
282
270
  const chain = yield* readChainId;
283
271
  if (chain === null) return {
284
272
  ok: false,
285
- detail: "cannot fund SUI: no resolved sui plugin / chain id in this stack",
286
- digest: null
273
+ detail: "cannot fund SUI: no resolved sui plugin / chain id in this stack"
287
274
  };
288
275
  const key = faucetCapabilityKeyFor(chain);
289
276
  const strategy = yield* strategyRegistry.get(key).pipe(Effect.catchTag("StrategyNotFoundError", () => Effect.succeed(null)));
290
277
  if (strategy === null) return {
291
278
  ok: false,
292
- detail: `no SUI faucet strategy registered for chain '${chain}'`,
293
- digest: null
279
+ detail: `no SUI faucet strategy registered for chain '${chain}'`
294
280
  };
295
281
  const amount = parseAmount(input.amountBaseUnits) ?? 1000000000n;
296
282
  return yield* strategy.request({
@@ -298,36 +284,30 @@ const buildDashboardDomain = (deps) => {
298
284
  amount
299
285
  }).pipe(Effect.map(() => ({
300
286
  ok: true,
301
- detail: `requested SUI for ${recipient} (fixed-amount faucet grant)`,
302
- digest: null
287
+ detail: `requested SUI for ${recipient} (fixed-amount faucet grant)`
303
288
  })), Effect.catch((cause) => Effect.succeed({
304
289
  ok: false,
305
- detail: `SUI faucet request failed: ${faucetCauseDetail(cause)}`,
306
- digest: null
290
+ detail: `SUI faucet request failed: ${faucetCauseDetail(cause)}`
307
291
  })), Effect.catchCause((cause) => Effect.succeed({
308
292
  ok: false,
309
- detail: `SUI faucet request crashed: ${String(cause)}`,
310
- digest: null
293
+ detail: `SUI faucet request crashed: ${String(cause)}`
311
294
  })));
312
295
  }
313
296
  const amount = parseAmount(input.amountBaseUnits);
314
297
  if (amount === null) return {
315
298
  ok: false,
316
- detail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ""}': expected a positive integer string`,
317
- digest: null
299
+ detail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ""}': expected a positive integer string`
318
300
  };
319
301
  const key = `coinType:${coinType}`;
320
302
  const strategy = yield* strategyRegistry.get(key).pipe(Effect.catchTag("StrategyNotFoundError", () => Effect.succeed(null)));
321
303
  if (strategy === null) return {
322
304
  ok: false,
323
- detail: `no funding strategy registered for coin '${coinType}' — WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin`,
324
- digest: null
305
+ detail: `no funding strategy registered for coin '${coinType}' — WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin`
325
306
  };
326
- const account = matching(yield* control.resolvedValues, (id) => id.startsWith("account/")).map(({ value }) => value).find((v) => str(v.address) === recipient);
307
+ const account = matching(yield* control.resolvedValues, (id) => id.startsWith("account/")).map(({ value }) => value).find((v) => optStr(v.address) === recipient);
327
308
  if (strategy.requiresRecipientAccount === true && account === void 0) return {
328
309
  ok: false,
329
- detail: `coin '${coinType}' is funded by an account-signed swap, but '${recipient}' is not a resolved account in this stack — fund a configured account (the swap spends its SUI)`,
330
- digest: null
310
+ detail: `coin '${coinType}' is funded by an account-signed swap, but '${recipient}' is not a resolved account in this stack — fund a configured account (the swap spends its SUI)`
331
311
  };
332
312
  return yield* strategy.request({
333
313
  address: recipient,
@@ -335,16 +315,13 @@ const buildDashboardDomain = (deps) => {
335
315
  ...account === void 0 ? {} : { account }
336
316
  }).pipe(Effect.map(() => ({
337
317
  ok: true,
338
- detail: `funded ${amount} base units of ${coinType} to ${recipient}`,
339
- digest: null
318
+ detail: `funded ${amount} base units of ${coinType} to ${recipient}`
340
319
  })), Effect.catch((cause) => Effect.succeed({
341
320
  ok: false,
342
- detail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}`,
343
- digest: null
321
+ detail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}`
344
322
  })), Effect.catchCause((cause) => Effect.succeed({
345
323
  ok: false,
346
- detail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}`,
347
- digest: null
324
+ detail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}`
348
325
  })));
349
326
  });
350
327
  return {
@@ -352,50 +329,12 @@ const buildDashboardDomain = (deps) => {
352
329
  deepbook,
353
330
  seal,
354
331
  coinCaps,
355
- postgresStats: Effect.gen(function* () {
356
- const instances = matching(yield* control.resolvedValues, (id) => id === "postgres");
357
- if (instances.length === 0) return [];
358
- const out = [];
359
- for (const { pluginKey, value } of instances) {
360
- const pg = value;
361
- if (containerRuntime === null) {
362
- out.push(unavailablePgStats(pluginKey, pg, "container runtime unavailable"));
363
- continue;
364
- }
365
- const database = strReq((pg.databases ?? [])[0]) || "postgres";
366
- const pgUser = str(pg.user) ?? "postgres";
367
- const role = str(pg.name) ?? "postgres";
368
- const stats = yield* Effect.gen(function* () {
369
- const handles = yield* containerRuntime.inspectByLabels({
370
- app: String(identity.app),
371
- stack: String(identity.stack),
372
- plugin: "postgres",
373
- role
374
- });
375
- const running = handles.find((h) => h.status === "running") ?? handles[0];
376
- if (running === void 0) return unavailablePgStats(pluginKey, pg, "no running postgres container found");
377
- const result = yield* containerRuntime.exec(running, [
378
- "psql",
379
- "-U",
380
- pgUser,
381
- "-d",
382
- database,
383
- "-tAc",
384
- PG_STATS_SQL
385
- ]);
386
- if (result.exitCode !== 0) return unavailablePgStats(pluginKey, pg, `psql exited ${result.exitCode}: ${result.stderr.trim().slice(0, 200)}`);
387
- return parsePgStats(pluginKey, pg, result.stdout);
388
- }).pipe(Effect.catchCause((cause) => Effect.succeed(unavailablePgStats(pluginKey, pg, String(cause)))));
389
- out.push(stats);
390
- }
391
- return out;
392
- }),
393
332
  mintCoin,
394
333
  fundableCoins,
395
334
  fundAccount
396
335
  };
397
336
  };
398
- Effect.succeed(null), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]);
337
+ Effect.succeed(null), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]), Effect.succeed([]);
399
338
  //#endregion
400
339
  export { buildDashboardDomain };
401
340
 
@@ -1 +1 @@
1
- {"version":3,"file":"domain.mjs","names":[],"sources":["../../../src/plugins/dashboard/domain.ts"],"sourcesContent":["// Dashboard plugin-domain shaping.\n//\n// The substrate control-plane is GENERIC + name-blind: it hands out the\n// snapshot catalog, the observability rings, and a single uninterpreted\n// `resolvedValues` accessor (see `substrate/runtime/control-plane/`). This\n// module — which lives in the PLUGIN layer and is allowed to name plugins —\n// owns ALL plugin-name-aware shaping: it matches resolved plugin values by\n// resource id (`deepbook/`-prefix, `seal:`-prefix, `coin:`-prefix,\n// `id === 'sui'`, `id === 'postgres'`) and projects them into the\n// app-agnostic shapes the\n// GraphQL schema renders. It also owns the `mode` derivation, the coin\n// `mint` action, and the Postgres `psql`-exec wire-protocol stats.\n//\n// Design discipline (mirrors the old substrate seam, one layer up):\n// - We import NO plugin types — we narrow the opaque `unknown` resolved\n// value through shallow structural shapes that mirror the relevant\n// fields. A field missing on the live value collapses to the\n// null/empty default.\n// - Every accessor degrades to empty/`null` rather than failing, so a\n// single missing/uninitialised plugin can't take down a dashboard\n// query (`E = never` on the public surface).\n// - We match plugins by RESOURCE ID — a prefix for the multi-instance\n// kinds (`deepbook/`, `seal:`, `coin:`) and an exact id for the\n// singletons (`id === 'postgres'`, `id === 'sui'`) — rather than\n// plugin-key substrings: the resource id is the stable identity the\n// plugin factories mint.\n\nimport { Effect } from 'effect';\n\nimport type { ContainerRuntime } from '../../contracts/container-runtime.ts';\nimport type { Identity } from '../../substrate/identity.ts';\nimport type {\n\tControlPlaneDomain,\n\tControlPlaneResolvedValue,\n} from '../../substrate/runtime/control-plane/service.ts';\nimport type { StrategyRegistry } from '../../contracts/strategy-contributor.ts';\nimport type { FaucetStrategy } from '../../contracts/faucet-strategy.ts';\nimport type { AccountFundingStrategy } from '../../contracts/funding-strategy.ts';\nimport type { AccountValue } from '../account/index.ts';\n// The faucet capability-key prefix is owned by the faucet plugin (single\n// source of truth). The dashboard plugin layer is allowed to name plugins,\n// so importing the key constructor is the same cross-plugin reference the\n// account funding pass (`plugins/account/funding.ts`) uses — NOT a resolved\n// plugin-VALUE import (those stay structurally narrowed below). Imported via\n// the sibling's barrel to satisfy the plugin-boundary invariant.\nimport { FAUCET_CAPABILITY_KEY_PREFIX } from '../faucet/index.ts';\n\n// -----------------------------------------------------------------------------\n// App-agnostic domain shapes the GraphQL schema renders.\n// -----------------------------------------------------------------------------\n\n/** One DeepBook pool object id + coin types (prices are chain-direct). */\nexport interface DashboardDeepbookPool {\n\treadonly name: string;\n\treadonly poolId: string;\n\treadonly baseCoinType: string;\n\treadonly quoteCoinType: string;\n}\n\nexport interface DashboardDeepbookInfo {\n\treadonly pluginKey: string;\n\treadonly name: string;\n\treadonly mode: 'local' | 'override' | 'known';\n\treadonly chain: string;\n\treadonly packageId: string;\n\treadonly registryId: string;\n\treadonly adminCapId: string | null;\n\treadonly deepTreasuryId: string | null;\n\treadonly pools: ReadonlyArray<DashboardDeepbookPool>;\n\treadonly marketMakerRunning: boolean;\n\treadonly serverUrl: string | null;\n\treadonly indexerUrl: string | null;\n}\n\nexport interface DashboardSealKeyServer {\n\treadonly objectId: string;\n\treadonly weight: number;\n}\n\nexport interface DashboardSealInfo {\n\treadonly pluginKey: string;\n\treadonly mode: 'local-keygen' | 'live' | 'fork-known';\n\treadonly objectId: string;\n\treadonly keyServerUrl: string;\n\treadonly keyServers: ReadonlyArray<DashboardSealKeyServer>;\n\t/** Threshold = number of registered key-server configs. */\n\treadonly threshold: number;\n}\n\n/** A coin's treasury-cap id (drives the Mint action) + addressing facts. */\nexport interface DashboardCoinCap {\n\treadonly pluginKey: string;\n\treadonly symbol: string | null;\n\treadonly fullCoinType: string;\n\treadonly decimals: number;\n\treadonly source: 'registry' | 'on-chain' | 'builtin';\n\treadonly treasuryCapId: string | null;\n\treadonly packageId: string | null;\n}\n\n/** Input for the dashboard mint ACTION. `amountBaseUnits` is the raw\n * integer amount in the coin's smallest unit (decimals already applied\n * by the caller / form) — a string so large u64 values survive the wire\n * without precision loss. */\nexport interface DashboardMintInput {\n\treadonly coinType: string;\n\treadonly recipient: string;\n\treadonly amountBaseUnits: string;\n}\n\n/** Outcome of a dashboard mint ACTION. Mirrors the snapshot\n * restore/delete result shape plus the on-chain tx `digest` on success. */\nexport interface DashboardMintResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\n}\n\n/** Input for the dashboard fund ACTION.\n *\n * `coinType` selects the funding strategy: absent or the canonical SUI\n * type routes through the chain's faucet strategy (`faucet:request:<chainId>`,\n * fixed-amount); any other full coin type routes through the coin-specific\n * `coinType:<fullCoinType>` strategy (WAL exchange swap / DEEP pool swap).\n *\n * `amountBaseUnits` is the raw integer amount in the coin's smallest unit\n * (a string so large u64 values survive the wire without precision loss).\n * The SUI faucet is fixed-amount and IGNORES it; WAL/DEEP honor it. */\nexport interface DashboardFundInput {\n\treadonly recipient: string;\n\treadonly coinType?: string | null;\n\treadonly amountBaseUnits?: string | null;\n}\n\n/** Outcome of a dashboard fund ACTION. The in-process funding strategies\n * return `void` (not a digest), so `digest` is always `null` here — kept\n * for shape-parity with `DashboardMintResult`. `ok:true` means the\n * strategy's `request(...)` completed (the faucet POST landed / the swap\n * executed on-chain); `detail` carries the reason on failure. */\nexport interface DashboardFundResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\n}\n\n/** One coin the dashboard faucet can actually fund, with whether the\n * underlying strategy honors a caller-supplied amount.\n *\n * SUI is always present (fixed-amount faucet, `honorsAmount: false`).\n * WAL/DEEP appear only when their plugin registered a `coinType:<X>`\n * funding strategy AND (for WAL) carries a swap that spends the\n * recipient account's SUI — so `honorsAmount: true`. */\nexport interface DashboardFundableCoin {\n\treadonly symbol: string;\n\treadonly coinType: string;\n\treadonly honorsAmount: boolean;\n\t/** True when funding requires the recipient to BE a resolved account in\n\t * the stack (the swap spends that account's own SUI via its in-process\n\t * signer). SUI is `false` (any 0x address); WAL/DEEP are `true`. */\n\treadonly requiresAccountSigner: boolean;\n}\n\nexport interface DashboardPostgresTable {\n\treadonly schema: string;\n\treadonly name: string;\n\treadonly rowEstimate: number;\n\treadonly totalBytes: number;\n}\n\nexport interface DashboardPostgresStats {\n\treadonly pluginKey: string;\n\treadonly database: string;\n\t/** Plain (password-less) DSN — the credentialed form NEVER leaves the\n\t * backend. */\n\treadonly plainUrl: string;\n\treadonly databaseBytes: number;\n\treadonly connectionCount: number;\n\treadonly tables: ReadonlyArray<DashboardPostgresTable>;\n\t/** `false` when stats could not be gathered (container down, exec\n\t * failure). The dashboard renders a degraded state rather than\n\t * failing the whole query. */\n\treadonly available: boolean;\n\treadonly detail: string | null;\n}\n\n/** The dashboard plugin-domain accessor surface. Each member is a\n * self-contained Effect that never fails (`E = never`); they degrade to\n * empty/`null` so a single missing plugin can't take down the dashboard\n * query. */\nexport interface DashboardDomain {\n\t/** Fork-vs-local mode, derived from the resolved sui plugin's chain\n\t * identity. Used for advance-clock gating. `null` when no sui plugin\n\t * is present. */\n\treadonly mode: Effect.Effect<'fork' | 'local' | 'live' | null>;\n\t/** DeepBook deployments (registry/admin/pool ids + MM state). */\n\treadonly deepbook: Effect.Effect<ReadonlyArray<DashboardDeepbookInfo>>;\n\t/** Seal key-server deployments (objectId/threshold/mode). */\n\treadonly seal: Effect.Effect<ReadonlyArray<DashboardSealInfo>>;\n\t/** Coin treasury caps (drives Mint). */\n\treadonly coinCaps: Effect.Effect<ReadonlyArray<DashboardCoinCap>>;\n\t/** Postgres wire-protocol stats per postgres plugin instance. */\n\treadonly postgresStats: Effect.Effect<ReadonlyArray<DashboardPostgresStats>>;\n\t/** Mint ACTION — mints `amountBaseUnits` of `coinType` to `recipient`,\n\t * signed in-process by the treasury-cap-owning publisher signer the\n\t * resolved coin value's self-contained `mintFromCap` closure holds. */\n\treadonly mintCoin: (input: DashboardMintInput) => Effect.Effect<DashboardMintResult>;\n\t/** Coins the faucet can actually fund right now (SUI always; WAL/DEEP\n\t * only when their plugin registered a funding strategy). Drives the\n\t * faucet panel's coin pills + amount-field gating. */\n\treadonly fundableCoins: Effect.Effect<ReadonlyArray<DashboardFundableCoin>>;\n\t/** Fund ACTION — reuses devstack's in-process funding strategies. SUI\n\t * (absent/canonical type) routes through the chain faucet strategy\n\t * (fixed-amount); WAL/DEEP route through the coin-specific funding\n\t * strategy (account-signed exchange/pool swap). Real result — `ok`\n\t * reflects whether the strategy's `request(...)` completed. */\n\treadonly fundAccount: (input: DashboardFundInput) => Effect.Effect<DashboardFundResult>;\n}\n\n// -----------------------------------------------------------------------------\n// Structural projections of plugin-resolved values\n//\n// We narrow the opaque `unknown` resolved value through shallow structural\n// shapes that mirror the relevant fields. A field missing on the live value\n// collapses to the null/empty default.\n// -----------------------------------------------------------------------------\n\ninterface DeepbookShape {\n\treadonly mode?: unknown;\n\treadonly chain?: unknown;\n\treadonly packageId?: unknown;\n\treadonly registryId?: unknown;\n\treadonly adminCapId?: unknown;\n\treadonly deepTreasuryId?: unknown;\n\treadonly pools?: ReadonlyArray<{\n\t\treadonly name?: unknown;\n\t\treadonly poolId?: unknown;\n\t\treadonly baseCoinType?: unknown;\n\t\treadonly quoteCoinType?: unknown;\n\t}>;\n\treadonly marketMakerRunning?: unknown;\n\treadonly serverUrl?: unknown;\n\treadonly indexerUrl?: unknown;\n}\n\ninterface SealShape {\n\treadonly mode?: unknown;\n\treadonly objectId?: unknown;\n\treadonly keyServerUrl?: unknown;\n\treadonly serverConfigs?: ReadonlyArray<{\n\t\treadonly objectId?: unknown;\n\t\treadonly weight?: unknown;\n\t}>;\n}\n\ninterface CoinShape {\n\treadonly symbol?: unknown;\n\treadonly fullCoinType?: unknown;\n\treadonly decimals?: unknown;\n\treadonly source?: unknown;\n\treadonly treasuryCapId?: unknown;\n\treadonly packageId?: unknown;\n\t/** Self-contained mint closure on the resolved coin value (present\n\t * for witness-form coins whose publisher still owns the cap). Read\n\t * structurally — we import no coin types. Returns an Effect that\n\t * resolves a `{ digest }`-bearing result or fails with a\n\t * coin/artifact-publisher tagged error. */\n\treadonly mintFromCap?: (opts: {\n\t\treadonly to: string;\n\t\treadonly amount: bigint;\n\t}) => Effect.Effect<{ readonly digest: string }, { readonly message?: unknown }>;\n}\n\ninterface PostgresShape {\n\treadonly name?: unknown;\n\treadonly user?: unknown;\n\treadonly databases?: ReadonlyArray<unknown>;\n\treadonly plainEndpoint?: unknown;\n\treadonly networkAlias?: unknown;\n\treadonly port?: unknown;\n}\n\ninterface SuiShape {\n\treadonly mode?: unknown;\n\t/** Substrate-level chain id (`'sui:localnet'`, `'sui:testnet'`,\n\t * `'sui:mainnet-fork@123'`). Composes the faucet capability key\n\t * (`faucet:request:<chainId>`) the SUI funding path resolves. */\n\treadonly chain?: unknown;\n}\n\n/** Structural shape of the resolved account value (`account/<name>`). The\n * WAL/DEEP funding strategies need this handle as `req.account` — the swap\n * spends the recipient account's own SUI through its in-process signer.\n * Narrowed to the fields the strategy dispatch reads; the full\n * `AccountValue` is assignable to it, so we cast the matched value across\n * the seam without importing the account VALUE shape structurally\n * elsewhere. */\ninterface AccountShape {\n\treadonly address?: unknown;\n\treadonly name?: unknown;\n}\n\n/** A 0x-prefixed Sui address: `0x` + 1..64 hex digits. Mirrors the\n * address validation the mint PTB's `tx.pure.address` ultimately\n * enforces, surfaced up front so the dashboard gets a clean rejection\n * rather than an opaque build failure. */\nconst SUI_ADDRESS_RE = /^0x[0-9a-fA-F]{1,64}$/;\n\n/** The canonical builtin SUI coin type — selects the SUI faucet funding\n * path. Mirrors `SUI_FULL_COIN_TYPE` in `plugins/account/funding.ts`\n * (inlined here so the dashboard plugin does not cross-import the account\n * funding module just for the string). */\nconst SUI_FULL_COIN_TYPE = '0x2::sui::SUI' as const;\n\n/** A positive integer base-unit amount string (no sign, no decimal\n * point, no leading zeros beyond a bare `0` — which is itself rejected\n * as non-positive). */\nconst isPositiveIntegerString = (s: string): boolean => {\n\tif (!/^\\d+$/.test(s)) return false;\n\ttry {\n\t\treturn BigInt(s) > 0n;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** Compose the chain faucet capability key (`faucet:request:<chainId>`)\n * the SUI funding path resolves. Uses the faucet plugin's prefix constant\n * (single source of truth) — same key the boot-time funding pass builds. */\nconst faucetCapabilityKeyFor = (\n\tchain: string,\n): `${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${string}` => `${FAUCET_CAPABILITY_KEY_PREFIX}:${chain}`;\n\n/** Parse a base-unit amount string into a positive bigint, or `null` when\n * absent / non-positive / non-integer. */\nconst parseAmount = (s: string | null | undefined): bigint | null => {\n\tif (s == null) return null;\n\tconst trimmed = s.trim();\n\tif (!isPositiveIntegerString(trimmed)) return null;\n\treturn BigInt(trimmed);\n};\n\n/** Derive a display symbol from a full coin type's module path\n * (`0x…::wal::WAL` → `WAL`, `0x…::deep::DEEP` → `DEEP`). Falls back to the\n * struct name, then the raw type. Keeps the dashboard name-blind on the\n * resolved coin VALUE while still labeling the faucet pill. */\nconst coinSymbolFromType = (coinType: string): string => {\n\tconst parts = coinType.split('::');\n\tconst struct = parts[parts.length - 1];\n\treturn struct !== undefined && struct.length > 0 ? struct : coinType;\n};\n\n/** Extract a human detail from a faucet/funding strategy failure. The\n * strategy error channels are tagged structs carrying `message`/`reason`;\n * read them structurally without importing each plugin's error type. */\nconst causeDetail = (cause: unknown): string => {\n\tif (cause !== null && typeof cause === 'object') {\n\t\tconst c = cause as {\n\t\t\treadonly message?: unknown;\n\t\t\treadonly reason?: unknown;\n\t\t\treadonly _tag?: unknown;\n\t\t};\n\t\tif (typeof c.message === 'string' && c.message.length > 0) return c.message;\n\t\tif (typeof c.reason === 'string' && c.reason.length > 0) return c.reason;\n\t\tif (typeof c._tag === 'string' && c._tag.length > 0) return c._tag;\n\t}\n\treturn String(cause);\n};\nconst faucetCauseDetail = causeDetail;\nconst fundingCauseDetail = causeDetail;\n\nconst str = (v: unknown): string | null => (typeof v === 'string' ? v : null);\nconst strReq = (v: unknown): string => (typeof v === 'string' ? v : '');\nconst num = (v: unknown): number | null => (typeof v === 'number' && Number.isFinite(v) ? v : null);\nconst bool = (v: unknown): boolean => v === true;\n\n/** Filter the generic resolved values down to those whose resource id\n * matches a predicate, in graph order. Returns the `{ pluginKey, value }`\n * the shaping functions consume. */\nconst matching = (\n\tvalues: ReadonlyArray<ControlPlaneResolvedValue>,\n\tmatches: (resourceId: string) => boolean,\n): ReadonlyArray<ControlPlaneResolvedValue> => values.filter((v) => matches(v.id));\n\n// -----------------------------------------------------------------------------\n// Postgres wire-protocol stats via `psql` exec inside the container\n// -----------------------------------------------------------------------------\n\n/** SQL that emits a single line of JSON the dashboard can parse without a\n * PG client. Keeps the round trip to one exec. */\nconst PG_STATS_SQL = `SELECT json_build_object(\n 'db_bytes', pg_database_size(current_database()),\n 'connections', (SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()),\n 'tables', COALESCE((\n SELECT json_agg(t) FROM (\n SELECT schemaname AS schema, relname AS name,\n n_live_tup AS row_estimate,\n pg_total_relation_size(relid) AS total_bytes\n FROM pg_stat_user_tables\n ORDER BY pg_total_relation_size(relid) DESC\n LIMIT 200\n ) t\n ), '[]'::json)\n)`;\n\nconst parsePgStats = (\n\tpluginKey: string,\n\tpg: PostgresShape,\n\tstdout: string,\n): DashboardPostgresStats => {\n\tconst database = strReq((pg.databases ?? [])[0]) || 'postgres';\n\tconst host = str(pg.networkAlias) ?? 'postgres';\n\tconst port = num(pg.port) ?? 5432;\n\tconst plainUrl = `postgres://${host}:${port}`;\n\tconst base = {\n\t\tpluginKey,\n\t\tdatabase,\n\t\tplainUrl,\n\t} as const;\n\ttry {\n\t\tconst trimmed = stdout.trim();\n\t\tconst parsed = JSON.parse(trimmed) as {\n\t\t\tdb_bytes?: number;\n\t\t\tconnections?: number;\n\t\t\ttables?: ReadonlyArray<{\n\t\t\t\tschema?: string;\n\t\t\t\tname?: string;\n\t\t\t\trow_estimate?: number;\n\t\t\t\ttotal_bytes?: number;\n\t\t\t}>;\n\t\t};\n\t\tconst tables: DashboardPostgresTable[] = (parsed.tables ?? []).map((t) => ({\n\t\t\tschema: t.schema ?? 'public',\n\t\t\tname: t.name ?? '',\n\t\t\trowEstimate: num(t.row_estimate) ?? 0,\n\t\t\ttotalBytes: num(t.total_bytes) ?? 0,\n\t\t}));\n\t\treturn {\n\t\t\t...base,\n\t\t\tdatabaseBytes: num(parsed.db_bytes) ?? 0,\n\t\t\tconnectionCount: num(parsed.connections) ?? 0,\n\t\t\ttables,\n\t\t\tavailable: true,\n\t\t\tdetail: null,\n\t\t};\n\t} catch (cause) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tdatabaseBytes: 0,\n\t\t\tconnectionCount: 0,\n\t\t\ttables: [],\n\t\t\tavailable: false,\n\t\t\tdetail: `failed to parse psql output: ${String(cause)}`,\n\t\t};\n\t}\n};\n\nconst unavailablePgStats = (\n\tpluginKey: string,\n\tpg: PostgresShape,\n\tdetail: string,\n): DashboardPostgresStats => {\n\tconst database = strReq((pg.databases ?? [])[0]) || 'postgres';\n\tconst host = str(pg.networkAlias) ?? 'postgres';\n\tconst port = num(pg.port) ?? 5432;\n\treturn {\n\t\tpluginKey,\n\t\tdatabase,\n\t\tplainUrl: `postgres://${host}:${port}`,\n\t\tdatabaseBytes: 0,\n\t\tconnectionCount: 0,\n\t\ttables: [],\n\t\tavailable: false,\n\t\tdetail,\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// Builder\n// -----------------------------------------------------------------------------\n\nexport interface DashboardDomainDeps {\n\t/** The generic, name-blind control-plane domain (resolved values). */\n\treadonly control: ControlPlaneDomain;\n\t/** Stack identity, used for the postgres container label probe. */\n\treadonly identity: Identity;\n\t/** Container runtime for the Postgres `psql` exec-probe. `null` in bare\n\t * test paths; `postgresStats` degrades to an unavailable entry then. */\n\treadonly containerRuntime: ContainerRuntime | null;\n\t/** The scope-local strategy registry — the SAME registry the boot-time\n\t * account funding pass dispatches through (`plugins/account/funding.ts`).\n\t * Drives `fundableCoins` + `fundAccount`: SUI via `faucet:request:<chainId>`,\n\t * WAL/DEEP via `coinType:<fullCoinType>`. `null` in bare test paths; the\n\t * fund accessors degrade to unavailable then. */\n\treadonly strategyRegistry: StrategyRegistry | null;\n}\n\nexport const buildDashboardDomain = (deps: DashboardDomainDeps): DashboardDomain => {\n\tconst { control, identity, containerRuntime, strategyRegistry } = deps;\n\n\tconst mode: DashboardDomain['mode'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\tif (sui === undefined) return null;\n\t\t\tconst m = (sui.value as SuiShape).mode;\n\t\t\tswitch (m) {\n\t\t\t\tcase 'fork':\n\t\t\t\t\treturn 'fork';\n\t\t\t\tcase 'live':\n\t\t\t\t\treturn 'live';\n\t\t\t\tcase 'local':\n\t\t\t\tcase 'local-rpc':\n\t\t\t\t\treturn 'local';\n\t\t\t\tdefault:\n\t\t\t\t\treturn null;\n\t\t\t}\n\t\t}),\n\t);\n\n\tconst deepbook: DashboardDomain['deepbook'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('deepbook/')).map(\n\t\t\t\t({ pluginKey, value }): DashboardDeepbookInfo => {\n\t\t\t\t\tconst v = value as DeepbookShape;\n\t\t\t\t\tconst modeRaw = v.mode;\n\t\t\t\t\tconst dbMode =\n\t\t\t\t\t\tmodeRaw === 'override' ? 'override' : modeRaw === 'known' ? 'known' : 'local';\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tname: pluginKey.replace(/^deepbook:/, ''),\n\t\t\t\t\t\tmode: dbMode,\n\t\t\t\t\t\tchain: strReq(v.chain),\n\t\t\t\t\t\tpackageId: strReq(v.packageId),\n\t\t\t\t\t\tregistryId: strReq(v.registryId),\n\t\t\t\t\t\tadminCapId: str(v.adminCapId),\n\t\t\t\t\t\tdeepTreasuryId: str(v.deepTreasuryId),\n\t\t\t\t\t\tpools: (v.pools ?? []).map((p) => ({\n\t\t\t\t\t\t\tname: strReq(p.name),\n\t\t\t\t\t\t\tpoolId: strReq(p.poolId),\n\t\t\t\t\t\t\tbaseCoinType: strReq(p.baseCoinType),\n\t\t\t\t\t\t\tquoteCoinType: strReq(p.quoteCoinType),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tmarketMakerRunning: bool(v.marketMakerRunning),\n\t\t\t\t\t\tserverUrl: str(v.serverUrl),\n\t\t\t\t\t\tindexerUrl: str(v.indexerUrl),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst seal: DashboardDomain['seal'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('seal:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardSealInfo => {\n\t\t\t\t\tconst v = value as SealShape;\n\t\t\t\t\tconst sealMode =\n\t\t\t\t\t\tv.mode === 'live' ? 'live' : v.mode === 'fork-known' ? 'fork-known' : 'local-keygen';\n\t\t\t\t\tconst keyServers = (v.serverConfigs ?? []).map((c) => ({\n\t\t\t\t\t\tobjectId: strReq(c.objectId),\n\t\t\t\t\t\tweight: num(c.weight) ?? 1,\n\t\t\t\t\t}));\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tmode: sealMode,\n\t\t\t\t\t\tobjectId: strReq(v.objectId),\n\t\t\t\t\t\tkeyServerUrl: strReq(v.keyServerUrl),\n\t\t\t\t\t\tkeyServers,\n\t\t\t\t\t\tthreshold: keyServers.length,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst coinCaps: DashboardDomain['coinCaps'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('coin:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardCoinCap => {\n\t\t\t\t\tconst v = value as CoinShape;\n\t\t\t\t\tconst source =\n\t\t\t\t\t\tv.source === 'registry' ? 'registry' : v.source === 'builtin' ? 'builtin' : 'on-chain';\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tsymbol: str(v.symbol),\n\t\t\t\t\t\tfullCoinType: strReq(v.fullCoinType),\n\t\t\t\t\t\tdecimals: num(v.decimals) ?? 0,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\ttreasuryCapId: str(v.treasuryCapId),\n\t\t\t\t\t\tpackageId: str(v.packageId),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\t// Mint ACTION — drives the dashboard Coins panel's Mint button.\n\t//\n\t// Signer source: the resolved coin VALUE carries a self-contained\n\t// `mintFromCap` closure (present only for witness-form coins whose\n\t// publisher still owns the TreasuryCap). That closure already captures\n\t// the treasury-cap-owning publisher `MintSigner` + the resolved cap id\n\t// in-process — the same lease-owning path `coin/service.ts`'s\n\t// `fundingStrategy` uses — so we mint WITHOUT threading a signer through\n\t// this seam (we read the resolved value, never plugin internals).\n\t//\n\t// Never fails (`E = never`): every reject path (bad address, non-\n\t// positive amount, no matching coin, cap-not-owned, on-chain failure)\n\t// degrades to `{ ok: false, detail, digest: null }` so the dashboard\n\t// query can't be taken down by a single bad mint.\n\tconst mintCoin: DashboardDomain['mintCoin'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (!isPositiveIntegerString(input.amountBaseUnits)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits}': expected a positive integer string`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\t// Locate the resolved coin whose fullCoinType matches. Match on the\n\t\t\t// resolved value's `fullCoinType` (the stable on-chain type), not the\n\t\t\t// resource-id prefix, so callers pass the same `coinType` the\n\t\t\t// `coinCaps` query surfaced.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst match = matching(values, (id) => id.startsWith('coin:'))\n\t\t\t\t.map(({ value }) => value as CoinShape)\n\t\t\t\t.find((v) => strReq(v.fullCoinType) === input.coinType);\n\n\t\t\tif (match === undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `no resolved coin found for type '${input.coinType}'`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (typeof match.mintFromCap !== 'function') {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${input.coinType}' has no in-process treasury cap signer — ` +\n\t\t\t\t\t\t'mint is only available for local-package coins whose publisher still owns the TreasuryCap',\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\treturn yield* match\n\t\t\t\t.mintFromCap({ to: recipient, amount: BigInt(input.amountBaseUnits) })\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(r): DashboardMintResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `minted ${input.amountBaseUnits} of ${input.coinType} to ${recipient}`,\n\t\t\t\t\t\t\tdigest: r.digest,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Typed coin/artifact-publisher failures carry `.message`.\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\t\ttypeof cause?.message === 'string'\n\t\t\t\t\t\t\t\t\t? cause.message\n\t\t\t\t\t\t\t\t\t: `mint failed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Residual defects (interrupts, unexpected throws) — degrade\n\t\t\t\t\t// rather than crash the dashboard query.\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `mint crashed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\t// --- Fund ACTION + fundable-coin derivation ------------------------\n\t//\n\t// Reuses devstack's IN-PROCESS funding strategies — the same strategy\n\t// registry the boot-time account funding pass dispatches through\n\t// (`plugins/account/funding.ts`). We never re-implement signing or the\n\t// exchange/pool swaps:\n\t//\n\t// - SUI (absent / canonical type) → `faucet:request:<chainId>`. The SUI\n\t// faucet strategy takes `{ address, amount }` only (no account handle)\n\t// and is FIXED-AMOUNT (the standard faucet ignores `amount`). Recipient\n\t// may be ANY 0x address.\n\t// - WAL/DEEP → `coinType:<fullCoinType>`. The strategy takes\n\t// `{ address, amount, account }` and runs an account-signed swap, so\n\t// the recipient MUST be a resolved account in the stack (we match the\n\t// recipient address against the resolved `account/<name>` values and\n\t// pass the live `AccountValue` as `req.account`).\n\t//\n\t// Never fails (`E = never`): every reject path degrades to\n\t// `{ ok:false, detail }` so a single bad fund can't take down the query.\n\n\t/** The chain id the SUI funding path keys on, read from the resolved sui\n\t * value (same `chain` field the sui codegen/snapshot decls stamp). */\n\tconst readChainId = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\treturn sui === undefined ? null : str((sui.value as SuiShape).chain);\n\t\t}),\n\t);\n\n\tconst fundableCoins: DashboardDomain['fundableCoins'] = Effect.gen(function* () {\n\t\t// SUI is always fundable when a faucet strategy is registered for the\n\t\t// active chain; the fixed-amount faucet ignores the requested amount.\n\t\tconst out: DashboardFundableCoin[] = [];\n\t\tif (strategyRegistry === null) return out;\n\n\t\tconst chain = yield* readChainId;\n\t\tconst keys = yield* strategyRegistry.list();\n\t\tif (chain !== null && keys.includes(faucetCapabilityKeyFor(chain))) {\n\t\t\tout.push({\n\t\t\t\tsymbol: 'SUI',\n\t\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t\t\thonorsAmount: false,\n\t\t\t\trequiresAccountSigner: false,\n\t\t\t});\n\t\t}\n\n\t\t// A coin is fundable iff a `coinType:<fullCoinType>` strategy is actually\n\t\t// registered (the walrus/deepbook/coin plugin contributed one). Derive the\n\t\t// display symbol from the coin type's module path (`::wal::WAL` → WAL,\n\t\t// `::deep::DEEP` → DEEP) so we stay name-blind on the coin VALUE while\n\t\t// still labeling the pill. `requiresAccountSigner` is read from the\n\t\t// strategy's own `requiresRecipientAccount` flag — NOT assumed true for\n\t\t// every coin: WAL/DEEP swaps spend the recipient's SUI (true), but a\n\t\t// managed-coin MINT strategy transfers to a passive recipient (false), so\n\t\t// it can fund any 0x address.\n\t\tfor (const key of keys) {\n\t\t\tif (!key.startsWith('coinType:')) continue;\n\t\t\tconst coinType = key.slice('coinType:'.length);\n\t\t\tif (coinType === SUI_FULL_COIN_TYPE) continue;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tout.push({\n\t\t\t\tsymbol: coinSymbolFromType(coinType),\n\t\t\t\tcoinType,\n\t\t\t\thonorsAmount: true,\n\t\t\t\trequiresAccountSigner: strategy?.requiresRecipientAccount ?? false,\n\t\t\t});\n\t\t}\n\t\treturn out;\n\t});\n\n\tconst fundAccount: DashboardDomain['fundAccount'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\t\t\tif (strategyRegistry === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: 'funding unavailable: no strategy registry wired',\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst coinType = input.coinType?.trim() ?? '';\n\t\t\tconst isSui = coinType === '' || coinType === SUI_FULL_COIN_TYPE;\n\n\t\t\t// SUI path — chain faucet strategy. Fixed-amount: we pass a nominal\n\t\t\t// amount but the standard faucet ignores it. Recipient may be any\n\t\t\t// 0x address (no account handle required).\n\t\t\tif (isSui) {\n\t\t\t\tconst chain = yield* readChainId;\n\t\t\t\tif (chain === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: 'cannot fund SUI: no resolved sui plugin / chain id in this stack',\n\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\tconst key = faucetCapabilityKeyFor(chain);\n\t\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t\t.get<typeof key, FaucetStrategy>(key)\n\t\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\t\tif (strategy === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: `no SUI faucet strategy registered for chain '${chain}'`,\n\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\t// `amount` is nominal — the standard faucet grant is fixed and\n\t\t\t\t// ignores it. Default to 1 SUI in MIST so a strategy that DID\n\t\t\t\t// honor it lands a sane value.\n\t\t\t\tconst amount = parseAmount(input.amountBaseUnits) ?? 1_000_000_000n;\n\t\t\t\treturn yield* strategy.request({ address: recipient, amount }).pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `requested SUI for ${recipient} (fixed-amount faucet grant)`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request failed: ${faucetCauseDetail(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request crashed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// WAL/DEEP path — coin-specific account-signed funding strategy.\n\t\t\tconst amount = parseAmount(input.amountBaseUnits);\n\t\t\tif (amount === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ''}': expected a positive integer string`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst key = `coinType:${coinType}` as const;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tif (strategy === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`no funding strategy registered for coin '${coinType}' — ` +\n\t\t\t\t\t\t'WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin',\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\t// Match the recipient to a resolved account, if one holds this address.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst account = matching(values, (id) => id.startsWith('account/'))\n\t\t\t\t.map(({ value }) => value as AccountShape)\n\t\t\t\t.find((v) => str(v.address) === recipient);\n\n\t\t\t// Account-spending strategies (WAL/DEEP) swap the recipient's OWN SUI,\n\t\t\t// so the recipient must BE a resolved account with a signer. Mint-style\n\t\t\t// strategies (managed coins) transfer to a passive recipient, so any 0x\n\t\t\t// address is fine — gate the rejection on the strategy's flag, not on\n\t\t\t// the coin being non-SUI.\n\t\t\tif (strategy.requiresRecipientAccount === true && account === undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${coinType}' is funded by an account-signed swap, but '${recipient}' ` +\n\t\t\t\t\t\t'is not a resolved account in this stack — fund a configured account (the swap spends its SUI)',\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\treturn yield* strategy\n\t\t\t\t.request({\n\t\t\t\t\taddress: recipient,\n\t\t\t\t\tamount,\n\t\t\t\t\t...(account === undefined ? {} : { account: account as unknown as AccountValue }),\n\t\t\t\t})\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `funded ${amount} base units of ${coinType} to ${recipient}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\tconst postgresStats: DashboardDomain['postgresStats'] = Effect.gen(function* () {\n\t\tconst values = yield* control.resolvedValues;\n\t\tconst instances = matching(values, (id) => id === 'postgres');\n\t\tif (instances.length === 0) return [];\n\t\tconst out: DashboardPostgresStats[] = [];\n\t\tfor (const { pluginKey, value } of instances) {\n\t\t\tconst pg = value as PostgresShape;\n\t\t\tif (containerRuntime === null) {\n\t\t\t\tout.push(unavailablePgStats(pluginKey, pg, 'container runtime unavailable'));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst database = strReq((pg.databases ?? [])[0]) || 'postgres';\n\t\t\tconst pgUser = str(pg.user) ?? 'postgres';\n\t\t\tconst role = str(pg.name) ?? 'postgres';\n\t\t\tconst probe = Effect.gen(function* () {\n\t\t\t\tconst handles = yield* containerRuntime.inspectByLabels({\n\t\t\t\t\tapp: String(identity.app),\n\t\t\t\t\tstack: String(identity.stack),\n\t\t\t\t\tplugin: 'postgres',\n\t\t\t\t\trole,\n\t\t\t\t});\n\t\t\t\tconst running = handles.find((h) => h.status === 'running') ?? handles[0];\n\t\t\t\tif (running === undefined) {\n\t\t\t\t\treturn unavailablePgStats(pluginKey, pg, 'no running postgres container found');\n\t\t\t\t}\n\t\t\t\tconst result = yield* containerRuntime.exec(running, [\n\t\t\t\t\t'psql',\n\t\t\t\t\t'-U',\n\t\t\t\t\tpgUser,\n\t\t\t\t\t'-d',\n\t\t\t\t\tdatabase,\n\t\t\t\t\t'-tAc',\n\t\t\t\t\tPG_STATS_SQL,\n\t\t\t\t]);\n\t\t\t\tif (result.exitCode !== 0) {\n\t\t\t\t\treturn unavailablePgStats(\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tpg,\n\t\t\t\t\t\t`psql exited ${result.exitCode}: ${result.stderr.trim().slice(0, 200)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn parsePgStats(pluginKey, pg, result.stdout);\n\t\t\t});\n\t\t\tconst stats = yield* probe.pipe(\n\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\tEffect.succeed(unavailablePgStats(pluginKey, pg, String(cause))),\n\t\t\t\t),\n\t\t\t);\n\t\t\tout.push(stats);\n\t\t}\n\t\treturn out;\n\t});\n\n\treturn {\n\t\tmode,\n\t\tdeepbook,\n\t\tseal,\n\t\tcoinCaps,\n\t\tpostgresStats,\n\t\tmintCoin,\n\t\tfundableCoins,\n\t\tfundAccount,\n\t};\n};\n\n/** An all-empty dashboard domain. Used by tests that exercise the\n * schema/server without a live registry. Every accessor resolves to\n * empty/`null`. */\nexport const emptyDashboardDomain: DashboardDomain = {\n\tmode: Effect.succeed(null),\n\tdeepbook: Effect.succeed([]),\n\tseal: Effect.succeed([]),\n\tcoinCaps: Effect.succeed([]),\n\tpostgresStats: Effect.succeed([]),\n\tmintCoin: () => Effect.succeed({ ok: false, detail: 'unavailable', digest: null }),\n\tfundableCoins: Effect.succeed([]),\n\tfundAccount: () => Effect.succeed({ ok: false, detail: 'unavailable', digest: null }),\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"domain.mjs","names":[],"sources":["../../../src/plugins/dashboard/domain.ts"],"sourcesContent":["// Dashboard plugin-domain shaping.\n//\n// The substrate control-plane is GENERIC + name-blind: it hands out the\n// snapshot catalog, the observability rings, and a single uninterpreted\n// `resolvedValues` accessor (see `substrate/runtime/control-plane/`). This\n// module — which lives in the PLUGIN layer and is allowed to name plugins —\n// owns ALL plugin-name-aware shaping: it matches resolved plugin values by\n// resource id (`deepbook/`-prefix, `seal:`-prefix, `coin:`-prefix, `id ===\n// 'sui'`) and projects them into the app-agnostic shapes the GraphQL schema\n// renders. It also owns the `mode` derivation and the coin `mint` action.\n//\n// Design discipline (mirrors the old substrate seam, one layer up):\n// - We import NO plugin types — we narrow the opaque `unknown` resolved\n// value through shallow structural shapes that mirror the relevant\n// fields. A field missing on the live value collapses to the\n// null/empty default.\n// - Every accessor degrades to empty/`null` rather than failing, so a\n// single missing/uninitialised plugin can't take down a dashboard\n// query (`E = never` on the public surface).\n// - We match plugins by RESOURCE ID — a prefix for the multi-instance\n// kinds (`deepbook/`, `seal:`, `coin:`) and an exact id for the\n// singletons (`id === 'sui'`) — rather than\n// plugin-key substrings: the resource id is the stable identity the\n// plugin factories mint.\n\nimport { Effect } from 'effect';\n\nimport type {\n\tControlPlaneDomain,\n\tControlPlaneResolvedValue,\n} from '../../substrate/runtime/control-plane/service.ts';\nimport type { StrategyRegistry } from '../../contracts/strategy-contributor.ts';\nimport type { FaucetStrategy } from '../../contracts/faucet-strategy.ts';\nimport type { AccountFundingStrategy } from '../../contracts/funding-strategy.ts';\nimport type { AccountValue } from '../account/index.ts';\n// The faucet capability-key prefix is owned by the faucet plugin (single\n// source of truth). The dashboard plugin layer is allowed to name plugins,\n// so importing the key constructor is the same cross-plugin reference the\n// account funding pass (`plugins/account/funding.ts`) uses — NOT a resolved\n// plugin-VALUE import (those stay structurally narrowed below). Imported via\n// the sibling's barrel to satisfy the plugin-boundary invariant.\nimport { FAUCET_CAPABILITY_KEY_PREFIX } from '../faucet/index.ts';\n\n// -----------------------------------------------------------------------------\n// App-agnostic domain shapes the GraphQL schema renders.\n// -----------------------------------------------------------------------------\n\n/** One DeepBook pool object id + coin types (prices are chain-direct). */\nexport interface DashboardDeepbookPool {\n\treadonly name: string;\n\treadonly poolId: string;\n\treadonly baseCoinType: string;\n\treadonly quoteCoinType: string;\n}\n\nexport interface DashboardDeepbookInfo {\n\treadonly pluginKey: string;\n\treadonly name: string;\n\treadonly mode: 'local' | 'override' | 'known';\n\treadonly network: string;\n\treadonly packageId: string;\n\treadonly registryId: string;\n\treadonly adminCapId: string | null;\n\treadonly deepTreasuryId: string | null;\n\treadonly pools: ReadonlyArray<DashboardDeepbookPool>;\n\treadonly marketMakerRunning: boolean;\n\treadonly serverUrl: string | null;\n\treadonly indexerUrl: string | null;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud: schema drift surfaced to the caller\n\t * instead of silently degrading). */\n\treadonly narrowingFault: string | null;\n}\n\nexport interface DashboardSealKeyServer {\n\treadonly objectId: string;\n\treadonly weight: number;\n}\n\nexport interface DashboardSealInfo {\n\treadonly pluginKey: string;\n\treadonly mode: 'local-keygen' | 'live' | 'fork-known';\n\treadonly objectId: string;\n\treadonly keyServerUrl: string;\n\treadonly keyServers: ReadonlyArray<DashboardSealKeyServer>;\n\t/** Threshold = number of registered key-server configs. */\n\treadonly threshold: number;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud). */\n\treadonly narrowingFault: string | null;\n}\n\n/** A coin's treasury-cap id (drives the Mint action) + addressing facts. */\nexport interface DashboardCoinCap {\n\treadonly pluginKey: string;\n\treadonly symbol: string | null;\n\treadonly fullCoinType: string;\n\treadonly decimals: number;\n\treadonly source: 'registry' | 'on-chain' | 'builtin';\n\treadonly treasuryCapId: string | null;\n\treadonly packageId: string | null;\n\t/** Non-null when one or more required fields failed to narrow off the\n\t * opaque resolved value (fail-loud). */\n\treadonly narrowingFault: string | null;\n}\n\n/** Input for the dashboard mint ACTION. `amountBaseUnits` is the raw\n * integer amount in the coin's smallest unit (decimals already applied\n * by the caller / form) — a string so large u64 values survive the wire\n * without precision loss. */\nexport interface DashboardMintInput {\n\treadonly coinType: string;\n\treadonly recipient: string;\n\treadonly amountBaseUnits: string;\n}\n\n/** Outcome of a dashboard mint ACTION. Mirrors the snapshot\n * restore/delete result shape plus the on-chain tx `digest` on success. */\nexport interface DashboardMintResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n\treadonly digest: string | null;\n}\n\n/** Input for the dashboard fund ACTION.\n *\n * `coinType` selects the funding strategy: absent or the canonical SUI\n * type routes through the chain's faucet strategy (`faucet:request:<chainId>`,\n * fixed-amount); any other full coin type routes through the coin-specific\n * `coinType:<fullCoinType>` strategy (WAL exchange swap / DEEP pool swap).\n *\n * `amountBaseUnits` is the raw integer amount in the coin's smallest unit\n * (a string so large u64 values survive the wire without precision loss).\n * The SUI faucet is fixed-amount and IGNORES it; WAL/DEEP honor it. */\nexport interface DashboardFundInput {\n\treadonly recipient: string;\n\treadonly coinType?: string | null;\n\treadonly amountBaseUnits?: string | null;\n}\n\n/** Outcome of a dashboard fund ACTION. The in-process funding strategies\n * return `void` (not a digest), so the result carries only `ok`/`detail`.\n * `ok:true` means the strategy's `request(...)` completed (the faucet POST\n * landed / the swap executed on-chain); `detail` carries the reason on\n * failure. */\nexport interface DashboardFundResult {\n\treadonly ok: boolean;\n\treadonly detail: string;\n}\n\n/** One coin the dashboard faucet can actually fund, with whether the\n * underlying strategy honors a caller-supplied amount.\n *\n * SUI is always present (fixed-amount faucet, `honorsAmount: false`).\n * WAL/DEEP appear only when their plugin registered a `coinType:<X>`\n * funding strategy AND (for WAL) carries a swap that spends the\n * recipient account's SUI — so `honorsAmount: true`. */\nexport interface DashboardFundableCoin {\n\treadonly symbol: string;\n\treadonly coinType: string;\n\treadonly honorsAmount: boolean;\n\t/** True when funding requires the recipient to BE a resolved account in\n\t * the stack (the swap spends that account's own SUI via its in-process\n\t * signer). SUI is `false` (any 0x address); WAL/DEEP are `true`. */\n\treadonly requiresAccountSigner: boolean;\n}\n\n/** The dashboard plugin-domain accessor surface. Each member is a\n * self-contained Effect that never fails (`E = never`); they degrade to\n * empty/`null` so a single missing plugin can't take down the dashboard\n * query. */\nexport interface DashboardDomain {\n\t/** Fork-vs-local mode, derived from the resolved sui plugin's chain\n\t * identity. Used for advance-clock gating. `null` when no sui plugin\n\t * is present. */\n\treadonly mode: Effect.Effect<'fork' | 'local' | 'live' | null>;\n\t/** DeepBook deployments (registry/admin/pool ids + MM state). */\n\treadonly deepbook: Effect.Effect<ReadonlyArray<DashboardDeepbookInfo>>;\n\t/** Seal key-server deployments (objectId/threshold/mode). */\n\treadonly seal: Effect.Effect<ReadonlyArray<DashboardSealInfo>>;\n\t/** Coin treasury caps (drives Mint). */\n\treadonly coinCaps: Effect.Effect<ReadonlyArray<DashboardCoinCap>>;\n\t/** Mint ACTION — mints `amountBaseUnits` of `coinType` to `recipient`,\n\t * signed in-process by the treasury-cap-owning publisher signer the\n\t * resolved coin value's self-contained `mintFromCap` closure holds. */\n\treadonly mintCoin: (input: DashboardMintInput) => Effect.Effect<DashboardMintResult>;\n\t/** Coins the faucet can actually fund right now (SUI always; WAL/DEEP\n\t * only when their plugin registered a funding strategy). Drives the\n\t * faucet panel's coin pills + amount-field gating. */\n\treadonly fundableCoins: Effect.Effect<ReadonlyArray<DashboardFundableCoin>>;\n\t/** Fund ACTION — reuses devstack's in-process funding strategies. SUI\n\t * (absent/canonical type) routes through the chain faucet strategy\n\t * (fixed-amount); WAL/DEEP route through the coin-specific funding\n\t * strategy (account-signed exchange/pool swap). Real result — `ok`\n\t * reflects whether the strategy's `request(...)` completed. */\n\treadonly fundAccount: (input: DashboardFundInput) => Effect.Effect<DashboardFundResult>;\n}\n\n// -----------------------------------------------------------------------------\n// Structural projections of plugin-resolved values\n//\n// We narrow the opaque `unknown` resolved value through shallow structural\n// shapes that mirror the relevant fields. A field missing on the live value\n// collapses to the null/empty default.\n// -----------------------------------------------------------------------------\n\ninterface DeepbookShape {\n\treadonly mode?: unknown;\n\treadonly network?: unknown;\n\treadonly packageId?: unknown;\n\treadonly registryId?: unknown;\n\treadonly adminCapId?: unknown;\n\treadonly deepTreasuryId?: unknown;\n\treadonly pools?: ReadonlyArray<{\n\t\treadonly name?: unknown;\n\t\treadonly poolId?: unknown;\n\t\treadonly baseCoinType?: unknown;\n\t\treadonly quoteCoinType?: unknown;\n\t}>;\n\treadonly marketMakerRunning?: unknown;\n\treadonly serverUrl?: unknown;\n\treadonly indexerUrl?: unknown;\n}\n\ninterface SealShape {\n\treadonly mode?: unknown;\n\treadonly objectId?: unknown;\n\treadonly keyServerUrl?: unknown;\n\treadonly serverConfigs?: ReadonlyArray<{\n\t\treadonly objectId?: unknown;\n\t\treadonly weight?: unknown;\n\t}>;\n}\n\ninterface CoinShape {\n\treadonly symbol?: unknown;\n\treadonly fullCoinType?: unknown;\n\treadonly decimals?: unknown;\n\treadonly source?: unknown;\n\treadonly treasuryCapId?: unknown;\n\treadonly packageId?: unknown;\n\t/** Self-contained mint closure on the resolved coin value (present\n\t * for witness-form coins whose publisher still owns the cap). Read\n\t * structurally — we import no coin types. Returns an Effect that\n\t * resolves a `{ digest }`-bearing result or fails with a\n\t * coin/artifact-publisher tagged error. */\n\treadonly mintFromCap?: (opts: {\n\t\treadonly to: string;\n\t\treadonly amount: bigint;\n\t}) => Effect.Effect<{ readonly digest: string }, { readonly message?: unknown }>;\n}\n\ninterface SuiShape {\n\treadonly mode?: unknown;\n\t/** Genesis-digest chain id (`'sui:localnet'`, `'sui:testnet'`,\n\t * `'sui:mainnet-fork@123'`). Composes the faucet capability key\n\t * (`faucet:request:<chainId>`) the SUI funding path resolves. */\n\treadonly chainId?: unknown;\n}\n\n/** Structural shape of the resolved account value (`account/<name>`). The\n * WAL/DEEP funding strategies need this handle as `req.account` — the swap\n * spends the recipient account's own SUI through its in-process signer.\n * Narrowed to the fields the strategy dispatch reads; the full\n * `AccountValue` is assignable to it, so we cast the matched value across\n * the seam without importing the account VALUE shape structurally\n * elsewhere. */\ninterface AccountShape {\n\treadonly address?: unknown;\n\treadonly name?: unknown;\n}\n\n/** A 0x-prefixed Sui address: `0x` + 1..64 hex digits. Mirrors the\n * address validation the mint PTB's `tx.pure.address` ultimately\n * enforces, surfaced up front so the dashboard gets a clean rejection\n * rather than an opaque build failure. */\nconst SUI_ADDRESS_RE = /^0x[0-9a-fA-F]{1,64}$/;\n\n/** The canonical builtin SUI coin type — selects the SUI faucet funding\n * path. Mirrors `SUI_FULL_COIN_TYPE` in `plugins/account/funding.ts`\n * (inlined here so the dashboard plugin does not cross-import the account\n * funding module just for the string). */\nconst SUI_FULL_COIN_TYPE = '0x2::sui::SUI' as const;\n\n/** A positive integer base-unit amount string (no sign, no decimal\n * point, no leading zeros beyond a bare `0` — which is itself rejected\n * as non-positive). */\nconst isPositiveIntegerString = (s: string): boolean => {\n\tif (!/^\\d+$/.test(s)) return false;\n\ttry {\n\t\treturn BigInt(s) > 0n;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** Compose the chain faucet capability key (`faucet:request:<chainId>`)\n * the SUI funding path resolves. Uses the faucet plugin's prefix constant\n * (single source of truth) — same key the boot-time funding pass builds. */\nconst faucetCapabilityKeyFor = (\n\tchain: string,\n): `${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${string}` => `${FAUCET_CAPABILITY_KEY_PREFIX}:${chain}`;\n\n/** Parse a base-unit amount string into a positive bigint, or `null` when\n * absent / non-positive / non-integer. */\nconst parseAmount = (s: string | null | undefined): bigint | null => {\n\tif (s == null) return null;\n\tconst trimmed = s.trim();\n\tif (!isPositiveIntegerString(trimmed)) return null;\n\treturn BigInt(trimmed);\n};\n\n/** Derive a display symbol from a full coin type's module path\n * (`0x…::wal::WAL` → `WAL`, `0x…::deep::DEEP` → `DEEP`). Falls back to the\n * struct name, then the raw type. Keeps the dashboard name-blind on the\n * resolved coin VALUE while still labeling the faucet pill. */\nconst coinSymbolFromType = (coinType: string): string => {\n\tconst parts = coinType.split('::');\n\tconst struct = parts[parts.length - 1];\n\treturn struct !== undefined && struct.length > 0 ? struct : coinType;\n};\n\n/** Extract a human detail from a faucet/funding strategy failure. The\n * strategy error channels are tagged structs carrying `message`/`reason`;\n * read them structurally without importing each plugin's error type. */\nconst causeDetail = (cause: unknown): string => {\n\tif (cause !== null && typeof cause === 'object') {\n\t\tconst c = cause as {\n\t\t\treadonly message?: unknown;\n\t\t\treadonly reason?: unknown;\n\t\t\treadonly _tag?: unknown;\n\t\t};\n\t\tif (typeof c.message === 'string' && c.message.length > 0) return c.message;\n\t\tif (typeof c.reason === 'string' && c.reason.length > 0) return c.reason;\n\t\tif (typeof c._tag === 'string' && c._tag.length > 0) return c._tag;\n\t}\n\treturn String(cause);\n};\nconst faucetCauseDetail = causeDetail;\nconst fundingCauseDetail = causeDetail;\n\n// -----------------------------------------------------------------------------\n// Fail-aware structural narrowing\n//\n// The substrate hands us opaque `unknown` resolved values. We still narrow\n// through shallow structural shapes, but instead of SILENTLY degrading a\n// missing/wrong-typed required field to ''/0 (which hid integration-seam\n// drift), the `req*` readers ACCUMULATE a typed narrowing fault into a\n// per-shaping-call collector. The fault is threaded into the GraphQL-visible\n// result (`narrowingFault` / `detail`) so consumers SEE the drift — WITHOUT\n// ever throwing (the dashboard's `E = never` surface semantic is preserved).\n// `opt*` readers stay quiet: they are for genuinely-optional fields.\n// -----------------------------------------------------------------------------\n\n/** Mutable per-call sink for structural-narrowing faults. */\ntype FaultSink = Array<string>;\n\nconst newFaults = (): FaultSink => [];\n\n/** Collapse accumulated faults into a single nullable detail string for the\n * GraphQL-visible result. `null` when nothing drifted. */\nconst faultDetail = (faults: FaultSink): string | null =>\n\tfaults.length === 0 ? null : faults.join('; ');\n\n/** Describe why a value failed to narrow to the expected type — distinguishing\n * 'absent' from 'present but wrong type'. */\nconst typeFault = (field: string, expected: string, v: unknown): string => {\n\tif (v === undefined || v === null) return `${field}: missing (expected ${expected})`;\n\treturn `${field}: expected ${expected}, got ${typeof v}`;\n};\n\n/** Required string. On mismatch records a fault and returns '' so the panel\n * still renders a (degraded) cell. */\nconst reqStr = (v: unknown, field: string, faults: FaultSink): string => {\n\tif (typeof v === 'string') return v;\n\tfaults.push(typeFault(field, 'string', v));\n\treturn '';\n};\n\n/** Required finite number. On mismatch records a fault and returns the safe\n * display fallback (`fallback`, default 0). */\nconst reqNum = (v: unknown, field: string, faults: FaultSink, fallback = 0): number => {\n\tif (typeof v === 'number' && Number.isFinite(v)) return v;\n\tfaults.push(typeFault(field, 'number', v));\n\treturn fallback;\n};\n\n/** Allow-list enum narrow. Records a fault for an out-of-enum value while\n * still returning a safe display fallback so the panel renders. */\nconst narrowEnum = <T extends string>(\n\traw: unknown,\n\tallowed: ReadonlyArray<T>,\n\tfield: string,\n\tfaults: FaultSink,\n\tfallback: T,\n): T => {\n\tif (typeof raw === 'string' && (allowed as ReadonlyArray<string>).includes(raw)) return raw as T;\n\tfaults.push(\n\t\traw === undefined || raw === null\n\t\t\t? `${field}: missing (expected one of ${allowed.join('|')})`\n\t\t\t: `${field}: '${String(raw)}' not in ${allowed.join('|')}`,\n\t);\n\treturn fallback;\n};\n\n// Genuinely-optional readers — silent by design (absent is a valid state).\nconst optStr = (v: unknown): string | null => (typeof v === 'string' ? v : null);\nconst optNum = (v: unknown): number | null =>\n\ttypeof v === 'number' && Number.isFinite(v) ? v : null;\nconst bool = (v: unknown): boolean => v === true;\n\n/** Filter the generic resolved values down to those whose resource id\n * matches a predicate, in graph order. Returns the `{ pluginKey, value }`\n * the shaping functions consume. */\nconst matching = (\n\tvalues: ReadonlyArray<ControlPlaneResolvedValue>,\n\tmatches: (resourceId: string) => boolean,\n): ReadonlyArray<ControlPlaneResolvedValue> => values.filter((v) => matches(v.id));\n\n// -----------------------------------------------------------------------------\n// Builder\n// -----------------------------------------------------------------------------\n\nexport interface DashboardDomainDeps {\n\t/** The generic, name-blind control-plane domain (resolved values). */\n\treadonly control: ControlPlaneDomain;\n\t/** The scope-local strategy registry — the SAME registry the boot-time\n\t * account funding pass dispatches through (`plugins/account/funding.ts`).\n\t * Drives `fundableCoins` + `fundAccount`: SUI via `faucet:request:<chainId>`,\n\t * WAL/DEEP via `coinType:<fullCoinType>`. `null` in bare test paths; the\n\t * fund accessors degrade to unavailable then. */\n\treadonly strategyRegistry: StrategyRegistry | null;\n}\n\nexport const buildDashboardDomain = (deps: DashboardDomainDeps): DashboardDomain => {\n\tconst { control, strategyRegistry } = deps;\n\n\tconst mode: DashboardDomain['mode'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\tif (sui === undefined) return null;\n\t\t\tconst m = (sui.value as SuiShape).mode;\n\t\t\tswitch (m) {\n\t\t\t\tcase 'fork':\n\t\t\t\t\treturn 'fork';\n\t\t\t\tcase 'live':\n\t\t\t\t\treturn 'live';\n\t\t\t\tcase 'local':\n\t\t\t\tcase 'local-rpc':\n\t\t\t\t\treturn 'local';\n\t\t\t\tdefault:\n\t\t\t\t\treturn null;\n\t\t\t}\n\t\t}),\n\t);\n\n\tconst deepbook: DashboardDomain['deepbook'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('deepbook/')).map(\n\t\t\t\t({ pluginKey, value }): DashboardDeepbookInfo => {\n\t\t\t\t\tconst v = value as DeepbookShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst dbMode = narrowEnum(\n\t\t\t\t\t\tv.mode,\n\t\t\t\t\t\t['local', 'override', 'known'] as const,\n\t\t\t\t\t\t'deepbook.mode',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'local',\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tname: pluginKey.replace(/^deepbook:/, ''),\n\t\t\t\t\t\tmode: dbMode,\n\t\t\t\t\t\tnetwork: reqStr(v.network, 'deepbook.network', faults),\n\t\t\t\t\t\tpackageId: reqStr(v.packageId, 'deepbook.packageId', faults),\n\t\t\t\t\t\tregistryId: reqStr(v.registryId, 'deepbook.registryId', faults),\n\t\t\t\t\t\tadminCapId: optStr(v.adminCapId),\n\t\t\t\t\t\tdeepTreasuryId: optStr(v.deepTreasuryId),\n\t\t\t\t\t\tpools: (v.pools ?? []).map((p, i) => ({\n\t\t\t\t\t\t\tname: reqStr(p.name, `deepbook.pools[${i}].name`, faults),\n\t\t\t\t\t\t\tpoolId: reqStr(p.poolId, `deepbook.pools[${i}].poolId`, faults),\n\t\t\t\t\t\t\tbaseCoinType: reqStr(p.baseCoinType, `deepbook.pools[${i}].baseCoinType`, faults),\n\t\t\t\t\t\t\tquoteCoinType: reqStr(p.quoteCoinType, `deepbook.pools[${i}].quoteCoinType`, faults),\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tmarketMakerRunning: bool(v.marketMakerRunning),\n\t\t\t\t\t\tserverUrl: optStr(v.serverUrl),\n\t\t\t\t\t\tindexerUrl: optStr(v.indexerUrl),\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst seal: DashboardDomain['seal'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('seal:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardSealInfo => {\n\t\t\t\t\tconst v = value as SealShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst sealMode = narrowEnum(\n\t\t\t\t\t\tv.mode,\n\t\t\t\t\t\t['local-keygen', 'live', 'fork-known'] as const,\n\t\t\t\t\t\t'seal.mode',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'local-keygen',\n\t\t\t\t\t);\n\t\t\t\t\tconst keyServers = (v.serverConfigs ?? []).map((c, i) => ({\n\t\t\t\t\t\tobjectId: reqStr(c.objectId, `seal.serverConfigs[${i}].objectId`, faults),\n\t\t\t\t\t\tweight: optNum(c.weight) ?? 1,\n\t\t\t\t\t}));\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tmode: sealMode,\n\t\t\t\t\t\tobjectId: reqStr(v.objectId, 'seal.objectId', faults),\n\t\t\t\t\t\tkeyServerUrl: reqStr(v.keyServerUrl, 'seal.keyServerUrl', faults),\n\t\t\t\t\t\tkeyServers,\n\t\t\t\t\t\tthreshold: keyServers.length,\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\tconst coinCaps: DashboardDomain['coinCaps'] = control.resolvedValues.pipe(\n\t\tEffect.map((values) =>\n\t\t\tmatching(values, (id) => id.startsWith('coin:')).map(\n\t\t\t\t({ pluginKey, value }): DashboardCoinCap => {\n\t\t\t\t\tconst v = value as CoinShape;\n\t\t\t\t\tconst faults = newFaults();\n\t\t\t\t\tconst source = narrowEnum(\n\t\t\t\t\t\tv.source,\n\t\t\t\t\t\t['registry', 'on-chain', 'builtin'] as const,\n\t\t\t\t\t\t'coin.source',\n\t\t\t\t\t\tfaults,\n\t\t\t\t\t\t'on-chain',\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\tsymbol: optStr(v.symbol),\n\t\t\t\t\t\tfullCoinType: reqStr(v.fullCoinType, 'coin.fullCoinType', faults),\n\t\t\t\t\t\tdecimals: reqNum(v.decimals, 'coin.decimals', faults, 0),\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\ttreasuryCapId: optStr(v.treasuryCapId),\n\t\t\t\t\t\tpackageId: optStr(v.packageId),\n\t\t\t\t\t\tnarrowingFault: faultDetail(faults),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\t// Mint ACTION — drives the dashboard Coins panel's Mint button.\n\t//\n\t// Signer source: the resolved coin VALUE carries a self-contained\n\t// `mintFromCap` closure (present only for witness-form coins whose\n\t// publisher still owns the TreasuryCap). That closure already captures\n\t// the treasury-cap-owning publisher `MintSigner` + the resolved cap id\n\t// in-process — the same lease-owning path `coin/service.ts`'s\n\t// `fundingStrategy` uses — so we mint WITHOUT threading a signer through\n\t// this seam (we read the resolved value, never plugin internals).\n\t//\n\t// Never fails (`E = never`): every reject path (bad address, non-\n\t// positive amount, no matching coin, cap-not-owned, on-chain failure)\n\t// degrades to `{ ok: false, detail, digest: null }` so the dashboard\n\t// query can't be taken down by a single bad mint.\n\tconst mintCoin: DashboardDomain['mintCoin'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (!isPositiveIntegerString(input.amountBaseUnits)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits}': expected a positive integer string`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\t// Locate the resolved coin whose fullCoinType matches. Match on the\n\t\t\t// resolved value's `fullCoinType` (the stable on-chain type), not the\n\t\t\t// resource-id prefix, so callers pass the same `coinType` the\n\t\t\t// `coinCaps` query surfaced. Read `fullCoinType` fail-loud so a coin\n\t\t\t// value missing/empty `fullCoinType` names the REAL cause (a drifted\n\t\t\t// resolved shape) rather than collapsing into the generic\n\t\t\t// 'no resolved coin found' reject.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst candidates = matching(values, (id) => id.startsWith('coin:')).map(\n\t\t\t\t({ value }) => value as CoinShape,\n\t\t\t);\n\t\t\tconst matchFaults = newFaults();\n\t\t\tconst match = candidates.find(\n\t\t\t\t(v) => reqStr(v.fullCoinType, 'coin.fullCoinType', matchFaults) === input.coinType,\n\t\t\t);\n\n\t\t\tif (match === undefined) {\n\t\t\t\tconst fault = faultDetail(matchFaults);\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\tfault === null\n\t\t\t\t\t\t\t? `no resolved coin found for type '${input.coinType}'`\n\t\t\t\t\t\t\t: `no resolved coin found for type '${input.coinType}' (${fault})`,\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\t\t\tif (typeof match.mintFromCap !== 'function') {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${input.coinType}' has no in-process treasury cap signer — ` +\n\t\t\t\t\t\t'mint is only available for local-package coins whose publisher still owns the TreasuryCap',\n\t\t\t\t\tdigest: null,\n\t\t\t\t} satisfies DashboardMintResult;\n\t\t\t}\n\n\t\t\treturn yield* match\n\t\t\t\t.mintFromCap({ to: recipient, amount: BigInt(input.amountBaseUnits) })\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(r): DashboardMintResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `minted ${input.amountBaseUnits} of ${input.coinType} to ${recipient}`,\n\t\t\t\t\t\t\tdigest: r.digest,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Typed coin/artifact-publisher failures carry `.message`.\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\t\ttypeof cause?.message === 'string'\n\t\t\t\t\t\t\t\t\t? cause.message\n\t\t\t\t\t\t\t\t\t: `mint failed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// Residual defects (interrupts, unexpected throws) — degrade\n\t\t\t\t\t// rather than crash the dashboard query.\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardMintResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `mint crashed: ${String(cause)}`,\n\t\t\t\t\t\t\tdigest: null,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\t// --- Fund ACTION + fundable-coin derivation ------------------------\n\t//\n\t// Reuses devstack's IN-PROCESS funding strategies — the same strategy\n\t// registry the boot-time account funding pass dispatches through\n\t// (`plugins/account/funding.ts`). We never re-implement signing or the\n\t// exchange/pool swaps:\n\t//\n\t// - SUI (absent / canonical type) → `faucet:request:<chainId>`. The SUI\n\t// faucet strategy takes `{ address, amount }` only (no account handle)\n\t// and is FIXED-AMOUNT (the standard faucet ignores `amount`). Recipient\n\t// may be ANY 0x address.\n\t// - WAL/DEEP → `coinType:<fullCoinType>`. The strategy takes\n\t// `{ address, amount, account }` and runs an account-signed swap, so\n\t// the recipient MUST be a resolved account in the stack (we match the\n\t// recipient address against the resolved `account/<name>` values and\n\t// pass the live `AccountValue` as `req.account`).\n\t//\n\t// Never fails (`E = never`): every reject path degrades to\n\t// `{ ok:false, detail }` so a single bad fund can't take down the query.\n\n\t/** The chain id the SUI funding path keys on, read from the resolved sui\n\t * value (same `chainId` field the sui codegen/snapshot decls stamp). */\n\tconst readChainId = control.resolvedValues.pipe(\n\t\tEffect.map((values) => {\n\t\t\tconst sui = matching(values, (id) => id === 'sui')[0];\n\t\t\treturn sui === undefined ? null : optStr((sui.value as SuiShape).chainId);\n\t\t}),\n\t);\n\n\tconst fundableCoins: DashboardDomain['fundableCoins'] = Effect.gen(function* () {\n\t\t// SUI is always fundable when a faucet strategy is registered for the\n\t\t// active chain; the fixed-amount faucet ignores the requested amount.\n\t\tconst out: DashboardFundableCoin[] = [];\n\t\tif (strategyRegistry === null) return out;\n\n\t\tconst chain = yield* readChainId;\n\t\tconst keys = yield* strategyRegistry.list();\n\t\tif (chain !== null && keys.includes(faucetCapabilityKeyFor(chain))) {\n\t\t\tout.push({\n\t\t\t\tsymbol: 'SUI',\n\t\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t\t\thonorsAmount: false,\n\t\t\t\trequiresAccountSigner: false,\n\t\t\t});\n\t\t}\n\n\t\t// A coin is fundable iff a `coinType:<fullCoinType>` strategy is actually\n\t\t// registered (the walrus/deepbook/coin plugin contributed one). Derive the\n\t\t// display symbol from the coin type's module path (`::wal::WAL` → WAL,\n\t\t// `::deep::DEEP` → DEEP) so we stay name-blind on the coin VALUE while\n\t\t// still labeling the pill. `requiresAccountSigner` is read from the\n\t\t// strategy's own `requiresRecipientAccount` flag — NOT assumed true for\n\t\t// every coin: WAL/DEEP swaps spend the recipient's SUI (true), but a\n\t\t// managed-coin MINT strategy transfers to a passive recipient (false), so\n\t\t// it can fund any 0x address.\n\t\tfor (const key of keys) {\n\t\t\tif (!key.startsWith('coinType:')) continue;\n\t\t\tconst coinType = key.slice('coinType:'.length);\n\t\t\tif (coinType === SUI_FULL_COIN_TYPE) continue;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tout.push({\n\t\t\t\tsymbol: coinSymbolFromType(coinType),\n\t\t\t\tcoinType,\n\t\t\t\thonorsAmount: true,\n\t\t\t\trequiresAccountSigner: strategy?.requiresRecipientAccount ?? false,\n\t\t\t});\n\t\t}\n\t\treturn out;\n\t});\n\n\tconst fundAccount: DashboardDomain['fundAccount'] = (input) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst recipient = input.recipient.trim();\n\t\t\tif (!SUI_ADDRESS_RE.test(recipient)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid recipient '${input.recipient}': expected a 0x-prefixed Sui address`,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\t\t\tif (strategyRegistry === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: 'funding unavailable: no strategy registry wired',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst coinType = input.coinType?.trim() ?? '';\n\t\t\tconst isSui = coinType === '' || coinType === SUI_FULL_COIN_TYPE;\n\n\t\t\t// SUI path — chain faucet strategy. Fixed-amount: we pass a nominal\n\t\t\t// amount but the standard faucet ignores it. Recipient may be any\n\t\t\t// 0x address (no account handle required).\n\t\t\tif (isSui) {\n\t\t\t\tconst chain = yield* readChainId;\n\t\t\t\tif (chain === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: 'cannot fund SUI: no resolved sui plugin / chain id in this stack',\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\tconst key = faucetCapabilityKeyFor(chain);\n\t\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t\t.get<typeof key, FaucetStrategy>(key)\n\t\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\t\tif (strategy === null) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tdetail: `no SUI faucet strategy registered for chain '${chain}'`,\n\t\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t\t}\n\t\t\t\t// `amount` is nominal — the standard faucet grant is fixed and\n\t\t\t\t// ignores it. Default to 1 SUI in MIST so a strategy that DID\n\t\t\t\t// honor it lands a sane value.\n\t\t\t\tconst amount = parseAmount(input.amountBaseUnits) ?? 1_000_000_000n;\n\t\t\t\treturn yield* strategy.request({ address: recipient, amount }).pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `requested SUI for ${recipient} (fixed-amount faucet grant)`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request failed: ${faucetCauseDetail(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `SUI faucet request crashed: ${String(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// WAL/DEEP path — coin-specific account-signed funding strategy.\n\t\t\tconst amount = parseAmount(input.amountBaseUnits);\n\t\t\tif (amount === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail: `invalid amountBaseUnits '${input.amountBaseUnits ?? ''}': expected a positive integer string`,\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\tconst key = `coinType:${coinType}` as const;\n\t\t\tconst strategy = yield* strategyRegistry\n\t\t\t\t.get<typeof key, AccountFundingStrategy<unknown, AccountValue>>(key)\n\t\t\t\t.pipe(Effect.catchTag('StrategyNotFoundError', () => Effect.succeed(null)));\n\t\t\tif (strategy === null) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`no funding strategy registered for coin '${coinType}' — ` +\n\t\t\t\t\t\t'WAL needs the walrus plugin (with an exchange) and DEEP needs the deepbook plugin',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\t// Match the recipient to a resolved account, if one holds this address.\n\t\t\tconst values = yield* control.resolvedValues;\n\t\t\tconst account = matching(values, (id) => id.startsWith('account/'))\n\t\t\t\t.map(({ value }) => value as AccountShape)\n\t\t\t\t.find((v) => optStr(v.address) === recipient);\n\n\t\t\t// Account-spending strategies (WAL/DEEP) swap the recipient's OWN SUI,\n\t\t\t// so the recipient must BE a resolved account with a signer. Mint-style\n\t\t\t// strategies (managed coins) transfer to a passive recipient, so any 0x\n\t\t\t// address is fine — gate the rejection on the strategy's flag, not on\n\t\t\t// the coin being non-SUI.\n\t\t\tif (strategy.requiresRecipientAccount === true && account === undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tdetail:\n\t\t\t\t\t\t`coin '${coinType}' is funded by an account-signed swap, but '${recipient}' ` +\n\t\t\t\t\t\t'is not a resolved account in this stack — fund a configured account (the swap spends its SUI)',\n\t\t\t\t} satisfies DashboardFundResult;\n\t\t\t}\n\n\t\t\treturn yield* strategy\n\t\t\t\t.request({\n\t\t\t\t\taddress: recipient,\n\t\t\t\t\tamount,\n\t\t\t\t\t...(account === undefined ? {} : { account: account as unknown as AccountValue }),\n\t\t\t\t})\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(): DashboardFundResult => ({\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tdetail: `funded ${amount} base units of ${coinType} to ${recipient}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding failed: ${fundingCauseDetail(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\tEffect.succeed<DashboardFundResult>({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tdetail: `${coinSymbolFromType(coinType)} funding crashed: ${String(cause)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\n\treturn {\n\t\tmode,\n\t\tdeepbook,\n\t\tseal,\n\t\tcoinCaps,\n\t\tmintCoin,\n\t\tfundableCoins,\n\t\tfundAccount,\n\t};\n};\n\n/** An all-empty dashboard domain. Used by tests that exercise the\n * schema/server without a live registry. Every accessor resolves to\n * empty/`null`. */\nexport const emptyDashboardDomain: DashboardDomain = {\n\tmode: Effect.succeed(null),\n\tdeepbook: Effect.succeed([]),\n\tseal: Effect.succeed([]),\n\tcoinCaps: Effect.succeed([]),\n\tmintCoin: () => Effect.succeed({ ok: false, detail: 'unavailable', digest: null }),\n\tfundableCoins: Effect.succeed([]),\n\tfundAccount: () => Effect.succeed({ ok: false, detail: 'unavailable' }),\n};\n"],"mappings":"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"}