@fased/fased 0.1.62 → 0.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +44 -29
  3. package/config/dependency-ownership.json +1 -1
  4. package/config/signer-policies/README.md +58 -0
  5. package/config/signer-policies/agent.json.template +32 -0
  6. package/config/signer-policies/mining.json.template +69 -0
  7. package/config/signer-policies/network.json.template +5 -0
  8. package/config/signer-policies/vault.json.template +70 -0
  9. package/config/signer-protocol-v2.json +78 -0
  10. package/config/typescript-noemit-baseline.json +680 -0
  11. package/dist/agents/auth-profiles/store.js +267 -31
  12. package/dist/agents/bash-tools.exec.js +10 -4
  13. package/dist/agents/current-model-catalog.js +3 -3
  14. package/dist/agents/memory-search.js +7 -1
  15. package/dist/agents/model-catalog-access.js +1 -2
  16. package/dist/agents/model-catalog-snapshot.js +1 -1
  17. package/dist/agents/model-catalog-source.js +1 -1
  18. package/dist/agents/model-metadata.js +1 -1
  19. package/dist/agents/model-selection.js +2 -28
  20. package/dist/agents/models-config.providers.js +6 -6
  21. package/dist/agents/pi-embedded-runner/compact.js +15 -7
  22. package/dist/agents/pi-embedded-runner/model.js +1 -1
  23. package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
  24. package/dist/agents/pi-embedded-runner/run.js +2 -0
  25. package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
  26. package/dist/agents/pi-tool-definition-adapter.js +16 -1
  27. package/dist/agents/pi-tools.js +2 -1
  28. package/dist/agents/sandbox/config.js +1 -1
  29. package/dist/agents/sandbox/context.js +27 -2
  30. package/dist/agents/skills/env-overrides.js +38 -28
  31. package/dist/agents/skills/trust.js +93 -0
  32. package/dist/agents/skills/workspace.js +128 -0
  33. package/dist/agents/skills-clawhub.js +36 -11
  34. package/dist/agents/skills-marketplace-scan.js +49 -0
  35. package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
  36. package/dist/agents/tools/mining-tool.js +1 -1
  37. package/dist/agents/tools/session-status-tool.js +1 -1
  38. package/dist/agents/tools/wallet-action-tool.js +172 -36
  39. package/dist/agents/tools/wallet-skill-policy.js +65 -23
  40. package/dist/agents/tools/wallet-tool.js +7 -11
  41. package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
  42. package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
  43. package/dist/auto-reply/reply/directive-handling.model.js +2 -1
  44. package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
  45. package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
  46. package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
  47. package/dist/auto-reply/reply/model-selection.js +7 -4
  48. package/dist/auto-reply/reply/session-reset-model.js +4 -4
  49. package/dist/brand.js +1 -1
  50. package/dist/build-info.json +3 -3
  51. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  52. package/dist/channel-web.js +2 -2
  53. package/dist/cli/gateway-cli/run.js +8 -0
  54. package/dist/cli/program/command-registry.js +1 -1
  55. package/dist/cli/program/register.onboard.js +2 -3
  56. package/dist/cli/program/register.wallet.js +16 -123
  57. package/dist/cli/providers-cli.js +1 -1
  58. package/dist/cli/sat-cli.js +129 -2
  59. package/dist/cli/update-cli/update-command.js +260 -11
  60. package/dist/commands/auth-choice.apply.api-providers.js +3 -3
  61. package/dist/commands/doctor-config-flow.js +1 -1
  62. package/dist/commands/doctor-legacy-config.js +2 -13
  63. package/dist/commands/model-picker.js +6 -6
  64. package/dist/commands/models/auth.js +1 -1
  65. package/dist/commands/onboard-auth.config-gateways.js +1 -1
  66. package/dist/commands/onboard-auth.credentials.js +32 -8
  67. package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
  68. package/dist/commands/onboard-non-interactive/local.js +5 -1
  69. package/dist/commands/wallet.js +568 -1911
  70. package/dist/config/config.js +2 -2
  71. package/dist/config/io.js +64 -2
  72. package/dist/config/schema.help.js +8 -7
  73. package/dist/config/schema.labels.js +5 -4
  74. package/dist/config/zod-schema.agent-runtime.js +1 -0
  75. package/dist/config/zod-schema.js +5 -0
  76. package/dist/control-ui/assets/{app-DLil9VO1.js → app-MaQnPa5G.js} +1511 -1555
  77. package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
  78. package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
  79. package/dist/control-ui/assets/{index-DdE_NIXo.js → index-D4YMr1fA.js} +3 -3
  80. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  81. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-qMYs4aD-.js} +70 -50
  82. package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
  83. package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
  84. package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
  85. package/dist/control-ui/index.html +1 -1
  86. package/dist/control-ui/version.json +1 -1
  87. package/dist/daemon/systemd-system.js +56 -50
  88. package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
  89. package/dist/extensions/sat-mining/src/rpc-read.js +291 -84
  90. package/dist/extensions/sat-mining/src/sat-bond-layout.js +5 -2
  91. package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
  92. package/dist/extensions/sat-mining/src/solana-submit.js +1274 -390
  93. package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
  94. package/dist/federation/auto-connect.js +98 -8
  95. package/dist/federation/marketplace-capability-adapter.js +33 -7
  96. package/dist/federation/marketplace-delivery-outbox.js +196 -0
  97. package/dist/federation/marketplace-delivery.js +351 -215
  98. package/dist/federation/marketplace-direct-payment.js +272 -141
  99. package/dist/federation/marketplace-escrow.js +607 -249
  100. package/dist/federation/marketplace-settlement-ledger.js +352 -0
  101. package/dist/federation/offers.js +9 -7
  102. package/dist/federation/peer-auth-v2.js +529 -0
  103. package/dist/gateway/a2a-http.js +425 -96
  104. package/dist/gateway/a2a-settlement.js +259 -153
  105. package/dist/gateway/a2a-task-store.js +524 -0
  106. package/dist/gateway/auth.js +38 -2
  107. package/dist/gateway/config-reload.js +46 -33
  108. package/dist/gateway/durable-capacity.js +31 -0
  109. package/dist/gateway/federation-http.js +540 -135
  110. package/dist/gateway/federation-marketplace-run-store.js +397 -0
  111. package/dist/gateway/federation-marketplace.js +535 -230
  112. package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
  113. package/dist/gateway/security-path.js +1 -1
  114. package/dist/gateway/server-http.js +1084 -1205
  115. package/dist/gateway/server-methods/models.js +1 -1
  116. package/dist/gateway/server-methods/secrets.js +40 -0
  117. package/dist/gateway/server-methods.js +1 -2
  118. package/dist/gateway/server-reload-handlers.js +196 -66
  119. package/dist/gateway/server-runtime-config.js +1 -1
  120. package/dist/gateway/server-secrets-runtime.js +288 -0
  121. package/dist/gateway/server.impl.js +73 -42
  122. package/dist/gateway/sessions-patch.js +3 -5
  123. package/dist/index.js +4 -2
  124. package/dist/infra/fasedhub.js +64 -1
  125. package/dist/infra/local-source-paired-update.js +538 -0
  126. package/dist/infra/restart.js +41 -10
  127. package/dist/infra/update-runner.js +96 -0
  128. package/dist/light-update-status.js +11 -11
  129. package/dist/memory/backend-config.js +2 -1
  130. package/dist/memory/session-files.js +16 -2
  131. package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
  132. package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
  133. package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
  134. package/dist/plugin-sdk/{audio-preflight-Bwi2Oq03.js → audio-preflight-I4IngVlJ.js} +27 -27
  135. package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
  136. package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
  137. package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
  138. package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
  139. package/dist/plugin-sdk/channel-plugin-common.js +4 -4
  140. package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
  141. package/dist/plugin-sdk/{chunk-items-DzT4L4Ty.js → chunk-items-DLQ6_lLK.js} +1 -1
  142. package/dist/plugin-sdk/command-status.d.ts +2 -2
  143. package/dist/plugin-sdk/command-status.js +27 -27
  144. package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
  145. package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
  146. package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
  147. package/dist/plugin-sdk/{config-schema-BrkmtFxB.js → config-schema-D_8FVI1C.js} +6798 -3695
  148. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  149. package/dist/plugin-sdk/discord.d.ts +6 -6
  150. package/dist/plugin-sdk/discord.js +19 -19
  151. package/dist/plugin-sdk/file-lock.js +35 -4
  152. package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
  153. package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
  154. package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
  155. package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
  156. package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
  157. package/dist/plugin-sdk/index.d.ts +21 -39
  158. package/dist/plugin-sdk/index.js +29 -29
  159. package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
  160. package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
  161. package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
  162. package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
  163. package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
  164. package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
  165. package/dist/plugin-sdk/{monitor-M_ta2lMc.js → monitor-B4KF4Kpo.js} +31 -31
  166. package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-Bb6x1KAG.js} +32 -32
  167. package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DCTO8JkL.js} +27 -27
  168. package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
  169. package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
  170. package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
  171. package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  172. package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-DHPDFZbC.d.ts} +2 -2
  173. package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
  174. package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
  175. package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
  176. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
  177. package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
  178. package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
  179. package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
  180. package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
  181. package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
  182. package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
  183. package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
  184. package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
  185. package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
  186. package/dist/plugin-sdk/sat-runtime.d.ts +565 -309
  187. package/dist/plugin-sdk/sat-runtime.js +29 -29
  188. package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
  189. package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
  190. package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
  191. package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
  192. package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
  193. package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
  194. package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
  195. package/dist/plugin-sdk/{slack-CxE1mfzj.js → slack-BHmvqgjH.js} +39 -39
  196. package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
  197. package/dist/plugin-sdk/slack.d.ts +6 -6
  198. package/dist/plugin-sdk/slack.js +9 -9
  199. package/dist/plugin-sdk/{sticker-cache-CGzGWu00.js → sticker-cache-By5AcorL.js} +3 -3
  200. package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
  201. package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
  202. package/dist/plugin-sdk/{telegram-actions-DaEcYQ8r.js → telegram-actions-DGnBz1YT.js} +30 -30
  203. package/dist/plugin-sdk/telegram.d.ts +6 -6
  204. package/dist/plugin-sdk/telegram.js +8 -8
  205. package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
  206. package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
  207. package/dist/plugin-sdk/tmp-fased-dir-EJGTmL1Q.d.ts +486 -0
  208. package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-BdwdFCD6.d.ts} +2 -3
  209. package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-BrCpYMxn.d.ts} +2 -2
  210. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
  211. package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
  212. package/dist/plugin-sdk/{web-CInY-lCv.js → web-DUJwrTYs.js} +32 -32
  213. package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
  214. package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
  215. package/dist/plugin-sdk/whatsapp.d.ts +13 -13
  216. package/dist/plugin-sdk/whatsapp.js +12 -12
  217. package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
  218. package/dist/plugin-sdk/{zod-schema.providers-core-BEbNizPe.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
  219. package/dist/providers/refresh.js +1 -1
  220. package/dist/providers/registry.js +1 -1
  221. package/dist/secrets/apply.js +1 -1
  222. package/dist/secrets/runtime.js +1 -1
  223. package/dist/wallet/external-submission-ledger.js +376 -0
  224. package/dist/wallet/legacy-embedded-keystore.js +40 -0
  225. package/dist/wallet/local-socket-signer-archive.js +30 -0
  226. package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
  227. package/dist/wallet/local-socket-signer-policy.js +166 -0
  228. package/dist/wallet/local-socket-signer-protocol.js +578 -117
  229. package/dist/wallet/native-signer-wallet-id.js +25 -0
  230. package/dist/wallet/providers/alchemy-adapter.js +3 -0
  231. package/dist/wallet/providers/local-socket-signer-adapter.js +380 -105
  232. package/dist/wallet/providers/turnkey-adapter.js +292 -34
  233. package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
  234. package/dist/wallet/signer-network-admin.js +184 -0
  235. package/dist/wallet/signer-protocol-v2.generated.js +92 -0
  236. package/dist/wallet/solana-bond-signing.js +157 -69
  237. package/dist/wallet/solana-reviewed-transaction.js +375 -0
  238. package/dist/wallet/solana-swap.js +520 -64
  239. package/dist/wallet/solana-transaction-inspection.js +106 -4
  240. package/dist/wallet/solana-trigger.js +658 -320
  241. package/dist/wallet/turnkey-reviewed-state.js +370 -0
  242. package/dist/wallet/wallet-approval-auth.js +17 -28
  243. package/dist/wallet/wallet-atomic-state.js +53 -0
  244. package/dist/wallet/wallet-canary.js +0 -1
  245. package/dist/wallet/wallet-inbound-events.js +16 -11
  246. package/dist/wallet/wallet-policy-simulation.js +1 -1
  247. package/dist/wallet/wallet-policy.js +93 -37
  248. package/dist/wallet/wallet-provider-capabilities.js +28 -4
  249. package/dist/wallet/wallet-provider-registry.js +57 -44
  250. package/dist/wallet/wallet-provider-resolver.js +62 -63
  251. package/dist/wallet/wallet-runtime-config.js +28 -41
  252. package/dist/wallet/wallet-secrets-store.js +22 -0
  253. package/dist/wallet/wallet-send-approvals.js +1891 -589
  254. package/dist/wallet/wallet-send-execution-ledger.js +292 -0
  255. package/dist/wallet/wallet-settlement-links.js +14 -13
  256. package/dist/wallet/wallet-standard-review.js +353 -0
  257. package/dist/wallet/wallet-status.js +0 -9
  258. package/dist/wallet/wallet-task-ledger.js +16 -2
  259. package/dist/web/auto-reply/heartbeat-runner.js +1 -1
  260. package/dist/web/auto-reply/monitor.js +2 -2
  261. package/dist/wizard/host-security-capability.js +14 -23
  262. package/dist/wizard/onboarding.finalize.js +63 -184
  263. package/dist/wizard/onboarding.host-security.js +117 -1367
  264. package/dist/wizard/onboarding.js +172 -217
  265. package/dist/wizard/onboarding.wallet.js +232 -785
  266. package/extensions/acpx/package.json +1 -1
  267. package/extensions/bluebubbles/package.json +1 -1
  268. package/extensions/copilot-proxy/package.json +1 -1
  269. package/extensions/diagnostics-otel/package.json +1 -1
  270. package/extensions/fased-federation/package.json +1 -1
  271. package/extensions/google-gemini-cli-auth/package.json +1 -1
  272. package/extensions/imessage/package.json +1 -1
  273. package/extensions/irc/package.json +1 -1
  274. package/extensions/line/package.json +1 -1
  275. package/extensions/llm-task/package.json +1 -1
  276. package/extensions/lobster/package.json +1 -1
  277. package/extensions/matrix/CHANGELOG.md +18 -0
  278. package/extensions/matrix/package.json +1 -1
  279. package/extensions/mattermost/package.json +1 -1
  280. package/extensions/memory-core/package.json +2 -2
  281. package/extensions/memory-lancedb/package.json +1 -1
  282. package/extensions/minimax-portal-auth/package.json +1 -1
  283. package/extensions/msteams/CHANGELOG.md +18 -0
  284. package/extensions/msteams/package.json +1 -1
  285. package/extensions/nextcloud-talk/package.json +1 -1
  286. package/extensions/nostr/CHANGELOG.md +18 -0
  287. package/extensions/nostr/package.json +1 -1
  288. package/extensions/open-prose/package.json +1 -1
  289. package/extensions/sat-mining/index.ts +587 -154
  290. package/extensions/sat-mining/package.json +1 -1
  291. package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
  292. package/extensions/sat-mining/src/audit-store.ts +91 -5
  293. package/extensions/sat-mining/src/claim-service.ts +85 -14
  294. package/extensions/sat-mining/src/client.ts +13 -0
  295. package/extensions/sat-mining/src/config.ts +9 -0
  296. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  297. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  298. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  299. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  300. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  301. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  302. package/extensions/sat-mining/src/rpc-read.ts +431 -106
  303. package/extensions/sat-mining/src/runtime.ts +16 -0
  304. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  305. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  306. package/extensions/sat-mining/src/solana-submit.ts +1544 -436
  307. package/extensions/sat-mining/src/submission-ledger.ts +434 -0
  308. package/extensions/signal/package.json +1 -1
  309. package/extensions/synology-chat/package.json +1 -1
  310. package/extensions/tlon/package.json +1 -1
  311. package/extensions/twitch/CHANGELOG.md +18 -0
  312. package/extensions/twitch/package.json +1 -1
  313. package/extensions/voice-call/CHANGELOG.md +18 -0
  314. package/extensions/voice-call/package.json +1 -1
  315. package/extensions/zalo/CHANGELOG.md +18 -0
  316. package/extensions/zalo/package.json +1 -1
  317. package/extensions/zalouser/CHANGELOG.md +18 -0
  318. package/extensions/zalouser/package.json +1 -1
  319. package/install.sh +4951 -0
  320. package/package.json +23 -5
  321. package/scripts/fased-host-updater.mjs +1421 -0
  322. package/scripts/fased-host-updaterctl.mjs +186 -0
  323. package/scripts/fased-managed-service.sh +36 -0
  324. package/scripts/fased-managed-updater.mjs +3065 -156
  325. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  326. package/scripts/fased-signer-network-hosting.sh +143 -0
  327. package/scripts/fased-signer-owner-policy.mjs +1442 -0
  328. package/scripts/fased-signer-policy-hosting.sh +50 -0
  329. package/scripts/fased-signer-policy-local.sh +26 -0
  330. package/scripts/hosted-release-manifest.mjs +185 -0
  331. package/scripts/install-fased-signerd.sh +183 -108
  332. package/scripts/install-managed-runtime.mjs +212 -10
  333. package/scripts/managed-runtime-layout.mjs +75 -3
  334. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  335. package/scripts/start-managed.sh +173 -360
  336. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  337. package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
  338. package/dist/wallet/local-socket-signer-broker.js +0 -224
  339. package/dist/wallet/local-socket-signer-custody.js +0 -42
  340. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  341. package/dist/wallet/providers/privy-adapter.js +0 -80
  342. package/dist/wallet/wallet-custody.js +0 -1836
@@ -90,13 +90,16 @@ import {
90
90
  plannerPolicyVersion,
91
91
  scorePlannerOutcome,
92
92
  } from "./src/planner-policy.js";
93
+ import { SAT_PROTOCOL_CONSTANTS } from "./src/protocol-contract.js";
93
94
  import { createSatRecoveryService } from "./src/recovery-service.js";
94
95
  import { readSatValidatorArtifact, recomputeSatValidatorArtifact } from "./src/replay.js";
95
96
  import { createSatRoundWatcherService } from "./src/round-watcher.js";
96
97
  import {
97
98
  invalidateSatReadCaches,
99
+ inspectSatCycle,
98
100
  inspectSatEpoch,
99
101
  inspectSatClaimReceipt,
102
+ inspectSatBondStakingDistributor,
100
103
  inspectCurrentSatRoundBucket,
101
104
  inspectSatMinerCapitalAccountStatus,
102
105
  inspectSatMinerCycleByAddress,
@@ -133,36 +136,45 @@ import {
133
136
  withSatServiceReadTimeout,
134
137
  } from "./src/service-read-timeout.js";
135
138
  import {
136
- submitSatBootstrap,
137
139
  submitSatClaimProtocolDistributorSat,
138
140
  submitSatClaimProtocolTreasury,
141
+ submitSatClaimUnallocatedStakingRewards,
139
142
  submitSatClaimCycleRewards,
140
143
  submitSatClaimCycleRewardsBatch,
144
+ submitSatCleanupDistributionLookupTable,
145
+ submitSatAbortEmptyCycle,
141
146
  submitSatCompactPendingCycleRange,
142
147
  submitSatCloseResolvedCycleArtifacts,
143
148
  submitSatCloseResolvedCleanupBatch,
144
149
  submitSatCloseResolvedCycleRegistryPage,
145
150
  submitSatCloseResolvedMinerCycleState,
146
- submitSatCycle,
151
+ submitSatCloseCommitPhase,
152
+ submitSatCommitCycle,
147
153
  submitSatDepositMinerCapital,
148
154
  submitSatFinalizeCycleSettlement,
149
155
  submitSatInitMinerCapital,
150
156
  submitSatOpenCycle,
151
157
  submitSatOpenDispute,
158
+ submitSatReleaseUnrevealedCommit,
152
159
  submitSatRepublishEpochRoots,
160
+ submitSatRevealCycle,
153
161
  submitSatRefillRegistryReserveFromTreasury,
154
162
  submitSatScoreCyclePage,
155
163
  submitSatSetActiveCommit,
156
- submitSatSetProtocolRecipients,
164
+ submitSatSealCycleEntropy,
165
+ submitSatTopUpRegistryReserve,
157
166
  submitSatRetargetUnlock,
158
167
  submitSatResolveDispute,
159
168
  submitSatDistributeCyclePage,
160
169
  submitSatSettleCyclePage,
170
+ submitSatSyncBondStakingRewards,
161
171
  submitSatWithdrawMinerCapital,
162
172
  resolveSatValidatorAuthority,
163
173
  submitSatValidatorAttestation,
174
+ runWithSatSubmissionWorkflow,
164
175
  } from "./src/solana-submit.js";
165
176
  import { computeMiningStrategy } from "./src/strategy-engine.js";
177
+ import { digestSatSubmissionIntent } from "./src/submission-ledger.js";
166
178
  import {
167
179
  buildSatValidatorArtifact,
168
180
  findSatValidatorArtifact,
@@ -492,8 +504,7 @@ function resolveWalletSolanaRpcUrl(env: NodeJS.ProcessEnv, walletId?: string): s
492
504
  const perWalletKey = suffix ? `FASED_WALLET_SOLANA_RPC_URL__${suffix}` : "";
493
505
  const value =
494
506
  (perWalletKey ? String(env[perWalletKey] ?? "").trim() : "") ||
495
- String(env.FASED_WALLET_SOLANA_RPC_URL ?? "").trim() ||
496
- String(env.FASED_WALLET_EMBEDDED_KEYSTORE_RPC_URL ?? "").trim();
507
+ String(env.FASED_WALLET_SOLANA_RPC_URL ?? "").trim();
497
508
  return value || undefined;
498
509
  }
499
510
 
@@ -1200,9 +1211,9 @@ const satMiningPlugin = {
1200
1211
  disputes:
1201
1212
  "usage: /satdisputesonchain <validator-authority> <epoch-id> <round-id> [reasonCode=..] [requireNonzeroSlashPenalty=true] [sortBy=targetAuthority|reasonCode|slashPenaltyOwed|openedAt] [sortOrder=asc|desc]",
1202
1213
  resolve:
1203
- "usage: /satresolvedispute <dispute-authority> <target-authority> <epoch-id> <round-id> <dismissed|upheld>",
1214
+ "usage: /satresolvedispute <dispute-authority> <target-authority> <epoch-id> <round-id> <dismissed|upheld> [idempotencyKey=<key>]",
1204
1215
  republish:
1205
- "usage: /satrepublishroots <epoch-id> <bucket-root> <score-root> <coordination-root> # returns preflight rejection reasons instead of submitting when invalid",
1216
+ "usage: /satrepublishroots <epoch-id> <bucket-root> <score-root> <coordination-root> [idempotencyKey=<key>] # returns preflight rejection reasons instead of submitting when invalid",
1206
1217
  recovery: "usage: /satrecoverysummary <validator-authority> <epoch-id> <round-id>",
1207
1218
  };
1208
1219
  const satUsageWithCheatsheet = (usage: string) =>
@@ -1435,11 +1446,14 @@ const satMiningPlugin = {
1435
1446
  description: "Resolve a SAT dispute as dismissed or upheld.",
1436
1447
  acceptsArgs: true,
1437
1448
  handler: async (ctx) => {
1438
- const [disputeAuthority, targetAuthority, epochRaw, microRoundRaw, statusRaw] = (
1439
- ctx.args ?? ""
1440
- )
1441
- .split(/\s+/)
1442
- .filter(Boolean);
1449
+ const [
1450
+ disputeAuthority,
1451
+ targetAuthority,
1452
+ epochRaw,
1453
+ microRoundRaw,
1454
+ statusRaw,
1455
+ ...optionParts
1456
+ ] = (ctx.args ?? "").split(/\s+/).filter(Boolean);
1443
1457
  if (!disputeAuthority || !targetAuthority || !epochRaw || !microRoundRaw || !statusRaw) {
1444
1458
  return { text: satUsageWithCheatsheet(satUsageText.resolve) };
1445
1459
  }
@@ -1449,6 +1463,13 @@ const satMiningPlugin = {
1449
1463
  if (!Number.isFinite(statusFlag)) {
1450
1464
  return { text: satUsageWithCheatsheet(satUsageText.resolve) };
1451
1465
  }
1466
+ const idempotencyMatch =
1467
+ optionParts.length === 1
1468
+ ? optionParts[0]?.match(/^idempotency(?:Key|-key)=(.+)$/u)
1469
+ : null;
1470
+ if (optionParts.length > 0 && !idempotencyMatch) {
1471
+ return { text: satUsageWithCheatsheet(satUsageText.resolve) };
1472
+ }
1452
1473
  const request = state.client.buildResolveDisputeRequest({
1453
1474
  disputeAuthority,
1454
1475
  targetAuthority,
@@ -1456,7 +1477,10 @@ const satMiningPlugin = {
1456
1477
  microRoundId: Number(microRoundRaw),
1457
1478
  statusFlag,
1458
1479
  });
1459
- const submitted = await submitSatResolveDispute(state.activeConfig, request.params);
1480
+ const submitted = await runWithSatSubmissionWorkflow(
1481
+ `command:satresolvedispute:${idempotencyMatch?.[1] ?? digestSatSubmissionIntent(request.params)}`,
1482
+ async () => await submitSatResolveDispute(state.activeConfig, request.params),
1483
+ );
1460
1484
  return { text: JSON.stringify({ request, submitted }, null, 2) };
1461
1485
  },
1462
1486
  });
@@ -1465,12 +1489,19 @@ const satMiningPlugin = {
1465
1489
  description: "Republish corrected SAT epoch roots after upheld dispute review.",
1466
1490
  acceptsArgs: true,
1467
1491
  handler: async (ctx) => {
1468
- const [epochRaw, bucketRoot, scoreRoot, coordinationRoot] = (ctx.args ?? "")
1492
+ const [epochRaw, bucketRoot, scoreRoot, coordinationRoot, ...optionParts] = (ctx.args ?? "")
1469
1493
  .split(/\s+/)
1470
1494
  .filter(Boolean);
1471
1495
  if (!epochRaw || !bucketRoot || !scoreRoot || !coordinationRoot) {
1472
1496
  return { text: satUsageWithCheatsheet(satUsageText.republish) };
1473
1497
  }
1498
+ const idempotencyMatch =
1499
+ optionParts.length === 1
1500
+ ? optionParts[0]?.match(/^idempotency(?:Key|-key)=(.+)$/u)
1501
+ : null;
1502
+ if (optionParts.length > 0 && !idempotencyMatch) {
1503
+ return { text: satUsageWithCheatsheet(satUsageText.republish) };
1504
+ }
1474
1505
  const request = state.client.buildRepublishEpochRootsRequest({
1475
1506
  epochId: Number(epochRaw),
1476
1507
  bucketRoot,
@@ -1484,7 +1515,10 @@ const satMiningPlugin = {
1484
1515
  if (!preflight.canRepublish) {
1485
1516
  return { text: JSON.stringify({ request, preflight }, null, 2) };
1486
1517
  }
1487
- const submitted = await submitSatRepublishEpochRoots(state.activeConfig, request.params);
1518
+ const submitted = await runWithSatSubmissionWorkflow(
1519
+ `command:satrepublishroots:${idempotencyMatch?.[1] ?? digestSatSubmissionIntent(request.params)}`,
1520
+ async () => await submitSatRepublishEpochRoots(state.activeConfig, request.params),
1521
+ );
1488
1522
  return { text: JSON.stringify({ request, preflight, submitted }, null, 2) };
1489
1523
  },
1490
1524
  });
@@ -1905,7 +1939,10 @@ const satMiningPlugin = {
1905
1939
  parameters: SatResolveDisputeToolSchema,
1906
1940
  async execute(_toolCallId, params) {
1907
1941
  const request = state.client.buildResolveDisputeRequest(params);
1908
- const submitted = await submitSatResolveDispute(state.activeConfig, request.params);
1942
+ const submitted = await runWithSatSubmissionWorkflow(
1943
+ `tool:sat_resolve_dispute:${_toolCallId}`,
1944
+ async () => await submitSatResolveDispute(state.activeConfig, request.params),
1945
+ );
1909
1946
  return {
1910
1947
  content: [
1911
1948
  { type: "text" as const, text: JSON.stringify({ request, submitted }, null, 2) },
@@ -1933,7 +1970,10 @@ const satMiningPlugin = {
1933
1970
  details: { request, preflight },
1934
1971
  };
1935
1972
  }
1936
- const submitted = await submitSatRepublishEpochRoots(state.activeConfig, request.params);
1973
+ const submitted = await runWithSatSubmissionWorkflow(
1974
+ `tool:sat_republish_epoch_roots:${_toolCallId}`,
1975
+ async () => await submitSatRepublishEpochRoots(state.activeConfig, request.params),
1976
+ );
1937
1977
  return {
1938
1978
  content: [
1939
1979
  {
@@ -1952,7 +1992,10 @@ const satMiningPlugin = {
1952
1992
  parameters: SatValidatorToolSchema,
1953
1993
  async execute(_toolCallId, params) {
1954
1994
  const request = state.client.buildSubmitValidatorAttestationRequest(params);
1955
- const submitted = await submitSatValidatorAttestation(state.activeConfig, request.params);
1995
+ const submitted = await runWithSatSubmissionWorkflow(
1996
+ `tool:sat_submit_validator_attestation:${_toolCallId}`,
1997
+ async () => await submitSatValidatorAttestation(state.activeConfig, request.params),
1998
+ );
1956
1999
  const response = await buildValidatorSubmissionSummary({
1957
2000
  epochId: request.params.epochId,
1958
2001
  microRoundId: request.params.microRoundId,
@@ -1973,7 +2016,10 @@ const satMiningPlugin = {
1973
2016
  parameters: SatDisputeToolSchema,
1974
2017
  async execute(_toolCallId, params) {
1975
2018
  const request = state.client.buildOpenDisputeRequest(params);
1976
- const submitted = await submitSatOpenDispute(state.activeConfig, request.params);
2019
+ const submitted = await runWithSatSubmissionWorkflow(
2020
+ `tool:sat_open_dispute:${_toolCallId}`,
2021
+ async () => await submitSatOpenDispute(state.activeConfig, request.params),
2022
+ );
1977
2023
  const response = await buildValidatorSubmissionSummary({
1978
2024
  epochId: request.params.epochId,
1979
2025
  microRoundId: request.params.microRoundId,
@@ -2037,7 +2083,7 @@ const satMiningPlugin = {
2037
2083
  "depositMinerCapital",
2038
2084
  "withdrawMinerCapital",
2039
2085
  "setActiveCommit",
2040
- "bootstrapRegistryReserve",
2086
+ "topUpRegistryReserve",
2041
2087
  "openCycle",
2042
2088
  "submitCycle",
2043
2089
  "claimCycleRewards",
@@ -2051,6 +2097,7 @@ const satMiningPlugin = {
2051
2097
  const isInternalSatMaintenanceAction = (action: string | null | undefined) =>
2052
2098
  new Set([
2053
2099
  "bootstrapRegistryReserve",
2100
+ "topUpRegistryReserve",
2054
2101
  "openCycle",
2055
2102
  "setActiveCommit",
2056
2103
  "closeResolvedMinerCycleState",
@@ -2212,6 +2259,9 @@ const satMiningPlugin = {
2212
2259
  participants,
2213
2260
  }),
2214
2261
  ),
2262
+ settlementPageLookupTables: Array.from(state.settlementPageLookupTables.entries()).map(
2263
+ ([cacheKey, lookupTableAddress]) => ({ cacheKey, lookupTableAddress }),
2264
+ ),
2215
2265
  workers: state.workers,
2216
2266
  lastKnownStatus: state.lastKnownStatus,
2217
2267
  chainTime: state.chainTime,
@@ -2232,6 +2282,7 @@ const satMiningPlugin = {
2232
2282
  state.roundExecution.clear();
2233
2283
  state.claimBacklog.clear();
2234
2284
  state.settlementPageParticipants.clear();
2285
+ state.settlementPageLookupTables.clear();
2235
2286
  state.auditArtifacts.clear();
2236
2287
  state.recentActions = [];
2237
2288
  state.archivedFailures = [];
@@ -2298,6 +2349,12 @@ const satMiningPlugin = {
2298
2349
  [...entry.participants],
2299
2350
  ]),
2300
2351
  );
2352
+ state.settlementPageLookupTables = new Map(
2353
+ runtimeSummary.settlementPageLookupTables.map((entry) => [
2354
+ entry.cacheKey,
2355
+ entry.lookupTableAddress,
2356
+ ]),
2357
+ );
2301
2358
  if (runtimeSummary.workers.roundWatcher) {
2302
2359
  state.workers.roundWatcher = runtimeSummary.workers.roundWatcher;
2303
2360
  }
@@ -2928,6 +2985,7 @@ const satMiningPlugin = {
2928
2985
  cycleId?: number | null;
2929
2986
  txHash: string | null;
2930
2987
  status: "success" | "failure";
2988
+ complete?: boolean;
2931
2989
  message?: string | null;
2932
2990
  }) => {
2933
2991
  mergeRecentActionTail([
@@ -2986,6 +3044,34 @@ const satMiningPlugin = {
2986
3044
  );
2987
3045
  void persistRecentActions();
2988
3046
  };
3047
+ const markClaimActionResult = (params: {
3048
+ action: "claimCycleRewards" | "claimCycleRewardsBatch";
3049
+ txHash: string | null | undefined;
3050
+ cycleIds: readonly number[];
3051
+ resolvedCycleIds: readonly number[];
3052
+ }) => {
3053
+ invalidateMiningReadCaches();
3054
+ state.lastAction = params.action;
3055
+ state.lastActionTxHash = params.txHash ?? null;
3056
+ state.lastFailure = null;
3057
+ const resolved = new Set(params.resolvedCycleIds);
3058
+ const actionAt = new Date().toISOString();
3059
+ mergeRecentActionTail(
3060
+ [...new Set(params.cycleIds)]
3061
+ .filter((cycleId) => Number.isFinite(cycleId) && cycleId >= 0)
3062
+ .map((cycleId) => ({
3063
+ action: params.action,
3064
+ cycleId,
3065
+ txHash: params.txHash ?? null,
3066
+ status: "success" as const,
3067
+ complete: resolved.has(cycleId),
3068
+ message: resolved.has(cycleId)
3069
+ ? "Cycle rewards fully claimed."
3070
+ : "Bounded SAT claim chunk submitted; rewards remain claimable.",
3071
+ at: actionAt,
3072
+ })),
3073
+ );
3074
+ };
2989
3075
  const markActionFailure = (action: string, error: unknown, cycleId?: number | null) => {
2990
3076
  const message = sanitizeMiningActionMessage(error);
2991
3077
  state.lastAction = action;
@@ -3121,19 +3207,61 @@ const satMiningPlugin = {
3121
3207
  const claimableRebate =
3122
3208
  BigInt(minerCycle.claimableDetRebateLamports ?? "0") +
3123
3209
  BigInt(minerCycle.claimablePerfRebateLamports ?? "0");
3124
- const claimedSat = BigInt(minerCycle.claimedSatRaw ?? "0");
3125
- const claimedRebate =
3126
- BigInt(minerCycle.claimedDetRebateLamports ?? "0") +
3127
- BigInt(minerCycle.claimedPerfRebateLamports ?? "0");
3128
- if (
3129
- minerCycle.capitalLockReleased &&
3130
- (claimedSat > 0n || claimedRebate > 0n || (claimableSat === 0n && claimableRebate === 0n))
3131
- ) {
3210
+ if (minerCycle.capitalLockReleased && claimableSat === 0n && claimableRebate === 0n) {
3132
3211
  resolved.push(cycleId);
3133
3212
  }
3134
3213
  }
3135
3214
  return resolved;
3136
3215
  };
3216
+ const resolveClaimCompletion = async (cycleIds: readonly number[]) => {
3217
+ const authority = state.activeWalletAddress;
3218
+ if (!authority) {
3219
+ throw new Error("Mining wallet authority is unavailable after claim confirmation.");
3220
+ }
3221
+ invalidateMiningReadCaches();
3222
+ const resolvedCycleIds: number[] = [];
3223
+ const pendingCycleIds: number[] = [];
3224
+ for (const cycleId of [...new Set(cycleIds)]) {
3225
+ const minerCycle = await satOps
3226
+ .inspectSatMinerCycle(state.activeConfig, { authority, cycleId })
3227
+ .catch(() => null);
3228
+ const claimableSat = BigInt(minerCycle?.claimableSatRaw ?? "0");
3229
+ const claimableRebate =
3230
+ BigInt(minerCycle?.claimableDetRebateLamports ?? "0") +
3231
+ BigInt(minerCycle?.claimablePerfRebateLamports ?? "0");
3232
+ if (
3233
+ minerCycle?.capitalLockReleased === true &&
3234
+ claimableSat === 0n &&
3235
+ claimableRebate === 0n
3236
+ ) {
3237
+ resolvedCycleIds.push(cycleId);
3238
+ } else {
3239
+ pendingCycleIds.push(cycleId);
3240
+ }
3241
+ }
3242
+ return { resolvedCycleIds, pendingCycleIds };
3243
+ };
3244
+ const applyClaimCompletion = (params: {
3245
+ action: "claimCycleRewards" | "claimCycleRewardsBatch";
3246
+ txHash: string | null | undefined;
3247
+ cycleIds: readonly number[];
3248
+ resolvedCycleIds: readonly number[];
3249
+ pendingCycleIds: readonly number[];
3250
+ }) => {
3251
+ for (const cycleId of params.resolvedCycleIds) {
3252
+ getOrCreateRoundExecutionState(state, cycleId, 0).claimSubmitted = true;
3253
+ }
3254
+ for (const cycleId of params.pendingCycleIds) {
3255
+ getOrCreateRoundExecutionState(state, cycleId, 0).claimSubmitted = false;
3256
+ }
3257
+ markSatClaimBacklogClaimed(state, params.resolvedCycleIds, params.txHash);
3258
+ markSatClaimBacklogReady(
3259
+ state,
3260
+ params.pendingCycleIds,
3261
+ "bounded SAT claim chunk submitted; rewards remain claimable",
3262
+ );
3263
+ markClaimActionResult(params);
3264
+ };
3137
3265
  const capturePendingPlannerCycle = async (cycleId: number): Promise<void> => {
3138
3266
  const plannerSnapshot =
3139
3267
  state.lastPlannerDecision?.cycleId === cycleId ? state.lastPlannerDecision.snapshot : null;
@@ -3234,7 +3362,10 @@ const satMiningPlugin = {
3234
3362
  }
3235
3363
  }
3236
3364
  for (const execution of state.roundExecution.values()) {
3237
- if (execution.participationSubmitted && !execution.claimSubmitted) {
3365
+ if (
3366
+ (execution.commitSubmitted || execution.participationSubmitted) &&
3367
+ !execution.claimSubmitted
3368
+ ) {
3238
3369
  return true;
3239
3370
  }
3240
3371
  }
@@ -3242,7 +3373,12 @@ const satMiningPlugin = {
3242
3373
  if (entry.status !== "success" || typeof entry.cycleId !== "number" || entry.cycleId <= 0) {
3243
3374
  return false;
3244
3375
  }
3245
- if (entry.action !== "openCycle" && entry.action !== "submitCycle") {
3376
+ if (
3377
+ entry.action !== "openCycle" &&
3378
+ entry.action !== "submitCycle" &&
3379
+ entry.action !== "commitCycle" &&
3380
+ entry.action !== "revealCycle"
3381
+ ) {
3246
3382
  return false;
3247
3383
  }
3248
3384
  return !hasSuccessfulClaimOrCloseRecentAction(entry.cycleId);
@@ -3288,6 +3424,7 @@ const satMiningPlugin = {
3288
3424
  strategyExecution:
3289
3425
  state.activeConfig.strategyExecution ??
3290
3426
  strategyModeToExecution(state.activeConfig.strategyMode),
3427
+ cycleCadence: state.activeConfig.cycleCadence ?? 1,
3291
3428
  claimMode: "auto",
3292
3429
  payout: state.activeConfig.payout ?? true,
3293
3430
  strategyMode: state.activeConfig.strategyMode ?? "base",
@@ -3392,6 +3529,10 @@ const satMiningPlugin = {
3392
3529
  state.activeConfig.strategyExecution = strategyModeToExecution(
3393
3530
  state.activeConfig.strategyMode,
3394
3531
  );
3532
+ state.activeConfig.cycleCadence =
3533
+ profile.cycleCadence === 2 || profile.cycleCadence === 6 || profile.cycleCadence === 12
3534
+ ? profile.cycleCadence
3535
+ : 1;
3395
3536
  state.activeConfig.claimMode = "auto";
3396
3537
  state.activeConfig.payout =
3397
3538
  typeof profile.payout === "boolean" ? profile.payout : state.activeConfig.payout;
@@ -3641,8 +3782,7 @@ const satMiningPlugin = {
3641
3782
  const perWalletKey = suffix ? `FASED_WALLET_SOLANA_RPC_URL__${suffix.toUpperCase()}` : "";
3642
3783
  return Boolean(
3643
3784
  (perWalletKey ? String(effectiveEnv[perWalletKey] ?? "").trim() : "") ||
3644
- String(effectiveEnv.FASED_WALLET_SOLANA_RPC_URL ?? "").trim() ||
3645
- String(effectiveEnv.FASED_WALLET_EMBEDDED_KEYSTORE_RPC_URL ?? "").trim(),
3785
+ String(effectiveEnv.FASED_WALLET_SOLANA_RPC_URL ?? "").trim(),
3646
3786
  );
3647
3787
  };
3648
3788
  const normalizeAddressValue = (value?: string) => {
@@ -4182,7 +4322,7 @@ const satMiningPlugin = {
4182
4322
  remediation:
4183
4323
  wallet?.signerCapability === "background-ready"
4184
4324
  ? undefined
4185
- : "Use the built-in local signer or embedded keystore for unattended mining automation.",
4325
+ : "Use the local native signer for unattended Mining. Wallet Standard and Turnkey are reviewed/manual wallet paths, not background Mining signers.",
4186
4326
  },
4187
4327
  {
4188
4328
  key: "rpcReady",
@@ -4235,13 +4375,13 @@ const satMiningPlugin = {
4235
4375
  ? "SAT miner capital account has an invalid owner"
4236
4376
  : "Fund Mining capital first"
4237
4377
  : capitalFreeLamports >= capitalEntryThreshold
4238
- ? "Meets 0.25 SOL funded minimum entry"
4239
- : "Below 0.25 SOL funded minimum entry",
4378
+ ? "Meets 0.25 SOL minimum eligibility capital"
4379
+ : "Below 0.25 SOL minimum eligibility capital",
4240
4380
  remediation: !minerCapitalInitialized
4241
4381
  ? minerCapitalRemediation
4242
4382
  : capitalFreeLamports >= capitalEntryThreshold
4243
4383
  ? undefined
4244
- : "Deposit at least 0.25 SOL into miner capital to participate in SAT cycles.",
4384
+ : "Deposit at least 0.25 SOL plus reveal collateral into miner capital to participate in SAT cycles.",
4245
4385
  },
4246
4386
  {
4247
4387
  key: "ataReady",
@@ -4392,6 +4532,11 @@ const satMiningPlugin = {
4392
4532
  (await satOps
4393
4533
  .inspectSatCycle(state.activeConfig, { cycleId: currentCycleId })
4394
4534
  .catch(() => null));
4535
+ const currentSettlementProgress =
4536
+ statusAccounts?.currentSettlementProgress ??
4537
+ (await satOps
4538
+ .inspectSatCycleSettlementProgressV2(state.activeConfig, { cycleId: currentCycleId })
4539
+ .catch(() => null));
4395
4540
  const currentMinerCycleState =
4396
4541
  statusAccounts?.currentMinerCycle ??
4397
4542
  (statusAuthority
@@ -4471,7 +4616,9 @@ const satMiningPlugin = {
4471
4616
  return undefined;
4472
4617
  }
4473
4618
  })();
4474
- const totalCommittedLamports = currentExecution?.participationSubmitted ? 250_000_000 : 0;
4619
+ const totalCommittedLamports = currentExecution?.commitSubmitted
4620
+ ? (currentExecution.commitLamports ?? 250_000_000)
4621
+ : 0;
4475
4622
  const unlockRatio = Math.min(1, totalCommittedLamports / currentUnlockTargetLamports);
4476
4623
  const claimableSatRaw = snapshot.walletEpoch
4477
4624
  ? (
@@ -4481,7 +4628,11 @@ const satMiningPlugin = {
4481
4628
  : undefined;
4482
4629
  const slashPenaltyOwed = BigInt(snapshot.stake?.slashPenaltyOwed ?? "0");
4483
4630
  const hasClaimableSat = claimableSatRaw ? BigInt(claimableSatRaw) > 0n : false;
4484
- const lastParticipation = latestRecentAction("submitCycle");
4631
+ const lastParticipation = latestRecentActionAny([
4632
+ "revealCycle",
4633
+ "commitCycle",
4634
+ "submitCycle",
4635
+ ]);
4485
4636
  const lastMiningCrank =
4486
4637
  latestRecentAction("distributeCyclePage") ??
4487
4638
  latestRecentAction("scoreCyclePage") ??
@@ -4620,6 +4771,8 @@ const satMiningPlugin = {
4620
4771
  (action) =>
4621
4772
  action.status === "success" &&
4622
4773
  (action.action === "submitCycle" ||
4774
+ action.action === "commitCycle" ||
4775
+ action.action === "revealCycle" ||
4623
4776
  action.action === "setActiveCommit" ||
4624
4777
  action.action === "depositCapital" ||
4625
4778
  action.action === "withdrawCapital" ||
@@ -4636,6 +4789,8 @@ const satMiningPlugin = {
4636
4789
  (state.running ||
4637
4790
  state.activeConfig.enabled ||
4638
4791
  state.activeConfig.drainOnly ||
4792
+ currentExecution?.commitSubmitted ||
4793
+ previousExecution?.commitSubmitted ||
4639
4794
  currentExecution?.participationSubmitted ||
4640
4795
  previousExecution?.participationSubmitted ||
4641
4796
  hasPositiveLamportsValue(cachedStatus?.currentCapitalFundedLamports) ||
@@ -4654,6 +4809,39 @@ const satMiningPlugin = {
4654
4809
  globalState?.minimumEntryLamports ??
4655
4810
  "250000000";
4656
4811
  const cycleErosionPpm = resolveSatEffectiveCycleErosionPpm(globalState);
4812
+ const cycleCadence = state.activeConfig.cycleCadence ?? 1;
4813
+ const runway = (() => {
4814
+ try {
4815
+ const funded = BigInt(currentCapitalFundedLamports);
4816
+ const commit = BigInt(activeCommitLamports);
4817
+ const erosion = (commit * cycleErosionPpm) / 1_000_000n;
4818
+ const missedRevealPenalty =
4819
+ (commit * BigInt(SAT_PROTOCOL_CONSTANTS.cycleNonRevealPenaltyBps)) / 10_000n;
4820
+ const collateral = missedRevealPenalty > erosion ? missedRevealPenalty : erosion;
4821
+ const requiredToEnter = commit + collateral;
4822
+ const participations =
4823
+ funded < requiredToEnter
4824
+ ? 0n
4825
+ : erosion === 0n
4826
+ ? null
4827
+ : (funded - requiredToEnter) / erosion + 1n;
4828
+ const calendarCycles =
4829
+ participations == null ? null : participations * BigInt(cycleCadence);
4830
+ const days =
4831
+ calendarCycles == null
4832
+ ? null
4833
+ : Number(calendarCycles * BigInt(SAT_CYCLE_SECONDS)) / 86_400;
4834
+ return {
4835
+ commitCollateralLamports: collateral.toString(),
4836
+ estimatedParticipations: participations?.toString() ?? null,
4837
+ estimatedCalendarCycles: calendarCycles?.toString() ?? null,
4838
+ estimatedDays: days,
4839
+ excludesNetworkFees: true,
4840
+ };
4841
+ } catch {
4842
+ return null;
4843
+ }
4844
+ })();
4657
4845
  const liveCycleErosionLamports = (() => {
4658
4846
  try {
4659
4847
  return ((BigInt(liveCycleCommittedLamports) * cycleErosionPpm) / 1_000_000n).toString();
@@ -4776,7 +4964,7 @@ const satMiningPlugin = {
4776
4964
  const liveCycleTotalCommittedLamports =
4777
4965
  currentCycleState?.totalCommittedLamports ??
4778
4966
  currentMinerCycleState?.committedLamports ??
4779
- (currentExecution?.participationSubmitted ? liveCycleCommittedLamports : null);
4967
+ (currentExecution?.commitSubmitted ? liveCycleCommittedLamports : null);
4780
4968
  const liveCycleUnlockTargetLamports =
4781
4969
  currentCycleState?.unlockTargetLamports ?? globalState?.currentUnlockSolLamports ?? null;
4782
4970
  const liveCycleUnlockRatioFp =
@@ -4830,10 +5018,10 @@ const satMiningPlugin = {
4830
5018
  const latestSettledCycleId = settledHistory[0]?.cycleId ?? null;
4831
5019
  const latestSubmittedCycleId = (() => {
4832
5020
  const cycleIds = new Set<number>();
4833
- if (currentExecution?.participationSubmitted) {
5021
+ if (currentExecution?.commitSubmitted || currentExecution?.participationSubmitted) {
4834
5022
  cycleIds.add(currentCycleId);
4835
5023
  }
4836
- if (previousExecution?.participationSubmitted) {
5024
+ if (previousExecution?.commitSubmitted || previousExecution?.participationSubmitted) {
4837
5025
  cycleIds.add(previousCycleId);
4838
5026
  }
4839
5027
  for (const pendingCycleId of pendingCycleIds) {
@@ -4842,7 +5030,9 @@ const satMiningPlugin = {
4842
5030
  for (const entry of allUserFacingRecentActions) {
4843
5031
  if (
4844
5032
  entry.status === "success" &&
4845
- entry.action === "submitCycle" &&
5033
+ (entry.action === "submitCycle" ||
5034
+ entry.action === "commitCycle" ||
5035
+ entry.action === "revealCycle") &&
4846
5036
  typeof entry.cycleId === "number" &&
4847
5037
  Number.isFinite(entry.cycleId)
4848
5038
  ) {
@@ -5092,6 +5282,8 @@ const satMiningPlugin = {
5092
5282
  strategyExecution:
5093
5283
  state.activeConfig.strategyExecution ??
5094
5284
  strategyModeToExecution(state.activeConfig.strategyMode),
5285
+ cycleCadence,
5286
+ runway,
5095
5287
  strategyMode: state.activeConfig.strategyMode ?? "base",
5096
5288
  network: state.activeConfig.network,
5097
5289
  riskMode: state.activeConfig.riskMode,
@@ -5185,6 +5377,10 @@ const satMiningPlugin = {
5185
5377
  nextOpenCycleLamports: rentExemptionLamports?.openCycleLamports ?? null,
5186
5378
  nextSubmitCycleSharedLamports: rentExemptionLamports?.submitCycleSharedLamports ?? null,
5187
5379
  nextSubmitCycleSignerLamports: rentExemptionLamports?.submitCycleSignerLamports ?? null,
5380
+ currentKeeperBountyPaidLamports:
5381
+ currentSettlementProgress?.keeperBountyPaidLamports ?? null,
5382
+ currentKeeperBountyUnpaidLamports:
5383
+ currentSettlementProgress?.keeperBountyUnpaidLamports ?? null,
5188
5384
  currentCapitalAddress,
5189
5385
  currentCapitalFundedLamports,
5190
5386
  currentCapitalLockedLamports,
@@ -6661,7 +6857,30 @@ const satMiningPlugin = {
6661
6857
  return generated;
6662
6858
  };
6663
6859
 
6664
- api.registerGatewayMethod("sat.openCycle", async ({ params, respond }) => {
6860
+ type SatGatewayHandler = Parameters<typeof api.registerGatewayMethod>[1];
6861
+ const registerSatSubmissionMethod = (method: string, handler: SatGatewayHandler) => {
6862
+ api.registerGatewayMethod(method, async (context) => {
6863
+ const source =
6864
+ context.params && typeof context.params === "object" && !Array.isArray(context.params)
6865
+ ? (context.params as Record<string, unknown>)
6866
+ : {};
6867
+ const { idempotencyKey: rawIdempotencyKey, ...intentParams } = source;
6868
+ const idempotencyKey =
6869
+ typeof rawIdempotencyKey === "string" && rawIdempotencyKey.trim()
6870
+ ? rawIdempotencyKey.trim()
6871
+ : `derived:${digestSatSubmissionIntent(intentParams)}`;
6872
+ try {
6873
+ await runWithSatSubmissionWorkflow(
6874
+ `gateway:${method}:${idempotencyKey}`,
6875
+ async () => await handler(context),
6876
+ );
6877
+ } catch (error) {
6878
+ respondGatewayError(context.respond, error);
6879
+ }
6880
+ });
6881
+ };
6882
+
6883
+ registerSatSubmissionMethod("sat.openCycle", async ({ params, respond }) => {
6665
6884
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
6666
6885
  try {
6667
6886
  const request = state.client.buildOpenCycleRequest({ cycleId });
@@ -6679,51 +6898,23 @@ const satMiningPlugin = {
6679
6898
  }
6680
6899
  });
6681
6900
 
6682
- api.registerGatewayMethod("sat.bootstrapRegistryReserve", async ({ params, respond }) => {
6683
- try {
6684
- const authority =
6685
- typeof (params as { authority?: string })?.authority === "string"
6686
- ? String((params as { authority?: string }).authority).trim()
6687
- : (state.activeWalletAddress ?? "");
6688
- const initialStake =
6689
- typeof (params as { initialStake?: number })?.initialStake === "number"
6690
- ? Number((params as { initialStake?: number }).initialStake)
6691
- : 0;
6692
- const submitted = await submitSatBootstrap(state.activeConfig, {
6693
- authority,
6694
- initialStake,
6695
- });
6696
- markActionSuccess("bootstrapRegistryReserve", submitted.txHash, null);
6697
- respond(true, jsonOk({ submitted, status: await getMiningStatus() }));
6698
- } catch (error) {
6699
- markActionFailure("bootstrapRegistryReserve", error, null);
6700
- respondGatewayError(respond, error);
6701
- }
6702
- });
6703
-
6704
- api.registerGatewayMethod("sat.setProtocolRecipients", async ({ params, respond }) => {
6901
+ registerSatSubmissionMethod("sat.topUpRegistryReserve", async ({ params, respond }) => {
6705
6902
  try {
6706
- const treasuryRecipient =
6707
- typeof (params as { treasuryRecipient?: string })?.treasuryRecipient === "string"
6708
- ? String((params as { treasuryRecipient?: string }).treasuryRecipient).trim()
6709
- : "";
6710
- const distributorRecipient =
6711
- typeof (params as { distributorRecipient?: string })?.distributorRecipient === "string"
6712
- ? String((params as { distributorRecipient?: string }).distributorRecipient).trim()
6713
- : "";
6714
- const submitted = await submitSatSetProtocolRecipients(state.activeConfig, {
6715
- treasuryRecipient,
6716
- distributorRecipient,
6903
+ const targetBalanceLamports = Number(
6904
+ (params as { targetBalanceLamports?: number })?.targetBalanceLamports ?? 0,
6905
+ );
6906
+ const submitted = await submitSatTopUpRegistryReserve(state.activeConfig, {
6907
+ targetBalanceLamports,
6717
6908
  });
6718
- markActionSuccess("setProtocolRecipients", submitted.txHash, null);
6909
+ markActionSuccess("topUpRegistryReserve", submitted.txHash, null);
6719
6910
  respond(true, jsonOk({ submitted, status: await getMiningStatus() }));
6720
6911
  } catch (error) {
6721
- markActionFailure("setProtocolRecipients", error, null);
6912
+ markActionFailure("topUpRegistryReserve", error, null);
6722
6913
  respondGatewayError(respond, error);
6723
6914
  }
6724
6915
  });
6725
6916
 
6726
- api.registerGatewayMethod("sat.claimProtocolTreasury", async ({ params, respond }) => {
6917
+ registerSatSubmissionMethod("sat.claimProtocolTreasury", async ({ params, respond }) => {
6727
6918
  try {
6728
6919
  const recipientOwner =
6729
6920
  typeof (params as { recipientOwner?: string })?.recipientOwner === "string"
@@ -6740,7 +6931,7 @@ const satMiningPlugin = {
6740
6931
  }
6741
6932
  });
6742
6933
 
6743
- api.registerGatewayMethod("sat.claimProtocolDistributorSat", async ({ params, respond }) => {
6934
+ registerSatSubmissionMethod("sat.claimProtocolDistributorSat", async ({ params, respond }) => {
6744
6935
  try {
6745
6936
  const recipientOwner =
6746
6937
  typeof (params as { recipientOwner?: string })?.recipientOwner === "string"
@@ -6757,7 +6948,7 @@ const satMiningPlugin = {
6757
6948
  }
6758
6949
  });
6759
6950
 
6760
- api.registerGatewayMethod(
6951
+ registerSatSubmissionMethod(
6761
6952
  "sat.refillRegistryReserveFromTreasury",
6762
6953
  async ({ params, respond }) => {
6763
6954
  try {
@@ -6815,7 +7006,7 @@ const satMiningPlugin = {
6815
7006
  .slice(0, Math.max(0, Math.min(limit, SAT_MAINTENANCE_RECENT_CLEANUP_CYCLE_LIMIT)));
6816
7007
  };
6817
7008
 
6818
- api.registerGatewayMethod("sat.runProtocolMaintenanceOnce", async ({ params, respond }) => {
7009
+ registerSatSubmissionMethod("sat.runProtocolMaintenanceOnce", async ({ params, respond }) => {
6819
7010
  const submitted: Array<{
6820
7011
  lane: SatMaintenanceLane;
6821
7012
  action: string;
@@ -6891,18 +7082,20 @@ const satMiningPlugin = {
6891
7082
  };
6892
7083
  const readFresh = async () => {
6893
7084
  invalidateSatReadCaches();
6894
- const [global, treasuryState, registryReserve, rent] = await Promise.all([
6895
- satOps.inspectSatGlobalState(state.activeConfig).catch(() => null),
6896
- satOps.inspectSatTreasuryState(state.activeConfig).catch(() => null),
6897
- satOps.inspectSatRegistryReserveLamports(state.activeConfig).catch(() => null),
6898
- satOps.inspectSatRentExemptionLamports(state.activeConfig).catch(() => null),
6899
- ]);
7085
+ const [global, treasuryState, registryReserve, rent, stakingDistributor] =
7086
+ await Promise.all([
7087
+ satOps.inspectSatGlobalState(state.activeConfig).catch(() => null),
7088
+ satOps.inspectSatTreasuryState(state.activeConfig).catch(() => null),
7089
+ satOps.inspectSatRegistryReserveLamports(state.activeConfig).catch(() => null),
7090
+ satOps.inspectSatRentExemptionLamports(state.activeConfig).catch(() => null),
7091
+ inspectSatBondStakingDistributor(state.activeConfig).catch(() => null),
7092
+ ]);
6900
7093
  const target =
6901
7094
  targetBalanceLamports !== undefined
6902
7095
  ? BigInt(targetBalanceLamports)
6903
7096
  : BigInt(rent?.registryReserveTargetLamports ?? "200000000");
6904
7097
  const reserve = BigInt(registryReserve?.lamports ?? "0");
6905
- return { global, treasuryState, registryReserve, target, reserve };
7098
+ return { global, treasuryState, registryReserve, stakingDistributor, target, reserve };
6906
7099
  };
6907
7100
  const buildLaneSummary = () => {
6908
7101
  const lanes: Record<
@@ -6955,6 +7148,7 @@ const satMiningPlugin = {
6955
7148
  pendingTreasurySatRaw: snapshot.treasuryState?.pendingTreasurySatRaw ?? "0",
6956
7149
  pendingTreasurySolLamports: snapshot.treasuryState?.pendingTreasurySolLamports ?? "0",
6957
7150
  pendingDistributorSatRaw: snapshot.treasuryState?.pendingDistributorSatRaw ?? "0",
7151
+ unallocatedStakingRewardRaw: snapshot.stakingDistributor?.unallocatedRewardRaw ?? "0",
6958
7152
  cleanup: cleanupSummary,
6959
7153
  lanes: buildLaneSummary(),
6960
7154
  updatedAt: new Date().toISOString(),
@@ -7029,6 +7223,60 @@ const satMiningPlugin = {
7029
7223
  });
7030
7224
  }
7031
7225
 
7226
+ // Protocol rewards are recorded atomically by the mining claim CPI.
7227
+ // Any remaining vault delta is an unsolicited transfer and must be
7228
+ // quarantined for the fixed treasury, never allocated to stakers.
7229
+ const stakingRewardVaultRaw = BigInt(
7230
+ snapshot.stakingDistributor?.rewardVaultBalanceRaw ?? "0",
7231
+ );
7232
+ const observedStakingRewardRaw = BigInt(
7233
+ snapshot.stakingDistributor?.observedRewardVaultRaw ?? "0",
7234
+ );
7235
+ if (
7236
+ snapshot.stakingDistributor?.statusLabel === "active" &&
7237
+ stakingRewardVaultRaw > observedStakingRewardRaw &&
7238
+ stakingRewardVaultRaw - observedStakingRewardRaw >= minSatRaw
7239
+ ) {
7240
+ const tx = await submitSatSyncBondStakingRewards(state.activeConfig);
7241
+ pushSubmitted({
7242
+ lane: "distributor",
7243
+ action: "syncBondStakingRewards",
7244
+ txHash: tx.txHash,
7245
+ });
7246
+ markActionSuccess("syncBondStakingRewards", tx.txHash, null);
7247
+ snapshot = await readFresh();
7248
+ } else {
7249
+ pushSubmitted({
7250
+ lane: "distributor",
7251
+ action: "syncBondStakingRewards",
7252
+ skipped: "no-unexpected-vault-balance-or-below-threshold",
7253
+ });
7254
+ }
7255
+
7256
+ const unallocatedTreasuryRecipient = snapshot.global?.treasuryRecipient;
7257
+ if (
7258
+ unallocatedTreasuryRecipient &&
7259
+ unallocatedTreasuryRecipient !== defaultPubkey &&
7260
+ BigInt(snapshot.stakingDistributor?.unallocatedRewardRaw ?? "0") >= minSatRaw
7261
+ ) {
7262
+ const tx = await submitSatClaimUnallocatedStakingRewards(state.activeConfig, {
7263
+ recipientOwner: unallocatedTreasuryRecipient,
7264
+ });
7265
+ pushSubmitted({
7266
+ lane: "treasury",
7267
+ action: "claimUnallocatedStakingRewards",
7268
+ txHash: tx.txHash,
7269
+ });
7270
+ markActionSuccess("claimUnallocatedStakingRewards", tx.txHash, null);
7271
+ snapshot = await readFresh();
7272
+ } else {
7273
+ pushSubmitted({
7274
+ lane: "treasury",
7275
+ action: "claimUnallocatedStakingRewards",
7276
+ skipped: "no-recipient-or-below-threshold",
7277
+ });
7278
+ }
7279
+
7032
7280
  if (cleanupMaxCycles > 0 && cleanupBudgetMs > 0 && cleanupMaxTransactions > 0) {
7033
7281
  const maxCleanupCandidates = Math.min(
7034
7282
  50,
@@ -7180,7 +7428,7 @@ const satMiningPlugin = {
7180
7428
  }
7181
7429
  });
7182
7430
 
7183
- api.registerGatewayMethod("sat.initMinerCapital", async ({ params, respond }) => {
7431
+ registerSatSubmissionMethod("sat.initMinerCapital", async ({ params, respond }) => {
7184
7432
  try {
7185
7433
  await ensureSatCapitalActionSignerReady();
7186
7434
  const authority =
@@ -7196,7 +7444,7 @@ const satMiningPlugin = {
7196
7444
  }
7197
7445
  });
7198
7446
 
7199
- api.registerGatewayMethod("sat.depositMinerCapital", async ({ params, respond }) => {
7447
+ registerSatSubmissionMethod("sat.depositMinerCapital", async ({ params, respond }) => {
7200
7448
  try {
7201
7449
  await ensureSatCapitalActionSignerReady();
7202
7450
  const lamports = Number((params as { lamports?: number })?.lamports ?? 0);
@@ -7213,7 +7461,7 @@ const satMiningPlugin = {
7213
7461
  }
7214
7462
  });
7215
7463
 
7216
- api.registerGatewayMethod("sat.withdrawMinerCapital", async ({ params, respond }) => {
7464
+ registerSatSubmissionMethod("sat.withdrawMinerCapital", async ({ params, respond }) => {
7217
7465
  try {
7218
7466
  await ensureSatCapitalActionSignerReady();
7219
7467
  const lamports = Number((params as { lamports?: number })?.lamports ?? 0);
@@ -7228,7 +7476,7 @@ const satMiningPlugin = {
7228
7476
  }
7229
7477
  });
7230
7478
 
7231
- api.registerGatewayMethod("sat.setActiveCommit", async ({ params, respond }) => {
7479
+ registerSatSubmissionMethod("sat.setActiveCommit", async ({ params, respond }) => {
7232
7480
  try {
7233
7481
  await ensureSatCapitalActionSignerReady();
7234
7482
  const lamports = Number((params as { lamports?: number })?.lamports ?? 0);
@@ -7253,38 +7501,147 @@ const satMiningPlugin = {
7253
7501
  }
7254
7502
  });
7255
7503
 
7256
- api.registerGatewayMethod("sat.submitCycle", async ({ params, respond }) => {
7504
+ registerSatSubmissionMethod("sat.commitCycle", async ({ params, respond }) => {
7505
+ const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7506
+ try {
7507
+ const commitmentHex = String(
7508
+ (params as { commitmentHex?: string })?.commitmentHex ?? "",
7509
+ ).trim();
7510
+ if (!/^[0-9a-f]{64}$/i.test(commitmentHex)) {
7511
+ throw new Error("cycle commitment must be a 32-byte hexadecimal digest");
7512
+ }
7513
+ const submitted = await submitSatCommitCycle(state.activeConfig, {
7514
+ cycleId,
7515
+ commitmentHex,
7516
+ });
7517
+ if (Number.isFinite(cycleId) && cycleId >= 0) {
7518
+ const execution = getOrCreateRoundExecutionState(state, cycleId, 0);
7519
+ execution.openRoundSubmitted = true;
7520
+ execution.commitSubmitted = true;
7521
+ execution.commitmentHex = commitmentHex.toLowerCase();
7522
+ }
7523
+ markActionSuccess("commitCycle", submitted.txHash, cycleId);
7524
+ await persistRecentActions();
7525
+ respond(true, jsonOk({ submitted }));
7526
+ } catch (error) {
7527
+ if (!isCycleMismatchError(error)) {
7528
+ markActionFailure("commitCycle", error, cycleId);
7529
+ }
7530
+ respondGatewayError(respond, error);
7531
+ }
7532
+ });
7533
+
7534
+ registerSatSubmissionMethod("sat.closeCommitPhase", async ({ params, respond }) => {
7257
7535
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7258
7536
  try {
7537
+ const submitted = await submitSatCloseCommitPhase(state.activeConfig, { cycleId });
7538
+ invalidateMiningReadCaches();
7539
+ getOrCreateRoundExecutionState(state, cycleId, 0).entropyTargetPinned = true;
7540
+ markActionSuccess("closeCommitPhase", submitted.txHash, cycleId);
7541
+ await persistRecentActions();
7542
+ respond(true, jsonOk({ submitted }));
7543
+ } catch (error) {
7544
+ markActionFailure("closeCommitPhase", error, cycleId);
7545
+ respondGatewayError(respond, error);
7546
+ }
7547
+ });
7548
+
7549
+ registerSatSubmissionMethod("sat.sealCycleEntropy", async ({ params, respond }) => {
7550
+ const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7551
+ try {
7552
+ const cycle = await inspectSatCycle(state.activeConfig, { cycleId });
7553
+ if (cycle.unlockIntervalStartCycleId == null) {
7554
+ throw new Error(`cycle ${cycleId} does not expose its unlock interval start`);
7555
+ }
7556
+ const submitted = await submitSatSealCycleEntropy(state.activeConfig, {
7557
+ cycleId,
7558
+ intervalStartCycleId: cycle.unlockIntervalStartCycleId,
7559
+ });
7560
+ invalidateMiningReadCaches();
7561
+ markActionSuccess("sealCycleEntropy", submitted.txHash, cycleId);
7562
+ await persistRecentActions();
7563
+ respond(true, jsonOk({ submitted }));
7564
+ } catch (error) {
7565
+ markActionFailure("sealCycleEntropy", error, cycleId);
7566
+ respondGatewayError(respond, error);
7567
+ }
7568
+ });
7569
+
7570
+ registerSatSubmissionMethod("sat.revealCycle", async ({ params, respond }) => {
7571
+ const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7572
+ try {
7573
+ const nonceBase64 = String((params as { nonceBase64?: string })?.nonceBase64 ?? "").trim();
7259
7574
  const allocationFp = Array.isArray((params as { allocationFp?: number[] })?.allocationFp)
7260
7575
  ? ((params as { allocationFp?: number[] }).allocationFp ?? [])
7261
7576
  : [];
7262
- const request = state.client.buildSubmitCycleRequest({
7577
+ const cycle = await inspectSatCycle(state.activeConfig, { cycleId });
7578
+ if (cycle.unlockIntervalStartCycleId == null) {
7579
+ throw new Error(`cycle ${cycleId} does not expose its unlock interval start`);
7580
+ }
7581
+ const submitted = await submitSatRevealCycle(state.activeConfig, {
7263
7582
  cycleId,
7583
+ intervalStartCycleId: cycle.unlockIntervalStartCycleId,
7584
+ nonceBase64,
7264
7585
  allocationFp,
7265
7586
  });
7266
- const submitted = await submitSatCycle(state.activeConfig, request.params);
7587
+ invalidateMiningReadCaches();
7267
7588
  await capturePendingPlannerCycle(cycleId);
7268
- if (Number.isFinite(cycleId) && cycleId >= 0) {
7269
- const execution = getOrCreateRoundExecutionState(state, cycleId, 0);
7270
- execution.openRoundSubmitted = true;
7271
- execution.participationSubmitted = true;
7272
- }
7273
- markActionSuccess("submitCycle", submitted.txHash, cycleId);
7589
+ const execution = getOrCreateRoundExecutionState(state, cycleId, 0);
7590
+ execution.openRoundSubmitted = true;
7591
+ execution.commitSubmitted = true;
7592
+ execution.participationSubmitted = true;
7593
+ markActionSuccess("revealCycle", submitted.txHash, cycleId);
7274
7594
  await persistRecentActions();
7275
- respond(true, jsonOk({ request, submitted }));
7595
+ respond(true, jsonOk({ submitted }));
7276
7596
  } catch (error) {
7277
7597
  state.pendingPlannerCycles.delete(cycleId);
7278
- if (isCycleMismatchError(error)) {
7279
- respondGatewayError(respond, error);
7280
- return;
7281
- }
7282
- markActionFailure("submitCycle", error, cycleId);
7598
+ markActionFailure("revealCycle", error, cycleId);
7283
7599
  respondGatewayError(respond, error);
7284
7600
  }
7285
7601
  });
7286
7602
 
7287
- api.registerGatewayMethod("sat.settleCyclePage", async ({ params, respond }) => {
7603
+ registerSatSubmissionMethod("sat.releaseUnrevealedCommit", async ({ params, respond }) => {
7604
+ const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7605
+ try {
7606
+ const minerAuthority = String(
7607
+ (params as { minerAuthority?: string })?.minerAuthority ?? "",
7608
+ ).trim();
7609
+ const submitted = await submitSatReleaseUnrevealedCommit(state.activeConfig, {
7610
+ cycleId,
7611
+ minerAuthority,
7612
+ });
7613
+ invalidateMiningReadCaches();
7614
+ markActionSuccess("releaseUnrevealedCommit", submitted.txHash, cycleId);
7615
+ await persistRecentActions();
7616
+ respond(true, jsonOk({ submitted }));
7617
+ } catch (error) {
7618
+ markActionFailure("releaseUnrevealedCommit", error, cycleId);
7619
+ respondGatewayError(respond, error);
7620
+ }
7621
+ });
7622
+
7623
+ registerSatSubmissionMethod("sat.abortEmptyCycle", async ({ params, respond }) => {
7624
+ const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7625
+ try {
7626
+ const submitted = await submitSatAbortEmptyCycle(state.activeConfig, { cycleId });
7627
+ invalidateMiningReadCaches();
7628
+ markActionSuccess("abortEmptyCycle", submitted.txHash, cycleId);
7629
+ await persistRecentActions();
7630
+ respond(true, jsonOk({ submitted }));
7631
+ } catch (error) {
7632
+ markActionFailure("abortEmptyCycle", error, cycleId);
7633
+ respondGatewayError(respond, error);
7634
+ }
7635
+ });
7636
+
7637
+ registerSatSubmissionMethod("sat.submitCycle", async ({ respond }) => {
7638
+ respondGatewayError(
7639
+ respond,
7640
+ new Error("public allocation submission is retired; update Fased to use commit/reveal"),
7641
+ );
7642
+ });
7643
+
7644
+ registerSatSubmissionMethod("sat.settleCyclePage", async ({ params, respond }) => {
7288
7645
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7289
7646
  try {
7290
7647
  const pageIndex = Number((params as { pageIndex?: number })?.pageIndex ?? 0);
@@ -7319,7 +7676,7 @@ const satMiningPlugin = {
7319
7676
  }
7320
7677
  });
7321
7678
 
7322
- api.registerGatewayMethod("sat.finalizeCycleSettlement", async ({ params, respond }) => {
7679
+ registerSatSubmissionMethod("sat.finalizeCycleSettlement", async ({ params, respond }) => {
7323
7680
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7324
7681
  try {
7325
7682
  const pageCount = Number((params as { pageCount?: number })?.pageCount ?? 1);
@@ -7339,7 +7696,7 @@ const satMiningPlugin = {
7339
7696
  }
7340
7697
  });
7341
7698
 
7342
- api.registerGatewayMethod("sat.scoreCyclePage", async ({ params, respond }) => {
7699
+ registerSatSubmissionMethod("sat.scoreCyclePage", async ({ params, respond }) => {
7343
7700
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7344
7701
  try {
7345
7702
  const pageIndex = Number((params as { pageIndex?: number })?.pageIndex ?? 0);
@@ -7370,7 +7727,7 @@ const satMiningPlugin = {
7370
7727
  }
7371
7728
  });
7372
7729
 
7373
- api.registerGatewayMethod("sat.distributeCyclePage", async ({ params, respond }) => {
7730
+ registerSatSubmissionMethod("sat.distributeCyclePage", async ({ params, respond }) => {
7374
7731
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7375
7732
  try {
7376
7733
  const pageIndex = Number((params as { pageIndex?: number })?.pageIndex ?? 0);
@@ -7382,6 +7739,12 @@ const satMiningPlugin = {
7382
7739
  : Array.isArray((params as { minerAuthorities?: string[] })?.minerAuthorities)
7383
7740
  ? ((params as { minerAuthorities?: string[] }).minerAuthorities ?? [])
7384
7741
  : [];
7742
+ const lookupTableAddress = String(
7743
+ (params as { lookupTableAddress?: string })?.lookupTableAddress ?? "",
7744
+ ).trim();
7745
+ const lookupTableCacheKey = `${cycleId}:${pageIndex}`;
7746
+ const effectiveLookupTableAddress =
7747
+ lookupTableAddress || state.settlementPageLookupTables.get(lookupTableCacheKey) || "";
7385
7748
  const request = state.client.buildDistributeCyclePageRequest({
7386
7749
  cycleId,
7387
7750
  pageIndex,
@@ -7390,13 +7753,28 @@ const satMiningPlugin = {
7390
7753
  const submitted = await submitSatDistributeCyclePage(state.activeConfig, {
7391
7754
  ...request.params,
7392
7755
  minerCycleAccounts,
7756
+ ...(effectiveLookupTableAddress
7757
+ ? { lookupTableAddress: effectiveLookupTableAddress }
7758
+ : {}),
7393
7759
  });
7760
+ if (submitted.lookupTableAddress) {
7761
+ state.settlementPageLookupTables.set(lookupTableCacheKey, submitted.lookupTableAddress);
7762
+ }
7394
7763
  markActionSuccess("distributeCyclePage", submitted.txHash, cycleId);
7395
7764
  await persistRecentActions();
7396
7765
  respond(
7397
7766
  true,
7398
7767
  jsonOk({
7399
- request: { ...request, params: { ...request.params, minerCycleAccounts } },
7768
+ request: {
7769
+ ...request,
7770
+ params: {
7771
+ ...request.params,
7772
+ minerCycleAccounts,
7773
+ ...(submitted.lookupTableAddress
7774
+ ? { lookupTableAddress: submitted.lookupTableAddress }
7775
+ : {}),
7776
+ },
7777
+ },
7400
7778
  submitted,
7401
7779
  }),
7402
7780
  );
@@ -7406,20 +7784,68 @@ const satMiningPlugin = {
7406
7784
  }
7407
7785
  });
7408
7786
 
7409
- api.registerGatewayMethod("sat.claimCycleRewards", async ({ params, respond }) => {
7787
+ registerSatSubmissionMethod(
7788
+ "sat.cleanupDistributionLookupTable",
7789
+ async ({ params, respond }) => {
7790
+ const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7791
+ try {
7792
+ const pageIndex = Number((params as { pageIndex?: number })?.pageIndex ?? 0);
7793
+ const action = String((params as { action?: string })?.action ?? "").trim();
7794
+ if (action !== "deactivate" && action !== "close") {
7795
+ throw new Error("SAT lookup-table cleanup action must be deactivate or close");
7796
+ }
7797
+ const cacheKey = `${cycleId}:${pageIndex}`;
7798
+ const lookupTableAddress =
7799
+ String((params as { lookupTableAddress?: string })?.lookupTableAddress ?? "").trim() ||
7800
+ state.settlementPageLookupTables.get(cacheKey) ||
7801
+ "";
7802
+ if (!lookupTableAddress) {
7803
+ throw new Error(`SAT distribution lookup table is unknown for ${cacheKey}`);
7804
+ }
7805
+ const submitted = await submitSatCleanupDistributionLookupTable(state.activeConfig, {
7806
+ lookupTableAddress,
7807
+ action,
7808
+ });
7809
+ if (action === "close") {
7810
+ state.settlementPageLookupTables.delete(cacheKey);
7811
+ } else {
7812
+ state.settlementPageLookupTables.set(cacheKey, lookupTableAddress);
7813
+ }
7814
+ markActionSuccess(
7815
+ "cleanupDistributionLookupTable",
7816
+ submitted.transactionHashes.at(-1),
7817
+ cycleId,
7818
+ );
7819
+ await persistRecentActions();
7820
+ respond(
7821
+ true,
7822
+ jsonOk({
7823
+ request: { cycleId, pageIndex, action, lookupTableAddress },
7824
+ submitted,
7825
+ }),
7826
+ );
7827
+ } catch (error) {
7828
+ markActionFailure("cleanupDistributionLookupTable", error, cycleId);
7829
+ respondGatewayError(respond, error);
7830
+ }
7831
+ },
7832
+ );
7833
+
7834
+ registerSatSubmissionMethod("sat.claimCycleRewards", async ({ params, respond }) => {
7410
7835
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7411
7836
  try {
7412
7837
  const request = state.client.buildClaimCycleRewardsRequest({ cycleId });
7413
7838
  const submitted = await submitSatClaimCycleRewards(state.activeConfig, request.params);
7414
- if (Number.isFinite(cycleId) && cycleId >= 0) {
7415
- const execution = getOrCreateRoundExecutionState(state, cycleId, 0);
7416
- execution.claimSubmitted = true;
7417
- }
7418
- markSatClaimBacklogClaimed(state, [cycleId], submitted.txHash);
7419
- markActionSuccess("claimCycleRewards", submitted.txHash, cycleId);
7839
+ const completion = await resolveClaimCompletion([cycleId]);
7840
+ applyClaimCompletion({
7841
+ action: "claimCycleRewards",
7842
+ txHash: submitted.txHash,
7843
+ cycleIds: [cycleId],
7844
+ ...completion,
7845
+ });
7420
7846
  await persistRecentActions();
7421
- void capturePlannerOutcomesForCycles([cycleId], submitted.txHash);
7422
- respond(true, jsonOk({ request, submitted }));
7847
+ void capturePlannerOutcomesForCycles(completion.resolvedCycleIds, submitted.txHash);
7848
+ respond(true, jsonOk({ request, submitted, ...completion }));
7423
7849
  } catch (error) {
7424
7850
  markSatClaimBacklogFailure(state, [cycleId], error);
7425
7851
  markActionFailure("claimCycleRewards", error, cycleId);
@@ -7427,7 +7853,7 @@ const satMiningPlugin = {
7427
7853
  }
7428
7854
  });
7429
7855
 
7430
- api.registerGatewayMethod("sat.claimCycleRewardsBatch", async ({ params, respond }) => {
7856
+ registerSatSubmissionMethod("sat.claimCycleRewardsBatch", async ({ params, respond }) => {
7431
7857
  const cycleIds = Array.isArray((params as { cycleIds?: number[] })?.cycleIds)
7432
7858
  ? ((params as { cycleIds?: number[] }).cycleIds ?? [])
7433
7859
  .map((value) => Number(value))
@@ -7437,15 +7863,16 @@ const satMiningPlugin = {
7437
7863
  try {
7438
7864
  markSatClaimBacklogReady(state, cycleIds, "manual claim batch action");
7439
7865
  const submitted = await submitSatClaimCycleRewardsBatch(state.activeConfig, request.params);
7440
- for (const cycleId of cycleIds) {
7441
- const execution = getOrCreateRoundExecutionState(state, cycleId, 0);
7442
- execution.claimSubmitted = true;
7443
- }
7444
- markSatClaimBacklogClaimed(state, cycleIds, submitted.txHash);
7445
- markBatchActionSuccess("claimCycleRewardsBatch", submitted.txHash, cycleIds);
7866
+ const completion = await resolveClaimCompletion(cycleIds);
7867
+ applyClaimCompletion({
7868
+ action: "claimCycleRewardsBatch",
7869
+ txHash: submitted.txHash,
7870
+ cycleIds,
7871
+ ...completion,
7872
+ });
7446
7873
  await persistRecentActions();
7447
- void capturePlannerOutcomesForCycles(cycleIds, submitted.txHash);
7448
- respond(true, jsonOk({ request, submitted }));
7874
+ void capturePlannerOutcomesForCycles(completion.resolvedCycleIds, submitted.txHash);
7875
+ respond(true, jsonOk({ request, submitted, ...completion }));
7449
7876
  } catch (error) {
7450
7877
  if (cycleIds.length > 0 && isInvalidAccountOwnerError(error)) {
7451
7878
  const resolvedCycleIds = await resolveClaimBatchInvalidOwnerCycles(cycleIds);
@@ -7492,7 +7919,7 @@ const satMiningPlugin = {
7492
7919
  }
7493
7920
  });
7494
7921
 
7495
- api.registerGatewayMethod("sat.claimBacklog", async ({ respond }) => {
7922
+ registerSatSubmissionMethod("sat.claimBacklog", async ({ respond }) => {
7496
7923
  const batchCycles = resolveSatClaimBatchCycles(state.activeConfig);
7497
7924
  const cycleIds = collectReadySatClaimBacklogCycleIds(state, batchCycles);
7498
7925
  const request = state.client.buildClaimCycleRewardsBatchRequest({ cycleIds });
@@ -7512,19 +7939,21 @@ const satMiningPlugin = {
7512
7939
  }
7513
7940
  markSatClaimBacklogReady(state, cycleIds, "manual claim backlog action");
7514
7941
  const submitted = await submitSatClaimCycleRewardsBatch(state.activeConfig, request.params);
7515
- for (const cycleId of cycleIds) {
7516
- const execution = getOrCreateRoundExecutionState(state, cycleId, 0);
7517
- execution.claimSubmitted = true;
7518
- }
7519
- markSatClaimBacklogClaimed(state, cycleIds, submitted.txHash);
7520
- markBatchActionSuccess("claimCycleRewardsBatch", submitted.txHash, cycleIds);
7942
+ const completion = await resolveClaimCompletion(cycleIds);
7943
+ applyClaimCompletion({
7944
+ action: "claimCycleRewardsBatch",
7945
+ txHash: submitted.txHash,
7946
+ cycleIds,
7947
+ ...completion,
7948
+ });
7521
7949
  await persistRecentActions();
7522
- void capturePlannerOutcomesForCycles(cycleIds, submitted.txHash);
7950
+ void capturePlannerOutcomesForCycles(completion.resolvedCycleIds, submitted.txHash);
7523
7951
  respond(
7524
7952
  true,
7525
7953
  jsonOk({
7526
7954
  request,
7527
7955
  submitted,
7956
+ ...completion,
7528
7957
  claimBacklog: buildSatClaimBacklogSummary(state),
7529
7958
  }),
7530
7959
  );
@@ -7535,7 +7964,7 @@ const satMiningPlugin = {
7535
7964
  }
7536
7965
  });
7537
7966
 
7538
- api.registerGatewayMethod("sat.retargetUnlock", async ({ params, respond }) => {
7967
+ registerSatSubmissionMethod("sat.retargetUnlock", async ({ params, respond }) => {
7539
7968
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7540
7969
  try {
7541
7970
  const request = state.client.buildRetargetUnlockRequest({ cycleId });
@@ -7548,7 +7977,7 @@ const satMiningPlugin = {
7548
7977
  }
7549
7978
  });
7550
7979
 
7551
- api.registerGatewayMethod("sat.closeResolvedCycleAccounts", async ({ params, respond }) => {
7980
+ registerSatSubmissionMethod("sat.closeResolvedCycleAccounts", async ({ params, respond }) => {
7552
7981
  const cycleId = Number((params as { cycleId?: number })?.cycleId ?? 0);
7553
7982
  try {
7554
7983
  const result = await closeResolvedExactCycleAccounts(cycleId);
@@ -7580,7 +8009,7 @@ const satMiningPlugin = {
7580
8009
  }
7581
8010
  });
7582
8011
 
7583
- api.registerGatewayMethod("sat.compactPendingCycleRange", async ({ params, respond }) => {
8012
+ registerSatSubmissionMethod("sat.compactPendingCycleRange", async ({ params, respond }) => {
7584
8013
  try {
7585
8014
  const maxFrontCycles =
7586
8015
  typeof (params as { maxFrontCycles?: number })?.maxFrontCycles === "number"
@@ -7695,7 +8124,7 @@ const satMiningPlugin = {
7695
8124
  respond(true, jsonOk(await Promise.resolve(readProfile())));
7696
8125
  });
7697
8126
 
7698
- api.registerGatewayMethod("sat.setMinerProfile", async ({ params, respond }) => {
8127
+ registerSatSubmissionMethod("sat.setMinerProfile", async ({ params, respond }) => {
7699
8128
  try {
7700
8129
  const request =
7701
8130
  params && typeof params === "object" && !Array.isArray(params)
@@ -7965,10 +8394,14 @@ const satMiningPlugin = {
7965
8394
  ) {
7966
8395
  return;
7967
8396
  }
7968
- const compacted = await compactPendingCycleRange({
7969
- maxFrontCycles: SAT_PENDING_RANGE_COMPACT_CHUNK_CYCLES,
7970
- maxBackCycles: SAT_PENDING_RANGE_COMPACT_CHUNK_CYCLES,
7971
- }).catch(() => null);
8397
+ const compacted = await runWithSatSubmissionWorkflow(
8398
+ `startup:compact-pending:${authority}:${firstPendingCycleId}:${lastPendingCycleId}`,
8399
+ async () =>
8400
+ await compactPendingCycleRange({
8401
+ maxFrontCycles: SAT_PENDING_RANGE_COMPACT_CHUNK_CYCLES,
8402
+ maxBackCycles: SAT_PENDING_RANGE_COMPACT_CHUNK_CYCLES,
8403
+ }),
8404
+ ).catch(() => null);
7972
8405
  if (compacted?.compacted) {
7973
8406
  api.logger.info(
7974
8407
  `[sat-mining] compacted stale pending range during startup for wallet ${authority}`,
@@ -8081,7 +8514,7 @@ const satMiningPlugin = {
8081
8514
  }, 10_000);
8082
8515
  };
8083
8516
 
8084
- api.registerGatewayMethod("sat.startMining", async ({ params, respond }) => {
8517
+ registerSatSubmissionMethod("sat.startMining", async ({ params, respond }) => {
8085
8518
  try {
8086
8519
  if (state.activeConfig.network === "mainnet-beta") {
8087
8520
  const syncStatus = await getSatMainnetSyncStatus();
@@ -8210,7 +8643,7 @@ const satMiningPlugin = {
8210
8643
  }
8211
8644
  });
8212
8645
 
8213
- api.registerGatewayMethod("sat.stopMining", async ({ respond }) => {
8646
+ registerSatSubmissionMethod("sat.stopMining", async ({ params: _params, respond }) => {
8214
8647
  try {
8215
8648
  const authority = await resolveSatCapitalActionAuthority().catch(
8216
8649
  () => state.activeWalletAddress ?? "",
@@ -8344,7 +8777,7 @@ const satMiningPlugin = {
8344
8777
  }
8345
8778
  });
8346
8779
 
8347
- api.registerGatewayMethod("sat.resolveDispute", async ({ params, respond }) => {
8780
+ registerSatSubmissionMethod("sat.resolveDispute", async ({ params, respond }) => {
8348
8781
  try {
8349
8782
  const request = state.client.buildResolveDisputeRequest({
8350
8783
  disputeAuthority: String(
@@ -8364,7 +8797,7 @@ const satMiningPlugin = {
8364
8797
  }
8365
8798
  });
8366
8799
 
8367
- api.registerGatewayMethod("sat.republishEpochRoots", async ({ params, respond }) => {
8800
+ registerSatSubmissionMethod("sat.republishEpochRoots", async ({ params, respond }) => {
8368
8801
  try {
8369
8802
  const request = state.client.buildRepublishEpochRootsRequest({
8370
8803
  epochId: Number((params as { epochId?: number })?.epochId ?? 0),
@@ -8483,7 +8916,7 @@ const satMiningPlugin = {
8483
8916
  }
8484
8917
  });
8485
8918
 
8486
- api.registerGatewayMethod("sat.submitValidatorAttestation", async ({ params, respond }) => {
8919
+ registerSatSubmissionMethod("sat.submitValidatorAttestation", async ({ params, respond }) => {
8487
8920
  try {
8488
8921
  const request = state.client.buildSubmitValidatorAttestationRequest({
8489
8922
  targetAuthority: String((params as { targetAuthority?: string })?.targetAuthority ?? ""),
@@ -8516,7 +8949,7 @@ const satMiningPlugin = {
8516
8949
  }
8517
8950
  });
8518
8951
 
8519
- api.registerGatewayMethod("sat.openDispute", async ({ params, respond }) => {
8952
+ registerSatSubmissionMethod("sat.openDispute", async ({ params, respond }) => {
8520
8953
  try {
8521
8954
  const request = state.client.buildOpenDisputeRequest({
8522
8955
  targetAuthority: String((params as { targetAuthority?: string })?.targetAuthority ?? ""),