@fased/fased 0.1.62 → 0.1.65

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 (342) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +44 -29
  3. package/config/dependency-ownership.json +1 -1
  4. package/config/signer-policies/README.md +58 -0
  5. package/config/signer-policies/agent.json.template +32 -0
  6. package/config/signer-policies/mining.json.template +69 -0
  7. package/config/signer-policies/network.json.template +5 -0
  8. package/config/signer-policies/vault.json.template +70 -0
  9. package/config/signer-protocol-v2.json +78 -0
  10. package/config/typescript-noemit-baseline.json +680 -0
  11. package/dist/agents/auth-profiles/store.js +267 -31
  12. package/dist/agents/bash-tools.exec.js +10 -4
  13. package/dist/agents/current-model-catalog.js +3 -3
  14. package/dist/agents/memory-search.js +7 -1
  15. package/dist/agents/model-catalog-access.js +1 -2
  16. package/dist/agents/model-catalog-snapshot.js +1 -1
  17. package/dist/agents/model-catalog-source.js +1 -1
  18. package/dist/agents/model-metadata.js +1 -1
  19. package/dist/agents/model-selection.js +2 -28
  20. package/dist/agents/models-config.providers.js +6 -6
  21. package/dist/agents/pi-embedded-runner/compact.js +15 -7
  22. package/dist/agents/pi-embedded-runner/model.js +1 -1
  23. package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
  24. package/dist/agents/pi-embedded-runner/run.js +2 -0
  25. package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
  26. package/dist/agents/pi-tool-definition-adapter.js +16 -1
  27. package/dist/agents/pi-tools.js +2 -1
  28. package/dist/agents/sandbox/config.js +1 -1
  29. package/dist/agents/sandbox/context.js +27 -2
  30. package/dist/agents/skills/env-overrides.js +38 -28
  31. package/dist/agents/skills/trust.js +93 -0
  32. package/dist/agents/skills/workspace.js +128 -0
  33. package/dist/agents/skills-clawhub.js +36 -11
  34. package/dist/agents/skills-marketplace-scan.js +49 -0
  35. package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
  36. package/dist/agents/tools/mining-tool.js +1 -1
  37. package/dist/agents/tools/session-status-tool.js +1 -1
  38. package/dist/agents/tools/wallet-action-tool.js +172 -36
  39. package/dist/agents/tools/wallet-skill-policy.js +65 -23
  40. package/dist/agents/tools/wallet-tool.js +7 -11
  41. package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
  42. package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
  43. package/dist/auto-reply/reply/directive-handling.model.js +2 -1
  44. package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
  45. package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
  46. package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
  47. package/dist/auto-reply/reply/model-selection.js +7 -4
  48. package/dist/auto-reply/reply/session-reset-model.js +4 -4
  49. package/dist/brand.js +1 -1
  50. package/dist/build-info.json +3 -3
  51. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  52. package/dist/channel-web.js +2 -2
  53. package/dist/cli/gateway-cli/run.js +8 -0
  54. package/dist/cli/program/command-registry.js +1 -1
  55. package/dist/cli/program/register.onboard.js +2 -3
  56. package/dist/cli/program/register.wallet.js +16 -123
  57. package/dist/cli/providers-cli.js +1 -1
  58. package/dist/cli/sat-cli.js +129 -2
  59. package/dist/cli/update-cli/update-command.js +260 -11
  60. package/dist/commands/auth-choice.apply.api-providers.js +3 -3
  61. package/dist/commands/doctor-config-flow.js +1 -1
  62. package/dist/commands/doctor-legacy-config.js +2 -13
  63. package/dist/commands/model-picker.js +6 -6
  64. package/dist/commands/models/auth.js +1 -1
  65. package/dist/commands/onboard-auth.config-gateways.js +1 -1
  66. package/dist/commands/onboard-auth.credentials.js +32 -8
  67. package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
  68. package/dist/commands/onboard-non-interactive/local.js +5 -1
  69. package/dist/commands/wallet.js +568 -1911
  70. package/dist/config/config.js +2 -2
  71. package/dist/config/io.js +64 -2
  72. package/dist/config/schema.help.js +8 -7
  73. package/dist/config/schema.labels.js +5 -4
  74. package/dist/config/zod-schema.agent-runtime.js +1 -0
  75. package/dist/config/zod-schema.js +5 -0
  76. package/dist/control-ui/assets/{app-DLil9VO1.js → app-MaQnPa5G.js} +1511 -1555
  77. package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
  78. package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
  79. package/dist/control-ui/assets/{index-DdE_NIXo.js → index-D4YMr1fA.js} +3 -3
  80. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  81. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-qMYs4aD-.js} +70 -50
  82. package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
  83. package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
  84. package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
  85. package/dist/control-ui/index.html +1 -1
  86. package/dist/control-ui/version.json +1 -1
  87. package/dist/daemon/systemd-system.js +56 -50
  88. package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
  89. package/dist/extensions/sat-mining/src/rpc-read.js +291 -84
  90. package/dist/extensions/sat-mining/src/sat-bond-layout.js +5 -2
  91. package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
  92. package/dist/extensions/sat-mining/src/solana-submit.js +1274 -390
  93. package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
  94. package/dist/federation/auto-connect.js +98 -8
  95. package/dist/federation/marketplace-capability-adapter.js +33 -7
  96. package/dist/federation/marketplace-delivery-outbox.js +196 -0
  97. package/dist/federation/marketplace-delivery.js +351 -215
  98. package/dist/federation/marketplace-direct-payment.js +272 -141
  99. package/dist/federation/marketplace-escrow.js +607 -249
  100. package/dist/federation/marketplace-settlement-ledger.js +352 -0
  101. package/dist/federation/offers.js +9 -7
  102. package/dist/federation/peer-auth-v2.js +529 -0
  103. package/dist/gateway/a2a-http.js +425 -96
  104. package/dist/gateway/a2a-settlement.js +259 -153
  105. package/dist/gateway/a2a-task-store.js +524 -0
  106. package/dist/gateway/auth.js +38 -2
  107. package/dist/gateway/config-reload.js +46 -33
  108. package/dist/gateway/durable-capacity.js +31 -0
  109. package/dist/gateway/federation-http.js +540 -135
  110. package/dist/gateway/federation-marketplace-run-store.js +397 -0
  111. package/dist/gateway/federation-marketplace.js +535 -230
  112. package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
  113. package/dist/gateway/security-path.js +1 -1
  114. package/dist/gateway/server-http.js +1084 -1205
  115. package/dist/gateway/server-methods/models.js +1 -1
  116. package/dist/gateway/server-methods/secrets.js +40 -0
  117. package/dist/gateway/server-methods.js +1 -2
  118. package/dist/gateway/server-reload-handlers.js +196 -66
  119. package/dist/gateway/server-runtime-config.js +1 -1
  120. package/dist/gateway/server-secrets-runtime.js +288 -0
  121. package/dist/gateway/server.impl.js +73 -42
  122. package/dist/gateway/sessions-patch.js +3 -5
  123. package/dist/index.js +4 -2
  124. package/dist/infra/fasedhub.js +64 -1
  125. package/dist/infra/local-source-paired-update.js +538 -0
  126. package/dist/infra/restart.js +41 -10
  127. package/dist/infra/update-runner.js +96 -0
  128. package/dist/light-update-status.js +11 -11
  129. package/dist/memory/backend-config.js +2 -1
  130. package/dist/memory/session-files.js +16 -2
  131. package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
  132. package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
  133. package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
  134. package/dist/plugin-sdk/{audio-preflight-Bwi2Oq03.js → audio-preflight-I4IngVlJ.js} +27 -27
  135. package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
  136. package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
  137. package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
  138. package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
  139. package/dist/plugin-sdk/channel-plugin-common.js +4 -4
  140. package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
  141. package/dist/plugin-sdk/{chunk-items-DzT4L4Ty.js → chunk-items-DLQ6_lLK.js} +1 -1
  142. package/dist/plugin-sdk/command-status.d.ts +2 -2
  143. package/dist/plugin-sdk/command-status.js +27 -27
  144. package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
  145. package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
  146. package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
  147. package/dist/plugin-sdk/{config-schema-BrkmtFxB.js → config-schema-D_8FVI1C.js} +6798 -3695
  148. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  149. package/dist/plugin-sdk/discord.d.ts +6 -6
  150. package/dist/plugin-sdk/discord.js +19 -19
  151. package/dist/plugin-sdk/file-lock.js +35 -4
  152. package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
  153. package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
  154. package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
  155. package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
  156. package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
  157. package/dist/plugin-sdk/index.d.ts +21 -39
  158. package/dist/plugin-sdk/index.js +29 -29
  159. package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
  160. package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
  161. package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
  162. package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
  163. package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
  164. package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
  165. package/dist/plugin-sdk/{monitor-M_ta2lMc.js → monitor-B4KF4Kpo.js} +31 -31
  166. package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-Bb6x1KAG.js} +32 -32
  167. package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DCTO8JkL.js} +27 -27
  168. package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
  169. package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
  170. package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
  171. package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  172. package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-DHPDFZbC.d.ts} +2 -2
  173. package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
  174. package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
  175. package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
  176. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
  177. package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
  178. package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
  179. package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
  180. package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
  181. package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
  182. package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
  183. package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
  184. package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
  185. package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
  186. package/dist/plugin-sdk/sat-runtime.d.ts +565 -309
  187. package/dist/plugin-sdk/sat-runtime.js +29 -29
  188. package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
  189. package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
  190. package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
  191. package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
  192. package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
  193. package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
  194. package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
  195. package/dist/plugin-sdk/{slack-CxE1mfzj.js → slack-BHmvqgjH.js} +39 -39
  196. package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
  197. package/dist/plugin-sdk/slack.d.ts +6 -6
  198. package/dist/plugin-sdk/slack.js +9 -9
  199. package/dist/plugin-sdk/{sticker-cache-CGzGWu00.js → sticker-cache-By5AcorL.js} +3 -3
  200. package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
  201. package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
  202. package/dist/plugin-sdk/{telegram-actions-DaEcYQ8r.js → telegram-actions-DGnBz1YT.js} +30 -30
  203. package/dist/plugin-sdk/telegram.d.ts +6 -6
  204. package/dist/plugin-sdk/telegram.js +8 -8
  205. package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
  206. package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
  207. package/dist/plugin-sdk/tmp-fased-dir-EJGTmL1Q.d.ts +486 -0
  208. package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-BdwdFCD6.d.ts} +2 -3
  209. package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-BrCpYMxn.d.ts} +2 -2
  210. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
  211. package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
  212. package/dist/plugin-sdk/{web-CInY-lCv.js → web-DUJwrTYs.js} +32 -32
  213. package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
  214. package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
  215. package/dist/plugin-sdk/whatsapp.d.ts +13 -13
  216. package/dist/plugin-sdk/whatsapp.js +12 -12
  217. package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
  218. package/dist/plugin-sdk/{zod-schema.providers-core-BEbNizPe.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
  219. package/dist/providers/refresh.js +1 -1
  220. package/dist/providers/registry.js +1 -1
  221. package/dist/secrets/apply.js +1 -1
  222. package/dist/secrets/runtime.js +1 -1
  223. package/dist/wallet/external-submission-ledger.js +376 -0
  224. package/dist/wallet/legacy-embedded-keystore.js +40 -0
  225. package/dist/wallet/local-socket-signer-archive.js +30 -0
  226. package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
  227. package/dist/wallet/local-socket-signer-policy.js +166 -0
  228. package/dist/wallet/local-socket-signer-protocol.js +578 -117
  229. package/dist/wallet/native-signer-wallet-id.js +25 -0
  230. package/dist/wallet/providers/alchemy-adapter.js +3 -0
  231. package/dist/wallet/providers/local-socket-signer-adapter.js +380 -105
  232. package/dist/wallet/providers/turnkey-adapter.js +292 -34
  233. package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
  234. package/dist/wallet/signer-network-admin.js +184 -0
  235. package/dist/wallet/signer-protocol-v2.generated.js +92 -0
  236. package/dist/wallet/solana-bond-signing.js +157 -69
  237. package/dist/wallet/solana-reviewed-transaction.js +375 -0
  238. package/dist/wallet/solana-swap.js +520 -64
  239. package/dist/wallet/solana-transaction-inspection.js +106 -4
  240. package/dist/wallet/solana-trigger.js +658 -320
  241. package/dist/wallet/turnkey-reviewed-state.js +370 -0
  242. package/dist/wallet/wallet-approval-auth.js +17 -28
  243. package/dist/wallet/wallet-atomic-state.js +53 -0
  244. package/dist/wallet/wallet-canary.js +0 -1
  245. package/dist/wallet/wallet-inbound-events.js +16 -11
  246. package/dist/wallet/wallet-policy-simulation.js +1 -1
  247. package/dist/wallet/wallet-policy.js +93 -37
  248. package/dist/wallet/wallet-provider-capabilities.js +28 -4
  249. package/dist/wallet/wallet-provider-registry.js +57 -44
  250. package/dist/wallet/wallet-provider-resolver.js +62 -63
  251. package/dist/wallet/wallet-runtime-config.js +28 -41
  252. package/dist/wallet/wallet-secrets-store.js +22 -0
  253. package/dist/wallet/wallet-send-approvals.js +1891 -589
  254. package/dist/wallet/wallet-send-execution-ledger.js +292 -0
  255. package/dist/wallet/wallet-settlement-links.js +14 -13
  256. package/dist/wallet/wallet-standard-review.js +353 -0
  257. package/dist/wallet/wallet-status.js +0 -9
  258. package/dist/wallet/wallet-task-ledger.js +16 -2
  259. package/dist/web/auto-reply/heartbeat-runner.js +1 -1
  260. package/dist/web/auto-reply/monitor.js +2 -2
  261. package/dist/wizard/host-security-capability.js +14 -23
  262. package/dist/wizard/onboarding.finalize.js +63 -184
  263. package/dist/wizard/onboarding.host-security.js +117 -1367
  264. package/dist/wizard/onboarding.js +172 -217
  265. package/dist/wizard/onboarding.wallet.js +232 -785
  266. package/extensions/acpx/package.json +1 -1
  267. package/extensions/bluebubbles/package.json +1 -1
  268. package/extensions/copilot-proxy/package.json +1 -1
  269. package/extensions/diagnostics-otel/package.json +1 -1
  270. package/extensions/fased-federation/package.json +1 -1
  271. package/extensions/google-gemini-cli-auth/package.json +1 -1
  272. package/extensions/imessage/package.json +1 -1
  273. package/extensions/irc/package.json +1 -1
  274. package/extensions/line/package.json +1 -1
  275. package/extensions/llm-task/package.json +1 -1
  276. package/extensions/lobster/package.json +1 -1
  277. package/extensions/matrix/CHANGELOG.md +18 -0
  278. package/extensions/matrix/package.json +1 -1
  279. package/extensions/mattermost/package.json +1 -1
  280. package/extensions/memory-core/package.json +2 -2
  281. package/extensions/memory-lancedb/package.json +1 -1
  282. package/extensions/minimax-portal-auth/package.json +1 -1
  283. package/extensions/msteams/CHANGELOG.md +18 -0
  284. package/extensions/msteams/package.json +1 -1
  285. package/extensions/nextcloud-talk/package.json +1 -1
  286. package/extensions/nostr/CHANGELOG.md +18 -0
  287. package/extensions/nostr/package.json +1 -1
  288. package/extensions/open-prose/package.json +1 -1
  289. package/extensions/sat-mining/index.ts +587 -154
  290. package/extensions/sat-mining/package.json +1 -1
  291. package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
  292. package/extensions/sat-mining/src/audit-store.ts +91 -5
  293. package/extensions/sat-mining/src/claim-service.ts +85 -14
  294. package/extensions/sat-mining/src/client.ts +13 -0
  295. package/extensions/sat-mining/src/config.ts +9 -0
  296. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  297. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  298. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  299. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  300. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  301. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  302. package/extensions/sat-mining/src/rpc-read.ts +431 -106
  303. package/extensions/sat-mining/src/runtime.ts +16 -0
  304. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  305. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  306. package/extensions/sat-mining/src/solana-submit.ts +1544 -436
  307. package/extensions/sat-mining/src/submission-ledger.ts +434 -0
  308. package/extensions/signal/package.json +1 -1
  309. package/extensions/synology-chat/package.json +1 -1
  310. package/extensions/tlon/package.json +1 -1
  311. package/extensions/twitch/CHANGELOG.md +18 -0
  312. package/extensions/twitch/package.json +1 -1
  313. package/extensions/voice-call/CHANGELOG.md +18 -0
  314. package/extensions/voice-call/package.json +1 -1
  315. package/extensions/zalo/CHANGELOG.md +18 -0
  316. package/extensions/zalo/package.json +1 -1
  317. package/extensions/zalouser/CHANGELOG.md +18 -0
  318. package/extensions/zalouser/package.json +1 -1
  319. package/install.sh +4951 -0
  320. package/package.json +23 -5
  321. package/scripts/fased-host-updater.mjs +1421 -0
  322. package/scripts/fased-host-updaterctl.mjs +186 -0
  323. package/scripts/fased-managed-service.sh +36 -0
  324. package/scripts/fased-managed-updater.mjs +3065 -156
  325. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  326. package/scripts/fased-signer-network-hosting.sh +143 -0
  327. package/scripts/fased-signer-owner-policy.mjs +1442 -0
  328. package/scripts/fased-signer-policy-hosting.sh +50 -0
  329. package/scripts/fased-signer-policy-local.sh +26 -0
  330. package/scripts/hosted-release-manifest.mjs +185 -0
  331. package/scripts/install-fased-signerd.sh +183 -108
  332. package/scripts/install-managed-runtime.mjs +212 -10
  333. package/scripts/managed-runtime-layout.mjs +75 -3
  334. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  335. package/scripts/start-managed.sh +173 -360
  336. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  337. package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
  338. package/dist/wallet/local-socket-signer-broker.js +0 -224
  339. package/dist/wallet/local-socket-signer-custody.js +0 -42
  340. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  341. package/dist/wallet/providers/privy-adapter.js +0 -80
  342. package/dist/wallet/wallet-custody.js +0 -1836
@@ -1,15 +1,20 @@
1
1
  import { loadConfig } from "../../../config/io.js";
2
- import { resolveWalletRuntimeConfig } from "../../../wallet/wallet-runtime-config.js";
2
+ import { LEGACY_EMBEDDED_KEYSTORE_MIGRATION_MESSAGE } from "../../../wallet/legacy-embedded-keystore.js";
3
3
  import { readWalletProviderRegistry } from "../../../wallet/wallet-provider-registry.js";
4
4
  import { resolveSatBondProgramIdFromEnv, resolveSatMintAddressFromEnv, resolveSatMintProgramIdFromEnv, resolveSatProgramIdFromEnv } from "../../../config/sat-runtime-ids.js";
5
5
  import { callLocalSocketSigner, requireLocalSocketSignerPath } from "../../../wallet/providers/local-socket-signer-adapter.js";
6
6
  import { resolveWalletProviderId } from "../../../wallet/wallet-provider-resolver.js";
7
- import { enforceWalletCustodyForAutonomousSend } from "../../../wallet/wallet-custody.js";
7
+ import { createSignerReviewApprovalRequest } from "../../../wallet/wallet-send-approvals.js";
8
8
  import "../../../plugin-sdk/sat-runtime.js";
9
- import { inspectSatCycleRegistryMeta, inspectSatMinerCyclesByAddress } from "./rpc-read.js";
9
+ import { SAT_BOND_INSTRUCTION_DISCRIMINATORS, SAT_INSTRUCTION_DISCRIMINATORS, SAT_PROTOCOL_CONSTANTS, resolveSatGenesisProfileContract } from "./protocol-contract.js";
10
+ import { inspectSatAddressLookupTable, inspectSatChainSlot, inspectSatCycle, inspectSatCycleRegistryMeta, inspectSatMinerCyclesByAddress } from "./rpc-read.js";
10
11
  import { decodeHash32 } from "./hash-spec.js";
11
- import { SAT_BOND_INSTRUCTION_DISCRIMINATORS, SAT_INSTRUCTION_DISCRIMINATORS } from "./protocol-contract.js";
12
+ import { resolveSatSignerCodec } from "./signer-codec-manifest.js";
13
+ import { buildSatSubmissionOperationKey, claimSatSubmission, digestSatSubmissionIntent, updateSatSubmission, waitForSatSubmissionLease } from "./submission-ledger.js";
12
14
  import { createRequire } from "node:module";
15
+ import { isDeepStrictEqual } from "node:util";
16
+ import { createHash } from "node:crypto";
17
+ import { AsyncLocalStorage } from "node:async_hooks";
13
18
 
14
19
  //#region extensions/sat-mining/src/solana-submit.ts
15
20
  const require = createRequire(import.meta.url);
@@ -37,13 +42,37 @@ const SAT_TREASURY_STATE_SEED = "sat_treasury_state";
37
42
  const SAT_REGISTRY_RESERVE_SEED = "sat_registry_reserve";
38
43
  const SAT_REBATE_VAULT_SEED = "sat_rebate_vault";
39
44
  const SAT_TREASURY_VAULT_SEED = "sat_treasury_vault";
45
+ const SAT_UNLOCK_INTERVAL_STATE_SEED = "sat_unlock_interval_state";
40
46
  const SAT_CYCLE_REGISTRY_PAGE_CAPACITY = 64;
41
47
  const MINING_POOL_SEED = "mining_pool";
42
48
  const MINING_STAKE_SEED = "mining_stake";
43
49
  const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
44
50
  const ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
51
+ const SLOT_HASHES_SYSVAR_ID = "SysvarS1otHashes111111111111111111111111111";
52
+ const SAT_DISTRIBUTION_LOOKUP_MIN_MINERS = 16;
53
+ const SAT_LOOKUP_TABLE_EXTEND_CHUNK_SIZE = 20;
45
54
  const IX = SAT_INSTRUCTION_DISCRIMINATORS;
46
55
  const BOND_IX = SAT_BOND_INSTRUCTION_DISCRIMINATORS;
56
+ const VAULT_BOND_ACTIONS = new Set([
57
+ "updateBondTierPolicy",
58
+ "openBondPosition",
59
+ "increaseBondPosition",
60
+ "requestBondUnlock",
61
+ "cancelBondUnlock",
62
+ "finalizeBondUnlock",
63
+ "syncBondStakingRewards",
64
+ "syncBondStakingPosition",
65
+ "claimBondStakingRewards",
66
+ "claimUnallocatedStakingRewards"
67
+ ]);
68
+ const satSubmissionWorkflowStorage = new AsyncLocalStorage();
69
+ async function runWithSatSubmissionWorkflow(workflowId, task) {
70
+ const normalized = workflowId.trim();
71
+ if (!normalized || normalized.length > 240 || /[\u0000-\u001f\u007f]/u.test(normalized)) {
72
+ throw new Error("SAT submission idempotency key must contain 1-240 printable characters");
73
+ }
74
+ return await satSubmissionWorkflowStorage.run(normalized, task);
75
+ }
47
76
  function satSubmitDebug(message) {
48
77
  if (String(process.env.FASED_SAT_SUBMIT_DEBUG ?? "").trim() === "1") {
49
78
  console.error(message);
@@ -84,6 +113,10 @@ function resolveSatWalletId(cfg) {
84
113
  const value = cfg.plugins?.entries?.["sat-mining"]?.config?.walletId;
85
114
  return typeof value === "string" && value.trim() ? value.trim() : undefined;
86
115
  }
116
+ function resolveSatCluster(cfg) {
117
+ const value = cfg.plugins?.entries?.["sat-mining"]?.config?.network;
118
+ return value === "local" || value === "mainnet-beta" || value === "devnet" ? value : "devnet";
119
+ }
87
120
  function resolveSatEffectiveEnv(cfg, env) {
88
121
  return {
89
122
  ...env,
@@ -93,68 +126,46 @@ function resolveSatEffectiveEnv(cfg, env) {
93
126
  function resolveSatProviderId(cfg, env) {
94
127
  const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
95
128
  const walletId = resolveSatWalletId(cfg);
129
+ const signerSocket = String(effectiveEnv.FASED_WALLET_LOCAL_SIGNER_SOCKET ?? "").trim();
96
130
  if (walletId) {
97
- const hasSelfHostedSignerMaterial = String(effectiveEnv.FASED_WALLET_LOCAL_SIGNER_SOCKET ?? "").trim() || String(effectiveEnv.FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET ?? "").trim() || String(walletEnvValue(effectiveEnv, "FASED_WALLET_SOLANA_KEYSTORE_PATH", walletId) ?? "").trim();
98
- try {
99
- const wallet = readWalletProviderRegistry(effectiveEnv).wallets.find((entry) => entry.id === walletId);
100
- if (wallet?.providerId === "local-socket-signer") {
101
- return wallet.providerId;
102
- }
103
- if (hasSelfHostedSignerMaterial) {
104
- return "local-socket-signer";
105
- }
106
- if (wallet?.providerId) {
107
- return wallet.providerId;
108
- }
109
- } catch {}
110
- if (hasSelfHostedSignerMaterial) {
111
- return "local-socket-signer";
131
+ const wallet = readWalletProviderRegistry(effectiveEnv).wallets.find((entry) => entry.id === walletId);
132
+ if (wallet?.providerId === "embedded-keystore") {
133
+ throw new Error(LEGACY_EMBEDDED_KEYSTORE_MIGRATION_MESSAGE);
134
+ }
135
+ if (wallet?.providerId && wallet.providerId !== "local-socket-signer") {
136
+ return wallet.providerId;
137
+ }
138
+ if (wallet?.providerId === "local-socket-signer" && !signerSocket) {
139
+ throw new Error("SAT mining requires the actual protocol-v2 fased-signerd application socket; legacy keystore paths and backend sockets are not signer capability.");
140
+ }
141
+ if (wallet?.providerId === "local-socket-signer") {
142
+ return wallet.providerId;
112
143
  }
113
144
  }
114
- return resolveWalletProviderId(cfg, effectiveEnv);
115
- }
116
- async function enforceSatCustodyAutonomousSigning(cfg, env) {
117
- const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
118
- const walletCfg = resolveWalletRuntimeConfig(cfg, effectiveEnv);
119
- const walletId = resolveSatWalletId(cfg);
120
- if (walletCfg.execution.mode !== "autonomous") {
121
- return;
122
- }
123
- const custodyGate = await enforceWalletCustodyForAutonomousSend({
124
- wallet: walletCfg,
125
- env: effectiveEnv,
126
- cfg,
127
- walletId,
128
- approvalHost: String(effectiveEnv.FASED_WALLET_CUSTODY_ACTIVE_HOST ?? effectiveEnv.FASED_A2A_ORIGIN ?? "127.0.0.1")
129
- });
130
- if (!custodyGate.ok) {
131
- throw new Error(custodyGate.message);
145
+ const providerId = resolveWalletProviderId(cfg, effectiveEnv);
146
+ if (providerId === "local-socket-signer" && !signerSocket) {
147
+ throw new Error("SAT mining requires the actual protocol-v2 fased-signerd application socket; configure FASED_WALLET_LOCAL_SIGNER_SOCKET.");
132
148
  }
149
+ return providerId;
133
150
  }
134
- function resolveSatRegistrySolanaAddress(cfg, env) {
151
+ async function resolveSatLocalSignerAddress(cfg, env, errorMessage, verifyCapabilities = true) {
135
152
  const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
136
153
  const walletId = resolveSatWalletId(cfg);
137
154
  if (!walletId) {
138
- return "";
155
+ throw new Error("SAT mining local signer address lookup requires an attached walletId");
139
156
  }
140
- const wallet = readWalletProviderRegistry(effectiveEnv).wallets.find((entry) => entry.id === walletId);
141
- return typeof wallet?.addresses?.solana === "string" ? wallet.addresses.solana.trim() : "";
142
- }
143
- async function resolveSatLocalSignerAddress(cfg, env, errorMessage) {
144
- const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
145
- const walletId = resolveSatWalletId(cfg);
146
- const result = await callLocalSocketSigner(requireLocalSocketSignerPath(effectiveEnv), {
147
- op: "getAddresses",
148
- ...walletId ? { walletId } : {}
157
+ const socketPath = requireLocalSocketSignerPath(effectiveEnv);
158
+ if (verifyCapabilities) {
159
+ await requireTypedSatSignerCapabilities(socketPath, "solana.satAction");
160
+ }
161
+ const result = await callLocalSocketSigner(socketPath, {
162
+ op: "v2.wallet.get",
163
+ walletId
149
164
  });
150
- const signer = String(result.solana ?? "").trim();
165
+ const signer = String(result.publicKey ?? "").trim();
151
166
  if (signer) {
152
167
  return signer;
153
168
  }
154
- const fallback = resolveSatRegistrySolanaAddress(cfg, env);
155
- if (fallback) {
156
- return fallback;
157
- }
158
169
  throw new Error(errorMessage);
159
170
  }
160
171
  function encodeU64(value) {
@@ -203,7 +214,6 @@ function assertDedicatedBondProgram(env) {
203
214
  async function resolveSatValidatorAuthority(_config) {
204
215
  const cfg = loadConfigForSatRuntime(_config);
205
216
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
206
- await enforceSatCustodyAutonomousSigning(cfg, effectiveEnv);
207
217
  if (resolveSatProviderId(cfg, effectiveEnv) !== "local-socket-signer") {
208
218
  throw new Error("SAT mining unattended signing currently requires local-socket-signer for validator authority resolution");
209
219
  }
@@ -214,7 +224,7 @@ async function prepareLocalSignerSubmitContext(cfg, env) {
214
224
  const solana = await loadSolanaWeb3();
215
225
  const walletId = resolveSatWalletId(cfg);
216
226
  const socketPath = requireLocalSocketSignerPath(effectiveEnv);
217
- const signerAddress = await resolveSatLocalSignerAddress(cfg, effectiveEnv, "local-socket-signer returned no Solana address for SAT mining wallet");
227
+ const signerAddress = await resolveSatLocalSignerAddress(cfg, effectiveEnv, "local-socket-signer returned no Solana address for SAT mining wallet", false);
218
228
  const signer = new solana.PublicKey(signerAddress);
219
229
  return {
220
230
  effectiveEnv,
@@ -226,39 +236,645 @@ async function prepareLocalSignerSubmitContext(cfg, env) {
226
236
  };
227
237
  }
228
238
  async function buildLocalSignerInstructionRequest(params) {
229
- const keys = await params.spec.accountResolver(params.solana, params.signer);
230
- satSubmitDebug(`[sat-submit-debug] data_len=${params.spec.data.length} disc=${params.spec.data[0] ?? -1} keys=${keys.length}`);
239
+ const resolved = await params.spec.accountResolver(params.solana, params.signer);
240
+ const keys = Array.isArray(resolved) ? resolved : resolved.keys;
241
+ const context = Array.isArray(resolved) ? undefined : resolved.context;
242
+ const programId = params.spec.programId ?? resolveSatProgramIdFromEnv(params.env);
243
+ const mainProgramId = resolveSatProgramIdFromEnv(params.env);
244
+ const bondProgramId = resolveSatBondProgramIdFromEnv(params.env).trim() || undefined;
245
+ const codec = resolveSatSignerCodec({
246
+ programId,
247
+ mainProgramId,
248
+ bondProgramId,
249
+ data: params.spec.data
250
+ });
251
+ satSubmitDebug(`[sat-submit-debug] action=${codec.action} data_len=${params.spec.data.length} disc=${params.spec.data[0] ?? -1} keys=${keys.length}`);
231
252
  return {
232
- ...params.walletId ? { walletId: params.walletId } : {},
233
- programId: params.spec.programId ?? SAT_PROGRAM_ID(),
253
+ action: codec.action,
254
+ programId,
234
255
  dataBase64: params.spec.data.toString("base64"),
235
256
  keys: keys.map((key) => ({
236
257
  pubkey: key.pubkey.toBase58(),
237
258
  isSigner: key.isSigner,
238
259
  isWritable: key.isWritable
239
- }))
260
+ })),
261
+ ...params.spec.addressLookupTables?.length ? { addressLookupTables: params.spec.addressLookupTables } : {},
262
+ ...context ? { context } : {}
263
+ };
264
+ }
265
+ const REQUIRED_SAT_SIGNER_FEATURES = [
266
+ "failClosedPolicies",
267
+ "policyHashes",
268
+ "durableCaps",
269
+ "atomicIdempotency",
270
+ "ambiguousBroadcastReconciliation",
271
+ "signerOwnedKeys",
272
+ "typedSolanaTransactions",
273
+ "typedSATActions"
274
+ ];
275
+ async function requireTypedSatSignerCapabilities(socketPath, intentType) {
276
+ const result = await callLocalSocketSigner(socketPath, { op: "v2.capabilities" });
277
+ const capabilities = result.capabilities;
278
+ const protocol = capabilities?.protocol;
279
+ const features = new Set(capabilities?.features ?? []);
280
+ const states = new Set(capabilities?.operationStates ?? []);
281
+ const missingFeatures = REQUIRED_SAT_SIGNER_FEATURES.filter((feature) => !features.has(feature));
282
+ const missingStates = [
283
+ "reserved",
284
+ "broadcast",
285
+ "confirmed",
286
+ "failed",
287
+ "unknown"
288
+ ].filter((state) => !states.has(state));
289
+ const missingVaultReviewFeatures = intentType === "solana.vaultBondAction" ? [
290
+ "signerOwnedReviewPrepareExecute",
291
+ "exactPreparedTransactions",
292
+ "reviewedVaultBondActions",
293
+ "signerOwnedStateRecheck",
294
+ "durableReviewAuthorization"
295
+ ].filter((feature) => !features.has(feature)) : [];
296
+ const missingLookupFeatures = intentType === "solana.satLookupTable" && !features.has("typedSATAddressLookupTables") ? ["typedSATAddressLookupTables"] : [];
297
+ if (result.ready !== true || protocol?.current !== 2 || typeof protocol.min !== "number" || protocol.min > 2 || typeof protocol.max !== "number" || protocol.max < 2 || !capabilities?.intentTypes?.includes(intentType) || missingFeatures.length > 0 || missingLookupFeatures.length > 0 || intentType === "solana.vaultBondAction" && !features.has("typedVaultBondActions") || missingVaultReviewFeatures.length > 0 || missingStates.length > 0) {
298
+ throw new Error(`local-socket-signer does not support the required typed SAT protocol-v2 contract${missingFeatures.length > 0 ? `; missing features: ${missingFeatures.join(", ")}` : ""}${missingVaultReviewFeatures.length > 0 ? `; missing reviewed Vault features: ${missingVaultReviewFeatures.join(", ")}` : ""}${missingLookupFeatures.length > 0 ? `; missing SAT lookup features: ${missingLookupFeatures.join(", ")}` : ""}${missingStates.length > 0 ? `; missing states: ${missingStates.join(", ")}` : ""}`);
299
+ }
300
+ }
301
+ async function reconcileTypedSatOperation(params) {
302
+ let operation = params.operation ?? await callLocalSocketSigner(params.socketPath, {
303
+ op: "v2.operation.get",
304
+ walletId: params.walletId,
305
+ request: { requestId: params.requestId }
306
+ });
307
+ if (operation.state === "broadcast" || operation.state === "unknown") {
308
+ try {
309
+ operation = await callLocalSocketSigner(params.socketPath, {
310
+ op: "v2.operation.reconcile",
311
+ walletId: params.walletId,
312
+ request: { requestId: params.requestId }
313
+ });
314
+ } catch {}
315
+ }
316
+ return operation;
317
+ }
318
+ function assertSatSignerOperationIdentity(operation, requestId) {
319
+ if (operation.requestId !== requestId) {
320
+ throw new Error(`SAT signer returned request ${operation.requestId || "<empty>"} while reconciling ${requestId}`);
321
+ }
322
+ return operation;
323
+ }
324
+ function signerStateForLedger(state) {
325
+ return state;
326
+ }
327
+ function assertSatLookupTableAction(value) {
328
+ if (value !== "create" && value !== "extend" && value !== "deactivate" && value !== "close") {
329
+ throw new Error(`unsupported SAT lookup-table action ${value}`);
330
+ }
331
+ }
332
+ var SatSubmissionUnresolvedError = class extends Error {
333
+ constructor(params) {
334
+ super(`SAT signer operation ${params.requestId} remains ${params.state}${params.signature ? ` with signature ${params.signature}` : ""}; it is unresolved and must be reconciled with the same idempotency key before any new submission${params.detail ? ` (${params.detail})` : ""}`);
335
+ this.name = "SatSubmissionUnresolvedError";
336
+ this.requestId = params.requestId;
337
+ this.signature = params.signature;
338
+ }
339
+ };
340
+ async function executeTypedSatIntent(params) {
341
+ const isLookupTable = params.lookupTable != null;
342
+ const isVaultBond = !isLookupTable && params.action !== "cleanupBatch" && VAULT_BOND_ACTIONS.has(params.action);
343
+ const intentType = isLookupTable ? "solana.satLookupTable" : isVaultBond ? "solana.vaultBondAction" : "solana.satAction";
344
+ await requireTypedSatSignerCapabilities(params.socketPath, intentType);
345
+ const intent = isLookupTable ? (() => {
346
+ if (params.instruction || params.instructions || !params.lookupTable) {
347
+ throw new Error("typed SAT lookup-table execution accepts only semantic lookup details");
348
+ }
349
+ const action = params.action;
350
+ assertSatLookupTableAction(action);
351
+ return {
352
+ type: "solana.satLookupTable",
353
+ action,
354
+ lookupTable: params.lookupTable
355
+ };
356
+ })() : isVaultBond ? (() => {
357
+ if (!params.instruction || params.instructions) {
358
+ throw new Error("typed Vault bond execution requires exactly one semantic instruction");
359
+ }
360
+ return {
361
+ type: "solana.vaultBondAction",
362
+ cluster: params.cluster,
363
+ ...params.instruction
364
+ };
365
+ })() : {
366
+ type: "solana.satAction",
367
+ action: params.action,
368
+ ...params.instruction ?? {},
369
+ ...params.instructions ? { instructions: params.instructions } : {}
370
+ };
371
+ const policy = await callLocalSocketSigner(params.socketPath, {
372
+ op: "v2.policy.get",
373
+ walletId: params.walletId
374
+ });
375
+ const intentDigest = digestSatSubmissionIntent({
376
+ walletId: params.walletId,
377
+ policyHash: policy.hash,
378
+ intent
379
+ });
380
+ const operationKey = buildSatSubmissionOperationKey(intent);
381
+ const workflowId = satSubmissionWorkflowStorage.getStore() ?? `derived:${operationKey}:${intentDigest}`;
382
+ let claim = await claimSatSubmission({
383
+ walletId: params.walletId,
384
+ workflowId,
385
+ operationKey,
386
+ intentDigest,
387
+ action: params.action,
388
+ env: params.env
389
+ });
390
+ if (!claim.claimed) {
391
+ await waitForSatSubmissionLease({
392
+ walletId: params.walletId,
393
+ requestId: claim.record.requestId,
394
+ env: params.env
395
+ });
396
+ claim = await claimSatSubmission({
397
+ walletId: params.walletId,
398
+ workflowId,
399
+ operationKey,
400
+ intentDigest,
401
+ action: params.action,
402
+ env: params.env,
403
+ owner: claim.owner
404
+ });
405
+ if (!claim.claimed) {
406
+ throw new Error(`SAT submission ${claim.record.requestId} could not acquire its durable execution lease`);
407
+ }
408
+ }
409
+ const requestId = claim.record.requestId;
410
+ let resumedReviewedOperation;
411
+ if (intent.type === "solana.vaultBondAction") {
412
+ let reviewWasSigned = false;
413
+ try {
414
+ let review;
415
+ try {
416
+ review = await callLocalSocketSigner(params.socketPath, {
417
+ op: "v2.review.get",
418
+ walletId: params.walletId,
419
+ request: { requestId }
420
+ });
421
+ } catch (lookupError) {
422
+ if (!String(lookupError).includes("signer review not found")) {
423
+ throw lookupError;
424
+ }
425
+ review = await callLocalSocketSigner(params.socketPath, {
426
+ op: "v2.review.prepare",
427
+ walletId: params.walletId,
428
+ request: {
429
+ requestId,
430
+ policyHash: policy.hash,
431
+ mode: "reviewed",
432
+ intent
433
+ }
434
+ });
435
+ }
436
+ if (review.requestId !== requestId || review.policyHash !== policy.hash || review.mode !== "reviewed" || review.intentType !== intent.type || !isDeepStrictEqual(review.semanticIntent, intent)) {
437
+ throw new Error(`Vault bond review ${requestId} does not match the exact SAT intent`);
438
+ }
439
+ if (review.state === "prepared") {
440
+ const approval = createSignerReviewApprovalRequest({
441
+ review,
442
+ role: "vault",
443
+ walletId: params.walletId,
444
+ requestedBy: "sat-mining-vault",
445
+ assetSymbol: "SAT",
446
+ assetName: "SAT bond",
447
+ memo: `Reviewed Vault bond action: ${intent.action}`,
448
+ env: params.env
449
+ });
450
+ await updateSatSubmission({
451
+ walletId: params.walletId,
452
+ requestId,
453
+ intentDigest,
454
+ state: "reserved",
455
+ error: `review ${approval.id} pending`,
456
+ owner: claim.owner,
457
+ releaseLease: true,
458
+ env: params.env
459
+ });
460
+ throw new Error(`Vault bond review ${approval.id} is pending in Wallet Approvals for ${intent.action}; approve it there with the signer-owned passkey`);
461
+ }
462
+ reviewWasSigned = true;
463
+ resumedReviewedOperation = assertSatSignerOperationIdentity(await reconcileTypedSatOperation({
464
+ socketPath: params.socketPath,
465
+ walletId: params.walletId,
466
+ requestId
467
+ }), requestId);
468
+ } catch (error) {
469
+ await updateSatSubmission({
470
+ walletId: params.walletId,
471
+ requestId,
472
+ intentDigest,
473
+ state: reviewWasSigned ? "unknown" : "reserved",
474
+ error: error instanceof Error ? error.message : String(error),
475
+ owner: claim.owner,
476
+ releaseLease: true,
477
+ env: params.env
478
+ }).catch(() => undefined);
479
+ throw error;
480
+ }
481
+ }
482
+ const executeExactOrRecover = async () => {
483
+ try {
484
+ return await callLocalSocketSigner(params.socketPath, {
485
+ op: "v2.execute",
486
+ walletId: params.walletId,
487
+ request: {
488
+ requestId,
489
+ policyHash: policy.hash,
490
+ intent
491
+ }
492
+ });
493
+ } catch (executeError) {
494
+ try {
495
+ return await callLocalSocketSigner(params.socketPath, {
496
+ op: "v2.operation.get",
497
+ walletId: params.walletId,
498
+ request: { requestId }
499
+ });
500
+ } catch (lookupError) {
501
+ const detail = `${executeError instanceof Error ? executeError.message : String(executeError)}; ${lookupError instanceof Error ? lookupError.message : String(lookupError)}`;
502
+ await updateSatSubmission({
503
+ walletId: params.walletId,
504
+ requestId,
505
+ intentDigest,
506
+ state: claim.record.state === "confirmed" || claim.record.state === "failed" ? claim.record.state : "unknown",
507
+ ...claim.record.signature ? { signature: claim.record.signature } : {},
508
+ error: detail,
509
+ owner: claim.owner,
510
+ releaseLease: true,
511
+ env: params.env
512
+ });
513
+ throw new SatSubmissionUnresolvedError({
514
+ requestId,
515
+ state: "unknown",
516
+ detail
517
+ });
518
+ }
519
+ }
520
+ };
521
+ let operation;
522
+ if (resumedReviewedOperation) {
523
+ operation = resumedReviewedOperation;
524
+ } else if (!claim.created) {
525
+ const callerStateWasAmbiguous = claim.record.state === "broadcast" || claim.record.state === "unknown";
526
+ try {
527
+ operation = assertSatSignerOperationIdentity(await callLocalSocketSigner(params.socketPath, {
528
+ op: "v2.operation.get",
529
+ walletId: params.walletId,
530
+ request: { requestId }
531
+ }), requestId);
532
+ operation = assertSatSignerOperationIdentity(await reconcileTypedSatOperation({
533
+ socketPath: params.socketPath,
534
+ walletId: params.walletId,
535
+ requestId,
536
+ operation
537
+ }), requestId);
538
+ } catch (lookupError) {
539
+ if (claim.record.signature) {
540
+ await updateSatSubmission({
541
+ walletId: params.walletId,
542
+ requestId,
543
+ intentDigest,
544
+ state: claim.record.state === "confirmed" ? "confirmed" : "unknown",
545
+ signature: claim.record.signature,
546
+ error: lookupError instanceof Error ? lookupError.message : String(lookupError),
547
+ owner: claim.owner,
548
+ releaseLease: true,
549
+ env: params.env
550
+ });
551
+ throw new SatSubmissionUnresolvedError({
552
+ requestId,
553
+ state: claim.record.state === "confirmed" ? "confirmed-but-unverified" : "unknown",
554
+ signature: claim.record.signature,
555
+ detail: lookupError instanceof Error ? lookupError.message : String(lookupError)
556
+ });
557
+ }
558
+ if (claim.record.state === "failed" || claim.record.state === "confirmed") {
559
+ const detail = lookupError instanceof Error ? lookupError.message : String(lookupError);
560
+ await updateSatSubmission({
561
+ walletId: params.walletId,
562
+ requestId,
563
+ intentDigest,
564
+ state: claim.record.state,
565
+ error: detail,
566
+ owner: claim.owner,
567
+ releaseLease: true,
568
+ env: params.env
569
+ });
570
+ if (claim.record.state === "failed") {
571
+ throw new Error(claim.record.error || `SAT signer operation ${requestId} failed`);
572
+ }
573
+ throw new SatSubmissionUnresolvedError({
574
+ requestId,
575
+ state: "confirmed-without-signature",
576
+ detail
577
+ });
578
+ }
579
+ operation = await executeExactOrRecover();
580
+ }
581
+ if (operation.state === "reserved" && !operation.signature) {
582
+ if (callerStateWasAmbiguous) {
583
+ const detail = `signer regressed to reserved after caller persisted ${claim.record.state}`;
584
+ await updateSatSubmission({
585
+ walletId: params.walletId,
586
+ requestId,
587
+ intentDigest,
588
+ state: "unknown",
589
+ ...claim.record.signature ? { signature: claim.record.signature } : {},
590
+ error: detail,
591
+ owner: claim.owner,
592
+ releaseLease: true,
593
+ env: params.env
594
+ });
595
+ throw new SatSubmissionUnresolvedError({
596
+ requestId,
597
+ state: "unknown",
598
+ signature: claim.record.signature,
599
+ detail
600
+ });
601
+ }
602
+ operation = await executeExactOrRecover();
603
+ }
604
+ } else {
605
+ operation = await executeExactOrRecover();
606
+ }
607
+ try {
608
+ operation = assertSatSignerOperationIdentity(operation, requestId);
609
+ operation = assertSatSignerOperationIdentity(await reconcileTypedSatOperation({
610
+ socketPath: params.socketPath,
611
+ walletId: params.walletId,
612
+ requestId,
613
+ operation
614
+ }), requestId);
615
+ } catch (error) {
616
+ const detail = error instanceof Error ? error.message : String(error);
617
+ await updateSatSubmission({
618
+ walletId: params.walletId,
619
+ requestId,
620
+ intentDigest,
621
+ state: claim.record.state === "confirmed" || claim.record.state === "failed" ? claim.record.state : "unknown",
622
+ ...claim.record.signature ? { signature: claim.record.signature } : {},
623
+ error: detail,
624
+ owner: claim.owner,
625
+ releaseLease: true,
626
+ env: params.env
627
+ });
628
+ throw new SatSubmissionUnresolvedError({
629
+ requestId,
630
+ state: "unknown",
631
+ detail
632
+ });
633
+ }
634
+ await updateSatSubmission({
635
+ walletId: params.walletId,
636
+ requestId,
637
+ intentDigest,
638
+ state: signerStateForLedger(operation.state),
639
+ ...operation.signature ? { signature: operation.signature } : {},
640
+ ...operation.error ? { error: operation.error } : {},
641
+ owner: claim.owner,
642
+ releaseLease: true,
643
+ env: params.env
644
+ });
645
+ if (operation.state === "failed") {
646
+ throw new Error(operation.error || `SAT signer operation ${requestId} failed`);
647
+ }
648
+ if (operation.state !== "confirmed" || !operation.signature) {
649
+ throw new SatSubmissionUnresolvedError({
650
+ requestId,
651
+ state: operation.state,
652
+ signature: operation.signature,
653
+ detail: operation.error
654
+ });
655
+ }
656
+ return {
657
+ ...operation,
658
+ signature: operation.signature
659
+ };
660
+ }
661
+ function assertSatLookupTableEnabled(env) {
662
+ if (String(env.FASED_SAT_ENABLE_ALT_V0 ?? "").trim() !== "1") {
663
+ throw new Error("SAT ALT/v0 support is disabled; set FASED_SAT_ENABLE_ALT_V0=1");
664
+ }
665
+ }
666
+ async function executeTypedSatLookupOperation(params) {
667
+ return await executeTypedSatIntent({
668
+ socketPath: params.context.socketPath,
669
+ walletId: params.context.walletId,
670
+ action: params.action,
671
+ lookupTable: {
672
+ address: params.address,
673
+ ...params.recentSlot == null ? {} : { recentSlot: String(params.recentSlot) },
674
+ ...params.addresses?.length ? { addresses: params.addresses } : {}
675
+ },
676
+ cluster: resolveSatCluster(params.cfg),
677
+ env: params.context.effectiveEnv
678
+ });
679
+ }
680
+ async function readValidatedSatLookupTable(params) {
681
+ const state = await inspectSatAddressLookupTable(params.config, { address: params.address });
682
+ if (!state) {
683
+ return null;
684
+ }
685
+ if (state.authority !== params.authority) {
686
+ throw new Error("SAT distribution lookup table is not controlled by the Mining signer");
687
+ }
688
+ if (!state.active) {
689
+ throw new Error("SAT distribution lookup table is not active");
690
+ }
691
+ return state;
692
+ }
693
+ async function waitForSatLookupTable(params) {
694
+ let lastError;
695
+ for (let attempt = 0; attempt < 24; attempt += 1) {
696
+ try {
697
+ const state = await readValidatedSatLookupTable(params);
698
+ if (state) {
699
+ const currentSlot = await inspectSatChainSlot(params.config);
700
+ if (!params.requireNextSlot || currentSlot > state.lastExtendedSlot) {
701
+ return state;
702
+ }
703
+ }
704
+ } catch (error) {
705
+ lastError = error;
706
+ }
707
+ await new Promise((resolve) => setTimeout(resolve, 250));
708
+ }
709
+ throw new Error(`SAT distribution lookup table did not become active for use within 6s${lastError instanceof Error ? `: ${lastError.message}` : ""}`);
710
+ }
711
+ async function ensureSatDistributionLookupTable(params) {
712
+ assertSatLookupTableEnabled(params.context.effectiveEnv);
713
+ const desiredAddresses = [...new Set(params.addresses.map((entry) => entry.trim()))].filter(Boolean);
714
+ if (desiredAddresses.length === 0 || desiredAddresses.length > 256) {
715
+ throw new Error("SAT distribution lookup table requires 1-256 exact account addresses");
716
+ }
717
+ let lookupTable = params.lookupTableAddress?.trim() ?? "";
718
+ let state = lookupTable ? await readValidatedSatLookupTable({
719
+ config: params.config,
720
+ address: lookupTable,
721
+ authority: params.context.signerAddress
722
+ }) : null;
723
+ let created = false;
724
+ const transactionHashes = [];
725
+ if (!lookupTable) {
726
+ const currentSlot = await inspectSatChainSlot(params.config);
727
+ const recentSlot = Math.max(0, currentSlot - 1);
728
+ const [, derivedAddress] = params.context.solana.AddressLookupTableProgram.createLookupTable({
729
+ authority: params.context.signer,
730
+ payer: params.context.signer,
731
+ recentSlot
732
+ });
733
+ lookupTable = derivedAddress.toBase58();
734
+ state = await readValidatedSatLookupTable({
735
+ config: params.config,
736
+ address: lookupTable,
737
+ authority: params.context.signerAddress
738
+ });
739
+ if (!state) {
740
+ try {
741
+ const submitted = await executeTypedSatLookupOperation({
742
+ context: params.context,
743
+ cfg: params.cfg,
744
+ action: "create",
745
+ address: lookupTable,
746
+ recentSlot
747
+ });
748
+ transactionHashes.push(submitted.signature);
749
+ created = true;
750
+ } catch (error) {
751
+ if (error instanceof SatSubmissionUnresolvedError) {
752
+ throw error;
753
+ }
754
+ try {
755
+ state = await waitForSatLookupTable({
756
+ config: params.config,
757
+ address: lookupTable,
758
+ authority: params.context.signerAddress,
759
+ requireNextSlot: false
760
+ });
761
+ } catch {
762
+ throw error;
763
+ }
764
+ }
765
+ state ??= await waitForSatLookupTable({
766
+ config: params.config,
767
+ address: lookupTable,
768
+ authority: params.context.signerAddress,
769
+ requireNextSlot: false
770
+ });
771
+ }
772
+ }
773
+ if (!state) {
774
+ throw new Error("SAT distribution lookup table was not found at the confirmed commitment");
775
+ }
776
+ const existing = new Set(state.addresses);
777
+ const missing = desiredAddresses.filter((entry) => !existing.has(entry));
778
+ for (let offset = 0; offset < missing.length; offset += SAT_LOOKUP_TABLE_EXTEND_CHUNK_SIZE) {
779
+ const addresses = missing.slice(offset, offset + SAT_LOOKUP_TABLE_EXTEND_CHUNK_SIZE);
780
+ try {
781
+ const submitted = await executeTypedSatLookupOperation({
782
+ context: params.context,
783
+ cfg: params.cfg,
784
+ action: "extend",
785
+ address: lookupTable,
786
+ addresses
787
+ });
788
+ transactionHashes.push(submitted.signature);
789
+ } catch (error) {
790
+ if (error instanceof SatSubmissionUnresolvedError) {
791
+ throw error;
792
+ }
793
+ const concurrentState = await waitForSatLookupTable({
794
+ config: params.config,
795
+ address: lookupTable,
796
+ authority: params.context.signerAddress,
797
+ requireNextSlot: false
798
+ }).catch(() => null);
799
+ if (!concurrentState || addresses.some((address) => !concurrentState.addresses.includes(address))) {
800
+ throw error;
801
+ }
802
+ }
803
+ }
804
+ const ready = await waitForSatLookupTable({
805
+ config: params.config,
806
+ address: lookupTable,
807
+ authority: params.context.signerAddress,
808
+ requireNextSlot: true
809
+ });
810
+ for (const address of desiredAddresses) {
811
+ if (!ready.addresses.includes(address)) {
812
+ throw new Error(`SAT distribution lookup table did not persist required account ${address}`);
813
+ }
814
+ }
815
+ return {
816
+ lookupTable,
817
+ created,
818
+ extended: missing.length > 0,
819
+ addressCount: ready.addresses.length,
820
+ transactionHashes
240
821
  };
241
822
  }
242
823
  async function submitInstructionViaLocalSigner(params) {
243
824
  const context = await prepareLocalSignerSubmitContext(params.cfg, params.env);
244
- const request = await buildLocalSignerInstructionRequest({
825
+ const baseRequest = await buildLocalSignerInstructionRequest({
245
826
  solana: context.solana,
246
827
  signer: context.signer,
247
- walletId: context.walletId,
828
+ env: context.effectiveEnv,
248
829
  spec: params
249
830
  });
250
- const submitted = await callLocalSocketSigner(context.socketPath, {
251
- op: "sendSolanaInstruction",
252
- request
831
+ if (!context.walletId) {
832
+ throw new Error("typed SAT signing requires an explicit mining walletId");
833
+ }
834
+ let managedLookupTable;
835
+ if (params.manageAddressLookupTable) {
836
+ managedLookupTable = await ensureSatDistributionLookupTable({
837
+ context: {
838
+ ...context,
839
+ walletId: context.walletId
840
+ },
841
+ cfg: params.cfg,
842
+ config: params.cfg,
843
+ lookupTableAddress: params.manageAddressLookupTable.lookupTableAddress,
844
+ addresses: baseRequest.keys.filter((key) => !key.isSigner).map((key) => key.pubkey)
845
+ });
846
+ }
847
+ const request = managedLookupTable ? {
848
+ ...baseRequest,
849
+ addressLookupTables: [managedLookupTable.lookupTable]
850
+ } : baseRequest;
851
+ const submitted = await executeTypedSatIntent({
852
+ socketPath: context.socketPath,
853
+ walletId: context.walletId,
854
+ action: request.action,
855
+ instruction: request,
856
+ cluster: resolveSatCluster(params.cfg),
857
+ env: context.effectiveEnv
253
858
  });
254
859
  return {
255
- txHash: submitted.txHash,
256
- signer: submitted.signer ?? context.signerAddress
860
+ txHash: submitted.signature,
861
+ signer: context.signerAddress,
862
+ signerState: submitted.state,
863
+ requestId: submitted.requestId,
864
+ ...request.addressLookupTables?.length ? {
865
+ transactionVersion: "v0",
866
+ lookupTableAddress: request.addressLookupTables[0]
867
+ } : { transactionVersion: "legacy" },
868
+ ...managedLookupTable ? {
869
+ lookupTableCreated: managedLookupTable.created,
870
+ lookupTableExtended: managedLookupTable.extended,
871
+ lookupTableAddressCount: managedLookupTable.addressCount,
872
+ lookupTableTransactionHashes: managedLookupTable.transactionHashes
873
+ } : {}
257
874
  };
258
875
  }
259
876
  async function submitInstruction(params) {
260
877
  const effectiveEnv = resolveSatEffectiveEnv(params.cfg, params.env);
261
- await enforceSatCustodyAutonomousSigning(params.cfg, effectiveEnv);
262
878
  if (resolveSatProviderId(params.cfg, effectiveEnv) !== "local-socket-signer") {
263
879
  throw new Error("SAT mining unattended submission currently requires local-socket-signer");
264
880
  }
@@ -267,6 +883,8 @@ async function submitInstruction(params) {
267
883
  env: effectiveEnv,
268
884
  data: params.data,
269
885
  programId: params.programId,
886
+ addressLookupTables: params.addressLookupTables,
887
+ manageAddressLookupTable: params.manageAddressLookupTable,
270
888
  accountResolver: params.accountResolver
271
889
  });
272
890
  }
@@ -278,7 +896,6 @@ async function submitInstructionBatch(params) {
278
896
  throw new Error("SAT cleanup batch exceeds signer limit");
279
897
  }
280
898
  const effectiveEnv = resolveSatEffectiveEnv(params.cfg, params.env);
281
- await enforceSatCustodyAutonomousSigning(params.cfg, effectiveEnv);
282
899
  if (resolveSatProviderId(params.cfg, effectiveEnv) !== "local-socket-signer") {
283
900
  throw new Error("SAT mining unattended batch submission currently requires local-socket-signer");
284
901
  }
@@ -288,21 +905,26 @@ async function submitInstructionBatch(params) {
288
905
  instructions.push(await buildLocalSignerInstructionRequest({
289
906
  solana: context.solana,
290
907
  signer: context.signer,
291
- walletId: context.walletId,
908
+ env: context.effectiveEnv,
292
909
  spec
293
910
  }));
294
911
  }
295
- const submitted = await callLocalSocketSigner(context.socketPath, {
296
- op: "sendSolanaInstructions",
297
- request: {
298
- ...context.walletId ? { walletId: context.walletId } : {},
299
- purpose: params.purpose,
300
- instructions
301
- }
912
+ if (!context.walletId) {
913
+ throw new Error("typed SAT cleanup signing requires an explicit mining walletId");
914
+ }
915
+ const submitted = await executeTypedSatIntent({
916
+ socketPath: context.socketPath,
917
+ walletId: context.walletId,
918
+ action: "cleanupBatch",
919
+ instructions,
920
+ cluster: resolveSatCluster(params.cfg),
921
+ env: context.effectiveEnv
302
922
  });
303
923
  return {
304
- txHash: submitted.txHash,
305
- signer: submitted.signer ?? context.signerAddress,
924
+ txHash: submitted.signature,
925
+ signer: context.signerAddress,
926
+ signerState: submitted.state,
927
+ requestId: submitted.requestId,
306
928
  instructionCount: instructions.length
307
929
  };
308
930
  }
@@ -390,12 +1012,8 @@ function buildClaimData(params) {
390
1012
  function buildMiningCrankData() {
391
1013
  return Buffer.from([IX.miningCrank]);
392
1014
  }
393
- function buildBootstrapData(params) {
394
- return Buffer.concat([
395
- Buffer.from([IX.bootstrap]),
396
- encodePubkey(params.authority),
397
- encodeU64(params.initialStake)
398
- ]);
1015
+ function buildTopUpRegistryReserveData(params) {
1016
+ return Buffer.concat([Buffer.from([IX.topUpRegistryReserve]), encodeU64(params.targetBalanceLamports)]);
399
1017
  }
400
1018
  function buildOpenCycleData(params) {
401
1019
  return Buffer.concat([Buffer.from([IX.openCycle]), encodeU64(params.cycleId)]);
@@ -412,16 +1030,6 @@ function buildWithdrawMinerCapitalData(params) {
412
1030
  function buildSetActiveCommitData(params) {
413
1031
  return Buffer.concat([Buffer.from([IX.setActiveCommit]), encodeU64(params.lamports)]);
414
1032
  }
415
- function buildInitBondTierPolicyData(params) {
416
- return Buffer.concat([
417
- Buffer.from([BOND_IX.initTierPolicy]),
418
- encodePubkey(params.updateAuthority),
419
- encodeU64(params.basicMinRaw),
420
- encodeU64(params.operatorMinRaw),
421
- encodeU64(params.unlockDelaySlots),
422
- encodeU64(params.scheduledEffectiveSlot ?? 0)
423
- ]);
424
- }
425
1033
  function buildUpdateBondTierPolicyData(params) {
426
1034
  return Buffer.concat([
427
1035
  Buffer.from([BOND_IX.updateTierPolicy]),
@@ -452,14 +1060,6 @@ function buildFinalizeBondUnlockData(env = process.env) {
452
1060
  assertDedicatedBondProgram(env);
453
1061
  return Buffer.from([BOND_IX.finalizeBondUnlock]);
454
1062
  }
455
- function buildInitBondStakingDistributorData(params, env = process.env) {
456
- assertDedicatedBondProgram(env);
457
- return Buffer.concat([
458
- Buffer.from([BOND_IX.initStakingDistributor]),
459
- encodePubkey(params.updateAuthority),
460
- encodeU64(params.minStakeRaw)
461
- ]);
462
- }
463
1063
  function buildSyncBondStakingRewardsData(env = process.env) {
464
1064
  assertDedicatedBondProgram(env);
465
1065
  return Buffer.from([BOND_IX.syncStakingRewards]);
@@ -472,22 +1072,75 @@ function buildClaimBondStakingRewardsData(env = process.env) {
472
1072
  assertDedicatedBondProgram(env);
473
1073
  return Buffer.from([BOND_IX.claimStakingRewards]);
474
1074
  }
475
- function buildSubmitCycleData(params) {
476
- if (params.allocationFp.length !== 25) {
477
- throw new Error(`expected 25 allocation buckets, got ${params.allocationFp.length}`);
1075
+ function buildClaimUnallocatedStakingRewardsData(env = process.env) {
1076
+ assertDedicatedBondProgram(env);
1077
+ return Buffer.from([BOND_IX.claimUnallocatedStakingRewards]);
1078
+ }
1079
+ function encodeAllocationFp(allocationFp) {
1080
+ if (allocationFp.length !== 25) {
1081
+ throw new Error(`expected 25 allocation buckets, got ${allocationFp.length}`);
1082
+ }
1083
+ return Buffer.concat(allocationFp.map((value) => {
1084
+ if (!Number.isSafeInteger(value) || value < 0 || value > 4294967295) {
1085
+ throw new Error(`invalid allocation bucket value: ${value}`);
1086
+ }
1087
+ const out = Buffer.alloc(4);
1088
+ out.writeUInt32LE(value);
1089
+ return out;
1090
+ }));
1091
+ }
1092
+ function buildSatCycleCommitment(params) {
1093
+ if (params.nonce.length !== 32) {
1094
+ throw new Error(`expected 32-byte cycle nonce, got ${params.nonce.length}`);
478
1095
  }
479
- const body = Buffer.concat([
480
- Buffer.from([IX.submitCycle]),
1096
+ const allocation = encodeAllocationFp(params.allocationFp);
1097
+ return createHash("sha256").update(Buffer.concat([
1098
+ Buffer.from("sat-cycle-commit-v1"),
1099
+ encodePubkey(params.programId ?? SAT_PROGRAM_ID()),
1100
+ encodePubkey(params.authority),
481
1101
  encodeU64(params.cycleId),
482
- Buffer.concat(params.allocationFp.map((value) => {
483
- const out = Buffer.alloc(4);
484
- out.writeUInt32LE(value);
485
- return out;
486
- })),
1102
+ encodeU64(params.committedLamports),
1103
+ params.nonce,
1104
+ allocation
1105
+ ])).digest();
1106
+ }
1107
+ function buildCommitCycleData(params) {
1108
+ if (params.commitment.length !== 32) {
1109
+ throw new Error(`expected 32-byte cycle commitment, got ${params.commitment.length}`);
1110
+ }
1111
+ return Buffer.concat([
1112
+ Buffer.from([IX.commitCycle]),
1113
+ encodeU64(params.cycleId),
1114
+ params.commitment
1115
+ ]);
1116
+ }
1117
+ function buildCloseCommitPhaseData(params) {
1118
+ return Buffer.concat([Buffer.from([IX.closeCommitPhase]), encodeU64(params.cycleId)]);
1119
+ }
1120
+ function buildSealCycleEntropyData(params) {
1121
+ return Buffer.concat([Buffer.from([IX.sealCycleEntropy]), encodeU64(params.cycleId)]);
1122
+ }
1123
+ function buildRevealCycleData(params) {
1124
+ if (params.nonce.length !== 32) {
1125
+ throw new Error(`expected 32-byte cycle nonce, got ${params.nonce.length}`);
1126
+ }
1127
+ return Buffer.concat([
1128
+ Buffer.from([IX.revealCycle]),
1129
+ encodeU64(params.cycleId),
1130
+ params.nonce,
1131
+ encodeAllocationFp(params.allocationFp),
487
1132
  Buffer.alloc(4)
488
1133
  ]);
489
- satSubmitDebug(`[sat-submit-build] allocs=${params.allocationFp.length} len=${body.length} cycle=${params.cycleId}`);
490
- return body;
1134
+ }
1135
+ function buildReleaseUnrevealedCommitData(params) {
1136
+ return Buffer.concat([
1137
+ Buffer.from([IX.releaseUnrevealedCommit]),
1138
+ encodeU64(params.cycleId),
1139
+ encodePubkey(params.minerAuthority)
1140
+ ]);
1141
+ }
1142
+ function buildAbortEmptyCycleData(params) {
1143
+ return Buffer.concat([Buffer.from([IX.abortEmptyCycle]), encodeU64(params.cycleId)]);
491
1144
  }
492
1145
  function buildClaimCycleRewardsData(params) {
493
1146
  return Buffer.concat([Buffer.from([IX.claimCycleRewards]), encodeU64(params.cycleId)]);
@@ -504,13 +1157,6 @@ function buildClaimCycleRewardsBatchData(params) {
504
1157
  ...params.cycleIds.map((cycleId) => encodeU64(cycleId))
505
1158
  ]);
506
1159
  }
507
- function buildSetProtocolRecipientsData(params) {
508
- return Buffer.concat([
509
- Buffer.from([IX.setProtocolRecipients]),
510
- encodePubkey(params.treasuryRecipient),
511
- encodePubkey(params.distributorRecipient)
512
- ]);
513
- }
514
1160
  function buildClaimProtocolTreasuryData() {
515
1161
  return Buffer.from([IX.claimProtocolTreasury]);
516
1162
  }
@@ -644,33 +1290,36 @@ async function submitSatValidatorAttestation(_config, params) {
644
1290
  encodeU64(params.microRoundId)
645
1291
  ], programId);
646
1292
  const [miningStake] = solana.PublicKey.findProgramAddressSync([Buffer.from(MINING_STAKE_SEED), targetAuthority.toBuffer()], programId);
647
- return [
648
- {
649
- pubkey: signer,
650
- isSigner: true,
651
- isWritable: true
652
- },
653
- {
654
- pubkey: satEpoch,
655
- isSigner: false,
656
- isWritable: true
657
- },
658
- {
659
- pubkey: satValidatorAttestation,
660
- isSigner: false,
661
- isWritable: true
662
- },
663
- {
664
- pubkey: miningStake,
665
- isSigner: false,
666
- isWritable: true
667
- },
668
- {
669
- pubkey: solana.SystemProgram.programId,
670
- isSigner: false,
671
- isWritable: false
672
- }
673
- ];
1293
+ return {
1294
+ keys: [
1295
+ {
1296
+ pubkey: signer,
1297
+ isSigner: true,
1298
+ isWritable: true
1299
+ },
1300
+ {
1301
+ pubkey: satEpoch,
1302
+ isSigner: false,
1303
+ isWritable: true
1304
+ },
1305
+ {
1306
+ pubkey: satValidatorAttestation,
1307
+ isSigner: false,
1308
+ isWritable: true
1309
+ },
1310
+ {
1311
+ pubkey: miningStake,
1312
+ isSigner: false,
1313
+ isWritable: true
1314
+ },
1315
+ {
1316
+ pubkey: solana.SystemProgram.programId,
1317
+ isSigner: false,
1318
+ isWritable: false
1319
+ }
1320
+ ],
1321
+ context: { targetAuthority: targetAuthority.toBase58() }
1322
+ };
674
1323
  }
675
1324
  });
676
1325
  }
@@ -692,33 +1341,36 @@ async function submitSatOpenDispute(_config, params) {
692
1341
  encodeU64(params.microRoundId)
693
1342
  ], programId);
694
1343
  const [miningStake] = solana.PublicKey.findProgramAddressSync([Buffer.from(MINING_STAKE_SEED), targetAuthority.toBuffer()], programId);
695
- return [
696
- {
697
- pubkey: signer,
698
- isSigner: true,
699
- isWritable: true
700
- },
701
- {
702
- pubkey: satEpoch,
703
- isSigner: false,
704
- isWritable: true
705
- },
706
- {
707
- pubkey: satDispute,
708
- isSigner: false,
709
- isWritable: true
710
- },
711
- {
712
- pubkey: miningStake,
713
- isSigner: false,
714
- isWritable: true
715
- },
716
- {
717
- pubkey: solana.SystemProgram.programId,
718
- isSigner: false,
719
- isWritable: false
720
- }
721
- ];
1344
+ return {
1345
+ keys: [
1346
+ {
1347
+ pubkey: signer,
1348
+ isSigner: true,
1349
+ isWritable: true
1350
+ },
1351
+ {
1352
+ pubkey: satEpoch,
1353
+ isSigner: false,
1354
+ isWritable: true
1355
+ },
1356
+ {
1357
+ pubkey: satDispute,
1358
+ isSigner: false,
1359
+ isWritable: true
1360
+ },
1361
+ {
1362
+ pubkey: miningStake,
1363
+ isSigner: false,
1364
+ isWritable: true
1365
+ },
1366
+ {
1367
+ pubkey: solana.SystemProgram.programId,
1368
+ isSigner: false,
1369
+ isWritable: false
1370
+ }
1371
+ ],
1372
+ context: { targetAuthority: targetAuthority.toBase58() }
1373
+ };
722
1374
  }
723
1375
  });
724
1376
  }
@@ -741,28 +1393,31 @@ async function submitSatResolveDispute(_config, params) {
741
1393
  encodeU64(params.epochId),
742
1394
  encodeU64(params.microRoundId)
743
1395
  ], programId);
744
- return [
745
- {
746
- pubkey: signer,
747
- isSigner: true,
748
- isWritable: true
749
- },
750
- {
751
- pubkey: miningPool,
752
- isSigner: false,
753
- isWritable: false
754
- },
755
- {
756
- pubkey: satEpoch,
757
- isSigner: false,
758
- isWritable: true
759
- },
760
- {
761
- pubkey: satDispute,
762
- isSigner: false,
763
- isWritable: true
764
- }
765
- ];
1396
+ return {
1397
+ keys: [
1398
+ {
1399
+ pubkey: signer,
1400
+ isSigner: true,
1401
+ isWritable: true
1402
+ },
1403
+ {
1404
+ pubkey: miningPool,
1405
+ isSigner: false,
1406
+ isWritable: false
1407
+ },
1408
+ {
1409
+ pubkey: satEpoch,
1410
+ isSigner: false,
1411
+ isWritable: true
1412
+ },
1413
+ {
1414
+ pubkey: satDispute,
1415
+ isSigner: false,
1416
+ isWritable: true
1417
+ }
1418
+ ],
1419
+ context: { disputeAuthority: disputeAuthority.toBase58() }
1420
+ };
766
1421
  }
767
1422
  });
768
1423
  }
@@ -796,44 +1451,29 @@ async function submitSatRepublishEpochRoots(_config, params) {
796
1451
  }
797
1452
  });
798
1453
  }
799
- async function submitSatBootstrap(_config, params = {}) {
1454
+ async function submitSatTopUpRegistryReserve(_config, params) {
800
1455
  const cfg = loadConfigForSatRuntime(_config);
1456
+ const targetBalanceLamports = Math.max(0, Math.floor(params.targetBalanceLamports));
1457
+ if (!Number.isSafeInteger(targetBalanceLamports)) {
1458
+ throw new Error("registry reserve target must be a safe integer lamport amount");
1459
+ }
1460
+ const profile = resolveSatGenesisProfileContract(_config.network);
1461
+ if (BigInt(targetBalanceLamports) > profile.registryReserveMaxLamports) {
1462
+ throw new Error(`registry reserve target exceeds ${profile.cluster} genesis maximum ${profile.registryReserveMaxLamports}`);
1463
+ }
801
1464
  return submitInstruction({
802
1465
  cfg,
803
1466
  env: process.env,
804
- data: buildBootstrapData({
805
- authority: params.authority ?? "",
806
- initialStake: Math.max(0, Math.floor(params.initialStake ?? 0))
807
- }),
1467
+ data: buildTopUpRegistryReserveData({ targetBalanceLamports }),
808
1468
  accountResolver: async (solana, signer) => {
809
1469
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
810
- const [satGlobalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_GLOBAL_STATE_SEED)], programId);
811
- const [treasury] = solana.PublicKey.findProgramAddressSync([Buffer.from("treasury")], programId);
812
- const [satTreasuryState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_STATE_SEED)], programId);
813
1470
  const [satRegistryReserve] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_REGISTRY_RESERVE_SEED)], programId);
814
- const [satRebateVault] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_REBATE_VAULT_SEED)], programId);
815
- const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_VAULT_SEED)], programId);
816
1471
  return [
817
1472
  {
818
1473
  pubkey: signer,
819
1474
  isSigner: true,
820
1475
  isWritable: true
821
1476
  },
822
- {
823
- pubkey: satGlobalState,
824
- isSigner: false,
825
- isWritable: true
826
- },
827
- {
828
- pubkey: treasury,
829
- isSigner: false,
830
- isWritable: true
831
- },
832
- {
833
- pubkey: satTreasuryState,
834
- isSigner: false,
835
- isWritable: true
836
- },
837
1477
  {
838
1478
  pubkey: satRegistryReserve,
839
1479
  isSigner: false,
@@ -843,16 +1483,6 @@ async function submitSatBootstrap(_config, params = {}) {
843
1483
  pubkey: solana.SystemProgram.programId,
844
1484
  isSigner: false,
845
1485
  isWritable: false
846
- },
847
- {
848
- pubkey: satRebateVault,
849
- isSigner: false,
850
- isWritable: true
851
- },
852
- {
853
- pubkey: satTreasuryVault,
854
- isSigner: false,
855
- isWritable: true
856
1486
  }
857
1487
  ];
858
1488
  }
@@ -919,14 +1549,16 @@ async function submitSatOpenCycle(_config, params) {
919
1549
  }
920
1550
  async function submitSatInitMinerCapital(_config, params) {
921
1551
  const cfg = loadConfigForSatRuntime(_config);
1552
+ const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1553
+ const authority = params.authority?.trim() || await resolveSatLocalSignerAddress(cfg, effectiveEnv, "local-socket-signer returned no Solana address for SAT miner capital authority");
922
1554
  return submitInstruction({
923
1555
  cfg,
924
- env: process.env,
925
- data: buildInitMinerCapitalData({ authority: params.authority ?? "" }),
1556
+ env: effectiveEnv,
1557
+ data: buildInitMinerCapitalData({ authority }),
926
1558
  accountResolver: async (solana, signer) => {
927
1559
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
928
- const authority = params.authority?.trim() ? new solana.PublicKey(params.authority) : signer;
929
- const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), authority.toBuffer()], programId);
1560
+ const authorityKey = new solana.PublicKey(authority);
1561
+ const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), authorityKey.toBuffer()], programId);
930
1562
  return [
931
1563
  {
932
1564
  pubkey: signer,
@@ -1049,50 +1681,13 @@ function resolveSatBondAccounts(solana, signer, env = process.env) {
1049
1681
  dedicated: hasDedicatedBondProgram(env)
1050
1682
  };
1051
1683
  }
1052
- async function submitSatInitBondTierPolicy(_config, params) {
1053
- const cfg = loadConfigForSatRuntime(_config);
1054
- const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1055
- if (!hasDedicatedBondProgram(effectiveEnv)) {
1056
- throw new Error("SAT bond tier policy init requires FASED_SAT_BOND_PROGRAM_ID");
1057
- }
1058
- const defaultUpdateAuthority = resolveSatRegistrySolanaAddress(cfg, effectiveEnv) || await resolveSatLocalSignerAddress(cfg, effectiveEnv, "local-socket-signer returned no Solana address for SAT bond policy authority");
1059
- return submitInstruction({
1060
- cfg,
1061
- env: effectiveEnv,
1062
- data: buildInitBondTierPolicyData({
1063
- ...params,
1064
- updateAuthority: params.updateAuthority ?? defaultUpdateAuthority
1065
- }),
1066
- programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1067
- accountResolver: async (solana, signer) => {
1068
- const { bondTierPolicy } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1069
- return [
1070
- {
1071
- pubkey: signer,
1072
- isSigner: true,
1073
- isWritable: true
1074
- },
1075
- {
1076
- pubkey: bondTierPolicy,
1077
- isSigner: false,
1078
- isWritable: true
1079
- },
1080
- {
1081
- pubkey: solana.SystemProgram.programId,
1082
- isSigner: false,
1083
- isWritable: false
1084
- }
1085
- ];
1086
- }
1087
- });
1088
- }
1089
1684
  async function submitSatUpdateBondTierPolicy(_config, params) {
1090
1685
  const cfg = loadConfigForSatRuntime(_config);
1091
1686
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1092
1687
  if (!hasDedicatedBondProgram(effectiveEnv)) {
1093
1688
  throw new Error("SAT bond tier policy update requires FASED_SAT_BOND_PROGRAM_ID");
1094
1689
  }
1095
- const defaultUpdateAuthority = resolveSatRegistrySolanaAddress(cfg, effectiveEnv) || await resolveSatLocalSignerAddress(cfg, effectiveEnv, "local-socket-signer returned no Solana address for SAT bond policy authority");
1690
+ const defaultUpdateAuthority = await resolveSatLocalSignerAddress(cfg, effectiveEnv, "local-socket-signer returned no Solana address for SAT bond policy authority");
1096
1691
  return submitInstruction({
1097
1692
  cfg,
1098
1693
  env: effectiveEnv,
@@ -1231,7 +1826,7 @@ async function submitSatRequestBondUnlock(_config) {
1231
1826
  data: buildRequestBondUnlockData(effectiveEnv),
1232
1827
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1233
1828
  accountResolver: async (solana, signer) => {
1234
- const { bondTierPolicy, bondPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1829
+ const { bondTierPolicy, bondPosition, bondStakingDistributor, bondStakingPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1235
1830
  const accounts = [{
1236
1831
  pubkey: signer,
1237
1832
  isSigner: true,
@@ -1245,6 +1840,14 @@ async function submitSatRequestBondUnlock(_config) {
1245
1840
  pubkey: bondPosition,
1246
1841
  isSigner: false,
1247
1842
  isWritable: true
1843
+ }, {
1844
+ pubkey: bondStakingDistributor,
1845
+ isSigner: false,
1846
+ isWritable: true
1847
+ }, {
1848
+ pubkey: bondStakingPosition,
1849
+ isSigner: false,
1850
+ isWritable: true
1248
1851
  });
1249
1852
  return accounts;
1250
1853
  }
@@ -1260,7 +1863,7 @@ async function submitSatCancelBondUnlock(_config) {
1260
1863
  data: buildCancelBondUnlockData(effectiveEnv),
1261
1864
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1262
1865
  accountResolver: async (solana, signer) => {
1263
- const { bondTierPolicy, bondPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1866
+ const { bondTierPolicy, bondPosition, bondStakingDistributor, bondStakingPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1264
1867
  const accounts = [{
1265
1868
  pubkey: signer,
1266
1869
  isSigner: true,
@@ -1274,6 +1877,14 @@ async function submitSatCancelBondUnlock(_config) {
1274
1877
  pubkey: bondPosition,
1275
1878
  isSigner: false,
1276
1879
  isWritable: true
1880
+ }, {
1881
+ pubkey: bondStakingDistributor,
1882
+ isSigner: false,
1883
+ isWritable: true
1884
+ }, {
1885
+ pubkey: bondStakingPosition,
1886
+ isSigner: false,
1887
+ isWritable: true
1277
1888
  });
1278
1889
  return accounts;
1279
1890
  }
@@ -1289,7 +1900,7 @@ async function submitSatFinalizeBondUnlock(_config) {
1289
1900
  data: buildFinalizeBondUnlockData(effectiveEnv),
1290
1901
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1291
1902
  accountResolver: async (solana, signer) => {
1292
- const { bondTierPolicy, bondPosition, signerTokenAccount, bondVault, mint } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1903
+ const { bondTierPolicy, bondPosition, bondStakingDistributor, bondStakingPosition, signerTokenAccount, bondVault, mint } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1293
1904
  const accounts = [{
1294
1905
  pubkey: signer,
1295
1906
  isSigner: true,
@@ -1303,6 +1914,14 @@ async function submitSatFinalizeBondUnlock(_config) {
1303
1914
  pubkey: bondPosition,
1304
1915
  isSigner: false,
1305
1916
  isWritable: true
1917
+ }, {
1918
+ pubkey: bondStakingDistributor,
1919
+ isSigner: false,
1920
+ isWritable: true
1921
+ }, {
1922
+ pubkey: bondStakingPosition,
1923
+ isSigner: false,
1924
+ isWritable: true
1306
1925
  }, {
1307
1926
  pubkey: bondVault,
1308
1927
  isSigner: false,
@@ -1332,27 +1951,18 @@ async function submitSatFinalizeBondUnlock(_config) {
1332
1951
  }
1333
1952
  });
1334
1953
  }
1335
- async function submitSatInitBondStakingDistributor(_config, params) {
1954
+ async function submitSatSyncBondStakingRewards(_config) {
1336
1955
  const cfg = loadConfigForSatRuntime(_config);
1337
1956
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1338
1957
  assertDedicatedBondProgram(effectiveEnv);
1339
- const defaultUpdateAuthority = await resolveSatLocalSignerAddress(cfg, effectiveEnv, "local-socket-signer returned no Solana address for SAT bond staking distributor authority");
1340
1958
  return submitInstruction({
1341
1959
  cfg,
1342
1960
  env: effectiveEnv,
1343
- data: buildInitBondStakingDistributorData({
1344
- minStakeRaw: params.minStakeRaw,
1345
- updateAuthority: params.updateAuthority ?? defaultUpdateAuthority
1346
- }, effectiveEnv),
1961
+ data: buildSyncBondStakingRewardsData(effectiveEnv),
1347
1962
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1348
1963
  accountResolver: async (solana, signer) => {
1349
1964
  const { bondStakingDistributor, bondStakingRewardVault, mint } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1350
1965
  return [
1351
- {
1352
- pubkey: signer,
1353
- isSigner: true,
1354
- isWritable: true
1355
- },
1356
1966
  {
1357
1967
  pubkey: bondStakingDistributor,
1358
1968
  isSigner: false,
@@ -1361,25 +1971,10 @@ async function submitSatInitBondStakingDistributor(_config, params) {
1361
1971
  {
1362
1972
  pubkey: bondStakingRewardVault,
1363
1973
  isSigner: false,
1364
- isWritable: true
1365
- },
1366
- {
1367
- pubkey: mint,
1368
- isSigner: false,
1369
- isWritable: true
1370
- },
1371
- {
1372
- pubkey: solana.SystemProgram.programId,
1373
- isSigner: false,
1374
- isWritable: false
1375
- },
1376
- {
1377
- pubkey: new solana.PublicKey(TOKEN_PROGRAM_ID),
1378
- isSigner: false,
1379
1974
  isWritable: false
1380
1975
  },
1381
1976
  {
1382
- pubkey: new solana.PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID),
1977
+ pubkey: mint,
1383
1978
  isSigner: false,
1384
1979
  isWritable: false
1385
1980
  }
@@ -1387,30 +1982,45 @@ async function submitSatInitBondStakingDistributor(_config, params) {
1387
1982
  }
1388
1983
  });
1389
1984
  }
1390
- async function submitSatSyncBondStakingRewards(_config) {
1985
+ async function submitSatSyncBondStakingPosition(_config) {
1391
1986
  const cfg = loadConfigForSatRuntime(_config);
1392
1987
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1393
1988
  assertDedicatedBondProgram(effectiveEnv);
1394
1989
  return submitInstruction({
1395
1990
  cfg,
1396
1991
  env: effectiveEnv,
1397
- data: buildSyncBondStakingRewardsData(effectiveEnv),
1992
+ data: buildSyncBondStakingPositionData(effectiveEnv),
1398
1993
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1399
1994
  accountResolver: async (solana, signer) => {
1400
- const { bondStakingDistributor, bondStakingRewardVault, mint } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1995
+ const { bondTierPolicy, bondStakingDistributor, bondStakingPosition, bondPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1401
1996
  return [
1997
+ {
1998
+ pubkey: signer,
1999
+ isSigner: true,
2000
+ isWritable: true
2001
+ },
2002
+ {
2003
+ pubkey: bondTierPolicy,
2004
+ isSigner: false,
2005
+ isWritable: false
2006
+ },
1402
2007
  {
1403
2008
  pubkey: bondStakingDistributor,
1404
2009
  isSigner: false,
1405
2010
  isWritable: true
1406
2011
  },
1407
2012
  {
1408
- pubkey: bondStakingRewardVault,
2013
+ pubkey: bondStakingPosition,
2014
+ isSigner: false,
2015
+ isWritable: true
2016
+ },
2017
+ {
2018
+ pubkey: bondPosition,
1409
2019
  isSigner: false,
1410
2020
  isWritable: false
1411
2021
  },
1412
2022
  {
1413
- pubkey: mint,
2023
+ pubkey: solana.SystemProgram.programId,
1414
2024
  isSigner: false,
1415
2025
  isWritable: false
1416
2026
  }
@@ -1418,17 +2028,17 @@ async function submitSatSyncBondStakingRewards(_config) {
1418
2028
  }
1419
2029
  });
1420
2030
  }
1421
- async function submitSatSyncBondStakingPosition(_config) {
2031
+ async function submitSatClaimBondStakingRewards(_config) {
1422
2032
  const cfg = loadConfigForSatRuntime(_config);
1423
2033
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1424
2034
  assertDedicatedBondProgram(effectiveEnv);
1425
2035
  return submitInstruction({
1426
2036
  cfg,
1427
2037
  env: effectiveEnv,
1428
- data: buildSyncBondStakingPositionData(effectiveEnv),
2038
+ data: buildClaimBondStakingRewardsData(effectiveEnv),
1429
2039
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1430
2040
  accountResolver: async (solana, signer) => {
1431
- const { bondTierPolicy, bondStakingDistributor, bondStakingPosition, bondPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
2041
+ const { bondTierPolicy, bondStakingDistributor, bondStakingPosition, bondPosition, bondStakingRewardVault, signerTokenAccount, mint } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1432
2042
  return [
1433
2043
  {
1434
2044
  pubkey: signer,
@@ -1455,61 +2065,78 @@ async function submitSatSyncBondStakingPosition(_config) {
1455
2065
  isSigner: false,
1456
2066
  isWritable: false
1457
2067
  },
2068
+ {
2069
+ pubkey: bondStakingRewardVault,
2070
+ isSigner: false,
2071
+ isWritable: true
2072
+ },
2073
+ {
2074
+ pubkey: signerTokenAccount,
2075
+ isSigner: false,
2076
+ isWritable: true
2077
+ },
2078
+ {
2079
+ pubkey: mint,
2080
+ isSigner: false,
2081
+ isWritable: true
2082
+ },
1458
2083
  {
1459
2084
  pubkey: solana.SystemProgram.programId,
1460
2085
  isSigner: false,
1461
2086
  isWritable: false
2087
+ },
2088
+ {
2089
+ pubkey: new solana.PublicKey(TOKEN_PROGRAM_ID),
2090
+ isSigner: false,
2091
+ isWritable: false
2092
+ },
2093
+ {
2094
+ pubkey: new solana.PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID),
2095
+ isSigner: false,
2096
+ isWritable: false
1462
2097
  }
1463
2098
  ];
1464
2099
  }
1465
2100
  });
1466
2101
  }
1467
- async function submitSatClaimBondStakingRewards(_config) {
2102
+ async function submitSatClaimUnallocatedStakingRewards(_config, params) {
1468
2103
  const cfg = loadConfigForSatRuntime(_config);
1469
2104
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1470
2105
  assertDedicatedBondProgram(effectiveEnv);
1471
2106
  return submitInstruction({
1472
2107
  cfg,
1473
2108
  env: effectiveEnv,
1474
- data: buildClaimBondStakingRewardsData(effectiveEnv),
2109
+ data: buildClaimUnallocatedStakingRewardsData(effectiveEnv),
1475
2110
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1476
2111
  accountResolver: async (solana, signer) => {
1477
- const { bondTierPolicy, bondStakingDistributor, bondStakingPosition, bondPosition, bondStakingRewardVault, signerTokenAccount, mint } = resolveSatBondAccounts(solana, signer, effectiveEnv);
2112
+ const { bondStakingDistributor, bondStakingRewardVault, mint } = resolveSatBondAccounts(solana, signer, effectiveEnv);
2113
+ const recipientOwner = new solana.PublicKey(params.recipientOwner);
2114
+ const recipientTokenAccount = deriveAssociatedTokenAddress(solana, recipientOwner, mint);
1478
2115
  return [
1479
2116
  {
1480
2117
  pubkey: signer,
1481
2118
  isSigner: true,
1482
2119
  isWritable: true
1483
2120
  },
1484
- {
1485
- pubkey: bondTierPolicy,
1486
- isSigner: false,
1487
- isWritable: false
1488
- },
1489
2121
  {
1490
2122
  pubkey: bondStakingDistributor,
1491
2123
  isSigner: false,
1492
2124
  isWritable: true
1493
2125
  },
1494
2126
  {
1495
- pubkey: bondStakingPosition,
2127
+ pubkey: bondStakingRewardVault,
1496
2128
  isSigner: false,
1497
2129
  isWritable: true
1498
2130
  },
1499
2131
  {
1500
- pubkey: bondPosition,
1501
- isSigner: false,
1502
- isWritable: false
1503
- },
1504
- {
1505
- pubkey: bondStakingRewardVault,
2132
+ pubkey: recipientTokenAccount,
1506
2133
  isSigner: false,
1507
2134
  isWritable: true
1508
2135
  },
1509
2136
  {
1510
- pubkey: signerTokenAccount,
2137
+ pubkey: recipientOwner,
1511
2138
  isSigner: false,
1512
- isWritable: true
2139
+ isWritable: false
1513
2140
  },
1514
2141
  {
1515
2142
  pubkey: mint,
@@ -1535,34 +2162,25 @@ async function submitSatClaimBondStakingRewards(_config) {
1535
2162
  }
1536
2163
  });
1537
2164
  }
1538
- async function submitSatCycle(_config, params) {
2165
+ async function submitSatCommitCycle(_config, params) {
1539
2166
  const cfg = loadConfigForSatRuntime(_config);
2167
+ const commitment = Buffer.from(params.commitmentHex, "hex");
1540
2168
  return submitInstruction({
1541
2169
  cfg,
1542
2170
  env: process.env,
1543
- data: buildSubmitCycleData(params),
2171
+ data: buildCommitCycleData({
2172
+ cycleId: params.cycleId,
2173
+ commitment
2174
+ }),
1544
2175
  accountResolver: async (solana, signer) => {
1545
2176
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
1546
- const pageIndex = await resolveSatCycleRegistryPageIndex(_config, params.cycleId);
1547
- const [satGlobalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_GLOBAL_STATE_SEED)], programId);
1548
2177
  const [satCycleState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)], programId);
1549
- const [satCycleRegistryMeta] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_REGISTRY_META_SEED), encodeU64(params.cycleId)], programId);
1550
- const [satCycleRegistryPage] = solana.PublicKey.findProgramAddressSync([
1551
- Buffer.from(SAT_CYCLE_REGISTRY_PAGE_SEED),
1552
- encodeU64(params.cycleId),
1553
- encodeU64(pageIndex)
1554
- ], programId);
1555
- const [satCycleSettlementProgress] = solana.PublicKey.findProgramAddressSync([Buffer.from("sat_cycle_settlement_progress_v2"), encodeU64(params.cycleId)], programId);
1556
2178
  const [satMinerCycleState] = solana.PublicKey.findProgramAddressSync([
1557
2179
  Buffer.from(SAT_MINER_CYCLE_STATE_SEED),
1558
2180
  signer.toBuffer(),
1559
2181
  encodeU64(params.cycleId)
1560
2182
  ], programId);
1561
2183
  const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), signer.toBuffer()], programId);
1562
- const [satRegistryReserve] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_REGISTRY_RESERVE_SEED)], programId);
1563
- const [satTreasuryState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_STATE_SEED)], programId);
1564
- const [satRebateVault] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_REBATE_VAULT_SEED)], programId);
1565
- const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_VAULT_SEED)], programId);
1566
2184
  return [
1567
2185
  {
1568
2186
  pubkey: signer,
@@ -1570,27 +2188,112 @@ async function submitSatCycle(_config, params) {
1570
2188
  isWritable: true
1571
2189
  },
1572
2190
  {
1573
- pubkey: satGlobalState,
2191
+ pubkey: satCycleState,
1574
2192
  isSigner: false,
1575
2193
  isWritable: true
1576
2194
  },
1577
2195
  {
1578
- pubkey: satCycleState,
2196
+ pubkey: satMinerCycleState,
1579
2197
  isSigner: false,
1580
2198
  isWritable: true
1581
2199
  },
1582
2200
  {
1583
- pubkey: satCycleRegistryMeta,
2201
+ pubkey: satMinerCapitalState,
1584
2202
  isSigner: false,
1585
2203
  isWritable: true
1586
2204
  },
1587
2205
  {
1588
- pubkey: satCycleRegistryPage,
2206
+ pubkey: solana.SystemProgram.programId,
2207
+ isSigner: false,
2208
+ isWritable: false
2209
+ }
2210
+ ];
2211
+ }
2212
+ });
2213
+ }
2214
+ async function submitSatCyclePhaseInstruction(_config, params) {
2215
+ const cfg = loadConfigForSatRuntime(_config);
2216
+ return submitInstruction({
2217
+ cfg,
2218
+ env: process.env,
2219
+ data: params.phase === "close" ? buildCloseCommitPhaseData(params) : buildSealCycleEntropyData(params),
2220
+ accountResolver: async (solana, signer) => {
2221
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2222
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)], programId);
2223
+ const accounts = [{
2224
+ pubkey: signer,
2225
+ isSigner: true,
2226
+ isWritable: false
2227
+ }, {
2228
+ pubkey: satCycleState,
2229
+ isSigner: false,
2230
+ isWritable: true
2231
+ }];
2232
+ let intervalStartCycleIdForSigner;
2233
+ if (params.phase === "seal") {
2234
+ const cycle = params.intervalStartCycleId == null ? await inspectSatCycle(_config, { cycleId: params.cycleId }) : null;
2235
+ const intervalStartCycleId = params.intervalStartCycleId ?? cycle?.unlockIntervalStartCycleId;
2236
+ if (intervalStartCycleId == null || !Number.isSafeInteger(intervalStartCycleId)) {
2237
+ throw new Error(`SAT cycle ${params.cycleId} does not expose its unlock interval start`);
2238
+ }
2239
+ intervalStartCycleIdForSigner = intervalStartCycleId;
2240
+ const [satUnlockIntervalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_UNLOCK_INTERVAL_STATE_SEED), encodeU64(intervalStartCycleId)], programId);
2241
+ accounts.push({
2242
+ pubkey: satUnlockIntervalState,
1589
2243
  isSigner: false,
1590
2244
  isWritable: true
2245
+ });
2246
+ accounts.push({
2247
+ pubkey: new solana.PublicKey(SLOT_HASHES_SYSVAR_ID),
2248
+ isSigner: false,
2249
+ isWritable: false
2250
+ });
2251
+ }
2252
+ return {
2253
+ keys: accounts,
2254
+ ...intervalStartCycleIdForSigner == null ? {} : { context: { intervalStartCycleId: String(intervalStartCycleIdForSigner) } }
2255
+ };
2256
+ }
2257
+ });
2258
+ }
2259
+ async function submitSatCloseCommitPhase(_config, params) {
2260
+ return submitSatCyclePhaseInstruction(_config, {
2261
+ ...params,
2262
+ phase: "close"
2263
+ });
2264
+ }
2265
+ async function submitSatSealCycleEntropy(_config, params) {
2266
+ return submitSatCyclePhaseInstruction(_config, {
2267
+ ...params,
2268
+ phase: "seal"
2269
+ });
2270
+ }
2271
+ async function submitSatReleaseUnrevealedCommit(_config, params) {
2272
+ const cfg = loadConfigForSatRuntime(_config);
2273
+ return submitInstruction({
2274
+ cfg,
2275
+ env: process.env,
2276
+ data: buildReleaseUnrevealedCommitData(params),
2277
+ accountResolver: async (solana, signer) => {
2278
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2279
+ const minerAuthority = new solana.PublicKey(params.minerAuthority);
2280
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)], programId);
2281
+ const [satMinerCycleState] = solana.PublicKey.findProgramAddressSync([
2282
+ Buffer.from(SAT_MINER_CYCLE_STATE_SEED),
2283
+ minerAuthority.toBuffer(),
2284
+ encodeU64(params.cycleId)
2285
+ ], programId);
2286
+ const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), minerAuthority.toBuffer()], programId);
2287
+ const [satTreasuryState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_STATE_SEED)], programId);
2288
+ const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_VAULT_SEED)], programId);
2289
+ return [
2290
+ {
2291
+ pubkey: signer,
2292
+ isSigner: true,
2293
+ isWritable: false
1591
2294
  },
1592
2295
  {
1593
- pubkey: satCycleSettlementProgress,
2296
+ pubkey: satCycleState,
1594
2297
  isSigner: false,
1595
2298
  isWritable: true
1596
2299
  },
@@ -1605,27 +2308,42 @@ async function submitSatCycle(_config, params) {
1605
2308
  isWritable: true
1606
2309
  },
1607
2310
  {
1608
- pubkey: satRegistryReserve,
2311
+ pubkey: satTreasuryState,
1609
2312
  isSigner: false,
1610
2313
  isWritable: true
1611
2314
  },
1612
2315
  {
1613
- pubkey: satTreasuryState,
2316
+ pubkey: satTreasuryVault,
1614
2317
  isSigner: false,
1615
2318
  isWritable: true
1616
- },
2319
+ }
2320
+ ];
2321
+ }
2322
+ });
2323
+ }
2324
+ async function submitSatAbortEmptyCycle(_config, params) {
2325
+ const cfg = loadConfigForSatRuntime(_config);
2326
+ return submitInstruction({
2327
+ cfg,
2328
+ env: process.env,
2329
+ data: buildAbortEmptyCycleData(params),
2330
+ accountResolver: async (solana, signer) => {
2331
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2332
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)], programId);
2333
+ const [satCycleRegistryMeta] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_REGISTRY_META_SEED), encodeU64(params.cycleId)], programId);
2334
+ return [
1617
2335
  {
1618
- pubkey: solana.SystemProgram.programId,
1619
- isSigner: false,
2336
+ pubkey: signer,
2337
+ isSigner: true,
1620
2338
  isWritable: false
1621
2339
  },
1622
2340
  {
1623
- pubkey: satRebateVault,
2341
+ pubkey: satCycleState,
1624
2342
  isSigner: false,
1625
2343
  isWritable: true
1626
2344
  },
1627
2345
  {
1628
- pubkey: satTreasuryVault,
2346
+ pubkey: satCycleRegistryMeta,
1629
2347
  isSigner: false,
1630
2348
  isWritable: true
1631
2349
  }
@@ -1633,6 +2351,101 @@ async function submitSatCycle(_config, params) {
1633
2351
  }
1634
2352
  });
