@mysten-incubation/devstack 0.1.0 → 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 +7 -4
  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 -31
  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":"index.mjs","names":["brandChainId"],"sources":["../../../../src/plugins/deepbook/pyth/index.ts"],"sourcesContent":["// Pyth — internal module under the DeepBook plugin.\n//\n// Local mode uses the DeepBook sandbox's mock Pyth package shape: publish a\n// local Move package with `pyth::create_price_feeds`, then create shared\n// `PriceInfoObject`s for the requested feeds. This is intentionally not a\n// top-level devstack plugin; DeepBook owns the oracle wiring it needs.\n\nimport { Effect, type Scope } from 'effect';\nimport { Transaction } from '@mysten/sui/transactions';\nimport { fromBase64, fromHex, toHex } from '@mysten/sui/utils';\n\nimport {\n\tartifactPublishError,\n\ttype ArtifactPublisher,\n} from '../../../primitives/artifact-publisher.ts';\nimport { acquireOnChainArtifact } from '../../internal/acquire-on-chain-artifact.ts';\nimport type { ResolvedSigner } from '../../../substrate/runtime/sui-execute/index.ts';\nimport {\n\texecuteSuiTx,\n\tformatExecutedFailure,\n} from '../../../substrate/runtime/sui-execute/index.ts';\nimport { probeManyLenient } from '../../../substrate/runtime/probes.ts';\nimport { chainId as brandChainId } from '../../../substrate/brand.ts';\nimport type { SuiSdkShim } from '../../sui/index.ts';\nimport { deepbookPluginError, type DeepbookPluginError } from '../errors.ts';\nimport { stableContentHash } from '../hash.ts';\nimport { DeepbookSpans } from '../spans.ts';\nimport type { PythFeed, PythHandle, PythPriceFeedId } from '../types.ts';\n\nexport interface PythDeployment {\n\treadonly packageId: string;\n}\n\ninterface CachedPythFeed {\n\treadonly symbol: string;\n\treadonly feedId: string;\n\treadonly priceInfoObjectId: string;\n\treadonly price: string;\n\treadonly expo: number;\n}\n\ninterface CachedPythHandle {\n\treadonly packageId: string;\n\treadonly feeds: ReadonlyArray<CachedPythFeed>;\n}\n\nconst DEFAULT_EXPO = -8;\nconst PYTH_GAS_BUDGET = 200_000_000;\n\nconst normalizeFeedId = (feedId: string): string => feedId.replace(/^0x/i, '').toLowerCase();\n\nconst feedExpo = (feed: PythFeed): number => feed.expo ?? DEFAULT_EXPO;\n\nconst toCachedFeed = (feed: PythFeed, priceInfoObjectId: string): CachedPythFeed => ({\n\tsymbol: feed.symbol,\n\tfeedId: normalizeFeedId(feed.feedId),\n\tpriceInfoObjectId,\n\tprice: feed.initialPrice.toString(),\n\texpo: feedExpo(feed),\n});\n\nconst fromCachedHandle = (cached: CachedPythHandle): PythHandle => ({\n\tpackageId: cached.packageId,\n\tstateId: null,\n\twormholeStateId: null,\n\tfeeds: cached.feeds.map((feed) => ({\n\t\tsymbol: feed.symbol,\n\t\tfeedId: normalizeFeedId(feed.feedId) as PythPriceFeedId,\n\t\tpriceInfoObjectId: feed.priceInfoObjectId,\n\t\tprice: BigInt(feed.price),\n\t\texpo: feed.expo,\n\t})),\n});\n\nconst pythInputsHash = (\n\tpkg: PythDeployment,\n\tsigner: ResolvedSigner,\n\tfeeds: ReadonlyArray<PythFeed>,\n) =>\n\tstableContentHash(\n\t\t[\n\t\t\t'v1',\n\t\t\tpkg.packageId,\n\t\t\tsigner.address,\n\t\t\t...feeds\n\t\t\t\t.map((feed) =>\n\t\t\t\t\t[\n\t\t\t\t\t\tfeed.symbol,\n\t\t\t\t\t\tnormalizeFeedId(feed.feedId),\n\t\t\t\t\t\tfeed.initialPrice.toString(),\n\t\t\t\t\t\tfeedExpo(feed).toString(),\n\t\t\t\t\t\t(feed.confidence ?? 0n).toString(),\n\t\t\t\t\t\t(feed.emaPrice ?? feed.initialPrice).toString(),\n\t\t\t\t\t].join('|'),\n\t\t\t\t)\n\t\t\t\t.sort(),\n\t\t].join('||'),\n\t);\n\nconst buildVerifyProbe = (\n\tsdk: SuiSdkShim,\n\tcached: CachedPythHandle,\n): Effect.Effect<CachedPythHandle | null, never> =>\n\tEffect.gen(function* () {\n\t\tconst results = yield* probeManyLenient(\n\t\t\tcached.feeds.map((feed) =>\n\t\t\t\tEffect.tryPromise({\n\t\t\t\t\ttry: () => sdk.core.getObject({ objectId: feed.priceInfoObjectId }),\n\t\t\t\t\tcatch: () => null,\n\t\t\t\t}).pipe(Effect.catch(() => Effect.succeed(null))),\n\t\t\t),\n\t\t);\n\t\tif (results.some((raw) => raw === null || raw === undefined)) return null;\n\t\treturn cached;\n\t});\n\nconst addI64 = (tx: Transaction, packageId: string, value: bigint | number) => {\n\tconst raw = BigInt(value);\n\tconst negative = raw < 0n;\n\treturn tx.moveCall({\n\t\ttarget: `${packageId}::i64::new`,\n\t\targuments: [tx.pure.u64(negative ? -raw : raw), tx.pure.bool(negative)],\n\t});\n};\n\nconst addPriceInfo = (tx: Transaction, packageId: string, feed: PythFeed, timestamp: bigint) => {\n\tconst price = tx.moveCall({\n\t\ttarget: `${packageId}::price::new`,\n\t\targuments: [\n\t\t\taddI64(tx, packageId, feed.initialPrice),\n\t\t\ttx.pure.u64(feed.confidence ?? 0n),\n\t\t\taddI64(tx, packageId, BigInt(feedExpo(feed))),\n\t\t\ttx.pure.u64(timestamp),\n\t\t],\n\t});\n\tconst emaPrice = tx.moveCall({\n\t\ttarget: `${packageId}::price::new`,\n\t\targuments: [\n\t\t\taddI64(tx, packageId, feed.emaPrice ?? feed.initialPrice),\n\t\t\ttx.pure.u64(feed.confidence ?? 0n),\n\t\t\taddI64(tx, packageId, BigInt(feedExpo(feed))),\n\t\t\ttx.pure.u64(timestamp),\n\t\t],\n\t});\n\tconst priceIdentifier = tx.moveCall({\n\t\ttarget: `${packageId}::price_identifier::from_byte_vec`,\n\t\targuments: [tx.pure.vector('u8', Array.from(fromHex(normalizeFeedId(feed.feedId))))],\n\t});\n\tconst priceFeed = tx.moveCall({\n\t\ttarget: `${packageId}::price_feed::new`,\n\t\targuments: [priceIdentifier, price, emaPrice],\n\t});\n\treturn tx.moveCall({\n\t\ttarget: `${packageId}::price_info::new_price_info`,\n\t\targuments: [tx.pure.u64(timestamp), tx.pure.u64(timestamp), priceFeed],\n\t});\n};\n\nconst feedIdBytesFromJson = (bytes: unknown): Uint8Array | null => {\n\tif (typeof bytes === 'string' && bytes.length > 0) {\n\t\ttry {\n\t\t\treturn fromBase64(bytes);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\tif (!Array.isArray(bytes) || bytes.length === 0) return null;\n\tif (!bytes.every((byte): byte is number => Number.isInteger(byte) && byte >= 0 && byte <= 255)) {\n\t\treturn null;\n\t}\n\treturn Uint8Array.from(bytes);\n};\n\nexport const feedIdFromJson = (json: unknown): string | null => {\n\tif (typeof json !== 'object' || json === null) return null;\n\tconst priceInfo = (json as { readonly price_info?: unknown }).price_info;\n\tif (typeof priceInfo !== 'object' || priceInfo === null) return null;\n\tconst priceFeed = (priceInfo as { readonly price_feed?: unknown }).price_feed;\n\tif (typeof priceFeed !== 'object' || priceFeed === null) return null;\n\tconst priceIdentifier = (priceFeed as { readonly price_identifier?: unknown }).price_identifier;\n\tif (typeof priceIdentifier !== 'object' || priceIdentifier === null) return null;\n\tconst bytes = (priceIdentifier as { readonly bytes?: unknown }).bytes;\n\tconst decoded = feedIdBytesFromJson(bytes);\n\tif (decoded === null) return null;\n\treturn normalizeFeedId(toHex(decoded));\n};\n\nconst mapCreatedPriceObjects = async (\n\tsdk: SuiSdkShim,\n\tobjectIds: ReadonlyArray<string>,\n): Promise<ReadonlyMap<string, string>> => {\n\tconst objects = await sdk.client.core.getObjects({\n\t\tobjectIds: [...objectIds],\n\t\tinclude: { json: true },\n\t});\n\tconst result = new Map<string, string>();\n\tfor (const object of objects.objects) {\n\t\tif (object instanceof Error) continue;\n\t\tconst feedId = feedIdFromJson(object.json);\n\t\tif (feedId !== null) result.set(feedId, object.objectId);\n\t}\n\treturn result;\n};\n\nconst pickCreatedPriceInfoObjects = (\n\tchanges: ReadonlyArray<{\n\t\treadonly objectId: string;\n\t\treadonly objectType?: string;\n\t\treadonly idOperation?: string;\n\t}>,\n): ReadonlyArray<string> =>\n\tchanges\n\t\t.filter(\n\t\t\t(change) =>\n\t\t\t\tchange.idOperation === 'Created' &&\n\t\t\t\tchange.objectType?.includes('::price_info::PriceInfoObject') === true,\n\t\t)\n\t\t.map((change) => change.objectId);\n\n/** Create shared mock-Pyth PriceInfoObjects for local DeepBook feeds. */\nexport const initLocalPythFeeds = (\n\tpublisher: ArtifactPublisher,\n\tsdk: SuiSdkShim,\n\tchain: string,\n\tsigner: ResolvedSigner,\n\tpkg: PythDeployment,\n\tfeeds: ReadonlyArray<PythFeed>,\n): Effect.Effect<PythHandle | null, DeepbookPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tif (feeds.length === 0) return null;\n\n\t\tconst cached = yield* acquireOnChainArtifact<CachedPythHandle, CachedPythHandle>(publisher, {\n\t\t\tnamespace: 'deepbook/pyth',\n\t\t\tchain: brandChainId(chain),\n\t\t\tcontentHash: pythInputsHash(pkg, signer, feeds),\n\t\t\tverify: (entry) => buildVerifyProbe(sdk, entry),\n\t\t\tproduce: Effect.gen(function* () {\n\t\t\t\tconst result = yield* executeSuiTx({\n\t\t\t\t\tclient: sdk.client,\n\t\t\t\t\tsigner,\n\t\t\t\t\tbuild: async () => {\n\t\t\t\t\t\tconst tx = new Transaction();\n\t\t\t\t\t\ttx.setSender(signer.address);\n\t\t\t\t\t\ttx.setGasBudget(PYTH_GAS_BUDGET);\n\t\t\t\t\t\tconst timestamp = 0n;\n\t\t\t\t\t\tconst priceInfos = feeds.map((feed) =>\n\t\t\t\t\t\t\taddPriceInfo(tx, pkg.packageId, feed, timestamp),\n\t\t\t\t\t\t);\n\t\t\t\t\t\ttx.moveCall({\n\t\t\t\t\t\t\ttarget: `${pkg.packageId}::pyth::create_price_feeds`,\n\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\ttx.makeMoveVec({\n\t\t\t\t\t\t\t\t\ttype: `${pkg.packageId}::price_info::PriceInfo`,\n\t\t\t\t\t\t\t\t\telements: priceInfos,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn tx.build({ client: sdk.client });\n\t\t\t\t\t},\n\t\t\t\t}).pipe(\n\t\t\t\t\tEffect.mapError((err) =>\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`pyth feed transaction failed: ${err.message}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tif (result.$kind === 'FailedTransaction') {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`pyth feed transaction on-chain execution failed ` +\n\t\t\t\t\t\t\t\tformatExecutedFailure(result.FailedTransaction),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst receipt = result.Transaction;\n\n\t\t\t\tconst created = pickCreatedPriceInfoObjects(receipt.objectChanges);\n\t\t\t\tif (created.length !== feeds.length) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`expected ${feeds.length} Pyth PriceInfoObject creations, got ${created.length} ` +\n\t\t\t\t\t\t\t\t`(digest=${receipt.digest}).`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst idsByFeed = yield* Effect.tryPromise({\n\t\t\t\t\ttry: () => mapCreatedPriceObjects(sdk, created),\n\t\t\t\t\tcatch: (cause) =>\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`failed to read created Pyth PriceInfoObjects: ${\n\t\t\t\t\t\t\t\tcause instanceof Error ? cause.message : String(cause)\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\tconst cachedFeeds: CachedPythFeed[] = [];\n\t\t\t\tfor (const feed of feeds) {\n\t\t\t\t\tconst priceInfoObjectId = idsByFeed.get(normalizeFeedId(feed.feedId));\n\t\t\t\t\tif (priceInfoObjectId === undefined) {\n\t\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t\t`created Pyth PriceInfoObject for '${feed.symbol}' was not found by feed id.`,\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\tcachedFeeds.push(toCachedFeed(feed, priceInfoObjectId));\n\t\t\t\t}\n\t\t\t\treturn { packageId: pkg.packageId, feeds: cachedFeeds };\n\t\t\t}),\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(err): DeepbookPluginError =>\n\t\t\t\t\tdeepbookPluginError(\n\t\t\t\t\t\t'pyth-feed',\n\t\t\t\t\t\terr._tag === 'ArtifactPublishError' ? err.detail : String(err),\n\t\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t\treturn fromCachedHandle(cached);\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.deepbook.pyth.initFeeds', {\n\t\t\tattributes: {\n\t\t\t\t[DeepbookSpans.pyth.packageId]: pkg.packageId,\n\t\t\t\t[DeepbookSpans.pyth.feedCount]: feeds.length,\n\t\t\t},\n\t\t}),\n\t);\n\n// Compatibility exports for callers/tests that import the internal module.\nexport type { PythFeed, PythHandle, PythOptions } from '../types.ts';\nexport {\n\tDEEP_PRICE_FEED_ID,\n\tpythPriceFeedId,\n\tSUI_PRICE_FEED_ID,\n\tUSDC_PRICE_FEED_ID,\n} from '../types.ts';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/plugins/deepbook/pyth/index.ts"],"sourcesContent":["// Pyth — internal module under the DeepBook plugin.\n//\n// Local mode uses the DeepBook sandbox's mock Pyth package shape: publish a\n// local Move package with `pyth::create_price_feeds`, then create shared\n// `PriceInfoObject`s for the requested feeds. This is intentionally not a\n// top-level devstack plugin; DeepBook owns the oracle wiring it needs.\n\nimport { Effect, type Scope } from 'effect';\nimport { Transaction } from '@mysten/sui/transactions';\nimport { fromBase64, fromHex, toHex } from '@mysten/sui/utils';\n\nimport {\n\tartifactPublishError,\n\ttype ArtifactPublisher,\n} from '../../../primitives/artifact-publisher.ts';\nimport { acquireOnChainArtifact } from '../../internal/acquire-on-chain-artifact.ts';\nimport { probeManyLenient } from '../../../substrate/runtime/probes.ts';\nimport {\n\texecuteSuiTx,\n\tformatExecutedFailure,\n\ttype ResolvedSigner,\n\ttype SuiSdkShim,\n} from '../../sui/index.ts';\nimport { deepbookPluginError, type DeepbookPluginError } from '../errors.ts';\nimport { stableContentHash } from '../hash.ts';\nimport type { PythFeed, PythHandle, PythPriceFeedId } from '../types.ts';\n\nexport interface PythDeployment {\n\treadonly packageId: string;\n}\n\ninterface CachedPythFeed {\n\treadonly symbol: string;\n\treadonly feedId: string;\n\treadonly priceInfoObjectId: string;\n\treadonly price: string;\n\treadonly expo: number;\n}\n\ninterface CachedPythHandle {\n\treadonly packageId: string;\n\treadonly feeds: ReadonlyArray<CachedPythFeed>;\n}\n\nconst DEFAULT_EXPO = -8;\nconst PYTH_GAS_BUDGET = 200_000_000;\n\nconst normalizeFeedId = (feedId: string): string => feedId.replace(/^0x/i, '').toLowerCase();\n\nconst feedExpo = (feed: PythFeed): number => feed.expo ?? DEFAULT_EXPO;\n\nconst toCachedFeed = (feed: PythFeed, priceInfoObjectId: string): CachedPythFeed => ({\n\tsymbol: feed.symbol,\n\tfeedId: normalizeFeedId(feed.feedId),\n\tpriceInfoObjectId,\n\tprice: feed.initialPrice.toString(),\n\texpo: feedExpo(feed),\n});\n\nconst fromCachedHandle = (cached: CachedPythHandle): PythHandle => ({\n\tpackageId: cached.packageId,\n\tstateId: null,\n\twormholeStateId: null,\n\tfeeds: cached.feeds.map((feed) => ({\n\t\tsymbol: feed.symbol,\n\t\tfeedId: normalizeFeedId(feed.feedId) as PythPriceFeedId,\n\t\tpriceInfoObjectId: feed.priceInfoObjectId,\n\t\tprice: BigInt(feed.price),\n\t\texpo: feed.expo,\n\t})),\n});\n\nconst pythInputsHash = (\n\tpkg: PythDeployment,\n\tsigner: ResolvedSigner,\n\tfeeds: ReadonlyArray<PythFeed>,\n) =>\n\tstableContentHash(\n\t\t[\n\t\t\t'v1',\n\t\t\tpkg.packageId,\n\t\t\tsigner.address,\n\t\t\t...feeds\n\t\t\t\t.map((feed) =>\n\t\t\t\t\t[\n\t\t\t\t\t\tfeed.symbol,\n\t\t\t\t\t\tnormalizeFeedId(feed.feedId),\n\t\t\t\t\t\tfeed.initialPrice.toString(),\n\t\t\t\t\t\tfeedExpo(feed).toString(),\n\t\t\t\t\t\t(feed.confidence ?? 0n).toString(),\n\t\t\t\t\t\t(feed.emaPrice ?? feed.initialPrice).toString(),\n\t\t\t\t\t].join('|'),\n\t\t\t\t)\n\t\t\t\t.sort(),\n\t\t].join('||'),\n\t);\n\nconst buildVerifyProbe = (\n\tsdk: SuiSdkShim,\n\tcached: CachedPythHandle,\n): Effect.Effect<CachedPythHandle | null, never> =>\n\tEffect.gen(function* () {\n\t\tconst results = yield* probeManyLenient(\n\t\t\tcached.feeds.map((feed) =>\n\t\t\t\tEffect.tryPromise({\n\t\t\t\t\ttry: () => sdk.core.getObject({ objectId: feed.priceInfoObjectId }),\n\t\t\t\t\tcatch: () => null,\n\t\t\t\t}).pipe(Effect.catch(() => Effect.succeed(null))),\n\t\t\t),\n\t\t);\n\t\tif (results.some((raw) => raw === null || raw === undefined)) return null;\n\t\treturn cached;\n\t});\n\nconst addI64 = (tx: Transaction, packageId: string, value: bigint | number) => {\n\tconst raw = BigInt(value);\n\tconst negative = raw < 0n;\n\treturn tx.moveCall({\n\t\ttarget: `${packageId}::i64::new`,\n\t\targuments: [tx.pure.u64(negative ? -raw : raw), tx.pure.bool(negative)],\n\t});\n};\n\nconst addPriceInfo = (tx: Transaction, packageId: string, feed: PythFeed, timestamp: bigint) => {\n\tconst price = tx.moveCall({\n\t\ttarget: `${packageId}::price::new`,\n\t\targuments: [\n\t\t\taddI64(tx, packageId, feed.initialPrice),\n\t\t\ttx.pure.u64(feed.confidence ?? 0n),\n\t\t\taddI64(tx, packageId, BigInt(feedExpo(feed))),\n\t\t\ttx.pure.u64(timestamp),\n\t\t],\n\t});\n\tconst emaPrice = tx.moveCall({\n\t\ttarget: `${packageId}::price::new`,\n\t\targuments: [\n\t\t\taddI64(tx, packageId, feed.emaPrice ?? feed.initialPrice),\n\t\t\ttx.pure.u64(feed.confidence ?? 0n),\n\t\t\taddI64(tx, packageId, BigInt(feedExpo(feed))),\n\t\t\ttx.pure.u64(timestamp),\n\t\t],\n\t});\n\tconst priceIdentifier = tx.moveCall({\n\t\ttarget: `${packageId}::price_identifier::from_byte_vec`,\n\t\targuments: [tx.pure.vector('u8', Array.from(fromHex(normalizeFeedId(feed.feedId))))],\n\t});\n\tconst priceFeed = tx.moveCall({\n\t\ttarget: `${packageId}::price_feed::new`,\n\t\targuments: [priceIdentifier, price, emaPrice],\n\t});\n\treturn tx.moveCall({\n\t\ttarget: `${packageId}::price_info::new_price_info`,\n\t\targuments: [tx.pure.u64(timestamp), tx.pure.u64(timestamp), priceFeed],\n\t});\n};\n\nconst feedIdBytesFromJson = (bytes: unknown): Uint8Array | null => {\n\tif (typeof bytes === 'string' && bytes.length > 0) {\n\t\ttry {\n\t\t\treturn fromBase64(bytes);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\tif (!Array.isArray(bytes) || bytes.length === 0) return null;\n\tif (!bytes.every((byte): byte is number => Number.isInteger(byte) && byte >= 0 && byte <= 255)) {\n\t\treturn null;\n\t}\n\treturn Uint8Array.from(bytes);\n};\n\nexport const feedIdFromJson = (json: unknown): string | null => {\n\tif (typeof json !== 'object' || json === null) return null;\n\tconst priceInfo = (json as { readonly price_info?: unknown }).price_info;\n\tif (typeof priceInfo !== 'object' || priceInfo === null) return null;\n\tconst priceFeed = (priceInfo as { readonly price_feed?: unknown }).price_feed;\n\tif (typeof priceFeed !== 'object' || priceFeed === null) return null;\n\tconst priceIdentifier = (priceFeed as { readonly price_identifier?: unknown }).price_identifier;\n\tif (typeof priceIdentifier !== 'object' || priceIdentifier === null) return null;\n\tconst bytes = (priceIdentifier as { readonly bytes?: unknown }).bytes;\n\tconst decoded = feedIdBytesFromJson(bytes);\n\tif (decoded === null) return null;\n\treturn normalizeFeedId(toHex(decoded));\n};\n\nconst mapCreatedPriceObjects = async (\n\tsdk: SuiSdkShim,\n\tobjectIds: ReadonlyArray<string>,\n): Promise<ReadonlyMap<string, string>> => {\n\tconst objects = await sdk.client.core.getObjects({\n\t\tobjectIds: [...objectIds],\n\t\tinclude: { json: true },\n\t});\n\tconst result = new Map<string, string>();\n\tfor (const object of objects.objects) {\n\t\tif (object instanceof Error) continue;\n\t\tconst feedId = feedIdFromJson(object.json);\n\t\tif (feedId !== null) result.set(feedId, object.objectId);\n\t}\n\treturn result;\n};\n\nconst pickCreatedPriceInfoObjects = (\n\tchanges: ReadonlyArray<{\n\t\treadonly objectId: string;\n\t\treadonly objectType?: string;\n\t\treadonly idOperation?: string;\n\t}>,\n): ReadonlyArray<string> =>\n\tchanges\n\t\t.filter(\n\t\t\t(change) =>\n\t\t\t\tchange.idOperation === 'Created' &&\n\t\t\t\tchange.objectType?.includes('::price_info::PriceInfoObject') === true,\n\t\t)\n\t\t.map((change) => change.objectId);\n\n/** Create shared mock-Pyth PriceInfoObjects for local DeepBook feeds. */\nexport const initLocalPythFeeds = (\n\tpublisher: ArtifactPublisher,\n\tsdk: SuiSdkShim,\n\tchain: string,\n\tsigner: ResolvedSigner,\n\tpkg: PythDeployment,\n\tfeeds: ReadonlyArray<PythFeed>,\n): Effect.Effect<PythHandle | null, DeepbookPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tif (feeds.length === 0) return null;\n\n\t\tconst cached = yield* acquireOnChainArtifact<CachedPythHandle, CachedPythHandle>(publisher, {\n\t\t\tnamespace: 'deepbook/pyth',\n\t\t\tchain,\n\t\t\tcontentHash: pythInputsHash(pkg, signer, feeds),\n\t\t\tverify: (entry) => buildVerifyProbe(sdk, entry),\n\t\t\tproduce: Effect.gen(function* () {\n\t\t\t\tconst result = yield* executeSuiTx({\n\t\t\t\t\tclient: sdk.client,\n\t\t\t\t\tsigner,\n\t\t\t\t\tbuild: async () => {\n\t\t\t\t\t\tconst tx = new Transaction();\n\t\t\t\t\t\ttx.setSender(signer.address);\n\t\t\t\t\t\ttx.setGasBudget(PYTH_GAS_BUDGET);\n\t\t\t\t\t\tconst timestamp = 0n;\n\t\t\t\t\t\tconst priceInfos = feeds.map((feed) =>\n\t\t\t\t\t\t\taddPriceInfo(tx, pkg.packageId, feed, timestamp),\n\t\t\t\t\t\t);\n\t\t\t\t\t\ttx.moveCall({\n\t\t\t\t\t\t\ttarget: `${pkg.packageId}::pyth::create_price_feeds`,\n\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\ttx.makeMoveVec({\n\t\t\t\t\t\t\t\t\ttype: `${pkg.packageId}::price_info::PriceInfo`,\n\t\t\t\t\t\t\t\t\telements: priceInfos,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn tx.build({ client: sdk.client });\n\t\t\t\t\t},\n\t\t\t\t}).pipe(\n\t\t\t\t\tEffect.mapError((err) =>\n\t\t\t\t\t\tartifactPublishError('produce-failed', `pyth feed transaction failed: ${err.message}`),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tif (result.$kind === 'FailedTransaction') {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`pyth feed transaction on-chain execution failed ` +\n\t\t\t\t\t\t\t\tformatExecutedFailure(result.FailedTransaction),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst receipt = result.Transaction;\n\n\t\t\t\tconst created = pickCreatedPriceInfoObjects(receipt.objectChanges);\n\t\t\t\tif (created.length !== feeds.length) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`expected ${feeds.length} Pyth PriceInfoObject creations, got ${created.length} ` +\n\t\t\t\t\t\t\t\t`(digest=${receipt.digest}).`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst idsByFeed = yield* Effect.tryPromise({\n\t\t\t\t\ttry: () => mapCreatedPriceObjects(sdk, created),\n\t\t\t\t\tcatch: (cause) =>\n\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t`failed to read created Pyth PriceInfoObjects: ${\n\t\t\t\t\t\t\t\tcause instanceof Error ? cause.message : String(cause)\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\tconst cachedFeeds: CachedPythFeed[] = [];\n\t\t\t\tfor (const feed of feeds) {\n\t\t\t\t\tconst priceInfoObjectId = idsByFeed.get(normalizeFeedId(feed.feedId));\n\t\t\t\t\tif (priceInfoObjectId === undefined) {\n\t\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\t\tartifactPublishError(\n\t\t\t\t\t\t\t\t'produce-failed',\n\t\t\t\t\t\t\t\t`created Pyth PriceInfoObject for '${feed.symbol}' was not found by feed id.`,\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\tcachedFeeds.push(toCachedFeed(feed, priceInfoObjectId));\n\t\t\t\t}\n\t\t\t\treturn { packageId: pkg.packageId, feeds: cachedFeeds };\n\t\t\t}),\n\t\t}).pipe(\n\t\t\tEffect.mapError(\n\t\t\t\t(err): DeepbookPluginError =>\n\t\t\t\t\tdeepbookPluginError(\n\t\t\t\t\t\t'pyth-feed',\n\t\t\t\t\t\terr._tag === 'ArtifactPublishError' ? err.detail : String(err),\n\t\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t\treturn fromCachedHandle(cached);\n\t});\n\n// Compatibility exports for callers/tests that import the internal module.\nexport type { PythFeed, PythHandle, PythOptions } from '../types.ts';\nexport {\n\tDEEP_PRICE_FEED_ID,\n\tpythPriceFeedId,\n\tSUI_PRICE_FEED_ID,\n\tUSDC_PRICE_FEED_ID,\n} from '../types.ts';\n"],"mappings":"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"}
