@fased/fased 0.1.67 → 0.1.69
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.
- package/CHANGELOG.md +27 -0
- package/README.md +20 -22
- package/config/sat-runtime.env +6 -2
- package/config/signer-protocol-v2.json +10 -0
- package/dist/agents/tools/wallet-action-tool.js +2 -0
- package/dist/agents/tools/wallet-tool.js +5 -3
- package/dist/brand.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/cli/program/register.wallet.js +119 -5
- package/dist/commands/wallet.js +1286 -74
- package/dist/config/sat-runtime-ids.js +6 -1
- package/dist/control-ui/assets/{app-De8gTtZU.js → app-BLFLoFPk.js} +1526 -1526
- package/dist/control-ui/assets/{federation-DgA9e-Pn.js → federation-SGMAnM_8.js} +2 -2
- package/dist/control-ui/assets/{index-DYYBRBOS.js → index-S88kp5ZQ.js} +3 -3
- package/dist/control-ui/assets/{mining-Dg-3ll0F.js → mining-ClI8RW4u.js} +2 -2
- package/dist/control-ui/assets/{wallet-DvStR_AT.js → wallet-CRIhDQbW.js} +325 -156
- package/dist/control-ui/index.html +1 -1
- package/dist/control-ui/version.json +1 -1
- package/dist/gateway/server-http.js +394 -55
- package/dist/mining/mainnet-sync.js +67 -5
- package/dist/operator/operator-readiness.js +1 -1
- package/dist/plugin-sdk/{actions-DRu135h0.js → actions-B-Vwj64K.js} +3 -3
- package/dist/plugin-sdk/{allow-list-DyAxs4yw.js → allow-list-Bf45HfoP.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-Dq_rJtqH.js → audio-preflight-CS7Q_7-R.js} +26 -25
- package/dist/plugin-sdk/{audit-C5d2z5U1.js → audit-CUULWG22.js} +1 -1
- package/dist/plugin-sdk/{channel-access-configure-DaI5wevh.js → channel-access-configure-BoUsC-Ys.js} +1 -1
- package/dist/plugin-sdk/{channel-adapters.discord-BS4S4Svh.js → channel-adapters.discord-DSiR4X2Y.js} +1 -1
- package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
- package/dist/plugin-sdk/channel-plugin-common.js +1 -1
- package/dist/plugin-sdk/{chunk-CyoyqpbG.js → chunk-CBpl-AiQ.js} +1 -1
- package/dist/plugin-sdk/{chunk-items-Dunoq4Er.js → chunk-items-BLBZNORg.js} +1 -1
- package/dist/plugin-sdk/command-status.js +26 -25
- package/dist/plugin-sdk/{commands-registry-BfqdEWdF.js → commands-registry-G5KXSi_y.js} +1 -1
- package/dist/plugin-sdk/{config-schema--vl89M7d.js → config-schema-BiBOUW89.js} +431 -125
- package/dist/plugin-sdk/device-pair.d.ts +1 -1
- package/dist/plugin-sdk/{diagnostic-DLL_zekv.js → diagnostic-sYs6Agr-.js} +1 -1
- package/dist/plugin-sdk/{directory-live-CSuYxdwk.js → directory-live-BXMpuYAF.js} +1 -1
- package/dist/plugin-sdk/{directory-live-Dw7ZgC9_.js → directory-live-Rn1BzPof.js} +1 -1
- package/dist/plugin-sdk/discord.d.ts +4 -4
- package/dist/plugin-sdk/discord.js +20 -20
- package/dist/plugin-sdk/{draft-stream-controls-BqchW1vi.js → draft-stream-controls-CMNdKSx-.js} +1 -1
- package/dist/plugin-sdk/{guilds-CDhRIX57.js → guilds-Dkwl0yHv.js} +1 -1
- package/dist/plugin-sdk/{handle-action-hvwapMKg.js → handle-action-CRdM6B-8.js} +15 -15
- package/dist/plugin-sdk/index.d.ts +15 -15
- package/dist/plugin-sdk/index.js +28 -27
- package/dist/plugin-sdk/{login-Ca583Okc.js → login-D7WnK8-P.js} +1 -1
- package/dist/plugin-sdk/{login-qr-CGciBSNP.js → login-qr-CRueOKZK.js} +2 -114
- package/dist/plugin-sdk/{markdown-tables-DCOXEUfZ.js → markdown-tables-d7GlUs5R.js} +1 -1
- package/dist/plugin-sdk/{media-CAdQF5TG.js → media-BAoaxCrt.js} +1 -1
- package/dist/plugin-sdk/{monitor-DrTy_4CL.js → monitor-WXdn4mR-.js} +34 -33
- package/dist/plugin-sdk/{monitor-CV1sr0p2.js → monitor-xzVAPbg2.js} +44 -43
- package/dist/plugin-sdk/{openresponses-http-BAjgURZa.js → openresponses-http-DnI1LFgq.js} +26 -25
- package/dist/plugin-sdk/{outbound-attachment-QqTnIhZL.js → outbound-attachment-CyXM3cAv.js} +1 -1
- package/dist/plugin-sdk/{outbound-BgVDdHxx.js → outbound-zB6llMGW.js} +6 -6
- package/dist/plugin-sdk/{pairing-message-BjIJYVvp.d.ts → pairing-message-CiTcdD6m.d.ts} +1 -1
- package/dist/plugin-sdk/{pairing-store-BChahgI2.js → pairing-store-B6J2C0vP.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-DxTMz_XF.js → pi-model-discovery-runtime-6JzLw9Gk.js} +1 -1
- package/dist/plugin-sdk/{probe-CJb5uR8B.js → probe-BM7Oe40M.js} +2 -2
- package/dist/plugin-sdk/{probe-l_whvGLY.js → probe-CMPksimh.js} +1 -1
- package/dist/plugin-sdk/{probe-BFroeK3g.js → probe-oVp12D6L.js} +1 -1
- package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +1 -1
- package/dist/plugin-sdk/{pw-ai-DlxqX6Es.js → pw-ai-DZYLDC-S.js} +1 -1
- package/dist/plugin-sdk/qr-image-B4MlMG4N.js +115 -0
- package/dist/plugin-sdk/{replies-ChYo5ZQM.js → replies-CY-V0Zob.js} +3 -3
- package/dist/plugin-sdk/{resolve-channels-87LZrFk_.js → resolve-channels-1HtDcMqh.js} +2 -2
- package/dist/plugin-sdk/{resolve-channels-_-nV-EK2.js → resolve-channels-CU72Qh2j.js} +1 -1
- package/dist/plugin-sdk/{resolve-outbound-target-D-KGgHJZ.js → resolve-outbound-target-nQSBVYz9.js} +2 -2
- package/dist/plugin-sdk/{resolve-route-C8tvQm8Z.js → resolve-route-Dufnu2cT.js} +1 -1
- package/dist/plugin-sdk/{resolve-users-DN9VQBwv.js → resolve-users-Bk_ss2vC.js} +1 -1
- package/dist/plugin-sdk/{resolve-users-V6dHh_2B.js → resolve-users-IevCOk4W.js} +2 -2
- package/dist/plugin-sdk/{runtime-2B9_WKoI.js → runtime-CXSQwMaR.js} +1 -1
- package/dist/plugin-sdk/{runtime-dependency-nup8niQL.js → runtime-dependency-DczkvPxn.js} +9 -9
- package/dist/plugin-sdk/sat-runtime.d.ts +105 -10
- package/dist/plugin-sdk/sat-runtime.js +26 -25
- package/dist/plugin-sdk/{send-DCO441U7.js → send-BXBS_mRK.js} +8 -8
- package/dist/plugin-sdk/{send-CFzGKJXo.js → send-D-HfKQZm.js} +4 -4
- package/dist/plugin-sdk/{send-B6KkGKZD.js → send-D1j12ZgX.js} +5 -5
- package/dist/plugin-sdk/{send-q9HXrSwK.js → send-DWKm6yay.js} +10 -10
- package/dist/plugin-sdk/{send-gDoGA-7e.js → send-Di1Jit3L.js} +7 -7
- package/dist/plugin-sdk/{skill-commands-FKEPLS7T.js → skill-commands-iJtvpqgb.js} +2 -2
- package/dist/plugin-sdk/{slack-DSC6T2KW.js → slack-CkIRVDUK.js} +45 -44
- package/dist/plugin-sdk/{slack-actions-DhbMcp8M.js → slack-actions-BzUEszJa.js} +10 -10
- package/dist/plugin-sdk/slack.d.ts +4 -4
- package/dist/plugin-sdk/slack.js +6 -6
- package/dist/plugin-sdk/{sticker-cache-C0l_5IKg.js → sticker-cache-Dpap5ce_.js} +2 -2
- package/dist/plugin-sdk/{tables-B3jr0Pvq.js → tables-_1W36GII.js} +2 -2
- package/dist/plugin-sdk/{targets-CtSbTxYX.js → targets-DDbNnLnB.js} +2 -2
- package/dist/plugin-sdk/{telegram-actions-BwGBIVDE.js → telegram-actions-Cewdga8H.js} +30 -29
- package/dist/plugin-sdk/telegram.d.ts +4 -4
- package/dist/plugin-sdk/telegram.js +3 -3
- package/dist/plugin-sdk/{thread-bindings.lifecycle-QbkNl-m6.js → thread-bindings.lifecycle-Y9T3CQGf.js} +3 -3
- package/dist/plugin-sdk/{thread-bindings.state-D9hg_M1c.js → thread-bindings.state-D2oOWDpv.js} +1 -1
- package/dist/plugin-sdk/{tmp-fased-dir-DXnGKKgi.d.ts → tmp-fased-dir-BSEHc8MQ.d.ts} +8 -2
- package/dist/plugin-sdk/{types-eG9aYqXF.d.ts → types-BakzIzGN.d.ts} +1 -1
- package/dist/plugin-sdk/{types-Cegc86EP.d.ts → types-CzF0YQqK.d.ts} +3 -3
- package/dist/plugin-sdk/{web-C_AH5PyB.js → web-DGWi7i3B.js} +33 -32
- package/dist/plugin-sdk/{whatsapp-actions-Bj_rOncr.js → whatsapp-actions-Blu9-eX-.js} +9 -9
- package/dist/plugin-sdk/{whatsapp-heartbeat-B1WHkJIg.js → whatsapp-heartbeat-DjmQM7hq.js} +2 -2
- package/dist/plugin-sdk/whatsapp.d.ts +9 -9
- package/dist/plugin-sdk/whatsapp.js +7 -7
- package/dist/plugin-sdk/{wsl-J-HscWxS.js → wsl-CTvIWvZz.js} +1 -1
- package/dist/plugin-sdk/{zod-schema.providers-core-FaYR6KdD.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
- package/dist/wallet/local-socket-signer-lifecycle.js +107 -3
- package/dist/wallet/local-socket-signer-protocol.js +97 -10
- package/dist/wallet/mining-wallet-retirement.js +256 -0
- package/dist/wallet/providers/local-socket-signer-adapter.js +10 -0
- package/dist/wallet/signer-network-admin.js +11 -118
- package/dist/wallet/signer-protocol-v2.generated.js +10 -0
- package/dist/wallet/solana-assets.js +9 -3
- package/dist/wallet/solana-rpc-read-fetch.js +65 -0
- package/dist/wallet/wallet-agent-selection.js +6 -10
- package/dist/wallet/wallet-provider-registry.js +70 -29
- package/dist/wallet/wallet-send-approvals.js +6 -2
- package/dist/wallet/wallet-status.js +63 -1
- package/dist/web/login-qr.js +1 -1
- package/dist/wizard/onboarding.js +86 -84
- package/dist/wizard/onboarding.wallet.js +10 -1
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/fased-federation/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +12 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +2 -2
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +12 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +12 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/sat-mining/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +12 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +12 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +12 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +12 -0
- package/extensions/zalouser/package.json +1 -1
- package/install.sh +286 -107
- package/package.json +4 -2
- package/scripts/fased-managed-updater.mjs +10 -2
- package/scripts/install-fased-signerd.sh +4 -8
- package/scripts/install-managed-runtime.mjs +10 -7
- package/scripts/install-runtime-profile.sh +27 -0
- package/scripts/start-managed.sh +13 -1
- /package/dist/plugin-sdk/{active-listener-B_NMtgPL.js → active-listener-p9Ooc1qj.js} +0 -0
- /package/dist/plugin-sdk/{blocks-input-Bg-8S2pl.js → blocks-input-DiZaqaN7.js} +0 -0
- /package/dist/plugin-sdk/{channel-access-CcFRdRPO.js → channel-access-B0aZBSd2.js} +0 -0
- /package/dist/plugin-sdk/{channel-activity-DBDMQ3yI.js → channel-activity-F07DjroV.js} +0 -0
- /package/dist/plugin-sdk/{channel-core-CFRs8LPy.js → channel-core-DoF4X04L.js} +0 -0
- /package/dist/plugin-sdk/{client-pI228AVT.js → client-DLY-kWF_.js} +0 -0
- /package/dist/plugin-sdk/{command-poll-backoff-yJU83wEq.js → command-poll-backoff-NAePk3eL.js} +0 -0
- /package/dist/plugin-sdk/{date-time-uUevHscU.js → date-time-ChY_tHoG.js} +0 -0
- /package/dist/plugin-sdk/{draft-stream-loop-CrOPfV3F.js → draft-stream-loop-DMBwjjd1.js} +0 -0
- /package/dist/plugin-sdk/{fetch-BtmoPIlf.js → fetch-B0v6OTUZ.js} +0 -0
- /package/dist/plugin-sdk/{filesystem-manager-DoI8IBNF.js → filesystem-manager-BzuIJ9K9.js} +0 -0
- /package/dist/plugin-sdk/{gateway-registry-DZDsqicG.js → gateway-registry-Bgl2GFgy.js} +0 -0
- /package/dist/plugin-sdk/{inbound-context-DrAcXE0y.js → inbound-context-CQnfFFQ9.js} +0 -0
- /package/dist/plugin-sdk/{pi-model-discovery-BX_JLcEJ.js → pi-model-discovery-BHNVyRny.js} +0 -0
- /package/dist/plugin-sdk/{polls-DKQXVfJp.js → polls-DXd67TD8.js} +0 -0
- /package/dist/plugin-sdk/{proxy-DWpYcsvR.js → proxy-CLRUdShp.js} +0 -0
- /package/dist/plugin-sdk/{qmd-manager-CgRaTxUq.js → qmd-manager-B8Vnu0ND.js} +0 -0
- /package/dist/plugin-sdk/{render-e7fENCYH.js → render-DrBfVs0u.js} +0 -0
- /package/dist/plugin-sdk/{reply-reference-Bqk-7HXE.js → reply-reference-BnAk5Wjb.js} +0 -0
- /package/dist/plugin-sdk/{retry-policy-C6SjKjQA.js → retry-policy-CXh1owkc.js} +0 -0
- /package/dist/plugin-sdk/{sandbox-paths-Dx2lUqCu.js → sandbox-paths-Bzh1CuZc.js} +0 -0
- /package/dist/plugin-sdk/{session-DHD4ZKyG.js → session-iuGR_rdi.js} +0 -0
- /package/dist/plugin-sdk/{shared-CBgp_GBw.js → shared-D1AD2Ejn.js} +0 -0
- /package/dist/plugin-sdk/{target-errors-Ckufe179.js → target-errors-DfS1sLR9.js} +0 -0
- /package/dist/plugin-sdk/{tool-loop-detection-Bp8bPJLs.js → tool-loop-detection-sDZl27w7.js} +0 -0
- /package/dist/plugin-sdk/{ui-Be8cLHIS.js → ui-GQDYm_jw.js} +0 -0
- /package/dist/plugin-sdk/{with-timeout-ckWB8rTo.js → with-timeout-CVV8tytk.js} +0 -0
|
@@ -36,14 +36,18 @@ const SignerPolicyAssetV2Schema = Type.Object({
|
|
|
36
36
|
asset: Type.String(),
|
|
37
37
|
destinations: Type.Array(Type.String()),
|
|
38
38
|
maxPerTx: Type.String(),
|
|
39
|
-
maxDaily: Type.String()
|
|
39
|
+
maxDaily: Type.String(),
|
|
40
|
+
reviewedDestinations: Type.Optional(Type.Boolean()),
|
|
41
|
+
typedSatDestinations: Type.Optional(Type.Boolean())
|
|
40
42
|
}, { additionalProperties: false });
|
|
41
43
|
const SignerPolicyInputV2Schema = Type.Object({
|
|
42
44
|
walletId: Type.Optional(Type.String()),
|
|
43
45
|
role: SignerWalletRoleSchema,
|
|
44
46
|
version: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
47
|
+
baselineVersion: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
45
48
|
operations: Type.Array(Type.String()),
|
|
46
49
|
programs: Type.Array(Type.String()),
|
|
50
|
+
typedSatPrograms: Type.Optional(Type.Boolean()),
|
|
47
51
|
assets: Type.Array(SignerPolicyAssetV2Schema),
|
|
48
52
|
hash: Type.Optional(Type.String())
|
|
49
53
|
}, { additionalProperties: false });
|
|
@@ -51,8 +55,10 @@ const LocalSocketSignerPolicyV2Schema = Type.Object({
|
|
|
51
55
|
walletId: Type.String(),
|
|
52
56
|
role: SignerWalletRoleSchema,
|
|
53
57
|
version: Type.Integer({ minimum: 1 }),
|
|
58
|
+
baselineVersion: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
54
59
|
operations: Type.Array(Type.String()),
|
|
55
60
|
programs: Type.Array(Type.String()),
|
|
61
|
+
typedSatPrograms: Type.Optional(Type.Boolean()),
|
|
56
62
|
assets: Type.Array(SignerPolicyAssetV2Schema),
|
|
57
63
|
hash: Type.String({ pattern: "^sha256:[0-9a-f]{64}$" })
|
|
58
64
|
}, { additionalProperties: false });
|
|
@@ -238,10 +244,13 @@ const SignerSolanaTransactionEnvelopeV2Schema = Type.Object({
|
|
|
238
244
|
}),
|
|
239
245
|
submission: Type.Literal("rpc")
|
|
240
246
|
}, { additionalProperties: false });
|
|
241
|
-
const SignerReviewAuthorizationV2Schema = Type.Object({
|
|
247
|
+
const SignerReviewAuthorizationV2Schema = Type.Union([Type.Object({
|
|
242
248
|
type: Type.Literal("webauthn"),
|
|
243
249
|
proof: Type.Object({ proofId: Type.String({ minLength: 1 }) }, { additionalProperties: false })
|
|
244
|
-
}, { additionalProperties: false })
|
|
250
|
+
}, { additionalProperties: false }), Type.Object({
|
|
251
|
+
type: Type.Literal("control-ui"),
|
|
252
|
+
proof: Type.Object({ proofId: Type.String({ pattern: "^[0-9a-f]{64}$" }) }, { additionalProperties: false })
|
|
253
|
+
}, { additionalProperties: false })]);
|
|
245
254
|
const LocalSocketSignerJupiterTriggerHistoryV2Schema = Type.Object({ orders: Type.Array(Type.Object({
|
|
246
255
|
orderId: Type.String({ minLength: 1 }),
|
|
247
256
|
orderState: Type.String({ minLength: 1 }),
|
|
@@ -266,10 +275,17 @@ const LocalSocketSignerJupiterTriggerHistoryV2Schema = Type.Object({ orders: Typ
|
|
|
266
275
|
program: Type.String({ minLength: 1 })
|
|
267
276
|
}, { additionalProperties: false }))
|
|
268
277
|
}, { additionalProperties: false })) }, { additionalProperties: false });
|
|
269
|
-
const
|
|
278
|
+
const SignerRoleBaselineV1Schema = Type.Object({
|
|
279
|
+
version: Type.Literal(1),
|
|
280
|
+
role: SignerWalletRoleSchema
|
|
281
|
+
}, { additionalProperties: false });
|
|
282
|
+
const SignerWalletPolicyCreateV2Schema = Type.Union([Type.Object({
|
|
270
283
|
expectedPolicyVersion: Type.Literal(0),
|
|
271
284
|
policy: SignerPolicyInputV2Schema
|
|
272
|
-
}, { additionalProperties: false })
|
|
285
|
+
}, { additionalProperties: false }), Type.Object({
|
|
286
|
+
expectedPolicyVersion: Type.Literal(0),
|
|
287
|
+
baseline: SignerRoleBaselineV1Schema
|
|
288
|
+
}, { additionalProperties: false })]);
|
|
273
289
|
const SignerOperationLookupV2Schema = Type.Object({ requestId: Type.String() }, { additionalProperties: false });
|
|
274
290
|
const SignerSatLookupBindingRequestV2Schema = Type.Object({
|
|
275
291
|
cycleId: Type.String({ pattern: "^(0|[1-9][0-9]*)$" }),
|
|
@@ -292,6 +308,16 @@ const LocalSocketSignerSatLookupBindingV2Schema = Type.Object({
|
|
|
292
308
|
Type.Literal("unknown")
|
|
293
309
|
]))
|
|
294
310
|
}, { additionalProperties: false });
|
|
311
|
+
const LocalSocketSignerNetworkSummaryV2Schema = Type.Object({
|
|
312
|
+
walletId: Type.String({
|
|
313
|
+
minLength: 1,
|
|
314
|
+
maxLength: 64
|
|
315
|
+
}),
|
|
316
|
+
configured: Type.Boolean(),
|
|
317
|
+
version: Type.Integer({ minimum: 0 }),
|
|
318
|
+
hash: Type.Optional(Type.String({ pattern: "^hmac-sha256:[0-9a-f]{64}$" })),
|
|
319
|
+
ready: Type.Boolean()
|
|
320
|
+
}, { additionalProperties: false });
|
|
295
321
|
const LocalSocketSignerRequestSchema = Type.Union([
|
|
296
322
|
Type.Object({ op: Type.Literal("health") }, { additionalProperties: false }),
|
|
297
323
|
Type.Object({ op: Type.Literal("v2.capabilities") }, { additionalProperties: false }),
|
|
@@ -303,6 +329,21 @@ const LocalSocketSignerRequestSchema = Type.Union([
|
|
|
303
329
|
op: Type.Literal("v2.policy.get"),
|
|
304
330
|
walletId: Type.String()
|
|
305
331
|
}, { additionalProperties: false }),
|
|
332
|
+
Type.Object({
|
|
333
|
+
op: Type.Literal("v2.network.get"),
|
|
334
|
+
walletId: Type.String()
|
|
335
|
+
}, { additionalProperties: false }),
|
|
336
|
+
Type.Object({
|
|
337
|
+
op: Type.Literal("v2.network.bootstrap"),
|
|
338
|
+
walletId: Type.String(),
|
|
339
|
+
request: Type.Object({
|
|
340
|
+
expectedVersion: Type.Integer({ minimum: 0 }),
|
|
341
|
+
primaryRpcUrl: Type.String({
|
|
342
|
+
minLength: 1,
|
|
343
|
+
maxLength: 2048
|
|
344
|
+
})
|
|
345
|
+
}, { additionalProperties: false })
|
|
346
|
+
}, { additionalProperties: false }),
|
|
306
347
|
Type.Object({
|
|
307
348
|
op: Type.Literal("v2.policy.put"),
|
|
308
349
|
walletId: Type.String(),
|
|
@@ -323,6 +364,18 @@ const LocalSocketSignerRequestSchema = Type.Union([
|
|
|
323
364
|
op: Type.Literal("v2.wallet.get"),
|
|
324
365
|
walletId: Type.String()
|
|
325
366
|
}, { additionalProperties: false }),
|
|
367
|
+
Type.Object({
|
|
368
|
+
op: Type.Literal("v2.wallet.readiness"),
|
|
369
|
+
walletId: Type.String()
|
|
370
|
+
}, { additionalProperties: false }),
|
|
371
|
+
Type.Object({
|
|
372
|
+
op: Type.Literal("v2.policy.activateBaseline"),
|
|
373
|
+
walletId: Type.String(),
|
|
374
|
+
request: Type.Object({
|
|
375
|
+
expectedPolicyVersion: Type.Integer({ minimum: 1 }),
|
|
376
|
+
baseline: SignerRoleBaselineV1Schema
|
|
377
|
+
}, { additionalProperties: false })
|
|
378
|
+
}, { additionalProperties: false }),
|
|
326
379
|
Type.Object({
|
|
327
380
|
op: Type.Literal("v2.wallet.create"),
|
|
328
381
|
walletId: Type.String(),
|
|
@@ -331,21 +384,30 @@ const LocalSocketSignerRequestSchema = Type.Union([
|
|
|
331
384
|
Type.Object({
|
|
332
385
|
op: Type.Literal("v2.wallet.import"),
|
|
333
386
|
walletId: Type.String(),
|
|
334
|
-
request: Type.Object({
|
|
387
|
+
request: Type.Union([Type.Object({
|
|
335
388
|
expectedPolicyVersion: Type.Literal(0),
|
|
336
389
|
policy: SignerPolicyInputV2Schema,
|
|
337
390
|
path: Type.String()
|
|
338
|
-
}, { additionalProperties: false })
|
|
391
|
+
}, { additionalProperties: false }), Type.Object({
|
|
392
|
+
expectedPolicyVersion: Type.Literal(0),
|
|
393
|
+
baseline: SignerRoleBaselineV1Schema,
|
|
394
|
+
path: Type.String()
|
|
395
|
+
}, { additionalProperties: false })])
|
|
339
396
|
}, { additionalProperties: false }),
|
|
340
397
|
Type.Object({
|
|
341
398
|
op: Type.Literal("v2.wallet.importLegacy"),
|
|
342
399
|
walletId: Type.String(),
|
|
343
|
-
request: Type.Object({
|
|
400
|
+
request: Type.Union([Type.Object({
|
|
344
401
|
expectedPolicyVersion: Type.Literal(0),
|
|
345
402
|
policy: SignerPolicyInputV2Schema,
|
|
346
403
|
path: Type.String(),
|
|
347
404
|
passphrasePath: Type.String()
|
|
348
|
-
}, { additionalProperties: false })
|
|
405
|
+
}, { additionalProperties: false }), Type.Object({
|
|
406
|
+
expectedPolicyVersion: Type.Literal(0),
|
|
407
|
+
baseline: SignerRoleBaselineV1Schema,
|
|
408
|
+
path: Type.String(),
|
|
409
|
+
passphrasePath: Type.String()
|
|
410
|
+
}, { additionalProperties: false })])
|
|
349
411
|
}, { additionalProperties: false }),
|
|
350
412
|
Type.Object({
|
|
351
413
|
op: Type.Literal("v2.wallet.reencrypt"),
|
|
@@ -625,6 +687,27 @@ const LocalSocketSignerWalletPolicyResultV2Schema = Type.Object({
|
|
|
625
687
|
wallet: LocalSocketSignerWalletV2Schema,
|
|
626
688
|
policy: LocalSocketSignerPolicyV2Schema
|
|
627
689
|
}, { additionalProperties: false });
|
|
690
|
+
const LocalSocketSignerWalletReadinessV2Schema = Type.Object({
|
|
691
|
+
walletId: Type.String({ minLength: 1 }),
|
|
692
|
+
publicKey: Type.String({ minLength: 1 }),
|
|
693
|
+
walletVersion: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
694
|
+
role: SignerWalletRoleSchema,
|
|
695
|
+
baselineVersion: Type.Integer({ minimum: 0 }),
|
|
696
|
+
policyVersion: Type.Integer({ minimum: 1 }),
|
|
697
|
+
policyHash: Type.String({ pattern: "^sha256:[0-9a-f]{64}$" }),
|
|
698
|
+
networkVersion: Type.Integer({ minimum: 0 }),
|
|
699
|
+
networkHash: Type.Optional(Type.String({ pattern: "^hmac-sha256:[0-9a-f]{64}$" })),
|
|
700
|
+
keyReady: Type.Boolean(),
|
|
701
|
+
policyReady: Type.Boolean(),
|
|
702
|
+
networkReady: Type.Boolean(),
|
|
703
|
+
operationLane: Type.Union([
|
|
704
|
+
Type.Literal("blocked"),
|
|
705
|
+
Type.Literal("agent-reviewed-and-autonomous"),
|
|
706
|
+
Type.Literal("mining-typed-sat"),
|
|
707
|
+
Type.Literal("vault-reviewed-only")
|
|
708
|
+
]),
|
|
709
|
+
ready: Type.Boolean()
|
|
710
|
+
}, { additionalProperties: false });
|
|
628
711
|
function isPositiveUnsignedInteger(value) {
|
|
629
712
|
return typeof value === "string" && /^[1-9][0-9]*$/.test(value);
|
|
630
713
|
}
|
|
@@ -665,11 +748,15 @@ function validateLocalSocketSignerResult(op, result) {
|
|
|
665
748
|
case "health":
|
|
666
749
|
case "v2.capabilities": return Value.Check(LocalSocketSignerHealthResultSchema, result);
|
|
667
750
|
case "v2.jupiter.trigger.history": return Value.Check(LocalSocketSignerJupiterTriggerHistoryV2Schema, result);
|
|
751
|
+
case "v2.network.get":
|
|
752
|
+
case "v2.network.bootstrap": return Value.Check(LocalSocketSignerNetworkSummaryV2Schema, result);
|
|
668
753
|
case "v2.policy.get":
|
|
669
754
|
case "v2.policy.put":
|
|
670
|
-
case "v2.policy.tighten":
|
|
755
|
+
case "v2.policy.tighten":
|
|
756
|
+
case "v2.policy.activateBaseline": return Value.Check(LocalSocketSignerPolicyV2Schema, result);
|
|
671
757
|
case "v2.wallet.get":
|
|
672
758
|
case "v2.wallet.reencrypt": return Value.Check(LocalSocketSignerWalletV2Schema, result);
|
|
759
|
+
case "v2.wallet.readiness": return Value.Check(LocalSocketSignerWalletReadinessV2Schema, result);
|
|
673
760
|
case "v2.wallet.create":
|
|
674
761
|
case "v2.wallet.import":
|
|
675
762
|
case "v2.wallet.importLegacy": return Value.Check(LocalSocketSignerWalletPolicyResultV2Schema, result);
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { resolveStateDir } from "../config/paths.js";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
5
|
+
|
|
6
|
+
//#region src/wallet/mining-wallet-retirement.ts
|
|
7
|
+
function record(value) {
|
|
8
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
9
|
+
}
|
|
10
|
+
function decimal(value, field) {
|
|
11
|
+
const normalized = typeof value === "string" ? value.trim() : "";
|
|
12
|
+
if (!/^\d+$/u.test(normalized)) {
|
|
13
|
+
throw new Error(`Mining retirement cannot verify ${field}`);
|
|
14
|
+
}
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
function nonNegativeCount(value) {
|
|
18
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : 0;
|
|
19
|
+
}
|
|
20
|
+
function sha256(raw) {
|
|
21
|
+
return `sha256:${createHash("sha256").update(raw).digest("hex")}`;
|
|
22
|
+
}
|
|
23
|
+
function base64UrlByteLength(value) {
|
|
24
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9_-]+$/u.test(value)) {
|
|
25
|
+
return -1;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return Buffer.from(value, "base64url").byteLength;
|
|
29
|
+
} catch {
|
|
30
|
+
return -1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function normalizedWalletStateKey(walletId) {
|
|
34
|
+
return walletId.replace(/[^a-zA-Z0-9._-]+/gu, "_") || "unattached";
|
|
35
|
+
}
|
|
36
|
+
function readStrictJSONFile(filePath, maxBytes) {
|
|
37
|
+
const info = fs.lstatSync(filePath);
|
|
38
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size <= 0 || info.size > maxBytes) {
|
|
39
|
+
throw new Error(`Mining retirement evidence file is invalid: ${filePath}`);
|
|
40
|
+
}
|
|
41
|
+
const raw = fs.readFileSync(filePath);
|
|
42
|
+
let parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = JSON.parse(raw.toString("utf8"));
|
|
45
|
+
} catch {
|
|
46
|
+
throw new Error(`Mining retirement evidence file is not valid JSON: ${filePath}`);
|
|
47
|
+
}
|
|
48
|
+
const value = record(parsed);
|
|
49
|
+
if (!value) {
|
|
50
|
+
throw new Error(`Mining retirement evidence file must contain one JSON object: ${filePath}`);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
raw,
|
|
54
|
+
value
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function unwrapMiningGatewayPayload(value) {
|
|
58
|
+
let current = value;
|
|
59
|
+
for (let index = 0; index < 4; index += 1) {
|
|
60
|
+
const currentRecord = record(current);
|
|
61
|
+
if (!currentRecord) {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
if (record(currentRecord.status)) {
|
|
65
|
+
return record(currentRecord.status);
|
|
66
|
+
}
|
|
67
|
+
if (!("payload" in currentRecord)) {
|
|
68
|
+
return currentRecord;
|
|
69
|
+
}
|
|
70
|
+
current = currentRecord.payload;
|
|
71
|
+
}
|
|
72
|
+
return record(current) ?? {};
|
|
73
|
+
}
|
|
74
|
+
function verifyMiningRecoveryPackage(params) {
|
|
75
|
+
const recoveryFile = params.recoveryFile.trim();
|
|
76
|
+
if (!path.isAbsolute(recoveryFile) || path.resolve(recoveryFile) !== recoveryFile) {
|
|
77
|
+
throw new Error("--recovery-file must be an absolute clean path");
|
|
78
|
+
}
|
|
79
|
+
const info = fs.lstatSync(recoveryFile);
|
|
80
|
+
if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1 || info.mode & 63) {
|
|
81
|
+
throw new Error("Mining recovery package must be one owner-only regular non-symlink file");
|
|
82
|
+
}
|
|
83
|
+
if (typeof process.getuid === "function" && info.uid !== process.getuid()) {
|
|
84
|
+
throw new Error("Mining recovery package must be owned by the current terminal user");
|
|
85
|
+
}
|
|
86
|
+
const { raw, value } = readStrictJSONFile(recoveryFile, 16 * 1024);
|
|
87
|
+
const kdf = record(value.kdf);
|
|
88
|
+
const encryption = record(value.encryption);
|
|
89
|
+
if (value.kind !== "fased-signer-wallet-recovery" || value.version !== 1 || value.walletId !== params.walletId || value.role !== "mining" || value.publicKey !== params.publicKey || typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt)) || kdf?.name !== "argon2id" || kdf.memoryKiB !== 64 * 1024 || kdf.iterations !== 3 || kdf.parallelism !== 1 || base64UrlByteLength(kdf.salt) !== 16 || encryption?.name !== "aes-256-gcm" || base64UrlByteLength(encryption.nonce) !== 12 || base64UrlByteLength(encryption.ciphertext) !== 80) {
|
|
90
|
+
throw new Error("Encrypted recovery package does not match the source Mining wallet");
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
packageHash: sha256(raw),
|
|
94
|
+
walletId: params.walletId,
|
|
95
|
+
publicKey: params.publicKey,
|
|
96
|
+
role: "mining"
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function buildMiningRetirementEvidence(params) {
|
|
100
|
+
const env = params.env ?? process.env;
|
|
101
|
+
const status = unwrapMiningGatewayPayload(params.liveStatus);
|
|
102
|
+
if (typeof status.retirementGatewayError === "string") {
|
|
103
|
+
throw new Error(`Could not stop and inspect Mining: ${status.retirementGatewayError}`);
|
|
104
|
+
}
|
|
105
|
+
if (status.walletId !== params.walletId && status.walletId !== params.signerWalletId) {
|
|
106
|
+
throw new Error("Live Mining status is not bound to the source wallet");
|
|
107
|
+
}
|
|
108
|
+
if (status.statusFresh === false || status.degraded === true) {
|
|
109
|
+
throw new Error("Live Mining status is degraded; normal retirement refuses unverifiable state");
|
|
110
|
+
}
|
|
111
|
+
if (status.running === true || status.drainOnly === true || status.enabledWanted === true) {
|
|
112
|
+
throw new Error("Mining is still running or draining; retry retirement after Clearing finishes");
|
|
113
|
+
}
|
|
114
|
+
const workers = record(status.workers) ?? {};
|
|
115
|
+
if (Object.values(workers).some((worker) => record(worker)?.running === true)) {
|
|
116
|
+
throw new Error("A Mining worker is still running");
|
|
117
|
+
}
|
|
118
|
+
const solBalanceLamports = decimal(status.currentSolBalanceLamports, "live SOL balance");
|
|
119
|
+
const signerBalance = decimal(params.signerSolBalanceLamports, "signer SOL balance");
|
|
120
|
+
if (solBalanceLamports !== signerBalance) {
|
|
121
|
+
throw new Error("Live Mining and signer SOL balance observations disagree");
|
|
122
|
+
}
|
|
123
|
+
const satBalanceRaw = decimal(status.currentSatBalanceRaw, "live SAT balance");
|
|
124
|
+
for (const [field, value] of [
|
|
125
|
+
["funded Mining capital", status.currentCapitalFundedLamports],
|
|
126
|
+
["locked Mining capital", status.currentCapitalLockedLamports],
|
|
127
|
+
["free Mining capital", status.currentCapitalFreeLamports]
|
|
128
|
+
]) {
|
|
129
|
+
if (decimal(value, field) !== "0") {
|
|
130
|
+
throw new Error(`${field} must be zero before normal Mining retirement`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (nonNegativeCount(status.currentCapitalPendingCycleCount) !== 0 || nonNegativeCount(record(status.claimBacklog)?.total) !== 0 || nonNegativeCount(status.missingCycleCount) !== 0 || Array.isArray(status.pendingCycleIds) && status.pendingCycleIds.length > 0 || status.exactPendingCycleId != null) {
|
|
134
|
+
throw new Error("Mining still has pending cycles, claims, or reconciliation gaps");
|
|
135
|
+
}
|
|
136
|
+
const walletStateDir = path.join(resolveStateDir(env), "sat-mining", "wallets", normalizedWalletStateKey(params.walletId));
|
|
137
|
+
const runtime = readStrictJSONFile(path.join(walletStateDir, "runtime-store.json"), 16 * 1024 * 1024);
|
|
138
|
+
if (runtime.value.enabledWanted === true) {
|
|
139
|
+
throw new Error("Durable Mining state still permits new jobs");
|
|
140
|
+
}
|
|
141
|
+
const durableWorkers = record(runtime.value.workers) ?? {};
|
|
142
|
+
if (Object.values(durableWorkers).some((worker) => record(worker)?.running === true)) {
|
|
143
|
+
throw new Error("Durable Mining state still records a running worker");
|
|
144
|
+
}
|
|
145
|
+
if (Array.isArray(runtime.value.pendingPlannerCycles) && runtime.value.pendingPlannerCycles.length) {
|
|
146
|
+
throw new Error("Durable Mining planner work remains pending");
|
|
147
|
+
}
|
|
148
|
+
if (Array.isArray(runtime.value.claimBacklog) && runtime.value.claimBacklog.length) {
|
|
149
|
+
throw new Error("Durable Mining claim backlog remains pending");
|
|
150
|
+
}
|
|
151
|
+
const lastKnown = record(runtime.value.lastKnownStatus);
|
|
152
|
+
if (!lastKnown || lastKnown.walletId !== params.walletId && lastKnown.walletId !== params.signerWalletId) {
|
|
153
|
+
throw new Error("Durable Mining balance state is missing or belongs to another wallet");
|
|
154
|
+
}
|
|
155
|
+
if (decimal(lastKnown.currentCapitalFundedLamports, "durable funded capital") !== "0" || decimal(lastKnown.currentCapitalLockedLamports, "durable locked capital") !== "0" || decimal(lastKnown.currentCapitalFreeLamports, "durable free capital") !== "0" || nonNegativeCount(lastKnown.currentCapitalPendingCycleCount) !== 0 || lastKnown.exactPendingCycleId != null) {
|
|
156
|
+
throw new Error("Durable Mining state still contains pending capital or protocol work");
|
|
157
|
+
}
|
|
158
|
+
const ledgerPath = path.join(walletStateDir, "submission-ledger.json");
|
|
159
|
+
let ledgerRaw = Buffer.from("{\"version\":1,\"records\":{}}\n", "utf8");
|
|
160
|
+
let ledger = {
|
|
161
|
+
version: 1,
|
|
162
|
+
records: {}
|
|
163
|
+
};
|
|
164
|
+
if (fs.existsSync(ledgerPath)) {
|
|
165
|
+
const loaded = readStrictJSONFile(ledgerPath, 16 * 1024 * 1024);
|
|
166
|
+
ledgerRaw = loaded.raw;
|
|
167
|
+
ledger = loaded.value;
|
|
168
|
+
}
|
|
169
|
+
if (ledger.version !== 1 || !record(ledger.records)) {
|
|
170
|
+
throw new Error("Durable Mining submission ledger is invalid");
|
|
171
|
+
}
|
|
172
|
+
const pendingByKind = {
|
|
173
|
+
commit: 0,
|
|
174
|
+
reveal: 0,
|
|
175
|
+
settlement: 0,
|
|
176
|
+
claim: 0,
|
|
177
|
+
cleanup: 0,
|
|
178
|
+
alt: 0
|
|
179
|
+
};
|
|
180
|
+
for (const rawEntry of Object.values(record(ledger.records))) {
|
|
181
|
+
const entry = record(rawEntry);
|
|
182
|
+
if (!entry) {
|
|
183
|
+
throw new Error("Durable Mining submission ledger contains an invalid record");
|
|
184
|
+
}
|
|
185
|
+
const state = typeof entry.state === "string" ? entry.state : "";
|
|
186
|
+
if (![
|
|
187
|
+
"prepared",
|
|
188
|
+
"reserved",
|
|
189
|
+
"broadcast",
|
|
190
|
+
"unknown"
|
|
191
|
+
].includes(state)) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const action = typeof entry.action === "string" ? entry.action.toLowerCase() : "";
|
|
195
|
+
if (action.includes("commit")) {
|
|
196
|
+
pendingByKind.commit += 1;
|
|
197
|
+
} else if (action.includes("reveal") || action.includes("submit")) {
|
|
198
|
+
pendingByKind.reveal += 1;
|
|
199
|
+
} else if (action.includes("settle") || action.includes("score") || action.includes("distribute") || action.includes("finalize")) {
|
|
200
|
+
pendingByKind.settlement += 1;
|
|
201
|
+
} else if (action.includes("claim")) {
|
|
202
|
+
pendingByKind.claim += 1;
|
|
203
|
+
} else if (action.includes("lookup") || action.includes("alt")) {
|
|
204
|
+
pendingByKind.alt += 1;
|
|
205
|
+
} else {
|
|
206
|
+
pendingByKind.cleanup += 1;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (Object.values(pendingByKind).some((count) => count > 0)) {
|
|
210
|
+
throw new Error("Reserved, broadcast, or unknown Mining submissions must be reconciled first");
|
|
211
|
+
}
|
|
212
|
+
const observedAt = typeof status.updatedAt === "string" ? status.updatedAt : typeof status.snapshotAt === "string" ? status.snapshotAt : typeof lastKnown.updatedAt === "string" ? lastKnown.updatedAt : "";
|
|
213
|
+
if (!observedAt || !Number.isFinite(Date.parse(observedAt))) {
|
|
214
|
+
throw new Error("Live Mining balance observation has no verifiable timestamp");
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
version: 1,
|
|
218
|
+
walletId: params.signerWalletId,
|
|
219
|
+
publicKey: params.publicKey,
|
|
220
|
+
observedAt: new Date(observedAt).toISOString(),
|
|
221
|
+
newJobsStopped: true,
|
|
222
|
+
workersDrained: true,
|
|
223
|
+
clearingDrained: true,
|
|
224
|
+
submissionsReconciled: true,
|
|
225
|
+
pendingCommits: pendingByKind.commit,
|
|
226
|
+
pendingReveals: pendingByKind.reveal,
|
|
227
|
+
pendingSettlements: pendingByKind.settlement,
|
|
228
|
+
pendingClaims: pendingByKind.claim,
|
|
229
|
+
pendingCleanup: pendingByKind.cleanup,
|
|
230
|
+
pendingAltMutations: pendingByKind.alt,
|
|
231
|
+
solBalanceLamports,
|
|
232
|
+
satBalanceRaw,
|
|
233
|
+
runtimeStateHash: sha256(runtime.raw),
|
|
234
|
+
submissionLedgerHash: sha256(ledgerRaw)
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function writeMiningRetirementReceipt(params) {
|
|
238
|
+
const root = path.join(resolveStateDir(params.env ?? process.env), "wallet-retirements");
|
|
239
|
+
fs.mkdirSync(root, {
|
|
240
|
+
recursive: true,
|
|
241
|
+
mode: 448
|
|
242
|
+
});
|
|
243
|
+
const filePath = path.join(root, `${normalizedWalletStateKey(params.sourceWalletId)}.json`);
|
|
244
|
+
const tempPath = `${filePath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
245
|
+
fs.writeFileSync(tempPath, `${JSON.stringify(params.receipt, null, 2)}\n`, {
|
|
246
|
+
encoding: "utf8",
|
|
247
|
+
flag: "wx",
|
|
248
|
+
mode: 384
|
|
249
|
+
});
|
|
250
|
+
fs.renameSync(tempPath, filePath);
|
|
251
|
+
fs.chmodSync(filePath, 384);
|
|
252
|
+
return filePath;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
//#endregion
|
|
256
|
+
export { buildMiningRetirementEvidence, verifyMiningRecoveryPackage, writeMiningRetirementReceipt };
|
|
@@ -14,11 +14,15 @@ const REQUIRED_PROTOCOL_V2_FEATURES = SIGNER_PROTOCOL_V2_REQUIRED_CLIENT_FEATURE
|
|
|
14
14
|
const SIGNER_SOCKET_TIMEOUT_MS = {
|
|
15
15
|
health: 2e3,
|
|
16
16
|
"v2.capabilities": 2e3,
|
|
17
|
+
"v2.network.get": 15e3,
|
|
18
|
+
"v2.network.bootstrap": 3e4,
|
|
17
19
|
"v2.jupiter.trigger.history": 3e4,
|
|
18
20
|
"v2.policy.get": 5e3,
|
|
19
21
|
"v2.policy.put": 5e3,
|
|
20
22
|
"v2.policy.tighten": 5e3,
|
|
23
|
+
"v2.policy.activateBaseline": 1e4,
|
|
21
24
|
"v2.wallet.get": 5e3,
|
|
25
|
+
"v2.wallet.readiness": 5e3,
|
|
22
26
|
"v2.wallet.create": 1e4,
|
|
23
27
|
"v2.wallet.import": 2e4,
|
|
24
28
|
"v2.wallet.importLegacy": 3e4,
|
|
@@ -227,6 +231,12 @@ var LocalSocketSignerAdapter = class {
|
|
|
227
231
|
provider: this.id,
|
|
228
232
|
configured: true,
|
|
229
233
|
checkedAt: new Date().toISOString(),
|
|
234
|
+
...details.webAuthn ? { nativeSignerApproval: {
|
|
235
|
+
configured: details.webAuthn.configured,
|
|
236
|
+
ready: details.webAuthn.ready,
|
|
237
|
+
credentialCount: details.webAuthn.credentialCount,
|
|
238
|
+
credentialVersion: details.webAuthn.credentialVersion
|
|
239
|
+
} } : {},
|
|
230
240
|
details: [
|
|
231
241
|
details?.details ?? "",
|
|
232
242
|
...!details?.details ? [
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { spawnSync } from "node:child_process";
|
|
1
|
+
import { resolveLocalSignerSocketPath } from "./wallet-runtime-config.js";
|
|
2
|
+
import { configureSignerOwnedWalletPrimaryRpc } from "./local-socket-signer-lifecycle.js";
|
|
4
3
|
|
|
5
4
|
//#region src/wallet/signer-network-admin.ts
|
|
6
|
-
const NETWORK_ADMIN_TIMEOUT_MS = 3e4;
|
|
7
|
-
const NETWORK_ADMIN_MAX_OUTPUT_BYTES = 256 * 1024;
|
|
8
5
|
function canonicalSignerWalletId(raw) {
|
|
9
6
|
const normalized = raw.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
10
7
|
return normalized || "default";
|
|
@@ -47,62 +44,7 @@ function parseSignerNetworkSummary(raw, expectedWalletId) {
|
|
|
47
44
|
ready: record.ready
|
|
48
45
|
};
|
|
49
46
|
}
|
|
50
|
-
function
|
|
51
|
-
let value = raw;
|
|
52
|
-
for (const secret of secrets.filter(Boolean).toSorted((a, b) => b.length - a.length)) {
|
|
53
|
-
value = value.split(secret).join("[redacted-rpc-url]");
|
|
54
|
-
}
|
|
55
|
-
value = value.replace(/https?:\/\/[^\s"'<>]+/gi, "[redacted-rpc-url]");
|
|
56
|
-
value = value.replace(/\b(api[_-]?key|access[_-]?token|token|key)=([^\s&"']+)/gi, "$1=[redacted]");
|
|
57
|
-
return value.trim().slice(0, 2e3) || "signer network administration failed";
|
|
58
|
-
}
|
|
59
|
-
function signerAdminEnvironment(env) {
|
|
60
|
-
const out = {};
|
|
61
|
-
for (const key of [
|
|
62
|
-
"HOME",
|
|
63
|
-
"PATH",
|
|
64
|
-
"TMPDIR",
|
|
65
|
-
"LANG",
|
|
66
|
-
"LC_ALL",
|
|
67
|
-
"TZ"
|
|
68
|
-
]) {
|
|
69
|
-
const value = String(env[key] ?? "").trim();
|
|
70
|
-
if (value) {
|
|
71
|
-
out[key] = value;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return out;
|
|
75
|
-
}
|
|
76
|
-
function runSignerAdmin(params) {
|
|
77
|
-
const child = spawnSync(params.command, params.args, {
|
|
78
|
-
input: params.input,
|
|
79
|
-
env: params.env,
|
|
80
|
-
encoding: "utf8",
|
|
81
|
-
timeout: NETWORK_ADMIN_TIMEOUT_MS,
|
|
82
|
-
maxBuffer: NETWORK_ADMIN_MAX_OUTPUT_BYTES,
|
|
83
|
-
stdio: [
|
|
84
|
-
"pipe",
|
|
85
|
-
"pipe",
|
|
86
|
-
"pipe"
|
|
87
|
-
]
|
|
88
|
-
});
|
|
89
|
-
if (child.error || child.status !== 0) {
|
|
90
|
-
const detail = [
|
|
91
|
-
child.stderr,
|
|
92
|
-
child.stdout,
|
|
93
|
-
child.error?.message
|
|
94
|
-
].filter((part) => typeof part === "string" && part.trim().length > 0).join("\n");
|
|
95
|
-
throw new Error(redactSignerNetworkError(detail, params.secrets));
|
|
96
|
-
}
|
|
97
|
-
return child.stdout;
|
|
98
|
-
}
|
|
99
|
-
function assertReadyNetworkSummary(summary, previousVersion) {
|
|
100
|
-
if (!summary.configured || !summary.ready || !summary.hash || summary.version !== previousVersion + 1) {
|
|
101
|
-
throw new Error("signer network update did not acknowledge the exact next ready version");
|
|
102
|
-
}
|
|
103
|
-
return summary;
|
|
104
|
-
}
|
|
105
|
-
function configureSignerOwnedWalletNetwork(params) {
|
|
47
|
+
async function configureSignerOwnedWalletNetwork(params) {
|
|
106
48
|
const env = params.env ?? process.env;
|
|
107
49
|
const walletId = canonicalSignerWalletId(params.walletId);
|
|
108
50
|
const primaryRpcUrl = params.primaryRpcUrl.trim();
|
|
@@ -111,61 +53,14 @@ function configureSignerOwnedWalletNetwork(params) {
|
|
|
111
53
|
if (!primaryRpcUrl) {
|
|
112
54
|
throw new Error("signer-owned wallet network requires a primary RPC URL");
|
|
113
55
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
executionFallbackRpcUrl,
|
|
117
|
-
verificationRpcUrl
|
|
118
|
-
];
|
|
119
|
-
const hosting = String(env.FASED_HOST_PROFILE ?? "").trim().toLowerCase() === "hosting";
|
|
120
|
-
if (hosting) {
|
|
121
|
-
return {
|
|
122
|
-
walletId,
|
|
123
|
-
configured: false,
|
|
124
|
-
version: 0,
|
|
125
|
-
ready: false,
|
|
126
|
-
rootAdminRequired: true,
|
|
127
|
-
rootCommand: `/usr/local/sbin/fased-signer-network --wallet-id ${walletId} ` + "--network-file /root/fased-network.json"
|
|
128
|
-
};
|
|
56
|
+
if (executionFallbackRpcUrl || verificationRpcUrl) {
|
|
57
|
+
throw new Error("Normal wallet setup accepts one primary RPC. Configure an advanced execution fallback or explicit witness with the native signer admin network command.");
|
|
129
58
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
controlSocketPath,
|
|
136
|
-
"--wallet-id",
|
|
137
|
-
walletId
|
|
138
|
-
];
|
|
139
|
-
const current = parseSignerNetworkSummary(runSignerAdmin({
|
|
140
|
-
command: signerBinPath,
|
|
141
|
-
args: [
|
|
142
|
-
"admin",
|
|
143
|
-
"network",
|
|
144
|
-
"get",
|
|
145
|
-
...commonArgs
|
|
146
|
-
],
|
|
147
|
-
env: adminEnv,
|
|
148
|
-
secrets
|
|
149
|
-
}), walletId);
|
|
150
|
-
const input = `${JSON.stringify({
|
|
151
|
-
expectedVersion: current.version,
|
|
152
|
-
primaryRpcUrl,
|
|
153
|
-
...executionFallbackRpcUrl ? { executionFallbackRpcUrl } : {},
|
|
154
|
-
...verificationRpcUrl ? { verificationRpcUrl } : {}
|
|
155
|
-
})}\n`;
|
|
156
|
-
const updated = parseSignerNetworkSummary(runSignerAdmin({
|
|
157
|
-
command: signerBinPath,
|
|
158
|
-
args: [
|
|
159
|
-
"admin",
|
|
160
|
-
"network",
|
|
161
|
-
"put",
|
|
162
|
-
...commonArgs
|
|
163
|
-
],
|
|
164
|
-
input,
|
|
165
|
-
env: adminEnv,
|
|
166
|
-
secrets
|
|
167
|
-
}), walletId);
|
|
168
|
-
return assertReadyNetworkSummary(updated, current.version);
|
|
59
|
+
return configureSignerOwnedWalletPrimaryRpc({
|
|
60
|
+
socketPath: params.socketPath ?? resolveLocalSignerSocketPath(env),
|
|
61
|
+
walletId,
|
|
62
|
+
primaryRpcUrl
|
|
63
|
+
});
|
|
169
64
|
}
|
|
170
65
|
/**
|
|
171
66
|
* Hosted policy changes are deliberately unavailable to the app process. New signer-owned
|
|
@@ -181,9 +76,7 @@ function applyHostedSignerOwnedWalletPolicy(params) {
|
|
|
181
76
|
}
|
|
182
77
|
const __testing = {
|
|
183
78
|
canonicalSignerWalletId,
|
|
184
|
-
parseSignerNetworkSummary
|
|
185
|
-
redactSignerNetworkError,
|
|
186
|
-
signerAdminEnvironment
|
|
79
|
+
parseSignerNetworkSummary
|
|
187
80
|
};
|
|
188
81
|
|
|
189
82
|
//#endregion
|
|
@@ -35,9 +35,16 @@ const SIGNER_PROTOCOL_V2 = {
|
|
|
35
35
|
"atomicIdempotency",
|
|
36
36
|
"ambiguousBroadcastReconciliation",
|
|
37
37
|
"signerOwnedKeys",
|
|
38
|
+
"signerOwnedRoleBaselines",
|
|
39
|
+
"liveWalletReadiness",
|
|
38
40
|
"signerOwnedSuccessorRotation",
|
|
41
|
+
"signerOwnedMiningRetirementEvidence",
|
|
39
42
|
"permanentRetiredWalletPolicies",
|
|
40
43
|
"signerOwnedRPC",
|
|
44
|
+
"applicationNetworkBootstrap",
|
|
45
|
+
"signerOwnedEncryptedRecovery",
|
|
46
|
+
"signerOwnedRawExport",
|
|
47
|
+
"restrictedOperatorLifecycle",
|
|
41
48
|
"typedSolanaTransactions",
|
|
42
49
|
"typedA2aPaymentMemos",
|
|
43
50
|
"typedA2aRefundMemos",
|
|
@@ -74,7 +81,10 @@ const SIGNER_PROTOCOL_V2_REQUIRED_CLIENT_FEATURES = [
|
|
|
74
81
|
"atomicIdempotency",
|
|
75
82
|
"ambiguousBroadcastReconciliation",
|
|
76
83
|
"signerOwnedKeys",
|
|
84
|
+
"signerOwnedRoleBaselines",
|
|
85
|
+
"liveWalletReadiness",
|
|
77
86
|
"signerOwnedRPC",
|
|
87
|
+
"applicationNetworkBootstrap",
|
|
78
88
|
"typedSolanaTransactions",
|
|
79
89
|
"typedA2aPaymentMemos",
|
|
80
90
|
"typedA2aRefundMemos",
|