1635
2353
  }
2354
+ async function submitSatRevealCycle(_config, params) {
2355
+ const cfg = loadConfigForSatRuntime(_config);
2356
+ const nonce = Buffer.from(params.nonceBase64, "base64");
2357
+ return submitInstruction({
2358
+ cfg,
2359
+ env: process.env,
2360
+ data: buildRevealCycleData({
2361
+ ...params,
2362
+ nonce
2363
+ }),
2364
+ accountResolver: async (solana, signer) => {
2365
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2366
+ const pageIndex = await resolveSatCycleRegistryPageIndex(_config, params.cycleId);
2367
+ const cycle = params.intervalStartCycleId == null ? await inspectSatCycle(_config, { cycleId: params.cycleId }) : null;
2368
+ const intervalStartCycleId = params.intervalStartCycleId ?? cycle?.unlockIntervalStartCycleId;
2369
+ if (intervalStartCycleId == null || !Number.isSafeInteger(intervalStartCycleId)) {
2370
+ throw new Error(`SAT cycle ${params.cycleId} does not expose its unlock interval start`);
2371
+ }
2372
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)], programId);
2373
+ const [satCycleRegistryMeta] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_REGISTRY_META_SEED), encodeU64(params.cycleId)], programId);
2374
+ const [satCycleRegistryPage] = solana.PublicKey.findProgramAddressSync([
2375
+ Buffer.from(SAT_CYCLE_REGISTRY_PAGE_SEED),
2376
+ encodeU64(params.cycleId),
2377
+ encodeU64(pageIndex)
2378
+ ], programId);
2379
+ const [satCycleSettlementProgress] = solana.PublicKey.findProgramAddressSync([Buffer.from("sat_cycle_settlement_progress_v2"), encodeU64(params.cycleId)], programId);
2380
+ const [satMinerCycleState] = solana.PublicKey.findProgramAddressSync([
2381
+ Buffer.from(SAT_MINER_CYCLE_STATE_SEED),
2382
+ signer.toBuffer(),
2383
+ encodeU64(params.cycleId)
2384
+ ], programId);
2385
+ const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), signer.toBuffer()], programId);
2386
+ const [satUnlockIntervalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_UNLOCK_INTERVAL_STATE_SEED), encodeU64(intervalStartCycleId)], programId);
2387
+ const [satRegistryReserve] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_REGISTRY_RESERVE_SEED)], programId);
2388
+ return {
2389
+ keys: [
2390
+ {
2391
+ pubkey: signer,
2392
+ isSigner: true,
2393
+ isWritable: true
2394
+ },
2395
+ {
2396
+ pubkey: satCycleState,
2397
+ isSigner: false,
2398
+ isWritable: true
2399
+ },
2400
+ {
2401
+ pubkey: satCycleRegistryMeta,
2402
+ isSigner: false,
2403
+ isWritable: true
2404
+ },
2405
+ {
2406
+ pubkey: satCycleRegistryPage,
2407
+ isSigner: false,
2408
+ isWritable: true
2409
+ },
2410
+ {
2411
+ pubkey: satCycleSettlementProgress,
2412
+ isSigner: false,
2413
+ isWritable: true
2414
+ },
2415
+ {
2416
+ pubkey: satMinerCycleState,
2417
+ isSigner: false,
2418
+ isWritable: true
2419
+ },
2420
+ {
2421
+ pubkey: satMinerCapitalState,
2422
+ isSigner: false,
2423
+ isWritable: true
2424
+ },
2425
+ {
2426
+ pubkey: satUnlockIntervalState,
2427
+ isSigner: false,
2428
+ isWritable: true
2429
+ },
2430
+ {
2431
+ pubkey: satRegistryReserve,
2432
+ isSigner: false,
2433
+ isWritable: true
2434
+ },
2435
+ {
2436
+ pubkey: solana.SystemProgram.programId,
2437
+ isSigner: false,
2438
+ isWritable: false
2439
+ }
2440
+ ],
2441
+ context: {
2442
+ intervalStartCycleId: String(intervalStartCycleId),
2443
+ registryPageIndex: String(pageIndex)
2444
+ }
2445
+ };
2446
+ }
2447
+ });
2448
+ }
1636
2449
  async function submitSatSettleCyclePage(_config, params) {
1637
2450
  const cfg = loadConfigForSatRuntime(_config);
1638
2451
  return submitInstruction({
@@ -1728,7 +2541,22 @@ async function submitSatSettleCyclePage(_config, params) {
1728
2541
  isWritable: true
1729
2542
  });
1730
2543
  }
1731
- return accounts;
2544
+ const minerCycleAddresses = params.minerCycleAccounts ?? [];
2545
+ const minerCycles = minerCycleAddresses.length > 0 ? await inspectSatMinerCyclesByAddress(_config, { addresses: minerCycleAddresses }) : [];
2546
+ const minerAuthorities = minerCycles.map((entry, index) => {
2547
+ const authority = String(entry?.authority ?? "").trim();
2548
+ if (!authority) {
2549
+ throw new Error(`SAT settleCyclePage could not resolve miner authority for ${minerCycleAddresses[index]}`);
2550
+ }
2551
+ return authority;
2552
+ });
2553
+ if (minerAuthorities.length !== minerCycleAddresses.length) {
2554
+ throw new Error("SAT settleCyclePage miner authority count mismatch");
2555
+ }
2556
+ return {
2557
+ keys: accounts,
2558
+ ...minerAuthorities.length > 0 ? { context: { minerAuthorities } } : {}
2559
+ };
1732
2560
  }
