@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
@@ -1 +1 @@
1
- {"version":3,"file":"funding.mjs","names":[],"sources":["../../../src/plugins/account/funding.ts"],"sourcesContent":["// Account plugin — funding logic.\n//\n// Two funding paths converge here:\n//\n// 1. **Default funding** — applies to the `ephemeral` variant only.\n// On non-fork networks: faucet POST via the SUI HTTP strategy\n// auto-registered by Faucet (see 11-faucet.md). On fork networks:\n// \"pay from a seed via impersonation\" because forks have no\n// faucet. The auto-promotion is LOUD by default per the\n// architecture's \"no silent surprises\" principle — we emit a\n// `log.appended` event the first time a stack hits this path.\n//\n// 2. **Cross-cutting funding** — declared per-account via\n// `AccountOptions.funding`. Applies to every variant.\n// Dispatched through the ambient strategy registry. Missing\n// strategy for non-SUI coins ⇒ silent noop (architecture-\n// mandated test-ergonomics contract, distilled-doc invariant:\n// \"Optional Faucet is a noop, not an error\"). Explicit SUI\n// entries use the SUI faucet strategy and fail loudly when no\n// faucet-bearing strategy exists.\n//\n// Distilled-doc invariant: per-address serialization — concurrent\n// funding requests for the same address MUST serialize. We share the\n// substrate `LeaseBroker` handle from `service.ts` and open a fresh\n// scope per wire call so the lease releases the moment that call\n// returns. Each cross-cutting iteration is its own scope: the broker\n// is non-reentrant by design, so a hypothetical loop holding a single\n// lease across iterations would deadlock the second one.\n\nimport { Effect } from 'effect';\n\nimport { FAUCET_CAPABILITY_KEY_PREFIX, type FaucetStrategy } from '../faucet/index.ts';\nimport {\n\tchainKeyedStrategyFor,\n\tStrategyRegistryService,\n} from '../../substrate/runtime/strategy-registry/index.ts';\nimport type { AnyResourceRef, ResourceRef } from '../../api/define-plugin.ts';\nimport type { LeaseBroker } from '../../substrate/runtime/lease-broker/index.ts';\nimport type { ChainId } from '../../substrate/brand.ts';\nimport type {\n\tAccountFundingRequest as ContractAccountFundingRequest,\n\tAccountFundingStrategy as ContractAccountFundingStrategy,\n} from '../../contracts/funding-strategy.ts';\nimport { setCurrentPluginPhase } from '../../substrate/runtime/current-plugin.ts';\nimport {\n\tBALANCE_POLL_PROFILE,\n\tmakeBoundedSpacedSchedule,\n} from '../../substrate/runtime/retry-policy.ts';\n\nimport {\n\taccountAcquireError,\n\ttype AccountAcquireError,\n\ttype AccountVariantKind,\n} from './errors.ts';\nimport { withAddressLease } from './lease.ts';\nimport { fundingFailureError } from '../internal/funding-failure-error.ts';\nimport type { AccountValue } from './service.ts';\nimport { AccountSpans } from './spans.ts';\nimport { SuiSpans } from '../sui/index.ts';\n\n// `CoinResourceId` is the literal-typed resource id the coin plugin\n// publishes. Inlined here as `coin:${Sym}` so this file does NOT\n// cross-import the coin plugin — the substrate's compose-time dedup\n// works by string equality on the resource id, and the coin plugin's\n// `coinResourceId` constructor produces the same shape. This is the\n// per-Task-A \"inline the literal type alias\" decision (the literal\n// pattern is the contract; promoting it to a substrate type would\n// be more ceremony than the single string template warrants).\ntype CoinResourceId<Sym extends string> = `coin:${Sym}`;\n\n/** Direct resource ref shape for a coin upstream. The user passes the\n * result of `coin.fromPackage(...)` / `coin.known(...)` /\n * `coin.builtin(...)` — NOT a bare string or discriminator. Generic\n * over the literal symbol so the account's dependency tuple preserves\n * each per-coin resource id (`coin:managed_coin/managed_coin`,\n * `coin:wal`, ...).\n *\n * Architecture (Direct Member Refs): cross-plugin references at the\n * user-facing surface are plugin/resource refs directly — no opaque\n * tag or string discriminator vocabulary. */\nexport interface AccountFundingCoinValue {\n\treadonly fullCoinType: string;\n\treadonly symbol?: string;\n}\n\nexport type CoinMember<Sym extends string = string> = ResourceRef<\n\tCoinResourceId<Sym>,\n\tAccountFundingCoinValue\n>;\n\n/** Optional dependency edge for the plugin that contributes the\n * funding strategy. Coin refs force the coin metadata edge; `via`\n * forces the strategy-provider edge (e.g. a known DeepBook\n * deployment that contributes `coinType:<DEEP>`). */\nexport type CrossCuttingFundingProvider = AnyResourceRef | readonly AnyResourceRef[];\n\n/** Built-in SUI funding entry. This uses the same account funding\n * list as arbitrary coins but avoids requiring `coin.builtin('sui')`\n * for the normal SUI faucet path. */\nexport interface SuiFundingEntry {\n\treadonly coin: 'sui';\n\treadonly amount: number | bigint;\n}\n\n/** A single cross-cutting funding entry. `coin` is a direct member ref\n * (the value returned by `coin.fromPackage(...)` etc.) — the account plugin\n * threads it through `dependsOn` so the substrate's dep graph forces\n * the publishing / discovery edge to land before funding.\n *\n * Distilled-doc invariant (\"Strict upstream declaration\"): coin\n * references cited by Account must force a dep edge. `via` is the\n * same contract for the strategy contributor that can satisfy the\n * funding request. */\nexport interface CrossCuttingFundingEntry<M extends CoinMember = CoinMember> {\n\treadonly coin: M;\n\treadonly amount: bigint;\n\treadonly via?: CrossCuttingFundingProvider;\n}\n\nexport type AccountFundingEntry<M extends CoinMember = CoinMember> =\n\t| SuiFundingEntry\n\t| CrossCuttingFundingEntry<M>;\n\nexport type AccountFunding = ReadonlyArray<AccountFundingEntry>;\n\n/** Internal projected shape — the acquire body in `account/index.ts`\n * receives each funding entry's resolved `CoinValue`, reads\n * `fullCoinType`, and passes the projected entries to\n * `applyCrossCuttingFunding`. The funding pass never sees the raw\n * member refs — keeps the strategy dispatch logic\n * substrate-name-blind. */\nexport interface ProjectedFundingEntry {\n\treadonly coin: string;\n\treadonly fullCoinType: string;\n\treadonly amount: bigint;\n}\n\nexport type ProjectedFunding = ReadonlyArray<ProjectedFundingEntry>;\n\n/** Outcome marker carried on each `applied` entry — distinguishes a\n * faucet/strategy call that actually moved funds (`'funded'`) from\n * the short-circuit case where the existing balance already covered\n * the request (`'already-satisfied'`). Downstream projection turns\n * this into the `AccountRegistryFundingEntry.status` column so a\n * no-faucet-call entry is not mislabeled as \"funded\".\n *\n * Distilled-doc invariant: the `applied` projection must reflect\n * what actually happened — not the user's request shape. */\nexport type AppliedFundingOutcome = 'funded' | 'already-satisfied';\n\nexport interface AppliedFundingEntry extends ProjectedFundingEntry {\n\treadonly outcome: AppliedFundingOutcome;\n}\n\nexport type AppliedFunding = ReadonlyArray<AppliedFundingEntry>;\n\nexport interface AccountFundingResult {\n\treadonly requested: ProjectedFunding;\n\treadonly applied: AppliedFunding;\n}\n\n/** Account-bus projection of the substrate funding-request contract\n * (`contracts/funding-strategy.ts`). Narrows the contract's generic\n * account-handle slot to the concrete `AccountValue` this plugin\n * publishes; strategies inside account or in sibling plugins\n * (coin/walrus/deepbook) see the real handle type without re-stating\n * the substrate shape. */\nexport type AccountFundingRequest = ContractAccountFundingRequest<AccountValue>;\n\n/** Account-bus projection of the substrate strategy contract. The\n * generic account-handle slot is fixed to `AccountValue` so\n * contributing plugins receive a typed account handle. */\nexport type AccountFundingStrategy<E = unknown> = ContractAccountFundingStrategy<E, AccountValue>;\n\nexport interface FundingBalanceReader {\n\treadonly readBalance: (args: {\n\t\treadonly owner: string;\n\t\treadonly coinType: string;\n\t}) => Effect.Effect<bigint | null>;\n}\n\n/** Sentinel brand identifying the test-only no-op reader. Surfaced as\n * a separate `readonly skipFinalityWait?: true` discriminator on\n * `NULL_BALANCE_READER` so the funding pass can short-circuit the\n * finality wait deterministically WITHOUT exhausting the bounded\n * poll schedule. Production readers MUST NOT set this. */\ninterface NullBalanceReader extends FundingBalanceReader {\n\treadonly skipFinalityWait: true;\n}\n\n/** Test-only no-op balance reader.\n *\n * Production callers (`account/service.ts`) build a real reader from\n * the live SDK via `makeFundingBalanceReader`; the funding pass\n * REQUIRES a reader so the post-faucet finality wait is load-bearing\n * on real wire calls. Tests that don't model the read/poll loop pass\n * this sentinel to explicitly opt OUT of the wait — the absence of\n * this opt-out previously hid as a silent `Effect.void` short-circuit\n * on any production caller that forgot to wire the reader. */\nexport const NULL_BALANCE_READER: FundingBalanceReader = {\n\treadBalance: () => Effect.succeed(null),\n\tskipFinalityWait: true,\n} as NullBalanceReader;\n\nconst skipsFinalityWait = (reader: FundingBalanceReader): boolean =>\n\t(reader as NullBalanceReader).skipFinalityWait === true;\n\n/** The canonical builtin SUI coin type. Used by the funding dispatch\n * to route SUI entries to the faucet strategy (same key as the\n * default-funding pass), and by everything that needs to detect\n * \"this is the protocol-defined SUI\". Mirrors `BUILTIN_COINS.sui`\n * in the coin plugin. */\nexport const SUI_FULL_COIN_TYPE = '0x2::sui::SUI' as const;\n\n/** Default funding amount for ephemeral accounts — 1 SUI in MIST.\n * Documented at the user-facing factory so a bare `account('alice')`\n * is predictable. */\nexport const DEFAULT_EPHEMERAL_FUND_MIST = 1_000_000_000n;\n\n/** Inputs the default-funding pass needs from the per-acquire ctx. */\nexport interface FundEphemeralDefaultArgs {\n\treadonly accountName: string;\n\treadonly address: string;\n\treadonly amountMist: bigint;\n\treadonly suiMode: 'local' | 'local-rpc' | 'live' | 'fork';\n\t/** Resolved sui chain id — the substrate-level chain identity used\n\t * to compose the faucet strategy's capability key\n\t * (`faucet:request:<chainId>`). */\n\treadonly chainId: ChainId;\n\t/** Loud-by-default auto-promotion event (called on fork before the\n\t * strategy is invoked, per the architecture's \"no silent surprises\"\n\t * principle). */\n\treadonly emitAutoPromotionEvent: () => Effect.Effect<void>;\n\t/** Substrate lease-broker handle — funding opens a fresh scope per\n\t * wire call and acquires the per-address lease so concurrent wire\n\t * calls for the same address serialize at the chain boundary. */\n\treadonly broker: LeaseBroker;\n\t/** Required. Production callers build this from the SDK via\n\t * `makeFundingBalanceReader`; tests that don't model the read/poll\n\t * loop opt out explicitly with `NULL_BALANCE_READER`. The previous\n\t * optional shape allowed a silent `Effect.void` short-circuit on\n\t * the finality wait when callers forgot to wire it. */\n\treadonly balanceReader: FundingBalanceReader;\n}\n\n/** Outcome of `fundEphemeralDefault`. `'skipped'` covers the\n * zero-amount no-op; `'already-satisfied'` covers the pre-existing-\n * balance short-circuit (no faucet call); `'funded'` covers the\n * successful wire path. Callers project this into the `applied`\n * shape so the `funded`-vs-`already-satisfied` distinction survives\n * to the registry projection. */\nexport type FundEphemeralDefaultOutcome = 'funded' | 'already-satisfied' | 'skipped';\n\n/** Apply the default-funding pass for an ephemeral account.\n *\n * Wiring: yields `StrategyRegistryService` (the R-channel from\n * Round 7), looks up the faucet strategy registered by the Sui\n * plugin under `faucet:request:<chainId>`, and dispatches a request\n * through it. Per-address serialization is enforced by acquiring\n * the address lock around the wire call. */\nexport const fundEphemeralDefault = (\n\tparts: FundEphemeralDefaultArgs,\n): Effect.Effect<FundEphemeralDefaultOutcome, AccountAcquireError, StrategyRegistryService> =>\n\tEffect.gen(function* () {\n\t\t// LOUD AUTO-PROMOTION — distilled-doc invariant: \"no silent\n\t\t// surprises\". Emit BEFORE attempting the dispatch so the user\n\t\t// sees the path change even if the wire call subsequently\n\t\t// fails. On fork we surface the path-change event; on non-fork\n\t\t// the strategy registered by Sui IS the canonical default and\n\t\t// no auto-promotion is needed.\n\t\tif (parts.suiMode === 'fork') {\n\t\t\tyield* parts.emitAutoPromotionEvent();\n\t\t}\n\n\t\t// Zero-amount short-circuit — both real strategies treat zero\n\t\t// as a no-op; doing the same here avoids a registry lookup +\n\t\t// span emission for the legitimately-no-funding case.\n\t\tif (parts.amountMist <= 0n) {\n\t\t\treturn 'skipped' as const;\n\t\t}\n\n\t\tyield* setCurrentPluginPhase('checking SUI funding');\n\t\tconst existingBalance = yield* readExistingBalance(parts.balanceReader, {\n\t\t\towner: parts.address,\n\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t});\n\t\tif (existingBalance !== null && existingBalance >= parts.amountMist) {\n\t\t\treturn 'already-satisfied' as const;\n\t\t}\n\n\t\t// Look up the strategy. Sui auto-registers a faucet strategy\n\t\t// on non-fork modes; fork-mode strategies have to be supplied\n\t\t// by the faucet plugin (with the fork admin closed over). If\n\t\t// nothing is registered we surface a typed, actionable error\n\t\t// pointing at the architecture's contract: ephemeral-on-non-\n\t\t// fork without a Faucet MUST fail at acquire time.\n\t\tconst strategy = yield* chainKeyedStrategyFor<FaucetStrategy>(\n\t\t\tFAUCET_CAPABILITY_KEY_PREFIX,\n\t\t\tparts.chainId,\n\t\t).pipe(\n\t\t\tEffect.catchTag('StrategyNotFoundError', (err) =>\n\t\t\t\tEffect.fail(\n\t\t\t\t\taccountAcquireError({\n\t\t\t\t\t\tphase: 'fund-default',\n\t\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\t\tvariant: 'ephemeral',\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`Account '${parts.accountName}': no faucet strategy registered for ` +\n\t\t\t\t\t\t\t`chain '${parts.chainId}' (sui mode=${parts.suiMode}). ` +\n\t\t\t\t\t\t\t`Registered keys: [${err.registeredKeys.join(', ')}].`,\n\t\t\t\t\t\thint:\n\t\t\t\t\t\t\tparts.suiMode === 'fork'\n\t\t\t\t\t\t\t\t? 'Fork networks have no HTTP faucet — compose a plugin that contributes defineFaucetStrategy(...) for this chain id.'\n\t\t\t\t\t\t\t\t: 'Ensure a sui() plugin with a faucet-bearing mode (local/live-testnet/live-devnet) is in the stack.',\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t\t// Per-address serialization around the wire call. The lease is\n\t\t// scope-bound and releases as soon as `request(...)` returns;\n\t\t// two concurrent funding requests for the same address — e.g.\n\t\t// ephemeral default + cross-cutting SUI top-up — interleave\n\t\t// deterministically via the broker's FIFO queue.\n\t\tconst wrapFaucetFailure = (cause: {\n\t\t\treadonly _tag: 'FaucetUnreachable' | 'FaucetExhausted' | 'FaucetBodyError';\n\t\t}) =>\n\t\t\tEffect.fail(\n\t\t\t\tfundingFailureError({\n\t\t\t\t\tphase: 'fund-default',\n\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\tvariant: 'ephemeral',\n\t\t\t\t\tchainId: parts.chainId,\n\t\t\t\t\tcause,\n\t\t\t\t}),\n\t\t\t);\n\t\tyield* setCurrentPluginPhase('funding SUI');\n\t\tyield* withAddressLease(\n\t\t\tparts.broker,\n\t\t\tparts.accountName,\n\t\t\tparts.address,\n\t\t\tstrategy.request({ address: parts.address, amount: parts.amountMist }).pipe(\n\t\t\t\tEffect.catchTags({\n\t\t\t\t\tFaucetUnreachable: wrapFaucetFailure,\n\t\t\t\t\tFaucetExhausted: wrapFaucetFailure,\n\t\t\t\t\tFaucetBodyError: wrapFaucetFailure,\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t\tyield* setCurrentPluginPhase('waiting for SUI funding settlement');\n\t\tyield* waitForBalanceAtLeast({\n\t\t\tbalanceReader: parts.balanceReader,\n\t\t\taccountName: parts.accountName,\n\t\t\tvariant: 'ephemeral',\n\t\t\tphase: 'fund-default',\n\t\t\towner: parts.address,\n\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t\tcoinLabel: 'SUI',\n\t\t\tamount: parts.amountMist,\n\t\t});\n\n\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t[AccountSpans.name]: parts.accountName,\n\t\t\t[AccountSpans.address]: parts.address,\n\t\t\t[AccountSpans.fundAmountMist]: parts.amountMist.toString(),\n\t\t\t[SuiSpans.chain]: parts.chainId,\n\t\t\t[SuiSpans.mode]: parts.suiMode,\n\t\t});\n\t\treturn 'funded' as const;\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.account.fundEphemeralDefault', {\n\t\t\tattributes: {\n\t\t\t\t[AccountSpans.name]: parts.accountName,\n\t\t\t\t[AccountSpans.address]: parts.address,\n\t\t\t\t[SuiSpans.mode]: parts.suiMode,\n\t\t\t},\n\t\t}),\n\t);\n\n/** Inputs the cross-cutting funding pass needs from the per-acquire ctx.\n *\n * `funding` is the PROJECTED shape — the acquire body in\n * `account/index.ts` receives each user-supplied `CoinMember` as a\n * resolved dependency and projects to `{fullCoinType, amount}` BEFORE\n * invoking this pass. Keeps the dispatch logic substrate-name-blind. */\nexport interface ApplyCrossCuttingFundingArgs {\n\treadonly accountName: string;\n\treadonly address: string;\n\treadonly variant: AccountVariantKind;\n\treadonly account: AccountValue;\n\treadonly funding: ProjectedFunding;\n\treadonly chainId: ChainId;\n\treadonly broker: LeaseBroker;\n\t/** Required. See `FundEphemeralDefaultArgs.balanceReader`. */\n\treadonly balanceReader: FundingBalanceReader;\n}\n\n/** Apply the cross-cutting funding pass. Variant-agnostic — runs for\n * every variant once the keypair / impersonation slot is bound and\n * the address is known.\n *\n * Distilled-doc invariant: \"Optional Faucet is a noop, not an\n * error\". Absence of a registered strategy for a non-SUI coin's\n * capability key short-circuits silently (the entry is dropped).\n * Explicit SUI entries are stricter: they route through the active\n * chain's faucet strategy and fail loudly when none is registered.\n * This lets a test author opt INTO arbitrary-coin funding without\n * forcing every surrounding network to satisfy every custom coin.\n *\n * Wiring: SUI entries (`fullCoinType === '0x2::sui::SUI'`) dispatch\n * through `faucet:request:<chainId>` (same key as the default pass);\n * other entries dispatch through `coinType:<fullCoinType>` keys\n * contributed by the respective Coin/Walrus/Seal plugins.\n *\n * Entries are processed serially. Strategies that use the resolved\n * account signer acquire the per-address lease internally; strategies\n * that do not are wrapped by this dispatcher. */\nexport const applyCrossCuttingFunding = (\n\tparts: ApplyCrossCuttingFundingArgs,\n): Effect.Effect<AppliedFunding, AccountAcquireError, StrategyRegistryService> =>\n\tEffect.gen(function* () {\n\t\tif (parts.funding.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\tconst registry = yield* StrategyRegistryService;\n\t\tconst applied: AppliedFundingEntry[] = [];\n\n\t\tfor (const entry of parts.funding) {\n\t\t\tif (entry.amount <= 0n) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tyield* setCurrentPluginPhase(`checking ${entry.coin} funding`);\n\t\t\tconst existingBalance = yield* readExistingBalance(parts.balanceReader, {\n\t\t\t\towner: parts.address,\n\t\t\t\tcoinType: entry.fullCoinType,\n\t\t\t});\n\t\t\tif (existingBalance !== null && existingBalance >= entry.amount) {\n\t\t\t\tapplied.push({ ...entry, outcome: 'already-satisfied' });\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Resolve the capability key from the projected coin type.\n\t\t\t//\n\t\t\t// SUI (`0x2::sui::SUI`) → reuse the faucet-request key so the\n\t\t\t// SUI auto-registered strategy fields the request (this\n\t\t\t// matches the default-funding pass and keeps the registry\n\t\t\t// surface uniform). The faucet contract takes\n\t\t\t// `{address, amount}` only (it never sees the resolved\n\t\t\t// account handle) — kept as its own helper so the typing is\n\t\t\t// honest at the dispatch site.\n\t\t\t//\n\t\t\t// Everything else → `coinType:<fullCoinType>` so user-defined\n\t\t\t// Coin plugins (and Walrus's exchange strategy keyed by\n\t\t\t// `coinType:<WAL fullCoinType>`) can contribute strategies\n\t\t\t// declaratively. These satisfy `AccountFundingStrategy` and\n\t\t\t// receive the resolved account handle in the request.\n\t\t\tconst isSui = entry.fullCoinType === SUI_FULL_COIN_TYPE;\n\t\t\tconst coinKey = `coinType:${entry.fullCoinType}` as const;\n\t\t\tconst key = isSui ? (`faucet:request:${parts.chainId}` as const) : coinKey;\n\n\t\t\tconst wrapCrossCuttingFailure = (cause: unknown): AccountAcquireError =>\n\t\t\t\tfundingFailureError({\n\t\t\t\t\tphase: 'fund-cross-cutting',\n\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\tvariant: parts.variant,\n\t\t\t\t\tkey,\n\t\t\t\t\tamount: entry.amount,\n\t\t\t\t\tcause,\n\t\t\t\t});\n\n\t\t\tlet request: Effect.Effect<void, AccountAcquireError>;\n\t\t\tlet usesAccountSigner = false;\n\t\t\tif (isSui) {\n\t\t\t\t// FaucetStrategy lookup — request shape is `{address, amount}`.\n\t\t\t\t// Architecture-distilled: explicit SUI entries are the\n\t\t\t\t// normal gas faucet path, so missing strategy is\n\t\t\t\t// actionable and loud (no silent drop).\n\t\t\t\tconst strategy = yield* chainKeyedStrategyFor<FaucetStrategy>(\n\t\t\t\t\tFAUCET_CAPABILITY_KEY_PREFIX,\n\t\t\t\t\tparts.chainId,\n\t\t\t\t).pipe(\n\t\t\t\t\tEffect.catchTag('StrategyNotFoundError', (err) =>\n\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\taccountAcquireError({\n\t\t\t\t\t\t\t\tphase: 'fund-cross-cutting',\n\t\t\t\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\t\t\t\tvariant: parts.variant,\n\t\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\t\t`Account '${parts.accountName}': no SUI funding strategy registered ` +\n\t\t\t\t\t\t\t\t\t`for chain '${parts.chainId}'. Registered keys: [${err.registeredKeys.join(', ')}].`,\n\t\t\t\t\t\t\t\tcause: err,\n\t\t\t\t\t\t\t\thint: 'Ensure a sui() plugin with a faucet-bearing mode (local/live-testnet/live-devnet) is in the stack.',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\trequest = strategy\n\t\t\t\t\t.request({ address: parts.address, amount: entry.amount })\n\t\t\t\t\t.pipe(Effect.mapError(wrapCrossCuttingFailure));\n\t\t\t} else {\n\t\t\t\t// AccountFundingStrategy lookup — request shape is\n\t\t\t\t// `{address, amount, account}`. Architecture-distilled:\n\t\t\t\t// optional-faucet-is-noop for arbitrary coins — missing\n\t\t\t\t// registration short-circuits silently rather than\n\t\t\t\t// failing the acquire.\n\t\t\t\tconst strategy = yield* registry\n\t\t\t\t\t.get<typeof coinKey, AccountFundingStrategy>(coinKey)\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\tEffect.catchTag('StrategyNotFoundError', () =>\n\t\t\t\t\t\t\tEffect.succeed(null as AccountFundingStrategy | null),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\tif (strategy === null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tusesAccountSigner = strategy.usesAccountSigner === true;\n\t\t\t\trequest = strategy\n\t\t\t\t\t.request({ address: parts.address, amount: entry.amount, account: parts.account })\n\t\t\t\t\t.pipe(Effect.mapError(wrapCrossCuttingFailure));\n\t\t\t}\n\n\t\t\tyield* setCurrentPluginPhase(`funding ${entry.coin}`);\n\t\t\tyield* usesAccountSigner\n\t\t\t\t? request\n\t\t\t\t: withAddressLease(parts.broker, parts.accountName, parts.address, request);\n\t\t\tyield* setCurrentPluginPhase(`waiting for ${entry.coin} funding settlement`);\n\t\t\tyield* waitForBalanceAtLeast({\n\t\t\t\tbalanceReader: parts.balanceReader,\n\t\t\t\taccountName: parts.accountName,\n\t\t\t\tvariant: parts.variant,\n\t\t\t\tphase: 'fund-cross-cutting',\n\t\t\t\towner: parts.address,\n\t\t\t\tcoinType: entry.fullCoinType,\n\t\t\t\tcoinLabel: entry.coin,\n\t\t\t\tamount: entry.amount,\n\t\t\t});\n\t\t\tapplied.push({ ...entry, outcome: 'funded' });\n\t\t}\n\n\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t[AccountSpans.name]: parts.accountName,\n\t\t\t[AccountSpans.address]: parts.address,\n\t\t\t[AccountSpans.fundCrossCuttingCount]: parts.funding.length,\n\t\t\t[SuiSpans.chain]: parts.chainId,\n\t\t});\n\t\treturn applied;\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.account.applyCrossCuttingFunding', {\n\t\t\tattributes: {\n\t\t\t\t[AccountSpans.name]: parts.accountName,\n\t\t\t\t[AccountSpans.address]: parts.address,\n\t\t\t\t[AccountSpans.fundCrossCuttingEntries]: parts.funding.length,\n\t\t\t},\n\t\t}),\n\t);\n\nconst readExistingBalance = (\n\tbalanceReader: FundingBalanceReader,\n\targs: {\n\t\treadonly owner: string;\n\t\treadonly coinType: string;\n\t},\n): Effect.Effect<bigint | null> => balanceReader.readBalance(args);\n\nconst waitForBalanceAtLeast = (parts: {\n\treadonly balanceReader: FundingBalanceReader;\n\treadonly accountName: string;\n\treadonly variant: AccountVariantKind;\n\treadonly phase: 'fund-default' | 'fund-cross-cutting';\n\treadonly owner: string;\n\treadonly coinType: string;\n\treadonly coinLabel: string;\n\treadonly amount: bigint;\n}): Effect.Effect<void, AccountAcquireError> => {\n\tconst reader = parts.balanceReader;\n\t// Test-only opt-out — the `NULL_BALANCE_READER` sentinel explicitly\n\t// declares \"this caller doesn't model the read/poll loop\". Production\n\t// readers never set `skipFinalityWait`, so the wait stays load-bearing\n\t// on real wire calls.\n\tif (skipsFinalityWait(reader)) {\n\t\treturn Effect.void;\n\t}\n\treturn Effect.gen(function* () {\n\t\tconst read = readExistingBalance(reader, {\n\t\t\towner: parts.owner,\n\t\t\tcoinType: parts.coinType,\n\t\t});\n\t\tconst lastBalance = yield* read.pipe(\n\t\t\tEffect.repeat({\n\t\t\t\tschedule: makeBoundedSpacedSchedule(\n\t\t\t\t\tBALANCE_POLL_PROFILE.intervalMs,\n\t\t\t\t\tBALANCE_POLL_PROFILE.timeoutMs,\n\t\t\t\t),\n\t\t\t\tuntil: (balance) => balance !== null && balance >= parts.amount,\n\t\t\t}),\n\t\t);\n\t\tif (lastBalance !== null && lastBalance >= parts.amount) {\n\t\t\treturn;\n\t\t}\n\t\treturn yield* Effect.fail(\n\t\t\taccountAcquireError({\n\t\t\t\tphase: parts.phase,\n\t\t\t\taccountName: parts.accountName,\n\t\t\t\tvariant: parts.variant,\n\t\t\t\tmessage:\n\t\t\t\t\t`Account '${parts.accountName}': funding for ${parts.coinLabel} was accepted ` +\n\t\t\t\t\t`but balance did not reach ${parts.amount} before the settlement timeout ` +\n\t\t\t\t\t`(last=${lastBalance === null ? '<unavailable>' : lastBalance}).`,\n\t\t\t\thint:\n\t\t\t\t\t'The faucet or funding strategy returned before the funded coin became spendable. ' +\n\t\t\t\t\t'Check the funding strategy finality gate and Sui RPC health.',\n\t\t\t}),\n\t\t);\n\t});\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"funding.mjs","names":[],"sources":["../../../src/plugins/account/funding.ts"],"sourcesContent":["// Account plugin — funding logic.\n//\n// Two funding paths converge here:\n//\n// 1. **Default funding** — applies to the `ephemeral` variant only.\n// On non-fork networks: faucet POST via the SUI HTTP strategy\n// auto-registered by Faucet (see 11-faucet.md). On fork networks:\n// \"pay from a seed via impersonation\" because forks have no\n// faucet. The auto-promotion is LOUD by default per the\n// architecture's \"no silent surprises\" principle — we emit a\n// `log.appended` event the first time a stack hits this path.\n//\n// 2. **Cross-cutting funding** — declared per-account via\n// `AccountOptions.funding`. Applies to every variant.\n// Dispatched through the ambient strategy registry. Missing\n// strategy for non-SUI coins ⇒ silent noop (architecture-\n// mandated test-ergonomics contract, distilled-doc invariant:\n// \"Optional Faucet is a noop, not an error\"). Explicit SUI\n// entries use the SUI faucet strategy and fail loudly when no\n// faucet-bearing strategy exists.\n//\n// Distilled-doc invariant: per-address serialization — concurrent\n// funding requests for the same address MUST serialize. We share the\n// substrate `LeaseBroker` handle from `service.ts` and open a fresh\n// scope per wire call so the lease releases the moment that call\n// returns. Each cross-cutting iteration is its own scope: the broker\n// is non-reentrant by design, so a hypothetical loop holding a single\n// lease across iterations would deadlock the second one.\n\nimport { Effect } from 'effect';\n\nimport { FAUCET_CAPABILITY_KEY_PREFIX, type FaucetStrategy } from '../faucet/index.ts';\nimport {\n\tchainKeyedStrategyFor,\n\tStrategyRegistryService,\n} from '../../substrate/runtime/strategy-registry/index.ts';\nimport type { AnyResourceRef, ResourceRef } from '../../api/define-plugin.ts';\nimport type { LeaseBroker } from '../../substrate/runtime/lease-broker/index.ts';\nimport type {\n\tAccountFundingRequest as ContractAccountFundingRequest,\n\tAccountFundingStrategy as ContractAccountFundingStrategy,\n} from '../../contracts/funding-strategy.ts';\nimport { setCurrentPluginPhase } from '../../substrate/runtime/current-plugin.ts';\nimport {\n\tBALANCE_POLL_PROFILE,\n\tmakeBoundedSpacedSchedule,\n} from '../../substrate/runtime/retry-policy.ts';\n\nimport {\n\taccountAcquireError,\n\ttype AccountAcquireError,\n\ttype AccountVariantKind,\n} from './errors.ts';\nimport { withAddressLease } from './lease.ts';\nimport { fundingFailureError } from '../internal/funding-failure-error.ts';\nimport type { AccountValue } from './service.ts';\n\n// `CoinResourceId` is the literal-typed resource id the coin plugin\n// publishes. Inlined here as `coin:${Sym}` so this file does NOT\n// cross-import the coin plugin — the substrate's compose-time dedup\n// works by string equality on the resource id, and the coin plugin's\n// `coinResourceId` constructor produces the same shape. This is the\n// per-Task-A \"inline the literal type alias\" decision (the literal\n// pattern is the contract; promoting it to a substrate type would\n// be more ceremony than the single string template warrants).\ntype CoinResourceId<Sym extends string> = `coin:${Sym}`;\n\n/** Direct resource ref shape for a coin upstream. The user passes the\n * result of `coin.fromPackage(...)` / `coin.known(...)` /\n * `coin.builtin(...)` — NOT a bare string or discriminator. Generic\n * over the literal symbol so the account's dependency tuple preserves\n * each per-coin resource id (`coin:managed_coin/managed_coin`,\n * `coin:wal`, ...).\n *\n * Architecture (Direct Member Refs): cross-plugin references at the\n * user-facing surface are plugin/resource refs directly — no opaque\n * tag or string discriminator vocabulary. */\nexport interface AccountFundingCoinValue {\n\treadonly fullCoinType: string;\n\treadonly symbol?: string;\n}\n\nexport type CoinMember<Sym extends string = string> = ResourceRef<\n\tCoinResourceId<Sym>,\n\tAccountFundingCoinValue\n>;\n\n/** Optional dependency edge for the plugin that contributes the\n * funding strategy. Coin refs force the coin metadata edge; `via`\n * forces the strategy-provider edge (e.g. a known DeepBook\n * deployment that contributes `coinType:<DEEP>`). */\nexport type CrossCuttingFundingProvider = AnyResourceRef | readonly AnyResourceRef[];\n\n/** Built-in SUI funding entry. This uses the same account funding\n * list as arbitrary coins but avoids requiring `coin.builtin('sui')`\n * for the normal SUI faucet path. */\nexport interface SuiFundingEntry {\n\treadonly coin: 'sui';\n\treadonly amount: number | bigint;\n}\n\n/** A single cross-cutting funding entry. `coin` is a direct member ref\n * (the value returned by `coin.fromPackage(...)` etc.) — the account plugin\n * threads it through `dependsOn` so the substrate's dep graph forces\n * the publishing / discovery edge to land before funding.\n *\n * Distilled-doc invariant (\"Strict upstream declaration\"): coin\n * references cited by Account must force a dep edge. `via` is the\n * same contract for the strategy contributor that can satisfy the\n * funding request. */\nexport interface CrossCuttingFundingEntry<M extends CoinMember = CoinMember> {\n\treadonly coin: M;\n\treadonly amount: bigint;\n\treadonly via?: CrossCuttingFundingProvider;\n}\n\nexport type AccountFundingEntry<M extends CoinMember = CoinMember> =\n\t| SuiFundingEntry\n\t| CrossCuttingFundingEntry<M>;\n\nexport type AccountFunding = ReadonlyArray<AccountFundingEntry>;\n\n/** Internal projected shape — the acquire body in `account/index.ts`\n * receives each funding entry's resolved `CoinValue`, reads\n * `fullCoinType`, and passes the projected entries to\n * `applyCrossCuttingFunding`. The funding pass never sees the raw\n * member refs — keeps the strategy dispatch logic\n * substrate-name-blind. */\nexport interface ProjectedFundingEntry {\n\treadonly coin: string;\n\treadonly fullCoinType: string;\n\treadonly amount: bigint;\n}\n\nexport type ProjectedFunding = ReadonlyArray<ProjectedFundingEntry>;\n\n/** Outcome marker carried on each `applied` entry — distinguishes a\n * faucet/strategy call that actually moved funds (`'funded'`) from\n * the short-circuit case where the existing balance already covered\n * the request (`'already-satisfied'`). Downstream projection turns\n * this into the `AccountRegistryFundingEntry.status` column so a\n * no-faucet-call entry is not mislabeled as \"funded\".\n *\n * Distilled-doc invariant: the `applied` projection must reflect\n * what actually happened — not the user's request shape. */\nexport type AppliedFundingOutcome = 'funded' | 'already-satisfied';\n\nexport interface AppliedFundingEntry extends ProjectedFundingEntry {\n\treadonly outcome: AppliedFundingOutcome;\n}\n\nexport type AppliedFunding = ReadonlyArray<AppliedFundingEntry>;\n\nexport interface AccountFundingResult {\n\treadonly requested: ProjectedFunding;\n\treadonly applied: AppliedFunding;\n}\n\n/** Account-bus projection of the substrate funding-request contract\n * (`contracts/funding-strategy.ts`). Narrows the contract's generic\n * account-handle slot to the concrete `AccountValue` this plugin\n * publishes; strategies inside account or in sibling plugins\n * (coin/walrus/deepbook) see the real handle type without re-stating\n * the substrate shape. */\nexport type AccountFundingRequest = ContractAccountFundingRequest<AccountValue>;\n\n/** Account-bus projection of the substrate strategy contract. The\n * generic account-handle slot is fixed to `AccountValue` so\n * contributing plugins receive a typed account handle. */\nexport type AccountFundingStrategy<E = unknown> = ContractAccountFundingStrategy<E, AccountValue>;\n\nexport interface FundingBalanceReader {\n\treadonly readBalance: (args: {\n\t\treadonly owner: string;\n\t\treadonly coinType: string;\n\t}) => Effect.Effect<bigint | null>;\n}\n\n/** Sentinel brand identifying the test-only no-op reader. Surfaced as\n * a separate `readonly skipFinalityWait?: true` discriminator on\n * `NULL_BALANCE_READER` so the funding pass can short-circuit the\n * finality wait deterministically WITHOUT exhausting the bounded\n * poll schedule. Production readers MUST NOT set this. */\ninterface NullBalanceReader extends FundingBalanceReader {\n\treadonly skipFinalityWait: true;\n}\n\n/** Test-only no-op balance reader.\n *\n * Production callers (`account/service.ts`) build a real reader from\n * the live SDK via `makeFundingBalanceReader`; the funding pass\n * REQUIRES a reader so the post-faucet finality wait is load-bearing\n * on real wire calls. Tests that don't model the read/poll loop pass\n * this sentinel to explicitly opt OUT of the wait. Requiring an\n * explicit reader means a production caller that forgets to wire one\n * fails loudly rather than silently short-circuiting the wait. */\nexport const NULL_BALANCE_READER: FundingBalanceReader = {\n\treadBalance: () => Effect.succeed(null),\n\tskipFinalityWait: true,\n} as NullBalanceReader;\n\nconst skipsFinalityWait = (reader: FundingBalanceReader): boolean =>\n\t(reader as NullBalanceReader).skipFinalityWait === true;\n\n/** The canonical builtin SUI coin type. Used by the funding dispatch\n * to route SUI entries to the faucet strategy (same key as the\n * default-funding pass), and by everything that needs to detect\n * \"this is the protocol-defined SUI\". Mirrors `BUILTIN_COINS.sui`\n * in the coin plugin. */\nexport const SUI_FULL_COIN_TYPE = '0x2::sui::SUI' as const;\n\n/** Default funding amount for ephemeral accounts — 1 SUI in MIST.\n * Documented at the user-facing factory so a bare `account('alice')`\n * is predictable. */\nexport const DEFAULT_EPHEMERAL_FUND_MIST = 1_000_000_000n;\n\n/** Inputs the default-funding pass needs from the per-acquire ctx. */\nexport interface FundEphemeralDefaultArgs {\n\treadonly accountName: string;\n\treadonly address: string;\n\treadonly amountMist: bigint;\n\treadonly suiMode: 'local' | 'local-rpc' | 'live' | 'fork';\n\t/** Resolved sui chain id — the substrate-level chain identity used\n\t * to compose the faucet strategy's capability key\n\t * (`faucet:request:<chainId>`). */\n\treadonly chainId: string;\n\t/** Loud-by-default auto-promotion event (called on fork before the\n\t * strategy is invoked, per the architecture's \"no silent surprises\"\n\t * principle). */\n\treadonly emitAutoPromotionEvent: () => Effect.Effect<void>;\n\t/** Substrate lease-broker handle — funding opens a fresh scope per\n\t * wire call and acquires the per-address lease so concurrent wire\n\t * calls for the same address serialize at the chain boundary. */\n\treadonly broker: LeaseBroker;\n\t/** Required. Production callers build this from the SDK via\n\t * `makeFundingBalanceReader`; tests that don't model the read/poll\n\t * loop opt out explicitly with `NULL_BALANCE_READER`. The previous\n\t * optional shape allowed a silent `Effect.void` short-circuit on\n\t * the finality wait when callers forgot to wire it. */\n\treadonly balanceReader: FundingBalanceReader;\n}\n\n/** Outcome of `fundEphemeralDefault`. `'skipped'` covers the\n * zero-amount no-op; `'already-satisfied'` covers the pre-existing-\n * balance short-circuit (no faucet call); `'funded'` covers the\n * successful wire path. Callers project this into the `applied`\n * shape so the `funded`-vs-`already-satisfied` distinction survives\n * to the registry projection. */\nexport type FundEphemeralDefaultOutcome = 'funded' | 'already-satisfied' | 'skipped';\n\n/** Apply the default-funding pass for an ephemeral account.\n *\n * Wiring: yields `StrategyRegistryService` (the R-channel from\n * Round 7), looks up the faucet strategy registered by the Sui\n * plugin under `faucet:request:<chainId>`, and dispatches a request\n * through it. Per-address serialization is enforced by acquiring\n * the address lock around the wire call. */\nexport const fundEphemeralDefault = (\n\tparts: FundEphemeralDefaultArgs,\n): Effect.Effect<FundEphemeralDefaultOutcome, AccountAcquireError, StrategyRegistryService> =>\n\tEffect.gen(function* () {\n\t\t// LOUD AUTO-PROMOTION — distilled-doc invariant: \"no silent\n\t\t// surprises\". Emit BEFORE attempting the dispatch so the user\n\t\t// sees the path change even if the wire call subsequently\n\t\t// fails. On fork we surface the path-change event; on non-fork\n\t\t// the strategy registered by Sui IS the canonical default and\n\t\t// no auto-promotion is needed.\n\t\tif (parts.suiMode === 'fork') {\n\t\t\tyield* parts.emitAutoPromotionEvent();\n\t\t}\n\n\t\t// Zero-amount short-circuit — both real strategies treat zero\n\t\t// as a no-op; doing the same here avoids a registry lookup +\n\t\t// span emission for the legitimately-no-funding case.\n\t\tif (parts.amountMist <= 0n) {\n\t\t\treturn 'skipped' as const;\n\t\t}\n\n\t\tyield* setCurrentPluginPhase('checking SUI funding');\n\t\tconst existingBalance = yield* readExistingBalance(parts.balanceReader, {\n\t\t\towner: parts.address,\n\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t});\n\t\tif (existingBalance !== null && existingBalance >= parts.amountMist) {\n\t\t\treturn 'already-satisfied' as const;\n\t\t}\n\n\t\t// Look up the strategy. Sui auto-registers a faucet strategy\n\t\t// on non-fork modes; fork-mode strategies have to be supplied\n\t\t// by the faucet plugin (with the fork admin closed over). If\n\t\t// nothing is registered we surface a typed, actionable error\n\t\t// pointing at the architecture's contract: ephemeral-on-non-\n\t\t// fork without a Faucet MUST fail at acquire time.\n\t\tconst strategy = yield* chainKeyedStrategyFor<FaucetStrategy>(\n\t\t\tFAUCET_CAPABILITY_KEY_PREFIX,\n\t\t\tparts.chainId,\n\t\t).pipe(\n\t\t\tEffect.catchTag('StrategyNotFoundError', (err) =>\n\t\t\t\tEffect.fail(\n\t\t\t\t\taccountAcquireError({\n\t\t\t\t\t\tphase: 'fund-default',\n\t\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\t\tvariant: 'ephemeral',\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`Account '${parts.accountName}': no faucet strategy registered for ` +\n\t\t\t\t\t\t\t`chain '${parts.chainId}' (sui mode=${parts.suiMode}). ` +\n\t\t\t\t\t\t\t`Registered keys: [${err.registeredKeys.join(', ')}].`,\n\t\t\t\t\t\thint:\n\t\t\t\t\t\t\tparts.suiMode === 'fork'\n\t\t\t\t\t\t\t\t? 'Fork networks have no HTTP faucet — compose a plugin that contributes defineFaucetStrategy(...) for this chain id.'\n\t\t\t\t\t\t\t\t: 'Ensure a sui() plugin with a faucet-bearing mode (local/live-testnet/live-devnet) is in the stack.',\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t\t// Per-address serialization around the wire call. The lease is\n\t\t// scope-bound and releases as soon as `request(...)` returns;\n\t\t// two concurrent funding requests for the same address — e.g.\n\t\t// ephemeral default + cross-cutting SUI top-up — interleave\n\t\t// deterministically via the broker's FIFO queue.\n\t\tconst wrapFaucetFailure = (cause: {\n\t\t\treadonly _tag: 'FaucetUnreachable' | 'FaucetExhausted' | 'FaucetBodyError';\n\t\t}) =>\n\t\t\tEffect.fail(\n\t\t\t\tfundingFailureError({\n\t\t\t\t\tphase: 'fund-default',\n\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\tvariant: 'ephemeral',\n\t\t\t\t\tchainId: parts.chainId,\n\t\t\t\t\tcause,\n\t\t\t\t}),\n\t\t\t);\n\t\tyield* setCurrentPluginPhase('funding SUI');\n\t\tyield* withAddressLease(\n\t\t\tparts.broker,\n\t\t\tparts.accountName,\n\t\t\tparts.address,\n\t\t\tstrategy.request({ address: parts.address, amount: parts.amountMist }).pipe(\n\t\t\t\tEffect.catchTags({\n\t\t\t\t\tFaucetUnreachable: wrapFaucetFailure,\n\t\t\t\t\tFaucetExhausted: wrapFaucetFailure,\n\t\t\t\t\tFaucetBodyError: wrapFaucetFailure,\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t\tyield* setCurrentPluginPhase('waiting for SUI funding settlement');\n\t\tyield* waitForBalanceAtLeast({\n\t\t\tbalanceReader: parts.balanceReader,\n\t\t\taccountName: parts.accountName,\n\t\t\tvariant: 'ephemeral',\n\t\t\tphase: 'fund-default',\n\t\t\towner: parts.address,\n\t\t\tcoinType: SUI_FULL_COIN_TYPE,\n\t\t\tcoinLabel: 'SUI',\n\t\t\tamount: parts.amountMist,\n\t\t});\n\n\t\treturn 'funded' as const;\n\t});\n\n/** Inputs the cross-cutting funding pass needs from the per-acquire ctx.\n *\n * `funding` is the PROJECTED shape — the acquire body in\n * `account/index.ts` receives each user-supplied `CoinMember` as a\n * resolved dependency and projects to `{fullCoinType, amount}` BEFORE\n * invoking this pass. Keeps the dispatch logic substrate-name-blind. */\nexport interface ApplyCrossCuttingFundingArgs {\n\treadonly accountName: string;\n\treadonly address: string;\n\treadonly variant: AccountVariantKind;\n\treadonly account: AccountValue;\n\treadonly funding: ProjectedFunding;\n\treadonly chainId: string;\n\treadonly broker: LeaseBroker;\n\t/** Required. See `FundEphemeralDefaultArgs.balanceReader`. */\n\treadonly balanceReader: FundingBalanceReader;\n}\n\n/** Apply the cross-cutting funding pass. Variant-agnostic — runs for\n * every variant once the keypair / impersonation slot is bound and\n * the address is known.\n *\n * Distilled-doc invariant: \"Optional Faucet is a noop, not an\n * error\". Absence of a registered strategy for a non-SUI coin's\n * capability key short-circuits silently (the entry is dropped).\n * Explicit SUI entries are stricter: they route through the active\n * chain's faucet strategy and fail loudly when none is registered.\n * This lets a test author opt INTO arbitrary-coin funding without\n * forcing every surrounding network to satisfy every custom coin.\n *\n * Wiring: SUI entries (`fullCoinType === '0x2::sui::SUI'`) dispatch\n * through `faucet:request:<chainId>` (same key as the default pass);\n * other entries dispatch through `coinType:<fullCoinType>` keys\n * contributed by the respective Coin/Walrus/Seal plugins.\n *\n * Entries are processed serially. Strategies that use the resolved\n * account signer acquire the per-address lease internally; strategies\n * that do not are wrapped by this dispatcher. */\nexport const applyCrossCuttingFunding = (\n\tparts: ApplyCrossCuttingFundingArgs,\n): Effect.Effect<AppliedFunding, AccountAcquireError, StrategyRegistryService> =>\n\tEffect.gen(function* () {\n\t\tif (parts.funding.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\tconst registry = yield* StrategyRegistryService;\n\t\tconst applied: AppliedFundingEntry[] = [];\n\n\t\tfor (const entry of parts.funding) {\n\t\t\tif (entry.amount <= 0n) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tyield* setCurrentPluginPhase(`checking ${entry.coin} funding`);\n\t\t\tconst existingBalance = yield* readExistingBalance(parts.balanceReader, {\n\t\t\t\towner: parts.address,\n\t\t\t\tcoinType: entry.fullCoinType,\n\t\t\t});\n\t\t\tif (existingBalance !== null && existingBalance >= entry.amount) {\n\t\t\t\tapplied.push({ ...entry, outcome: 'already-satisfied' });\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Resolve the capability key from the projected coin type.\n\t\t\t//\n\t\t\t// SUI (`0x2::sui::SUI`) → reuse the faucet-request key so the\n\t\t\t// SUI auto-registered strategy fields the request (this\n\t\t\t// matches the default-funding pass and keeps the registry\n\t\t\t// surface uniform). The faucet contract takes\n\t\t\t// `{address, amount}` only (it never sees the resolved\n\t\t\t// account handle) — kept as its own helper so the typing is\n\t\t\t// honest at the dispatch site.\n\t\t\t//\n\t\t\t// Everything else → `coinType:<fullCoinType>` so user-defined\n\t\t\t// Coin plugins (and Walrus's exchange strategy keyed by\n\t\t\t// `coinType:<WAL fullCoinType>`) can contribute strategies\n\t\t\t// declaratively. These satisfy `AccountFundingStrategy` and\n\t\t\t// receive the resolved account handle in the request.\n\t\t\tconst isSui = entry.fullCoinType === SUI_FULL_COIN_TYPE;\n\t\t\tconst coinKey = `coinType:${entry.fullCoinType}` as const;\n\t\t\tconst key = isSui ? (`faucet:request:${parts.chainId}` as const) : coinKey;\n\n\t\t\tconst wrapCrossCuttingFailure = (cause: unknown): AccountAcquireError =>\n\t\t\t\tfundingFailureError({\n\t\t\t\t\tphase: 'fund-cross-cutting',\n\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\tvariant: parts.variant,\n\t\t\t\t\tkey,\n\t\t\t\t\tamount: entry.amount,\n\t\t\t\t\tcause,\n\t\t\t\t});\n\n\t\t\tlet request: Effect.Effect<void, AccountAcquireError>;\n\t\t\tlet usesAccountSigner = false;\n\t\t\tif (isSui) {\n\t\t\t\t// FaucetStrategy lookup — request shape is `{address, amount}`.\n\t\t\t\t// Architecture-distilled: explicit SUI entries are the\n\t\t\t\t// normal gas faucet path, so missing strategy is\n\t\t\t\t// actionable and loud (no silent drop).\n\t\t\t\tconst strategy = yield* chainKeyedStrategyFor<FaucetStrategy>(\n\t\t\t\t\tFAUCET_CAPABILITY_KEY_PREFIX,\n\t\t\t\t\tparts.chainId,\n\t\t\t\t).pipe(\n\t\t\t\t\tEffect.catchTag('StrategyNotFoundError', (err) =>\n\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\taccountAcquireError({\n\t\t\t\t\t\t\t\tphase: 'fund-cross-cutting',\n\t\t\t\t\t\t\t\taccountName: parts.accountName,\n\t\t\t\t\t\t\t\tvariant: parts.variant,\n\t\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\t\t`Account '${parts.accountName}': no SUI funding strategy registered ` +\n\t\t\t\t\t\t\t\t\t`for chain '${parts.chainId}'. Registered keys: [${err.registeredKeys.join(', ')}].`,\n\t\t\t\t\t\t\t\tcause: err,\n\t\t\t\t\t\t\t\thint: 'Ensure a sui() plugin with a faucet-bearing mode (local/live-testnet/live-devnet) is in the stack.',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\trequest = strategy\n\t\t\t\t\t.request({ address: parts.address, amount: entry.amount })\n\t\t\t\t\t.pipe(Effect.mapError(wrapCrossCuttingFailure));\n\t\t\t} else {\n\t\t\t\t// AccountFundingStrategy lookup — request shape is\n\t\t\t\t// `{address, amount, account}`. Architecture-distilled:\n\t\t\t\t// optional-faucet-is-noop for arbitrary coins — missing\n\t\t\t\t// registration short-circuits silently rather than\n\t\t\t\t// failing the acquire.\n\t\t\t\tconst strategy = yield* registry\n\t\t\t\t\t.get<typeof coinKey, AccountFundingStrategy>(coinKey)\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\tEffect.catchTag('StrategyNotFoundError', () =>\n\t\t\t\t\t\t\tEffect.succeed(null as AccountFundingStrategy | null),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\tif (strategy === null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tusesAccountSigner = strategy.usesAccountSigner === true;\n\t\t\t\trequest = strategy\n\t\t\t\t\t.request({ address: parts.address, amount: entry.amount, account: parts.account })\n\t\t\t\t\t.pipe(Effect.mapError(wrapCrossCuttingFailure));\n\t\t\t}\n\n\t\t\tyield* setCurrentPluginPhase(`funding ${entry.coin}`);\n\t\t\tyield* usesAccountSigner\n\t\t\t\t? request\n\t\t\t\t: withAddressLease(parts.broker, parts.accountName, parts.address, request);\n\t\t\tyield* setCurrentPluginPhase(`waiting for ${entry.coin} funding settlement`);\n\t\t\tyield* waitForBalanceAtLeast({\n\t\t\t\tbalanceReader: parts.balanceReader,\n\t\t\t\taccountName: parts.accountName,\n\t\t\t\tvariant: parts.variant,\n\t\t\t\tphase: 'fund-cross-cutting',\n\t\t\t\towner: parts.address,\n\t\t\t\tcoinType: entry.fullCoinType,\n\t\t\t\tcoinLabel: entry.coin,\n\t\t\t\tamount: entry.amount,\n\t\t\t});\n\t\t\tapplied.push({ ...entry, outcome: 'funded' });\n\t\t}\n\n\t\treturn applied;\n\t});\n\nconst readExistingBalance = (\n\tbalanceReader: FundingBalanceReader,\n\targs: {\n\t\treadonly owner: string;\n\t\treadonly coinType: string;\n\t},\n): Effect.Effect<bigint | null> => balanceReader.readBalance(args);\n\nconst waitForBalanceAtLeast = (parts: {\n\treadonly balanceReader: FundingBalanceReader;\n\treadonly accountName: string;\n\treadonly variant: AccountVariantKind;\n\treadonly phase: 'fund-default' | 'fund-cross-cutting';\n\treadonly owner: string;\n\treadonly coinType: string;\n\treadonly coinLabel: string;\n\treadonly amount: bigint;\n}): Effect.Effect<void, AccountAcquireError> => {\n\tconst reader = parts.balanceReader;\n\t// Test-only opt-out — the `NULL_BALANCE_READER` sentinel explicitly\n\t// declares \"this caller doesn't model the read/poll loop\". Production\n\t// readers never set `skipFinalityWait`, so the wait stays load-bearing\n\t// on real wire calls.\n\tif (skipsFinalityWait(reader)) {\n\t\treturn Effect.void;\n\t}\n\treturn Effect.gen(function* () {\n\t\tconst read = readExistingBalance(reader, {\n\t\t\towner: parts.owner,\n\t\t\tcoinType: parts.coinType,\n\t\t});\n\t\tconst lastBalance = yield* read.pipe(\n\t\t\tEffect.repeat({\n\t\t\t\tschedule: makeBoundedSpacedSchedule(\n\t\t\t\t\tBALANCE_POLL_PROFILE.intervalMs,\n\t\t\t\t\tBALANCE_POLL_PROFILE.timeoutMs,\n\t\t\t\t),\n\t\t\t\tuntil: (balance) => balance !== null && balance >= parts.amount,\n\t\t\t}),\n\t\t);\n\t\tif (lastBalance !== null && lastBalance >= parts.amount) {\n\t\t\treturn;\n\t\t}\n\t\treturn yield* Effect.fail(\n\t\t\taccountAcquireError({\n\t\t\t\tphase: parts.phase,\n\t\t\t\taccountName: parts.accountName,\n\t\t\t\tvariant: parts.variant,\n\t\t\t\tmessage:\n\t\t\t\t\t`Account '${parts.accountName}': funding for ${parts.coinLabel} was accepted ` +\n\t\t\t\t\t`but balance did not reach ${parts.amount} before the settlement timeout ` +\n\t\t\t\t\t`(last=${lastBalance === null ? '<unavailable>' : lastBalance}).`,\n\t\t\t\thint:\n\t\t\t\t\t'The faucet or funding strategy returned before the funded coin became spendable. ' +\n\t\t\t\t\t'Check the funding strategy finality gate and Sui RPC health.',\n\t\t\t}),\n\t\t);\n\t});\n};\n"],"mappings":"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"}
@@ -1,14 +1,9 @@
1
- import { CodegenableDecl } from "../../contracts/codegenable.mjs";
2
- import { ProjectionDecl } from "../../contracts/projection.mjs";
3
- import { SnapshotableDecl } from "../../contracts/snapshotable.mjs";
4
- import { StrategyContributorDecl } from "../../contracts/strategy-contributor.mjs";
5
1
  import { AnyResourceRef, Plugin, ResourceRef } from "../../substrate/plugin.mjs";
6
- import { SuiClient } from "../sui/mode/shared.mjs";
7
2
  import { SuiOptions } from "../sui/mode/spec.mjs";
3
+ import { SuiClient } from "../sui/mode/shared.mjs";
8
4
  import { AccountAcquireError, AccountAcquirePhase, AccountError, AccountSignError, AccountSignPhase, AccountVariantKind } from "./errors.mjs";
9
- import { AccountOptions, AccountValue, SignAndExecuteResult, TxResult } from "./service.mjs";
5
+ import { AccountOptions, AccountSignerInput, AccountValue, SignAndExecuteResult, TxResult } from "./service.mjs";
10
6
  import { AccountFunding, AccountFundingCoinValue, AccountFundingEntry, AccountFundingRequest, AccountFundingResult, AccountFundingStrategy, AppliedFunding, AppliedFundingEntry, AppliedFundingOutcome, CoinMember, CrossCuttingFundingEntry, CrossCuttingFundingProvider, DEFAULT_EPHEMERAL_FUND_MIST, ProjectedFunding, ProjectedFundingEntry, SUI_FULL_COIN_TYPE, SuiFundingEntry } from "./funding.mjs";
11
- import { AccountRegistryEntry, AccountRegistryFunding } from "./registry.mjs";
12
7
  import { AccountBindings } from "./codegen.mjs";
13
8
  import { ResolvedKeypair, SignatureScheme } from "./keypair.mjs";
14
9
  import { SyntheticImpersonationSigner } from "./variants/impersonate.mjs";
@@ -46,7 +41,7 @@ type FundingEntryProviderDependencies<Entry> = Entry extends {
46
41
  type FundingProviderDependencies<Entries extends readonly unknown[]> = Entries extends readonly [infer Head, ...infer Tail] ? readonly [...FundingEntryProviderDependencies<Head>, ...FundingProviderDependencies<Tail>] : readonly [];
47
42
  declare const account: <const N extends string, const Funding extends AccountFunding = readonly []>(name: N, opts?: AccountOptions<Funding>) => Plugin<`account/${N}`, AccountValue, readonly [ResourceRef<"sui", SuiClient & {
48
43
  readonly mode: SuiOptions["mode"];
49
- }>, ...FundingCoinDependencies<Funding>, ...FundingProviderDependencies<Funding>], readonly [SnapshotableDecl, CodegenableDecl<`account/${N}`>, StrategyContributorDecl<`account:${N}`, AccountRegistryEntry>, ProjectionDecl]>;
44
+ }>, ...FundingCoinDependencies<Funding>, ...FundingProviderDependencies<Funding>]>;
50
45
  //#endregion
51
46
  export { AccountResourceId, account };
52
47
  //# sourceMappingURL=index.d.mts.map
@@ -1,19 +1,17 @@
1
- import { definePlugin, resource } from "../../substrate/plugin.mjs";
1
+ import { definePlugin, resource, staticInputIdentity } from "../../substrate/plugin.mjs";
2
2
  import "../../api/define-plugin.mjs";
3
3
  import { IdentityContext, StackPathsService } from "../../substrate/runtime/paths.mjs";
4
- import { pluginErrorContributions } from "../../api/plugin-errors.mjs";
5
- import { SuiSpans } from "../sui/spans.mjs";
4
+ import { PluginContext } from "../../substrate/plugin-ctx.mjs";
5
+ import { SuiLogAttr } from "../sui/log-attrs.mjs";
6
6
  import { suiResource } from "../sui/index.mjs";
7
- import { AccountSpans } from "./spans.mjs";
8
7
  import { makeAccountCodegen } from "./codegen.mjs";
9
- import { ACCOUNT_ERROR_TAGS, accountAcquireError } from "./errors.mjs";
10
- import { SUI_FULL_COIN_TYPE } from "./funding.mjs";
8
+ import { accountAcquireError } from "./errors.mjs";
9
+ import { DEFAULT_EPHEMERAL_FUND_MIST, SUI_FULL_COIN_TYPE } from "./funding.mjs";
11
10
  import { makeAccountProjectionContribution, makeAccountRegistryContribution } from "./registry.mjs";
12
11
  import { makeAccountSnapshotable } from "./snapshot.mjs";
13
12
  import { acquireAccount, assertAccountName } from "./service.mjs";
14
13
  import { Effect } from "effect";
15
14
  //#region src/plugins/account/index.ts
16
- const accountErrorContributions = pluginErrorContributions(ACCOUNT_ERROR_TAGS);
17
15
  const accountResource = (name) => resource(`account/${name}`);
18
16
  const isCoinFundingEntry = (entry) => typeof entry === "object" && entry.coin !== "sui";
19
17
  const fundingProviders = (provider) => {
@@ -44,6 +42,47 @@ const fundingAmountToBigInt = (amount, accountName) => {
44
42
  return Effect.succeed(BigInt(amount));
45
43
  };
46
44
  const coinLabelFor = (coin) => coin.symbol ?? coin.fullCoinType.split("::").at(-1) ?? coin.fullCoinType;
45
+ const inputAmount = (amount) => amount.toString();
46
+ const inputFundingProviderIds = (provider) => fundingProviders(provider).map((ref) => ref.id).sort((a, b) => a.localeCompare(b));
47
+ const inputFundingIdentityFor = (entry) => {
48
+ if (entry.coin === "sui") return {
49
+ coin: "sui",
50
+ amountMist: inputAmount(entry.amount)
51
+ };
52
+ const via = inputFundingProviderIds(entry.via);
53
+ return {
54
+ coin: entry.coin.id,
55
+ amountMist: entry.amount.toString(),
56
+ ...via.length === 0 ? {} : { via }
57
+ };
58
+ };
59
+ const accountFundingInputIdentity = (opts, fundingEntries) => {
60
+ const explicit = fundingEntries.map(inputFundingIdentityFor);
61
+ if (opts.kind === "ephemeral" && opts.funding === void 0) return [{
62
+ coin: "sui",
63
+ amountMist: DEFAULT_EPHEMERAL_FUND_MIST.toString()
64
+ }, ...explicit];
65
+ return explicit;
66
+ };
67
+ const accountVariantInputIdentity = (opts) => {
68
+ switch (opts.kind) {
69
+ case "ephemeral": return { kind: "ephemeral" };
70
+ case "impersonate": return {
71
+ kind: "impersonate",
72
+ address: opts.address
73
+ };
74
+ case "signer": return {
75
+ kind: "signer",
76
+ address: opts.addressOverride ?? opts.signer.toSuiAddress()
77
+ };
78
+ }
79
+ };
80
+ const accountInputIdentity = (opts, fundingEntries) => ({
81
+ plugin: "account",
82
+ name: opts.name,
83
+ variant: accountVariantInputIdentity(opts),
84
+ funding: accountFundingInputIdentity(opts, fundingEntries)
85
+ });
47
86
  const account = (name, opts) => {
48
87
  assertAccountName(name);
49
88
  const opts2 = opts === void 0 ? {
@@ -68,7 +107,9 @@ const account = (name, opts) => {
68
107
  dependsOn: dependencies,
69
108
  role: "task",
70
109
  section: "account",
110
+ inputIdentity: staticInputIdentity(accountInputIdentity(opts2, fundingEntryList)),
71
111
  start: (deps) => Effect.gen(function* () {
112
+ const ctx = yield* PluginContext;
72
113
  const [sui, ...resolvedDeps] = deps;
73
114
  const resolvedCoinValues = resolvedDeps.slice(0, coinFundingEntries.length);
74
115
  const identity = yield* IdentityContext;
@@ -94,10 +135,10 @@ const account = (name, opts) => {
94
135
  });
95
136
  }
96
137
  const projectedFunding = projectedFundingMutable;
97
- return yield* acquireAccount(opts2, {
138
+ const resolved = yield* acquireAccount(opts2, {
98
139
  sui: {
99
140
  mode: sui.mode,
100
- chain: sui.chain,
141
+ chainId: sui.chainId,
101
142
  sdk: sui.sdk,
102
143
  fork: sui.fork
103
144
  },
@@ -105,16 +146,13 @@ const account = (name, opts) => {
105
146
  app: identity.app,
106
147
  stack: identity.stack,
107
148
  emitAutoPromotionEvent: () => Effect.logWarning("account funding auto-promoted for fork mode").pipe(Effect.annotateLogs({
108
- [AccountSpans.name]: name,
109
- [AccountSpans.fundingFrom]: "faucet",
110
- [AccountSpans.fundingTo]: "pay-from-seed-via-impersonate",
111
- [SuiSpans.mode]: "fork"
149
+ "account.name": name,
150
+ "account.funding.from": "faucet",
151
+ "account.funding.to": "pay-from-seed-via-impersonate",
152
+ [SuiLogAttr.mode]: "fork"
112
153
  })),
113
154
  projectedFunding
114
155
  });
115
- }),
116
- errorContributions: accountErrorContributions,
117
- capabilities: ({ value: resolved, runtime: acquireCtx2 }) => {
118
156
  const realEntry = {
119
157
  name,
120
158
  address: resolved.address,
@@ -122,27 +160,25 @@ const account = (name, opts) => {
122
160
  source: resolved.source,
123
161
  funding: fundingProjectionForResult(resolved.funding)
124
162
  };
125
- const bindings = {
163
+ ctx.snapshotExtra(makeAccountSnapshotable({
164
+ accountName: name,
165
+ variant: opts2.kind,
166
+ app: identity.app,
167
+ stack: identity.stack
168
+ }));
169
+ ctx.codegen(makeAccountCodegen({
126
170
  name,
127
- address: resolved.address,
128
- scheme: resolved.scheme,
129
- source: resolved.source
130
- };
131
- return [
132
- makeAccountSnapshotable({
133
- accountName: name,
134
- variant: opts2.kind,
135
- app: acquireCtx2.identity.app,
136
- stack: acquireCtx2.identity.stack
137
- }),
138
- makeAccountCodegen({
171
+ resolved: {
139
172
  name,
140
- resolved: bindings
141
- }),
142
- makeAccountRegistryContribution(realEntry),
143
- makeAccountProjectionContribution(realEntry)
144
- ];
145
- }
173
+ address: resolved.address,
174
+ scheme: resolved.scheme,
175
+ source: resolved.source
176
+ }
177
+ }));
178
+ ctx.provides(makeAccountRegistryContribution(realEntry));
179
+ ctx.publish(makeAccountProjectionContribution(realEntry));
180
+ return resolved;
181
+ })
146
182
  });
147
183
  };
148
184
  /** @internal — exported only for the projection regression test
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/account/index.ts"],"sourcesContent":["// Account plugin — barrel + `account(name, opts?)` factory.\n//\n// Architecture (12-account.md): Account is the named-identity layer\n// for devstack. It acquires a keypair (or impersonation slot), funds\n// it (default + cross-cutting), registers `{name, address}`, and\n// publishes a per-account resolved value via a unique resource id.\n//\n// User-facing factory shape:\n//\n// account('alice') // default ephemeral\n// account('alice', { kind: 'ephemeral', funding: [{ coin: 'sui', amount: 5_000_000_000n }] })\n// account('alice', { kind: 'keystore', path: '~/.sui/keystore', aliasOrAddress: 'alice' })\n// account('alice', { kind: 'env', key: 'ALICE_PRIVATE_KEY' })\n// account('alice', { kind: 'inline', privateKey: 'suiprivkey1...' })\n// account('alice', { kind: 'signer', signer: hardwareWallet })\n// account('alice', { kind: 'impersonate', address: '0xabc...' })\n//\n// **Bare-form default**: `account('alice')` is shorthand for\n//\n// { kind: 'ephemeral' } plus default SUI funding.\n//\n// Distilled-doc invariant (12-account.md \"Make the bare-form auto-\n// promotion to fork-impersonate funding discoverable\"): on fork-\n// runtime Sui, the default-funding pass internally promotes from\n// \"faucet POST\" to \"pay-from-seed-via-impersonate\" because no\n// faucet exists on a fork. The promotion is LOUD by default — we\n// emit a `log.appended` event the first time the promotion fires\n// (see `funding.ts`).\n//\n// The plugin emits THREE capability decls + an error-tag contribution:\n//\n// 1. Snapshotable — secret-material subtree (ephemeral only).\n// 2. Codegenable — `account-map` bindings (name → address).\n// 3. StrategyContributor — per-stack `account:<name>` registry entry.\n//\n// Plus `errorContributions: [{ errorTags: ACCOUNT_ERROR_TAGS }]` —\n// harvested by the supervisor into the FormatterRegistry so the\n// cascade formatter renders account-tagged failures with the right\n// taxonomy header.\n\nimport { Effect } from 'effect';\n\nimport { definePlugin, resource, type AnyResourceRef } from '../../api/define-plugin.ts';\nimport { pluginErrorContributions } from '../../api/plugin-errors.ts';\nimport { IdentityContext, StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { suiResource, SuiSpans } from '../sui/index.ts';\n\nimport { AccountSpans } from './spans.ts';\n\nimport { makeAccountCodegen, type AccountBindings } from './codegen.ts';\nimport { ACCOUNT_ERROR_TAGS, accountAcquireError, type AccountAcquireError } from './errors.ts';\nimport {\n\tSUI_FULL_COIN_TYPE,\n\ttype AccountFunding,\n\ttype AccountFundingEntry,\n\ttype AccountFundingResult,\n\ttype CrossCuttingFundingEntry,\n\ttype CrossCuttingFundingProvider,\n\ttype CoinMember,\n\ttype ProjectedFundingEntry,\n} from './funding.ts';\nimport {\n\tmakeAccountProjectionContribution,\n\tmakeAccountRegistryContribution,\n\ttype AccountRegistryEntry,\n\ttype AccountRegistryFunding,\n} from './registry.ts';\nimport { makeAccountSnapshotable } from './snapshot.ts';\nimport {\n\tacquireAccount,\n\tassertAccountName,\n\ttype AccountAcquireContext,\n\ttype AccountOptions,\n\ttype ResolvedAccountOptions,\n\ttype AccountValue,\n} from './service.ts';\n\nconst accountErrorContributions = pluginErrorContributions(ACCOUNT_ERROR_TAGS);\n\n// ---------------------------------------------------------------------------\n// Resource construction\n// ---------------------------------------------------------------------------\n\n/** Per-account-instance resource. The substrate's resource id MUST be unique\n * across the stack — we encode the account name as a literal-typed\n * template literal so the compiler catches duplicate-name composes\n * at the `defineDevstack` call site.\n *\n * Distilled-doc invariant: resource id flows into the on-disk path, the\n * manifest key, container labels, and generated TypeScript exports —\n * the identifier-safe name validation (in `service.ts`) protects\n * those call sites. */\nexport type AccountResourceId<Name extends string> = `account/${Name}`;\n\nconst accountResource = <Name extends string>(name: Name) =>\n\tresource<AccountResourceId<Name>, AccountValue>(`account/${name}` as AccountResourceId<Name>);\n\n// ---------------------------------------------------------------------------\n// User-facing factory\n// ---------------------------------------------------------------------------\n\n/** Construct the account plugin instance.\n *\n * Variants — typed at the API boundary via the discriminated\n * `AccountOptions` union. The factory's second arg is OPTIONAL —\n * omitting it yields the bare-form default (ephemeral + default\n * funding). Passing a non-matching `kind:` is a compile error\n * thanks to the union's discriminator.\n *\n * Distilled-doc invariant: the name is validated at the FACTORY\n * boundary (not just at acquire time) so a typo surfaces\n * immediately, not at runtime. */\ntype FundingCoinDependencies<Entries extends readonly unknown[]> = Entries extends readonly [\n\tinfer Head,\n\t...infer Tail,\n]\n\t? Head extends { readonly coin: infer Coin }\n\t\t? Coin extends CoinMember\n\t\t\t? readonly [Coin, ...FundingCoinDependencies<Tail>]\n\t\t\t: FundingCoinDependencies<Tail>\n\t\t: FundingCoinDependencies<Tail>\n\t: readonly [];\n\ntype FundingProviderDependenciesFor<Provider> = Provider extends readonly AnyResourceRef[]\n\t? Provider\n\t: Provider extends AnyResourceRef\n\t\t? readonly [Provider]\n\t\t: readonly [];\n\ntype FundingEntryProviderDependencies<Entry> = Entry extends { readonly coin: CoinMember }\n\t? 'via' extends keyof Entry\n\t\t? Entry extends { readonly via: infer Provider }\n\t\t\t? FundingProviderDependenciesFor<Provider>\n\t\t\t: readonly []\n\t\t: readonly []\n\t: readonly [];\n\ntype FundingProviderDependencies<Entries extends readonly unknown[]> = Entries extends readonly [\n\tinfer Head,\n\t...infer Tail,\n]\n\t? readonly [...FundingEntryProviderDependencies<Head>, ...FundingProviderDependencies<Tail>]\n\t: readonly [];\n\ntype AccountDependencyMembers<Funding extends AccountFunding> = readonly [\n\ttypeof suiResource,\n\t...FundingCoinDependencies<Funding>,\n\t...FundingProviderDependencies<Funding>,\n];\n\nconst isCoinFundingEntry = (entry: AccountFundingEntry): entry is CrossCuttingFundingEntry =>\n\ttypeof entry === 'object' && entry.coin !== 'sui';\n\nconst fundingProviders = (\n\tprovider: CrossCuttingFundingProvider | undefined,\n): ReadonlyArray<AnyResourceRef> => {\n\tif (provider === undefined) return [];\n\treturn Array.isArray(provider)\n\t\t? (provider as ReadonlyArray<AnyResourceRef>)\n\t\t: [provider as AnyResourceRef];\n};\n\n/** Validate a SUI funding amount and project it to bigint MIST.\n * Returns a typed-error Effect so a bad amount surfaces as\n * `AccountAcquireError(phase: 'validate-funding')` on the failure\n * channel — NOT a synchronous throw lifted to a defect when called\n * from inside the acquire body's `Effect.gen`. */\nconst fundingAmountToBigInt = (\n\tamount: number | bigint,\n\taccountName: string,\n): Effect.Effect<bigint, AccountAcquireError> => {\n\tif (typeof amount === 'bigint') {\n\t\tif (amount < 0n) {\n\t\t\treturn Effect.fail(\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'validate-funding',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant: 'ephemeral',\n\t\t\t\t\tmessage: `Account '${accountName}': SUI funding amount must be a non-negative integer in MIST (got ${amount}).`,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn Effect.succeed(amount);\n\t}\n\tif (!Number.isSafeInteger(amount) || amount < 0) {\n\t\treturn Effect.fail(\n\t\t\taccountAcquireError({\n\t\t\t\tphase: 'validate-funding',\n\t\t\t\taccountName,\n\t\t\t\tvariant: 'ephemeral',\n\t\t\t\tmessage: `Account '${accountName}': SUI funding amount must be a non-negative safe integer in MIST (got ${amount}).`,\n\t\t\t}),\n\t\t);\n\t}\n\treturn Effect.succeed(BigInt(amount));\n};\n\nconst coinLabelFor = (coin: { readonly fullCoinType: string; readonly symbol?: string }): string =>\n\tcoin.symbol ?? coin.fullCoinType.split('::').at(-1) ?? coin.fullCoinType;\n\nexport const account = <const N extends string, const Funding extends AccountFunding = readonly []>(\n\tname: N,\n\topts?: AccountOptions<Funding>,\n) => {\n\tassertAccountName(name);\n\n\t// Normalize bare-form to ephemeral default. The user-facing\n\t// `AccountOptions` union does not include \"kind absent\" — we\n\t// inject the default here so the rest of the body sees a\n\t// fully-discriminated value.\n\tconst opts2: ResolvedAccountOptions =\n\t\topts === undefined\n\t\t\t? { kind: 'ephemeral', name }\n\t\t\t: ({ ...opts, name } as ResolvedAccountOptions);\n\n\tconst accountRef = accountResource(name);\n\n\t// Pull the funding resource tuple out of opts (may be undefined for\n\t// the bare form / variants without funding). The tuple preserves\n\t// plugin-valued refs when the caller passed coin plugins, so\n\t// recursive stack composition can include those publishers.\n\tconst fundingEntries = (opts?.funding ?? []) as unknown as Funding;\n\tconst fundingEntryList = fundingEntries as AccountFunding;\n\tconst coinFundingEntries = fundingEntryList.filter(isCoinFundingEntry);\n\tconst fundingMembers = coinFundingEntries.map((e) => e.coin);\n\tconst strategyProviderMembers = coinFundingEntries.flatMap((entry) =>\n\t\tfundingProviders(entry.via),\n\t);\n\tconst dependencies = [\n\t\tsuiResource,\n\t\t...fundingMembers,\n\t\t...strategyProviderMembers,\n\t] as unknown as AccountDependencyMembers<Funding>;\n\n\treturn definePlugin({\n\t\tid: accountRef.id,\n\t\tdependsOn: dependencies,\n\t\t// Account is a value-producer (no long-lived server / container);\n\t\t// tasks acquire their value, publish contributions, then reach\n\t\t// `done`.\n\t\trole: 'task',\n\t\tsection: 'account',\n\t\tstart: (deps) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst [sui, ...resolvedDeps] = deps;\n\t\t\t\tconst resolvedCoinValues = resolvedDeps.slice(\n\t\t\t\t\t0,\n\t\t\t\t\tcoinFundingEntries.length,\n\t\t\t\t) as ReadonlyArray<{\n\t\t\t\t\treadonly fullCoinType: string;\n\t\t\t\t\treadonly symbol?: string;\n\t\t\t\t}>;\n\t\t\t\t// Identity + on-disk runtime root come from the\n\t\t\t\t// supervisor-provided substrate context.\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst paths = yield* StackPathsService;\n\n\t\t\t\t// Project each funding dependency value to a\n\t\t\t\t// `{fullCoinType, amount}` projection. Dependency order\n\t\t\t\t// mirrors `fundingEntries`, after the hard Sui upstream.\n\t\t\t\t// SUI amount validation lives on the failure channel so a\n\t\t\t\t// negative / non-integer amount surfaces as a typed\n\t\t\t\t// `AccountAcquireError(phase: 'validate-funding')` instead\n\t\t\t\t// of a defect (the old sync-throw lifted to a defect when\n\t\t\t\t// run inside this `Effect.gen`).\n\t\t\t\tlet coinIndex = 0;\n\t\t\t\tconst projectedFundingMutable: ProjectedFundingEntry[] = [];\n\t\t\t\tfor (const entry of fundingEntryList) {\n\t\t\t\t\tif (entry.coin === 'sui') {\n\t\t\t\t\t\tconst amount = yield* fundingAmountToBigInt(entry.amount, name);\n\t\t\t\t\t\tprojectedFundingMutable.push({\n\t\t\t\t\t\t\tcoin: 'SUI',\n\t\t\t\t\t\t\tfullCoinType: SUI_FULL_COIN_TYPE,\n\t\t\t\t\t\t\tamount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst resolvedCoin = resolvedCoinValues[coinIndex]!;\n\t\t\t\t\tcoinIndex += 1;\n\t\t\t\t\tprojectedFundingMutable.push({\n\t\t\t\t\t\tcoin: coinLabelFor(resolvedCoin),\n\t\t\t\t\t\tfullCoinType: resolvedCoin.fullCoinType,\n\t\t\t\t\t\tamount: entry.amount,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst projectedFunding: ReadonlyArray<ProjectedFundingEntry> = projectedFundingMutable;\n\n\t\t\t\tconst acquireCtx: AccountAcquireContext = {\n\t\t\t\t\tsui: {\n\t\t\t\t\t\tmode: sui.mode,\n\t\t\t\t\t\tchain: sui.chain,\n\t\t\t\t\t\tsdk: sui.sdk,\n\t\t\t\t\t\tfork: sui.fork,\n\t\t\t\t\t},\n\t\t\t\t\truntimeRoot: paths.stackRoot,\n\t\t\t\t\tapp: identity.app,\n\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\temitAutoPromotionEvent: () =>\n\t\t\t\t\t\tEffect.logWarning('account funding auto-promoted for fork mode').pipe(\n\t\t\t\t\t\t\tEffect.annotateLogs({\n\t\t\t\t\t\t\t\t[AccountSpans.name]: name,\n\t\t\t\t\t\t\t\t[AccountSpans.fundingFrom]: 'faucet',\n\t\t\t\t\t\t\t\t[AccountSpans.fundingTo]: 'pay-from-seed-via-impersonate',\n\t\t\t\t\t\t\t\t[SuiSpans.mode]: 'fork',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\tprojectedFunding,\n\t\t\t\t};\n\t\t\t\treturn yield* acquireAccount(opts2, acquireCtx);\n\t\t\t}),\n\t\t// Dynamic capability factory — receives the resolved\n\t\t// `AccountValue` + acquire context AFTER `acquire` succeeds.\n\t\t// Lets snapshot + codegen + registry decls reference the\n\t\t// REAL address (and identity app/stack) — the static form\n\t\t// would force placeholder values for fields only known at\n\t\t// acquire time.\n\t\terrorContributions: accountErrorContributions,\n\t\tcapabilities: ({ value: resolved, runtime: acquireCtx2 }) => {\n\t\t\tconst realEntry: AccountRegistryEntry = {\n\t\t\t\tname,\n\t\t\t\taddress: resolved.address,\n\t\t\t\tscheme: resolved.scheme,\n\t\t\t\tsource: resolved.source,\n\t\t\t\tfunding: fundingProjectionForResult(resolved.funding),\n\t\t\t};\n\t\t\tconst bindings: AccountBindings = {\n\t\t\t\tname,\n\t\t\t\taddress: resolved.address,\n\t\t\t\tscheme: resolved.scheme,\n\t\t\t\tsource: resolved.source,\n\t\t\t};\n\t\t\tconst snapshot = makeAccountSnapshotable({\n\t\t\t\taccountName: name,\n\t\t\t\tvariant: opts2.kind,\n\t\t\t\tapp: acquireCtx2.identity.app,\n\t\t\t\tstack: acquireCtx2.identity.stack,\n\t\t\t});\n\t\t\tconst codegen = makeAccountCodegen<N>({ name, resolved: bindings });\n\t\t\tconst registry = makeAccountRegistryContribution<N>(\n\t\t\t\trealEntry as AccountRegistryEntry & { readonly name: N },\n\t\t\t);\n\t\t\tconst projection = makeAccountProjectionContribution<N>(\n\t\t\t\trealEntry as AccountRegistryEntry & { readonly name: N },\n\t\t\t);\n\t\t\treturn [snapshot, codegen, registry, projection] as const;\n\t\t},\n\t});\n};\n\n/** @internal — exported only for the projection regression test\n * (`test/plugins/account/funding-projection.test.ts`). Projects the runtime\n * `AccountFundingResult` (requested + applied) into the registry's\n * per-row funded/already-satisfied/skipped status. */\nexport const fundingProjectionForResult = (\n\tfunding: AccountFundingResult,\n): AccountRegistryFunding => {\n\tif (funding.requested.length === 0) {\n\t\treturn { status: 'skipped', balanceMist: null, requestedMist: null, entries: [] };\n\t}\n\n\t// Positional outcome consume so the projection can distinguish a\n\t// real faucet call (`funded`) from the pre-existing-balance\n\t// short-circuit (`already-satisfied`). `applied` is an\n\t// order-preserving SUBSEQUENCE of `requested`:\n\t// `applyCrossCuttingFunding` (and the default-funding pass) iterate\n\t// `requested` in order and only push a processed entry onto\n\t// `applied`, dropping zero-amount and no-strategy entries. So we\n\t// walk a cursor through `applied` and adopt its outcome for the\n\t// matching requested row by (fullCoinType, amount) — a keyed Map\n\t// would collapse duplicate (coin, amount) entries and mislabel the\n\t// genuinely-funded first row as `already-satisfied`. An entry the\n\t// funding pass never reached (zero-amount, or absent from `applied`)\n\t// does not match the cursor and projects as `skipped` without\n\t// advancing it.\n\tlet appliedCursor = 0;\n\tconst entries = funding.requested.map((entry) => {\n\t\tconst candidate = funding.applied[appliedCursor];\n\t\tconst matches =\n\t\t\tcandidate !== undefined &&\n\t\t\tcandidate.fullCoinType === entry.fullCoinType &&\n\t\t\tcandidate.amount === entry.amount;\n\t\tconst outcome = matches ? candidate.outcome : undefined;\n\t\tif (matches) {\n\t\t\tappliedCursor += 1;\n\t\t}\n\t\treturn {\n\t\t\tcoin: entry.coin,\n\t\t\tfullCoinType: entry.fullCoinType,\n\t\t\tamount: entry.amount.toString(),\n\t\t\tstatus:\n\t\t\t\toutcome === 'funded'\n\t\t\t\t\t? ('funded' as const)\n\t\t\t\t\t: outcome === 'already-satisfied'\n\t\t\t\t\t\t? ('already-satisfied' as const)\n\t\t\t\t\t\t: ('skipped' as const),\n\t\t};\n\t});\n\tconst requestedMist =\n\t\tfunding.requested\n\t\t\t.find((entry) => entry.fullCoinType === SUI_FULL_COIN_TYPE)\n\t\t\t?.amount.toString() ?? null;\n\tconst settledCount = entries.filter(\n\t\t(entry) => entry.status === 'funded' || entry.status === 'already-satisfied',\n\t).length;\n\treturn {\n\t\t// `funded` here means \"every requested entry is satisfied\" —\n\t\t// either the faucet succeeded or the pre-existing balance\n\t\t// already covered it. `unknown` covers the mixed partial-success\n\t\t// case so consumers can distinguish from \"nothing ran at all\".\n\t\tstatus: settledCount === entries.length ? 'funded' : settledCount === 0 ? 'skipped' : 'unknown',\n\t\tbalanceMist: null,\n\t\trequestedMist,\n\t\tentries,\n\t};\n};\n\n// ---------------------------------------------------------------------------\n// Re-exports for advanced callers (Coin, Wallet, Package)\n// ---------------------------------------------------------------------------\n\nexport type {\n\tAccountOptions,\n\tResolvedAccountOptions,\n\tAccountValue,\n\tSignAndExecuteResult,\n\tTxResult,\n} from './service.ts';\nexport type {\n\tAccountError,\n\tAccountAcquireError,\n\tAccountAcquirePhase,\n\tAccountSignError,\n\tAccountSignPhase,\n\tAccountVariantKind,\n} from './errors.ts';\nexport { ACCOUNT_ERROR_TAGS } from './errors.ts';\nexport type {\n\tAccountFunding,\n\tAccountFundingEntry,\n\tAccountFundingCoinValue,\n\tAccountFundingResult,\n\tAccountFundingRequest,\n\tAccountFundingStrategy,\n\tAppliedFunding,\n\tAppliedFundingEntry,\n\tAppliedFundingOutcome,\n\tCoinMember,\n\tCrossCuttingFundingEntry,\n\tCrossCuttingFundingProvider,\n\tFundEphemeralDefaultOutcome,\n\tProjectedFunding,\n\tProjectedFundingEntry,\n\tSuiFundingEntry,\n} from './funding.ts';\nexport { DEFAULT_EPHEMERAL_FUND_MIST, SUI_FULL_COIN_TYPE } from './funding.ts';\nexport type { AccountBindings } from './codegen.ts';\nexport type {\n\tAccountRegistryEntry,\n\tAccountRegistryFunding,\n\tAccountRegistryKey,\n} from './registry.ts';\nexport { accountRegistryKey } from './registry.ts';\nexport type { SyntheticImpersonationSigner } from './variants/impersonate.ts';\nexport type { SignatureScheme, ResolvedKeypair } from './keypair.ts';\nexport { AccountSpans } from './spans.ts';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/account/index.ts"],"sourcesContent":["// Account plugin — barrel + `account(name, opts?)` factory.\n//\n// Architecture (12-account.md): Account is the named-identity layer\n// for devstack. It acquires a keypair (or impersonation slot), funds\n// it (default + cross-cutting), registers `{name, address}`, and\n// publishes a per-account resolved value via a unique resource id.\n//\n// User-facing factory shape — THREE variants:\n//\n// account('alice') // default ephemeral\n// account('alice', { kind: 'ephemeral', funding: [{ coin: 'sui', amount: 5_000_000_000n }] })\n// account('alice', { kind: 'signer', signer: hardwareWallet })\n// account('alice', { kind: 'impersonate', address: '0xabc...' }) // fork-mode only\n//\n// The `signer` variant is the single bring-your-own door. Pass any\n// `@mysten/sui/cryptography` `Signer` or `Keypair`. Loading a secret\n// from an env var or an inline literal is expressed by constructing\n// the keypair yourself and passing it as the signer:\n//\n// account('ci', { kind: 'signer', signer: Ed25519Keypair.fromSecretKey(process.env.ALICE_PRIVATE_KEY!) })\n// account('demo', { kind: 'signer', signer: Ed25519Keypair.fromSecretKey('suiprivkey1...') })\n//\n// **Bare-form default**: `account('alice')` is shorthand for\n//\n// { kind: 'ephemeral' } plus default SUI funding.\n//\n// Distilled-doc invariant (12-account.md \"Make the bare-form auto-\n// promotion to fork-impersonate funding discoverable\"): on fork-\n// runtime Sui, the default-funding pass internally promotes from\n// \"faucet POST\" to \"pay-from-seed-via-impersonate\" because no\n// faucet exists on a fork. The promotion is LOUD by default — we\n// emit a `log.appended` event the first time the promotion fires\n// (see `funding.ts`).\n//\n// During `start`, the plugin emits (via the typed `ctx.*` verbs) plus an\n// error-tag contribution:\n//\n// 1. `ctx.snapshotExtra` — secret-material subtree (ephemeral only).\n// 2. `ctx.codegen` — `account-map` bindings (name → address).\n// 3. `ctx.provides` — per-stack `account:<name>` registry entry.\n\nimport { Effect } from 'effect';\n\nimport {\n\tdefinePlugin,\n\tresource,\n\tstaticInputIdentity,\n\ttype AnyResourceRef,\n} from '../../api/define-plugin.ts';\nimport { PluginContext } from '../../substrate/plugin-ctx.ts';\nimport { IdentityContext, StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { suiResource, SuiLogAttr } from '../sui/index.ts';\n\nimport { makeAccountCodegen } from './codegen.ts';\nimport { accountAcquireError, type AccountAcquireError } from './errors.ts';\nimport {\n\tDEFAULT_EPHEMERAL_FUND_MIST,\n\tSUI_FULL_COIN_TYPE,\n\ttype AccountFunding,\n\ttype AccountFundingEntry,\n\ttype AccountFundingResult,\n\ttype CrossCuttingFundingEntry,\n\ttype CrossCuttingFundingProvider,\n\ttype CoinMember,\n\ttype ProjectedFundingEntry,\n} from './funding.ts';\nimport {\n\tmakeAccountProjectionContribution,\n\tmakeAccountRegistryContribution,\n\ttype AccountRegistryEntry,\n\ttype AccountRegistryFunding,\n} from './registry.ts';\nimport { makeAccountSnapshotable } from './snapshot.ts';\nimport {\n\tacquireAccount,\n\tassertAccountName,\n\ttype AccountAcquireContext,\n\ttype AccountOptions,\n\ttype ResolvedAccountOptions,\n\ttype AccountValue,\n} from './service.ts';\n\n// ---------------------------------------------------------------------------\n// Resource construction\n// ---------------------------------------------------------------------------\n\n/** Per-account-instance resource. The substrate's resource id MUST be unique\n * across the stack — we encode the account name as a literal-typed\n * template literal so the compiler catches duplicate-name composes\n * at the `defineDevstack` call site.\n *\n * Distilled-doc invariant: resource id flows into the on-disk path, the\n * manifest key, container labels, and generated TypeScript exports —\n * the identifier-safe name validation (in `service.ts`) protects\n * those call sites. */\nexport type AccountResourceId<Name extends string> = `account/${Name}`;\n\nconst accountResource = <Name extends string>(name: Name) =>\n\tresource<AccountResourceId<Name>, AccountValue>(`account/${name}` as AccountResourceId<Name>);\n\n// ---------------------------------------------------------------------------\n// User-facing factory\n// ---------------------------------------------------------------------------\n\n/** Construct the account plugin instance.\n *\n * Variants — typed at the API boundary via the discriminated\n * `AccountOptions` union. The factory's second arg is OPTIONAL —\n * omitting it yields the bare-form default (ephemeral + default\n * funding). Passing a non-matching `kind:` is a compile error\n * thanks to the union's discriminator.\n *\n * Distilled-doc invariant: the name is validated at the FACTORY\n * boundary (not just at acquire time) so a typo surfaces\n * immediately, not at runtime. */\ntype FundingCoinDependencies<Entries extends readonly unknown[]> = Entries extends readonly [\n\tinfer Head,\n\t...infer Tail,\n]\n\t? Head extends { readonly coin: infer Coin }\n\t\t? Coin extends CoinMember\n\t\t\t? readonly [Coin, ...FundingCoinDependencies<Tail>]\n\t\t\t: FundingCoinDependencies<Tail>\n\t\t: FundingCoinDependencies<Tail>\n\t: readonly [];\n\ntype FundingProviderDependenciesFor<Provider> = Provider extends readonly AnyResourceRef[]\n\t? Provider\n\t: Provider extends AnyResourceRef\n\t\t? readonly [Provider]\n\t\t: readonly [];\n\ntype FundingEntryProviderDependencies<Entry> = Entry extends { readonly coin: CoinMember }\n\t? 'via' extends keyof Entry\n\t\t? Entry extends { readonly via: infer Provider }\n\t\t\t? FundingProviderDependenciesFor<Provider>\n\t\t\t: readonly []\n\t\t: readonly []\n\t: readonly [];\n\ntype FundingProviderDependencies<Entries extends readonly unknown[]> = Entries extends readonly [\n\tinfer Head,\n\t...infer Tail,\n]\n\t? readonly [...FundingEntryProviderDependencies<Head>, ...FundingProviderDependencies<Tail>]\n\t: readonly [];\n\ntype AccountDependencyMembers<Funding extends AccountFunding> = readonly [\n\ttypeof suiResource,\n\t...FundingCoinDependencies<Funding>,\n\t...FundingProviderDependencies<Funding>,\n];\n\nconst isCoinFundingEntry = (entry: AccountFundingEntry): entry is CrossCuttingFundingEntry =>\n\ttypeof entry === 'object' && entry.coin !== 'sui';\n\nconst fundingProviders = (\n\tprovider: CrossCuttingFundingProvider | undefined,\n): ReadonlyArray<AnyResourceRef> => {\n\tif (provider === undefined) return [];\n\treturn Array.isArray(provider)\n\t\t? (provider as ReadonlyArray<AnyResourceRef>)\n\t\t: [provider as AnyResourceRef];\n};\n\n/** Validate a SUI funding amount and project it to bigint MIST.\n * Returns a typed-error Effect so a bad amount surfaces as\n * `AccountAcquireError(phase: 'validate-funding')` on the failure\n * channel — NOT a synchronous throw lifted to a defect when called\n * from inside the acquire body's `Effect.gen`. */\nconst fundingAmountToBigInt = (\n\tamount: number | bigint,\n\taccountName: string,\n): Effect.Effect<bigint, AccountAcquireError> => {\n\tif (typeof amount === 'bigint') {\n\t\tif (amount < 0n) {\n\t\t\treturn Effect.fail(\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'validate-funding',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant: 'ephemeral',\n\t\t\t\t\tmessage: `Account '${accountName}': SUI funding amount must be a non-negative integer in MIST (got ${amount}).`,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn Effect.succeed(amount);\n\t}\n\tif (!Number.isSafeInteger(amount) || amount < 0) {\n\t\treturn Effect.fail(\n\t\t\taccountAcquireError({\n\t\t\t\tphase: 'validate-funding',\n\t\t\t\taccountName,\n\t\t\t\tvariant: 'ephemeral',\n\t\t\t\tmessage: `Account '${accountName}': SUI funding amount must be a non-negative safe integer in MIST (got ${amount}).`,\n\t\t\t}),\n\t\t);\n\t}\n\treturn Effect.succeed(BigInt(amount));\n};\n\nconst coinLabelFor = (coin: { readonly fullCoinType: string; readonly symbol?: string }): string =>\n\tcoin.symbol ?? coin.fullCoinType.split('::').at(-1) ?? coin.fullCoinType;\n\nconst inputAmount = (amount: number | bigint): string => amount.toString();\n\nconst inputFundingProviderIds = (\n\tprovider: CrossCuttingFundingProvider | undefined,\n): ReadonlyArray<string> =>\n\tfundingProviders(provider)\n\t\t.map((ref) => ref.id)\n\t\t.sort((a, b) => a.localeCompare(b));\n\nconst inputFundingIdentityFor = (entry: AccountFundingEntry): unknown => {\n\tif (entry.coin === 'sui') {\n\t\treturn { coin: 'sui', amountMist: inputAmount(entry.amount) };\n\t}\n\tconst via = inputFundingProviderIds(entry.via);\n\treturn {\n\t\tcoin: entry.coin.id,\n\t\tamountMist: entry.amount.toString(),\n\t\t...(via.length === 0 ? {} : { via }),\n\t};\n};\n\nconst accountFundingInputIdentity = (\n\topts: ResolvedAccountOptions,\n\tfundingEntries: AccountFunding,\n): ReadonlyArray<unknown> => {\n\tconst explicit = fundingEntries.map(inputFundingIdentityFor);\n\tif (opts.kind === 'ephemeral' && opts.funding === undefined) {\n\t\treturn [{ coin: 'sui', amountMist: DEFAULT_EPHEMERAL_FUND_MIST.toString() }, ...explicit];\n\t}\n\treturn explicit;\n};\n\nconst accountVariantInputIdentity = (opts: ResolvedAccountOptions): unknown => {\n\tswitch (opts.kind) {\n\t\tcase 'ephemeral':\n\t\t\treturn { kind: 'ephemeral' };\n\t\tcase 'impersonate':\n\t\t\treturn { kind: 'impersonate', address: opts.address };\n\t\tcase 'signer':\n\t\t\treturn {\n\t\t\t\tkind: 'signer',\n\t\t\t\taddress: opts.addressOverride ?? opts.signer.toSuiAddress(),\n\t\t\t};\n\t}\n};\n\nconst accountInputIdentity = (\n\topts: ResolvedAccountOptions,\n\tfundingEntries: AccountFunding,\n): unknown => ({\n\tplugin: 'account',\n\tname: opts.name,\n\tvariant: accountVariantInputIdentity(opts),\n\tfunding: accountFundingInputIdentity(opts, fundingEntries),\n});\n\n// ---------------------------------------------------------------------------\n// Capability emission — dynamic (POST-acquire). Receives the resolved\n// `AccountValue` + the identity so snapshot + codegen + registry + projection\n// decls reference the REAL address (and identity app/stack) — the static form\n// would force placeholder values for fields only known at acquire time.\n//\n// The account `start` emits its four contributions inline — snapshot →\n// codegen → registry → projection — directly via the typed `ctx` verbs,\n// AFTER resolving the value. The decl shapes + emit ORDER are load-bearing.\n// ---------------------------------------------------------------------------\n\nexport const account = <const N extends string, const Funding extends AccountFunding = readonly []>(\n\tname: N,\n\topts?: AccountOptions<Funding>,\n) => {\n\tassertAccountName(name);\n\n\t// Normalize bare-form to ephemeral default. The user-facing\n\t// `AccountOptions` union does not include \"kind absent\" — we\n\t// inject the default here so the rest of the body sees a\n\t// fully-discriminated value.\n\tconst opts2: ResolvedAccountOptions =\n\t\topts === undefined\n\t\t\t? { kind: 'ephemeral', name }\n\t\t\t: ({ ...opts, name } as ResolvedAccountOptions);\n\n\tconst accountRef = accountResource(name);\n\n\t// Pull the funding resource tuple out of opts (may be undefined for\n\t// the bare form / variants without funding). The tuple preserves\n\t// plugin-valued refs when the caller passed coin plugins, so\n\t// recursive stack composition can include those publishers.\n\tconst fundingEntries = (opts?.funding ?? []) as unknown as Funding;\n\tconst fundingEntryList = fundingEntries as AccountFunding;\n\tconst coinFundingEntries = fundingEntryList.filter(isCoinFundingEntry);\n\tconst fundingMembers = coinFundingEntries.map((e) => e.coin);\n\tconst strategyProviderMembers = coinFundingEntries.flatMap((entry) =>\n\t\tfundingProviders(entry.via),\n\t);\n\tconst dependencies = [\n\t\tsuiResource,\n\t\t...fundingMembers,\n\t\t...strategyProviderMembers,\n\t] as unknown as AccountDependencyMembers<Funding>;\n\n\treturn definePlugin({\n\t\tid: accountRef.id,\n\t\tdependsOn: dependencies,\n\t\t// Account is a value-producer (no long-lived server / container);\n\t\t// tasks acquire their value, publish contributions, then reach\n\t\t// `done`.\n\t\trole: 'task',\n\t\tsection: 'account',\n\t\tinputIdentity: staticInputIdentity(accountInputIdentity(opts2, fundingEntryList)),\n\t\t// `deps` auto-infers from the resolved `dependsOn`; `ctx` arrives\n\t\t// via the `PluginContext` service.\n\t\tstart: (deps) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst ctx = yield* PluginContext;\n\t\t\t\tconst [sui, ...resolvedDeps] = deps;\n\t\t\t\tconst resolvedCoinValues = resolvedDeps.slice(\n\t\t\t\t\t0,\n\t\t\t\t\tcoinFundingEntries.length,\n\t\t\t\t) as ReadonlyArray<{\n\t\t\t\t\treadonly fullCoinType: string;\n\t\t\t\t\treadonly symbol?: string;\n\t\t\t\t}>;\n\t\t\t\t// Identity + on-disk runtime root come from the\n\t\t\t\t// supervisor-provided substrate context.\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst paths = yield* StackPathsService;\n\n\t\t\t\t// Project each funding dependency value to a\n\t\t\t\t// `{fullCoinType, amount}` projection. Dependency order\n\t\t\t\t// mirrors `fundingEntries`, after the hard Sui upstream.\n\t\t\t\t// SUI amount validation lives on the failure channel so a\n\t\t\t\t// negative / non-integer amount surfaces as a typed\n\t\t\t\t// `AccountAcquireError(phase: 'validate-funding')` instead\n\t\t\t\t// of a defect (the old sync-throw lifted to a defect when\n\t\t\t\t// run inside this `Effect.gen`).\n\t\t\t\tlet coinIndex = 0;\n\t\t\t\tconst projectedFundingMutable: ProjectedFundingEntry[] = [];\n\t\t\t\tfor (const entry of fundingEntryList) {\n\t\t\t\t\tif (entry.coin === 'sui') {\n\t\t\t\t\t\tconst amount = yield* fundingAmountToBigInt(entry.amount, name);\n\t\t\t\t\t\tprojectedFundingMutable.push({\n\t\t\t\t\t\t\tcoin: 'SUI',\n\t\t\t\t\t\t\tfullCoinType: SUI_FULL_COIN_TYPE,\n\t\t\t\t\t\t\tamount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst resolvedCoin = resolvedCoinValues[coinIndex]!;\n\t\t\t\t\tcoinIndex += 1;\n\t\t\t\t\tprojectedFundingMutable.push({\n\t\t\t\t\t\tcoin: coinLabelFor(resolvedCoin),\n\t\t\t\t\t\tfullCoinType: resolvedCoin.fullCoinType,\n\t\t\t\t\t\tamount: entry.amount,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst projectedFunding: ReadonlyArray<ProjectedFundingEntry> = projectedFundingMutable;\n\n\t\t\t\tconst acquireCtx: AccountAcquireContext = {\n\t\t\t\t\tsui: {\n\t\t\t\t\t\tmode: sui.mode,\n\t\t\t\t\t\tchainId: sui.chainId,\n\t\t\t\t\t\tsdk: sui.sdk,\n\t\t\t\t\t\tfork: sui.fork,\n\t\t\t\t\t},\n\t\t\t\t\truntimeRoot: paths.stackRoot,\n\t\t\t\t\tapp: identity.app,\n\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\temitAutoPromotionEvent: () =>\n\t\t\t\t\t\tEffect.logWarning('account funding auto-promoted for fork mode').pipe(\n\t\t\t\t\t\t\tEffect.annotateLogs({\n\t\t\t\t\t\t\t\t'account.name': name,\n\t\t\t\t\t\t\t\t'account.funding.from': 'faucet',\n\t\t\t\t\t\t\t\t'account.funding.to': 'pay-from-seed-via-impersonate',\n\t\t\t\t\t\t\t\t[SuiLogAttr.mode]: 'fork',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\tprojectedFunding,\n\t\t\t\t};\n\t\t\t\tconst resolved = yield* acquireAccount(opts2, acquireCtx);\n\n\t\t\t\t// Emit the resolved account's contributions inline, in order:\n\t\t\t\t// snapshot → codegen → registry → projection. `resolved` is the\n\t\t\t\t// just-acquired `AccountValue`; `identity` (from\n\t\t\t\t// `IdentityContext`) supplies the snapshot's pre-restore guard\n\t\t\t\t// app/stack; the variant kind is `opts2.kind`. The registry +\n\t\t\t\t// projection decls share one `realEntry` so the registered\n\t\t\t\t// strategy and the published event agree byte-for-byte.\n\t\t\t\tconst realEntry: AccountRegistryEntry = {\n\t\t\t\t\tname,\n\t\t\t\t\taddress: resolved.address,\n\t\t\t\t\tscheme: resolved.scheme,\n\t\t\t\t\tsource: resolved.source,\n\t\t\t\t\tfunding: fundingProjectionForResult(resolved.funding),\n\t\t\t\t};\n\t\t\t\tctx.snapshotExtra(\n\t\t\t\t\tmakeAccountSnapshotable({\n\t\t\t\t\t\taccountName: name,\n\t\t\t\t\t\tvariant: opts2.kind,\n\t\t\t\t\t\tapp: identity.app,\n\t\t\t\t\t\tstack: identity.stack,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tctx.codegen(\n\t\t\t\t\tmakeAccountCodegen<N>({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tresolved: {\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\taddress: resolved.address,\n\t\t\t\t\t\t\tscheme: resolved.scheme,\n\t\t\t\t\t\t\tsource: resolved.source,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tctx.provides(\n\t\t\t\t\tmakeAccountRegistryContribution<N>(\n\t\t\t\t\t\trealEntry as AccountRegistryEntry & { readonly name: N },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tctx.publish(\n\t\t\t\t\tmakeAccountProjectionContribution<N>(\n\t\t\t\t\t\trealEntry as AccountRegistryEntry & { readonly name: N },\n\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\treturn resolved;\n\t\t\t}),\n\t});\n};\n\n/** @internal — exported only for the projection regression test\n * (`test/plugins/account/funding-projection.test.ts`). Projects the runtime\n * `AccountFundingResult` (requested + applied) into the registry's\n * per-row funded/already-satisfied/skipped status. */\nexport const fundingProjectionForResult = (\n\tfunding: AccountFundingResult,\n): AccountRegistryFunding => {\n\tif (funding.requested.length === 0) {\n\t\treturn { status: 'skipped', balanceMist: null, requestedMist: null, entries: [] };\n\t}\n\n\t// Positional outcome consume so the projection can distinguish a\n\t// real faucet call (`funded`) from the pre-existing-balance\n\t// short-circuit (`already-satisfied`). `applied` is an\n\t// order-preserving SUBSEQUENCE of `requested`:\n\t// `applyCrossCuttingFunding` (and the default-funding pass) iterate\n\t// `requested` in order and only push a processed entry onto\n\t// `applied`, dropping zero-amount and no-strategy entries. So we\n\t// walk a cursor through `applied` and adopt its outcome for the\n\t// matching requested row by (fullCoinType, amount) — a keyed Map\n\t// would collapse duplicate (coin, amount) entries and mislabel the\n\t// genuinely-funded first row as `already-satisfied`. An entry the\n\t// funding pass never reached (zero-amount, or absent from `applied`)\n\t// does not match the cursor and projects as `skipped` without\n\t// advancing it.\n\tlet appliedCursor = 0;\n\tconst entries = funding.requested.map((entry) => {\n\t\tconst candidate = funding.applied[appliedCursor];\n\t\tconst matches =\n\t\t\tcandidate !== undefined &&\n\t\t\tcandidate.fullCoinType === entry.fullCoinType &&\n\t\t\tcandidate.amount === entry.amount;\n\t\tconst outcome = matches ? candidate.outcome : undefined;\n\t\tif (matches) {\n\t\t\tappliedCursor += 1;\n\t\t}\n\t\treturn {\n\t\t\tcoin: entry.coin,\n\t\t\tfullCoinType: entry.fullCoinType,\n\t\t\tamount: entry.amount.toString(),\n\t\t\tstatus:\n\t\t\t\toutcome === 'funded'\n\t\t\t\t\t? ('funded' as const)\n\t\t\t\t\t: outcome === 'already-satisfied'\n\t\t\t\t\t\t? ('already-satisfied' as const)\n\t\t\t\t\t\t: ('skipped' as const),\n\t\t};\n\t});\n\tconst requestedMist =\n\t\tfunding.requested\n\t\t\t.find((entry) => entry.fullCoinType === SUI_FULL_COIN_TYPE)\n\t\t\t?.amount.toString() ?? null;\n\tconst settledCount = entries.filter(\n\t\t(entry) => entry.status === 'funded' || entry.status === 'already-satisfied',\n\t).length;\n\treturn {\n\t\t// `funded` here means \"every requested entry is satisfied\" —\n\t\t// either the faucet succeeded or the pre-existing balance\n\t\t// already covered it. `unknown` covers the mixed partial-success\n\t\t// case so consumers can distinguish from \"nothing ran at all\".\n\t\tstatus: settledCount === entries.length ? 'funded' : settledCount === 0 ? 'skipped' : 'unknown',\n\t\tbalanceMist: null,\n\t\trequestedMist,\n\t\tentries,\n\t};\n};\n\n// ---------------------------------------------------------------------------\n// Re-exports for advanced callers (Coin, Wallet, Package)\n// ---------------------------------------------------------------------------\n\nexport type {\n\tAccountOptions,\n\tAccountSignerInput,\n\tResolvedAccountOptions,\n\tAccountValue,\n\tSignAndExecuteResult,\n\tTxResult,\n} from './service.ts';\nexport type {\n\tAccountError,\n\tAccountAcquireError,\n\tAccountAcquirePhase,\n\tAccountSignError,\n\tAccountSignPhase,\n\tAccountVariantKind,\n} from './errors.ts';\nexport type {\n\tAccountFunding,\n\tAccountFundingEntry,\n\tAccountFundingCoinValue,\n\tAccountFundingResult,\n\tAccountFundingRequest,\n\tAccountFundingStrategy,\n\tAppliedFunding,\n\tAppliedFundingEntry,\n\tAppliedFundingOutcome,\n\tCoinMember,\n\tCrossCuttingFundingEntry,\n\tCrossCuttingFundingProvider,\n\tFundEphemeralDefaultOutcome,\n\tProjectedFunding,\n\tProjectedFundingEntry,\n\tSuiFundingEntry,\n} from './funding.ts';\nexport { DEFAULT_EPHEMERAL_FUND_MIST, SUI_FULL_COIN_TYPE } from './funding.ts';\nexport type { AccountBindings } from './codegen.ts';\nexport type {\n\tAccountRegistryEntry,\n\tAccountRegistryFunding,\n\tAccountRegistryKey,\n} from './registry.ts';\nexport { accountRegistryKey } from './registry.ts';\nexport type { SyntheticImpersonationSigner } from './variants/impersonate.ts';\nexport type { SignatureScheme, ResolvedKeypair } from './keypair.ts';\n"],"mappings":"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"}
@@ -17,14 +17,15 @@ interface ResolvedKeypair {
17
17
  readonly address: string;
18
18
  readonly scheme: SignatureScheme;
19
19
  readonly publicKey: Uint8Array;
20
- /** Opaque signer handle — typed loosely here because the four
21
- * real variants (ed25519/secp256k1/secp256r1 + bring-your-own
22
- * Signer) share no narrow TS type beyond `Signer`. The wallet /
23
- * sign-and-execute capability narrows downstream. */
20
+ /** Opaque signer handle — typed loosely here because the real
21
+ * variants (a generated/recovered Ed25519 keypair + a
22
+ * bring-your-own `Signer`) share no narrow TS type beyond
23
+ * `Signer`. The wallet / sign-and-execute capability narrows
24
+ * downstream. */
24
25
  readonly signer: unknown;
25
- /** Bech32-encoded secret. Only present for ephemeral / inline /
26
- * env / keystore variants — `null` for `signer` (we never ask
27
- * for it) and `impersonate` (no secret exists). */
26
+ /** Bech32-encoded secret. Only present for the `ephemeral` variant
27
+ * (the persisted generated key) — `null` for `signer` (we never
28
+ * ask for it) and `impersonate` (no secret exists). */
28
29
  readonly bech32Secret: string | null;
29
30
  }
30
31
  //#endregion
@@ -23,8 +23,9 @@ const normalizeScheme = (raw, accountName, variant) => {
23
23
  * `ephemeral` variant.
24
24
  *
25
25
  * Architecture-distilled invariant: schemes other than Ed25519
26
- * must be loaded via keystore/env/inline; we never generate
27
- * Secp256* keys from scratch. */
26
+ * must be brought in via the `signer` variant (pass a Secp256* or
27
+ * custom `Keypair`/`Signer`); we never generate Secp256* keys from
28
+ * scratch. */
28
29
  const generateEd25519Keypair = (accountName) => Effect.try({
29
30
  try: () => {
30
31
  return resolvedKeypairFromEd25519(Ed25519Keypair.generate());
@@ -38,7 +39,7 @@ const generateEd25519Keypair = (accountName) => Effect.try({
38
39
  })
39
40
  });
40
41
  /** Decode a bech32 `suiprivkey1...` string into a resolved keypair.
41
- * Used by the inline / env / keystore variants. */
42
+ * Used by the `ephemeral` variant to recover a persisted key. */
42
43
  const decodeBech32Secret = (bech32, accountName, variant) => Effect.gen(function* () {
43
44
  const parsed = yield* Effect.try({
44
45
  try: () => decodeSuiPrivateKey(bech32),
@@ -69,20 +70,6 @@ const decodeBech32Secret = (bech32, accountName, variant) => Effect.gen(function
69
70
  })
70
71
  });
71
72
  });
72
- /** Build a `ResolvedKeypair` view from a raw Ed25519 secret-key
73
- * byte array. Used by the inline-bytes path (`variants/inline.ts`
74
- * Uint8Array branch). */
75
- const resolvedKeypairFromEd25519Bytes = (secretKey, accountName, variant) => Effect.try({
76
- try: () => {
77
- return resolvedKeypairFromEd25519(Ed25519Keypair.fromSecretKey(secretKey));
78
- },
79
- catch: () => accountAcquireError({
80
- phase: "decode-inline",
81
- accountName,
82
- variant,
83
- message: `Account '${accountName}': Ed25519Keypair.fromSecretKey() rejected the supplied raw bytes.`
84
- })
85
- });
86
73
  const resolvedKeypairFromEd25519 = (kp) => ({
87
74
  address: kp.toSuiAddress(),
88
75
  scheme: "ed25519",
@@ -91,6 +78,6 @@ const resolvedKeypairFromEd25519 = (kp) => ({
91
78
  bech32Secret: kp.getSecretKey()
92
79
  });
93
80
  //#endregion
94
- export { decodeBech32Secret, generateEd25519Keypair, normalizeScheme, resolvedKeypairFromEd25519Bytes };
81
+ export { decodeBech32Secret, generateEd25519Keypair, normalizeScheme };
95
82
 
96
83
  //# sourceMappingURL=keypair.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"keypair.mjs","names":[],"sources":["../../../src/plugins/account/keypair.ts"],"sourcesContent":["// Account plugin — keypair generation + scheme normalization helpers.\n//\n// Distilled-doc finding (12-account.md \"Scheme normalization\"\n// invariant): scheme surfaced to consumers MUST be lowercased at the\n// account boundary. Mixed-case from the SDK leaks into manifest\n// serialization and on-chain Move type matching if not converted. We\n// pin the canonical lowercased union at this module's boundary and\n// every variant resolver dumps through `normalizeScheme` before\n// producing the resolved value.\n//\n// Distilled-doc opportunity (\"Co-locate the canonical Account-value\n// Schema with the canonical type\"): the canonical signature scheme\n// union lives here, NOT next to the factory, so future Schema sits\n// alongside the type.\n\nimport { Effect } from 'effect';\n\nimport { decodeSuiPrivateKey, encodeSuiPrivateKey } from '@mysten/sui/cryptography';\nimport { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\n\nimport {\n\taccountAcquireError,\n\ttype AccountAcquireError,\n\ttype AccountVariantKind,\n} from './errors.ts';\n\n/** Lowercased signature scheme — the canonical wire form. The SDK\n * occasionally hands us `'ED25519'` / `'Secp256k1'`; the boundary\n * conversion lives in `normalizeScheme`. */\nexport type SignatureScheme = 'ed25519' | 'secp256k1' | 'secp256r1';\n\n/** Resolved keypair shape — the variant resolvers all funnel into\n * this so the funding + register passes are variant-agnostic.\n *\n * Note: impersonation accounts do NOT produce a `Keypair`; they\n * produce a `SyntheticImpersonationSigner` (see\n * `variants/impersonate.ts`). The discriminator lives on the\n * resolved `AccountValue` (architecture: distilled doc opportunity\n * \"Tighten the resolved-account type\"). */\nexport interface ResolvedKeypair {\n\treadonly address: string;\n\treadonly scheme: SignatureScheme;\n\treadonly publicKey: Uint8Array;\n\t/** Opaque signer handle — typed loosely here because the four\n\t * real variants (ed25519/secp256k1/secp256r1 + bring-your-own\n\t * Signer) share no narrow TS type beyond `Signer`. The wallet /\n\t * sign-and-execute capability narrows downstream. */\n\treadonly signer: unknown;\n\t/** Bech32-encoded secret. Only present for ephemeral / inline /\n\t * env / keystore variants — `null` for `signer` (we never ask\n\t * for it) and `impersonate` (no secret exists). */\n\treadonly bech32Secret: string | null;\n}\n\n/** Normalize the SDK's mixed-case scheme to the lowercased wire form.\n * Unknown schemes surface as a typed acquisition error (distilled\n * doc: \"Unsupported signature scheme (multisig / zklogin / passkey)\n * — currently a raw throw; should be promoted to the typed-error\n * channel\"). */\nexport const normalizeScheme = (\n\traw: string,\n\taccountName: string,\n\tvariant: AccountVariantKind,\n): Effect.Effect<SignatureScheme, AccountAcquireError> => {\n\tconst lower = raw.toLowerCase();\n\tif (lower === 'ed25519' || lower === 'secp256k1' || lower === 'secp256r1') {\n\t\treturn Effect.succeed(lower);\n\t}\n\treturn Effect.fail(\n\t\taccountAcquireError({\n\t\t\tphase: 'unsupported-scheme',\n\t\t\taccountName,\n\t\t\tvariant,\n\t\t\tmessage: `Account '${accountName}': unsupported signature scheme '${raw}'. devstack supports ed25519, secp256k1, secp256r1.`,\n\t\t\thint: 'Multisig, zklogin, and passkey schemes are not yet supported via the Account plugin — bring your own Signer via {kind:\"signer\"}.',\n\t\t}),\n\t);\n};\n\n/** Generate a fresh Ed25519 keypair. The default for the\n * `ephemeral` variant.\n *\n * Architecture-distilled invariant: schemes other than Ed25519\n * must be loaded via keystore/env/inline; we never generate\n * Secp256* keys from scratch. */\nexport const generateEd25519Keypair = (\n\taccountName: string,\n): Effect.Effect<ResolvedKeypair, AccountAcquireError> =>\n\tEffect.try({\n\t\ttry: () => {\n\t\t\tconst kp = Ed25519Keypair.generate();\n\t\t\treturn resolvedKeypairFromEd25519(kp);\n\t\t},\n\t\tcatch: (cause): AccountAcquireError =>\n\t\t\taccountAcquireError({\n\t\t\t\tphase: 'generate-keypair',\n\t\t\t\taccountName,\n\t\t\t\tvariant: 'ephemeral',\n\t\t\t\tmessage: `Account '${accountName}': Ed25519Keypair.generate() threw.`,\n\t\t\t\tcause,\n\t\t\t}),\n\t});\n\n/** Decode a bech32 `suiprivkey1...` string into a resolved keypair.\n * Used by the inline / env / keystore variants. */\nexport const decodeBech32Secret = (\n\tbech32: string,\n\taccountName: string,\n\tvariant: AccountVariantKind,\n): Effect.Effect<ResolvedKeypair, AccountAcquireError> =>\n\tEffect.gen(function* () {\n\t\tconst parsed = yield* Effect.try({\n\t\t\ttry: () => decodeSuiPrivateKey(bech32),\n\t\t\t// Secret-leak guard: the thrown error from `decodeSuiPrivateKey`\n\t\t\t// can echo the rejected bech32 string back in its message, so we\n\t\t\t// deliberately DROP the raw `cause`. The typed `message` already\n\t\t\t// names the failure; a malformed-secret error carries no\n\t\t\t// actionable diagnostic beyond \"it was malformed\".\n\t\t\tcatch: (): AccountAcquireError =>\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'decode-inline',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant,\n\t\t\t\t\tmessage: `Account '${accountName}': decodeSuiPrivateKey() rejected the supplied bech32 secret.`,\n\t\t\t\t}),\n\t\t});\n\t\tconst scheme = yield* normalizeScheme(parsed.scheme, accountName, variant);\n\t\tif (scheme !== 'ed25519') {\n\t\t\t// Architecture-distilled: today we only construct Ed25519 here.\n\t\t\t// Secp256k1 / Secp256r1 paths land when the SDK's per-scheme\n\t\t\t// Keypair classes are wired in; the typed-error channel keeps\n\t\t\t// the failure actionable until then.\n\t\t\treturn yield* Effect.fail(\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'unsupported-scheme',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant,\n\t\t\t\t\tmessage: `Account '${accountName}': scheme '${scheme}' is not yet wired for the ${variant} variant.`,\n\t\t\t\t\thint: 'Wire the matching @mysten/sui/keypairs/<scheme> import next to the Ed25519 path.',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn yield* Effect.try({\n\t\t\ttry: () => {\n\t\t\t\tconst kp = Ed25519Keypair.fromSecretKey(parsed.secretKey);\n\t\t\t\treturn resolvedKeypairFromEd25519(kp);\n\t\t\t},\n\t\t\t// Secret-leak guard: `fromSecretKey` can echo the decoded\n\t\t\t// secret-key bytes in its error — DROP the raw `cause`.\n\t\t\tcatch: (): AccountAcquireError =>\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'decode-inline',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant,\n\t\t\t\t\tmessage: `Account '${accountName}': Ed25519Keypair.fromSecretKey() rejected the decoded secret.`,\n\t\t\t\t}),\n\t\t});\n\t});\n\n/** Build a `ResolvedKeypair` view from a raw Ed25519 secret-key\n * byte array. Used by the inline-bytes path (`variants/inline.ts`\n * Uint8Array branch). */\nexport const resolvedKeypairFromEd25519Bytes = (\n\tsecretKey: Uint8Array,\n\taccountName: string,\n\tvariant: AccountVariantKind,\n): Effect.Effect<ResolvedKeypair, AccountAcquireError> =>\n\tEffect.try({\n\t\ttry: () => {\n\t\t\tconst kp = Ed25519Keypair.fromSecretKey(secretKey);\n\t\t\treturn resolvedKeypairFromEd25519(kp);\n\t\t},\n\t\t// Secret-leak guard: `fromSecretKey` can echo the raw secret-key\n\t\t// bytes in its error — DROP the raw `cause`. (Mirrors the\n\t\t// bech32 path in `decodeBech32Secret`.)\n\t\tcatch: (): AccountAcquireError =>\n\t\t\taccountAcquireError({\n\t\t\t\tphase: 'decode-inline',\n\t\t\t\taccountName,\n\t\t\t\tvariant,\n\t\t\t\tmessage: `Account '${accountName}': Ed25519Keypair.fromSecretKey() rejected the supplied raw bytes.`,\n\t\t\t}),\n\t});\n\n/** Encode a 32-byte secret key as a bech32 `suiprivkey1...` string\n * for the canonical wire form. Re-exported because the\n * `variants/inline.ts` Uint8Array branch needs it. */\nexport const encodeEd25519Bech32 = (bytes: Uint8Array): string =>\n\tencodeSuiPrivateKey(bytes, 'ED25519');\n\nconst resolvedKeypairFromEd25519 = (kp: Ed25519Keypair): ResolvedKeypair => ({\n\taddress: kp.toSuiAddress(),\n\tscheme: 'ed25519',\n\tpublicKey: kp.getPublicKey().toRawBytes(),\n\tsigner: kp,\n\tbech32Secret: kp.getSecretKey(),\n});\n"],"mappings":";;;;;;;;;;AA2DA,MAAa,mBACZ,KACA,aACA,YACyD;CACzD,MAAM,QAAQ,IAAI,aAAa;AAC/B,KAAI,UAAU,aAAa,UAAU,eAAe,UAAU,YAC7D,QAAO,OAAO,QAAQ,MAAM;AAE7B,QAAO,OAAO,KACb,oBAAoB;EACnB,OAAO;EACP;EACA;EACA,SAAS,YAAY,YAAY,mCAAmC,IAAI;EACxE,MAAM;EACN,CAAC,CACF;;;;;;;;AASF,MAAa,0BACZ,gBAEA,OAAO,IAAI;CACV,WAAW;AAEV,SAAO,2BADI,eAAe,UACU,CAAC;;CAEtC,QAAQ,UACP,oBAAoB;EACnB,OAAO;EACP;EACA,SAAS;EACT,SAAS,YAAY,YAAY;EACjC;EACA,CAAC;CACH,CAAC;;;AAIH,MAAa,sBACZ,QACA,aACA,YAEA,OAAO,IAAI,aAAa;CACvB,MAAM,SAAS,OAAO,OAAO,IAAI;EAChC,WAAW,oBAAoB,OAAO;EAMtC,aACC,oBAAoB;GACnB,OAAO;GACP;GACA;GACA,SAAS,YAAY,YAAY;GACjC,CAAC;EACH,CAAC;CACF,MAAM,SAAS,OAAO,gBAAgB,OAAO,QAAQ,aAAa,QAAQ;AAC1E,KAAI,WAAW,UAKd,QAAO,OAAO,OAAO,KACpB,oBAAoB;EACnB,OAAO;EACP;EACA;EACA,SAAS,YAAY,YAAY,aAAa,OAAO,6BAA6B,QAAQ;EAC1F,MAAM;EACN,CAAC,CACF;AAEF,QAAO,OAAO,OAAO,IAAI;EACxB,WAAW;AAEV,UAAO,2BADI,eAAe,cAAc,OAAO,UACX,CAAC;;EAItC,aACC,oBAAoB;GACnB,OAAO;GACP;GACA;GACA,SAAS,YAAY,YAAY;GACjC,CAAC;EACH,CAAC;EACD;;;;AAKH,MAAa,mCACZ,WACA,aACA,YAEA,OAAO,IAAI;CACV,WAAW;AAEV,SAAO,2BADI,eAAe,cAAc,UACJ,CAAC;;CAKtC,aACC,oBAAoB;EACnB,OAAO;EACP;EACA;EACA,SAAS,YAAY,YAAY;EACjC,CAAC;CACH,CAAC;AAQH,MAAM,8BAA8B,QAAyC;CAC5E,SAAS,GAAG,cAAc;CAC1B,QAAQ;CACR,WAAW,GAAG,cAAc,CAAC,YAAY;CACzC,QAAQ;CACR,cAAc,GAAG,cAAc;CAC/B"}
1
+ {"version":3,"file":"keypair.mjs","names":[],"sources":["../../../src/plugins/account/keypair.ts"],"sourcesContent":["// Account plugin — keypair generation + scheme normalization helpers.\n//\n// Distilled-doc finding (12-account.md \"Scheme normalization\"\n// invariant): scheme surfaced to consumers MUST be lowercased at the\n// account boundary. Mixed-case from the SDK leaks into manifest\n// serialization and on-chain Move type matching if not converted. We\n// pin the canonical lowercased union at this module's boundary and\n// every variant resolver dumps through `normalizeScheme` before\n// producing the resolved value.\n//\n// Distilled-doc opportunity (\"Co-locate the canonical Account-value\n// Schema with the canonical type\"): the canonical signature scheme\n// union lives here, NOT next to the factory, so future Schema sits\n// alongside the type.\n\nimport { Effect } from 'effect';\n\nimport { decodeSuiPrivateKey } from '@mysten/sui/cryptography';\nimport { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\n\nimport {\n\taccountAcquireError,\n\ttype AccountAcquireError,\n\ttype AccountVariantKind,\n} from './errors.ts';\n\n/** Lowercased signature scheme — the canonical wire form. The SDK\n * occasionally hands us `'ED25519'` / `'Secp256k1'`; the boundary\n * conversion lives in `normalizeScheme`. */\nexport type SignatureScheme = 'ed25519' | 'secp256k1' | 'secp256r1';\n\n/** Resolved keypair shape — the variant resolvers all funnel into\n * this so the funding + register passes are variant-agnostic.\n *\n * Note: impersonation accounts do NOT produce a `Keypair`; they\n * produce a `SyntheticImpersonationSigner` (see\n * `variants/impersonate.ts`). The discriminator lives on the\n * resolved `AccountValue` (architecture: distilled doc opportunity\n * \"Tighten the resolved-account type\"). */\nexport interface ResolvedKeypair {\n\treadonly address: string;\n\treadonly scheme: SignatureScheme;\n\treadonly publicKey: Uint8Array;\n\t/** Opaque signer handle — typed loosely here because the real\n\t * variants (a generated/recovered Ed25519 keypair + a\n\t * bring-your-own `Signer`) share no narrow TS type beyond\n\t * `Signer`. The wallet / sign-and-execute capability narrows\n\t * downstream. */\n\treadonly signer: unknown;\n\t/** Bech32-encoded secret. Only present for the `ephemeral` variant\n\t * (the persisted generated key) — `null` for `signer` (we never\n\t * ask for it) and `impersonate` (no secret exists). */\n\treadonly bech32Secret: string | null;\n}\n\n/** Normalize the SDK's mixed-case scheme to the lowercased wire form.\n * Unknown schemes surface as a typed acquisition error (distilled\n * doc: \"Unsupported signature scheme (multisig / zklogin / passkey)\n * — currently a raw throw; should be promoted to the typed-error\n * channel\"). */\nexport const normalizeScheme = (\n\traw: string,\n\taccountName: string,\n\tvariant: AccountVariantKind,\n): Effect.Effect<SignatureScheme, AccountAcquireError> => {\n\tconst lower = raw.toLowerCase();\n\tif (lower === 'ed25519' || lower === 'secp256k1' || lower === 'secp256r1') {\n\t\treturn Effect.succeed(lower);\n\t}\n\treturn Effect.fail(\n\t\taccountAcquireError({\n\t\t\tphase: 'unsupported-scheme',\n\t\t\taccountName,\n\t\t\tvariant,\n\t\t\tmessage: `Account '${accountName}': unsupported signature scheme '${raw}'. devstack supports ed25519, secp256k1, secp256r1.`,\n\t\t\thint: 'Multisig, zklogin, and passkey schemes are not yet supported via the Account plugin — bring your own Signer via {kind:\"signer\"}.',\n\t\t}),\n\t);\n};\n\n/** Generate a fresh Ed25519 keypair. The default for the\n * `ephemeral` variant.\n *\n * Architecture-distilled invariant: schemes other than Ed25519\n * must be brought in via the `signer` variant (pass a Secp256* or\n * custom `Keypair`/`Signer`); we never generate Secp256* keys from\n * scratch. */\nexport const generateEd25519Keypair = (\n\taccountName: string,\n): Effect.Effect<ResolvedKeypair, AccountAcquireError> =>\n\tEffect.try({\n\t\ttry: () => {\n\t\t\tconst kp = Ed25519Keypair.generate();\n\t\t\treturn resolvedKeypairFromEd25519(kp);\n\t\t},\n\t\tcatch: (cause): AccountAcquireError =>\n\t\t\taccountAcquireError({\n\t\t\t\tphase: 'generate-keypair',\n\t\t\t\taccountName,\n\t\t\t\tvariant: 'ephemeral',\n\t\t\t\tmessage: `Account '${accountName}': Ed25519Keypair.generate() threw.`,\n\t\t\t\tcause,\n\t\t\t}),\n\t});\n\n/** Decode a bech32 `suiprivkey1...` string into a resolved keypair.\n * Used by the `ephemeral` variant to recover a persisted key. */\nexport const decodeBech32Secret = (\n\tbech32: string,\n\taccountName: string,\n\tvariant: AccountVariantKind,\n): Effect.Effect<ResolvedKeypair, AccountAcquireError> =>\n\tEffect.gen(function* () {\n\t\tconst parsed = yield* Effect.try({\n\t\t\ttry: () => decodeSuiPrivateKey(bech32),\n\t\t\t// Secret-leak guard: the thrown error from `decodeSuiPrivateKey`\n\t\t\t// can echo the rejected bech32 string back in its message, so we\n\t\t\t// deliberately DROP the raw `cause`. The typed `message` already\n\t\t\t// names the failure; a malformed-secret error carries no\n\t\t\t// actionable diagnostic beyond \"it was malformed\".\n\t\t\tcatch: (): AccountAcquireError =>\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'decode-inline',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant,\n\t\t\t\t\tmessage: `Account '${accountName}': decodeSuiPrivateKey() rejected the supplied bech32 secret.`,\n\t\t\t\t}),\n\t\t});\n\t\tconst scheme = yield* normalizeScheme(parsed.scheme, accountName, variant);\n\t\tif (scheme !== 'ed25519') {\n\t\t\t// Architecture-distilled: today we only construct Ed25519 here.\n\t\t\t// Secp256k1 / Secp256r1 paths land when the SDK's per-scheme\n\t\t\t// Keypair classes are wired in; the typed-error channel keeps\n\t\t\t// the failure actionable until then.\n\t\t\treturn yield* Effect.fail(\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'unsupported-scheme',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant,\n\t\t\t\t\tmessage: `Account '${accountName}': scheme '${scheme}' is not yet wired for the ${variant} variant.`,\n\t\t\t\t\thint: 'Wire the matching @mysten/sui/keypairs/<scheme> import next to the Ed25519 path.',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn yield* Effect.try({\n\t\t\ttry: () => {\n\t\t\t\tconst kp = Ed25519Keypair.fromSecretKey(parsed.secretKey);\n\t\t\t\treturn resolvedKeypairFromEd25519(kp);\n\t\t\t},\n\t\t\t// Secret-leak guard: `fromSecretKey` can echo the decoded\n\t\t\t// secret-key bytes in its error — DROP the raw `cause`.\n\t\t\tcatch: (): AccountAcquireError =>\n\t\t\t\taccountAcquireError({\n\t\t\t\t\tphase: 'decode-inline',\n\t\t\t\t\taccountName,\n\t\t\t\t\tvariant,\n\t\t\t\t\tmessage: `Account '${accountName}': Ed25519Keypair.fromSecretKey() rejected the decoded secret.`,\n\t\t\t\t}),\n\t\t});\n\t});\n\nconst resolvedKeypairFromEd25519 = (kp: Ed25519Keypair): ResolvedKeypair => ({\n\taddress: kp.toSuiAddress(),\n\tscheme: 'ed25519',\n\tpublicKey: kp.getPublicKey().toRawBytes(),\n\tsigner: kp,\n\tbech32Secret: kp.getSecretKey(),\n});\n"],"mappings":";;;;;;;;;;AA4DA,MAAa,mBACZ,KACA,aACA,YACyD;CACzD,MAAM,QAAQ,IAAI,YAAY;CAC9B,IAAI,UAAU,aAAa,UAAU,eAAe,UAAU,aAC7D,OAAO,OAAO,QAAQ,KAAK;CAE5B,OAAO,OAAO,KACb,oBAAoB;EACnB,OAAO;EACP;EACA;EACA,SAAS,YAAY,YAAY,mCAAmC,IAAI;EACxE,MAAM;CACP,CAAC,CACF;AACD;;;;;;;;AASA,MAAa,0BACZ,gBAEA,OAAO,IAAI;CACV,WAAW;EAEV,OAAO,2BADI,eAAe,SACS,CAAC;CACrC;CACA,QAAQ,UACP,oBAAoB;EACnB,OAAO;EACP;EACA,SAAS;EACT,SAAS,YAAY,YAAY;EACjC;CACD,CAAC;AACH,CAAC;;;AAIF,MAAa,sBACZ,QACA,aACA,YAEA,OAAO,IAAI,aAAa;CACvB,MAAM,SAAS,OAAO,OAAO,IAAI;EAChC,WAAW,oBAAoB,MAAM;EAMrC,aACC,oBAAoB;GACnB,OAAO;GACP;GACA;GACA,SAAS,YAAY,YAAY;EAClC,CAAC;CACH,CAAC;CACD,MAAM,SAAS,OAAO,gBAAgB,OAAO,QAAQ,aAAa,OAAO;CACzE,IAAI,WAAW,WAKd,OAAO,OAAO,OAAO,KACpB,oBAAoB;EACnB,OAAO;EACP;EACA;EACA,SAAS,YAAY,YAAY,aAAa,OAAO,6BAA6B,QAAQ;EAC1F,MAAM;CACP,CAAC,CACF;CAED,OAAO,OAAO,OAAO,IAAI;EACxB,WAAW;GAEV,OAAO,2BADI,eAAe,cAAc,OAAO,SACZ,CAAC;EACrC;EAGA,aACC,oBAAoB;GACnB,OAAO;GACP;GACA;GACA,SAAS,YAAY,YAAY;EAClC,CAAC;CACH,CAAC;AACF,CAAC;AAEF,MAAM,8BAA8B,QAAyC;CAC5E,SAAS,GAAG,aAAa;CACzB,QAAQ;CACR,WAAW,GAAG,aAAa,CAAC,CAAC,WAAW;CACxC,QAAQ;CACR,cAAc,GAAG,aAAa;AAC/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"lease.mjs","names":[],"sources":["../../../src/plugins/account/lease.ts"],"sourcesContent":["// Account plugin — per-address lease helper.\n//\n// Thin wrapper over `LeaseBrokerService.acquire(...)` that opens a\n// fresh scope per call and keys the lease as `account:<address>`.\n// Both the funding pass (`funding.ts`) and the resolved-value\n// sign/execute closures (`service.ts`) share this helper so the\n// per-key encoding lives in exactly one place.\n//\n// Substrate name-blindness: the broker treats the key as opaque —\n// the `account:` prefix is a plugin convention so the broker's\n// `holders()` snapshot is readable in the renderer / debug logs.\n\nimport { Effect } from 'effect';\n\nimport { leaseKey, type LeaseBroker } from '../../substrate/runtime/lease-broker/index.ts';\n\n/** Run `effect` while holding the per-address lease. Scope-bound\n * release: a fresh scope is opened per call, the broker installs\n * an uninterruptible finalizer, and the lease drops the moment\n * the inner Effect returns. Same-address concurrent callers\n * serialize via the broker's FIFO queue.\n *\n * Non-reentrant: nested calls for the SAME (broker, accountName,\n * address) tuple deadlock. The broker has no concept of\n * re-entrancy by design — per-address sequence-number semantics\n * require at-most-one in-flight. */\nexport const withAddressLease = <A, E, R>(\n\tbroker: LeaseBroker,\n\taccountName: string,\n\taddress: string,\n\teffect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> =>\n\tEffect.scoped(\n\t\tEffect.gen(function* () {\n\t\t\tyield* broker.acquire(leaseKey(`account:${address}`), accountName);\n\t\t\treturn yield* effect;\n\t\t}),\n\t);\n"],"mappings":";;;;;;;;;;;;;;AA0BA,MAAa,oBACZ,QACA,aACA,SACA,WAEA,OAAO,OACN,OAAO,IAAI,aAAa;AACvB,QAAO,OAAO,QAAQ,SAAS,WAAW,UAAU,EAAE,YAAY;AAClE,QAAO,OAAO;EACb,CACF"}
1
+ {"version":3,"file":"lease.mjs","names":[],"sources":["../../../src/plugins/account/lease.ts"],"sourcesContent":["// Account plugin — per-address lease helper.\n//\n// Thin wrapper over `LeaseBrokerService.acquire(...)` that opens a\n// fresh scope per call and keys the lease as `account:<address>`.\n// Both the funding pass (`funding.ts`) and the resolved-value\n// sign/execute closures (`service.ts`) share this helper so the\n// per-key encoding lives in exactly one place.\n//\n// Substrate name-blindness: the broker treats the key as opaque —\n// the `account:` prefix is a plugin convention so the broker's\n// `holders()` snapshot is readable in the renderer / debug logs.\n\nimport { Effect } from 'effect';\n\nimport { leaseKey, type LeaseBroker } from '../../substrate/runtime/lease-broker/index.ts';\n\n/** Run `effect` while holding the per-address lease. Scope-bound\n * release: a fresh scope is opened per call, the broker installs\n * an uninterruptible finalizer, and the lease drops the moment\n * the inner Effect returns. Same-address concurrent callers\n * serialize via the broker's FIFO queue.\n *\n * Non-reentrant: nested calls for the SAME (broker, accountName,\n * address) tuple deadlock. The broker has no concept of\n * re-entrancy by design — per-address sequence-number semantics\n * require at-most-one in-flight. */\nexport const withAddressLease = <A, E, R>(\n\tbroker: LeaseBroker,\n\taccountName: string,\n\taddress: string,\n\teffect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> =>\n\tEffect.scoped(\n\t\tEffect.gen(function* () {\n\t\t\tyield* broker.acquire(leaseKey(`account:${address}`), accountName);\n\t\t\treturn yield* effect;\n\t\t}),\n\t);\n"],"mappings":";;;;;;;;;;;;;;AA0BA,MAAa,oBACZ,QACA,aACA,SACA,WAEA,OAAO,OACN,OAAO,IAAI,aAAa;CACvB,OAAO,OAAO,QAAQ,SAAS,WAAW,SAAS,GAAG,WAAW;CACjE,OAAO,OAAO;AACf,CAAC,CACF"}