@fased/fased 0.1.62 → 0.1.64

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 (341) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +38 -30
  3. package/config/dependency-ownership.json +1 -1
  4. package/config/signer-policies/README.md +49 -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 +76 -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-bR-fO5ty.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-ckCxHwjy.js} +3 -3
  80. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-BgHFh0ei.js} +134 -114
  81. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  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 +235 -67
  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 +1038 -397
  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-BYxAt775.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-DIRHG2gJ.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-BOT7kHb6.js} +6779 -3696
  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-BCFDaqJ-.js} +31 -31
  166. package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-BgbjRiPM.js} +32 -32
  167. package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DFf87SMM.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-B3bHYGaw.d.ts → pairing-message-CS-9BHug.d.ts} +2 -2
  172. package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  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 +549 -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-BUTt8cxK.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-D0wHVqjt.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-CC_qN4v0.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-xOTGlzBE.d.ts +486 -0
  208. package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-C3avNytw.d.ts} +3 -4
  209. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
  210. package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-DWfbSAaM.d.ts} +2 -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-BXsJ1vqe.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 +561 -118
  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 +90 -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 +90 -36
  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 +12 -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 +12 -0
  284. package/extensions/msteams/package.json +1 -1
  285. package/extensions/nextcloud-talk/package.json +1 -1
  286. package/extensions/nostr/CHANGELOG.md +12 -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 +498 -153
  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 +50 -5
  293. package/extensions/sat-mining/src/claim-service.ts +85 -14
  294. package/extensions/sat-mining/src/config.ts +9 -0
  295. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  296. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  297. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  298. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  299. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  300. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  301. package/extensions/sat-mining/src/rpc-read.ts +330 -89
  302. package/extensions/sat-mining/src/runtime.ts +14 -0
  303. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  304. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  305. package/extensions/sat-mining/src/solana-submit.ts +1199 -428
  306. package/extensions/sat-mining/src/submission-ledger.ts +433 -0
  307. package/extensions/signal/package.json +1 -1
  308. package/extensions/synology-chat/package.json +1 -1
  309. package/extensions/tlon/package.json +1 -1
  310. package/extensions/twitch/CHANGELOG.md +12 -0
  311. package/extensions/twitch/package.json +1 -1
  312. package/extensions/voice-call/CHANGELOG.md +12 -0
  313. package/extensions/voice-call/package.json +1 -1
  314. package/extensions/zalo/CHANGELOG.md +12 -0
  315. package/extensions/zalo/package.json +1 -1
  316. package/extensions/zalouser/CHANGELOG.md +12 -0
  317. package/extensions/zalouser/package.json +1 -1
  318. package/install.sh +4955 -0
  319. package/package.json +23 -5
  320. package/scripts/fased-host-updater.mjs +1421 -0
  321. package/scripts/fased-host-updaterctl.mjs +186 -0
  322. package/scripts/fased-managed-service.sh +36 -0
  323. package/scripts/fased-managed-updater.mjs +3065 -156
  324. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  325. package/scripts/fased-signer-network-hosting.sh +143 -0
  326. package/scripts/fased-signer-owner-policy.mjs +1430 -0
  327. package/scripts/fased-signer-policy-hosting.sh +50 -0
  328. package/scripts/fased-signer-policy-local.sh +26 -0
  329. package/scripts/hosted-release-manifest.mjs +185 -0
  330. package/scripts/install-fased-signerd.sh +183 -108
  331. package/scripts/install-managed-runtime.mjs +212 -10
  332. package/scripts/managed-runtime-layout.mjs +75 -3
  333. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  334. package/scripts/start-managed.sh +169 -360
  335. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  336. package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
  337. package/dist/wallet/local-socket-signer-broker.js +0 -224
  338. package/dist/wallet/local-socket-signer-custody.js +0 -42
  339. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  340. package/dist/wallet/providers/privy-adapter.js +0 -80
  341. package/dist/wallet/wallet-custody.js +0 -1836
@@ -1,7 +1,11 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { createHash } from "node:crypto";
1
3
  import { createRequire } from "node:module";