1733
2561
  });
1734
2562
  }
@@ -1893,16 +2721,34 @@ async function submitSatScoreCyclePage(_config, params) {
1893
2721
  isWritable: true
1894
2722
  });
1895
2723
  }
1896
- return accounts;
2724
+ const minerCycleAddresses = params.minerCycleAccounts ?? [];
2725
+ const minerCycles = minerCycleAddresses.length > 0 ? await inspectSatMinerCyclesByAddress(_config, { addresses: minerCycleAddresses }) : [];
2726
+ const minerAuthorities = minerCycles.map((entry, index) => {
2727
+ const authority = String(entry?.authority ?? "").trim();
2728
+ if (!authority) {
2729
+ throw new Error(`SAT scoreCyclePage could not resolve miner authority for ${minerCycleAddresses[index]}`);
2730
+ }
2731
+ return authority;
2732
+ });
2733
+ if (minerAuthorities.length !== minerCycleAddresses.length) {
2734
+ throw new Error("SAT scoreCyclePage miner authority count mismatch");
2735
+ }
2736
+ return {
2737
+ keys: accounts,
2738
+ ...minerAuthorities.length > 0 ? { context: { minerAuthorities } } : {}
2739
+ };
1897
2740
  }
1898
2741
  });
1899
2742
  }
