@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
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import http from "node:http";
3
3
  import https from "node:https";
4
4
  import { createRequire } from "node:module";
5
- import { redactSensitiveUrlLikeString } from "fased/plugin-sdk";
5
+ import { fetchWithSsrFGuard, redactSensitiveUrlLikeString } from "fased/plugin-sdk";
6
6
  import {
7
7
  loadConfig,
8
8
  loadWalletProviderSecret,
@@ -14,6 +14,7 @@ import {
14
14
  type FasedAgentConfig,
15
15
  } from "fased/plugin-sdk/sat-runtime";
16
16
  import type { SatMiningConfig } from "./config.js";
17
+ import { resolveSatGenesisProfileContract, SAT_PROTOCOL_CONSTANTS } from "./protocol-contract.js";
17
18
  import {
18
19
  loadSatBondLayout,
19
20
  loadSatBondPolicyLayout,
@@ -32,6 +33,7 @@ const SAT_DISPUTE_SEED = "sat_dispute";
32
33
  const MINING_STAKE_SEED = "mining_stake";
33
34
  const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
34
35
  const ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
36
+ const ADDRESS_LOOKUP_TABLE_PROGRAM_ID = "AddressLookupTab1e1111111111111111111111111";
35
37
 
36
38
  function assertDedicatedBondProgramConfigured(env: NodeJS.ProcessEnv = process.env): void {
37
39
  const resolved = resolveSatBondProgramIdFromEnv(env);
@@ -225,6 +227,21 @@ export type SatCycleView = {
225
227
  openTs: number;
226
228
  closeTs: number;
227
229
  status: number;
230
+ cycleSeed?: string;
231
+ entropyUnavailable?: boolean;
232
+ commitDeadlineTs?: number;
233
+ revealDeadlineTs?: number;
234
+ entropyTargetSlot?: number;
235
+ openSlot?: number;
236
+ commitDeadlineSlot?: number;
237
+ revealDeadlineSlot?: number;
238
+ entropyHashCount?: number;
239
+ unlockIntervalStartCycleId?: number;
240
+ committedMinerCount?: string;
241
+ revealedMinerCount?: string;
242
+ resolvedCommitCount?: string;
243
+ releasedCommitCount?: string;
244
+ entropySealedSlot?: number;
228
245
  unlockTargetLamports: string;
229
246
  totalCommittedLamports: string;
230
247
  validMinerCount: string;
@@ -258,6 +275,10 @@ export type SatMinerCycleView = {
258
275
  claimedPerfRebateLamports: string;
259
276
  validParticipation: boolean;
260
277
  capitalLockReleased?: boolean;
278
+ commitment?: string;
279
+ commitSlot?: number;
280
+ revealSlot?: number;
281
+ lockedCollateralLamports?: string;
261
282
  };
262
283
 
263
284
  export type SatMinerCapitalView = {
@@ -320,6 +341,8 @@ export type SatBondStakingDistributorView = {
320
341
  totalActiveStakeRaw: string;
321
342
  rewardIndexFp: string;
322
343
  observedRewardVaultRaw: string;
344
+ unallocatedRewardRaw: string;
345
+ fractionalRemainderFp: string;
323
346
  rewardVaultBalanceRaw?: string;
324
347
  lastSyncedSlot: number;
325
348
  mintMatchesRuntime: boolean;
@@ -338,6 +361,7 @@ export type SatBondStakingPositionView = {
338
361
  activeStakeRaw: string;
339
362
  claimableRewardRaw: string;
340
363
  rewardDebtFp: string;
364
+ fractionalRemainderFp: string;
341
365
  lastSyncedSlot: number;
342
366
  };
343
367
 
@@ -376,6 +400,7 @@ export type SatCycleSettlementProgressV2View = {
376
400
  scoreExclusiveUntilSlot?: number | undefined;
377
401
  distributeExclusiveUntilSlot?: number | undefined;
378
402
  keeperBountyPaidLamports?: string | undefined;
403
+ keeperBountyUnpaidLamports?: string | undefined;
379
404
  };
380
405
 
381
406
  export type SatTreasuryStateView = {
@@ -398,6 +423,7 @@ export type SatPayoutReadinessView = {
398
423
  export type SatMiningStatusAccountsView = {
399
424
  globalState: SatGlobalStateView | null;
400
425
  currentCycle: SatCycleView | null;
426
+ currentSettlementProgress: SatCycleSettlementProgressV2View | null;
401
427
  currentMinerCycle: SatMinerCycleView | null;
402
428
  claimMinerCycle: SatMinerCycleView | null;
403
429
  minerCapital: SatMinerCapitalView | null;
@@ -800,17 +826,21 @@ export function decodeSatGlobalState(data: Buffer, address: string): SatGlobalSt
800
826
  };
801
827
  }
802
828
 
803
- function decodeSatCycle(data: Buffer, address: string): SatCycleView {
829
+ export function decodeSatCycle(data: Buffer, address: string): SatCycleView {
804
830
  const body = expectAccountData(data, ACCOUNT_DISCRIMINATOR.satCycleState, "SAT cycle state");
831
+ const validMinerCount = readU64String(body, 192);
832
+ const cycleSeed = readHash32(body, 40);
805
833
  return {
806
834
  address,
807
835
  cycleId: readU64Number(body, 0),
808
836
  openTs: readI64Number(body, 8),
809
837
  closeTs: readI64Number(body, 16),
810
838
  status: body.readUInt8(24),
839
+ cycleSeed,
840
+ entropyUnavailable: cycleSeed === SAT_PROTOCOL_CONSTANTS.entropyUnavailableSeedHex,
811
841
  unlockTargetLamports: readU64String(body, 176),
812
842
  totalCommittedLamports: readU64String(body, 184),
813
- validMinerCount: readU64String(body, 192),
843
+ validMinerCount,
814
844
  unlockRatioFp: readU64String(body, 200),
815
845
  issuedCycleMinerSatRaw: readU64String(body, 208),
816
846
  unissuedCycleMinerSatRaw: readU64String(body, 216),
@@ -820,6 +850,23 @@ function decodeSatCycle(data: Buffer, address: string): SatCycleView {
820
850
  treasurySolLamports: readU64String(body, 248),
821
851
  submittedSolErosionPoolLamports: readU64String(body, 256),
822
852
  keeperBountyPaidLamports: readU64String(body, 264),
853
+ commitDeadlineTs: readI64Number(body, 272),
854
+ revealDeadlineTs: readI64Number(body, 280),
855
+ entropyTargetSlot: readU64Number(body, 288),
856
+ committedMinerCount: readU64String(body, 296),
857
+ revealedMinerCount: validMinerCount,
858
+ resolvedCommitCount: readU64String(body, 304),
859
+ entropySealedSlot: readU64Number(body, 312),
860
+ ...(body.length >= 368
861
+ ? {
862
+ openSlot: readU64Number(body, 320),
863
+ commitDeadlineSlot: readU64Number(body, 328),
864
+ revealDeadlineSlot: readU64Number(body, 336),
865
+ entropyHashCount: readU64Number(body, 344),
866
+ unlockIntervalStartCycleId: readU64Number(body, 352),
867
+ releasedCommitCount: readU64String(body, 360),
868
+ }
869
+ : {}),
823
870
  };
824
871
  }
825
872
 
@@ -848,6 +895,18 @@ export function decodeSatMinerCycle(data: Buffer, address: string): SatMinerCycl
848
895
  claimedPerfRebateLamports: readU64String(body, 168),
849
896
  validParticipation: body.readUInt8(176) === 1,
850
897
  capitalLockReleased: body.readUInt8(177) === 1,
898
+ ...(body.length >= 336
899
+ ? {
900
+ commitment: readHash32(body, 184),
901
+ commitSlot: readU64Number(body, 216),
902
+ revealSlot: readU64Number(body, 224),
903
+ }
904
+ : {}),
905
+ ...(body.length >= 344
906
+ ? {
907
+ lockedCollateralLamports: readU64String(body, 232),
908
+ }
909
+ : {}),
851
910
  };
852
911
  }
853
912
 
@@ -969,7 +1028,7 @@ function decodeSatBondTierPolicy(data: Buffer, address: string): SatBondTierPoli
969
1028
  };
970
1029
  }
971
1030
 
972
- function decodeSatBondStakingDistributor(
1031
+ export function decodeSatBondStakingDistributor(
973
1032
  data: Buffer,
974
1033
  address: string,
975
1034
  ): SatBondStakingDistributorView {
@@ -999,6 +1058,8 @@ function decodeSatBondStakingDistributor(
999
1058
  totalActiveStakeRaw: readU64String(body, layout.offsets.totalActiveStakeRaw),
1000
1059
  rewardIndexFp: readU128String(body, layout.offsets.rewardIndexFp),
1001
1060
  observedRewardVaultRaw: readU64String(body, layout.offsets.observedRewardVaultRaw),
1061
+ unallocatedRewardRaw: readU64String(body, layout.offsets.unallocatedRewardRaw),
1062
+ fractionalRemainderFp: readU64String(body, layout.offsets.fractionalRemainderFp),
1002
1063
  lastSyncedSlot: readU64Number(body, layout.offsets.lastSyncedSlot),
1003
1064
  mintMatchesRuntime: rewardMint === SAT_MINT_ADDRESS(),
1004
1065
  vaultMatchesExpected: rewardVault === expectedRewardVault,
@@ -1021,6 +1082,7 @@ function decodeSatBondStakingPosition(data: Buffer, address: string): SatBondSta
1021
1082
  activeStakeRaw: readU64String(body, layout.offsets.activeStakeRaw),
1022
1083
  claimableRewardRaw: readU64String(body, layout.offsets.claimableRewardRaw),
1023
1084
  rewardDebtFp: readU128String(body, layout.offsets.rewardDebtFp),
1085
+ fractionalRemainderFp: readU64String(body, layout.offsets.fractionalRemainderFp),
1024
1086
  lastSyncedSlot: readU64Number(body, layout.offsets.lastSyncedSlot),
1025
1087
  };
1026
1088
  }
@@ -1068,7 +1130,7 @@ export function decodeSatCycleRegistryPage(
1068
1130
  };
1069
1131
  }
1070
1132
 
1071
- function decodeSatCycleSettlementProgressV2(
1133
+ export function decodeSatCycleSettlementProgressV2(
1072
1134
  data: Buffer,
1073
1135
  address: string,
1074
1136
  ): SatCycleSettlementProgressV2View {
@@ -1094,6 +1156,7 @@ function decodeSatCycleSettlementProgressV2(
1094
1156
  scoreExclusiveUntilSlot: readU64Number(body, 992),
1095
1157
  distributeExclusiveUntilSlot: readU64Number(body, 1000),
1096
1158
  keeperBountyPaidLamports: readU64String(body, 1008),
1159
+ keeperBountyUnpaidLamports: readU64String(body, 1016),
1097
1160
  };
1098
1161
  }
1099
1162
 
@@ -1336,6 +1399,15 @@ type SatReadRpcRuntimeState = {
1336
1399
  quotaLikely: boolean;
1337
1400
  };
1338
1401
 
1402
+ type SatReadRpcEndpointState = {
1403
+ consecutiveFailures: number;
1404
+ backoffUntilMs: number;
1405
+ quotaLikely: boolean;
1406
+ lastError: string | null;
1407
+ lastFailureAt: string | null;
1408
+ lastSuccessAt: string | null;
1409
+ };
1410
+
1339
1411
  type SatRpcMethodBucket = {
1340
1412
  requests: number;
1341
1413
  successes: number;
@@ -1372,6 +1444,7 @@ const satReadRpcRuntimeState: SatReadRpcRuntimeState = {
1372
1444
  lastRpcUrl: null,
1373
1445
  quotaLikely: false,
1374
1446
  };
1447
+ const satReadRpcEndpointStates = new Map<string, SatReadRpcEndpointState>();
1375
1448
 
1376
1449
  type SatReadConnectionLike = {
1377
1450
  rpcEndpoint: string;
@@ -1416,6 +1489,14 @@ const SAT_RPC_RENT_EXEMPTION_CACHE_TTL_MS = 5 * 60_000;
1416
1489
  const SAT_RPC_METHOD_METRIC_BUCKET_MS = 60 * 60_000;
1417
1490
  const SAT_RPC_METHOD_METRIC_RETENTION_MS = 24 * 60 * 60_000;
1418
1491
  const SAT_RPC_QUOTA_BACKOFF_MS = 30_000;
1492
+ const SAT_RPC_FAILURE_BACKOFF_THRESHOLD = 2;
1493
+ const SAT_RPC_FAILURE_BACKOFF_BASE_MS = 5_000;
1494
+ const SAT_RPC_FAILURE_BACKOFF_MAX_MS = 30_000;
1495
+ const SAT_RPC_MAX_RESPONSE_BYTES = 16 * 1024 * 1024;
1496
+
1497
+ function satRpcRequestTimeoutMs(): number {
1498
+ return readPositiveIntEnv("FASED_SAT_RPC_REQUEST_TIMEOUT_MS", 10_000);
1499
+ }
1419
1500
 
1420
1501
  const satRpcReadCache = new Map<string, { expiresAt: number; value: unknown }>();
1421
1502
  const satRpcReadInFlight = new Map<string, Promise<unknown>>();
@@ -1604,41 +1685,86 @@ function looksLikeRpcQuotaFailure(value: unknown): boolean {
1604
1685
  );
1605
1686
  }
1606
1687
 
1607
- function currentReadRpcQuotaBackoffMs(nowMs = Date.now()): number {
1608
- if (!satReadRpcRuntimeState.quotaLikely || !satReadRpcRuntimeState.lastFailureAt) {
1609
- return 0;
1688
+ function getOrCreateReadRpcEndpointState(rpcUrl: string): SatReadRpcEndpointState {
1689
+ const key = normalizeRpcUrlForComparison(rpcUrl);
1690
+ const existing = satReadRpcEndpointStates.get(key);
1691
+ if (existing) {
1692
+ return existing;
1610
1693
  }
1611
- const failedAtMs = Date.parse(satReadRpcRuntimeState.lastFailureAt);
1612
- if (!Number.isFinite(failedAtMs)) {
1694
+ const created: SatReadRpcEndpointState = {
1695
+ consecutiveFailures: 0,
1696
+ backoffUntilMs: 0,
1697
+ quotaLikely: false,
1698
+ lastError: null,
1699
+ lastFailureAt: null,
1700
+ lastSuccessAt: null,
1701
+ };
1702
+ satReadRpcEndpointStates.set(key, created);
1703
+ return created;
1704
+ }
1705
+
1706
+ function currentReadRpcBackoffMs(rpcUrl: string, nowMs = Date.now()): number {
1707
+ const state = satReadRpcEndpointStates.get(normalizeRpcUrlForComparison(rpcUrl));
1708
+ if (!state) {
1613
1709
  return 0;
1614
1710
  }
1615
- const remainingMs = SAT_RPC_QUOTA_BACKOFF_MS - (nowMs - failedAtMs);
1616
- return remainingMs > 0 ? remainingMs : 0;
1711
+ return Math.max(0, state.backoffUntilMs - nowMs);
1617
1712
  }
1618
1713
 
1619
- function makeReadRpcQuotaBackoffError(method: string, remainingMs: number): Error {
1714
+ function makeReadRpcBackoffError(method: string, remainingMs: number): Error {
1620
1715
  return new Error(
1621
- `rpc ${method} skipped during provider quota backoff; retry in ${Math.ceil(remainingMs / 1000)}s`,
1716
+ `rpc ${method} skipped during endpoint circuit backoff; retry in ${Math.ceil(remainingMs / 1000)}s`,
1622
1717
  );
1623
1718
  }
1624
1719
 
1720
+ function markReadRpcEndpointSuccess(rpcUrl: string) {
1721
+ const state = getOrCreateReadRpcEndpointState(rpcUrl);
1722
+ state.consecutiveFailures = 0;
1723
+ state.backoffUntilMs = 0;
1724
+ state.quotaLikely = false;
1725
+ state.lastError = null;
1726
+ state.lastSuccessAt = new Date().toISOString();
1727
+ }
1728
+
1729
+ function markReadRpcEndpointFailure(rpcUrl: string, error: unknown) {
1730
+ const state = getOrCreateReadRpcEndpointState(rpcUrl);
1731
+ const message = error instanceof Error ? error.message : String(error);
1732
+ const quotaLikely = looksLikeRpcQuotaFailure(message);
1733
+ state.consecutiveFailures += 1;
1734
+ state.quotaLikely = quotaLikely;
1735
+ state.lastError = message;
1736
+ state.lastFailureAt = new Date().toISOString();
1737
+ if (quotaLikely) {
1738
+ state.backoffUntilMs = Date.now() + SAT_RPC_QUOTA_BACKOFF_MS;
1739
+ } else if (state.consecutiveFailures >= SAT_RPC_FAILURE_BACKOFF_THRESHOLD) {
1740
+ const exponent = state.consecutiveFailures - SAT_RPC_FAILURE_BACKOFF_THRESHOLD;
1741
+ state.backoffUntilMs =
1742
+ Date.now() +
1743
+ Math.min(SAT_RPC_FAILURE_BACKOFF_MAX_MS, SAT_RPC_FAILURE_BACKOFF_BASE_MS * 2 ** exponent);
1744
+ }
1745
+ }
1746
+
1625
1747
  function markReadRpcSuccess(mode: "primary" | "fallback", rpcUrl: string) {
1748
+ markReadRpcEndpointSuccess(rpcUrl);
1626
1749
  satReadRpcRuntimeState.lastMode = mode;
1627
1750
  satReadRpcRuntimeState.lastRpcUrl = rpcUrl;
1628
- satReadRpcRuntimeState.lastError = null;
1629
1751
  satReadRpcRuntimeState.lastSuccessAt = new Date().toISOString();
1630
- satReadRpcRuntimeState.quotaLikely = false;
1631
- if (mode === "fallback") {
1752
+ if (mode === "primary") {
1753
+ satReadRpcRuntimeState.lastError = null;
1754
+ satReadRpcRuntimeState.quotaLikely = false;
1755
+ } else {
1632
1756
  satReadRpcRuntimeState.fallbackCount += 1;
1633
1757
  }
1634
1758
  }
1635
1759
 
1636
- function markReadRpcFailure(error: unknown) {
1760
+ function markReadRpcFailure(error: unknown, rpcUrl: string) {
1637
1761
  const message = error instanceof Error ? error.message : String(error);
1762
+ markReadRpcEndpointFailure(rpcUrl, error);
1638
1763
  satReadRpcRuntimeState.lastMode = "unavailable";
1639
1764
  satReadRpcRuntimeState.lastError = message;
1640
1765
  satReadRpcRuntimeState.lastFailureAt = new Date().toISOString();
1641
- satReadRpcRuntimeState.quotaLikely = looksLikeRpcQuotaFailure(message);
1766
+ satReadRpcRuntimeState.quotaLikely =
1767
+ satReadRpcRuntimeState.quotaLikely || looksLikeRpcQuotaFailure(message);
1642
1768
  }
1643
1769
 
1644
1770
  function firstNonEmpty(...values: Array<string | null | undefined>): string {
@@ -1808,17 +1934,11 @@ function resolveReadRpcConfig(cfg: FasedAgentConfig, env: NodeJS.ProcessEnv): Sa
1808
1934
  ? readWalletProviderRegistry(env).wallets.find((wallet) => wallet.id === walletId)?.providerId
1809
1935
  : undefined;
1810
1936
  const providerId = registryProviderId || resolveWalletProviderId(cfg, env);
1811
- const walletReadRpcUrl =
1812
- walletEnvValue(env, "FASED_WALLET_SOLANA_READ_RPC_URL", walletId) ||
1813
- walletEnvValue(env, "FASED_WALLET_EMBEDDED_KEYSTORE_READ_RPC_URL", walletId);
1814
- const walletRpcUrl =
1815
- walletEnvValue(env, "FASED_WALLET_SOLANA_RPC_URL", walletId) ||
1816
- walletEnvValue(env, "FASED_WALLET_EMBEDDED_KEYSTORE_RPC_URL", walletId);
1937
+ const walletReadRpcUrl = walletEnvValue(env, "FASED_WALLET_SOLANA_READ_RPC_URL", walletId);
1938
+ const walletRpcUrl = walletEnvValue(env, "FASED_WALLET_SOLANA_RPC_URL", walletId);
1817
1939
  const walletReadRpcFallbackUrl =
1818
1940
  walletEnvValue(env, "FASED_WALLET_SOLANA_READ_RPC_FALLBACK_URL", walletId) ||
1819
- walletEnvValue(env, "FASED_WALLET_SOLANA_RPC_FALLBACK_URL", walletId) ||
1820
- walletEnvValue(env, "FASED_WALLET_EMBEDDED_KEYSTORE_READ_RPC_FALLBACK_URL", walletId) ||
1821
- walletEnvValue(env, "FASED_WALLET_EMBEDDED_KEYSTORE_RPC_FALLBACK_URL", walletId);
1941
+ walletEnvValue(env, "FASED_WALLET_SOLANA_RPC_FALLBACK_URL", walletId);
1822
1942
  if (providerId === "local-socket-signer") {
1823
1943
  const primaryUrl = firstNonEmpty(walletReadRpcUrl, walletRpcUrl);
1824
1944
  if (!primaryUrl) {
@@ -1893,68 +2013,146 @@ export function resolveEffectiveReadRpcConfig(): SatReadRpcConfig {
1893
2013
  return resolveReadRpcConfig(cfg, mergedEnv);
1894
2014
  }
1895
2015
 
2016
+ function createAbortableReadRpcFetch(): typeof globalThis.fetch {
2017
+ return (async (input, init) => {
2018
+ const timeoutMs = satRpcRequestTimeoutMs();
2019
+ const requestUrl =
2020
+ typeof input === "string" || input instanceof URL ? input.toString() : input.url;
2021
+ let guardedFetch: Awaited<ReturnType<typeof fetchWithSsrFGuard>>;
2022
+ try {
2023
+ guardedFetch = await fetchWithSsrFGuard({
2024
+ url: requestUrl,
2025
+ init,
2026
+ timeoutMs,
2027
+ signal: init?.signal ?? (input instanceof Request ? input.signal : undefined),
2028
+ policy: { allowPrivateNetwork: true },
2029
+ auditContext: "sat-mining-read-rpc",
2030
+ });
2031
+ } catch (error) {
2032
+ const reason = redactSensitiveUrlLikeString(
2033
+ error instanceof Error ? `${error.name}: ${error.message}` : String(error),
2034
+ );
2035
+ throw new Error(
2036
+ `rpc fetch failed after at most ${timeoutMs}ms (${redactSensitiveUrlLikeString(requestUrl)}): ${reason}`,
2037
+ );
2038
+ }
2039
+ const { response, release } = guardedFetch;
2040
+ try {
2041
+ const body = await response.arrayBuffer();
2042
+ return new Response(body, {
2043
+ headers: response.headers,
2044
+ status: response.status,
2045
+ statusText: response.statusText,
2046
+ });
2047
+ } finally {
2048
+ await release();
2049
+ }
2050
+ }) as typeof globalThis.fetch;
2051
+ }
2052
+
2053
+ async function withReadRpcTimeout<T>(task: Promise<T>, method: string, rpcUrl: string): Promise<T> {
2054
+ const timeoutMs = satRpcRequestTimeoutMs();
2055
+ let timer: NodeJS.Timeout | undefined;
2056
+ try {
2057
+ return await Promise.race([
2058
+ task,
2059
+ new Promise<never>((_resolve, reject) => {
2060
+ timer = setTimeout(
2061
+ () =>
2062
+ reject(
2063
+ new Error(
2064
+ `rpc ${method} timed out after ${timeoutMs}ms (${redactSensitiveUrlLikeString(rpcUrl)})`,
2065
+ ),
2066
+ ),
2067
+ timeoutMs,
2068
+ );
2069
+ timer.unref?.();
2070
+ }),
2071
+ ]);
2072
+ } finally {
2073
+ if (timer) {
2074
+ clearTimeout(timer);
2075
+ }
2076
+ }
2077
+ }
2078
+
1896
2079
  export function createReadConnection(
1897
2080
  solana: SolanaModuleLike,
1898
2081
  rpc: SatReadRpcConfig,
1899
2082
  ): SatReadConnectionLike {
1900
- const primary = new solana.Connection(rpc.primaryUrl);
1901
- const secondary = rpc.secondaryUrl ? new solana.Connection(rpc.secondaryUrl) : null;
2083
+ const primary = new solana.Connection(rpc.primaryUrl, {
2084
+ disableRetryOnRateLimit: true,
2085
+ fetch: createAbortableReadRpcFetch(),
2086
+ });
2087
+ const secondary = rpc.secondaryUrl
2088
+ ? new solana.Connection(rpc.secondaryUrl, {
2089
+ disableRetryOnRateLimit: true,
2090
+ fetch: createAbortableReadRpcFetch(),
2091
+ })
2092
+ : null;
1902
2093
 
1903
2094
  const withFallback = <TMethod extends SatReadMethodName>(
1904
2095
  method: TMethod,
1905
2096
  ): SatReadConnectionLike[TMethod] => {
1906
2097
  return (async (...args: unknown[]): Promise<unknown> => {
1907
- const quotaBackoffMs = currentReadRpcQuotaBackoffMs();
1908
- if (quotaBackoffMs > 0) {
1909
- if (!secondary) {
1910
- throw makeReadRpcQuotaBackoffError(method, quotaBackoffMs);
1911
- }
2098
+ const primaryBackoffMs = currentReadRpcBackoffMs(rpc.primaryUrl);
2099
+ const secondaryBackoffMs = rpc.secondaryUrl ? currentReadRpcBackoffMs(rpc.secondaryUrl) : 0;
2100
+ const callEndpoint = async (
2101
+ connection: InstanceType<SolanaModuleLike["Connection"]>,
2102
+ mode: "primary" | "fallback",
2103
+ rpcUrl: string,
2104
+ ) => {
2105
+ updateSatRpcMethodMetric(method, "request");
1912
2106
  try {
1913
- updateSatRpcMethodMetric(method, "request");
1914
- const result = (await (
1915
- secondary[method] as unknown as (...inner: unknown[]) => Promise<unknown>
1916
- )(...args)) as unknown;
2107
+ const task = (connection[method] as unknown as (...inner: unknown[]) => Promise<unknown>)(
2108
+ ...args,
2109
+ );
2110
+ const result = await withReadRpcTimeout(task, method, rpcUrl);
1917
2111
  updateSatRpcMethodMetric(method, "success");
1918
- markReadRpcSuccess("fallback", rpc.secondaryUrl ?? rpc.primaryUrl);
2112
+ markReadRpcSuccess(mode, rpcUrl);
1919
2113
  return result;
1920
- } catch (secondaryError) {
2114
+ } catch (error) {
1921
2115
  updateSatRpcMethodMetric(method, "failure");
1922
- markReadRpcFailure(secondaryError);
1923
- throw secondaryError;
2116
+ markReadRpcFailure(error, rpcUrl);
2117
+ throw error;
1924
2118
  }
2119
+ };
2120
+ if (primaryBackoffMs > 0) {
2121
+ if (!secondary || !rpc.secondaryUrl || secondaryBackoffMs > 0) {
2122
+ throw makeReadRpcBackoffError(
2123
+ method,
2124
+ Math.min(
2125
+ primaryBackoffMs,
2126
+ secondaryBackoffMs > 0 ? secondaryBackoffMs : primaryBackoffMs,
2127
+ ),
2128
+ );
2129
+ }
2130
+ return await callEndpoint(secondary, "fallback", rpc.secondaryUrl);
1925
2131
  }
1926
2132
  try {
1927
- updateSatRpcMethodMetric(method, "request");
1928
- const result = (await (
1929
- primary[method] as unknown as (...inner: unknown[]) => Promise<unknown>
1930
- )(...args)) as unknown;
1931
- updateSatRpcMethodMetric(method, "success");
1932
- markReadRpcSuccess("primary", rpc.primaryUrl);
1933
- return result;
2133
+ return await callEndpoint(primary, "primary", rpc.primaryUrl);
1934
2134
  } catch (primaryError) {
1935
- updateSatRpcMethodMetric(method, "failure");
1936
- if (!secondary) {
1937
- markReadRpcFailure(primaryError);
2135
+ if (!secondary || !rpc.secondaryUrl) {
1938
2136
  throw primaryError;
1939
2137
  }
2138
+ const fallbackBackoffMs = currentReadRpcBackoffMs(rpc.secondaryUrl);
2139
+ if (fallbackBackoffMs > 0) {
2140
+ throw makeReadRpcBackoffError(method, fallbackBackoffMs);
2141
+ }
1940
2142
  try {
1941
- updateSatRpcMethodMetric(method, "request");
1942
- const result = (await (
1943
- secondary[method] as unknown as (...inner: unknown[]) => Promise<unknown>
1944
- )(...args)) as unknown;
1945
- updateSatRpcMethodMetric(method, "success");
1946
- markReadRpcSuccess("fallback", rpc.secondaryUrl ?? rpc.primaryUrl);
1947
- return result;
2143
+ return await callEndpoint(secondary, "fallback", rpc.secondaryUrl);
1948
2144
  } catch (secondaryError) {
1949
- updateSatRpcMethodMetric(method, "failure");
1950
- markReadRpcFailure(
1951
- new Error(
1952
- `${String(primaryError instanceof Error ? primaryError.message : primaryError)}; ${String(
1953
- secondaryError instanceof Error ? secondaryError.message : secondaryError,
1954
- )}`,
1955
- ),
2145
+ throw new Error(
2146
+ `rpc ${method} failed on primary (${String(
2147
+ redactSensitiveUrlLikeString(
2148
+ primaryError instanceof Error ? primaryError.message : String(primaryError),
2149
+ ),
2150
+ )}) and fallback (${String(
2151
+ redactSensitiveUrlLikeString(
2152
+ secondaryError instanceof Error ? secondaryError.message : String(secondaryError),
2153
+ ),
2154
+ )})`,
1956
2155
  );
1957
- throw secondaryError;
1958
2156
  }
1959
2157
  }
1960
2158
  }) as unknown as SatReadConnectionLike[TMethod];
@@ -2002,13 +2200,27 @@ async function resolveBondProgramContext(env: NodeJS.ProcessEnv) {
2002
2200
  };
2003
2201
  }
2004
2202
 
2005
- const SAT_REGISTRY_RESERVE_TARGET_LAMPORTS = 200_000_000;
2006
- const SAT_PROTOCOL_VAULT_ACCOUNT_SPACE = 0;
2007
- const SAT_CYCLE_STATE_ACCOUNT_SPACE = 336;
2008
- const SAT_CYCLE_REGISTRY_META_ACCOUNT_SPACE = 88;
2009
- const SAT_CYCLE_REGISTRY_PAGE_ACCOUNT_SPACE = 2_072;
2010
- const SAT_CYCLE_SETTLEMENT_PROGRESS_V2_ACCOUNT_SPACE = 1_048;
2011
- const SAT_MINER_CYCLE_ACCOUNT_SPACE = 296;
2203
+ export const SAT_RENT_ACCOUNT_SPACES = {
2204
+ protocolVault: 0,
2205
+ cycleState: 376,
2206
+ cycleRegistryMeta: 88,
2207
+ cycleRegistryPage: 2_072,
2208
+ cycleSettlementProgressV2: 1_048,
2209
+ minerCycle: 352,
2210
+ unlockInterval: 80,
2211
+ } as const;
2212
+
2213
+ export function calculateSatRevealSharedRentLamports(params: {
2214
+ cycleSettlementProgressLamports: number;
2215
+ cycleRegistryPageLamports: number;
2216
+ unlockIntervalLamports: number;
2217
+ }): number {
2218
+ return (
2219
+ params.cycleSettlementProgressLamports +
2220
+ params.cycleRegistryPageLamports +
2221
+ params.unlockIntervalLamports
2222
+ );
2223
+ }
2012
2224
 
2013
2225
  function normalizeReadRpcConfig(rpc: string | SatReadRpcConfig): SatReadRpcConfig {
2014
2226
  return typeof rpc === "string" ? { primaryUrl: rpc, secondaryUrl: null } : rpc;
@@ -2021,6 +2233,14 @@ async function rpcRequestOnce<T>(rpcUrl: string, method: string, params: unknown
2021
2233
  const target = new URL(rpcUrl);
2022
2234
  const transport = target.protocol === "https:" ? https : http;
2023
2235
  const payload = await new Promise<string>((resolve, reject) => {
2236
+ let settled = false;
2237
+ const finishReject = (error: Error) => {
2238
+ if (settled) {
2239
+ return;
2240
+ }
2241
+ settled = true;
2242
+ reject(error);
2243
+ };
2024
2244
  const req = transport.request(
2025
2245
  target,
2026
2246
  {
@@ -2032,20 +2252,38 @@ async function rpcRequestOnce<T>(rpcUrl: string, method: string, params: unknown
2032
2252
  },
2033
2253
  (res) => {
2034
2254
  const chunks: Buffer[] = [];
2035
- res.on("data", (chunk) =>
2036
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)),
2037
- );
2255
+ let responseBytes = 0;
2256
+ res.on("data", (chunk) => {
2257
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
2258
+ responseBytes += buffer.length;
2259
+ if (responseBytes > SAT_RPC_MAX_RESPONSE_BYTES) {
2260
+ req.destroy(new Error(`rpc ${method} response exceeded size limit`));
2261
+ return;
2262
+ }
2263
+ chunks.push(buffer);
2264
+ });
2038
2265
  res.on("end", () => {
2266
+ if (settled) {
2267
+ return;
2268
+ }
2039
2269
  const text = Buffer.concat(chunks).toString("utf8");
2040
2270
  if ((res.statusCode ?? 500) >= 400) {
2041
- reject(new Error(text || `rpc ${method} failed`));
2271
+ finishReject(new Error(text || `rpc ${method} failed`));
2042
2272
  return;
2043
2273
  }
2274
+ settled = true;
2044
2275
  resolve(text);
2045
2276
  });
2046
2277
  },
2047
2278
  );
2048
- req.on("error", reject);
2279
+ req.setTimeout(satRpcRequestTimeoutMs(), () => {
2280
+ req.destroy(
2281
+ new Error(
2282
+ `rpc ${method} timed out after ${satRpcRequestTimeoutMs()}ms (${redactSensitiveUrlLikeString(rpcUrl)})`,
2283
+ ),
2284
+ );
2285
+ });
2286
+ req.on("error", (error) => finishReject(error));
2049
2287
  req.write(body);
2050
2288
  req.end();
2051
2289
  });
@@ -2067,40 +2305,52 @@ async function rpcRequest<T>(
2067
2305
  params: unknown[],
2068
2306
  ): Promise<T> {
2069
2307
  const normalized = normalizeReadRpcConfig(rpc);
2070
- const quotaBackoffMs = currentReadRpcQuotaBackoffMs();
2071
- if (quotaBackoffMs > 0 && !normalized.secondaryUrl) {
2072
- throw makeReadRpcQuotaBackoffError(method, quotaBackoffMs);
2308
+ const primaryBackoffMs = currentReadRpcBackoffMs(normalized.primaryUrl);
2309
+ const secondaryBackoffMs = normalized.secondaryUrl
2310
+ ? currentReadRpcBackoffMs(normalized.secondaryUrl)
2311
+ : 0;
2312
+ if (primaryBackoffMs > 0 && (!normalized.secondaryUrl || secondaryBackoffMs > 0)) {
2313
+ throw makeReadRpcBackoffError(
2314
+ method,
2315
+ Math.min(primaryBackoffMs, secondaryBackoffMs > 0 ? secondaryBackoffMs : primaryBackoffMs),
2316
+ );
2073
2317
  }
2074
- const useFallbackDueToQuota = quotaBackoffMs > 0 && Boolean(normalized.secondaryUrl);
2318
+ const useFallbackDueToBackoff = primaryBackoffMs > 0 && Boolean(normalized.secondaryUrl);
2075
2319
  try {
2076
2320
  const rpcUrl =
2077
- useFallbackDueToQuota && normalized.secondaryUrl
2321
+ useFallbackDueToBackoff && normalized.secondaryUrl
2078
2322
  ? normalized.secondaryUrl
2079
2323
  : normalized.primaryUrl;
2080
2324
  const result = await rpcRequestOnce<T>(rpcUrl, method, params);
2081
2325
  markReadRpcSuccess(
2082
- useFallbackDueToQuota && normalized.secondaryUrl ? "fallback" : "primary",
2326
+ useFallbackDueToBackoff && normalized.secondaryUrl ? "fallback" : "primary",
2083
2327
  rpcUrl,
2084
2328
  );
2085
2329
  return result;
2086
2330
  } catch (primaryError) {
2087
- if (!normalized.secondaryUrl || useFallbackDueToQuota) {
2088
- markReadRpcFailure(primaryError);
2331
+ const failedRpcUrl =
2332
+ useFallbackDueToBackoff && normalized.secondaryUrl
2333
+ ? normalized.secondaryUrl
2334
+ : normalized.primaryUrl;
2335
+ markReadRpcFailure(primaryError, failedRpcUrl);
2336
+ if (!normalized.secondaryUrl || useFallbackDueToBackoff) {
2089
2337
  throw primaryError;
2090
2338
  }
2339
+ const fallbackBackoffMs = currentReadRpcBackoffMs(normalized.secondaryUrl);
2340
+ if (fallbackBackoffMs > 0) {
2341
+ throw makeReadRpcBackoffError(method, fallbackBackoffMs);
2342
+ }
2091
2343
  try {
2092
2344
  const result = await rpcRequestOnce<T>(normalized.secondaryUrl, method, params);
2093
2345
  markReadRpcSuccess("fallback", normalized.secondaryUrl);
2094
2346
  return result;
2095
2347
  } catch (secondaryError) {
2096
- const primaryMessage =
2097
- primaryError instanceof Error ? primaryError.message : String(primaryError);
2098
- const secondaryMessage =
2099
- secondaryError instanceof Error ? secondaryError.message : String(secondaryError);
2100
- markReadRpcFailure(
2101
- new Error(
2102
- `rpc ${method} failed on primary (${primaryMessage}) and fallback (${secondaryMessage})`,
2103
- ),
2348
+ markReadRpcFailure(secondaryError, normalized.secondaryUrl);
2349
+ const primaryMessage = redactSensitiveUrlLikeString(
2350
+ primaryError instanceof Error ? primaryError.message : String(primaryError),
2351
+ );
2352
+ const secondaryMessage = redactSensitiveUrlLikeString(
2353
+ secondaryError instanceof Error ? secondaryError.message : String(secondaryError),
2104
2354
  );
2105
2355
  throw new Error(
2106
2356
  `rpc ${method} failed on primary (${primaryMessage}) and fallback (${secondaryMessage})`,
@@ -2309,6 +2559,37 @@ export async function inspectSatChainSlot(_config: SatMiningConfig): Promise<num
2309
2559
  return await rpcRequest<number>(rpc, "getSlot", []);
2310
2560
  }
2311
2561
 
2562
+ export type SatAddressLookupTableView = {
2563
+ address: string;
2564
+ authority: string | null;
2565
+ addresses: string[];
2566
+ active: boolean;
2567
+ lastExtendedSlot: number;
2568
+ };
2569
+
2570
+ export async function inspectSatAddressLookupTable(
2571
+ _config: SatMiningConfig,
2572
+ params: { address: string },
2573
+ ): Promise<SatAddressLookupTableView | null> {
2574
+ const { solana, connection } = await resolveConnection(process.env);
2575
+ const address = new solana.PublicKey(params.address);
2576
+ const account = await connection.getAccountInfo(address, "confirmed");
2577
+ if (!account) {
2578
+ return null;
2579
+ }
2580
+ if (!account.owner.equals(new solana.PublicKey(ADDRESS_LOOKUP_TABLE_PROGRAM_ID))) {
2581
+ throw new Error("SAT distribution lookup table has the wrong program owner");
2582
+ }
2583
+ const state = solana.AddressLookupTableAccount.deserialize(account.data);
2584
+ return {
2585
+ address: address.toBase58(),
2586
+ authority: state.authority?.toBase58() ?? null,
2587
+ addresses: state.addresses.map((entry) => entry.toBase58()),
2588
+ active: state.deactivationSlot === 18_446_744_073_709_551_615n,
2589
+ lastExtendedSlot: state.lastExtendedSlot,
2590
+ };
2591
+ }
2592
+
2312
2593
  export async function inspectSatLamportBalance(
2313
2594
  _config: SatMiningConfig,
2314
2595
  params: { address: string },
@@ -2580,6 +2861,10 @@ export async function inspectSatMiningStatusAccounts(
2580
2861
  [Buffer.from("sat_cycle_state"), encodeU64(currentCycleId)],
2581
2862
  programId,
2582
2863
  );
2864
+ const [currentSettlementProgressAddress] = solana.PublicKey.findProgramAddressSync(
2865
+ [Buffer.from("sat_cycle_settlement_progress_v2"), encodeU64(currentCycleId)],
2866
+ programId,
2867
+ );
2583
2868
  const [treasuryStateAddress] = solana.PublicKey.findProgramAddressSync(
2584
2869
  [Buffer.from("sat_treasury_state")],
2585
2870
  programId,
@@ -2609,6 +2894,7 @@ export async function inspectSatMiningStatusAccounts(
2609
2894
 
2610
2895
  const coreEntries = [
2611
2896
  ["currentCycle", currentCycleAddress],
2897
+ ["currentSettlementProgress", currentSettlementProgressAddress],
2612
2898
  ["currentMinerCycle", currentMinerCycleAddress],
2613
2899
  ["claimMinerCycle", claimMinerCycleAddress],
2614
2900
  ["minerCapital", minerCapitalAddress],
@@ -2643,6 +2929,7 @@ export async function inspectSatMiningStatusAccounts(
2643
2929
 
2644
2930
  const globalRecord = recordFor(globalAddress);
2645
2931
  const currentCycleRecord = recordFor(currentCycleAddress);
2932
+ const currentSettlementProgressRecord = recordFor(currentSettlementProgressAddress);
2646
2933
  const currentMinerCycleRecord = recordFor(currentMinerCycleAddress);
2647
2934
  const claimMinerCycleRecord = recordFor(claimMinerCycleAddress);
2648
2935
  const minerCapitalRecord = recordFor(minerCapitalAddress);
@@ -2656,6 +2943,12 @@ export async function inspectSatMiningStatusAccounts(
2656
2943
  const currentCycle = currentCycleRecord?.data
2657
2944
  ? decodeSatCycle(currentCycleRecord.data, currentCycleAddress.toBase58())
2658
2945
  : null;
2946
+ const currentSettlementProgress = currentSettlementProgressRecord?.data
2947
+ ? decodeSatCycleSettlementProgressV2(
2948
+ currentSettlementProgressRecord.data,
2949
+ currentSettlementProgressAddress.toBase58(),
2950
+ )
2951
+ : null;
2659
2952
  const currentMinerCycle = currentMinerCycleRecord?.data
2660
2953
  ? decodeSatMinerCycle(currentMinerCycleRecord.data, currentMinerCycleAddress?.toBase58() ?? "")
2661
2954
  : null;
@@ -2690,6 +2983,11 @@ export async function inspectSatMiningStatusAccounts(
2690
2983
  SAT_RPC_LIVE_VIEW_CACHE_TTL_MS,
2691
2984
  currentCycle,
2692
2985
  );
2986
+ writeRpcCacheValue(
2987
+ `view:settlement-progress:${rpcCacheScope(rpc)}:${currentCycleId}`,
2988
+ SAT_RPC_LIVE_VIEW_CACHE_TTL_MS,
2989
+ currentSettlementProgress,
2990
+ );
2693
2991
  if (owner && currentMinerCycleAddress) {
2694
2992
  writeRpcCacheValue(
2695
2993
  `view:miner-cycle:${rpcCacheScope(rpc)}:${authority}:${currentCycleId}`,
@@ -2727,6 +3025,7 @@ export async function inspectSatMiningStatusAccounts(
2727
3025
  return {
2728
3026
  globalState,
2729
3027
  currentCycle,
3028
+ currentSettlementProgress,
2730
3029
  currentMinerCycle,
2731
3030
  claimMinerCycle,
2732
3031
  minerCapital,
@@ -3343,7 +3642,7 @@ export async function inspectSatTreasuryVaultLamports(
3343
3642
  };
3344
3643
  }
3345
3644
 
3346
- export async function inspectSatRentExemptionLamports(_config: SatMiningConfig): Promise<{
3645
+ export async function inspectSatRentExemptionLamports(config: SatMiningConfig): Promise<{
3347
3646
  registryReserveTargetLamports: string;
3348
3647
  protocolVaultLamports: string;
3349
3648
  cycleStateLamports: string;
@@ -3351,14 +3650,18 @@ export async function inspectSatRentExemptionLamports(_config: SatMiningConfig):
3351
3650
  cycleRegistryPageLamports: string;
3352
3651
  cycleSettlementProgressLamports: string;
3353
3652
  minerCycleLamports: string;
3653
+ unlockIntervalLamports: string;
3354
3654
  openCycleLamports: string;
3355
3655
  submitCycleSharedLamports: string;
3356
3656
  submitCycleSignerLamports: string;
3357
3657
  }> {
3358
3658
  const { connection } = await resolveConnection(process.env);
3359
3659
  const rpc = resolveEffectiveReadRpcConfig();
3660
+ const registryReserveTargetLamports = resolveSatGenesisProfileContract(
3661
+ config.network,
3662
+ ).registryReserveTargetLamports;
3360
3663
  return await getOrLoadRpcCacheValue(
3361
- `view:rent-exemption:${rpcCacheScope(rpc)}`,
3664
+ `view:rent-exemption:${rpcCacheScope(rpc)}:${registryReserveTargetLamports}`,
3362
3665
  SAT_RPC_RENT_EXEMPTION_CACHE_TTL_MS,
3363
3666
  async () => {
3364
3667
  const [
@@ -3368,26 +3671,33 @@ export async function inspectSatRentExemptionLamports(_config: SatMiningConfig):
3368
3671
  cycleRegistryPageLamports,
3369
3672
  cycleSettlementProgressLamports,
3370
3673
  minerCycleLamports,
3674
+ unlockIntervalLamports,
3371
3675
  ] = await Promise.all([
3372
- connection.getMinimumBalanceForRentExemption(SAT_PROTOCOL_VAULT_ACCOUNT_SPACE),
3373
- connection.getMinimumBalanceForRentExemption(SAT_CYCLE_STATE_ACCOUNT_SPACE),
3374
- connection.getMinimumBalanceForRentExemption(SAT_CYCLE_REGISTRY_META_ACCOUNT_SPACE),
3375
- connection.getMinimumBalanceForRentExemption(SAT_CYCLE_REGISTRY_PAGE_ACCOUNT_SPACE),
3676
+ connection.getMinimumBalanceForRentExemption(SAT_RENT_ACCOUNT_SPACES.protocolVault),
3677
+ connection.getMinimumBalanceForRentExemption(SAT_RENT_ACCOUNT_SPACES.cycleState),
3678
+ connection.getMinimumBalanceForRentExemption(SAT_RENT_ACCOUNT_SPACES.cycleRegistryMeta),
3679
+ connection.getMinimumBalanceForRentExemption(SAT_RENT_ACCOUNT_SPACES.cycleRegistryPage),
3376
3680
  connection.getMinimumBalanceForRentExemption(
3377
- SAT_CYCLE_SETTLEMENT_PROGRESS_V2_ACCOUNT_SPACE,
3681
+ SAT_RENT_ACCOUNT_SPACES.cycleSettlementProgressV2,
3378
3682
  ),
3379
- connection.getMinimumBalanceForRentExemption(SAT_MINER_CYCLE_ACCOUNT_SPACE),
3683
+ connection.getMinimumBalanceForRentExemption(SAT_RENT_ACCOUNT_SPACES.minerCycle),
3684
+ connection.getMinimumBalanceForRentExemption(SAT_RENT_ACCOUNT_SPACES.unlockInterval),
3380
3685
  ]);
3381
3686
  const openCycleLamports = cycleStateLamports + cycleRegistryMetaLamports;
3382
- const submitCycleSharedLamports = cycleSettlementProgressLamports + cycleRegistryPageLamports;
3687
+ const submitCycleSharedLamports = calculateSatRevealSharedRentLamports({
3688
+ cycleSettlementProgressLamports,
3689
+ cycleRegistryPageLamports,
3690
+ unlockIntervalLamports,
3691
+ });
3383
3692
  return {
3384
- registryReserveTargetLamports: String(SAT_REGISTRY_RESERVE_TARGET_LAMPORTS),
3693
+ registryReserveTargetLamports: String(registryReserveTargetLamports),
3385
3694
  protocolVaultLamports: String(protocolVaultLamports),
3386
3695
  cycleStateLamports: String(cycleStateLamports),
3387
3696
  cycleRegistryMetaLamports: String(cycleRegistryMetaLamports),
3388
3697
  cycleRegistryPageLamports: String(cycleRegistryPageLamports),
3389
3698
  cycleSettlementProgressLamports: String(cycleSettlementProgressLamports),
3390
3699
  minerCycleLamports: String(minerCycleLamports),
3700
+ unlockIntervalLamports: String(unlockIntervalLamports),
3391
3701
  openCycleLamports: String(openCycleLamports),
3392
3702
  submitCycleSharedLamports: String(submitCycleSharedLamports),
3393
3703
  submitCycleSignerLamports: String(minerCycleLamports),
@@ -3592,6 +3902,20 @@ export async function inspectSatRoundState(
3592
3902
 
3593
3903
  export function inspectSatConnectionDetails() {
3594
3904
  const rpc = resolveEffectiveReadRpcConfig();
3905
+ const endpointStates = [rpc.primaryUrl, rpc.secondaryUrl]
3906
+ .filter((rpcUrl): rpcUrl is string => Boolean(rpcUrl))
3907
+ .map((rpcUrl) => {
3908
+ const state = satReadRpcEndpointStates.get(normalizeRpcUrlForComparison(rpcUrl));
3909
+ return {
3910
+ rpcUrl: redactSensitiveUrlLikeString(rpcUrl),
3911
+ consecutiveFailures: state?.consecutiveFailures ?? 0,
3912
+ backoffRemainingMs: currentReadRpcBackoffMs(rpcUrl),
3913
+ quotaLikely: state?.quotaLikely ?? false,
3914
+ lastError: state?.lastError ? redactSensitiveUrlLikeString(state.lastError) : null,
3915
+ lastFailureAt: state?.lastFailureAt ?? null,
3916
+ lastSuccessAt: state?.lastSuccessAt ?? null,
3917
+ };
3918
+ });
3595
3919
  return {
3596
3920
  programId: SAT_PROGRAM_ID(),
3597
3921
  bondProgramId: SAT_BOND_PROGRAM_ID(),
@@ -3608,6 +3932,7 @@ export function inspectSatConnectionDetails() {
3608
3932
  quotaLikely:
3609
3933
  satReadRpcRuntimeState.quotaLikely ||
3610
3934
  looksLikeRpcQuotaFailure(satReadRpcRuntimeState.lastError),
3935
+ endpoints: endpointStates,
3611
3936
  },
3612
3937
  rpcMetrics: summarizeSatRpcMethodMetrics(),
3613
3938
  };