4
+ import { isDeepStrictEqual } from "node:util";
2
5
  import {
3
6
  callLocalSocketSigner,
4
- enforceWalletCustodyForAutonomousSend,
7
+ createSignerReviewApprovalRequest,
8
+ LEGACY_EMBEDDED_KEYSTORE_MIGRATION_MESSAGE,
5
9
  loadConfig,
6
10
  readWalletProviderRegistry,
7
11
  requireLocalSocketSignerPath,
@@ -12,14 +16,30 @@ import {
12
16
  resolveWalletProviderId,
13
17
  resolveWalletRuntimeConfig,
14
18
  type FasedAgentConfig,
19
+ type WalletProviderJupiterReviewV2,
15
20
  } from "fased/plugin-sdk/sat-runtime";
16
21
  import type { SatMiningConfig } from "./config.js";
17
22
  import { decodeHash32 } from "./hash-spec.js";
18
23
  import {
24
+ resolveSatGenesisProfileContract,
19
25
  SAT_BOND_INSTRUCTION_DISCRIMINATORS,
20
26
  SAT_INSTRUCTION_DISCRIMINATORS,
27
+ SAT_PROTOCOL_CONSTANTS,
21
28
  } from "./protocol-contract.js";
22
- import { inspectSatCycleRegistryMeta, inspectSatMinerCyclesByAddress } from "./rpc-read.js";
29
+ import {
30
+ inspectSatCycle,
31
+ inspectSatCycleRegistryMeta,
32
+ inspectSatMinerCyclesByAddress,
33
+ } from "./rpc-read.js";
34
+ import { resolveSatSignerCodec, type SatSignerAction } from "./signer-codec-manifest.js";
35
+ import {
36
+ buildSatSubmissionOperationKey,
37
+ claimSatSubmission,
38
+ digestSatSubmissionIntent,
39
+ updateSatSubmission,
40
+ waitForSatSubmissionLease,
41
+ type SatSubmissionSignerState,
42
+ } from "./submission-ledger.js";
23
43
 
24
44
  const require = createRequire(import.meta.url);
25
45
 
@@ -47,16 +67,44 @@ const SAT_TREASURY_STATE_SEED = "sat_treasury_state";
47
67
  const SAT_REGISTRY_RESERVE_SEED = "sat_registry_reserve";
48
68
  const SAT_REBATE_VAULT_SEED = "sat_rebate_vault";
49
69
  const SAT_TREASURY_VAULT_SEED = "sat_treasury_vault";
70
+ const SAT_UNLOCK_INTERVAL_STATE_SEED = "sat_unlock_interval_state";
50
71
  const SAT_CYCLE_REGISTRY_PAGE_CAPACITY = 64;
51
72
  const MINING_POOL_SEED = "mining_pool";
52
73
  const MINING_STAKE_SEED = "mining_stake";
53
74
  const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
54
75
  const ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
76
+ const SLOT_HASHES_SYSVAR_ID = "SysvarS1otHashes111111111111111111111111111";
55
77
 
56
78
  const IX = SAT_INSTRUCTION_DISCRIMINATORS;
57
79
 
58
80
  const BOND_IX = SAT_BOND_INSTRUCTION_DISCRIMINATORS;
59
81
 
82
+ const VAULT_BOND_ACTIONS = new Set<SatSignerAction>([
83
+ "updateBondTierPolicy",
84
+ "openBondPosition",
85
+ "increaseBondPosition",
86
+ "requestBondUnlock",
87
+ "cancelBondUnlock",
88
+ "finalizeBondUnlock",
89
+ "syncBondStakingRewards",
90
+ "syncBondStakingPosition",
91
+ "claimBondStakingRewards",
92
+ "claimUnallocatedStakingRewards",
93
+ ]);
94
+
95
+ const satSubmissionWorkflowStorage = new AsyncLocalStorage<string>();
96
+
97
+ export async function runWithSatSubmissionWorkflow<T>(
98
+ workflowId: string,
99
+ task: () => Promise<T>,
100
+ ): Promise<T> {
101
+ const normalized = workflowId.trim();
102
+ if (!normalized || normalized.length > 240 || /[\u0000-\u001f\u007f]/u.test(normalized)) {
103
+ throw new Error("SAT submission idempotency key must contain 1-240 printable characters");
104
+ }
105
+ return await satSubmissionWorkflowStorage.run(normalized, task);
106
+ }
107
+
60
108
  function satSubmitDebug(message: string) {
61
109
  if (String(process.env.FASED_SAT_SUBMIT_DEBUG ?? "").trim() === "1") {
62
110
  console.error(message);
@@ -71,6 +119,21 @@ type SolanaAccountMeta = {
71
119
  isWritable: boolean;
72
120
  };
73
121
 
122
+ type SatSignerSemanticContext = {
123
+ targetAuthority?: string;
124
+ disputeAuthority?: string;
125
+ intervalStartCycleId?: string;
126
+ registryPageIndex?: string;
127
+ minerAuthorities?: string[];
128
+ frontCycleIds?: string[];
129
+ backCycleIds?: string[];
130
+ };
131
+
132
+ type SatResolvedInstruction = {
133
+ keys: SolanaAccountMeta[];
134
+ context?: SatSignerSemanticContext;
135
+ };
136
+
74
137
  let solanaModulePromise: Promise<SolanaModuleLike> | null = null;
75
138
 
76
139
  async function loadSolanaWeb3(): Promise<SolanaModuleLike> {
@@ -115,6 +178,11 @@ function resolveSatWalletId(cfg: FasedAgentConfig): string | undefined {
115
178
  return typeof value === "string" && value.trim() ? value.trim() : undefined;
116
179
  }
117
180
 
181
+ function resolveSatCluster(cfg: FasedAgentConfig): "local" | "devnet" | "mainnet-beta" {
182
+ const value = cfg.plugins?.entries?.["sat-mining"]?.config?.network;
183
+ return value === "local" || value === "mainnet-beta" || value === "devnet" ? value : "devnet";
184
+ }
185
+
118
186
  function resolveSatEffectiveEnv(cfg: FasedAgentConfig, env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
119
187
  return {
120
188
  ...env,
@@ -125,92 +193,58 @@ function resolveSatEffectiveEnv(cfg: FasedAgentConfig, env: NodeJS.ProcessEnv):
125
193
  function resolveSatProviderId(cfg: FasedAgentConfig, env: NodeJS.ProcessEnv): string {
126
194
  const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
127
195
  const walletId = resolveSatWalletId(cfg);
196
+ const signerSocket = String(effectiveEnv.FASED_WALLET_LOCAL_SIGNER_SOCKET ?? "").trim();
128
197
  if (walletId) {
129
- const hasSelfHostedSignerMaterial =
130
- String(effectiveEnv.FASED_WALLET_LOCAL_SIGNER_SOCKET ?? "").trim() ||
131
- String(effectiveEnv.FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET ?? "").trim() ||
132
- String(
133
- walletEnvValue(effectiveEnv, "FASED_WALLET_SOLANA_KEYSTORE_PATH", walletId) ?? "",
134
- ).trim();
135
- try {
136
- const wallet = readWalletProviderRegistry(effectiveEnv).wallets.find(
137
- (entry) => entry.id === walletId,
198
+ const wallet = readWalletProviderRegistry(effectiveEnv).wallets.find(
199
+ (entry) => entry.id === walletId,
200
+ );
201
+ if (wallet?.providerId === "embedded-keystore") {
202
+ throw new Error(LEGACY_EMBEDDED_KEYSTORE_MIGRATION_MESSAGE);
203
+ }
204
+ if (wallet?.providerId && wallet.providerId !== "local-socket-signer") {
205
+ return wallet.providerId;
206
+ }
207
+ if (wallet?.providerId === "local-socket-signer" && !signerSocket) {
208
+ throw new Error(
209
+ "SAT mining requires the actual protocol-v2 fased-signerd application socket; legacy keystore paths and backend sockets are not signer capability.",
138
210
  );
139
- if (wallet?.providerId === "local-socket-signer") {
140
- return wallet.providerId;
141
- }
142
- if (hasSelfHostedSignerMaterial) {
143
- return "local-socket-signer";
144
- }
145
- if (wallet?.providerId) {
146
- return wallet.providerId;
147
- }
148
- } catch {}
149
- if (hasSelfHostedSignerMaterial) {
150
- return "local-socket-signer";
211
+ }
212
+ if (wallet?.providerId === "local-socket-signer") {
213
+ return wallet.providerId;
151
214
  }
152
215
  }
153
- return resolveWalletProviderId(cfg, effectiveEnv);
154
- }
155
-
156
- async function enforceSatCustodyAutonomousSigning(
157
- cfg: FasedAgentConfig,
158
- env: NodeJS.ProcessEnv,
159
- ): Promise<void> {
160
- const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
161
- const walletCfg = resolveWalletRuntimeConfig(cfg, effectiveEnv);
162
- const walletId = resolveSatWalletId(cfg);
163
- if (walletCfg.execution.mode !== "autonomous") {
164
- return;
165
- }
166
- const custodyGate = await enforceWalletCustodyForAutonomousSend({
167
- wallet: walletCfg,
168
- env: effectiveEnv,
169
- cfg,
170
- walletId,
171
- approvalHost: String(
172
- effectiveEnv.FASED_WALLET_CUSTODY_ACTIVE_HOST ?? effectiveEnv.FASED_A2A_ORIGIN ?? "127.0.0.1",
173
- ),
174
- });
175
- if (!custodyGate.ok) {
176
- throw new Error(custodyGate.message);
177
- }
178
- }
179
-
180
- function resolveSatRegistrySolanaAddress(cfg: FasedAgentConfig, env: NodeJS.ProcessEnv): string {
181
- const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
182
- const walletId = resolveSatWalletId(cfg);
183
- if (!walletId) {
184
- return "";
216
+ const providerId = resolveWalletProviderId(cfg, effectiveEnv);
217
+ if (providerId === "local-socket-signer" && !signerSocket) {
218
+ throw new Error(
219
+ "SAT mining requires the actual protocol-v2 fased-signerd application socket; configure FASED_WALLET_LOCAL_SIGNER_SOCKET.",
220
+ );
185
221
  }
186
- const wallet = readWalletProviderRegistry(effectiveEnv).wallets.find(
187
- (entry) => entry.id === walletId,
188
- );
189
- return typeof wallet?.addresses?.solana === "string" ? wallet.addresses.solana.trim() : "";
222
+ return providerId;
190
223
  }
191
224
 
192
225
  async function resolveSatLocalSignerAddress(
193
226
  cfg: FasedAgentConfig,
194
227
  env: NodeJS.ProcessEnv,
195
228
  errorMessage: string,
229
+ verifyCapabilities = true,
196
230
  ): Promise<string> {
197
231
  const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
198
232
  const walletId = resolveSatWalletId(cfg);
199
- const result = await callLocalSocketSigner<{ solana?: string }>(
200
- requireLocalSocketSignerPath(effectiveEnv),
201
- {
202
- op: "getAddresses",
203
- ...(walletId ? { walletId } : {}),
204
- },
205
- );
206
- const signer = String(result.solana ?? "").trim();
233
+ if (!walletId) {
234
+ throw new Error("SAT mining local signer address lookup requires an attached walletId");
235
+ }
236
+ const socketPath = requireLocalSocketSignerPath(effectiveEnv);
237
+ if (verifyCapabilities) {
238
+ await requireTypedSatSignerCapabilities(socketPath, "solana.satAction");
239
+ }
240
+ const result = await callLocalSocketSigner<{ publicKey?: string }>(socketPath, {
241
+ op: "v2.wallet.get",
242
+ walletId,
243
+ });
244
+ const signer = String(result.publicKey ?? "").trim();
207
245
  if (signer) {
208
246
  return signer;
209
247
  }
210
- const fallback = resolveSatRegistrySolanaAddress(cfg, env);
211
- if (fallback) {
212
- return fallback;
213
- }
214
248
  throw new Error(errorMessage);
215
249
  }
216
250
 
@@ -275,7 +309,6 @@ function assertDedicatedBondProgram(env: NodeJS.ProcessEnv): void {
275
309
  export async function resolveSatValidatorAuthority(_config: SatMiningConfig) {
276
310
  const cfg = loadConfigForSatRuntime(_config);
277
311
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
278
- await enforceSatCustodyAutonomousSigning(cfg, effectiveEnv);
279
312
  if (resolveSatProviderId(cfg, effectiveEnv) !== "local-socket-signer") {
280
313
  throw new Error(
281
314
  "SAT mining unattended signing currently requires local-socket-signer for validator authority resolution",
@@ -294,7 +327,7 @@ type SatInstructionSubmitSpec = {
294
327
  accountResolver: (
295
328
  solana: SolanaModuleLike,
296
329
  signer: import("@solana/web3.js").PublicKey,
297
- ) => Promise<SolanaAccountMeta[]>;
330
+ ) => Promise<SolanaAccountMeta[] | SatResolvedInstruction>;
298
331
  };
299
332
 
300
333
  async function prepareLocalSignerSubmitContext(cfg: FasedAgentConfig, env: NodeJS.ProcessEnv) {
@@ -306,6 +339,7 @@ async function prepareLocalSignerSubmitContext(cfg: FasedAgentConfig, env: NodeJ
306
339
  cfg,
307
340
  effectiveEnv,
308
341
  "local-socket-signer returned no Solana address for SAT mining wallet",
342
+ false,
309
343
  );
310
344
  const signer = new solana.PublicKey(signerAddress);
311
345
  return { effectiveEnv, solana, walletId, socketPath, signerAddress, signer };
@@ -314,25 +348,512 @@ async function prepareLocalSignerSubmitContext(cfg: FasedAgentConfig, env: NodeJ
314
348
  async function buildLocalSignerInstructionRequest(params: {
315
349
  solana: SolanaModuleLike;
316
350
  signer: import("@solana/web3.js").PublicKey;
317
- walletId?: string;
351
+ env: NodeJS.ProcessEnv;
318
352
  spec: SatInstructionSubmitSpec;
319
353
  }) {
320
- const keys = await params.spec.accountResolver(params.solana, params.signer);
354
+ const resolved = await params.spec.accountResolver(params.solana, params.signer);
355
+ const keys = Array.isArray(resolved) ? resolved : resolved.keys;
356
+ const context = Array.isArray(resolved) ? undefined : resolved.context;
357
+ const programId = params.spec.programId ?? resolveSatProgramIdFromEnv(params.env);
358
+ const mainProgramId = resolveSatProgramIdFromEnv(params.env);
359
+ const bondProgramId = resolveSatBondProgramIdFromEnv(params.env).trim() || undefined;
360
+ const codec = resolveSatSignerCodec({
361
+ programId,
362
+ mainProgramId,
363
+ bondProgramId,
364
+ data: params.spec.data,
365
+ });
321
366
  satSubmitDebug(
322
- `[sat-submit-debug] data_len=${params.spec.data.length} disc=${params.spec.data[0] ?? -1} keys=${keys.length}`,
367
+ `[sat-submit-debug] action=${codec.action} data_len=${params.spec.data.length} disc=${params.spec.data[0] ?? -1} keys=${keys.length}`,
323
368
  );
324
369
  return {
325
- ...(params.walletId ? { walletId: params.walletId } : {}),
326
- programId: params.spec.programId ?? SAT_PROGRAM_ID(),
370
+ action: codec.action,
371
+ programId,
327
372
  dataBase64: params.spec.data.toString("base64"),
328
373
  keys: keys.map((key) => ({
329
374
  pubkey: key.pubkey.toBase58(),
330
375
  isSigner: key.isSigner,
331
376
  isWritable: key.isWritable,
332
377
  })),
378
+ ...(context ? { context } : {}),
333
379
  };
334
380
  }
335
381
 
382
+ type SatSignerOperation = {
383
+ requestId: string;
384
+ state: "reserved" | "broadcast" | "confirmed" | "failed" | "unknown";
385
+ signature?: string;
386
+ error?: string;
387
+ };
388
+
389
+ const REQUIRED_SAT_SIGNER_FEATURES = [
390
+ "failClosedPolicies",
391
+ "policyHashes",
392
+ "durableCaps",
393
+ "atomicIdempotency",
394
+ "ambiguousBroadcastReconciliation",
395
+ "signerOwnedKeys",
396
+ "typedSolanaTransactions",
397
+ "typedSATActions",
398
+ ] as const;
399
+
400
+ async function requireTypedSatSignerCapabilities(
401
+ socketPath: string,
402
+ intentType: "solana.satAction" | "solana.vaultBondAction",
403
+ ) {
404
+ const result = await callLocalSocketSigner<{
405
+ ready?: boolean;
406
+ capabilities?: {
407
+ protocol?: { current?: number; min?: number; max?: number };
408
+ intentTypes?: string[];
409
+ operationStates?: string[];
410
+ features?: string[];
411
+ };
412
+ }>(socketPath, { op: "v2.capabilities" });
413
+ const capabilities = result.capabilities;
414
+ const protocol = capabilities?.protocol;
415
+ const features = new Set(capabilities?.features ?? []);
416
+ const states = new Set(capabilities?.operationStates ?? []);
417
+ const missingFeatures = REQUIRED_SAT_SIGNER_FEATURES.filter((feature) => !features.has(feature));
418
+ const missingStates = ["reserved", "broadcast", "confirmed", "failed", "unknown"].filter(
419
+ (state) => !states.has(state),
420
+ );
421
+ const missingVaultReviewFeatures =
422
+ intentType === "solana.vaultBondAction"
423
+ ? [
424
+ "signerOwnedReviewPrepareExecute",
425
+ "exactPreparedTransactions",
426
+ "reviewedVaultBondActions",
427
+ "signerOwnedStateRecheck",
428
+ "durableReviewAuthorization",
429
+ ].filter((feature) => !features.has(feature))
430
+ : [];
431
+ if (
432
+ result.ready !== true ||
433
+ protocol?.current !== 2 ||
434
+ typeof protocol.min !== "number" ||
435
+ protocol.min > 2 ||
436
+ typeof protocol.max !== "number" ||
437
+ protocol.max < 2 ||
438
+ !capabilities?.intentTypes?.includes(intentType) ||
439
+ missingFeatures.length > 0 ||
440
+ (intentType === "solana.vaultBondAction" && !features.has("typedVaultBondActions")) ||
441
+ missingVaultReviewFeatures.length > 0 ||
442
+ missingStates.length > 0
443
+ ) {
444
+ throw new Error(
445
+ `local-socket-signer does not support the required typed SAT protocol-v2 contract${
446
+ missingFeatures.length > 0 ? `; missing features: ${missingFeatures.join(", ")}` : ""
447
+ }${missingVaultReviewFeatures.length > 0 ? `; missing reviewed Vault features: ${missingVaultReviewFeatures.join(", ")}` : ""}${
448
+ missingStates.length > 0 ? `; missing states: ${missingStates.join(", ")}` : ""
449
+ }`,
450
+ );
451
+ }
452
+ }
453
+
454
+ async function reconcileTypedSatOperation(params: {
455
+ socketPath: string;
456
+ walletId: string;
457
+ requestId: string;
458
+ operation?: SatSignerOperation;
459
+ }) {
460
+ let operation =
461
+ params.operation ??
462
+ (await callLocalSocketSigner<SatSignerOperation>(params.socketPath, {
463
+ op: "v2.operation.get",
464
+ walletId: params.walletId,
465
+ request: { requestId: params.requestId },
466
+ }));
467
+ if (operation.state === "broadcast" || operation.state === "unknown") {
468
+ try {
469
+ operation = await callLocalSocketSigner<SatSignerOperation>(params.socketPath, {
470
+ op: "v2.operation.reconcile",
471
+ walletId: params.walletId,
472
+ request: { requestId: params.requestId },
473
+ });
474
+ } catch {
475
+ // The durable signature and ambiguous state remain authoritative. Never
476
+ // replace this with a second request ID or another broadcast attempt.
477
+ }
478
+ }
479
+ return operation;
480
+ }
481
+
482
+ function assertSatSignerOperationIdentity(
483
+ operation: SatSignerOperation,
484
+ requestId: string,
485
+ ): SatSignerOperation {
486
+ if (operation.requestId !== requestId) {
487
+ throw new Error(
488
+ `SAT signer returned request ${operation.requestId || "<empty>"} while reconciling ${requestId}`,
489
+ );
490
+ }
491
+ return operation;
492
+ }
493
+
494
+ function signerStateForLedger(state: SatSignerOperation["state"]): SatSubmissionSignerState {
495
+ return state;
496
+ }
497
+
498
+ class SatSubmissionUnresolvedError extends Error {
499
+ readonly requestId: string;
500
+ readonly signature?: string;
501
+
502
+ constructor(params: { requestId: string; state: string; signature?: string; detail?: string }) {
503
+ super(
504
+ `SAT signer operation ${params.requestId} remains ${params.state}${
505
+ params.signature ? ` with signature ${params.signature}` : ""
506
+ }; it is unresolved and must be reconciled with the same idempotency key before any new submission${
507
+ params.detail ? ` (${params.detail})` : ""
508
+ }`,
509
+ );
510
+ this.name = "SatSubmissionUnresolvedError";
511
+ this.requestId = params.requestId;
512
+ this.signature = params.signature;
513
+ }
514
+ }
515
+
516
+ async function executeTypedSatIntent(params: {
517
+ socketPath: string;
518
+ walletId: string;
519
+ action: SatSignerAction | "cleanupBatch";
520
+ instruction?: Awaited<ReturnType<typeof buildLocalSignerInstructionRequest>>;
521
+ instructions?: Array<Awaited<ReturnType<typeof buildLocalSignerInstructionRequest>>>;
522
+ cluster: "local" | "devnet" | "mainnet-beta";
523
+ env: NodeJS.ProcessEnv;
524
+ }) {
525
+ const isVaultBond = params.action !== "cleanupBatch" && VAULT_BOND_ACTIONS.has(params.action);
526
+ const intentType = isVaultBond ? "solana.vaultBondAction" : "solana.satAction";
527
+ await requireTypedSatSignerCapabilities(params.socketPath, intentType);
528
+ const intent = isVaultBond
529
+ ? (() => {
530
+ if (!params.instruction || params.instructions) {
531
+ throw new Error("typed Vault bond execution requires exactly one semantic instruction");
532
+ }
533
+ return {
534
+ type: "solana.vaultBondAction" as const,
535
+ cluster: params.cluster,
536
+ ...params.instruction,
537
+ };
538
+ })()
539
+ : {
540
+ type: "solana.satAction" as const,
541
+ action: params.action,
542
+ ...(params.instruction ?? {}),
543
+ ...(params.instructions ? { instructions: params.instructions } : {}),
544
+ };
545
+ const policy = await callLocalSocketSigner<{ hash: string }>(params.socketPath, {
546
+ op: "v2.policy.get",
547
+ walletId: params.walletId,
548
+ });
549
+ const intentDigest = digestSatSubmissionIntent({
550
+ walletId: params.walletId,
551
+ policyHash: policy.hash,
552
+ intent,
553
+ });
554
+ const operationKey = buildSatSubmissionOperationKey(intent);
555
+ const workflowId =
556
+ satSubmissionWorkflowStorage.getStore() ?? `derived:${operationKey}:${intentDigest}`;
557
+ let claim = await claimSatSubmission({
558
+ walletId: params.walletId,
559
+ workflowId,
560
+ operationKey,
561
+ intentDigest,
562
+ action: params.action,
563
+ env: params.env,
564
+ });
565
+ if (!claim.claimed) {
566
+ await waitForSatSubmissionLease({
567
+ walletId: params.walletId,
568
+ requestId: claim.record.requestId,
569
+ env: params.env,
570
+ });
571
+ claim = await claimSatSubmission({
572
+ walletId: params.walletId,
573
+ workflowId,
574
+ operationKey,
575
+ intentDigest,
576
+ action: params.action,
577
+ env: params.env,
578
+ owner: claim.owner,
579
+ });
580
+ if (!claim.claimed) {
581
+ throw new Error(
582
+ `SAT submission ${claim.record.requestId} could not acquire its durable execution lease`,
583
+ );
584
+ }
585
+ }
586
+ const requestId = claim.record.requestId;
587
+ let resumedReviewedOperation: SatSignerOperation | undefined;
588
+ if (intent.type === "solana.vaultBondAction") {
589
+ let reviewWasSigned = false;
590
+ try {
591
+ let review: WalletProviderJupiterReviewV2;
592
+ try {
593
+ review = await callLocalSocketSigner<WalletProviderJupiterReviewV2>(params.socketPath, {
594
+ op: "v2.review.get",
595
+ walletId: params.walletId,
596
+ request: { requestId },
597
+ });
598
+ } catch (lookupError) {
599
+ if (!String(lookupError).includes("signer review not found")) {
600
+ throw lookupError;
601
+ }
602
+ review = await callLocalSocketSigner<WalletProviderJupiterReviewV2>(params.socketPath, {
603
+ op: "v2.review.prepare",
604
+ walletId: params.walletId,
605
+ request: {
606
+ requestId,
607
+ policyHash: policy.hash,
608
+ mode: "reviewed",
609
+ intent,
610
+ },
611
+ });
612
+ }
613
+ if (
614
+ review.requestId !== requestId ||
615
+ review.policyHash !== policy.hash ||
616
+ review.mode !== "reviewed" ||
617
+ review.intentType !== intent.type ||
618
+ !isDeepStrictEqual(review.semanticIntent, intent)
619
+ ) {
620
+ throw new Error(`Vault bond review ${requestId} does not match the exact SAT intent`);
621
+ }
622
+ if (review.state === "prepared") {
623
+ const approval = createSignerReviewApprovalRequest({
624
+ review,
625
+ role: "vault",
626
+ walletId: params.walletId,
627
+ requestedBy: "sat-mining-vault",
628
+ assetSymbol: "SAT",
629
+ assetName: "SAT bond",
630
+ memo: `Reviewed Vault bond action: ${intent.action}`,
631
+ env: params.env,
632
+ });
633
+ await updateSatSubmission({
634
+ walletId: params.walletId,
635
+ requestId,
636
+ intentDigest,
637
+ state: "reserved",
638
+ error: `review ${approval.id} pending`,
639
+ owner: claim.owner,
640
+ releaseLease: true,
641
+ env: params.env,
642
+ });
643
+ throw new Error(
644
+ `Vault bond review ${approval.id} is pending in Wallet Approvals for ${intent.action}; approve it there with the signer-owned passkey`,
645
+ );
646
+ }
647
+ reviewWasSigned = true;
648
+ resumedReviewedOperation = assertSatSignerOperationIdentity(
649
+ await reconcileTypedSatOperation({
650
+ socketPath: params.socketPath,
651
+ walletId: params.walletId,
652
+ requestId,
653
+ }),
654
+ requestId,
655
+ );
656
+ } catch (error) {
657
+ await updateSatSubmission({
658
+ walletId: params.walletId,
659
+ requestId,
660
+ intentDigest,
661
+ state: reviewWasSigned ? "unknown" : "reserved",
662
+ error: error instanceof Error ? error.message : String(error),
663
+ owner: claim.owner,
664
+ releaseLease: true,
665
+ env: params.env,
666
+ }).catch(() => undefined);
667
+ throw error;
668
+ }
669
+ }
670
+ const executeExactOrRecover = async (): Promise<SatSignerOperation> => {
671
+ try {
672
+ return await callLocalSocketSigner<SatSignerOperation>(params.socketPath, {
673
+ op: "v2.execute",
674
+ walletId: params.walletId,
675
+ request: {
676
+ requestId,
677
+ policyHash: policy.hash,
678
+ intent,
679
+ },
680
+ });
681
+ } catch (executeError) {
682
+ try {
683
+ return await callLocalSocketSigner<SatSignerOperation>(params.socketPath, {
684
+ op: "v2.operation.get",
685
+ walletId: params.walletId,
686
+ request: { requestId },
687
+ });
688
+ } catch (lookupError) {
689
+ const detail = `${executeError instanceof Error ? executeError.message : String(executeError)}; ${
690
+ lookupError instanceof Error ? lookupError.message : String(lookupError)
691
+ }`;
692
+ await updateSatSubmission({
693
+ walletId: params.walletId,
694
+ requestId,
695
+ intentDigest,
696
+ state:
697
+ claim.record.state === "confirmed" || claim.record.state === "failed"
698
+ ? claim.record.state
699
+ : "unknown",
700
+ ...(claim.record.signature ? { signature: claim.record.signature } : {}),
701
+ error: detail,
702
+ owner: claim.owner,
703
+ releaseLease: true,
704
+ env: params.env,
705
+ });
706
+ throw new SatSubmissionUnresolvedError({ requestId, state: "unknown", detail });
707
+ }
708
+ }
709
+ };
710
+ let operation: SatSignerOperation;
711
+ if (resumedReviewedOperation) {
712
+ operation = resumedReviewedOperation;
713
+ } else if (!claim.created) {
714
+ const callerStateWasAmbiguous =
715
+ claim.record.state === "broadcast" || claim.record.state === "unknown";
716
+ try {
717
+ operation = assertSatSignerOperationIdentity(
718
+ await callLocalSocketSigner<SatSignerOperation>(params.socketPath, {
719
+ op: "v2.operation.get",
720
+ walletId: params.walletId,
721
+ request: { requestId },
722
+ }),
723
+ requestId,
724
+ );
725
+ operation = assertSatSignerOperationIdentity(
726
+ await reconcileTypedSatOperation({
727
+ socketPath: params.socketPath,
728
+ walletId: params.walletId,
729
+ requestId,
730
+ operation,
731
+ }),
732
+ requestId,
733
+ );
734
+ } catch (lookupError) {
735
+ if (claim.record.signature) {
736
+ await updateSatSubmission({
737
+ walletId: params.walletId,
738
+ requestId,
739
+ intentDigest,
740
+ state: claim.record.state === "confirmed" ? "confirmed" : "unknown",
741
+ signature: claim.record.signature,
742
+ error: lookupError instanceof Error ? lookupError.message : String(lookupError),
743
+ owner: claim.owner,
744
+ releaseLease: true,
745
+ env: params.env,
746
+ });
747
+ throw new SatSubmissionUnresolvedError({
748
+ requestId,
749
+ state: claim.record.state === "confirmed" ? "confirmed-but-unverified" : "unknown",
750
+ signature: claim.record.signature,
751
+ detail: lookupError instanceof Error ? lookupError.message : String(lookupError),
752
+ });
753
+ }
754
+ if (claim.record.state === "failed" || claim.record.state === "confirmed") {
755
+ const detail = lookupError instanceof Error ? lookupError.message : String(lookupError);
756
+ await updateSatSubmission({
757
+ walletId: params.walletId,
758
+ requestId,
759
+ intentDigest,
760
+ state: claim.record.state,
761
+ error: detail,
762
+ owner: claim.owner,
763
+ releaseLease: true,
764
+ env: params.env,
765
+ });
766
+ if (claim.record.state === "failed") {
767
+ throw new Error(claim.record.error || `SAT signer operation ${requestId} failed`);
768
+ }
769
+ throw new SatSubmissionUnresolvedError({
770
+ requestId,
771
+ state: "confirmed-without-signature",
772
+ detail,
773
+ });
774
+ }
775
+ operation = await executeExactOrRecover();
776
+ }
777
+ if (operation.state === "reserved" && !operation.signature) {
778
+ if (callerStateWasAmbiguous) {
779
+ const detail = `signer regressed to reserved after caller persisted ${claim.record.state}`;
780
+ await updateSatSubmission({
781
+ walletId: params.walletId,
782
+ requestId,
783
+ intentDigest,
784
+ state: "unknown",
785
+ ...(claim.record.signature ? { signature: claim.record.signature } : {}),
786
+ error: detail,
787
+ owner: claim.owner,
788
+ releaseLease: true,
789
+ env: params.env,
790
+ });
791
+ throw new SatSubmissionUnresolvedError({
792
+ requestId,
793
+ state: "unknown",
794
+ signature: claim.record.signature,
795
+ detail,
796
+ });
797
+ }
798
+ operation = await executeExactOrRecover();
799
+ }
800
+ } else {
801
+ operation = await executeExactOrRecover();
802
+ }
803
+ try {
804
+ operation = assertSatSignerOperationIdentity(operation, requestId);
805
+ operation = assertSatSignerOperationIdentity(
806
+ await reconcileTypedSatOperation({
807
+ socketPath: params.socketPath,
808
+ walletId: params.walletId,
809
+ requestId,
810
+ operation,
811
+ }),
812
+ requestId,
813
+ );
814
+ } catch (error) {
815
+ const detail = error instanceof Error ? error.message : String(error);
816
+ await updateSatSubmission({
817
+ walletId: params.walletId,
818
+ requestId,
819
+ intentDigest,
820
+ state:
821
+ claim.record.state === "confirmed" || claim.record.state === "failed"
822
+ ? claim.record.state
823
+ : "unknown",
824
+ ...(claim.record.signature ? { signature: claim.record.signature } : {}),
825
+ error: detail,
826
+ owner: claim.owner,
827
+ releaseLease: true,
828
+ env: params.env,
829
+ });
830
+ throw new SatSubmissionUnresolvedError({ requestId, state: "unknown", detail });
831
+ }
832
+ await updateSatSubmission({
833
+ walletId: params.walletId,
834
+ requestId,
835
+ intentDigest,
836
+ state: signerStateForLedger(operation.state),
837
+ ...(operation.signature ? { signature: operation.signature } : {}),
838
+ ...(operation.error ? { error: operation.error } : {}),
839
+ owner: claim.owner,
840
+ releaseLease: true,
841
+ env: params.env,
842
+ });
843
+ if (operation.state === "failed") {
844
+ throw new Error(operation.error || `SAT signer operation ${requestId} failed`);
845
+ }
846
+ if (operation.state !== "confirmed" || !operation.signature) {
847
+ throw new SatSubmissionUnresolvedError({
848
+ requestId,
849
+ state: operation.state,
850
+ signature: operation.signature,
851
+ detail: operation.error,
852
+ });
853
+ }
854
+ return { ...operation, signature: operation.signature };
855
+ }
856
+
336
857
  async function submitInstructionViaLocalSigner(
337
858
  params: {
338
859
  cfg: FasedAgentConfig;
@@ -343,34 +864,35 @@ async function submitInstructionViaLocalSigner(
343
864
  const request = await buildLocalSignerInstructionRequest({
344
865
  solana: context.solana,
345
866
  signer: context.signer,
346
- walletId: context.walletId,
867
+ env: context.effectiveEnv,
347
868
  spec: params,
348
869
  });
349
- const submitted = await callLocalSocketSigner<{ txHash: string; signer?: string }>(
350
- context.socketPath,
351
- {
352
- op: "sendSolanaInstruction",
353
- request,
354
- },
355
- );
870
+ if (!context.walletId) {
871
+ throw new Error("typed SAT signing requires an explicit mining walletId");
872
+ }
873
+ const submitted = await executeTypedSatIntent({
874
+ socketPath: context.socketPath,
875
+ walletId: context.walletId,
876
+ action: request.action,
877
+ instruction: request,
878
+ cluster: resolveSatCluster(params.cfg),
879
+ env: context.effectiveEnv,
880
+ });
356
881
  return {
357
- txHash: submitted.txHash,
358
- signer: submitted.signer ?? context.signerAddress,
882
+ txHash: submitted.signature,
883
+ signer: context.signerAddress,
884
+ signerState: submitted.state,
885
+ requestId: submitted.requestId,
359
886
  };
360
887
  }
361
888
 
362
- async function submitInstruction(params: {
363
- cfg: FasedAgentConfig;
364
- env: NodeJS.ProcessEnv;
365
- data: Buffer;
366
- programId?: string;
367
- accountResolver: (
368
- solana: SolanaModuleLike,
369
- signer: import("@solana/web3.js").PublicKey,
370
- ) => Promise<import("@solana/web3.js").AccountMeta[]>;
371
- }) {
889
+ async function submitInstruction(
890
+ params: {
891
+ cfg: FasedAgentConfig;
892
+ env: NodeJS.ProcessEnv;
893
+ } & SatInstructionSubmitSpec,
894
+ ) {
372
895
  const effectiveEnv = resolveSatEffectiveEnv(params.cfg, params.env);
373
- await enforceSatCustodyAutonomousSigning(params.cfg, effectiveEnv);
374
896
  if (resolveSatProviderId(params.cfg, effectiveEnv) !== "local-socket-signer") {
375
897
  throw new Error("SAT mining unattended submission currently requires local-socket-signer");
376
898
  }
@@ -396,7 +918,6 @@ async function submitInstructionBatch(params: {
396
918
  throw new Error("SAT cleanup batch exceeds signer limit");
397
919
  }
398
920
  const effectiveEnv = resolveSatEffectiveEnv(params.cfg, params.env);
399
- await enforceSatCustodyAutonomousSigning(params.cfg, effectiveEnv);
400
921
  if (resolveSatProviderId(params.cfg, effectiveEnv) !== "local-socket-signer") {
401
922
  throw new Error(
402
923
  "SAT mining unattended batch submission currently requires local-socket-signer",
@@ -409,26 +930,27 @@ async function submitInstructionBatch(params: {
409
930
  await buildLocalSignerInstructionRequest({
410
931
  solana: context.solana,
411
932
  signer: context.signer,
412
- walletId: context.walletId,
933
+ env: context.effectiveEnv,
413
934
  spec,
414
935
  }),
415
936
  );
416
937
  }
417
- const submitted = await callLocalSocketSigner<{
418
- txHash: string;
419
- signer?: string;
420
- metadata?: Record<string, unknown>;
421
- }>(context.socketPath, {
422
- op: "sendSolanaInstructions",
423
- request: {
424
- ...(context.walletId ? { walletId: context.walletId } : {}),
425
- purpose: params.purpose,
426
- instructions,
427
- },
938
+ if (!context.walletId) {
939
+ throw new Error("typed SAT cleanup signing requires an explicit mining walletId");
940
+ }
941
+ const submitted = await executeTypedSatIntent({
942
+ socketPath: context.socketPath,
943
+ walletId: context.walletId,
944
+ action: "cleanupBatch",
945
+ instructions,
946
+ cluster: resolveSatCluster(params.cfg),
947
+ env: context.effectiveEnv,
428
948
  });
429
949
  return {
430
- txHash: submitted.txHash,
431
- signer: submitted.signer ?? context.signerAddress,
950
+ txHash: submitted.signature,
951
+ signer: context.signerAddress,
952
+ signerState: submitted.state,
953
+ requestId: submitted.requestId,
432
954
  instructionCount: instructions.length,
433
955
  };
434
956
  }
@@ -568,11 +1090,10 @@ function buildMiningCrankData() {
568
1090
  return Buffer.from([IX.miningCrank]);
569
1091
  }
570
1092
 
571
- function buildBootstrapData(params: { authority: string; initialStake: number }) {
1093
+ function buildTopUpRegistryReserveData(params: { targetBalanceLamports: number }) {
572
1094
  return Buffer.concat([
573
- Buffer.from([IX.bootstrap]),
574
- encodePubkey(params.authority),
575
- encodeU64(params.initialStake),
1095
+ Buffer.from([IX.topUpRegistryReserve]),
1096
+ encodeU64(params.targetBalanceLamports),
576
1097
  ]);
577
1098
  }
578
1099
 
@@ -596,23 +1117,6 @@ function buildSetActiveCommitData(params: { lamports: number }) {
596
1117
  return Buffer.concat([Buffer.from([IX.setActiveCommit]), encodeU64(params.lamports)]);
597
1118
  }
598
1119
 
599
- function buildInitBondTierPolicyData(params: {
600
- updateAuthority: string;
601
- basicMinRaw: number;
602
- operatorMinRaw: number;
603
- unlockDelaySlots: number;
604
- scheduledEffectiveSlot?: number;
605
- }) {
606
- return Buffer.concat([
607
- Buffer.from([BOND_IX.initTierPolicy]),
608
- encodePubkey(params.updateAuthority),
609
- encodeU64(params.basicMinRaw),
610
- encodeU64(params.operatorMinRaw),
611
- encodeU64(params.unlockDelaySlots),
612
- encodeU64(params.scheduledEffectiveSlot ?? 0),
613
- ]);
614
- }
615
-
616
1120
  function buildUpdateBondTierPolicyData(params: {
617
1121
  updateAuthority: string;
618
1122
  basicMinRaw: number;
@@ -661,18 +1165,6 @@ function buildFinalizeBondUnlockData(env: NodeJS.ProcessEnv = process.env) {
661
1165
  return Buffer.from([BOND_IX.finalizeBondUnlock]);
662
1166
  }
663
1167
 
664
- function buildInitBondStakingDistributorData(
665
- params: { updateAuthority: string; minStakeRaw: number },
666
- env: NodeJS.ProcessEnv = process.env,
667
- ) {
668
- assertDedicatedBondProgram(env);
669
- return Buffer.concat([
670
- Buffer.from([BOND_IX.initStakingDistributor]),
671
- encodePubkey(params.updateAuthority),
672
- encodeU64(params.minStakeRaw),
673
- ]);
674
- }
675
-
676
1168
  function buildSyncBondStakingRewardsData(env: NodeJS.ProcessEnv = process.env) {
677
1169
  assertDedicatedBondProgram(env);
678
1170
  return Buffer.from([BOND_IX.syncStakingRewards]);
@@ -688,26 +1180,96 @@ function buildClaimBondStakingRewardsData(env: NodeJS.ProcessEnv = process.env)
688
1180
  return Buffer.from([BOND_IX.claimStakingRewards]);
689
1181
  }
690
1182
 
691
- function buildSubmitCycleData(params: { cycleId: number; allocationFp: number[] }) {
692
- if (params.allocationFp.length !== 25) {
693
- throw new Error(`expected 25 allocation buckets, got ${params.allocationFp.length}`);
1183
+ function buildClaimUnallocatedStakingRewardsData(env: NodeJS.ProcessEnv = process.env) {
1184
+ assertDedicatedBondProgram(env);
1185
+ return Buffer.from([BOND_IX.claimUnallocatedStakingRewards]);
1186
+ }
1187
+
1188
+ function encodeAllocationFp(allocationFp: number[]): Buffer {
1189
+ if (allocationFp.length !== 25) {
1190
+ throw new Error(`expected 25 allocation buckets, got ${allocationFp.length}`);
1191
+ }
1192
+ return Buffer.concat(
1193
+ allocationFp.map((value) => {
1194
+ if (!Number.isSafeInteger(value) || value < 0 || value > 0xffff_ffff) {
1195
+ throw new Error(`invalid allocation bucket value: ${value}`);
1196
+ }
1197
+ const out = Buffer.alloc(4);
1198
+ out.writeUInt32LE(value);
1199
+ return out;
1200
+ }),
1201
+ );
1202
+ }
1203
+
1204
+ export function buildSatCycleCommitment(params: {
1205
+ authority: string;
1206
+ cycleId: number;
1207
+ committedLamports: number;
1208
+ nonce: Buffer;
1209
+ allocationFp: number[];
1210
+ programId?: string;
1211
+ }): Buffer {
1212
+ if (params.nonce.length !== 32) {
1213
+ throw new Error(`expected 32-byte cycle nonce, got ${params.nonce.length}`);
1214
+ }
1215
+ const allocation = encodeAllocationFp(params.allocationFp);
1216
+ return createHash("sha256")
1217
+ .update(
1218
+ Buffer.concat([
1219
+ Buffer.from("sat-cycle-commit-v1"),
1220
+ encodePubkey(params.programId ?? SAT_PROGRAM_ID()),
1221
+ encodePubkey(params.authority),
1222
+ encodeU64(params.cycleId),
1223
+ encodeU64(params.committedLamports),
1224
+ params.nonce,
1225
+ allocation,
1226
+ ]),
1227
+ )
1228
+ .digest();
1229
+ }
1230
+
1231
+ function buildCommitCycleData(params: { cycleId: number; commitment: Buffer }) {
1232
+ if (params.commitment.length !== 32) {
1233
+ throw new Error(`expected 32-byte cycle commitment, got ${params.commitment.length}`);
694
1234
  }
695
- const body = Buffer.concat([
696
- Buffer.from([IX.submitCycle]),
1235
+ return Buffer.concat([
1236
+ Buffer.from([IX.commitCycle]),
697
1237
  encodeU64(params.cycleId),
698
- Buffer.concat(
699
- params.allocationFp.map((value) => {
700
- const out = Buffer.alloc(4);
701
- out.writeUInt32LE(value);
702
- return out;
703
- }),
704
- ),
1238
+ params.commitment,
1239
+ ]);
1240
+ }
1241
+
1242
+ function buildCloseCommitPhaseData(params: { cycleId: number }) {
1243
+ return Buffer.concat([Buffer.from([IX.closeCommitPhase]), encodeU64(params.cycleId)]);
1244
+ }
1245
+
1246
+ function buildSealCycleEntropyData(params: { cycleId: number }) {
1247
+ return Buffer.concat([Buffer.from([IX.sealCycleEntropy]), encodeU64(params.cycleId)]);
1248
+ }
1249
+
1250
+ function buildRevealCycleData(params: { cycleId: number; nonce: Buffer; allocationFp: number[] }) {
1251
+ if (params.nonce.length !== 32) {
1252
+ throw new Error(`expected 32-byte cycle nonce, got ${params.nonce.length}`);
1253
+ }
1254
+ return Buffer.concat([
1255
+ Buffer.from([IX.revealCycle]),
1256
+ encodeU64(params.cycleId),
1257
+ params.nonce,
1258
+ encodeAllocationFp(params.allocationFp),
705
1259
  Buffer.alloc(4),
706
1260
  ]);
707
- satSubmitDebug(
708
- `[sat-submit-build] allocs=${params.allocationFp.length} len=${body.length} cycle=${params.cycleId}`,
709
- );
710
- return body;
1261
+ }
1262
+
1263
+ function buildReleaseUnrevealedCommitData(params: { cycleId: number; minerAuthority: string }) {
1264
+ return Buffer.concat([
1265
+ Buffer.from([IX.releaseUnrevealedCommit]),
1266
+ encodeU64(params.cycleId),
1267
+ encodePubkey(params.minerAuthority),
1268
+ ]);
1269
+ }
1270
+
1271
+ function buildAbortEmptyCycleData(params: { cycleId: number }) {
1272
+ return Buffer.concat([Buffer.from([IX.abortEmptyCycle]), encodeU64(params.cycleId)]);
711
1273
  }
712
1274
 
713
1275
  function buildClaimCycleRewardsData(params: { cycleId: number }) {
@@ -728,17 +1290,6 @@ function buildClaimCycleRewardsBatchData(params: { cycleIds: number[] }) {
728
1290
  ]);
729
1291
  }
730
1292
 
731
- function buildSetProtocolRecipientsData(params: {
732
- treasuryRecipient: string;
733
- distributorRecipient: string;
734
- }) {
735
- return Buffer.concat([
736
- Buffer.from([IX.setProtocolRecipients]),
737
- encodePubkey(params.treasuryRecipient),
738
- encodePubkey(params.distributorRecipient),
739
- ]);
740
- }
741
-
742
1293
  function buildClaimProtocolTreasuryData() {
743
1294
  return Buffer.from([IX.claimProtocolTreasury]);
744
1295
  }
@@ -924,13 +1475,16 @@ export async function submitSatValidatorAttestation(
924
1475
  [Buffer.from(MINING_STAKE_SEED), targetAuthority.toBuffer()],
925
1476
  programId,
926
1477
  );
927
- return [
928
- { pubkey: signer, isSigner: true, isWritable: true },
929
- { pubkey: satEpoch, isSigner: false, isWritable: true },
930
- { pubkey: satValidatorAttestation, isSigner: false, isWritable: true },
931
- { pubkey: miningStake, isSigner: false, isWritable: true },
932
- { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
933
- ];
1478
+ return {
1479
+ keys: [
1480
+ { pubkey: signer, isSigner: true, isWritable: true },
1481
+ { pubkey: satEpoch, isSigner: false, isWritable: true },
1482
+ { pubkey: satValidatorAttestation, isSigner: false, isWritable: true },
1483
+ { pubkey: miningStake, isSigner: false, isWritable: true },
1484
+ { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1485
+ ],
1486
+ context: { targetAuthority: targetAuthority.toBase58() },
1487
+ };
934
1488
  },
935
1489
  });
936
1490
  }
@@ -967,13 +1521,16 @@ export async function submitSatOpenDispute(
967
1521
  [Buffer.from(MINING_STAKE_SEED), targetAuthority.toBuffer()],
968
1522
  programId,
969
1523
  );
970
- return [
971
- { pubkey: signer, isSigner: true, isWritable: true },
972
- { pubkey: satEpoch, isSigner: false, isWritable: true },
973
- { pubkey: satDispute, isSigner: false, isWritable: true },
974
- { pubkey: miningStake, isSigner: false, isWritable: true },
975
- { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
976
- ];
1524
+ return {
1525
+ keys: [
1526
+ { pubkey: signer, isSigner: true, isWritable: true },
1527
+ { pubkey: satEpoch, isSigner: false, isWritable: true },
1528
+ { pubkey: satDispute, isSigner: false, isWritable: true },
1529
+ { pubkey: miningStake, isSigner: false, isWritable: true },
1530
+ { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1531
+ ],
1532
+ context: { targetAuthority: targetAuthority.toBase58() },
1533
+ };
977
1534
  },
978
1535
  });
979
1536
  }
@@ -1009,12 +1566,15 @@ export async function submitSatResolveDispute(
1009
1566
  ],
1010
1567
  programId,
1011
1568
  );
1012
- return [
1013
- { pubkey: signer, isSigner: true, isWritable: true },
1014
- { pubkey: miningPool, isSigner: false, isWritable: false },
1015
- { pubkey: satEpoch, isSigner: false, isWritable: true },
1016
- { pubkey: satDispute, isSigner: false, isWritable: true },
1017
- ];
1569
+ return {
1570
+ keys: [
1571
+ { pubkey: signer, isSigner: true, isWritable: true },
1572
+ { pubkey: miningPool, isSigner: false, isWritable: false },
1573
+ { pubkey: satEpoch, isSigner: false, isWritable: true },
1574
+ { pubkey: satDispute, isSigner: false, isWritable: true },
1575
+ ],
1576
+ context: { disputeAuthority: disputeAuthority.toBase58() },
1577
+ };
1018
1578
  },
1019
1579
  });
1020
1580
  }
@@ -1047,53 +1607,37 @@ export async function submitSatRepublishEpochRoots(
1047
1607
  });
1048
1608
  }
1049
1609
 
1050
- export async function submitSatBootstrap(
1610
+ export async function submitSatTopUpRegistryReserve(
1051
1611
  _config: SatMiningConfig,
1052
- params: { authority?: string; initialStake?: number } = {},
1612
+ params: { targetBalanceLamports: number },
1053
1613
  ) {
1054
1614
  const cfg = loadConfigForSatRuntime(_config);
1615
+ const targetBalanceLamports = Math.max(0, Math.floor(params.targetBalanceLamports));
1616
+ if (!Number.isSafeInteger(targetBalanceLamports)) {
1617
+ throw new Error("registry reserve target must be a safe integer lamport amount");
1618
+ }
1619
+ const profile = resolveSatGenesisProfileContract(_config.network);
1620
+ if (BigInt(targetBalanceLamports) > profile.registryReserveMaxLamports) {
1621
+ throw new Error(
1622
+ `registry reserve target exceeds ${profile.cluster} genesis maximum ${profile.registryReserveMaxLamports}`,
1623
+ );
1624
+ }
1055
1625
  return submitInstruction({
1056
1626
  cfg,
1057
1627
  env: process.env,
1058
- data: buildBootstrapData({
1059
- authority: params.authority ?? "",
1060
- initialStake: Math.max(0, Math.floor(params.initialStake ?? 0)),
1628
+ data: buildTopUpRegistryReserveData({
1629
+ targetBalanceLamports,
1061
1630
  }),
1062
1631
  accountResolver: async (solana, signer) => {
1063
1632
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
1064
- const [satGlobalState] = solana.PublicKey.findProgramAddressSync(
1065
- [Buffer.from(SAT_GLOBAL_STATE_SEED)],
1066
- programId,
1067
- );
1068
- const [treasury] = solana.PublicKey.findProgramAddressSync(
1069
- [Buffer.from("treasury")],
1070
- programId,
1071
- );
1072
- const [satTreasuryState] = solana.PublicKey.findProgramAddressSync(
1073
- [Buffer.from(SAT_TREASURY_STATE_SEED)],
1074
- programId,
1075
- );
1076
1633
  const [satRegistryReserve] = solana.PublicKey.findProgramAddressSync(
1077
1634
  [Buffer.from(SAT_REGISTRY_RESERVE_SEED)],
1078
1635
  programId,
1079
1636
  );
1080
- const [satRebateVault] = solana.PublicKey.findProgramAddressSync(
1081
- [Buffer.from(SAT_REBATE_VAULT_SEED)],
1082
- programId,
1083
- );
1084
- const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync(
1085
- [Buffer.from(SAT_TREASURY_VAULT_SEED)],
1086
- programId,
1087
- );
1088
1637
  return [
1089
1638
  { pubkey: signer, isSigner: true, isWritable: true },
1090
- { pubkey: satGlobalState, isSigner: false, isWritable: true },
1091
- { pubkey: treasury, isSigner: false, isWritable: true },
1092
- { pubkey: satTreasuryState, isSigner: false, isWritable: true },
1093
1639
  { pubkey: satRegistryReserve, isSigner: false, isWritable: true },
1094
1640
  { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1095
- { pubkey: satRebateVault, isSigner: false, isWritable: true },
1096
- { pubkey: satTreasuryVault, isSigner: false, isWritable: true },
1097
1641
  ];
1098
1642
  },
1099
1643
  });
@@ -1150,15 +1694,23 @@ export async function submitSatInitMinerCapital(
1150
1694
  params: { authority?: string },
1151
1695
  ) {
1152
1696
  const cfg = loadConfigForSatRuntime(_config);
1697
+ const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1698
+ const authority =
1699
+ params.authority?.trim() ||
1700
+ (await resolveSatLocalSignerAddress(
1701
+ cfg,
1702
+ effectiveEnv,
1703
+ "local-socket-signer returned no Solana address for SAT miner capital authority",
1704
+ ));
1153
1705
  return submitInstruction({
1154
1706
  cfg,
1155
- env: process.env,
1156
- data: buildInitMinerCapitalData({ authority: params.authority ?? "" }),
1707
+ env: effectiveEnv,
1708
+ data: buildInitMinerCapitalData({ authority }),
1157
1709
  accountResolver: async (solana, signer) => {
1158
1710
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
1159
- const authority = params.authority?.trim() ? new solana.PublicKey(params.authority) : signer;
1711
+ const authorityKey = new solana.PublicKey(authority);
1160
1712
  const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync(
1161
- [Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), authority.toBuffer()],
1713
+ [Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), authorityKey.toBuffer()],
1162
1714
  programId,
1163
1715
  );
1164
1716
  return [
@@ -1281,47 +1833,6 @@ function resolveSatBondAccounts(
1281
1833
  };
1282
1834
  }
1283
1835
 
1284
- export async function submitSatInitBondTierPolicy(
1285
- _config: SatMiningConfig,
1286
- params: {
1287
- updateAuthority?: string;
1288
- basicMinRaw: number;
1289
- operatorMinRaw: number;
1290
- unlockDelaySlots: number;
1291
- scheduledEffectiveSlot?: number;
1292
- },
1293
- ) {
1294
- const cfg = loadConfigForSatRuntime(_config);
1295
- const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1296
- if (!hasDedicatedBondProgram(effectiveEnv)) {
1297
- throw new Error("SAT bond tier policy init requires FASED_SAT_BOND_PROGRAM_ID");
1298
- }
1299
- const defaultUpdateAuthority =
1300
- resolveSatRegistrySolanaAddress(cfg, effectiveEnv) ||
1301
- (await resolveSatLocalSignerAddress(
1302
- cfg,
1303
- effectiveEnv,
1304
- "local-socket-signer returned no Solana address for SAT bond policy authority",
1305
- ));
1306
- return submitInstruction({
1307
- cfg,
1308
- env: effectiveEnv,
1309
- data: buildInitBondTierPolicyData({
1310
- ...params,
1311
- updateAuthority: params.updateAuthority ?? defaultUpdateAuthority,
1312
- }),
1313
- programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1314
- accountResolver: async (solana, signer) => {
1315
- const { bondTierPolicy } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1316
- return [
1317
- { pubkey: signer, isSigner: true, isWritable: true },
1318
- { pubkey: bondTierPolicy, isSigner: false, isWritable: true },
1319
- { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1320
- ];
1321
- },
1322
- });
1323
- }
1324
-
1325
1836
  export async function submitSatUpdateBondTierPolicy(
1326
1837
  _config: SatMiningConfig,
1327
1838
  params: {
@@ -1337,13 +1848,11 @@ export async function submitSatUpdateBondTierPolicy(
1337
1848
  if (!hasDedicatedBondProgram(effectiveEnv)) {
1338
1849
  throw new Error("SAT bond tier policy update requires FASED_SAT_BOND_PROGRAM_ID");
1339
1850
  }
1340
- const defaultUpdateAuthority =
1341
- resolveSatRegistrySolanaAddress(cfg, effectiveEnv) ||
1342
- (await resolveSatLocalSignerAddress(
1343
- cfg,
1344
- effectiveEnv,
1345
- "local-socket-signer returned no Solana address for SAT bond policy authority",
1346
- ));
1851
+ const defaultUpdateAuthority = await resolveSatLocalSignerAddress(
1852
+ cfg,
1853
+ effectiveEnv,
1854
+ "local-socket-signer returned no Solana address for SAT bond policy authority",
1855
+ );
1347
1856
  return submitInstruction({
1348
1857
  cfg,
1349
1858
  env: effectiveEnv,
@@ -1446,12 +1955,17 @@ export async function submitSatRequestBondUnlock(_config: SatMiningConfig) {
1446
1955
  data: buildRequestBondUnlockData(effectiveEnv),
1447
1956
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1448
1957
  accountResolver: async (solana, signer) => {
1449
- const { bondTierPolicy, bondPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1958
+ const { bondTierPolicy, bondPosition, bondStakingDistributor, bondStakingPosition } =
1959
+ resolveSatBondAccounts(solana, signer, effectiveEnv);
1450
1960
  const accounts = [
1451
1961
  { pubkey: signer, isSigner: true, isWritable: true },
1452
1962
  { pubkey: bondTierPolicy, isSigner: false, isWritable: false },
1453
1963
  ];
1454
- accounts.push({ pubkey: bondPosition, isSigner: false, isWritable: true });
1964
+ accounts.push(
1965
+ { pubkey: bondPosition, isSigner: false, isWritable: true },
1966
+ { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
1967
+ { pubkey: bondStakingPosition, isSigner: false, isWritable: true },
1968
+ );
1455
1969
  return accounts;
1456
1970
  },
1457
1971
  });
@@ -1467,12 +1981,17 @@ export async function submitSatCancelBondUnlock(_config: SatMiningConfig) {
1467
1981
  data: buildCancelBondUnlockData(effectiveEnv),
1468
1982
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1469
1983
  accountResolver: async (solana, signer) => {
1470
- const { bondTierPolicy, bondPosition } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1984
+ const { bondTierPolicy, bondPosition, bondStakingDistributor, bondStakingPosition } =
1985
+ resolveSatBondAccounts(solana, signer, effectiveEnv);
1471
1986
  const accounts = [
1472
1987
  { pubkey: signer, isSigner: true, isWritable: true },
1473
1988
  { pubkey: bondTierPolicy, isSigner: false, isWritable: false },
1474
1989
  ];
1475
- accounts.push({ pubkey: bondPosition, isSigner: false, isWritable: true });
1990
+ accounts.push(
1991
+ { pubkey: bondPosition, isSigner: false, isWritable: true },
1992
+ { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
1993
+ { pubkey: bondStakingPosition, isSigner: false, isWritable: true },
1994
+ );
1476
1995
  return accounts;
1477
1996
  },
1478
1997
  });
@@ -1488,14 +2007,23 @@ export async function submitSatFinalizeBondUnlock(_config: SatMiningConfig) {
1488
2007
  data: buildFinalizeBondUnlockData(effectiveEnv),
1489
2008
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1490
2009
  accountResolver: async (solana, signer) => {
1491
- const { bondTierPolicy, bondPosition, signerTokenAccount, bondVault, mint } =
1492
- resolveSatBondAccounts(solana, signer, effectiveEnv);
2010
+ const {
2011
+ bondTierPolicy,
2012
+ bondPosition,
2013
+ bondStakingDistributor,
2014
+ bondStakingPosition,
2015
+ signerTokenAccount,
2016
+ bondVault,
2017
+ mint,
2018
+ } = resolveSatBondAccounts(solana, signer, effectiveEnv);
1493
2019
  const accounts = [
1494
2020
  { pubkey: signer, isSigner: true, isWritable: true },
1495
2021
  { pubkey: bondTierPolicy, isSigner: false, isWritable: false },
1496
2022
  ];
1497
2023
  accounts.push(
1498
2024
  { pubkey: bondPosition, isSigner: false, isWritable: true },
2025
+ { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
2026
+ { pubkey: bondStakingPosition, isSigner: false, isWritable: true },
1499
2027
  { pubkey: bondVault, isSigner: false, isWritable: true },
1500
2028
  { pubkey: signerTokenAccount, isSigner: false, isWritable: true },
1501
2029
  { pubkey: mint, isSigner: false, isWritable: true },
@@ -1512,28 +2040,105 @@ export async function submitSatFinalizeBondUnlock(_config: SatMiningConfig) {
1512
2040
  });
1513
2041
  }
1514
2042
 
1515
- export async function submitSatInitBondStakingDistributor(
2043
+ export async function submitSatSyncBondStakingRewards(_config: SatMiningConfig) {
2044
+ const cfg = loadConfigForSatRuntime(_config);
2045
+ const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
2046
+ assertDedicatedBondProgram(effectiveEnv);
2047
+ return submitInstruction({
2048
+ cfg,
2049
+ env: effectiveEnv,
2050
+ data: buildSyncBondStakingRewardsData(effectiveEnv),
2051
+ programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
2052
+ accountResolver: async (solana, signer) => {
2053
+ const { bondStakingDistributor, bondStakingRewardVault, mint } = resolveSatBondAccounts(
2054
+ solana,
2055
+ signer,
2056
+ effectiveEnv,
2057
+ );
2058
+ return [
2059
+ { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
2060
+ { pubkey: bondStakingRewardVault, isSigner: false, isWritable: false },
2061
+ { pubkey: mint, isSigner: false, isWritable: false },
2062
+ ];
2063
+ },
2064
+ });
2065
+ }
2066
+
2067
+ export async function submitSatSyncBondStakingPosition(_config: SatMiningConfig) {
2068
+ const cfg = loadConfigForSatRuntime(_config);
2069
+ const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
2070
+ assertDedicatedBondProgram(effectiveEnv);
2071
+ return submitInstruction({
2072
+ cfg,
2073
+ env: effectiveEnv,
2074
+ data: buildSyncBondStakingPositionData(effectiveEnv),
2075
+ programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
2076
+ accountResolver: async (solana, signer) => {
2077
+ const { bondTierPolicy, bondStakingDistributor, bondStakingPosition, bondPosition } =
2078
+ resolveSatBondAccounts(solana, signer, effectiveEnv);
2079
+ return [
2080
+ { pubkey: signer, isSigner: true, isWritable: true },
2081
+ { pubkey: bondTierPolicy, isSigner: false, isWritable: false },
2082
+ { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
2083
+ { pubkey: bondStakingPosition, isSigner: false, isWritable: true },
2084
+ { pubkey: bondPosition, isSigner: false, isWritable: false },
2085
+ { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
2086
+ ];
2087
+ },
2088
+ });
2089
+ }
2090
+
2091
+ export async function submitSatClaimBondStakingRewards(_config: SatMiningConfig) {
2092
+ const cfg = loadConfigForSatRuntime(_config);
2093
+ const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
2094
+ assertDedicatedBondProgram(effectiveEnv);
2095
+ return submitInstruction({
2096
+ cfg,
2097
+ env: effectiveEnv,
2098
+ data: buildClaimBondStakingRewardsData(effectiveEnv),
2099
+ programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
2100
+ accountResolver: async (solana, signer) => {
2101
+ const {
2102
+ bondTierPolicy,
2103
+ bondStakingDistributor,
2104
+ bondStakingPosition,
2105
+ bondPosition,
2106
+ bondStakingRewardVault,
2107
+ signerTokenAccount,
2108
+ mint,
2109
+ } = resolveSatBondAccounts(solana, signer, effectiveEnv);
2110
+ return [
2111
+ { pubkey: signer, isSigner: true, isWritable: true },
2112
+ { pubkey: bondTierPolicy, isSigner: false, isWritable: false },
2113
+ { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
2114
+ { pubkey: bondStakingPosition, isSigner: false, isWritable: true },
2115
+ { pubkey: bondPosition, isSigner: false, isWritable: false },
2116
+ { pubkey: bondStakingRewardVault, isSigner: false, isWritable: true },
2117
+ { pubkey: signerTokenAccount, isSigner: false, isWritable: true },
2118
+ { pubkey: mint, isSigner: false, isWritable: true },
2119
+ { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
2120
+ { pubkey: new solana.PublicKey(TOKEN_PROGRAM_ID), isSigner: false, isWritable: false },
2121
+ {
2122
+ pubkey: new solana.PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID),
2123
+ isSigner: false,
2124
+ isWritable: false,
2125
+ },
2126
+ ];
2127
+ },
2128
+ });
2129
+ }
2130
+
2131
+ export async function submitSatClaimUnallocatedStakingRewards(
1516
2132
  _config: SatMiningConfig,
1517
- params: { minStakeRaw: number; updateAuthority?: string },
2133
+ params: { recipientOwner: string },
1518
2134
  ) {
1519
2135
  const cfg = loadConfigForSatRuntime(_config);
1520
2136
  const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1521
2137
  assertDedicatedBondProgram(effectiveEnv);
1522
- const defaultUpdateAuthority = await resolveSatLocalSignerAddress(
1523
- cfg,
1524
- effectiveEnv,
1525
- "local-socket-signer returned no Solana address for SAT bond staking distributor authority",
1526
- );
1527
2138
  return submitInstruction({
1528
2139
  cfg,
1529
2140
  env: effectiveEnv,
1530
- data: buildInitBondStakingDistributorData(
1531
- {
1532
- minStakeRaw: params.minStakeRaw,
1533
- updateAuthority: params.updateAuthority ?? defaultUpdateAuthority,
1534
- },
1535
- effectiveEnv,
1536
- ),
2141
+ data: buildClaimUnallocatedStakingRewardsData(effectiveEnv),
1537
2142
  programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
1538
2143
  accountResolver: async (solana, signer) => {
1539
2144
  const { bondStakingDistributor, bondStakingRewardVault, mint } = resolveSatBondAccounts(
@@ -1541,127 +2146,237 @@ export async function submitSatInitBondStakingDistributor(
1541
2146
  signer,
1542
2147
  effectiveEnv,
1543
2148
  );
2149
+ const recipientOwner = new solana.PublicKey(params.recipientOwner);
2150
+ const recipientTokenAccount = deriveAssociatedTokenAddress(solana, recipientOwner, mint);
1544
2151
  return [
1545
2152
  { pubkey: signer, isSigner: true, isWritable: true },
1546
2153
  { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
1547
2154
  { pubkey: bondStakingRewardVault, isSigner: false, isWritable: true },
2155
+ { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
2156
+ { pubkey: recipientOwner, isSigner: false, isWritable: false },
1548
2157
  { pubkey: mint, isSigner: false, isWritable: true },
1549
2158
  { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1550
- { pubkey: new solana.PublicKey(TOKEN_PROGRAM_ID), isSigner: false, isWritable: false },
1551
- {
1552
- pubkey: new solana.PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID),
1553
- isSigner: false,
1554
- isWritable: false,
1555
- },
2159
+ { pubkey: new solana.PublicKey(TOKEN_PROGRAM_ID), isSigner: false, isWritable: false },
2160
+ {
2161
+ pubkey: new solana.PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID),
2162
+ isSigner: false,
2163
+ isWritable: false,
2164
+ },
2165
+ ];
2166
+ },
2167
+ });
2168
+ }
2169
+
2170
+ export async function submitSatCommitCycle(
2171
+ _config: SatMiningConfig,
2172
+ params: { cycleId: number; commitmentHex: string },
2173
+ ) {
2174
+ const cfg = loadConfigForSatRuntime(_config);
2175
+ const commitment = Buffer.from(params.commitmentHex, "hex");
2176
+ return submitInstruction({
2177
+ cfg,
2178
+ env: process.env,
2179
+ data: buildCommitCycleData({ cycleId: params.cycleId, commitment }),
2180
+ accountResolver: async (solana, signer) => {
2181
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2182
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync(
2183
+ [Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)],
2184
+ programId,
2185
+ );
2186
+ const [satMinerCycleState] = solana.PublicKey.findProgramAddressSync(
2187
+ [Buffer.from(SAT_MINER_CYCLE_STATE_SEED), signer.toBuffer(), encodeU64(params.cycleId)],
2188
+ programId,
2189
+ );
2190
+ const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync(
2191
+ [Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), signer.toBuffer()],
2192
+ programId,
2193
+ );
2194
+ return [
2195
+ { pubkey: signer, isSigner: true, isWritable: true },
2196
+ { pubkey: satCycleState, isSigner: false, isWritable: true },
2197
+ { pubkey: satMinerCycleState, isSigner: false, isWritable: true },
2198
+ { pubkey: satMinerCapitalState, isSigner: false, isWritable: true },
2199
+ { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1556
2200
  ];
1557
2201
  },
1558
2202
  });
1559
2203
  }
1560
2204
 
1561
- export async function submitSatSyncBondStakingRewards(_config: SatMiningConfig) {
2205
+ async function submitSatCyclePhaseInstruction(
2206
+ _config: SatMiningConfig,
2207
+ params: { cycleId: number; phase: "close" | "seal"; intervalStartCycleId?: number },
2208
+ ) {
1562
2209
  const cfg = loadConfigForSatRuntime(_config);
1563
- const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1564
- assertDedicatedBondProgram(effectiveEnv);
1565
2210
  return submitInstruction({
1566
2211
  cfg,
1567
- env: effectiveEnv,
1568
- data: buildSyncBondStakingRewardsData(effectiveEnv),
1569
- programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
2212
+ env: process.env,
2213
+ data:
2214
+ params.phase === "close"
2215
+ ? buildCloseCommitPhaseData(params)
2216
+ : buildSealCycleEntropyData(params),
1570
2217
  accountResolver: async (solana, signer) => {
1571
- const { bondStakingDistributor, bondStakingRewardVault, mint } = resolveSatBondAccounts(
1572
- solana,
1573
- signer,
1574
- effectiveEnv,
2218
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2219
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync(
2220
+ [Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)],
2221
+ programId,
1575
2222
  );
1576
- return [
1577
- { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
1578
- { pubkey: bondStakingRewardVault, isSigner: false, isWritable: false },
1579
- { pubkey: mint, isSigner: false, isWritable: false },
2223
+ const accounts = [
2224
+ { pubkey: signer, isSigner: true, isWritable: false },
2225
+ { pubkey: satCycleState, isSigner: false, isWritable: true },
1580
2226
  ];
2227
+ let intervalStartCycleIdForSigner: number | undefined;
2228
+ if (params.phase === "seal") {
2229
+ const cycle =
2230
+ params.intervalStartCycleId == null
2231
+ ? await inspectSatCycle(_config, { cycleId: params.cycleId })
2232
+ : null;
2233
+ const intervalStartCycleId =
2234
+ params.intervalStartCycleId ?? cycle?.unlockIntervalStartCycleId;
2235
+ if (intervalStartCycleId == null || !Number.isSafeInteger(intervalStartCycleId)) {
2236
+ throw new Error(`SAT cycle ${params.cycleId} does not expose its unlock interval start`);
2237
+ }
2238
+ intervalStartCycleIdForSigner = intervalStartCycleId;
2239
+ const [satUnlockIntervalState] = solana.PublicKey.findProgramAddressSync(
2240
+ [Buffer.from(SAT_UNLOCK_INTERVAL_STATE_SEED), encodeU64(intervalStartCycleId)],
2241
+ programId,
2242
+ );
2243
+ accounts.push({
2244
+ pubkey: satUnlockIntervalState,
2245
+ isSigner: false,
2246
+ isWritable: true,
2247
+ });
2248
+ accounts.push({
2249
+ pubkey: new solana.PublicKey(SLOT_HASHES_SYSVAR_ID),
2250
+ isSigner: false,
2251
+ isWritable: false,
2252
+ });
2253
+ }
2254
+ return {
2255
+ keys: accounts,
2256
+ ...(intervalStartCycleIdForSigner == null
2257
+ ? {}
2258
+ : { context: { intervalStartCycleId: String(intervalStartCycleIdForSigner) } }),
2259
+ };
1581
2260
  },
1582
2261
  });
1583
2262
  }
1584
2263
 
1585
- export async function submitSatSyncBondStakingPosition(_config: SatMiningConfig) {
2264
+ export async function submitSatCloseCommitPhase(
2265
+ _config: SatMiningConfig,
2266
+ params: { cycleId: number },
2267
+ ) {
2268
+ return submitSatCyclePhaseInstruction(_config, { ...params, phase: "close" });
2269
+ }
2270
+
2271
+ export async function submitSatSealCycleEntropy(
2272
+ _config: SatMiningConfig,
2273
+ params: { cycleId: number; intervalStartCycleId?: number },
2274
+ ) {
2275
+ return submitSatCyclePhaseInstruction(_config, { ...params, phase: "seal" });
2276
+ }
2277
+
2278
+ export async function submitSatReleaseUnrevealedCommit(
2279
+ _config: SatMiningConfig,
2280
+ params: { cycleId: number; minerAuthority: string },
2281
+ ) {
1586
2282
  const cfg = loadConfigForSatRuntime(_config);
1587
- const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1588
- assertDedicatedBondProgram(effectiveEnv);
1589
2283
  return submitInstruction({
1590
2284
  cfg,
1591
- env: effectiveEnv,
1592
- data: buildSyncBondStakingPositionData(effectiveEnv),
1593
- programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
2285
+ env: process.env,
2286
+ data: buildReleaseUnrevealedCommitData(params),
1594
2287
  accountResolver: async (solana, signer) => {
1595
- const { bondTierPolicy, bondStakingDistributor, bondStakingPosition, bondPosition } =
1596
- resolveSatBondAccounts(solana, signer, effectiveEnv);
2288
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2289
+ const minerAuthority = new solana.PublicKey(params.minerAuthority);
2290
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync(
2291
+ [Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)],
2292
+ programId,
2293
+ );
2294
+ const [satMinerCycleState] = solana.PublicKey.findProgramAddressSync(
2295
+ [
2296
+ Buffer.from(SAT_MINER_CYCLE_STATE_SEED),
2297
+ minerAuthority.toBuffer(),
2298
+ encodeU64(params.cycleId),
2299
+ ],
2300
+ programId,
2301
+ );
2302
+ const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync(
2303
+ [Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), minerAuthority.toBuffer()],
2304
+ programId,
2305
+ );
2306
+ const [satTreasuryState] = solana.PublicKey.findProgramAddressSync(
2307
+ [Buffer.from(SAT_TREASURY_STATE_SEED)],
2308
+ programId,
2309
+ );
2310
+ const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync(
2311
+ [Buffer.from(SAT_TREASURY_VAULT_SEED)],
2312
+ programId,
2313
+ );
1597
2314
  return [
1598
- { pubkey: signer, isSigner: true, isWritable: true },
1599
- { pubkey: bondTierPolicy, isSigner: false, isWritable: false },
1600
- { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
1601
- { pubkey: bondStakingPosition, isSigner: false, isWritable: true },
1602
- { pubkey: bondPosition, isSigner: false, isWritable: false },
1603
- { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
2315
+ { pubkey: signer, isSigner: true, isWritable: false },
2316
+ { pubkey: satCycleState, isSigner: false, isWritable: true },
2317
+ { pubkey: satMinerCycleState, isSigner: false, isWritable: true },
2318
+ { pubkey: satMinerCapitalState, isSigner: false, isWritable: true },
2319
+ { pubkey: satTreasuryState, isSigner: false, isWritable: true },
2320
+ { pubkey: satTreasuryVault, isSigner: false, isWritable: true },
1604
2321
  ];
1605
2322
  },
1606
2323
  });
1607
2324
  }
1608
2325
 
1609
- export async function submitSatClaimBondStakingRewards(_config: SatMiningConfig) {
2326
+ export async function submitSatAbortEmptyCycle(
2327
+ _config: SatMiningConfig,
2328
+ params: { cycleId: number },
2329
+ ) {
1610
2330
  const cfg = loadConfigForSatRuntime(_config);
1611
- const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
1612
- assertDedicatedBondProgram(effectiveEnv);
1613
2331
  return submitInstruction({
1614
2332
  cfg,
1615
- env: effectiveEnv,
1616
- data: buildClaimBondStakingRewardsData(effectiveEnv),
1617
- programId: resolveSatBondProgramIdFromEnv(effectiveEnv),
2333
+ env: process.env,
2334
+ data: buildAbortEmptyCycleData(params),
1618
2335
  accountResolver: async (solana, signer) => {
1619
- const {
1620
- bondTierPolicy,
1621
- bondStakingDistributor,
1622
- bondStakingPosition,
1623
- bondPosition,
1624
- bondStakingRewardVault,
1625
- signerTokenAccount,
1626
- mint,
1627
- } = resolveSatBondAccounts(solana, signer, effectiveEnv);
2336
+ const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2337
+ const [satCycleState] = solana.PublicKey.findProgramAddressSync(
2338
+ [Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)],
2339
+ programId,
2340
+ );
2341
+ const [satCycleRegistryMeta] = solana.PublicKey.findProgramAddressSync(
2342
+ [Buffer.from(SAT_CYCLE_REGISTRY_META_SEED), encodeU64(params.cycleId)],
2343
+ programId,
2344
+ );
1628
2345
  return [
1629
- { pubkey: signer, isSigner: true, isWritable: true },
1630
- { pubkey: bondTierPolicy, isSigner: false, isWritable: false },
1631
- { pubkey: bondStakingDistributor, isSigner: false, isWritable: true },
1632
- { pubkey: bondStakingPosition, isSigner: false, isWritable: true },
1633
- { pubkey: bondPosition, isSigner: false, isWritable: false },
1634
- { pubkey: bondStakingRewardVault, isSigner: false, isWritable: true },
1635
- { pubkey: signerTokenAccount, isSigner: false, isWritable: true },
1636
- { pubkey: mint, isSigner: false, isWritable: true },
1637
- { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1638
- { pubkey: new solana.PublicKey(TOKEN_PROGRAM_ID), isSigner: false, isWritable: false },
1639
- {
1640
- pubkey: new solana.PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID),
1641
- isSigner: false,
1642
- isWritable: false,
1643
- },
2346
+ { pubkey: signer, isSigner: true, isWritable: false },
2347
+ { pubkey: satCycleState, isSigner: false, isWritable: true },
2348
+ { pubkey: satCycleRegistryMeta, isSigner: false, isWritable: true },
1644
2349
  ];
1645
2350
  },
1646
2351
  });
1647
2352
  }
1648
2353
 
1649
- export async function submitSatCycle(
2354
+ export async function submitSatRevealCycle(
1650
2355
  _config: SatMiningConfig,
1651
- params: { cycleId: number; allocationFp: number[] },
2356
+ params: {
2357
+ cycleId: number;
2358
+ intervalStartCycleId?: number;
2359
+ nonceBase64: string;
2360
+ allocationFp: number[];
2361
+ },
1652
2362
  ) {
1653
2363
  const cfg = loadConfigForSatRuntime(_config);
2364
+ const nonce = Buffer.from(params.nonceBase64, "base64");
1654
2365
  return submitInstruction({
1655
2366
  cfg,
1656
2367
  env: process.env,
1657
- data: buildSubmitCycleData(params),
2368
+ data: buildRevealCycleData({ ...params, nonce }),
1658
2369
  accountResolver: async (solana, signer) => {
1659
2370
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
1660
2371
  const pageIndex = await resolveSatCycleRegistryPageIndex(_config, params.cycleId);
1661
- const [satGlobalState] = solana.PublicKey.findProgramAddressSync(
1662
- [Buffer.from(SAT_GLOBAL_STATE_SEED)],
1663
- programId,
1664
- );
2372
+ const cycle =
2373
+ params.intervalStartCycleId == null
2374
+ ? await inspectSatCycle(_config, { cycleId: params.cycleId })
2375
+ : null;
2376
+ const intervalStartCycleId = params.intervalStartCycleId ?? cycle?.unlockIntervalStartCycleId;
2377
+ if (intervalStartCycleId == null || !Number.isSafeInteger(intervalStartCycleId)) {
2378
+ throw new Error(`SAT cycle ${params.cycleId} does not expose its unlock interval start`);
2379
+ }
1665
2380
  const [satCycleState] = solana.PublicKey.findProgramAddressSync(
1666
2381
  [Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)],
1667
2382
  programId,
@@ -1690,37 +2405,32 @@ export async function submitSatCycle(
1690
2405
  [Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), signer.toBuffer()],
1691
2406
  programId,
1692
2407
  );
1693
- const [satRegistryReserve] = solana.PublicKey.findProgramAddressSync(
1694
- [Buffer.from(SAT_REGISTRY_RESERVE_SEED)],
1695
- programId,
1696
- );
1697
- const [satTreasuryState] = solana.PublicKey.findProgramAddressSync(
1698
- [Buffer.from(SAT_TREASURY_STATE_SEED)],
1699
- programId,
1700
- );
1701
- const [satRebateVault] = solana.PublicKey.findProgramAddressSync(
1702
- [Buffer.from(SAT_REBATE_VAULT_SEED)],
2408
+ const [satUnlockIntervalState] = solana.PublicKey.findProgramAddressSync(
2409
+ [Buffer.from(SAT_UNLOCK_INTERVAL_STATE_SEED), encodeU64(intervalStartCycleId)],
1703
2410
  programId,
1704
2411
  );
1705
- const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync(
1706
- [Buffer.from(SAT_TREASURY_VAULT_SEED)],
2412
+ const [satRegistryReserve] = solana.PublicKey.findProgramAddressSync(
2413
+ [Buffer.from(SAT_REGISTRY_RESERVE_SEED)],
1707
2414
  programId,
1708
2415
  );
1709
- return [
1710
- { pubkey: signer, isSigner: true, isWritable: true },
1711
- { pubkey: satGlobalState, isSigner: false, isWritable: true },
1712
- { pubkey: satCycleState, isSigner: false, isWritable: true },
1713
- { pubkey: satCycleRegistryMeta, isSigner: false, isWritable: true },
1714
- { pubkey: satCycleRegistryPage, isSigner: false, isWritable: true },
1715
- { pubkey: satCycleSettlementProgress, isSigner: false, isWritable: true },
1716
- { pubkey: satMinerCycleState, isSigner: false, isWritable: true },
1717
- { pubkey: satMinerCapitalState, isSigner: false, isWritable: true },
1718
- { pubkey: satRegistryReserve, isSigner: false, isWritable: true },
1719
- { pubkey: satTreasuryState, isSigner: false, isWritable: true },
1720
- { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
1721
- { pubkey: satRebateVault, isSigner: false, isWritable: true },
1722
- { pubkey: satTreasuryVault, isSigner: false, isWritable: true },
1723
- ];
2416
+ return {
2417
+ keys: [
2418
+ { pubkey: signer, isSigner: true, isWritable: true },
2419
+ { pubkey: satCycleState, isSigner: false, isWritable: true },
2420
+ { pubkey: satCycleRegistryMeta, isSigner: false, isWritable: true },
2421
+ { pubkey: satCycleRegistryPage, isSigner: false, isWritable: true },
2422
+ { pubkey: satCycleSettlementProgress, isSigner: false, isWritable: true },
2423
+ { pubkey: satMinerCycleState, isSigner: false, isWritable: true },
2424
+ { pubkey: satMinerCapitalState, isSigner: false, isWritable: true },
2425
+ { pubkey: satUnlockIntervalState, isSigner: false, isWritable: true },
2426
+ { pubkey: satRegistryReserve, isSigner: false, isWritable: true },
2427
+ { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
2428
+ ],
2429
+ context: {
2430
+ intervalStartCycleId: String(intervalStartCycleId),
2431
+ registryPageIndex: String(pageIndex),
2432
+ },
2433
+ };
1724
2434
  },
1725
2435
  });
1726
2436
  }
@@ -1801,7 +2511,29 @@ export async function submitSatSettleCyclePage(
1801
2511
  isWritable: true,
1802
2512
  });
1803
2513
  }
1804
- return accounts;
2514
+ const minerCycleAddresses = params.minerCycleAccounts ?? [];
2515
+ const minerCycles =
2516
+ minerCycleAddresses.length > 0
2517
+ ? await inspectSatMinerCyclesByAddress(_config, {
2518
+ addresses: minerCycleAddresses,
2519
+ })
2520
+ : [];
2521
+ const minerAuthorities = minerCycles.map((entry, index) => {
2522
+ const authority = String(entry?.authority ?? "").trim();
2523
+ if (!authority) {
2524
+ throw new Error(
2525
+ `SAT settleCyclePage could not resolve miner authority for ${minerCycleAddresses[index]}`,
2526
+ );
2527
+ }
2528
+ return authority;
2529
+ });
2530
+ if (minerAuthorities.length !== minerCycleAddresses.length) {
2531
+ throw new Error("SAT settleCyclePage miner authority count mismatch");
2532
+ }
2533
+ return {
2534
+ keys: accounts,
2535
+ ...(minerAuthorities.length > 0 ? { context: { minerAuthorities } } : {}),
2536
+ };
1805
2537
  },
1806
2538
  });
1807
2539
  }
@@ -1941,7 +2673,29 @@ export async function submitSatScoreCyclePage(
1941
2673
  isWritable: true,
1942
2674
  });
1943
2675
  }
1944
- return accounts;
2676
+ const minerCycleAddresses = params.minerCycleAccounts ?? [];
2677
+ const minerCycles =
2678
+ minerCycleAddresses.length > 0
2679
+ ? await inspectSatMinerCyclesByAddress(_config, {
2680
+ addresses: minerCycleAddresses,
2681
+ })
2682
+ : [];
2683
+ const minerAuthorities = minerCycles.map((entry, index) => {
2684
+ const authority = String(entry?.authority ?? "").trim();
2685
+ if (!authority) {
2686
+ throw new Error(
2687
+ `SAT scoreCyclePage could not resolve miner authority for ${minerCycleAddresses[index]}`,
2688
+ );
2689
+ }
2690
+ return authority;
2691
+ });
2692
+ if (minerAuthorities.length !== minerCycleAddresses.length) {
2693
+ throw new Error("SAT scoreCyclePage miner authority count mismatch");
2694
+ }
2695
+ return {
2696
+ keys: accounts,
2697
+ ...(minerAuthorities.length > 0 ? { context: { minerAuthorities } } : {}),
2698
+ };
1945
2699
  },
1946
2700
  });
1947
2701
  }
@@ -1993,16 +2747,21 @@ export async function submitSatDistributeCyclePage(
1993
2747
  [Buffer.from(SAT_REBATE_VAULT_SEED)],
1994
2748
  programId,
1995
2749
  );
2750
+ const [satTreasuryVault] = solana.PublicKey.findProgramAddressSync(
2751
+ [Buffer.from(SAT_TREASURY_VAULT_SEED)],
2752
+ programId,
2753
+ );
1996
2754
  const accounts = [
1997
2755
  { pubkey: signer, isSigner: true, isWritable: true },
1998
2756
  { pubkey: satCycleState, isSigner: false, isWritable: true },
1999
2757
  { pubkey: satCycleRegistryPage, isSigner: false, isWritable: false },
2000
2758
  { pubkey: satCycleSettlementProgress, isSigner: false, isWritable: true },
2001
- { pubkey: satGlobalState, isSigner: false, isWritable: true },
2759
+ { pubkey: satGlobalState, isSigner: false, isWritable: false },
2002
2760
  { pubkey: satTreasuryState, isSigner: false, isWritable: true },
2003
2761
  { pubkey: satSignerMinerCycleState, isSigner: false, isWritable: false },
2004
2762
  { pubkey: satSignerMinerCapitalState, isSigner: false, isWritable: true },
2005
2763
  { pubkey: satRebateVault, isSigner: false, isWritable: true },
2764
+ { pubkey: satTreasuryVault, isSigner: false, isWritable: true },
2006
2765
  ];
2007
2766
  const minerCycleAccounts = params.minerCycleAccounts ?? [];
2008
2767
  const minerCycles =
@@ -2011,6 +2770,7 @@ export async function submitSatDistributeCyclePage(
2011
2770
  addresses: minerCycleAccounts,
2012
2771
  }).catch(() => [])
2013
2772
  : [];
2773
+ const minerAuthorities: string[] = [];
2014
2774
  for (const [index, minerCycleAccount] of minerCycleAccounts.entries()) {
2015
2775
  const satMinerCycleState = new solana.PublicKey(minerCycleAccount);
2016
2776
  const minerCycle = minerCycles[index] ?? null;
@@ -2022,6 +2782,7 @@ export async function submitSatDistributeCyclePage(
2022
2782
  `SAT distributeCyclePage could not resolve miner authority for ${minerCycleAccount}`,
2023
2783
  );
2024
2784
  }
2785
+ minerAuthorities.push(authorityKey.toBase58());
2025
2786
  const [satMinerCapitalState] = solana.PublicKey.findProgramAddressSync(
2026
2787
  [Buffer.from(SAT_MINER_CAPITAL_STATE_SEED), authorityKey.toBuffer()],
2027
2788
  programId,
@@ -2029,7 +2790,10 @@ export async function submitSatDistributeCyclePage(
2029
2790
  accounts.push({ pubkey: satMinerCycleState, isSigner: false, isWritable: true });
2030
2791
  accounts.push({ pubkey: satMinerCapitalState, isSigner: false, isWritable: true });
2031
2792
  }
2032
- return accounts;
2793
+ return {
2794
+ keys: accounts,
2795
+ ...(minerAuthorities.length > 0 ? { context: { minerAuthorities } } : {}),
2796
+ };
2033
2797
  },
2034
2798
  });
2035
2799
  }
@@ -2188,29 +2952,6 @@ export async function submitSatClaimCycleRewardsBatch(
2188
2952
  });
2189
2953
  }
2190
2954
 
2191
- export async function submitSatSetProtocolRecipients(
2192
- _config: SatMiningConfig,
2193
- params: { treasuryRecipient: string; distributorRecipient: string },
2194
- ) {
2195
- const cfg = loadConfigForSatRuntime(_config);
2196
- return submitInstruction({
2197
- cfg,
2198
- env: process.env,
2199
- data: buildSetProtocolRecipientsData(params),
2200
- accountResolver: async (solana, signer) => {
2201
- const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2202
- const [satGlobalState] = solana.PublicKey.findProgramAddressSync(
2203
- [Buffer.from(SAT_GLOBAL_STATE_SEED)],
2204
- programId,
2205
- );
2206
- return [
2207
- { pubkey: signer, isSigner: true, isWritable: true },
2208
- { pubkey: satGlobalState, isSigner: false, isWritable: true },
2209
- ];
2210
- },
2211
- });
2212
- }
2213
-
2214
2955
  export async function submitSatClaimProtocolTreasury(
2215
2956
  _config: SatMiningConfig,
2216
2957
  params: { recipientOwner: string },
@@ -2320,12 +3061,14 @@ export async function submitSatClaimProtocolDistributorSat(
2320
3061
  params: { recipientOwner: string },
2321
3062
  ) {
2322
3063
  const cfg = loadConfigForSatRuntime(_config);
3064
+ const effectiveEnv = resolveSatEffectiveEnv(cfg, process.env);
3065
+ assertDedicatedBondProgram(effectiveEnv);
2323
3066
  return submitInstruction({
2324
3067
  cfg,
2325
- env: process.env,
3068
+ env: effectiveEnv,
2326
3069
  data: buildClaimProtocolDistributorSatData(),
2327
3070
  accountResolver: async (solana, signer) => {
2328
- const programId = new solana.PublicKey(SAT_PROGRAM_ID());
3071
+ const programId = new solana.PublicKey(resolveSatProgramIdFromEnv(effectiveEnv));
2329
3072
  const recipientOwner = new solana.PublicKey(params.recipientOwner);
2330
3073
  const [satGlobalState] = solana.PublicKey.findProgramAddressSync(
2331
3074
  [Buffer.from(SAT_GLOBAL_STATE_SEED)],
@@ -2341,12 +3084,12 @@ export async function submitSatClaimProtocolDistributorSat(
2341
3084
  );
2342
3085
  const [mintAuthority] = solana.PublicKey.findProgramAddressSync(
2343
3086
  [Buffer.from("authority")],
2344
- new solana.PublicKey(SAT_MINT_PROGRAM_ID()),
3087
+ new solana.PublicKey(resolveSatMintProgramIdFromEnv(effectiveEnv)),
2345
3088
  );
2346
3089
  const recipientAta = deriveAssociatedTokenAddress(
2347
3090
  solana,
2348
3091
  recipientOwner,
2349
- new solana.PublicKey(SAT_MINT_ADDRESS()),
3092
+ new solana.PublicKey(resolveSatMintAddressFromEnv(effectiveEnv)),
2350
3093
  );
2351
3094
  return [
2352
3095
  { pubkey: signer, isSigner: true, isWritable: true },
@@ -2355,7 +3098,11 @@ export async function submitSatClaimProtocolDistributorSat(
2355
3098
  { pubkey: satTreasuryState, isSigner: false, isWritable: true },
2356
3099
  { pubkey: recipientOwner, isSigner: false, isWritable: true },
2357
3100
  { pubkey: mintAuthority, isSigner: false, isWritable: true },
2358
- { pubkey: new solana.PublicKey(SAT_MINT_ADDRESS()), isSigner: false, isWritable: true },
3101
+ {
3102
+ pubkey: new solana.PublicKey(resolveSatMintAddressFromEnv(effectiveEnv)),
3103
+ isSigner: false,
3104
+ isWritable: true,
3105
+ },
2359
3106
  { pubkey: recipientAta, isSigner: false, isWritable: true },
2360
3107
  { pubkey: solana.SystemProgram.programId, isSigner: false, isWritable: false },
2361
3108
  { pubkey: new solana.PublicKey(TOKEN_PROGRAM_ID), isSigner: false, isWritable: false },
@@ -2364,7 +3111,16 @@ export async function submitSatClaimProtocolDistributorSat(
2364
3111
  isSigner: false,
2365
3112
  isWritable: false,
2366
3113
  },
2367
- { pubkey: new solana.PublicKey(SAT_MINT_PROGRAM_ID()), isSigner: false, isWritable: false },
3114
+ {
3115
+ pubkey: new solana.PublicKey(resolveSatMintProgramIdFromEnv(effectiveEnv)),
3116
+ isSigner: false,
3117
+ isWritable: false,
3118
+ },
3119
+ {
3120
+ pubkey: new solana.PublicKey(resolveSatBondProgramIdFromEnv(effectiveEnv)),
3121
+ isSigner: false,
3122
+ isWritable: false,
3123
+ },
2368
3124
  ];
2369
3125
  },
2370
3126
  });
@@ -2389,10 +3145,19 @@ export async function submitSatRetargetUnlock(
2389
3145
  [Buffer.from(SAT_CYCLE_STATE_SEED), encodeU64(params.cycleId)],
2390
3146
  programId,
2391
3147
  );
3148
+ const intervalStartCycleId = Math.max(
3149
+ 0,
3150
+ params.cycleId + 1 - SAT_PROTOCOL_CONSTANTS.cycleUnlockRetargetIntervalCycles,
3151
+ );
3152
+ const [satUnlockIntervalState] = solana.PublicKey.findProgramAddressSync(
3153
+ [Buffer.from(SAT_UNLOCK_INTERVAL_STATE_SEED), encodeU64(intervalStartCycleId)],
3154
+ programId,
3155
+ );
2392
3156
  return [
2393
3157
  { pubkey: signer, isSigner: true, isWritable: true },
2394
3158
  { pubkey: satGlobalState, isSigner: false, isWritable: true },
2395
3159
  { pubkey: satCycleState, isSigner: false, isWritable: false },
3160
+ { pubkey: satUnlockIntervalState, isSigner: false, isWritable: true },
2396
3161
  ];
2397
3162
  },
2398
3163
  });
@@ -2624,7 +3389,13 @@ export async function submitSatCompactPendingCycleRange(
2624
3389
  isWritable: false,
2625
3390
  });
2626
3391
  }
2627
- return accounts;
3392
+ return {
3393
+ keys: accounts,
3394
+ context: {
3395
+ frontCycleIds: params.frontCycleIds.map(String),
3396
+ backCycleIds: params.backCycleIds.map(String),
3397
+ },
3398
+ };
2628
3399
  },
2629
3400
  });
2630
3401
  }