1900
2743
  async function submitSatDistributeCyclePage(_config, params) {
1901
2744
  const cfg = loadConfigForSatRuntime(_config);
2745
+ const lookupTableAddress = params.lookupTableAddress?.trim() ?? "";
2746
+ const requiresLookupTable = (params.minerCycleAccounts?.length ?? 0) >= SAT_DISTRIBUTION_LOOKUP_MIN_MINERS;
1902
2747
  return submitInstruction({
1903
2748
  cfg,
1904
2749
  env: process.env,
1905
2750
  data: buildDistributeCyclePageData(params),
2751
+ ...lookupTableAddress || requiresLookupTable ? { manageAddressLookupTable: { ...lookupTableAddress ? { lookupTableAddress } : {} } } : {},
1906
2752
  accountResolver: async (solana, signer) => {
1907
2753
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
1908
2754
  const [satCycleState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)], programId);
@@ -1921,6 +2767,7 @@ async function submitSatDistributeCyclePage(_config, params) {
1921
2767
  ], programId);
1922
2768
  const [satSignerMinerCapitalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), signer.toBuffer()], programId);
1923
2769
  const [satRebateVault] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_REBATE_VAULT_SEED)], programId);
2770
+ const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_VAULT_SEED)], programId);
1924
2771
  const accounts = [
1925
2772
  {
1926
2773
  pubkey: signer,
@@ -1945,7 +2792,7 @@ async function submitSatDistributeCyclePage(_config, params) {
1945
2792
  {
1946
2793
  pubkey: satGlobalState,
1947
2794
  isSigner: false,
1948
- isWritable: true
2795
+ isWritable: false
1949
2796
  },
1950
2797
  {
1951
2798
  pubkey: satTreasuryState,
@@ -1966,10 +2813,16 @@ async function submitSatDistributeCyclePage(_config, params) {
1966
2813
  pubkey: satRebateVault,
1967
2814
  isSigner: false,
1968
2815
  isWritable: true
2816
+ },
2817
+ {
2818
+ pubkey: satTreasuryVault,
2819
+ isSigner: false,
2820
+ isWritable: true
1969
2821
  }
1970
2822
  ];
1971
2823
  const minerCycleAccounts = params.minerCycleAccounts ?? [];
1972
2824
  const minerCycles = minerCycleAccounts.length > 0 ? await inspectSatMinerCyclesByAddress(_config, { addresses: minerCycleAccounts }).catch(() => []) : [];
2825
+ const minerAuthorities = [];
1973
2826
  for (const [index, minerCycleAccount] of minerCycleAccounts.entries()) {
1974
2827
  const satMinerCycleState = new solana.PublicKey(minerCycleAccount);
1975
2828
  const minerCycle = minerCycles[index] ?? null;
@@ -1977,6 +2830,7 @@ async function submitSatDistributeCyclePage(_config, params) {
1977
2830
  if (!authorityKey) {
1978
2831
  throw new Error(`SAT distributeCyclePage could not resolve miner authority for ${minerCycleAccount}`);
1979
2832
  }
2833
+ minerAuthorities.push(authorityKey.toBase58());
1980
2834
  const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), authorityKey.toBuffer()], programId);
1981
2835
  accounts.push({
1982
2836
  pubkey: satMinerCycleState,
@@ -1989,10 +2843,41 @@ async function submitSatDistributeCyclePage(_config, params) {
1989
2843
  isWritable: true
1990
2844
  });
1991
2845
  }
1992
- return accounts;
2846
+ return {
2847
+ keys: accounts,
2848
+ ...minerAuthorities.length > 0 ? { context: { minerAuthorities } } : {}
2849
+ };
1993
2850
  }
1994
2851
  });