@@ -8,7 +8,6 @@ const makeLocalSnapshotable = (inputs) => ({
8
8
  kind: "snapshotable",
9
9
  subtrees: [`deepbook/${inputs.name}`],
10
10
  managedContainers: [],
11
- quiesce: Effect.void,
12
11
  preRestore: Effect.succeed({
13
12
  kind: "deepbook",
14
13
  name: inputs.name
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.mjs","names":[],"sources":["../../../src/plugins/deepbook/snapshot.ts"],"sourcesContent":["// Deepbook plugin — Snapshotable contribution.\n//\n// What needs to survive snapshot:\n//\n// - Cached publish receipts under runtime/deepbook/<name>/cache/\n// (driven by the artifact publisher primitive's cache layer; the host-tree\n// subtree is `deepbook/<name>` and the artifact publisher cache lives inside it).\n// - Managed containers — the optional indexer + server use\n// labeled tuples drive the docker commit + save path.\n//\n// Architecture: the orchestrator is service-name-blind — it walks\n// the Snapshotable decls, sees `deepbook/<name>` as just a subtree\n// path, and treats the secret flag as opaque.\n\nimport { Effect } from 'effect';\n\nimport type { SnapshotableDecl } from '../../contracts/snapshotable.ts';\n\n/** Build the Snapshotable contribution for the local-mode plugin.\n * Deepbook's deploy artifacts live on the host subtree; no managed\n * containers participate (the indexer + server daemons aren't wired\n * yet). When they land, add their `ContainerLabelTuple` here. */\nexport const makeLocalSnapshotable = (inputs: { readonly name: string }): SnapshotableDecl => ({\n\tkind: 'snapshotable',\n\tsubtrees: [`deepbook/${inputs.name}`],\n\tmanagedContainers: [],\n\tquiesce: Effect.void,\n\tpreRestore: Effect.succeed({ kind: 'deepbook' as const, name: inputs.name }),\n\tpostRestore: Effect.void,\n\tmissingTolerance: 'fine',\n\tsecretMaterial: false,\n});\n\n/** Build the Snapshotable contribution for the known-deployment\n * mode. No on-disk state, no managed containers — pure value\n * producer. */\nexport const makeKnownSnapshotable = (inputs: { readonly name: string }): SnapshotableDecl => ({\n\tkind: 'snapshotable',\n\tsubtrees: [],\n\tpreRestore: Effect.succeed({ kind: 'deepbook' as const, name: inputs.name }),\n\tpostRestore: Effect.void,\n\tmissingTolerance: 'fine',\n\tsecretMaterial: false,\n});\n"],"mappings":";;;;;;AAsBA,MAAa,yBAAyB,YAAyD;CAC9F,MAAM;CACN,UAAU,CAAC,YAAY,OAAO,OAAO;CACrC,mBAAmB,EAAE;CACrB,SAAS,OAAO;CAChB,YAAY,OAAO,QAAQ;EAAE,MAAM;EAAqB,MAAM,OAAO;EAAM,CAAC;CAC5E,aAAa,OAAO;CACpB,kBAAkB;CAClB,gBAAgB;CAChB;;;;AAKD,MAAa,yBAAyB,YAAyD;CAC9F,MAAM;CACN,UAAU,EAAE;CACZ,YAAY,OAAO,QAAQ;EAAE,MAAM;EAAqB,MAAM,OAAO;EAAM,CAAC;CAC5E,aAAa,OAAO;CACpB,kBAAkB;CAClB,gBAAgB;CAChB"}
1
+ {"version":3,"file":"snapshot.mjs","names":[],"sources":["../../../src/plugins/deepbook/snapshot.ts"],"sourcesContent":["// Deepbook plugin — Snapshotable contribution.\n//\n// What needs to survive snapshot:\n//\n// - Cached publish receipts under runtime/deepbook/<name>/cache/\n// (driven by the artifact publisher primitive's cache layer; the host-tree\n// subtree is `deepbook/<name>` and the artifact publisher cache lives inside it).\n// - Managed containers — the optional indexer + server use\n// labeled tuples drive the docker commit + save path.\n//\n// Architecture: the orchestrator is service-name-blind — it walks\n// the Snapshotable decls, sees `deepbook/<name>` as just a subtree\n// path, and treats the secret flag as opaque.\n\nimport { Effect } from 'effect';\n\nimport type { SnapshotableDecl } from '../../contracts/snapshotable.ts';\n\n/** Build the Snapshotable contribution for the local-mode plugin.\n * Deepbook's deploy artifacts live on the host subtree; no managed\n * containers participate (the indexer + server daemons aren't wired\n * yet). When they land, add their `ContainerLabelTuple` here. */\nexport const makeLocalSnapshotable = (inputs: { readonly name: string }): SnapshotableDecl => ({\n\tkind: 'snapshotable',\n\tsubtrees: [`deepbook/${inputs.name}`],\n\tmanagedContainers: [],\n\tpreRestore: Effect.succeed({ kind: 'deepbook' as const, name: inputs.name }),\n\tpostRestore: Effect.void,\n\tmissingTolerance: 'fine',\n\tsecretMaterial: false,\n});\n\n/** Build the Snapshotable contribution for the known-deployment\n * mode. No on-disk state, no managed containers — pure value\n * producer. */\nexport const makeKnownSnapshotable = (inputs: { readonly name: string }): SnapshotableDecl => ({\n\tkind: 'snapshotable',\n\tsubtrees: [],\n\tpreRestore: Effect.succeed({ kind: 'deepbook' as const, name: inputs.name }),\n\tpostRestore: Effect.void,\n\tmissingTolerance: 'fine',\n\tsecretMaterial: false,\n});\n"],"mappings":";;;;;;AAsBA,MAAa,yBAAyB,YAAyD;CAC9F,MAAM;CACN,UAAU,CAAC,YAAY,OAAO,MAAM;CACpC,mBAAmB,CAAC;CACpB,YAAY,OAAO,QAAQ;EAAE,MAAM;EAAqB,MAAM,OAAO;CAAK,CAAC;CAC3E,aAAa,OAAO;CACpB,kBAAkB;CAClB,gBAAgB;AACjB;;;;AAKA,MAAa,yBAAyB,YAAyD;CAC9F,MAAM;CACN,UAAU,CAAC;CACX,YAAY,OAAO,QAAQ;EAAE,MAAM;EAAqB,MAAM,OAAO;CAAK,CAAC;CAC3E,aAAa,OAAO;CACpB,kBAAkB;CAClB,gBAAgB;AACjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"type-strings.mjs","names":[],"sources":["../../../src/plugins/deepbook/type-strings.ts"],"sourcesContent":["// DeepBook type-string helpers.\n//\n// Mirrors `plugins/coin/type-strings.ts`: a position-aware matcher over\n// a fully-qualified Sui type string instead of substring sniffing.\n//\n// The coin helper is anchored to the framework `0x2::coin::<Wrapper><T>`\n// (single inner generic). A DeepBook pool object is\n// `<pkg>::pool::Pool<Base, Quote>` — a NON-framework package with TWO\n// positional generic arguments — so it needs its own parser. Both\n// arguments and the spec coin types are normalized with the shared SDK\n// `normalizeStructTag` (which recursively pads addresses) and compared\n// POSITIONALLY, so a reversed pair (`DEEP/SUI` vs `SUI/DEEP`) or a coin\n// type that is a substring of another can no longer cross-match.\n\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\n/** Parse the two positional generic arguments out of a\n * `<pkg>::pool::Pool<Base, Quote>` object type. Returns `null` when the\n * type is not a `::pool::Pool<…>` with exactly two top-level arguments\n * (the SDK may pad the package address, so the module/wrapper suffix is\n * matched on the `::pool::Pool<` marker rather than the full prefix). */\nexport const parsePoolGenericArgs = (\n\tobjectType: string,\n): { readonly base: string; readonly quote: string } | null => {\n\tif (!objectType.endsWith('>')) return null;\n\tconst marker = '::pool::Pool<';\n\tconst markerIndex = objectType.indexOf(marker);\n\tif (markerIndex === -1) return null;\n\tconst inner = objectType.slice(markerIndex + marker.length, -1);\n\tconst args = splitTopLevelGenericArgs(inner);\n\tif (args.length !== 2) return null;\n\tconst [base, quote] = args;\n\tif (base === undefined || quote === undefined) return null;\n\treturn { base, quote };\n};\n\n/** Does `objectType` name a `Pool<Base, Quote>` whose generic arguments\n * match `(baseCoinType, quoteCoinType)` POSITIONALLY? Each side is\n * compared via `normalizeStructTag` so framework-address padding does\n * not defeat the match and a reversed pair does not collide. */\nexport const isPoolForPair = (\n\tobjectType: string,\n\tbaseCoinType: string,\n\tquoteCoinType: string,\n): boolean => {\n\tconst parsed = parsePoolGenericArgs(objectType);\n\tif (parsed === null) return false;\n\tconst base = normalizeStructTagSafe(parsed.base);\n\tconst quote = normalizeStructTagSafe(parsed.quote);\n\tconst wantBase = normalizeStructTagSafe(baseCoinType);\n\tconst wantQuote = normalizeStructTagSafe(quoteCoinType);\n\t// A malformed tag normalizes to `null`; never let two nulls compare\n\t// equal — a doubly-malformed side must NOT spuriously pair.\n\tif (base === null || quote === null || wantBase === null || wantQuote === null) return false;\n\treturn base === wantBase && quote === wantQuote;\n};\n\n/** Split a generic-argument list on top-level commas, respecting nested\n * `<…>` so a generic coin type argument is not split mid-bracket. */\nconst splitTopLevelGenericArgs = (inner: string): ReadonlyArray<string> => {\n\tconst args: string[] = [];\n\tlet depth = 0;\n\tlet start = 0;\n\tfor (let i = 0; i < inner.length; i += 1) {\n\t\tconst ch = inner[i];\n\t\tif (ch === '<') depth += 1;\n\t\telse if (ch === '>') depth -= 1;\n\t\telse if (ch === ',' && depth === 0) {\n\t\t\targs.push(inner.slice(start, i).trim());\n\t\t\tstart = i + 1;\n\t\t}\n\t}\n\targs.push(inner.slice(start).trim());\n\treturn args;\n};\n\n/** `normalizeStructTag` throws on a malformed tag; coerce to a sentinel\n * so a bad parse fails the positional compare rather than the caller. */\nconst normalizeStructTagSafe = (tag: string): string | null => {\n\ttry {\n\t\treturn normalizeStructTag(tag);\n\t} catch {\n\t\treturn null;\n\t}\n};\n"],"mappings":";;;;;;;AAqBA,MAAa,wBACZ,eAC8D;AAC9D,KAAI,CAAC,WAAW,SAAS,IAAI,CAAE,QAAO;CAEtC,MAAM,cAAc,WAAW,QAAQ,gBAAO;AAC9C,KAAI,gBAAgB,GAAI,QAAO;CAE/B,MAAM,OAAO,yBADC,WAAW,MAAM,cAAc,IAAe,GACjB,CAAC;AAC5C,KAAI,KAAK,WAAW,EAAG,QAAO;CAC9B,MAAM,CAAC,MAAM,SAAS;AACtB,KAAI,SAAS,KAAA,KAAa,UAAU,KAAA,EAAW,QAAO;AACtD,QAAO;EAAE;EAAM;EAAO;;;;;;AAOvB,MAAa,iBACZ,YACA,cACA,kBACa;CACb,MAAM,SAAS,qBAAqB,WAAW;AAC/C,KAAI,WAAW,KAAM,QAAO;CAC5B,MAAM,OAAO,uBAAuB,OAAO,KAAK;CAChD,MAAM,QAAQ,uBAAuB,OAAO,MAAM;CAClD,MAAM,WAAW,uBAAuB,aAAa;CACrD,MAAM,YAAY,uBAAuB,cAAc;AAGvD,KAAI,SAAS,QAAQ,UAAU,QAAQ,aAAa,QAAQ,cAAc,KAAM,QAAO;AACvF,QAAO,SAAS,YAAY,UAAU;;;;AAKvC,MAAM,4BAA4B,UAAyC;CAC1E,MAAM,OAAiB,EAAE;CACzB,IAAI,QAAQ;CACZ,IAAI,QAAQ;AACZ,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACzC,MAAM,KAAK,MAAM;AACjB,MAAI,OAAO,IAAK,UAAS;WAChB,OAAO,IAAK,UAAS;WACrB,OAAO,OAAO,UAAU,GAAG;AACnC,QAAK,KAAK,MAAM,MAAM,OAAO,EAAE,CAAC,MAAM,CAAC;AACvC,WAAQ,IAAI;;;AAGd,MAAK,KAAK,MAAM,MAAM,MAAM,CAAC,MAAM,CAAC;AACpC,QAAO;;;;AAKR,MAAM,0BAA0B,QAA+B;AAC9D,KAAI;AACH,SAAO,mBAAmB,IAAI;SACvB;AACP,SAAO"}
1
+ {"version":3,"file":"type-strings.mjs","names":[],"sources":["../../../src/plugins/deepbook/type-strings.ts"],"sourcesContent":["// DeepBook type-string helpers.\n//\n// Mirrors `plugins/coin/type-strings.ts`: a position-aware matcher over\n// a fully-qualified Sui type string instead of substring sniffing.\n//\n// The coin helper is anchored to the framework `0x2::coin::<Wrapper><T>`\n// (single inner generic). A DeepBook pool object is\n// `<pkg>::pool::Pool<Base, Quote>` — a NON-framework package with TWO\n// positional generic arguments — so it needs its own parser. Both\n// arguments and the spec coin types are normalized with the shared SDK\n// `normalizeStructTag` (which recursively pads addresses) and compared\n// POSITIONALLY, so a reversed pair (`DEEP/SUI` vs `SUI/DEEP`) or a coin\n// type that is a substring of another cannot cross-match.\n\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\n/** Parse the two positional generic arguments out of a\n * `<pkg>::pool::Pool<Base, Quote>` object type. Returns `null` when the\n * type is not a `::pool::Pool<…>` with exactly two top-level arguments\n * (the SDK may pad the package address, so the module/wrapper suffix is\n * matched on the `::pool::Pool<` marker rather than the full prefix). */\nexport const parsePoolGenericArgs = (\n\tobjectType: string,\n): { readonly base: string; readonly quote: string } | null => {\n\tif (!objectType.endsWith('>')) return null;\n\tconst marker = '::pool::Pool<';\n\tconst markerIndex = objectType.indexOf(marker);\n\tif (markerIndex === -1) return null;\n\tconst inner = objectType.slice(markerIndex + marker.length, -1);\n\tconst args = splitTopLevelGenericArgs(inner);\n\tif (args.length !== 2) return null;\n\tconst [base, quote] = args;\n\tif (base === undefined || quote === undefined) return null;\n\treturn { base, quote };\n};\n\n/** Does `objectType` name a `Pool<Base, Quote>` whose generic arguments\n * match `(baseCoinType, quoteCoinType)` POSITIONALLY? Each side is\n * compared via `normalizeStructTag` so framework-address padding does\n * not defeat the match and a reversed pair does not collide. */\nexport const isPoolForPair = (\n\tobjectType: string,\n\tbaseCoinType: string,\n\tquoteCoinType: string,\n): boolean => {\n\tconst parsed = parsePoolGenericArgs(objectType);\n\tif (parsed === null) return false;\n\tconst base = normalizeStructTagSafe(parsed.base);\n\tconst quote = normalizeStructTagSafe(parsed.quote);\n\tconst wantBase = normalizeStructTagSafe(baseCoinType);\n\tconst wantQuote = normalizeStructTagSafe(quoteCoinType);\n\t// A malformed tag normalizes to `null`; never let two nulls compare\n\t// equal — a doubly-malformed side must NOT spuriously pair.\n\tif (base === null || quote === null || wantBase === null || wantQuote === null) return false;\n\treturn base === wantBase && quote === wantQuote;\n};\n\n/** Split a generic-argument list on top-level commas, respecting nested\n * `<…>` so a generic coin type argument is not split mid-bracket. */\nconst splitTopLevelGenericArgs = (inner: string): ReadonlyArray<string> => {\n\tconst args: string[] = [];\n\tlet depth = 0;\n\tlet start = 0;\n\tfor (let i = 0; i < inner.length; i += 1) {\n\t\tconst ch = inner[i];\n\t\tif (ch === '<') depth += 1;\n\t\telse if (ch === '>') depth -= 1;\n\t\telse if (ch === ',' && depth === 0) {\n\t\t\targs.push(inner.slice(start, i).trim());\n\t\t\tstart = i + 1;\n\t\t}\n\t}\n\targs.push(inner.slice(start).trim());\n\treturn args;\n};\n\n/** `normalizeStructTag` throws on a malformed tag; coerce to a sentinel\n * so a bad parse fails the positional compare rather than the caller. */\nconst normalizeStructTagSafe = (tag: string): string | null => {\n\ttry {\n\t\treturn normalizeStructTag(tag);\n\t} catch {\n\t\treturn null;\n\t}\n};\n"],"mappings":";;;;;;;AAqBA,MAAa,wBACZ,eAC8D;CAC9D,IAAI,CAAC,WAAW,SAAS,GAAG,GAAG,OAAO;CAEtC,MAAM,cAAc,WAAW,QAAQ,eAAM;CAC7C,IAAI,gBAAgB,IAAI,OAAO;CAE/B,MAAM,OAAO,yBADC,WAAW,MAAM,cAAc,IAAe,EAClB,CAAC;CAC3C,IAAI,KAAK,WAAW,GAAG,OAAO;CAC9B,MAAM,CAAC,MAAM,SAAS;CACtB,IAAI,SAAS,KAAA,KAAa,UAAU,KAAA,GAAW,OAAO;CACtD,OAAO;EAAE;EAAM;CAAM;AACtB;;;;;AAMA,MAAa,iBACZ,YACA,cACA,kBACa;CACb,MAAM,SAAS,qBAAqB,UAAU;CAC9C,IAAI,WAAW,MAAM,OAAO;CAC5B,MAAM,OAAO,uBAAuB,OAAO,IAAI;CAC/C,MAAM,QAAQ,uBAAuB,OAAO,KAAK;CACjD,MAAM,WAAW,uBAAuB,YAAY;CACpD,MAAM,YAAY,uBAAuB,aAAa;CAGtD,IAAI,SAAS,QAAQ,UAAU,QAAQ,aAAa,QAAQ,cAAc,MAAM,OAAO;CACvF,OAAO,SAAS,YAAY,UAAU;AACvC;;;AAIA,MAAM,4BAA4B,UAAyC;CAC1E,MAAM,OAAiB,CAAC;CACxB,IAAI,QAAQ;CACZ,IAAI,QAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACzC,MAAM,KAAK,MAAM;EACjB,IAAI,OAAO,KAAK,SAAS;OACpB,IAAI,OAAO,KAAK,SAAS;OACzB,IAAI,OAAO,OAAO,UAAU,GAAG;GACnC,KAAK,KAAK,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;GACtC,QAAQ,IAAI;EACb;CACD;CACA,KAAK,KAAK,MAAM,MAAM,KAAK,CAAC,CAAC,KAAK,CAAC;CACnC,OAAO;AACR;;;AAIA,MAAM,0BAA0B,QAA+B;CAC9D,IAAI;EACH,OAAO,mBAAmB,GAAG;CAC9B,QAAQ;EACP,OAAO;CACR;AACD"}
@@ -1,7 +1,8 @@
1
1
  import { ResourceRef } from "../../substrate/plugin.mjs";
2
2
  import { AccountValue } from "../account/service.mjs";
3
- import { LocalPackageResolved } from "../package/index.mjs";
4
3
  import { CoinValue } from "../coin/service.mjs";
4
+ import { LocalPackageResolved } from "../package/index.mjs";
5
+
5
6
  //#region src/plugins/deepbook/types.d.ts
6
7
  /** A Pyth price feed id — opaque 64-character hex string. */
7
8
  type PythPriceFeedId = string & {
@@ -1 +1 @@
1
- {"version":3,"file":"types.mjs","names":[],"sources":["../../../src/plugins/deepbook/types.ts"],"sourcesContent":["// Deepbook plugin — public user-facing types.\n//\n// This file declares the DeepBook resolved-value and helper shapes.\n// The local factory in `index.ts` only accepts options that acquire\n// real behavior in the current implementation.\n//\n// Substrate-blindness rule: nothing here references a specific\n// account / coin / package member's resolved value — the references\n// flow in as Direct Member Refs (the locked Decision per\n// `feedback_no_inline_validation_in_parallel_agents` /\n// `project_devstack_api_design_locked_decisions`).\n\nimport type { AccountValue } from '../account/index.ts';\nimport type { CoinValue } from '../coin/index.ts';\nimport type { LocalPackageResolved } from '../package/index.ts';\nimport type { ResourceRef } from '../../api/define-plugin.ts';\n\n// ---------------------------------------------------------------------------\n// Pyth — internal sub-module shapes (NOT a top-level plugin per memory\n// `project_pyth_inside_deepbook`).\n// ---------------------------------------------------------------------------\n\n/** A Pyth price feed id — opaque 64-character hex string. */\nexport type PythPriceFeedId = string & { readonly __pythPriceFeedId: unique symbol };\n\nexport const pythPriceFeedId = (s: string): PythPriceFeedId => s as PythPriceFeedId;\n\n/** Pyth feed binding — symbol + feed id + initial price. */\nexport interface PythFeed {\n\treadonly symbol: string;\n\treadonly feedId: PythPriceFeedId;\n\t/** Initial price expressed in feed-native scale (Pyth conf is the\n\t * signed-int representation; bigint avoids float precision drift). */\n\treadonly initialPrice: bigint;\n\t/** Feed exponent. Defaults to -8, matching the DeepBook sandbox. */\n\treadonly expo?: number;\n\t/** Optional confidence interval. Defaults to 0 for deterministic local feeds. */\n\treadonly confidence?: bigint;\n\t/** Optional EMA price. Defaults to `initialPrice`. */\n\treadonly emaPrice?: bigint;\n}\n\n/** Pyth options. `package` and `pusher` are member refs, not magic strings. */\nexport interface PythOptions<\n\tPackage extends PythPackageMember = PythPackageMember,\n\tPusher extends AccountMemberAlias = AccountMemberAlias,\n> {\n\treadonly package: Package;\n\treadonly pusher: Pusher;\n\treadonly feeds: ReadonlyArray<PythFeed>;\n}\n\n/** Resolved Pyth handle exposed inside the deepbook resolved value. */\nexport interface PythHandle {\n\t/** Local sandbox Pyth has no Wormhole state; known deployments do. */\n\treadonly packageId: string | null;\n\treadonly stateId: string | null;\n\treadonly wormholeStateId: string | null;\n\treadonly feeds: ReadonlyArray<{\n\t\treadonly symbol: string;\n\t\treadonly feedId: PythPriceFeedId;\n\t\treadonly priceInfoObjectId: string;\n\t\treadonly price: bigint;\n\t\treadonly expo: number;\n\t}>;\n}\n\n/** Common Pyth price feed ids (subset; users pass their own as\n * needed). These are the well-known Pyth hex feed ids, NOT\n * per-stack derived. */\nexport const SUI_PRICE_FEED_ID: PythPriceFeedId = pythPriceFeedId(\n\t'23d7315113f5b1d3ba7a83604c44b94d79f4fd69af77f804fc7f920a6dc65744',\n);\nexport const USDC_PRICE_FEED_ID: PythPriceFeedId = pythPriceFeedId(\n\t'eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a',\n);\nexport const DEEP_PRICE_FEED_ID: PythPriceFeedId = pythPriceFeedId(\n\t'29bdd5248234e33bd93d3b81100b5fa32eaa5997843847e2c2cb16d7c6d9f7ff',\n);\n\n// ---------------------------------------------------------------------------\n// Pool spec\n// ---------------------------------------------------------------------------\n\n/** Coin handle used by local DeepBook pool specs. `key` is the SDK-facing\n * coin key (for example `DEEP` or `SUI`); `coin` is the devstack member ref\n * whose resolved value supplies the full Move coin type. */\nexport interface DeepbookPoolCoin<Coin extends CoinMemberAlias = CoinMemberAlias> {\n\treadonly key: string;\n\treadonly coin: Coin;\n\t/** SDK scalar for this coin. Defaults to the resolved coin decimals. */\n\treadonly scalar?: number;\n\t/** SDK address column. Defaults to the package id for package coins, or\n\t * the address portion of the resolved full coin type. */\n\treadonly address?: string;\n}\n\n/** Seed order placed after a local pool is created. Price and quantity use\n * DeepBook's on-chain units: `price` is quote-unit price and `quantity` is\n * base-asset quantity. */\nexport interface DeepbookPoolSeedOrder {\n\treadonly side: 'ask' | 'bid';\n\treadonly price: bigint;\n\treadonly quantity: bigint;\n\treadonly clientOrderId?: bigint;\n\treadonly payWithDeep?: boolean;\n}\n\n/** Optional local liquidity seed. Package coins with a generic funding\n * strategy are minted to the publisher before the seed transaction; otherwise\n * the publisher must already own the deposited coins. */\nexport interface DeepbookPoolSeedLiquidity {\n\treadonly baseAmount?: bigint;\n\treadonly quoteAmount?: bigint;\n\treadonly orders: ReadonlyArray<DeepbookPoolSeedOrder>;\n}\n\n/** Whitelisted pool to create at deploy time. `base` / `quote` are real coin\n * member refs so pool creation cannot race package/coin resolution. */\nexport interface DeepbookPoolSpec<\n\tBase extends CoinMemberAlias = CoinMemberAlias,\n\tQuote extends CoinMemberAlias = CoinMemberAlias,\n> {\n\treadonly name: string;\n\treadonly base: DeepbookPoolCoin<Base>;\n\treadonly quote: DeepbookPoolCoin<Quote>;\n\treadonly tickSize: bigint;\n\treadonly lotSize: bigint;\n\treadonly minSize: bigint;\n\t/** Whitelisted? Defaults true for local deploy (no DEEP-burn). */\n\treadonly whitelisted?: boolean;\n\t/** Stable pool? Defaults false. */\n\treadonly stablePool?: boolean;\n\t/** Optional publisher-owned BalanceManager + seed orders for local demos. */\n\treadonly seed?: DeepbookPoolSeedLiquidity;\n}\n\n/** A resolved pool record on chain. */\nexport interface DeepbookPool {\n\treadonly name: string;\n\treadonly poolId: string;\n\treadonly base: string;\n\treadonly baseCoinType: string;\n\treadonly quote: string;\n\treadonly quoteCoinType: string;\n\treadonly tickSize: bigint;\n\treadonly lotSize: bigint;\n\treadonly minSize: bigint;\n}\n\n// ---------------------------------------------------------------------------\n// Member ref aliases — Direct Member Refs surface (locked API decision)\n// ---------------------------------------------------------------------------\n\n/** Account ref alias — the user passes the value returned by\n * `account('name')`. Resource-typed at the factory boundary so a\n * package-shaped ref is a TS error while preserving the literal\n * `account/<name>` id. */\nexport type AccountMemberAlias<Name extends string = string> = ResourceRef<\n\t`account/${Name}`,\n\tAccountValue\n>;\n\n/** Coin ref alias — the user passes `coin.fromPackage(...)`, `coin.known(...)`,\n * or `coin.builtin(...)`. */\nexport type CoinMemberAlias<Name extends string = string> = ResourceRef<`coin:${Name}`, CoinValue>;\n\n/** Local package ref alias for the published DeepBook package. The package\n * should capture `registryId` and `adminCapId` from its publish output. */\nexport type DeepbookPackageMember<Name extends string = string> = ResourceRef<\n\t`package:${Name}`,\n\tLocalPackageResolved\n>;\n\n/** Local package ref alias for the mock Pyth package used by local DeepBook. */\nexport type PythPackageMember<Name extends string = string> = ResourceRef<\n\t`package:${Name}`,\n\tLocalPackageResolved\n>;\n"],"mappings":";AAyBA,MAAa,mBAAmB,MAA+B;;;;AA6C/D,MAAa,oBAAqC,gBACjD,mEACA;AACD,MAAa,qBAAsC,gBAClD,mEACA;AACD,MAAa,qBAAsC,gBAClD,mEACA"}
1
+ {"version":3,"file":"types.mjs","names":[],"sources":["../../../src/plugins/deepbook/types.ts"],"sourcesContent":["// Deepbook plugin — public user-facing types.\n//\n// This file declares the DeepBook resolved-value and helper shapes.\n// The local factory in `index.ts` only accepts options that acquire\n// real behavior in the current implementation.\n//\n// Substrate-blindness rule: nothing here references a specific\n// account / coin / package member's resolved value — the references\n// flow in as Direct Member Refs (the locked Decision per\n// `feedback_no_inline_validation_in_parallel_agents` /\n// `project_devstack_api_design_locked_decisions`).\n\nimport type { AccountValue } from '../account/index.ts';\nimport type { CoinValue } from '../coin/index.ts';\nimport type { LocalPackageResolved } from '../package/index.ts';\nimport type { ResourceRef } from '../../api/define-plugin.ts';\n\n// ---------------------------------------------------------------------------\n// Pyth — internal sub-module shapes (NOT a top-level plugin per memory\n// `project_pyth_inside_deepbook`).\n// ---------------------------------------------------------------------------\n\n/** A Pyth price feed id — opaque 64-character hex string. */\nexport type PythPriceFeedId = string & { readonly __pythPriceFeedId: unique symbol };\n\nexport const pythPriceFeedId = (s: string): PythPriceFeedId => s as PythPriceFeedId;\n\n/** Pyth feed binding — symbol + feed id + initial price. */\nexport interface PythFeed {\n\treadonly symbol: string;\n\treadonly feedId: PythPriceFeedId;\n\t/** Initial price expressed in feed-native scale (Pyth conf is the\n\t * signed-int representation; bigint avoids float precision drift). */\n\treadonly initialPrice: bigint;\n\t/** Feed exponent. Defaults to -8, matching the DeepBook sandbox. */\n\treadonly expo?: number;\n\t/** Optional confidence interval. Defaults to 0 for deterministic local feeds. */\n\treadonly confidence?: bigint;\n\t/** Optional EMA price. Defaults to `initialPrice`. */\n\treadonly emaPrice?: bigint;\n}\n\n/** Pyth options. `package` and `pusher` are member refs, not magic strings. */\nexport interface PythOptions<\n\tPackage extends PythPackageMember = PythPackageMember,\n\tPusher extends AccountMemberAlias = AccountMemberAlias,\n> {\n\treadonly package: Package;\n\treadonly pusher: Pusher;\n\treadonly feeds: ReadonlyArray<PythFeed>;\n}\n\n/** Resolved Pyth handle exposed inside the deepbook resolved value. */\nexport interface PythHandle {\n\t/** Local sandbox Pyth has no Wormhole state; known deployments do. */\n\treadonly packageId: string | null;\n\treadonly stateId: string | null;\n\treadonly wormholeStateId: string | null;\n\treadonly feeds: ReadonlyArray<{\n\t\treadonly symbol: string;\n\t\treadonly feedId: PythPriceFeedId;\n\t\treadonly priceInfoObjectId: string;\n\t\treadonly price: bigint;\n\t\treadonly expo: number;\n\t}>;\n}\n\n/** Common Pyth price feed ids (subset; users pass their own as\n * needed). These are the well-known Pyth hex feed ids, NOT\n * per-stack derived. */\nexport const SUI_PRICE_FEED_ID: PythPriceFeedId = pythPriceFeedId(\n\t'23d7315113f5b1d3ba7a83604c44b94d79f4fd69af77f804fc7f920a6dc65744',\n);\nexport const USDC_PRICE_FEED_ID: PythPriceFeedId = pythPriceFeedId(\n\t'eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a',\n);\nexport const DEEP_PRICE_FEED_ID: PythPriceFeedId = pythPriceFeedId(\n\t'29bdd5248234e33bd93d3b81100b5fa32eaa5997843847e2c2cb16d7c6d9f7ff',\n);\n\n// ---------------------------------------------------------------------------\n// Pool spec\n// ---------------------------------------------------------------------------\n\n/** Coin handle used by local DeepBook pool specs. `key` is the SDK-facing\n * coin key (for example `DEEP` or `SUI`); `coin` is the devstack member ref\n * whose resolved value supplies the full Move coin type. */\nexport interface DeepbookPoolCoin<Coin extends CoinMemberAlias = CoinMemberAlias> {\n\treadonly key: string;\n\treadonly coin: Coin;\n\t/** SDK scalar for this coin. Defaults to the resolved coin decimals. */\n\treadonly scalar?: number;\n\t/** SDK address column. Defaults to the package id for package coins, or\n\t * the address portion of the resolved full coin type. */\n\treadonly address?: string;\n}\n\n/** Seed order placed after a local pool is created. Price and quantity use\n * DeepBook's on-chain units: `price` is quote-unit price and `quantity` is\n * base-asset quantity. */\nexport interface DeepbookPoolSeedOrder {\n\treadonly side: 'ask' | 'bid';\n\treadonly price: bigint;\n\treadonly quantity: bigint;\n\treadonly clientOrderId?: bigint;\n\treadonly payWithDeep?: boolean;\n}\n\n/** Optional local liquidity seed. Package coins with a generic funding\n * strategy are minted to the publisher before the seed transaction; otherwise\n * the publisher must already own the deposited coins. */\nexport interface DeepbookPoolSeedLiquidity {\n\treadonly baseAmount?: bigint;\n\treadonly quoteAmount?: bigint;\n\treadonly orders: ReadonlyArray<DeepbookPoolSeedOrder>;\n}\n\n/** Whitelisted pool to create at deploy time. `base` / `quote` are real coin\n * member refs so pool creation cannot race package/coin resolution. */\nexport interface DeepbookPoolSpec<\n\tBase extends CoinMemberAlias = CoinMemberAlias,\n\tQuote extends CoinMemberAlias = CoinMemberAlias,\n> {\n\treadonly name: string;\n\treadonly base: DeepbookPoolCoin<Base>;\n\treadonly quote: DeepbookPoolCoin<Quote>;\n\treadonly tickSize: bigint;\n\treadonly lotSize: bigint;\n\treadonly minSize: bigint;\n\t/** Whitelisted? Defaults true for local deploy (no DEEP-burn). */\n\treadonly whitelisted?: boolean;\n\t/** Stable pool? Defaults false. */\n\treadonly stablePool?: boolean;\n\t/** Optional publisher-owned BalanceManager + seed orders for local demos. */\n\treadonly seed?: DeepbookPoolSeedLiquidity;\n}\n\n/** A resolved pool record on chain. */\nexport interface DeepbookPool {\n\treadonly name: string;\n\treadonly poolId: string;\n\treadonly base: string;\n\treadonly baseCoinType: string;\n\treadonly quote: string;\n\treadonly quoteCoinType: string;\n\treadonly tickSize: bigint;\n\treadonly lotSize: bigint;\n\treadonly minSize: bigint;\n}\n\n// ---------------------------------------------------------------------------\n// Member ref aliases — Direct Member Refs surface (locked API decision)\n// ---------------------------------------------------------------------------\n\n/** Account ref alias — the user passes the value returned by\n * `account('name')`. Resource-typed at the factory boundary so a\n * package-shaped ref is a TS error while preserving the literal\n * `account/<name>` id. */\nexport type AccountMemberAlias<Name extends string = string> = ResourceRef<\n\t`account/${Name}`,\n\tAccountValue\n>;\n\n/** Coin ref alias — the user passes `coin.fromPackage(...)`, `coin.known(...)`,\n * or `coin.builtin(...)`. */\nexport type CoinMemberAlias<Name extends string = string> = ResourceRef<`coin:${Name}`, CoinValue>;\n\n/** Local package ref alias for the published DeepBook package. The package\n * should capture `registryId` and `adminCapId` from its publish output. */\nexport type DeepbookPackageMember<Name extends string = string> = ResourceRef<\n\t`package:${Name}`,\n\tLocalPackageResolved\n>;\n\n/** Local package ref alias for the mock Pyth package used by local DeepBook. */\nexport type PythPackageMember<Name extends string = string> = ResourceRef<\n\t`package:${Name}`,\n\tLocalPackageResolved\n>;\n"],"mappings":";AAyBA,MAAa,mBAAmB,MAA+B;;;;AA6C/D,MAAa,oBAAqC,gBACjD,kEACD;AACA,MAAa,qBAAsC,gBAClD,kEACD;AACA,MAAa,qBAAsC,gBAClD,kEACD"}
@@ -12,9 +12,9 @@ declare const FAUCET_CAPABILITY_KEY_PREFIX: "faucet:request";
12
12
  *
13
13
  * The generic contract lives in `contracts/faucet-strategy.ts` and
14
14
  * is parameterised over the strategy's error channel. The faucet
15
- * plugin narrows the alias to its tagged-error union so existing
16
- * dispatcher consumers (the strategy registry, request retry shim)
17
- * see the historical type unchanged.
15
+ * plugin narrows the alias to its tagged-error union so dispatcher
16
+ * consumers (the strategy registry, request retry shim) see a stable
17
+ * type.
18
18
  *
19
19
  * `amount` is the chain-native smallest unit (MIST for SUI). Some
20
20
  * backends (the local sui-faucet binary) grant a fixed amount per
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.mjs","names":[],"sources":["../../../src/plugins/faucet/dispatcher.ts"],"sourcesContent":["// Faucet capability-key encoding + dispatch contract.\n//\n// Architecture (distilled doc §Selection rule): the faucet plugin's\n// substrate-side dispatch is by capability key only — `faucet:request:<chainId>`.\n// The chain id is the substrate-level `NetworkConfig.chain` value\n// (e.g. `'sui:localnet'`, `'sui:testnet'`, `'sui:mainnet-fork@123'`).\n//\n// Sibling plugins (currently `sui`) reach in for `faucetCapabilityKey`\n// to register a faucet strategy keyed by chain id. The previous\n// `FaucetDispatcher` / `makeDispatcher` shape was a dead acquire-time\n// closure with no callers; the substrate-level\n// `substrate/runtime/strategy-registry/faucet-capability-for.ts` is the\n// canonical lookup helper now.\n//\n// The generic `FaucetStrategy<E>` contract lives in\n// `contracts/faucet-strategy.ts` (substrate-neutral, name-blind). This\n// file narrows the alias to the faucet plugin's tagged-error union so\n// strategy implementations (sui-local, future user strategies) close\n// over their own wire surface and satisfy this shape; the dispatcher\n// is implementation-blind.\n\nimport type { FaucetStrategy as FaucetStrategyContract } from '../../contracts/faucet-strategy.ts';\n\nimport type { FaucetBodyError, FaucetExhausted, FaucetUnreachable } from './errors.ts';\n\n/** Capability key prefix for a faucet request strategy. The full\n * key is `faucet:request:<chainId>`. */\nexport const FAUCET_CAPABILITY_KEY_PREFIX = 'faucet:request' as const;\n\n/** Build the full capability key for a chain. Literal-typed so the\n * downstream `StrategyFor<Caps, Key>` lookup picks the strategy\n * shape out of a tuple by name. */\nexport const faucetCapabilityKey = <ChainId extends string>(\n\tchainId: ChainId,\n): `${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${ChainId}` =>\n\t`${FAUCET_CAPABILITY_KEY_PREFIX}:${chainId}` as const;\n\n/**\n * Faucet strategy value. The dispatch surface is uniform across\n * strategies — the dispatcher doesn't know how a strategy delivers\n * coins, only how to invoke it.\n *\n * The generic contract lives in `contracts/faucet-strategy.ts` and\n * is parameterised over the strategy's error channel. The faucet\n * plugin narrows the alias to its tagged-error union so existing\n * dispatcher consumers (the strategy registry, request retry shim)\n * see the historical type unchanged.\n *\n * `amount` is the chain-native smallest unit (MIST for SUI). Some\n * backends (the local sui-faucet binary) grant a fixed amount per\n * request and IGNORE this value; the parameter is here for type\n * uniformity and to land correctly-denominated values in\n * `FaucetExhausted`.\n */\nexport type FaucetStrategy = FaucetStrategyContract<\n\tFaucetExhausted | FaucetUnreachable | FaucetBodyError\n>;\n"],"mappings":";;;AA2BA,MAAa,+BAA+B;;;;AAK5C,MAAa,uBACZ,YAEA,GAAG,6BAA6B,GAAG"}
1
+ {"version":3,"file":"dispatcher.mjs","names":[],"sources":["../../../src/plugins/faucet/dispatcher.ts"],"sourcesContent":["// Faucet capability-key encoding + dispatch contract.\n//\n// Architecture (distilled doc §Selection rule): the faucet plugin's\n// substrate-side dispatch is by capability key only — `faucet:request:<chainId>`.\n// The chain id is the substrate-level `NetworkConfig.chain` value\n// (e.g. `'sui:localnet'`, `'sui:testnet'`, `'sui:mainnet-fork@123'`).\n//\n// Sibling plugins (currently `sui`) reach in for `faucetCapabilityKey`\n// to register a faucet strategy keyed by chain id. The previous\n// `FaucetDispatcher` / `makeDispatcher` shape was a dead acquire-time\n// closure with no callers; the substrate-level\n// `substrate/runtime/strategy-registry/faucet-capability-for.ts` is the\n// canonical lookup helper now.\n//\n// The generic `FaucetStrategy<E>` contract lives in\n// `contracts/faucet-strategy.ts` (substrate-neutral, name-blind). This\n// file narrows the alias to the faucet plugin's tagged-error union so\n// strategy implementations (sui-local, future user strategies) close\n// over their own wire surface and satisfy this shape; the dispatcher\n// is implementation-blind.\n\nimport type { FaucetStrategy as FaucetStrategyContract } from '../../contracts/faucet-strategy.ts';\n\nimport type { FaucetBodyError, FaucetExhausted, FaucetUnreachable } from './errors.ts';\n\n/** Capability key prefix for a faucet request strategy. The full\n * key is `faucet:request:<chainId>`. */\nexport const FAUCET_CAPABILITY_KEY_PREFIX = 'faucet:request' as const;\n\n/** Build the full capability key for a chain. Literal-typed so the\n * downstream `StrategyFor<Caps, Key>` lookup picks the strategy\n * shape out of a tuple by name. */\nexport const faucetCapabilityKey = <ChainId extends string>(\n\tchainId: ChainId,\n): `${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${ChainId}` =>\n\t`${FAUCET_CAPABILITY_KEY_PREFIX}:${chainId}` as const;\n\n/**\n * Faucet strategy value. The dispatch surface is uniform across\n * strategies — the dispatcher doesn't know how a strategy delivers\n * coins, only how to invoke it.\n *\n * The generic contract lives in `contracts/faucet-strategy.ts` and\n * is parameterised over the strategy's error channel. The faucet\n * plugin narrows the alias to its tagged-error union so dispatcher\n * consumers (the strategy registry, request retry shim) see a stable\n * type.\n *\n * `amount` is the chain-native smallest unit (MIST for SUI). Some\n * backends (the local sui-faucet binary) grant a fixed amount per\n * request and IGNORE this value; the parameter is here for type\n * uniformity and to land correctly-denominated values in\n * `FaucetExhausted`.\n */\nexport type FaucetStrategy = FaucetStrategyContract<\n\tFaucetExhausted | FaucetUnreachable | FaucetBodyError\n>;\n"],"mappings":";;;AA2BA,MAAa,+BAA+B;;;;AAK5C,MAAa,uBACZ,YAEA,GAAG,6BAA6B,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/plugins/faucet/errors.ts"],"sourcesContent":["// Faucet plugin — typed errors.\n//\n// Architecture (distilled doc §Invariants / §Edge cases):\n// - A non-2xx HTTP status MUST raise (NOT be silently treated as\n// success). The Sui faucet binary binds its socket before its\n// validator can transfer coins → the warm-up window returns 5xx.\n// - A 200 OK body carrying `{ status: { Failure: ... } }` MUST\n// raise. The most load-bearing wire-level invariant: during\n// warm-up the faucet accepts requests it cannot execute, and\n// treating those bodies as success marks accounts funded when\n// no coins moved.\n// - Wall-clock budget exhaustion surfaces as `FaucetExhausted`. The\n// attempt-cap (`maxRetries` on the underlying retry schedule)\n// re-raises the LAST `FaucetUnreachable | FaucetBodyError` directly\n// — wrapping it in `FaucetExhausted` would just hide the wire-level\n// error the cap was triggered by. The wall-clock budget is the\n// dominant exit; the attempt cap exists as a safety net.\n//\n// Effect v4: tagged errors are plain interfaces; `Effect.catchTag` /\n// `catchTags` match on the `_tag` literal.\n\nimport { defineConfigError, type ConfigIssue } from '../../substrate/runtime/config-validation.ts';\n\n/**\n * Transport-level reachability failure. Raised when `fetch` itself\n * rejects (ECONNREFUSED, DNS failure, TLS failure, AbortSignal\n * timeout). Typical during cold boot before the faucet HTTP server\n * binds.\n *\n * The retry loop catches this; it surfaces to the caller only after\n * the wall-clock budget elapses.\n */\nexport interface FaucetUnreachable {\n\treadonly _tag: 'FaucetUnreachable';\n\treadonly url: string;\n\treadonly address: string;\n\treadonly amount: bigint;\n\treadonly message: string;\n\treadonly cause?: unknown;\n}\n\nexport const faucetUnreachable = (parts: Omit<FaucetUnreachable, '_tag'>): FaucetUnreachable => ({\n\t_tag: 'FaucetUnreachable',\n\t...parts,\n});\n\n/**\n * Wall-clock budget exhaustion. The retry loop did not land a\n * successful attempt within the configured `timeoutMs`.\n *\n * The attempt-count cap (`maxRetries` on the schedule) does NOT\n * surface as `FaucetExhausted` — when the retry schedule exhausts,\n * Effect re-raises the LAST `FaucetUnreachable | FaucetBodyError`\n * verbatim, which is more informative than a wrapped budget message.\n * Callers handling `FaucetUnreachable | FaucetBodyError` already see\n * the right wire-level cause.\n *\n * Carries the last underlying cause so pretty-error rendering can\n * show what was actually failing instead of just the budget message.\n */\nexport interface FaucetExhausted {\n\treadonly _tag: 'FaucetExhausted';\n\treadonly url: string;\n\treadonly address: string;\n\treadonly amount: bigint;\n\treadonly attempts: number;\n\treadonly message: string;\n\treadonly lastCause?: unknown;\n}\n\nexport const faucetExhausted = (parts: Omit<FaucetExhausted, '_tag'>): FaucetExhausted => ({\n\t_tag: 'FaucetExhausted',\n\t...parts,\n});\n\n/**\n * Body-level Failure on a 200 OK. The load-bearing invariant: the\n * Sui faucet returns `{ status: { Failure: ... } }` when it accepted\n * the request but couldn't execute the underlying tx (gas object\n * stale, mid-genesis, consensus hiccup).\n *\n * Also covers JSON-parse failures on a 200 body and other malformed-\n * response cases — anything that means \"the HTTP layer says OK but\n * the body does not confirm a successful transfer\". Caller code MUST\n * treat this as a failed funding, not a silent success.\n */\nexport interface FaucetBodyError {\n\treadonly _tag: 'FaucetBodyError';\n\treadonly url: string;\n\treadonly address: string;\n\treadonly amount: bigint;\n\treadonly status: number;\n\treadonly reason: 'failure-status' | 'invalid-json';\n\treadonly message: string;\n\t/** The raw body payload (truncated where necessary) for diagnostics. */\n\treadonly bodySnippet?: string;\n}\n\nexport const faucetBodyError = (parts: Omit<FaucetBodyError, '_tag'>): FaucetBodyError => ({\n\t_tag: 'FaucetBodyError',\n\t...parts,\n});\n\nexport interface FaucetConfigError extends ConfigIssue {\n\treadonly _tag: 'FaucetConfigError';\n}\n\nexport const faucetConfigError = defineConfigError('FaucetConfigError');\n\n/** Union of every error a faucet caller may encounter. */\nexport type FaucetError =\n\t| FaucetUnreachable\n\t| FaucetExhausted\n\t| FaucetBodyError\n\t| FaucetConfigError;\n"],"mappings":";;AAyCA,MAAa,qBAAqB,WAA+D;CAChG,MAAM;CACN,GAAG;CACH;AA0BD,MAAa,mBAAmB,WAA2D;CAC1F,MAAM;CACN,GAAG;CACH;AAyBD,MAAa,mBAAmB,WAA2D;CAC1F,MAAM;CACN,GAAG;CACH;AAMgC,kBAAkB,oBAAoB"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/plugins/faucet/errors.ts"],"sourcesContent":["// Faucet plugin — typed errors.\n//\n// Architecture (distilled doc §Invariants / §Edge cases):\n// - A non-2xx HTTP status MUST raise (NOT be silently treated as\n// success). The Sui faucet binary binds its socket before its\n// validator can transfer coins → the warm-up window returns 5xx.\n// - A 200 OK body carrying `{ status: { Failure: ... } }` MUST\n// raise. The most load-bearing wire-level invariant: during\n// warm-up the faucet accepts requests it cannot execute, and\n// treating those bodies as success marks accounts funded when\n// no coins moved.\n// - Wall-clock budget exhaustion surfaces as `FaucetExhausted`. The\n// attempt-cap (`maxRetries` on the underlying retry schedule)\n// re-raises the LAST `FaucetUnreachable | FaucetBodyError` directly\n// — wrapping it in `FaucetExhausted` would just hide the wire-level\n// error the cap was triggered by. The wall-clock budget is the\n// dominant exit; the attempt cap exists as a safety net.\n//\n// Effect v4: tagged errors are plain interfaces; `Effect.catchTag` /\n// `catchTags` match on the `_tag` literal.\n\nimport { defineConfigError, type ConfigIssue } from '../../substrate/runtime/config-validation.ts';\n\n/**\n * Transport-level reachability failure. Raised when `fetch` itself\n * rejects (ECONNREFUSED, DNS failure, TLS failure, AbortSignal\n * timeout). Typical during cold boot before the faucet HTTP server\n * binds.\n *\n * The retry loop catches this; it surfaces to the caller only after\n * the wall-clock budget elapses.\n */\nexport interface FaucetUnreachable {\n\treadonly _tag: 'FaucetUnreachable';\n\treadonly url: string;\n\treadonly address: string;\n\treadonly amount: bigint;\n\treadonly message: string;\n\treadonly cause?: unknown;\n}\n\nexport const faucetUnreachable = (parts: Omit<FaucetUnreachable, '_tag'>): FaucetUnreachable => ({\n\t_tag: 'FaucetUnreachable',\n\t...parts,\n});\n\n/**\n * Wall-clock budget exhaustion. The retry loop did not land a\n * successful attempt within the configured `timeoutMs`.\n *\n * The attempt-count cap (`maxRetries` on the schedule) does NOT\n * surface as `FaucetExhausted` — when the retry schedule exhausts,\n * Effect re-raises the LAST `FaucetUnreachable | FaucetBodyError`\n * verbatim, which is more informative than a wrapped budget message.\n * Callers handling `FaucetUnreachable | FaucetBodyError` already see\n * the right wire-level cause.\n *\n * Carries the last underlying cause so pretty-error rendering can\n * show what was actually failing instead of just the budget message.\n */\nexport interface FaucetExhausted {\n\treadonly _tag: 'FaucetExhausted';\n\treadonly url: string;\n\treadonly address: string;\n\treadonly amount: bigint;\n\treadonly attempts: number;\n\treadonly message: string;\n\treadonly lastCause?: unknown;\n}\n\nexport const faucetExhausted = (parts: Omit<FaucetExhausted, '_tag'>): FaucetExhausted => ({\n\t_tag: 'FaucetExhausted',\n\t...parts,\n});\n\n/**\n * Body-level Failure on a 200 OK. The load-bearing invariant: the\n * Sui faucet returns `{ status: { Failure: ... } }` when it accepted\n * the request but couldn't execute the underlying tx (gas object\n * stale, mid-genesis, consensus hiccup).\n *\n * Also covers JSON-parse failures on a 200 body and other malformed-\n * response cases — anything that means \"the HTTP layer says OK but\n * the body does not confirm a successful transfer\". Caller code MUST\n * treat this as a failed funding, not a silent success.\n */\nexport interface FaucetBodyError {\n\treadonly _tag: 'FaucetBodyError';\n\treadonly url: string;\n\treadonly address: string;\n\treadonly amount: bigint;\n\treadonly status: number;\n\treadonly reason: 'failure-status' | 'invalid-json';\n\treadonly message: string;\n\t/** The raw body payload (truncated where necessary) for diagnostics. */\n\treadonly bodySnippet?: string;\n}\n\nexport const faucetBodyError = (parts: Omit<FaucetBodyError, '_tag'>): FaucetBodyError => ({\n\t_tag: 'FaucetBodyError',\n\t...parts,\n});\n\nexport interface FaucetConfigError extends ConfigIssue {\n\treadonly _tag: 'FaucetConfigError';\n}\n\nexport const faucetConfigError = defineConfigError('FaucetConfigError');\n\n/** Union of every error a faucet caller may encounter. */\nexport type FaucetError = FaucetUnreachable | FaucetExhausted | FaucetBodyError | FaucetConfigError;\n"],"mappings":";;AAyCA,MAAa,qBAAqB,WAA+D;CAChG,MAAM;CACN,GAAG;AACJ;AA0BA,MAAa,mBAAmB,WAA2D;CAC1F,MAAM;CACN,GAAG;AACJ;AAyBA,MAAa,mBAAmB,WAA2D;CAC1F,MAAM;CACN,GAAG;AACJ;AAMiC,kBAAkB,mBAAmB"}
@@ -1,6 +1,5 @@
1
1
  import { FAUCET_HTTP_RETRY_PROFILE, makeExponentialRetrySchedule } from "../../substrate/runtime/retry-policy.mjs";
2
2
  import { faucetBodyError, faucetExhausted, faucetUnreachable } from "./errors.mjs";
3
- import { FaucetSpans } from "./spans.mjs";
4
3
  import { Effect, Ref } from "effect";
5
4
  //#region src/plugins/faucet/http.ts
6
5
  /** Retry attempts cap. Paired with the wall-clock budget below: at
@@ -93,7 +92,7 @@ const requestFundsOnce = (opts) => Effect.gen(function* () {
93
92
  bodySnippet: payload
94
93
  }));
95
94
  }
96
- }).pipe(Effect.withSpan("devstack.plugin.faucet.requestFundsOnce"));
95
+ });
97
96
  /**
98
97
  * Retry-wrapped POST. Combines `requestFundsOnce` with a jittered
99
98
  * exponential schedule and a wall-clock budget; on exhaustion raises
@@ -107,13 +106,6 @@ const requestFundsWithRetry = (opts) => Effect.gen(function* () {
107
106
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
108
107
  const maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
109
108
  const initialDelayMs = opts.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;
110
- yield* Effect.annotateCurrentSpan({
111
- [FaucetSpans.url]: opts.faucetUrl,
112
- [FaucetSpans.address]: opts.address,
113
- [FaucetSpans.amount]: opts.amount.toString(),
114
- [FaucetSpans.budgetMs]: timeoutMs,
115
- [FaucetSpans.maxAttempts]: maxAttempts
116
- });
117
109
  const attempts = yield* Ref.make(0);
118
110
  const lastError = yield* Ref.make(void 0);
119
111
  yield* requestFundsOnce(opts).pipe(Effect.tapError((err) => Effect.gen(function* () {
@@ -139,7 +131,7 @@ const requestFundsWithRetry = (opts) => Effect.gen(function* () {
139
131
  }));
140
132
  })
141
133
  }));
142
- }).pipe(Effect.withSpan("devstack.plugin.faucet.requestFundsWithRetry"));
134
+ });
143
135
  //#endregion
144
136
  export { requestFundsWithRetry };
145
137
 
@@ -1 +1 @@
1
- {"version":3,"file":"http.mjs","names":[],"sources":["../../../src/plugins/faucet/http.ts"],"sourcesContent":["// Faucet HTTP wrapper.\n//\n// One module per the distilled-doc \"collapse engine/service split\"\n// guidance — the HTTP helper is the only wire-level path for any\n// HTTP-based faucet strategy, and it lives WITH the plugin instead\n// of in a sibling engine module.\n//\n// Wire-level invariants (distilled doc §Invariants):\n//\n// 1. A non-2xx HTTP status MUST raise (NOT be treated as success).\n// The Sui faucet binds its TCP socket before its validator can\n// transfer coins — the warm-up window returns 5xx and must be\n// retried, not silently absorbed.\n//\n// 2. A 200 OK body with `{ status: { Failure: ... } }` MUST raise.\n// The single most load-bearing invariant in this module: during\n// warm-up the faucet ACCEPTS requests it cannot execute (gas\n// object stale, consensus hiccup, mid-genesis). Treating those\n// bodies as success marks accounts funded when no coins moved.\n//\n// 3. Per-fetch deadline is short relative to wall-clock budget\n// (5s vs 90s). The faucet's internal retries can block one POST\n// for ~60s; capping each POST lets the outer retry loop hammer\n// quickly and land on the first attempt after the chain catches\n// up.\n//\n// 4. Retry MUST jitter. Pre-jitter, parallel-account retries\n// synchronized on the wall-clock tick and thundering-herded the\n// faucet.\n//\n// The shared funds-transferable barrier (invariant #5 in the doc)\n// is owned by Sui and surfaced directly via\n// `resolved.waitForTransactionsReady.wait`; consumers call it before\n// the FIRST POST. This module is barrier-agnostic: it assumes callers\n// gate themselves.\n//\n// HTTP transport: `globalThis.fetch` + `AbortSignal.timeout`. Kept\n// direct rather than going through `@effect/platform-node`'s\n// `HttpClient`: this body owns the wire-level contract (status,\n// body-Failure detection, per-fetch deadline) and adding the Effect\n// HttpClient layer here would not change behaviour at any of the\n// invariants above.\n//\n// The substrate's `HttpProbes.waitForHttpEndpoint(...)` is for *readiness probes*\n// (poll a GET until ready), not one-shot POST + body-shape validation.\n// The wire-level contract above (non-2xx raise, body-Failure raise,\n// short per-fetch deadline relative to retry budget) is owned here.\n// The retry SCHEDULE shape, however, IS substrate-supplied — it\n// composes `makeExponentialRetrySchedule` from `retry-policy.ts`\n// and reads its constants from `FAUCET_HTTP_RETRY_PROFILE`.\n\nimport { Effect, Ref } from 'effect';\n\nimport {\n\tFAUCET_HTTP_RETRY_PROFILE,\n\tmakeExponentialRetrySchedule,\n} from '../../substrate/runtime/retry-policy.ts';\nimport {\n\tfaucetBodyError,\n\tfaucetExhausted,\n\tfaucetUnreachable,\n\ttype FaucetBodyError,\n\ttype FaucetExhausted,\n\ttype FaucetUnreachable,\n} from './errors.ts';\nimport { FaucetSpans } from './spans.ts';\n\n// ---------------------------------------------------------------------------\n// Default retry profile\n// ---------------------------------------------------------------------------\n\n/** Retry attempts cap. Paired with the wall-clock budget below: at\n * 500ms initial × 1.5 backoff × jitter, 15 attempts saturates well\n * before 90s, so the wall-clock check is the dominant exit. */\nexport const DEFAULT_MAX_ATTEMPTS = FAUCET_HTTP_RETRY_PROFILE.maxAttempts;\n\n/** Initial delay between retries (ms). Subsequent delays grow by\n * the `BACKOFF_FACTOR`. */\nexport const DEFAULT_INITIAL_DELAY_MS = FAUCET_HTTP_RETRY_PROFILE.initialDelayMs;\n\n/** Wall-clock budget for the WHOLE request including all retries.\n * Sized for a cold sui-localnet boot — the validator binary needs\n * ~30–60s after its HTTP socket opens before it can submit txs. */\nexport const DEFAULT_TIMEOUT_MS = FAUCET_HTTP_RETRY_PROFILE.wallClockBudgetMs;\n\n/** Exponential growth factor between retries. */\nexport const BACKOFF_FACTOR = FAUCET_HTTP_RETRY_PROFILE.backoffFactor;\n\n/** Per-POST hard deadline. The sui-faucet binary internally retries\n * the underlying SUI transfer tx twice with ~30s timeouts; a single\n * cold-chain request blocks ~60s before returning 500. Capping each\n * POST at 5s lets the outer retry loop hammer quickly — when the\n * chain catches up the next attempt lands in <1s. Successful\n * warm-faucet calls return well under 1s, so 5s is a safe ceiling. */\nexport const DEFAULT_FETCH_DEADLINE_MS = FAUCET_HTTP_RETRY_PROFILE.perRequestDeadlineMs;\n\n// ---------------------------------------------------------------------------\n// Single-shot POST + body parser\n// ---------------------------------------------------------------------------\n\n/** Configuration for a single faucet POST. */\nexport interface FaucetPostOptions {\n\t/** Base URL — e.g. `http://localhost:9123` or\n\t * `https://faucet.testnet.sui.io`. Path is appended internally. */\n\treadonly faucetUrl: string;\n\t/** Recipient address. */\n\treadonly address: string;\n\t/** Amount in the strategy-native unit (carried through to error\n\t * payloads). The Sui HTTP faucet itself ignores `amount` and\n\t * funds a fixed grant per request; the field is here so\n\t * exhaustion errors carry the unit-correct value. */\n\treadonly amount: bigint;\n\t/** Endpoint path (default `/v2/gas`). Live faucets sometimes\n\t * diverge — `/gas` on older endpoints. */\n\treadonly path?: string;\n\t/** Per-fetch deadline in ms (default `DEFAULT_FETCH_DEADLINE_MS`). */\n\treadonly fetchDeadlineMs?: number;\n}\n\n/**\n * One-shot POST: send + check status + parse body + check body\n * status. Exported so tests can pin the body-Failure detection\n * without paying the retry / wall-clock cost of the wrapper. Production\n * callers go through `requestFundsWithRetry`.\n *\n * Failure modes raised:\n * - `FaucetUnreachable` on transport failure (fetch reject, abort\n * timeout, network error).\n * - `FaucetBodyError` on non-2xx, body Failure status, or\n * unparseable JSON. The doc-load-bearing distinction.\n */\nexport const requestFundsOnce = (\n\topts: FaucetPostOptions,\n): Effect.Effect<void, FaucetUnreachable | FaucetBodyError> =>\n\tEffect.gen(function* () {\n\t\tconst path = opts.path ?? '/v2/gas';\n\t\tconst endpoint = `${opts.faucetUrl}${path}`;\n\t\tconst deadlineMs = opts.fetchDeadlineMs ?? DEFAULT_FETCH_DEADLINE_MS;\n\n\t\tconst response = yield* Effect.tryPromise({\n\t\t\ttry: () =>\n\t\t\t\tfetch(endpoint, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'content-type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tFixedAmountRequest: { recipient: opts.address },\n\t\t\t\t\t}),\n\t\t\t\t\tsignal: AbortSignal.timeout(deadlineMs),\n\t\t\t\t}),\n\t\t\tcatch: (cause) =>\n\t\t\t\tfaucetUnreachable({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tmessage: `faucet POST to ${endpoint} failed (transport)`,\n\t\t\t\t\tcause,\n\t\t\t\t}),\n\t\t});\n\n\t\t// Invariant #1: non-2xx MUST raise. We read the body\n\t\t// best-effort so the diagnostic carries the upstream reason\n\t\t// instead of just a numeric status.\n\t\tif (!response.ok) {\n\t\t\tconst body = yield* Effect.tryPromise({\n\t\t\t\ttry: () => response.text(),\n\t\t\t\tcatch: () => undefined,\n\t\t\t}).pipe(Effect.orElseSucceed(() => undefined as string | undefined));\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tfaucetBodyError({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\treason: 'failure-status',\n\t\t\t\t\tmessage: `faucet returned ${response.status} ${response.statusText}`,\n\t\t\t\t\t...(body !== undefined && body.length > 0 ? { bodySnippet: body } : {}),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// Invariant #2: 200 OK with body-level Failure MUST raise.\n\t\t// We treat JSON-parse failure as an `invalid-json` raise too —\n\t\t// during cold boot the faucet very occasionally writes an empty\n\t\t// or truncated body before it's ready, and silently accepting\n\t\t// that mirrors the bug we're explicitly guarding against.\n\t\tconst body = (yield* Effect.tryPromise({\n\t\t\ttry: () => response.json() as Promise<unknown>,\n\t\t\tcatch: (cause) =>\n\t\t\t\tfaucetBodyError({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\treason: 'invalid-json',\n\t\t\t\t\tmessage: 'faucet response was not valid JSON',\n\t\t\t\t\t...(cause !== undefined ? { bodySnippet: String(cause) } : {}),\n\t\t\t\t}),\n\t\t})) as { status?: unknown };\n\n\t\tconst status = body.status;\n\t\tif (typeof status === 'object' && status !== null && 'Failure' in status) {\n\t\t\tconst payload = JSON.stringify((status as { Failure: unknown }).Failure);\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tfaucetBodyError({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\treason: 'failure-status',\n\t\t\t\t\tmessage: `faucet body reported Failure: ${payload}`,\n\t\t\t\t\tbodySnippet: payload,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}).pipe(Effect.withSpan('devstack.plugin.faucet.requestFundsOnce'));\n\n// ---------------------------------------------------------------------------\n// Retry wrapper\n// ---------------------------------------------------------------------------\n\n/** Configuration for a retry-wrapped faucet POST. */\nexport interface RetryOptions extends FaucetPostOptions {\n\t/** Wall-clock budget for the WHOLE request including retries.\n\t * Default `DEFAULT_TIMEOUT_MS`. CI configs pointing at a clearly\n\t * broken faucet can lower this to fail-fast. */\n\treadonly timeoutMs?: number;\n\t/** Max attempts cap. Default `DEFAULT_MAX_ATTEMPTS`. */\n\treadonly maxAttempts?: number;\n\t/** Initial inter-attempt delay (ms). Default\n\t * `DEFAULT_INITIAL_DELAY_MS`. */\n\treadonly initialDelayMs?: number;\n\t/** Optional per-attempt callback. Lets callers surface \"waiting\n\t * on faucet (attempt N)\" in a TUI row so cold-start doesn't look\n\t * like a hang. */\n\treadonly onAttempt?: (\n\t\tattempt: number,\n\t\terror: FaucetUnreachable | FaucetBodyError,\n\t) => Effect.Effect<void>;\n}\n\n/**\n * Retry-wrapped POST. Combines `requestFundsOnce` with a jittered\n * exponential schedule and a wall-clock budget; on exhaustion raises\n * `FaucetExhausted` carrying the last underlying cause.\n *\n * Invariant #4 (jitter): handled by the schedule above. Invariant #3\n * (per-fetch deadline): handled by `requestFundsOnce`'s\n * `AbortSignal.timeout`.\n */\nexport const requestFundsWithRetry = (\n\topts: RetryOptions,\n): Effect.Effect<void, FaucetExhausted | FaucetUnreachable | FaucetBodyError> =>\n\tEffect.gen(function* () {\n\t\tconst timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\t\tconst maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n\t\tconst initialDelayMs = opts.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n\n\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t[FaucetSpans.url]: opts.faucetUrl,\n\t\t\t[FaucetSpans.address]: opts.address,\n\t\t\t[FaucetSpans.amount]: opts.amount.toString(),\n\t\t\t[FaucetSpans.budgetMs]: timeoutMs,\n\t\t\t[FaucetSpans.maxAttempts]: maxAttempts,\n\t\t});\n\n\t\tconst attempts = yield* Ref.make(0);\n\t\tconst lastError = yield* Ref.make<FaucetUnreachable | FaucetBodyError | undefined>(undefined);\n\n\t\tconst wrapped = requestFundsOnce(opts).pipe(\n\t\t\tEffect.tapError((err) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst n = yield* Ref.updateAndGet(attempts, (x) => x + 1);\n\t\t\t\t\tyield* Ref.set(lastError, err);\n\t\t\t\t\tif (opts.onAttempt !== undefined) {\n\t\t\t\t\t\tyield* opts.onAttempt(n, err);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\n\t\tyield* wrapped.pipe(\n\t\t\tEffect.retry(\n\t\t\t\tmakeExponentialRetrySchedule({\n\t\t\t\t\tinitialDelayMs,\n\t\t\t\t\tmaxRetries: maxAttempts,\n\t\t\t\t\tfactor: BACKOFF_FACTOR,\n\t\t\t\t}),\n\t\t\t),\n\t\t\tEffect.timeoutOrElse({\n\t\t\t\tduration: `${timeoutMs} millis`,\n\t\t\t\torElse: () =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst n = yield* Ref.get(attempts);\n\t\t\t\t\t\tconst last = yield* Ref.get(lastError);\n\t\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\t\tfaucetExhausted({\n\t\t\t\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\t\t\t\taddress: opts.address,\n\t\t\t\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\t\t\t\tattempts: n,\n\t\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\t\t`faucet did not accept request within ${timeoutMs}ms ` +\n\t\t\t\t\t\t\t\t\t`(${n} attempts; last: ${last?.message ?? 'unknown'})`,\n\t\t\t\t\t\t\t\tlastCause: last,\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}),\n\t\t);\n\t}).pipe(Effect.withSpan('devstack.plugin.faucet.requestFundsWithRetry'));\n"],"mappings":"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"}
1
+ {"version":3,"file":"http.mjs","names":[],"sources":["../../../src/plugins/faucet/http.ts"],"sourcesContent":["// Faucet HTTP wrapper.\n//\n// One module per the distilled-doc \"collapse engine/service split\"\n// guidance — the HTTP helper is the only wire-level path for any\n// HTTP-based faucet strategy, and it lives WITH the plugin instead\n// of in a sibling engine module.\n//\n// Wire-level invariants (distilled doc §Invariants):\n//\n// 1. A non-2xx HTTP status MUST raise (NOT be treated as success).\n// The Sui faucet binds its TCP socket before its validator can\n// transfer coins — the warm-up window returns 5xx and must be\n// retried, not silently absorbed.\n//\n// 2. A 200 OK body with `{ status: { Failure: ... } }` MUST raise.\n// The single most load-bearing invariant in this module: during\n// warm-up the faucet ACCEPTS requests it cannot execute (gas\n// object stale, consensus hiccup, mid-genesis). Treating those\n// bodies as success marks accounts funded when no coins moved.\n//\n// 3. Per-fetch deadline is short relative to wall-clock budget\n// (5s vs 90s). The faucet's internal retries can block one POST\n// for ~60s; capping each POST lets the outer retry loop hammer\n// quickly and land on the first attempt after the chain catches\n// up.\n//\n// 4. Retry MUST jitter. Pre-jitter, parallel-account retries\n// synchronized on the wall-clock tick and thundering-herded the\n// faucet.\n//\n// The shared funds-transferable barrier (invariant #5 in the doc)\n// is owned by Sui and surfaced directly via\n// `resolved.waitForTransactionsReady.wait`; consumers call it before\n// the FIRST POST. This module is barrier-agnostic: it assumes callers\n// gate themselves.\n//\n// HTTP transport: `globalThis.fetch` + `AbortSignal.timeout`. Kept\n// direct rather than going through `@effect/platform-node`'s\n// `HttpClient`: this body owns the wire-level contract (status,\n// body-Failure detection, per-fetch deadline) and adding the Effect\n// HttpClient layer here would not change behaviour at any of the\n// invariants above.\n//\n// The substrate's `HttpProbes.waitForHttpEndpoint(...)` is for *readiness probes*\n// (poll a GET until ready), not one-shot POST + body-shape validation.\n// The wire-level contract above (non-2xx raise, body-Failure raise,\n// short per-fetch deadline relative to retry budget) is owned here.\n// The retry SCHEDULE shape, however, IS substrate-supplied — it\n// composes `makeExponentialRetrySchedule` from `retry-policy.ts`\n// and reads its constants from `FAUCET_HTTP_RETRY_PROFILE`.\n\nimport { Effect, Ref } from 'effect';\n\nimport {\n\tFAUCET_HTTP_RETRY_PROFILE,\n\tmakeExponentialRetrySchedule,\n} from '../../substrate/runtime/retry-policy.ts';\nimport {\n\tfaucetBodyError,\n\tfaucetExhausted,\n\tfaucetUnreachable,\n\ttype FaucetBodyError,\n\ttype FaucetExhausted,\n\ttype FaucetUnreachable,\n} from './errors.ts';\n\n// ---------------------------------------------------------------------------\n// Default retry profile\n// ---------------------------------------------------------------------------\n\n/** Retry attempts cap. Paired with the wall-clock budget below: at\n * 500ms initial × 1.5 backoff × jitter, 15 attempts saturates well\n * before 90s, so the wall-clock check is the dominant exit. */\nexport const DEFAULT_MAX_ATTEMPTS = FAUCET_HTTP_RETRY_PROFILE.maxAttempts;\n\n/** Initial delay between retries (ms). Subsequent delays grow by\n * the `BACKOFF_FACTOR`. */\nexport const DEFAULT_INITIAL_DELAY_MS = FAUCET_HTTP_RETRY_PROFILE.initialDelayMs;\n\n/** Wall-clock budget for the WHOLE request including all retries.\n * Sized for a cold sui-localnet boot — the validator binary needs\n * ~30–60s after its HTTP socket opens before it can submit txs. */\nexport const DEFAULT_TIMEOUT_MS = FAUCET_HTTP_RETRY_PROFILE.wallClockBudgetMs;\n\n/** Exponential growth factor between retries. */\nexport const BACKOFF_FACTOR = FAUCET_HTTP_RETRY_PROFILE.backoffFactor;\n\n/** Per-POST hard deadline. The sui-faucet binary internally retries\n * the underlying SUI transfer tx twice with ~30s timeouts; a single\n * cold-chain request blocks ~60s before returning 500. Capping each\n * POST at 5s lets the outer retry loop hammer quickly — when the\n * chain catches up the next attempt lands in <1s. Successful\n * warm-faucet calls return well under 1s, so 5s is a safe ceiling. */\nexport const DEFAULT_FETCH_DEADLINE_MS = FAUCET_HTTP_RETRY_PROFILE.perRequestDeadlineMs;\n\n// ---------------------------------------------------------------------------\n// Single-shot POST + body parser\n// ---------------------------------------------------------------------------\n\n/** Configuration for a single faucet POST. */\nexport interface FaucetPostOptions {\n\t/** Base URL — e.g. `http://localhost:9123` or\n\t * `https://faucet.testnet.sui.io`. Path is appended internally. */\n\treadonly faucetUrl: string;\n\t/** Recipient address. */\n\treadonly address: string;\n\t/** Amount in the strategy-native unit (carried through to error\n\t * payloads). The Sui HTTP faucet itself ignores `amount` and\n\t * funds a fixed grant per request; the field is here so\n\t * exhaustion errors carry the unit-correct value. */\n\treadonly amount: bigint;\n\t/** Endpoint path (default `/v2/gas`). Live faucets sometimes\n\t * diverge — `/gas` on older endpoints. */\n\treadonly path?: string;\n\t/** Per-fetch deadline in ms (default `DEFAULT_FETCH_DEADLINE_MS`). */\n\treadonly fetchDeadlineMs?: number;\n}\n\n/**\n * One-shot POST: send + check status + parse body + check body\n * status. Exported so tests can pin the body-Failure detection\n * without paying the retry / wall-clock cost of the wrapper. Production\n * callers go through `requestFundsWithRetry`.\n *\n * Failure modes raised:\n * - `FaucetUnreachable` on transport failure (fetch reject, abort\n * timeout, network error).\n * - `FaucetBodyError` on non-2xx, body Failure status, or\n * unparseable JSON. The doc-load-bearing distinction.\n */\nexport const requestFundsOnce = (\n\topts: FaucetPostOptions,\n): Effect.Effect<void, FaucetUnreachable | FaucetBodyError> =>\n\tEffect.gen(function* () {\n\t\tconst path = opts.path ?? '/v2/gas';\n\t\tconst endpoint = `${opts.faucetUrl}${path}`;\n\t\tconst deadlineMs = opts.fetchDeadlineMs ?? DEFAULT_FETCH_DEADLINE_MS;\n\n\t\tconst response = yield* Effect.tryPromise({\n\t\t\ttry: () =>\n\t\t\t\tfetch(endpoint, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'content-type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tFixedAmountRequest: { recipient: opts.address },\n\t\t\t\t\t}),\n\t\t\t\t\tsignal: AbortSignal.timeout(deadlineMs),\n\t\t\t\t}),\n\t\t\tcatch: (cause) =>\n\t\t\t\tfaucetUnreachable({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tmessage: `faucet POST to ${endpoint} failed (transport)`,\n\t\t\t\t\tcause,\n\t\t\t\t}),\n\t\t});\n\n\t\t// Invariant #1: non-2xx MUST raise. We read the body\n\t\t// best-effort so the diagnostic carries the upstream reason\n\t\t// instead of just a numeric status.\n\t\tif (!response.ok) {\n\t\t\tconst body = yield* Effect.tryPromise({\n\t\t\t\ttry: () => response.text(),\n\t\t\t\tcatch: () => undefined,\n\t\t\t}).pipe(Effect.orElseSucceed(() => undefined as string | undefined));\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tfaucetBodyError({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\treason: 'failure-status',\n\t\t\t\t\tmessage: `faucet returned ${response.status} ${response.statusText}`,\n\t\t\t\t\t...(body !== undefined && body.length > 0 ? { bodySnippet: body } : {}),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// Invariant #2: 200 OK with body-level Failure MUST raise.\n\t\t// We treat JSON-parse failure as an `invalid-json` raise too —\n\t\t// during cold boot the faucet very occasionally writes an empty\n\t\t// or truncated body before it's ready, and silently accepting\n\t\t// that mirrors the bug we're explicitly guarding against.\n\t\tconst body = (yield* Effect.tryPromise({\n\t\t\ttry: () => response.json() as Promise<unknown>,\n\t\t\tcatch: (cause) =>\n\t\t\t\tfaucetBodyError({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\treason: 'invalid-json',\n\t\t\t\t\tmessage: 'faucet response was not valid JSON',\n\t\t\t\t\t...(cause !== undefined ? { bodySnippet: String(cause) } : {}),\n\t\t\t\t}),\n\t\t})) as { status?: unknown };\n\n\t\tconst status = body.status;\n\t\tif (typeof status === 'object' && status !== null && 'Failure' in status) {\n\t\t\tconst payload = JSON.stringify((status as { Failure: unknown }).Failure);\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tfaucetBodyError({\n\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\taddress: opts.address,\n\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\treason: 'failure-status',\n\t\t\t\t\tmessage: `faucet body reported Failure: ${payload}`,\n\t\t\t\t\tbodySnippet: payload,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t});\n\n// ---------------------------------------------------------------------------\n// Retry wrapper\n// ---------------------------------------------------------------------------\n\n/** Configuration for a retry-wrapped faucet POST. */\nexport interface RetryOptions extends FaucetPostOptions {\n\t/** Wall-clock budget for the WHOLE request including retries.\n\t * Default `DEFAULT_TIMEOUT_MS`. CI configs pointing at a clearly\n\t * broken faucet can lower this to fail-fast. */\n\treadonly timeoutMs?: number;\n\t/** Max attempts cap. Default `DEFAULT_MAX_ATTEMPTS`. */\n\treadonly maxAttempts?: number;\n\t/** Initial inter-attempt delay (ms). Default\n\t * `DEFAULT_INITIAL_DELAY_MS`. */\n\treadonly initialDelayMs?: number;\n\t/** Optional per-attempt callback. Lets callers surface \"waiting\n\t * on faucet (attempt N)\" in a TUI row so cold-start doesn't look\n\t * like a hang. */\n\treadonly onAttempt?: (\n\t\tattempt: number,\n\t\terror: FaucetUnreachable | FaucetBodyError,\n\t) => Effect.Effect<void>;\n}\n\n/**\n * Retry-wrapped POST. Combines `requestFundsOnce` with a jittered\n * exponential schedule and a wall-clock budget; on exhaustion raises\n * `FaucetExhausted` carrying the last underlying cause.\n *\n * Invariant #4 (jitter): handled by the schedule above. Invariant #3\n * (per-fetch deadline): handled by `requestFundsOnce`'s\n * `AbortSignal.timeout`.\n */\nexport const requestFundsWithRetry = (\n\topts: RetryOptions,\n): Effect.Effect<void, FaucetExhausted | FaucetUnreachable | FaucetBodyError> =>\n\tEffect.gen(function* () {\n\t\tconst timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\t\tconst maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n\t\tconst initialDelayMs = opts.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n\n\t\tconst attempts = yield* Ref.make(0);\n\t\tconst lastError = yield* Ref.make<FaucetUnreachable | FaucetBodyError | undefined>(undefined);\n\n\t\tconst wrapped = requestFundsOnce(opts).pipe(\n\t\t\tEffect.tapError((err) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst n = yield* Ref.updateAndGet(attempts, (x) => x + 1);\n\t\t\t\t\tyield* Ref.set(lastError, err);\n\t\t\t\t\tif (opts.onAttempt !== undefined) {\n\t\t\t\t\t\tyield* opts.onAttempt(n, err);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\n\t\tyield* wrapped.pipe(\n\t\t\tEffect.retry(\n\t\t\t\tmakeExponentialRetrySchedule({\n\t\t\t\t\tinitialDelayMs,\n\t\t\t\t\tmaxRetries: maxAttempts,\n\t\t\t\t\tfactor: BACKOFF_FACTOR,\n\t\t\t\t}),\n\t\t\t),\n\t\t\tEffect.timeoutOrElse({\n\t\t\t\tduration: `${timeoutMs} millis`,\n\t\t\t\torElse: () =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst n = yield* Ref.get(attempts);\n\t\t\t\t\t\tconst last = yield* Ref.get(lastError);\n\t\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\t\tfaucetExhausted({\n\t\t\t\t\t\t\t\turl: opts.faucetUrl,\n\t\t\t\t\t\t\t\taddress: opts.address,\n\t\t\t\t\t\t\t\tamount: opts.amount,\n\t\t\t\t\t\t\t\tattempts: n,\n\t\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\t\t`faucet did not accept request within ${timeoutMs}ms ` +\n\t\t\t\t\t\t\t\t\t`(${n} attempts; last: ${last?.message ?? 'unknown'})`,\n\t\t\t\t\t\t\t\tlastCause: last,\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}),\n\t\t);\n\t});\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { faucetCapabilityKey } from "./dispatcher.mjs";
2
2
  import "./errors.mjs";
3
- import "./spans.mjs";
4
3
  import "./http.mjs";
5
4
  //#region src/plugins/faucet/index.ts
6
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/faucet/index.ts"],"sourcesContent":["// Faucet plugin-author helpers.\n//\n// Author-side helper: `defineFaucetStrategy(...)` packages a\n// `{ chainId, strategy }` pair into a `StrategyContributorDecl` so\n// third-party plugins can contribute strategies declaratively. The\n// helper threads the literal `chainId` through the type so the\n// downstream consumer's `StrategyFor<...>` lookup recovers the\n// strategy's shape. Built-in account funding reads the strategy\n// registry directly; there is no public `faucet()` stack member.\n\nimport type { StrategyContributorDecl } from '../../contracts/strategy-contributor.ts';\nimport {\n\tFAUCET_CAPABILITY_KEY_PREFIX,\n\tfaucetCapabilityKey,\n\ttype FaucetStrategy,\n} from './dispatcher.ts';\n\n// ---------------------------------------------------------------------------\n// Author-side: helper for third-party strategy contributions.\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `StrategyContributorDecl` for a faucet request strategy.\n * Use from a sibling plugin's `capabilities` array so the\n * substrate auto-registers the strategy as the plugin acquires:\n *\n * ```ts\n * definePlugin({\n * id: 'my-faucet-strategy',\n * role: 'service',\n * start: () => Effect.succeed({}),\n * capabilities: [\n * defineFaucetStrategy({\n * chainId: 'sui:my-net',\n * strategy: makeMyFaucetStrategy(opts),\n * }),\n * ],\n * });\n * ```\n *\n * The capability key is computed from the chain id so the dispatcher\n * picks the contribution up automatically — no extra wiring on the\n * faucet-plugin side.\n *\n * `autoMounted` defaults to `false` (third-party contributions show\n * up in the dashboard). Pass `autoMounted: true` for built-ins that\n * the orchestrator includes automatically.\n */\nexport function defineFaucetStrategy<ChainId extends string>(decl: {\n\treadonly chainId: ChainId;\n\treadonly strategy: FaucetStrategy;\n\treadonly autoMounted?: boolean;\n\treadonly priority?: number;\n}): StrategyContributorDecl<`${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${ChainId}`, FaucetStrategy> {\n\treturn {\n\t\tkind: 'strategy-contributor',\n\t\tcapabilityKey: faucetCapabilityKey(decl.chainId),\n\t\tstrategy: decl.strategy,\n\t\tautoMounted: decl.autoMounted ?? false,\n\t\t...(decl.priority !== undefined ? { priority: decl.priority } : {}),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** A registered strategy contribution. Plugin authors that batch\n * multiple per-chain strategies (custom fork admins, alt-network\n * faucets) shape their config arrays around this; the underlying\n * registration mechanic is `defineFaucetStrategy`. */\nexport interface FaucetStrategyContribution {\n\t/** Capability-key chain id (`'sui:localnet'`, `'sui:testnet'`, etc.). */\n\treadonly chainId: string;\n\t/** The strategy value — closes over its own dependencies. */\n\treadonly strategy: FaucetStrategy;\n\t/** Optional priority. Defaults to `1` so user strategies win over\n\t * the built-in's `0`. */\n\treadonly priority?: number;\n}\n\nexport type {\n\tFaucetError,\n\tFaucetUnreachable,\n\tFaucetExhausted,\n\tFaucetBodyError,\n\tFaucetConfigError,\n} from './errors.ts';\nexport { faucetBodyError, faucetConfigError } from './errors.ts';\nexport { requestFundsWithRetry, type RetryOptions } from './http.ts';\nexport {\n\tFAUCET_CAPABILITY_KEY_PREFIX,\n\tfaucetCapabilityKey,\n\ttype FaucetStrategy,\n} from './dispatcher.ts';\nexport { FaucetSpans } from './spans.ts';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,SAAgB,qBAA6C,MAKoC;AAChG,QAAO;EACN,MAAM;EACN,eAAe,oBAAoB,KAAK,QAAQ;EAChD,UAAU,KAAK;EACf,aAAa,KAAK,eAAe;EACjC,GAAI,KAAK,aAAa,KAAA,IAAY,EAAE,UAAU,KAAK,UAAU,GAAG,EAAE;EAClE"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/faucet/index.ts"],"sourcesContent":["// Faucet plugin-author helpers.\n//\n// Author-side helper: `defineFaucetStrategy(...)` packages a\n// `{ chainId, strategy }` pair into a `StrategyContributorDecl` so\n// third-party plugins can contribute strategies declaratively. The\n// helper threads the literal `chainId` through the type so the\n// downstream consumer's `StrategyFor<...>` lookup recovers the\n// strategy's shape. Built-in account funding reads the strategy\n// registry directly; there is no public `faucet()` stack member.\n\nimport type { StrategyContributorDecl } from '../../contracts/strategy-contributor.ts';\nimport {\n\tFAUCET_CAPABILITY_KEY_PREFIX,\n\tfaucetCapabilityKey,\n\ttype FaucetStrategy,\n} from './dispatcher.ts';\n\n// ---------------------------------------------------------------------------\n// Author-side: helper for third-party strategy contributions.\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `StrategyContributorDecl` for a faucet request strategy.\n * Use from a sibling plugin's `capabilities` array so the\n * substrate auto-registers the strategy as the plugin acquires:\n *\n * ```ts\n * definePlugin({\n * id: 'my-faucet-strategy',\n * role: 'service',\n * start: () => Effect.succeed({}),\n * capabilities: [\n * defineFaucetStrategy({\n * chainId: 'sui:my-net',\n * strategy: makeMyFaucetStrategy(opts),\n * }),\n * ],\n * });\n * ```\n *\n * The capability key is computed from the chain id so the dispatcher\n * picks the contribution up automatically — no extra wiring on the\n * faucet-plugin side.\n *\n * `autoMounted` defaults to `false` (third-party contributions show\n * up in the dashboard). Pass `autoMounted: true` for built-ins that\n * the orchestrator includes automatically.\n */\nexport function defineFaucetStrategy<ChainId extends string>(decl: {\n\treadonly chainId: ChainId;\n\treadonly strategy: FaucetStrategy;\n\treadonly autoMounted?: boolean;\n\treadonly priority?: number;\n}): StrategyContributorDecl<`${typeof FAUCET_CAPABILITY_KEY_PREFIX}:${ChainId}`, FaucetStrategy> {\n\treturn {\n\t\tkind: 'strategy-contributor',\n\t\tcapabilityKey: faucetCapabilityKey(decl.chainId),\n\t\tstrategy: decl.strategy,\n\t\tautoMounted: decl.autoMounted ?? false,\n\t\t...(decl.priority !== undefined ? { priority: decl.priority } : {}),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** A registered strategy contribution. Plugin authors that batch\n * multiple per-chain strategies (custom fork admins, alt-network\n * faucets) shape their config arrays around this; the underlying\n * registration mechanic is `defineFaucetStrategy`. */\nexport interface FaucetStrategyContribution {\n\t/** Capability-key chain id (`'sui:localnet'`, `'sui:testnet'`, etc.). */\n\treadonly chainId: string;\n\t/** The strategy value — closes over its own dependencies. */\n\treadonly strategy: FaucetStrategy;\n\t/** Optional priority. Defaults to `1` so user strategies win over\n\t * the built-in's `0`. */\n\treadonly priority?: number;\n}\n\nexport type {\n\tFaucetError,\n\tFaucetUnreachable,\n\tFaucetExhausted,\n\tFaucetBodyError,\n\tFaucetConfigError,\n} from './errors.ts';\nexport { faucetBodyError, faucetConfigError } from './errors.ts';\nexport { requestFundsWithRetry, type RetryOptions } from './http.ts';\nexport {\n\tFAUCET_CAPABILITY_KEY_PREFIX,\n\tfaucetCapabilityKey,\n\ttype FaucetStrategy,\n} from './dispatcher.ts';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,SAAgB,qBAA6C,MAKoC;CAChG,OAAO;EACN,MAAM;EACN,eAAe,oBAAoB,KAAK,OAAO;EAC/C,UAAU,KAAK;EACf,aAAa,KAAK,eAAe;EACjC,GAAI,KAAK,aAAa,KAAA,IAAY,EAAE,UAAU,KAAK,SAAS,IAAI,CAAC;CAClE;AACD"}
@@ -1,13 +1,11 @@
1
1
  import { ConfigIssue } from "../../substrate/runtime/config-validation.mjs";
2
- import * as _$effect_Cause0 from "effect/Cause";
3
- import * as _$effect_Types0 from "effect/Types";
4
2
 
5
3
  //#region src/plugins/host-service/errors.d.ts
6
4
  interface HostServiceConfigError extends ConfigIssue {
7
5
  readonly _tag: 'HostServiceConfigError';
8
6
  readonly serviceName: string;
9
7
  }
10
- declare const HostServiceAcquireError_base: new <A extends Record<string, any> = {}>(args: _$effect_Types0.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => _$effect_Cause0.YieldableError & {
8
+ declare const HostServiceAcquireError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
11
9
  readonly _tag: "HostServiceAcquireError";
12
10
  } & Readonly<A>;
13
11
  declare class HostServiceAcquireError extends HostServiceAcquireError_base<{
@@ -7,8 +7,7 @@ const hostServiceConfigError = (serviceName, issue) => ({
7
7
  serviceName
8
8
  });
9
9
  var HostServiceAcquireError = class extends Data.TaggedError("HostServiceAcquireError") {};
10
- const HOST_SERVICE_ERROR_TAGS = ["HostServiceConfigError", "HostServiceAcquireError"];
11
10
  //#endregion
12
- export { HOST_SERVICE_ERROR_TAGS, HostServiceAcquireError, hostServiceConfigError };
11
+ export { HostServiceAcquireError, hostServiceConfigError };
13
12
 
14
13
  //# sourceMappingURL=errors.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/plugins/host-service/errors.ts"],"sourcesContent":["import { Data } from 'effect';\n\nimport { defineConfigError, type ConfigIssue } from '../../substrate/runtime/config-validation.ts';\n\nexport interface HostServiceConfigError extends ConfigIssue {\n\treadonly _tag: 'HostServiceConfigError';\n\treadonly serviceName: string;\n}\n\nconst makeHostServiceConfigError = defineConfigError('HostServiceConfigError');\n\nexport const hostServiceConfigError = (\n\tserviceName: string,\n\tissue: ConfigIssue,\n): HostServiceConfigError => ({\n\t...makeHostServiceConfigError(issue),\n\tserviceName,\n});\n\nexport class HostServiceAcquireError extends Data.TaggedError('HostServiceAcquireError')<{\n\treadonly serviceName: string;\n\treadonly cwd: string;\n\treadonly command: string;\n\treadonly args: ReadonlyArray<string>;\n\treadonly phase: 'allocate-port' | 'spawn' | 'ready' | 'exit';\n\treadonly message: string;\n\treadonly exitCode?: number | null;\n\treadonly signal?: NodeJS.Signals | null;\n\treadonly cause?: unknown;\n}> {}\n\nexport type HostServiceError = HostServiceConfigError | HostServiceAcquireError;\n\nexport const HOST_SERVICE_ERROR_TAGS = [\n\t'HostServiceConfigError',\n\t'HostServiceAcquireError',\n] as const;\n"],"mappings":";;;AASA,MAAM,6BAA6B,kBAAkB,yBAAyB;AAE9E,MAAa,0BACZ,aACA,WAC6B;CAC7B,GAAG,2BAA2B,MAAM;CACpC;CACA;AAED,IAAa,0BAAb,cAA6C,KAAK,YAAY,0BAA0B,CAUrF;AAIH,MAAa,0BAA0B,CACtC,0BACA,0BACA"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/plugins/host-service/errors.ts"],"sourcesContent":["import { Data } from 'effect';\n\nimport { defineConfigError, type ConfigIssue } from '../../substrate/runtime/config-validation.ts';\n\nexport interface HostServiceConfigError extends ConfigIssue {\n\treadonly _tag: 'HostServiceConfigError';\n\treadonly serviceName: string;\n}\n\nconst makeHostServiceConfigError = defineConfigError('HostServiceConfigError');\n\nexport const hostServiceConfigError = (\n\tserviceName: string,\n\tissue: ConfigIssue,\n): HostServiceConfigError => ({\n\t...makeHostServiceConfigError(issue),\n\tserviceName,\n});\n\nexport class HostServiceAcquireError extends Data.TaggedError('HostServiceAcquireError')<{\n\treadonly serviceName: string;\n\treadonly cwd: string;\n\treadonly command: string;\n\treadonly args: ReadonlyArray<string>;\n\treadonly phase: 'allocate-port' | 'spawn' | 'ready' | 'exit';\n\treadonly message: string;\n\treadonly exitCode?: number | null;\n\treadonly signal?: NodeJS.Signals | null;\n\treadonly cause?: unknown;\n}> {}\n\nexport type HostServiceError = HostServiceConfigError | HostServiceAcquireError;\n\nexport const HOST_SERVICE_ERROR_TAGS = [\n\t'HostServiceConfigError',\n\t'HostServiceAcquireError',\n] as const;\n"],"mappings":";;;AASA,MAAM,6BAA6B,kBAAkB,wBAAwB;AAE7E,MAAa,0BACZ,aACA,WAC6B;CAC7B,GAAG,2BAA2B,KAAK;CACnC;AACD;AAEA,IAAa,0BAAb,cAA6C,KAAK,YAAY,yBAAyB,CAAC,CAUrF,CAAC"}
@@ -1,10 +1,9 @@
1
- import { RoutableDecl } from "../../contracts/routable.mjs";
2
1
  import { AnyResourceRef, Plugin } from "../../substrate/plugin.mjs";
3
2
  import { HostServiceAcquireError, HostServiceConfigError, HostServiceError } from "./errors.mjs";
4
3
  import { HOST_SERVICE_PORT_TOKEN, HostServiceOptions, HostServiceReadyProbe, HostServiceValue } from "./service.mjs";
5
4
  //#region src/plugins/host-service/index.d.ts
6
5
  type HostServiceAfter = ReadonlyArray<AnyResourceRef>;
7
- declare const hostService: <const After extends HostServiceAfter = readonly []>(options: HostServiceOptions<After>) => Plugin<`host-service/${string}`, HostServiceValue, After, readonly [RoutableDecl]>;
6
+ declare const hostService: <const After extends HostServiceAfter = readonly []>(options: HostServiceOptions<After>) => Plugin<`host-service/${string}`, HostServiceValue, After>;
8
7
  //#endregion
9
8
  export { hostService };
10
9
  //# sourceMappingURL=index.d.mts.map
@@ -1,22 +1,21 @@
1
1
  import { definePlugin, resource } from "../../substrate/plugin.mjs";
2
2
  import "../../api/define-plugin.mjs";
3
- import { IdentityContext, RuntimeRoot } from "../../substrate/runtime/paths.mjs";
4
3
  import { Logger as Logger$1 } from "../../substrate/runtime/observability/logger.mjs";
5
4
  import "../../substrate/runtime/observability/index.mjs";
6
5
  import { CurrentPluginKey } from "../../substrate/runtime/current-plugin.mjs";
6
+ import { IdentityContext, RuntimeRoot } from "../../substrate/runtime/paths.mjs";
7
+ import { PluginContext } from "../../substrate/plugin-ctx.mjs";
7
8
  import { PostAcquireTasksService } from "../../substrate/runtime/post-acquire-tasks.mjs";
8
9
  import { PortBrokerService } from "../../substrate/runtime/port-broker/service.mjs";
9
10
  import "../../substrate/runtime/port-broker/index.mjs";
10
11
  import { renderUrl, routedHostname } from "../../substrate/runtime/routed-url.mjs";
11
12
  import { HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT, makeHostServiceRoutable } from "./routable.mjs";
12
- import { pluginErrorContributions } from "../../api/plugin-errors.mjs";
13
- import { HOST_SERVICE_ERROR_TAGS } from "./errors.mjs";
13
+ import "./errors.mjs";
14
14
  import { normalizeHostServiceOptions, prepareHostService } from "./service.mjs";
15
15
  import { Effect } from "effect";
16
16
  //#region src/plugins/host-service/index.ts
17
17
  const hostServiceResourceId = (name) => `host-service/${name}`;
18
18
  const hostServiceResource = (name) => resource(hostServiceResourceId(name));
19
- const hostServiceErrorContributions = pluginErrorContributions(HOST_SERVICE_ERROR_TAGS);
20
19
  const HOST_SERVICE_PORT_PROBE_HOST = "0.0.0.0";
21
20
  const hostService = (options) => {
22
21
  const normalized = normalizeHostServiceOptions(options);
@@ -27,7 +26,9 @@ const hostService = (options) => {
27
26
  dependsOn: after,
28
27
  role: "service",
29
28
  section: "service",
29
+ keepAliveOnRestore: true,
30
30
  start: () => Effect.gen(function* () {
31
+ const ctx = yield* PluginContext;
31
32
  const portBroker = yield* PortBrokerService;
32
33
  const logger = yield* Logger$1;
33
34
  const currentPlugin = yield* CurrentPluginKey;
@@ -58,14 +59,13 @@ const hostService = (options) => {
58
59
  label: `host-service:${normalized.serviceName}.start`,
59
60
  run: prepared.start
60
61
  });
62
+ ctx.endpoint(makeHostServiceRoutable({
63
+ endpointName: prepared.value.endpointName,
64
+ serviceName: prepared.value.name,
65
+ port: prepared.value.port
66
+ }));
61
67
  return prepared.value;
62
- }),
63
- errorContributions: hostServiceErrorContributions,
64
- capabilities: ({ value }) => [makeHostServiceRoutable({
65
- endpointName: value.endpointName,
66
- serviceName: value.name,
67
- port: value.port
68
- })]
68
+ })
69
69
  });
70
70
  };
71
71
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Logger"],"sources":["../../../src/plugins/host-service/index.ts"],"sourcesContent":["// Generic host-process service plugin.\n//\n// Use this for browser dev servers and other local host processes that\n// should be supervised by devstack rather than launched manually in a\n// sibling terminal.\n\nimport { Effect } from 'effect';\n\nimport { definePlugin, resource, type AnyResourceRef } from '../../api/define-plugin.ts';\nimport { pluginErrorContributions } from '../../api/plugin-errors.ts';\nimport {\n\tPortBrokerService,\n\ttype PortProbeHost,\n} from '../../substrate/runtime/port-broker/index.ts';\nimport { PostAcquireTasksService } from '../../substrate/runtime/post-acquire-tasks.ts';\nimport { Logger } from '../../substrate/runtime/observability/index.ts';\nimport { CurrentPluginKey } from '../../substrate/runtime/current-plugin.ts';\nimport { IdentityContext, RuntimeRoot } from '../../substrate/runtime/paths.ts';\nimport { renderUrl, routedHostname } from '../../substrate/runtime/routed-url.ts';\n\nimport {\n\tHOST_SERVICE_ERROR_TAGS,\n\tHostServiceAcquireError,\n\ttype HostServiceConfigError,\n\ttype HostServiceError,\n} from './errors.ts';\nimport {\n\tacquireHostService,\n\tnormalizeHostServiceOptions,\n\tprepareHostService,\n\tHOST_SERVICE_PORT_TOKEN,\n\ttype HostServiceOptions,\n\ttype PreparedHostService,\n\ttype HostServiceResolvedOptions,\n\ttype HostServiceValue,\n\ttype HostServiceReadyProbe,\n\ttype HostProcessChild,\n\ttype HostProcessSpawner,\n\ttype HostProcessSpawnOptions,\n\ttype HostServiceAcquireContext,\n} from './service.ts';\nimport {\n\tHOST_SERVICE_DEFAULT_ENDPOINT_NAME,\n\tHOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\tmakeHostServiceRoutable,\n} from './routable.ts';\n\nexport const hostServiceResourceId = <Name extends string>(name: Name): `host-service/${Name}` =>\n\t`host-service/${name}`;\n\nexport const hostServiceResource = <Name extends string>(name: Name) =>\n\tresource<`host-service/${Name}`, HostServiceValue>(hostServiceResourceId(name));\n\nconst hostServiceErrorContributions = pluginErrorContributions(HOST_SERVICE_ERROR_TAGS);\nconst HOST_SERVICE_PORT_PROBE_HOST: PortProbeHost = '0.0.0.0';\n\nexport type HostServiceAfter = ReadonlyArray<AnyResourceRef>;\n\nexport const hostService = <const After extends HostServiceAfter = readonly []>(\n\toptions: HostServiceOptions<After>,\n) => {\n\tconst normalized = normalizeHostServiceOptions(options);\n\tconst serviceResource = hostServiceResource(normalized.serviceName);\n\tconst after = options.after ?? ([] as unknown as After);\n\n\treturn definePlugin({\n\t\tid: serviceResource.id,\n\t\tdependsOn: after,\n\t\trole: 'service',\n\t\tsection: 'service',\n\t\tstart: () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst portBroker = yield* PortBrokerService;\n\t\t\t\tconst logger = yield* Logger;\n\t\t\t\tconst currentPlugin = yield* CurrentPluginKey;\n\t\t\t\tconst postAcquireTasks = yield* PostAcquireTasksService;\n\t\t\t\t// Effective stack + runtime root for this supervised run, so\n\t\t\t\t// the host-service can publish them into the spawned child's\n\t\t\t\t// env. The Vite plugin runs IN that child and re-discovers the\n\t\t\t\t// manifest via `resolveDiscoveryEnv(process.env)`; `--stack` is\n\t\t\t\t// a CLI flag that never reaches the child otherwise. Sourced\n\t\t\t\t// from the same boot-wired `Identity` / `RuntimeRoot` the rest\n\t\t\t\t// of the run uses, so the values point at the real manifest at\n\t\t\t\t// `<root>/stacks/<stack>/manifest.json`.\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst { root: runtimeRoot } = yield* RuntimeRoot;\n\t\t\t\t// Best-effort canonical routed URL for this endpoint. This is the\n\t\t\t\t// URL the dev-wallet CORS allowlist accepts (the wallet allowlists\n\t\t\t\t// `routedHostname(identity, dev) : 5175`, NOT the raw Vite bind), so\n\t\t\t\t// publishing it as the host-service's `value.url` points `devstack\n\t\t\t\t// up` output (and any consumer holding the resolved value) at the\n\t\t\t\t// URL that pairs the wallet successfully. The routed entrypoint port is the\n\t\t\t\t// shared Traefik port for every built-in endpoint\n\t\t\t\t// (`HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT` ===\n\t\t\t\t// `DEFAULT_ROUTER_ENTRYPOINT_PORT`); the role is THIS service's\n\t\t\t\t// `endpointName`, matching `makeHostServiceRoutable`'s\n\t\t\t\t// `dispatchId.role`. A hostname-validation failure (an\n\t\t\t\t// out-of-RFC-1035 app/stack/endpoint label) must NOT fail the\n\t\t\t\t// host-service boot — fall back to the raw loopback `value.url` via\n\t\t\t\t// `Effect.orElseSucceed(() => null)`. The raw bind still exists for\n\t\t\t\t// Vite's listen + the readiness probe (which derives its own\n\t\t\t\t// `127.0.0.1:<port>` literal independently of `value.url`).\n\t\t\t\tconst routedUrl = yield* routedHostname(identity, normalized.endpointName).pipe(\n\t\t\t\t\tEffect.map((hostname) =>\n\t\t\t\t\t\trenderUrl({\n\t\t\t\t\t\t\tprotocol: 'http',\n\t\t\t\t\t\t\thostname,\n\t\t\t\t\t\t\tport: HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.orElseSucceed(() => null),\n\t\t\t\t);\n\t\t\t\tconst acquireContext = {\n\t\t\t\t\tallocatePort: (preferredPort) =>\n\t\t\t\t\t\tportBroker\n\t\t\t\t\t\t\t.allocate({\n\t\t\t\t\t\t\t\towner: `host-service:${normalized.serviceName}`,\n\t\t\t\t\t\t\t\tprobeHost: HOST_SERVICE_PORT_PROBE_HOST,\n\t\t\t\t\t\t\t\t...(preferredPort === undefined ? {} : { preferredPort }),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.pipe(Effect.map((allocation) => allocation.port)),\n\t\t\t\t\tlogger,\n\t\t\t\t\tpluginKey: currentPlugin.key,\n\t\t\t\t\tdiscoveryIdentity: { stack: identity.stack, runtimeRoot },\n\t\t\t\t\troutedUrl,\n\t\t\t\t} satisfies HostServiceAcquireContext;\n\t\t\t\tconst prepared = yield* prepareHostService(normalized, acquireContext);\n\t\t\t\tyield* postAcquireTasks.register({\n\t\t\t\t\tpluginKey: currentPlugin.key,\n\t\t\t\t\tlabel: `host-service:${normalized.serviceName}.start`,\n\t\t\t\t\trun: prepared.start,\n\t\t\t\t});\n\t\t\t\treturn prepared.value;\n\t\t\t}),\n\t\terrorContributions: hostServiceErrorContributions,\n\t\tcapabilities: ({ value }) =>\n\t\t\t[\n\t\t\t\tmakeHostServiceRoutable({\n\t\t\t\t\tendpointName: value.endpointName,\n\t\t\t\t\tserviceName: value.name,\n\t\t\t\t\tport: value.port,\n\t\t\t\t}),\n\t\t\t] as const,\n\t});\n};\n\nexport type {\n\tHostServiceAcquireContext,\n\tHostServiceError,\n\tHostServiceOptions,\n\tPreparedHostService,\n\tHostServiceReadyProbe,\n\tHostServiceResolvedOptions,\n\tHostServiceValue,\n\tHostProcessChild,\n\tHostProcessSpawner,\n\tHostProcessSpawnOptions,\n\tHostServiceConfigError,\n};\nexport {\n\tacquireHostService,\n\tprepareHostService,\n\tHOST_SERVICE_DEFAULT_ENDPOINT_NAME,\n\tHOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\tHOST_SERVICE_ERROR_TAGS,\n\tHOST_SERVICE_PORT_TOKEN,\n\tHostServiceAcquireError,\n\tmakeHostServiceRoutable,\n\tnormalizeHostServiceOptions,\n};\n"],"mappings":";;;;;;;;;;;;;;;;AA+CA,MAAa,yBAA8C,SAC1D,gBAAgB;AAEjB,MAAa,uBAA4C,SACxD,SAAmD,sBAAsB,KAAK,CAAC;AAEhF,MAAM,gCAAgC,yBAAyB,wBAAwB;AACvF,MAAM,+BAA8C;AAIpD,MAAa,eACZ,YACI;CACJ,MAAM,aAAa,4BAA4B,QAAQ;CACvD,MAAM,kBAAkB,oBAAoB,WAAW,YAAY;CACnE,MAAM,QAAQ,QAAQ,SAAU,EAAE;AAElC,QAAO,aAAa;EACnB,IAAI,gBAAgB;EACpB,WAAW;EACX,MAAM;EACN,SAAS;EACT,aACC,OAAO,IAAI,aAAa;GACvB,MAAM,aAAa,OAAO;GAC1B,MAAM,SAAS,OAAOA;GACtB,MAAM,gBAAgB,OAAO;GAC7B,MAAM,mBAAmB,OAAO;GAShC,MAAM,WAAW,OAAO;GACxB,MAAM,EAAE,MAAM,gBAAgB,OAAO;GAiBrC,MAAM,YAAY,OAAO,eAAe,UAAU,WAAW,aAAa,CAAC,KAC1E,OAAO,KAAK,aACX,UAAU;IACT,UAAU;IACV;IACA,MAAM;IACN,CAAC,CACF,EACD,OAAO,oBAAoB,KAAK,CAChC;GAeD,MAAM,WAAW,OAAO,mBAAmB,YAAY;IAbtD,eAAe,kBACd,WACE,SAAS;KACT,OAAO,gBAAgB,WAAW;KAClC,WAAW;KACX,GAAI,kBAAkB,KAAA,IAAY,EAAE,GAAG,EAAE,eAAe;KACxD,CAAC,CACD,KAAK,OAAO,KAAK,eAAe,WAAW,KAAK,CAAC;IACpD;IACA,WAAW,cAAc;IACzB,mBAAmB;KAAE,OAAO,SAAS;KAAO;KAAa;IACzD;IAEoE,CAAC;AACtE,UAAO,iBAAiB,SAAS;IAChC,WAAW,cAAc;IACzB,OAAO,gBAAgB,WAAW,YAAY;IAC9C,KAAK,SAAS;IACd,CAAC;AACF,UAAO,SAAS;IACf;EACH,oBAAoB;EACpB,eAAe,EAAE,YAChB,CACC,wBAAwB;GACvB,cAAc,MAAM;GACpB,aAAa,MAAM;GACnB,MAAM,MAAM;GACZ,CAAC,CACF;EACF,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":["Logger"],"sources":["../../../src/plugins/host-service/index.ts"],"sourcesContent":["// Generic host-process service plugin.\n//\n// Use this for browser dev servers and other local host processes that\n// should be supervised by devstack rather than launched manually in a\n// sibling terminal.\n\nimport { Effect } from 'effect';\n\nimport { definePlugin, resource, type AnyResourceRef } from '../../api/define-plugin.ts';\nimport {\n\tPortBrokerService,\n\ttype PortProbeHost,\n} from '../../substrate/runtime/port-broker/index.ts';\nimport { PostAcquireTasksService } from '../../substrate/runtime/post-acquire-tasks.ts';\nimport { Logger } from '../../substrate/runtime/observability/index.ts';\nimport { CurrentPluginKey } from '../../substrate/runtime/current-plugin.ts';\nimport { IdentityContext, RuntimeRoot } from '../../substrate/runtime/paths.ts';\nimport { renderUrl, routedHostname } from '../../substrate/runtime/routed-url.ts';\nimport { PluginContext } from '../../substrate/plugin-ctx.ts';\n\nimport {\n\tHostServiceAcquireError,\n\ttype HostServiceConfigError,\n\ttype HostServiceError,\n} from './errors.ts';\nimport {\n\tacquireHostService,\n\tnormalizeHostServiceOptions,\n\tprepareHostService,\n\tHOST_SERVICE_PORT_TOKEN,\n\ttype HostServiceOptions,\n\ttype PreparedHostService,\n\ttype HostServiceResolvedOptions,\n\ttype HostServiceValue,\n\ttype HostServiceReadyProbe,\n\ttype HostProcessChild,\n\ttype HostProcessSpawner,\n\ttype HostProcessSpawnOptions,\n\ttype HostServiceAcquireContext,\n} from './service.ts';\nimport {\n\tHOST_SERVICE_DEFAULT_ENDPOINT_NAME,\n\tHOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\tmakeHostServiceRoutable,\n} from './routable.ts';\n\nexport const hostServiceResourceId = <Name extends string>(name: Name): `host-service/${Name}` =>\n\t`host-service/${name}`;\n\nexport const hostServiceResource = <Name extends string>(name: Name) =>\n\tresource<`host-service/${Name}`, HostServiceValue>(hostServiceResourceId(name));\n\nconst HOST_SERVICE_PORT_PROBE_HOST: PortProbeHost = '0.0.0.0';\n\nexport type HostServiceAfter = ReadonlyArray<AnyResourceRef>;\n\nexport const hostService = <const After extends HostServiceAfter = readonly []>(\n\toptions: HostServiceOptions<After>,\n) => {\n\tconst normalized = normalizeHostServiceOptions(options);\n\tconst serviceResource = hostServiceResource(normalized.serviceName);\n\tconst after = options.after ?? ([] as unknown as After);\n\n\treturn definePlugin({\n\t\tid: serviceResource.id,\n\t\tdependsOn: after,\n\t\trole: 'service',\n\t\tsection: 'service',\n\t\t// Operator transport: a live snapshot-restore re-acquire leaves\n\t\t// supervised host processes running. They read chain over the\n\t\t// network at stable hostnames and hold no restorable chain state,\n\t\t// so draining them mid-restore only churns the connection a\n\t\t// dashboard-initiated restore is answering on.\n\t\tkeepAliveOnRestore: true,\n\t\tstart: () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst ctx = yield* PluginContext;\n\t\t\t\tconst portBroker = yield* PortBrokerService;\n\t\t\t\tconst logger = yield* Logger;\n\t\t\t\tconst currentPlugin = yield* CurrentPluginKey;\n\t\t\t\tconst postAcquireTasks = yield* PostAcquireTasksService;\n\t\t\t\t// Effective stack + runtime root for this supervised run, so\n\t\t\t\t// the host-service can publish them into the spawned child's\n\t\t\t\t// env. The Vite plugin runs IN that child and re-discovers the\n\t\t\t\t// manifest via `resolveDiscoveryEnv(process.env)`; `--stack` is\n\t\t\t\t// a CLI flag that never reaches the child otherwise. Sourced\n\t\t\t\t// from the same boot-wired `Identity` / `RuntimeRoot` the rest\n\t\t\t\t// of the run uses, so the values point at the real manifest at\n\t\t\t\t// `<root>/stacks/<stack>/manifest.json`.\n\t\t\t\tconst identity = yield* IdentityContext;\n\t\t\t\tconst { root: runtimeRoot } = yield* RuntimeRoot;\n\t\t\t\t// Best-effort canonical routed URL for this endpoint. This is the\n\t\t\t\t// URL the dev-wallet CORS allowlist accepts (the wallet allowlists\n\t\t\t\t// `routedHostname(identity, dev) : 5175`, NOT the raw Vite bind), so\n\t\t\t\t// publishing it as the host-service's `value.url` points `devstack\n\t\t\t\t// up` output (and any consumer holding the resolved value) at the\n\t\t\t\t// URL that pairs the wallet successfully. The routed entrypoint port is the\n\t\t\t\t// shared Traefik port for every built-in endpoint\n\t\t\t\t// (`HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT` ===\n\t\t\t\t// `DEFAULT_ROUTER_ENTRYPOINT_PORT`); the role is THIS service's\n\t\t\t\t// `endpointName`, matching `makeHostServiceRoutable`'s\n\t\t\t\t// `dispatchId.role`. A hostname-validation failure (an\n\t\t\t\t// out-of-RFC-1035 app/stack/endpoint label) must NOT fail the\n\t\t\t\t// host-service boot — fall back to the raw loopback `value.url` via\n\t\t\t\t// `Effect.orElseSucceed(() => null)`. The raw bind still exists for\n\t\t\t\t// Vite's listen + the readiness probe (which derives its own\n\t\t\t\t// `127.0.0.1:<port>` literal independently of `value.url`).\n\t\t\t\tconst routedUrl = yield* routedHostname(identity, normalized.endpointName).pipe(\n\t\t\t\t\tEffect.map((hostname) =>\n\t\t\t\t\t\trenderUrl({\n\t\t\t\t\t\t\tprotocol: 'http',\n\t\t\t\t\t\t\thostname,\n\t\t\t\t\t\t\tport: HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.orElseSucceed(() => null),\n\t\t\t\t);\n\t\t\t\tconst acquireContext = {\n\t\t\t\t\tallocatePort: (preferredPort) =>\n\t\t\t\t\t\tportBroker\n\t\t\t\t\t\t\t.allocate({\n\t\t\t\t\t\t\t\towner: `host-service:${normalized.serviceName}`,\n\t\t\t\t\t\t\t\tprobeHost: HOST_SERVICE_PORT_PROBE_HOST,\n\t\t\t\t\t\t\t\t...(preferredPort === undefined ? {} : { preferredPort }),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.pipe(Effect.map((allocation) => allocation.port)),\n\t\t\t\t\tlogger,\n\t\t\t\t\tpluginKey: currentPlugin.key,\n\t\t\t\t\tdiscoveryIdentity: { stack: identity.stack, runtimeRoot },\n\t\t\t\t\troutedUrl,\n\t\t\t\t} satisfies HostServiceAcquireContext;\n\t\t\t\tconst prepared = yield* prepareHostService(normalized, acquireContext);\n\t\t\t\tyield* postAcquireTasks.register({\n\t\t\t\t\tpluginKey: currentPlugin.key,\n\t\t\t\t\tlabel: `host-service:${normalized.serviceName}.start`,\n\t\t\t\t\trun: prepared.start,\n\t\t\t\t});\n\t\t\t\t// Emit the routable endpoint inline. The decl reads\n\t\t\t\t// `value.{endpointName,name,port}` off the resolved\n\t\t\t\t// `HostServiceValue` (`prepared.value` here), emitted BEFORE\n\t\t\t\t// returning it. `ctx.endpoint` returns void and buffers the\n\t\t\t\t// decl for the supervisor's post-start replay.\n\t\t\t\tctx.endpoint(\n\t\t\t\t\tmakeHostServiceRoutable({\n\t\t\t\t\t\tendpointName: prepared.value.endpointName,\n\t\t\t\t\t\tserviceName: prepared.value.name,\n\t\t\t\t\t\tport: prepared.value.port,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn prepared.value;\n\t\t\t}),\n\t});\n};\n\nexport type {\n\tHostServiceAcquireContext,\n\tHostServiceError,\n\tHostServiceOptions,\n\tPreparedHostService,\n\tHostServiceReadyProbe,\n\tHostServiceResolvedOptions,\n\tHostServiceValue,\n\tHostProcessChild,\n\tHostProcessSpawner,\n\tHostProcessSpawnOptions,\n\tHostServiceConfigError,\n};\nexport {\n\tacquireHostService,\n\tprepareHostService,\n\tHOST_SERVICE_DEFAULT_ENDPOINT_NAME,\n\tHOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\tHOST_SERVICE_PORT_TOKEN,\n\tHostServiceAcquireError,\n\tmakeHostServiceRoutable,\n\tnormalizeHostServiceOptions,\n};\n"],"mappings":";;;;;;;;;;;;;;;;AA8CA,MAAa,yBAA8C,SAC1D,gBAAgB;AAEjB,MAAa,uBAA4C,SACxD,SAAmD,sBAAsB,IAAI,CAAC;AAE/E,MAAM,+BAA8C;AAIpD,MAAa,eACZ,YACI;CACJ,MAAM,aAAa,4BAA4B,OAAO;CACtD,MAAM,kBAAkB,oBAAoB,WAAW,WAAW;CAClE,MAAM,QAAQ,QAAQ,SAAU,CAAC;CAEjC,OAAO,aAAa;EACnB,IAAI,gBAAgB;EACpB,WAAW;EACX,MAAM;EACN,SAAS;EAMT,oBAAoB;EACpB,aACC,OAAO,IAAI,aAAa;GACvB,MAAM,MAAM,OAAO;GACnB,MAAM,aAAa,OAAO;GAC1B,MAAM,SAAS,OAAOA;GACtB,MAAM,gBAAgB,OAAO;GAC7B,MAAM,mBAAmB,OAAO;GAShC,MAAM,WAAW,OAAO;GACxB,MAAM,EAAE,MAAM,gBAAgB,OAAO;GAiBrC,MAAM,YAAY,OAAO,eAAe,UAAU,WAAW,YAAY,CAAC,CAAC,KAC1E,OAAO,KAAK,aACX,UAAU;IACT,UAAU;IACV;IACA,MAAM;GACP,CAAC,CACF,GACA,OAAO,oBAAoB,IAAI,CAChC;GAeA,MAAM,WAAW,OAAO,mBAAmB,YAAY;IAbtD,eAAe,kBACd,WACE,SAAS;KACT,OAAO,gBAAgB,WAAW;KAClC,WAAW;KACX,GAAI,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc;IACxD,CAAC,CAAC,CACD,KAAK,OAAO,KAAK,eAAe,WAAW,IAAI,CAAC;IACnD;IACA,WAAW,cAAc;IACzB,mBAAmB;KAAE,OAAO,SAAS;KAAO;IAAY;IACxD;GAEmE,CAAC;GACrE,OAAO,iBAAiB,SAAS;IAChC,WAAW,cAAc;IACzB,OAAO,gBAAgB,WAAW,YAAY;IAC9C,KAAK,SAAS;GACf,CAAC;GAMD,IAAI,SACH,wBAAwB;IACvB,cAAc,SAAS,MAAM;IAC7B,aAAa,SAAS,MAAM;IAC5B,MAAM,SAAS,MAAM;GACtB,CAAC,CACF;GACA,OAAO,SAAS;EACjB,CAAC;CACH,CAAC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"routable.mjs","names":[],"sources":["../../../src/plugins/host-service/routable.ts"],"sourcesContent":["import type { EntrypointDecl, RoutableDecl } from '../../contracts/routable.ts';\n\nexport const HOST_SERVICE_DEFAULT_ENDPOINT_NAME = 'dev' as const;\nexport const HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT = 5175;\n\nexport const HOST_SERVICE_ENTRYPOINTS: ReadonlyArray<EntrypointDecl> = [\n\t{\n\t\tname: HOST_SERVICE_DEFAULT_ENDPOINT_NAME,\n\t\tport: HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\t\tprotocol: 'http',\n\t},\n];\n\nexport const makeHostServiceRoutable = (parts: {\n\treadonly endpointName: string;\n\treadonly serviceName: string;\n\treadonly port: number;\n}): RoutableDecl => ({\n\tkind: 'routable',\n\tendpointName: parts.endpointName,\n\tdispatchId: {\n\t\tserviceKey: `host-service.${parts.serviceName}`,\n\t\trole: parts.endpointName,\n\t},\n\tupstream: { type: 'host-loopback', port: parts.port },\n\tcors: true,\n\twireProtocol: 'http',\n\treadiness: 'deferred',\n});\n"],"mappings":"AAGA,MAAa,uCAAuC;AAEpD,MAAa,2BAA0D,CACtE;CACC,MAAA;CACA,MAAM;CACN,UAAU;CACV,CACD;AAED,MAAa,2BAA2B,WAInB;CACpB,MAAM;CACN,cAAc,MAAM;CACpB,YAAY;EACX,YAAY,gBAAgB,MAAM;EAClC,MAAM,MAAM;EACZ;CACD,UAAU;EAAE,MAAM;EAAiB,MAAM,MAAM;EAAM;CACrD,MAAM;CACN,cAAc;CACd,WAAW;CACX"}
1
+ {"version":3,"file":"routable.mjs","names":[],"sources":["../../../src/plugins/host-service/routable.ts"],"sourcesContent":["import type { EntrypointDecl, RoutableDecl } from '../../contracts/routable.ts';\n\nexport const HOST_SERVICE_DEFAULT_ENDPOINT_NAME = 'dev' as const;\nexport const HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT = 5175;\n\nexport const HOST_SERVICE_ENTRYPOINTS: ReadonlyArray<EntrypointDecl> = [\n\t{\n\t\tname: HOST_SERVICE_DEFAULT_ENDPOINT_NAME,\n\t\tport: HOST_SERVICE_DEFAULT_ENTRYPOINT_PORT,\n\t\tprotocol: 'http',\n\t},\n];\n\nexport const makeHostServiceRoutable = (parts: {\n\treadonly endpointName: string;\n\treadonly serviceName: string;\n\treadonly port: number;\n}): RoutableDecl => ({\n\tkind: 'routable',\n\tendpointName: parts.endpointName,\n\tdispatchId: {\n\t\tserviceKey: `host-service.${parts.serviceName}`,\n\t\trole: parts.endpointName,\n\t},\n\tupstream: { type: 'host-loopback', port: parts.port },\n\tcors: true,\n\twireProtocol: 'http',\n\treadiness: 'deferred',\n});\n"],"mappings":"AAGA,MAAa,uCAAuC;AAEpD,MAAa,2BAA0D,CACtE;CACC,MAAA;CACA,MAAM;CACN,UAAU;AACX,CACD;AAEA,MAAa,2BAA2B,WAInB;CACpB,MAAM;CACN,cAAc,MAAM;CACpB,YAAY;EACX,YAAY,gBAAgB,MAAM;EAClC,MAAM,MAAM;CACb;CACA,UAAU;EAAE,MAAM;EAAiB,MAAM,MAAM;CAAK;CACpD,MAAM;CACN,cAAc;CACd,WAAW;AACZ"}