@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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fetchPinnedSolanaRpcRead } from "./solana-rpc-read-fetch.js";
|
|
1
2
|
import { PublicKey } from "@solana/web3.js";
|
|
2
3
|
|
|
3
4
|
//#region src/wallet/solana-assets.ts
|
|
@@ -427,10 +428,11 @@ function formatTokenAmount(raw, decimals) {
|
|
|
427
428
|
}
|
|
428
429
|
}
|
|
429
430
|
async function fetchSolanaRpc(rpcUrl, method, params) {
|
|
431
|
+
let release;
|
|
430
432
|
try {
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
433
|
+
const guarded = await fetchPinnedSolanaRpcRead({
|
|
434
|
+
rpcUrl,
|
|
435
|
+
timeoutMs: 1e4,
|
|
434
436
|
body: JSON.stringify({
|
|
435
437
|
jsonrpc: "2.0",
|
|
436
438
|
id: 1,
|
|
@@ -438,6 +440,8 @@ async function fetchSolanaRpc(rpcUrl, method, params) {
|
|
|
438
440
|
params
|
|
439
441
|
})
|
|
440
442
|
});
|
|
443
|
+
release = guarded.release;
|
|
444
|
+
const response = guarded.response;
|
|
441
445
|
if (!response.ok) {
|
|
442
446
|
recordSolanaAssetRpcMethod(method, "failure");
|
|
443
447
|
return null;
|
|
@@ -452,6 +456,8 @@ async function fetchSolanaRpc(rpcUrl, method, params) {
|
|
|
452
456
|
} catch {
|
|
453
457
|
recordSolanaAssetRpcMethod(method, "failure");
|
|
454
458
|
return null;
|
|
459
|
+
} finally {
|
|
460
|
+
await release?.();
|
|
455
461
|
}
|
|
456
462
|
}
|
|
457
463
|
async function fetchSolanaMetadataFromMintViaRpc(params) {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { closeDispatcher, createPinnedDispatcher, resolvePinnedHostnameWithPolicy } from "../infra/net/ssrf.js";
|
|
2
|
+
|
|
3
|
+
//#region src/wallet/solana-rpc-read-fetch.ts
|
|
4
|
+
function normalizeRpcHostname(hostname) {
|
|
5
|
+
const normalized = hostname.trim().toLowerCase().replace(/\.$/, "");
|
|
6
|
+
return normalized.startsWith("[") && normalized.endsWith("]") ? normalized.slice(1, -1) : normalized;
|
|
7
|
+
}
|
|
8
|
+
function isLoopbackRpcHostname(hostname) {
|
|
9
|
+
const normalized = normalizeRpcHostname(hostname);
|
|
10
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
11
|
+
}
|
|
12
|
+
function isLoopbackRpcAddress(address) {
|
|
13
|
+
const normalized = normalizeRpcHostname(address);
|
|
14
|
+
return normalized === "::1" || normalized === "0:0:0:0:0:0:0:1" || /^127(?:\.\d{1,3}){3}$/.test(normalized) || /^::ffff:127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
15
|
+
}
|
|
16
|
+
async function resolveWithTimeout(hostname, policy, timeoutMs) {
|
|
17
|
+
let timer;
|
|
18
|
+
try {
|
|
19
|
+
return await Promise.race([resolvePinnedHostnameWithPolicy(hostname, { policy }), new Promise((_resolve, reject) => {
|
|
20
|
+
timer = setTimeout(() => reject(new Error("stored Solana RPC hostname resolution timed out")), Math.max(250, timeoutMs));
|
|
21
|
+
timer.unref?.();
|
|
22
|
+
})]);
|
|
23
|
+
} finally {
|
|
24
|
+
if (timer) {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function fetchPinnedSolanaRpcRead(params) {
|
|
30
|
+
const parsed = new URL(params.rpcUrl);
|
|
31
|
+
const hostname = normalizeRpcHostname(parsed.hostname);
|
|
32
|
+
const loopback = isLoopbackRpcHostname(hostname);
|
|
33
|
+
if (!hostname || parsed.username || parsed.password || parsed.hash || parsed.protocol !== "https:" && !(parsed.protocol === "http:" && loopback)) {
|
|
34
|
+
throw new Error("stored Solana RPC URL is not safe for Gateway reads");
|
|
35
|
+
}
|
|
36
|
+
const policy = {
|
|
37
|
+
hostnameAllowlist: [hostname],
|
|
38
|
+
...loopback ? { allowPrivateNetwork: true } : {}
|
|
39
|
+
};
|
|
40
|
+
const pinned = await resolveWithTimeout(hostname, policy, params.timeoutMs);
|
|
41
|
+
if (loopback && !pinned.addresses.every(isLoopbackRpcAddress)) {
|
|
42
|
+
throw new Error("stored Local Solana RPC hostname did not resolve only to loopback addresses");
|
|
43
|
+
}
|
|
44
|
+
const dispatcher = createPinnedDispatcher(pinned);
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(parsed.toString(), {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: { "content-type": "application/json" },
|
|
49
|
+
body: params.body,
|
|
50
|
+
redirect: "error",
|
|
51
|
+
signal: AbortSignal.timeout(Math.max(250, params.timeoutMs)),
|
|
52
|
+
dispatcher
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
response,
|
|
56
|
+
release: async () => closeDispatcher(dispatcher)
|
|
57
|
+
};
|
|
58
|
+
} catch (error) {
|
|
59
|
+
await closeDispatcher(dispatcher);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
65
|
+
export { fetchPinnedSolanaRpcRead };
|
|
@@ -42,16 +42,12 @@ function resolveWalletActionSelection(params) {
|
|
|
42
42
|
providerId: params.providerId,
|
|
43
43
|
env
|
|
44
44
|
});
|
|
45
|
-
} else if (registry.defaultWalletId) {
|
|
46
|
-
const fallback = registry.wallets.find((entry) => entry.id === registry.defaultWalletId);
|
|
47
|
-
selection = fallback ? {
|
|
48
|
-
walletId: fallback.id,
|
|
49
|
-
walletName: fallback.name,
|
|
50
|
-
providerId: fallback.providerId,
|
|
51
|
-
source: "fallback"
|
|
52
|
-
} : { source: "none" };
|
|
53
45
|
} else {
|
|
54
|
-
selection = {
|
|
46
|
+
selection = resolveWalletSelection({
|
|
47
|
+
agentId: params.agentId,
|
|
48
|
+
skillWalletId: params.skillWalletId,
|
|
49
|
+
env
|
|
50
|
+
});
|
|
55
51
|
}
|
|
56
52
|
} catch (error) {
|
|
57
53
|
const message = error instanceof Error ? error.message : "wallet selection failed";
|
|
@@ -61,7 +57,7 @@ function resolveWalletActionSelection(params) {
|
|
|
61
57
|
throw new WalletActionSelectionError("wallet_not_found", message);
|
|
62
58
|
}
|
|
63
59
|
if (!selection.walletId) {
|
|
64
|
-
throw new WalletActionSelectionError("wallet_handle_required", "Agent wallet
|
|
60
|
+
throw new WalletActionSelectionError("wallet_handle_required", "Select an Agent wallet: use an explicit wallet, skill override, Agent assignment, or Default Agent wallet fallback");
|
|
65
61
|
}
|
|
66
62
|
const wallet = registry.wallets.find((entry) => entry.id === selection.walletId);
|
|
67
63
|
if (!wallet) {
|
|
@@ -479,9 +479,6 @@ function upsertNamedWallet(params) {
|
|
|
479
479
|
updatedAt: now
|
|
480
480
|
};
|
|
481
481
|
registry.wallets = [...registry.wallets.filter((entry) => entry.id !== next.id), next].toSorted((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
482
|
-
if (!registry.defaultWalletId || !registry.wallets.some((wallet) => wallet.id === registry.defaultWalletId)) {
|
|
483
|
-
registry.defaultWalletId = resolveWalletUserRole(next) === "agent" ? next.id : undefined;
|
|
484
|
-
}
|
|
485
482
|
writeWalletProviderRegistry(registry, env);
|
|
486
483
|
return next;
|
|
487
484
|
}
|
|
@@ -497,6 +494,10 @@ function deleteNamedWallet(params) {
|
|
|
497
494
|
walletId,
|
|
498
495
|
env
|
|
499
496
|
});
|
|
497
|
+
const targetWallet = registry.wallets.find((wallet) => wallet.id === walletId);
|
|
498
|
+
if (resolveWalletUserRole(targetWallet) === "mining") {
|
|
499
|
+
throw new Error("Mining wallets cannot be deleted directly; use Retire and replace Mining wallet so signer acknowledgement precedes registry detachment");
|
|
500
|
+
}
|
|
500
501
|
const before = registry.wallets.length;
|
|
501
502
|
registry.wallets = registry.wallets.filter((entry) => entry.id !== walletId);
|
|
502
503
|
for (const [agentId, assignedWalletId] of Object.entries(registry.assignments)) {
|
|
@@ -514,6 +515,50 @@ function deleteNamedWallet(params) {
|
|
|
514
515
|
registry
|
|
515
516
|
};
|
|
516
517
|
}
|
|
518
|
+
function replaceRetiredMiningWallet(params) {
|
|
519
|
+
const env = params.env ?? process.env;
|
|
520
|
+
const registry = readWalletProviderRegistry(env);
|
|
521
|
+
const sourceWalletId = params.sourceWalletId.trim();
|
|
522
|
+
if (!/^sha256:[0-9a-f]{64}$/u.test(params.signerAcknowledgement.rotationId) || !/^sha256:[0-9a-f]{64}$/u.test(params.signerAcknowledgement.sourceRetiredPolicyHash) || !/^sha256:[0-9a-f]{64}$/u.test(params.signerAcknowledgement.successorPolicyHash) || params.signerAcknowledgement.successorPublicKey !== params.successor.addresses?.solana || params.successor.metadata?.rotationId !== params.signerAcknowledgement.rotationId || params.successor.metadata?.policyHash !== params.signerAcknowledgement.successorPolicyHash) {
|
|
523
|
+
throw new Error("signer retirement acknowledgement is missing or does not match the successor");
|
|
524
|
+
}
|
|
525
|
+
const sourceIndex = registry.wallets.findIndex((wallet) => wallet.id === sourceWalletId);
|
|
526
|
+
if (sourceIndex < 0) {
|
|
527
|
+
const existing = registry.wallets.find((wallet) => wallet.id === params.successor.id);
|
|
528
|
+
if (existing?.providerId === "local-socket-signer" && existing.addresses?.solana === params.successor.addresses?.solana && resolveWalletUserRole(existing) === "mining") {
|
|
529
|
+
return existing;
|
|
530
|
+
}
|
|
531
|
+
throw new Error("retired Mining source registration is missing");
|
|
532
|
+
}
|
|
533
|
+
const source = registry.wallets[sourceIndex];
|
|
534
|
+
if (resolveWalletUserRole(source) !== "mining") {
|
|
535
|
+
throw new Error("source registration is not the active Mining wallet");
|
|
536
|
+
}
|
|
537
|
+
if (params.successor.id === sourceWalletId || registry.wallets.some((wallet) => wallet.id === params.successor.id)) {
|
|
538
|
+
throw new Error("Mining successor registration must use a new wallet id");
|
|
539
|
+
}
|
|
540
|
+
assertNamedWalletDeletionSafe({
|
|
541
|
+
walletId: sourceWalletId,
|
|
542
|
+
env
|
|
543
|
+
});
|
|
544
|
+
const now = nowIso();
|
|
545
|
+
const successor = {
|
|
546
|
+
...params.successor,
|
|
547
|
+
createdAt: now,
|
|
548
|
+
updatedAt: now
|
|
549
|
+
};
|
|
550
|
+
registry.wallets.splice(sourceIndex, 1, successor);
|
|
551
|
+
for (const [agentId, assignedWalletId] of Object.entries(registry.assignments)) {
|
|
552
|
+
if (assignedWalletId === sourceWalletId) {
|
|
553
|
+
delete registry.assignments[agentId];
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (registry.defaultWalletId === sourceWalletId) {
|
|
557
|
+
registry.defaultWalletId = undefined;
|
|
558
|
+
}
|
|
559
|
+
writeWalletProviderRegistry(registry, env);
|
|
560
|
+
return successor;
|
|
561
|
+
}
|
|
517
562
|
function setAgentWalletAssignment(params) {
|
|
518
563
|
const env = params.env ?? process.env;
|
|
519
564
|
const registry = readWalletProviderRegistry(env);
|
|
@@ -527,9 +572,13 @@ function setAgentWalletAssignment(params) {
|
|
|
527
572
|
writeWalletProviderRegistry(registry, env);
|
|
528
573
|
return registry;
|
|
529
574
|
}
|
|
530
|
-
|
|
575
|
+
const wallet = registry.wallets.find((entry) => entry.id === walletId);
|
|
576
|
+
if (!wallet) {
|
|
531
577
|
throw new Error("walletId does not exist");
|
|
532
578
|
}
|
|
579
|
+
if (resolveWalletUserRole(wallet) !== "agent") {
|
|
580
|
+
throw new Error("only Agent wallets can be assigned to an Agent");
|
|
581
|
+
}
|
|
533
582
|
registry.assignments[agentId] = walletId;
|
|
534
583
|
writeWalletProviderRegistry(registry, env);
|
|
535
584
|
return registry;
|
|
@@ -548,23 +597,9 @@ function setDefaultWallet(params) {
|
|
|
548
597
|
throw new Error("walletId does not exist");
|
|
549
598
|
}
|
|
550
599
|
const purpose = resolveWalletUserRole(targetWallet);
|
|
551
|
-
if (purpose
|
|
552
|
-
throw new Error("only Agent
|
|
600
|
+
if (purpose !== "agent") {
|
|
601
|
+
throw new Error("only an explicit Agent wallet can become the Default Agent wallet fallback");
|
|
553
602
|
}
|
|
554
|
-
registry.wallets = registry.wallets.map((wallet) => {
|
|
555
|
-
if (wallet.id !== walletId) {
|
|
556
|
-
return wallet;
|
|
557
|
-
}
|
|
558
|
-
return {
|
|
559
|
-
...wallet,
|
|
560
|
-
metadata: {
|
|
561
|
-
...wallet.metadata,
|
|
562
|
-
role: "agent",
|
|
563
|
-
purpose: "agent"
|
|
564
|
-
},
|
|
565
|
-
updatedAt: nowIso()
|
|
566
|
-
};
|
|
567
|
-
});
|
|
568
603
|
registry.defaultWalletId = walletId;
|
|
569
604
|
writeWalletProviderRegistry(registry, env);
|
|
570
605
|
return registry;
|
|
@@ -588,12 +623,15 @@ function setNamedWalletRole(params) {
|
|
|
588
623
|
},
|
|
589
624
|
updatedAt: nowIso()
|
|
590
625
|
} : wallet);
|
|
591
|
-
if (params.role
|
|
592
|
-
registry.defaultWalletId =
|
|
626
|
+
if (params.role !== "agent" && registry.defaultWalletId === walletId) {
|
|
627
|
+
registry.defaultWalletId = undefined;
|
|
593
628
|
}
|
|
594
|
-
if (params.role
|
|
595
|
-
const
|
|
596
|
-
|
|
629
|
+
if (params.role !== "agent") {
|
|
630
|
+
for (const [agentId, assignedWalletId] of Object.entries(registry.assignments)) {
|
|
631
|
+
if (assignedWalletId === walletId) {
|
|
632
|
+
delete registry.assignments[agentId];
|
|
633
|
+
}
|
|
634
|
+
}
|
|
597
635
|
}
|
|
598
636
|
writeWalletProviderRegistry(registry, env);
|
|
599
637
|
return registry;
|
|
@@ -603,7 +641,8 @@ function resolveWalletSelectionForAgent(params) {
|
|
|
603
641
|
const registry = readWalletProviderRegistry(env);
|
|
604
642
|
const directAgent = params.agentId?.trim();
|
|
605
643
|
const directWalletId = directAgent ? registry.assignments[directAgent] : undefined;
|
|
606
|
-
const
|
|
644
|
+
const skillWalletId = params.skillWalletId?.trim();
|
|
645
|
+
const walletId = skillWalletId ?? directWalletId ?? registry.defaultWalletId;
|
|
607
646
|
if (!walletId) {
|
|
608
647
|
return {};
|
|
609
648
|
}
|
|
@@ -614,7 +653,8 @@ function resolveWalletSelectionForAgent(params) {
|
|
|
614
653
|
return {
|
|
615
654
|
walletId: wallet.id,
|
|
616
655
|
walletName: wallet.name,
|
|
617
|
-
providerId: wallet.providerId
|
|
656
|
+
providerId: wallet.providerId,
|
|
657
|
+
source: skillWalletId ? "skill" : directWalletId ? "agent" : "default"
|
|
618
658
|
};
|
|
619
659
|
}
|
|
620
660
|
function resolveWalletSelection(params) {
|
|
@@ -676,16 +716,17 @@ function resolveWalletSelection(params) {
|
|
|
676
716
|
}
|
|
677
717
|
const fallback = resolveWalletSelectionForAgent({
|
|
678
718
|
agentId: params.agentId,
|
|
719
|
+
skillWalletId: params.skillWalletId,
|
|
679
720
|
env
|
|
680
721
|
});
|
|
681
722
|
if (fallback.walletId || fallback.providerId) {
|
|
682
723
|
return {
|
|
683
724
|
...fallback,
|
|
684
|
-
source: "fallback"
|
|
725
|
+
source: fallback.source ?? "fallback"
|
|
685
726
|
};
|
|
686
727
|
}
|
|
687
728
|
return { source: "none" };
|
|
688
729
|
}
|
|
689
730
|
|
|
690
731
|
//#endregion
|
|
691
|
-
export { WALLET_PROVIDER_IDS, checkNamedWalletDeletionSafety, deleteNamedWallet, normalizeWalletUserRole, readWalletProviderRegistry, resolveWalletSelection, resolveWalletUserRole, setAgentWalletAssignment, setDefaultWallet, setNamedWalletRole, setWalletProviderEnabled, setWalletProvidersEnabled, upsertNamedWallet };
|
|
732
|
+
export { WALLET_PROVIDER_IDS, checkNamedWalletDeletionSafety, deleteNamedWallet, normalizeWalletUserRole, readWalletProviderRegistry, replaceRetiredMiningWallet, resolveWalletSelection, resolveWalletUserRole, setAgentWalletAssignment, setDefaultWallet, setNamedWalletRole, setWalletProviderEnabled, setWalletProvidersEnabled, upsertNamedWallet, writeWalletProviderRegistry };
|
|
@@ -2126,7 +2126,11 @@ async function approveWalletSendRequest(params) {
|
|
|
2126
2126
|
request
|
|
2127
2127
|
};
|
|
2128
2128
|
}
|
|
2129
|
-
|
|
2129
|
+
const controlUIAuthorization = storedReview.state === "prepared" && !params.reviewAuthorization && (storedReview.intentType === "solana.nativeTransfer" || storedReview.intentType === "solana.splTransferChecked") ? {
|
|
2130
|
+
type: "control-ui",
|
|
2131
|
+
proof: { proofId: storedReview.nonce }
|
|
2132
|
+
} : undefined;
|
|
2133
|
+
if (storedReview.state === "prepared" && !params.reviewAuthorization && !controlUIAuthorization) {
|
|
2130
2134
|
if (claim.recovered && request.status === "executing") {
|
|
2131
2135
|
await withApprovalMutationLock(env, () => {
|
|
2132
2136
|
file = loadFile(env);
|
|
@@ -2151,7 +2155,7 @@ async function approveWalletSendRequest(params) {
|
|
|
2151
2155
|
request
|
|
2152
2156
|
};
|
|
2153
2157
|
}
|
|
2154
|
-
const executionAuthorization = storedReview.state === "prepared" ? params.reviewAuthorization : undefined;
|
|
2158
|
+
const executionAuthorization = storedReview.state === "prepared" ? params.reviewAuthorization ?? controlUIAuthorization : undefined;
|
|
2155
2159
|
let executed;
|
|
2156
2160
|
try {
|
|
2157
2161
|
executed = await provider.executeSignerReview({
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { loadConfig } from "../config/io.js";
|
|
2
2
|
import "../config/config.js";
|
|
3
|
-
import { ensureWalletStateDir, resolveWalletRuntimeConfig, resolveWalletStatePaths } from "./wallet-runtime-config.js";
|
|
3
|
+
import { ensureWalletStateDir, resolveLocalSignerSocketPath, resolveWalletRuntimeConfig, resolveWalletStatePaths } from "./wallet-runtime-config.js";
|
|
4
4
|
import { readWalletProviderRegistry } from "./wallet-provider-registry.js";
|
|
5
5
|
import { resolveWalletPolicyConfig } from "./wallet-policy.js";
|
|
6
6
|
import { redactWalletDiagnosticText, walletDiagnosticErrorMessage, walletDiagnosticErrorString } from "./wallet-redaction.js";
|
|
7
7
|
import { createWalletProviderAdapter, resolveWalletProviderId } from "./wallet-provider-resolver.js";
|
|
8
|
+
import { readSignerOwnedWalletReadiness } from "./local-socket-signer-lifecycle.js";
|
|
9
|
+
import { normalizeNativeSignerWalletId } from "./native-signer-wallet-id.js";
|
|
8
10
|
import { readWalletApprovalAuthSnapshot } from "./wallet-approval-auth.js";
|
|
9
11
|
|
|
10
12
|
//#region src/wallet/wallet-status.ts
|
|
@@ -26,8 +28,12 @@ async function readWalletStatusSnapshot(params) {
|
|
|
26
28
|
const statePaths = resolveWalletStatePaths(effectiveEnv);
|
|
27
29
|
const approvalAuth = readWalletApprovalAuthSnapshot(effectiveEnv, cfg);
|
|
28
30
|
const checkedAt = new Date().toISOString();
|
|
31
|
+
const registeredWallets = params?.walletId ? providerRegistry.wallets.filter((wallet) => wallet.id === params.walletId) : providerRegistry.wallets;
|
|
29
32
|
let providerHealth = {
|
|
30
33
|
ok: false,
|
|
34
|
+
provider: providerId,
|
|
35
|
+
configured: false,
|
|
36
|
+
checkedAt,
|
|
31
37
|
details: "provider health probe unavailable"
|
|
32
38
|
};
|
|
33
39
|
let addresses;
|
|
@@ -53,6 +59,9 @@ async function readWalletStatusSnapshot(params) {
|
|
|
53
59
|
} catch (err) {
|
|
54
60
|
providerHealth = {
|
|
55
61
|
ok: false,
|
|
62
|
+
provider: providerId,
|
|
63
|
+
configured: false,
|
|
64
|
+
checkedAt,
|
|
56
65
|
details: walletDiagnosticErrorString(err)
|
|
57
66
|
};
|
|
58
67
|
}
|
|
@@ -71,6 +80,58 @@ async function readWalletStatusSnapshot(params) {
|
|
|
71
80
|
summary: "Real-chain settlement depends on the configured wallet provider and RPC connectivity."
|
|
72
81
|
},
|
|
73
82
|
chains: resolved.chains,
|
|
83
|
+
wallets: await Promise.all(registeredWallets.map(async (wallet) => {
|
|
84
|
+
if (wallet.providerId !== "local-socket-signer") {
|
|
85
|
+
return {
|
|
86
|
+
id: wallet.id,
|
|
87
|
+
name: wallet.name,
|
|
88
|
+
providerId: wallet.providerId,
|
|
89
|
+
addresses: wallet.addresses,
|
|
90
|
+
readiness: {
|
|
91
|
+
keystore: Boolean(wallet.addresses?.solana),
|
|
92
|
+
rpc: serviceHealthy,
|
|
93
|
+
ready: serviceHealthy && Boolean(wallet.addresses?.solana)
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const metadataSignerWalletId = typeof wallet.metadata?.signerWalletId === "string" ? wallet.metadata.signerWalletId.trim() : "";
|
|
98
|
+
const signerWalletId = metadataSignerWalletId || normalizeNativeSignerWalletId(wallet.id);
|
|
99
|
+
try {
|
|
100
|
+
const signer = await readSignerOwnedWalletReadiness({
|
|
101
|
+
socketPath: resolveLocalSignerSocketPath(effectiveEnv),
|
|
102
|
+
walletId: signerWalletId
|
|
103
|
+
});
|
|
104
|
+
const addressMatches = typeof wallet.addresses?.solana === "string" && wallet.addresses.solana === signer.publicKey;
|
|
105
|
+
const roleMatches = typeof wallet.metadata?.role === "string" && wallet.metadata.role === signer.role;
|
|
106
|
+
const ready = signer.ready && addressMatches && roleMatches;
|
|
107
|
+
return {
|
|
108
|
+
id: wallet.id,
|
|
109
|
+
name: wallet.name,
|
|
110
|
+
providerId: wallet.providerId,
|
|
111
|
+
addresses: wallet.addresses,
|
|
112
|
+
readiness: {
|
|
113
|
+
keystore: signer.keyReady,
|
|
114
|
+
rpc: signer.networkReady,
|
|
115
|
+
ready,
|
|
116
|
+
...!ready && signer.ready ? { error: "registry address or immutable role does not match live signer state" } : {},
|
|
117
|
+
signer
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
} catch (error) {
|
|
121
|
+
return {
|
|
122
|
+
id: wallet.id,
|
|
123
|
+
name: wallet.name,
|
|
124
|
+
providerId: wallet.providerId,
|
|
125
|
+
addresses: wallet.addresses,
|
|
126
|
+
readiness: {
|
|
127
|
+
keystore: false,
|
|
128
|
+
rpc: false,
|
|
129
|
+
ready: false,
|
|
130
|
+
error: walletDiagnosticErrorMessage(error)
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
})),
|
|
74
135
|
service: {
|
|
75
136
|
host: resolved.service.host,
|
|
76
137
|
port: resolved.service.port,
|
|
@@ -90,6 +151,7 @@ async function readWalletStatusSnapshot(params) {
|
|
|
90
151
|
}
|
|
91
152
|
},
|
|
92
153
|
approvalAuth,
|
|
154
|
+
...providerHealth.nativeSignerApproval ? { nativeSignerApproval: providerHealth.nativeSignerApproval } : {},
|
|
93
155
|
addresses,
|
|
94
156
|
paths: {
|
|
95
157
|
rootDir: paths.rootDir,
|
package/dist/web/login-qr.js
CHANGED
|
@@ -5,8 +5,8 @@ import { loadConfig } from "../config/io.js";
|
|
|
5
5
|
import "../config/config.js";
|
|
6
6
|
import { logoutWeb, readWebSelfId, webAuthExists } from "./auth-store.js";
|
|
7
7
|
import { resolveWhatsAppAccount } from "./accounts.js";
|
|
8
|
-
import { createWaSocket, formatError, getStatusCode, waitForWaConnection } from "./session.js";
|
|
9
8
|
import { renderQrPngBase64 } from "./qr-image.js";
|
|
9
|
+
import { createWaSocket, formatError, getStatusCode, waitForWaConnection } from "./session.js";
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
11
|
import { DisconnectReason } from "@whiskeysockets/baileys";
|
|
12
12
|
|