1995
2852
  }
2853
+ async function submitSatCleanupDistributionLookupTable(_config, params) {
2854
+ const cfg = loadConfigForSatRuntime(_config);
2855
+ const context = await prepareLocalSignerSubmitContext(cfg, process.env);
2856
+ assertSatLookupTableEnabled(context.effectiveEnv);
2857
+ if (!context.walletId) {
2858
+ throw new Error("typed SAT lookup-table cleanup requires an explicit mining walletId");
2859
+ }
2860
+ const lookupTable = params.lookupTableAddress.trim();
2861
+ if (!lookupTable) {
2862
+ throw new Error("SAT distribution lookup table address is required");
2863
+ }
2864
+ const submitted = await executeTypedSatLookupOperation({
2865
+ context: {
2866
+ ...context,
2867
+ walletId: context.walletId
2868
+ },
2869
+ cfg,
2870
+ action: params.action,
2871
+ address: lookupTable
2872
+ });
2873
+ return {
2874
+ lookupTable,
2875
+ action: params.action,
2876
+ transactionHashes: [submitted.signature],
2877
+ signerState: submitted.state,
2878
+ requestId: submitted.requestId
2879
+ };
2880
+ }
1996
2881
  async function submitSatClaimCycleRewards(_config, params) {
1997
2882
  const cfg = loadConfigForSatRuntime(_config);
1998
2883
  return submitInstruction({
@@ -2199,27 +3084,6 @@ async function submitSatClaimCycleRewardsBatch(_config, params) {
2199
3084
  }
2200
3085
  });
2201
3086
  }
2202
- async function submitSatSetProtocolRecipients(_config, params) {
2203
- const cfg = loadConfigForSatRuntime(_config);
2204
- return submitInstruction({
2205
- cfg,
2206
- env: process.env,
2207
- data: buildSetProtocolRecipientsData(params),
2208
- accountResolver: async (solana, signer) => {
2209
- const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2210
- const [satGlobalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_GLOBAL_STATE_SEED)], programId);
2211
- return [{
2212
- pubkey: signer,
2213
- isSigner: true,
2214
- isWritable: true
2215
- }, {
2216
- pubkey: satGlobalState,
2217
- isSigner: false,
2218
- isWritable: true
2219
- }];
2220
- }
2221
- });
2222
- }
2223
3087
  async function submitSatClaimProtocolTreasury(_config, params) {
2224
3088
  const cfg = loadConfigForSatRuntime(_config);
2225
3089
  return submitInstruction({
@@ -2355,18 +3219,20 @@ async function submitSatRefillRegistryReserveFromTreasury(_config, params) {
2355
3219
  }
2356
3220
  async function submitSatClaimProtocolDistributorSat(_config, params) {
2357
3221
  const cfg = loadConfigForSatRuntime(_config);
3222
+ const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
3223
+ assertDedicatedBondProgram(effectiveEnv);
2358
3224
  return submitInstruction({
2359
3225
  cfg,
2360
- env: process.env,
3226
+ env: effectiveEnv,
2361
3227
  data: buildClaimProtocolDistributorSatData(),
2362
3228
  accountResolver: async (solana, signer) => {
2363
- const programId = new solana.PublicKey(SAT_PROGRAM_ID());
3229
+ const programId = new solana.PublicKey(resolveSatProgramIdFromEnv(effectiveEnv));
2364
3230
  const recipientOwner = new solana.PublicKey(params.recipientOwner);
2365
3231
  const [satGlobalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_GLOBAL_STATE_SEED)], programId);
2366
3232
  const [treasury] = solana.PublicKey.findProgramAddressSync([Buffer.from("treasury")], programId);
2367
3233
  const [satTreasuryState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_TREASURY_STATE_SEED)], programId);
2368
- const [mintAuthority] = solana.PublicKey.findProgramAddressSync([Buffer.from("authority")], new solana.PublicKey(SAT_MINT_PROGRAM_ID()));
2369
- const recipientAta = deriveAssociatedTokenAddress(solana, recipientOwner, new solana.PublicKey(SAT_MINT_ADDRESS()));
3234
+ const [mintAuthority] = solana.PublicKey.findProgramAddressSync([Buffer.from("authority")], new solana.PublicKey(resolveSatMintProgramIdFromEnv(effectiveEnv)));
3235
+ const recipientAta = deriveAssociatedTokenAddress(solana, recipientOwner, new solana.PublicKey(resolveSatMintAddressFromEnv(effectiveEnv)));
2370
3236
  return [
2371
3237
  {
2372
3238
  pubkey: signer,
@@ -2399,7 +3265,7 @@ async function submitSatClaimProtocolDistributorSat(_config, params) {
2399
3265
  isWritable: true
2400
3266
  },
2401
3267
  {
2402
- pubkey: new solana.PublicKey(SAT_MINT_ADDRESS()),
3268
+ pubkey: new solana.PublicKey(resolveSatMintAddressFromEnv(effectiveEnv)),
2403
3269
  isSigner: false,
2404
3270
  isWritable: true
2405
3271
  },
@@ -2424,7 +3290,12 @@ async function submitSatClaimProtocolDistributorSat(_config, params) {
2424
3290
  isWritable: false
2425
3291
  },
2426
3292
  {
2427
- pubkey: new solana.PublicKey(SAT_MINT_PROGRAM_ID()),
3293
+ pubkey: new solana.PublicKey(resolveSatMintProgramIdFromEnv(effectiveEnv)),
3294
+ isSigner: false,
3295
+ isWritable: false
3296
+ },
3297
+ {
3298
+ pubkey: new solana.PublicKey(resolveSatBondProgramIdFromEnv(effectiveEnv)),
2428
3299
  isSigner: false,
2429
3300
  isWritable: false
2430
3301
  }
@@ -2442,6 +3313,8 @@ async function submitSatRetargetUnlock(_config, params) {
2442
3313
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2443
3314
  const [satGlobalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_GLOBAL_STATE_SEED)], programId);
2444
3315
  const [satCycleState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)], programId);
3316
+ const intervalStartCycleId = Math.max(0, params.cycleId + 1 - SAT_PROTOCOL_CONSTANTS.cycleUnlockRetargetIntervalCycles);
3317
+ const [satUnlockIntervalState] = solana.PublicKey.findProgramAddressSync([Buffer.from(SAT_UNLOCK_INTERVAL_STATE_SEED), encodeU64(intervalStartCycleId)], programId);
2445
3318
  return [
2446
3319
  {
2447
3320
  pubkey: signer,
@@ -2457,6 +3330,11 @@ async function submitSatRetargetUnlock(_config, params) {
2457
3330
  pubkey: satCycleState,
2458
3331
  isSigner: false,
2459
3332
  isWritable: false
3333
+ },
3334
+ {
3335
+ pubkey: satUnlockIntervalState,
3336
+ isSigner: false,
3337
+ isWritable: true
2460
3338
  }
2461
3339
  ];
2462
3340
  }
@@ -2677,10 +3555,16 @@ async function submitSatCompactPendingCycleRange(_config, params) {
2677
3555
  isWritable: false
2678
3556
  });
2679
3557
  }
2680
- return accounts;
3558
+ return {
3559
+ keys: accounts,
3560
+ context: {
3561
+ frontCycleIds: params.frontCycleIds.map(String),
3562
+ backCycleIds: params.backCycleIds.map(String)
3563
+ }
3564
+ };
2681
3565
  }
2682
3566
  });
2683
3567
  }
2684
3568
 
2685
3569
  //#endregion
2686
- export { submitSatCancelBondUnlock, submitSatClaimBondStakingRewards, submitSatFinalizeBondUnlock, submitSatIncreaseBondPosition, submitSatInitBondStakingDistributor, submitSatOpenBondPosition, submitSatRequestBondUnlock, submitSatSyncBondStakingPosition, submitSatSyncBondStakingRewards };
3570
+ export { runWithSatSubmissionWorkflow, submitSatCancelBondUnlock, submitSatClaimBondStakingRewards, submitSatFinalizeBondUnlock, submitSatIncreaseBondPosition, submitSatOpenBondPosition, submitSatRequestBondUnlock, submitSatSyncBondStakingPosition, submitSatSyncBondStakingRewards };