shinjuku-shielded 0.3.30 → 0.3.32
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/manifest.json +3 -3
- package/package.json +3 -3
- package/shinjuku-wallet.mjs +188 -42
package/manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "carbon-shielded-wallet/bundle-manifest/v1",
|
|
3
3
|
"file": "shinjuku-wallet.mjs",
|
|
4
|
-
"sha256": "
|
|
5
|
-
"bytes":
|
|
6
|
-
"sourceCommit": "
|
|
4
|
+
"sha256": "3ec79a8335ea99f87cf8f2c34ea8723c70a30bd6f30fc5c0fb177edfa1816714",
|
|
5
|
+
"bytes": 11184498,
|
|
6
|
+
"sourceCommit": "8bd35a850efa3fb8dac143ea02a6d02a3f4008c6",
|
|
7
7
|
"sourceDirty": false,
|
|
8
8
|
"installRecordMatchesLockfile": true,
|
|
9
9
|
"releaseRule": "valid only when two fresh npm ci --ignore-scripts builds on different OSes give the same sha256; installRecordMatchesLockfile true means every entry npm installed equals its package-lock.json entry and every entry not marked optional, devOptional included, is installed: an optional entry (a package for another platform) may be absent",
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shielded",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.32",
|
|
4
4
|
"mcpName": "io.github.ShinjukuStaition/shinjuku-mcp",
|
|
5
5
|
"description": "Shinjuku Shielded, the private x402 facilitator on Solana: the self-custody wallet CLI and its MCP server. Shield, pay, and unshield USDC from any MCP agent, under caps you set.",
|
|
6
|
-
"shinjukuRelease": "
|
|
7
|
-
"shinjukuSha256": "
|
|
6
|
+
"shinjukuRelease": "3ec79a83",
|
|
7
|
+
"shinjukuSha256": "3ec79a8335ea99f87cf8f2c34ea8723c70a30bd6f30fc5c0fb177edfa1816714",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
9
9
|
"author": "Shinjuku Shielded",
|
|
10
10
|
"homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
|
package/shinjuku-wallet.mjs
CHANGED
|
@@ -50445,8 +50445,9 @@ function createMemoReader(baseUrl, { fetchImpl = fetch, pause: pause3 = pauseFor
|
|
|
50445
50445
|
};
|
|
50446
50446
|
const origin = new URL(baseUrl).origin;
|
|
50447
50447
|
const keyOf2 = (digest2) => `${origin}|${digest2}`;
|
|
50448
|
-
|
|
50449
|
-
|
|
50448
|
+
const aheadKey = typeof fetchImpl?.baseFetch === "function" ? fetchImpl.baseFetch : fetchImpl;
|
|
50449
|
+
let ahead = prefetchedMemosByFetch.get(aheadKey);
|
|
50450
|
+
if (ahead === void 0) prefetchedMemosByFetch.set(aheadKey, ahead = /* @__PURE__ */ new Map());
|
|
50450
50451
|
const live = (key) => {
|
|
50451
50452
|
const entry = ahead.get(key);
|
|
50452
50453
|
if (entry !== void 0 && now() - entry.at > MEMO_PREFETCH_LIFE_MS) ahead.delete(key);
|
|
@@ -54852,6 +54853,23 @@ function foldCompactLeaves(leaves, counts) {
|
|
|
54852
54853
|
});
|
|
54853
54854
|
return roots;
|
|
54854
54855
|
}
|
|
54856
|
+
function foldCompactLeavesReusing(pool2, leaves, counts) {
|
|
54857
|
+
const prior = lastFolds.get(pool2);
|
|
54858
|
+
let common = 0;
|
|
54859
|
+
if (prior !== void 0) {
|
|
54860
|
+
const most = Math.min(prior.leaves.length, leaves.length);
|
|
54861
|
+
while (common < most && prior.leaves[common] === leaves[common]) common += 1;
|
|
54862
|
+
}
|
|
54863
|
+
const known = (at) => prior !== void 0 && at <= common && prior.roots.has(at);
|
|
54864
|
+
const roots = foldCompactLeaves(leaves, new Set([...counts].filter((at) => !known(at))));
|
|
54865
|
+
for (const at of counts) if (known(at)) roots.set(at, prior.roots.get(at));
|
|
54866
|
+
const kept = new Map(roots);
|
|
54867
|
+
if (prior !== void 0) {
|
|
54868
|
+
for (const [at, root] of prior.roots) if (at <= common && !kept.has(at)) kept.set(at, root);
|
|
54869
|
+
}
|
|
54870
|
+
lastFolds.set(pool2, { leaves: leaves.slice(), roots: kept });
|
|
54871
|
+
return roots;
|
|
54872
|
+
}
|
|
54855
54873
|
function fieldOf(hex4) {
|
|
54856
54874
|
if (typeof hex4 !== "string" || !HEX64.test(hex4)) throw refuse3("p03_compact_history_record_invalid");
|
|
54857
54875
|
const value = BigInt(`0x${hex4}`);
|
|
@@ -55062,7 +55080,7 @@ function withBoundedOwnReads(connection) {
|
|
|
55062
55080
|
}
|
|
55063
55081
|
});
|
|
55064
55082
|
}
|
|
55065
|
-
async function readPages(history, pool2, needed, first) {
|
|
55083
|
+
async function readPages(history, pool2, needed, first, { wakeSlot } = {}) {
|
|
55066
55084
|
const records = [];
|
|
55067
55085
|
const imports = [];
|
|
55068
55086
|
let initialization;
|
|
@@ -55093,7 +55111,19 @@ async function readPages(history, pool2, needed, first) {
|
|
|
55093
55111
|
initialization = result.initialization;
|
|
55094
55112
|
syncedSlot = result.syncedSlot;
|
|
55095
55113
|
records.push(...result.records);
|
|
55096
|
-
if (result.total < needed)
|
|
55114
|
+
if (result.total < needed) {
|
|
55115
|
+
if (isIndex(wakeSlot)) {
|
|
55116
|
+
Promise.resolve().then(() => history._rpcRequest("getP03Transitions", [pool2, {
|
|
55117
|
+
commitment: "finalized",
|
|
55118
|
+
fromOrdinal: 0,
|
|
55119
|
+
toOrdinal: 1,
|
|
55120
|
+
minContextSlot: wakeSlot
|
|
55121
|
+
}])).catch(() => {
|
|
55122
|
+
});
|
|
55123
|
+
markPhase("compact-behind-wake");
|
|
55124
|
+
}
|
|
55125
|
+
throw refuse3("p03_compact_history_source_behind");
|
|
55126
|
+
}
|
|
55097
55127
|
}
|
|
55098
55128
|
return { records: records.slice(0, needed), imports, initialization, syncedSlot };
|
|
55099
55129
|
}
|
|
@@ -55322,7 +55352,12 @@ async function readCompactP03History({
|
|
|
55322
55352
|
knownSnapshot,
|
|
55323
55353
|
// compactP03HistoryReport: run beside the spot checks once the initialization is verified
|
|
55324
55354
|
// ({ snapshot, initialization, contexts }); its result comes back as `alongside`.
|
|
55325
|
-
alongside
|
|
55355
|
+
alongside,
|
|
55356
|
+
// Called once with the served contexts in chain order, before the fold and every own-RPC
|
|
55357
|
+
// check: they are NOT verified yet. A payment asks the memo service for their memos here
|
|
55358
|
+
// (payAndFetch.mjs), and uses an answer only for a context the verified report names. Its
|
|
55359
|
+
// result and any throw are ignored.
|
|
55360
|
+
onList
|
|
55326
55361
|
}) {
|
|
55327
55362
|
const program = new import_web397.PublicKey(programId);
|
|
55328
55363
|
const poolKey = new import_web397.PublicKey(pool2);
|
|
@@ -55349,7 +55384,7 @@ async function readCompactP03History({
|
|
|
55349
55384
|
initialization: served.initialization,
|
|
55350
55385
|
syncedSlot: served.syncedSlot,
|
|
55351
55386
|
cached: true
|
|
55352
|
-
} : await readPages(source, poolString, count2, first);
|
|
55387
|
+
} : await readPages(source, poolString, count2, first, { wakeSlot: snapshot.slot });
|
|
55353
55388
|
markPhase(page.cached === true ? "compact-list-cached" : "compact-list");
|
|
55354
55389
|
const binding = {
|
|
55355
55390
|
programId: programString,
|
|
@@ -55375,6 +55410,10 @@ async function readCompactP03History({
|
|
|
55375
55410
|
}
|
|
55376
55411
|
});
|
|
55377
55412
|
const imports = orderCompactImports(page.imports, contexts, { snapshot, replay });
|
|
55413
|
+
try {
|
|
55414
|
+
onList?.(contexts);
|
|
55415
|
+
} catch {
|
|
55416
|
+
}
|
|
55378
55417
|
const picks = [];
|
|
55379
55418
|
const order = [...contexts.keys()];
|
|
55380
55419
|
const checks = page.cached === true ? 0 : spotChecks;
|
|
@@ -55406,7 +55445,7 @@ async function readCompactP03History({
|
|
|
55406
55445
|
for (const anchor of anchors) counts.add(Number(anchor.index / SUBTREE_LEAVES3));
|
|
55407
55446
|
if (appendRoots) for (let at = 1; at <= count2; at += 1) counts.add(at);
|
|
55408
55447
|
for (const at of counts) if (at > count2) throw refuse3("p03_compact_history_snapshot_invalid");
|
|
55409
|
-
roots =
|
|
55448
|
+
roots = foldCompactLeavesReusing(poolString, contexts.map((context) => context.outCommitment), counts);
|
|
55410
55449
|
if (roots.get(count2) !== snapshot.currentRoot) throw refuse3("p03_compact_history_root_mismatch");
|
|
55411
55450
|
for (const anchor of anchors) {
|
|
55412
55451
|
if (roots.get(Number(anchor.index / SUBTREE_LEAVES3)) !== anchor.root) throw refuse3("p03_compact_history_root_mismatch");
|
|
@@ -55470,7 +55509,8 @@ async function compactP03HistoryReport({
|
|
|
55470
55509
|
forceRead = false,
|
|
55471
55510
|
freshMs = 0,
|
|
55472
55511
|
priorAttestation,
|
|
55473
|
-
knownSnapshot
|
|
55512
|
+
knownSnapshot,
|
|
55513
|
+
onList
|
|
55474
55514
|
}) {
|
|
55475
55515
|
if (deploymentIdentity === void 0) throw new Error("p03_history_deployment_identity_required");
|
|
55476
55516
|
const program = new import_web397.PublicKey(programId);
|
|
@@ -55539,6 +55579,7 @@ async function compactP03HistoryReport({
|
|
|
55539
55579
|
pool: pool2,
|
|
55540
55580
|
alongside: attest,
|
|
55541
55581
|
...knownSnapshot !== void 0 ? { knownSnapshot } : {},
|
|
55582
|
+
...onList !== void 0 ? { onList } : {},
|
|
55542
55583
|
...warm ? { served: cached.served } : {},
|
|
55543
55584
|
...cached ? { initialization: cached.initialization } : {}
|
|
55544
55585
|
});
|
|
@@ -55616,7 +55657,7 @@ async function tryCompactP03HistoryReport(options) {
|
|
|
55616
55657
|
return { ok: false, reason: refusalReason(error), ...typeof error?.detail === "string" ? { detail: error.detail } : {}, error };
|
|
55617
55658
|
}
|
|
55618
55659
|
}
|
|
55619
|
-
var import_web397, P03_COMPACT_HISTORY_SOURCE_MODEL, P03_COMPACT_PAGE, P03_COMPACT_SPOT_CHECKS, FIELD_MODULUS5, SUBTREE_LEAVES3, LOCAL_DEPTH2, OUTER_DEPTH2, PRIMARY_PROOF_BYTES2, FIELD_BYTES3, ED25519_SPKI_PREFIX2, VERSION_1_PREFIX2, HEX64, BASE58, REPLAY_STORE_INDEXED2, PROFILES2, MOVE_HEAD_BYTES2, MOVE_INSERTED_VALUES2, refuse3, hash4, bitAt, zeroRootsMemo, isSignature, isIndex, IMPORT_KEYS, IMPORT_MAX_VALUES, LIST_ATTEMPTS, OWN_READ_TIMEOUT_MS, BOUNDED_OWN_METHODS;
|
|
55660
|
+
var import_web397, P03_COMPACT_HISTORY_SOURCE_MODEL, P03_COMPACT_PAGE, P03_COMPACT_SPOT_CHECKS, FIELD_MODULUS5, SUBTREE_LEAVES3, LOCAL_DEPTH2, OUTER_DEPTH2, PRIMARY_PROOF_BYTES2, FIELD_BYTES3, ED25519_SPKI_PREFIX2, VERSION_1_PREFIX2, HEX64, BASE58, REPLAY_STORE_INDEXED2, PROFILES2, MOVE_HEAD_BYTES2, MOVE_INSERTED_VALUES2, refuse3, hash4, bitAt, zeroRootsMemo, lastFolds, isSignature, isIndex, IMPORT_KEYS, IMPORT_MAX_VALUES, LIST_ATTEMPTS, OWN_READ_TIMEOUT_MS, BOUNDED_OWN_METHODS;
|
|
55620
55661
|
var init_compact = __esm({
|
|
55621
55662
|
"wallet/src/history/compact.mjs"() {
|
|
55622
55663
|
"use strict";
|
|
@@ -55727,6 +55768,7 @@ var init_compact = __esm({
|
|
|
55727
55768
|
};
|
|
55728
55769
|
hash4 = (left, right) => poseidon2([left, right], 3);
|
|
55729
55770
|
bitAt = (value, level) => Math.floor(value / 2 ** level) % 2;
|
|
55771
|
+
lastFolds = /* @__PURE__ */ new Map();
|
|
55730
55772
|
isSignature = (value) => typeof value === "string" && value.length >= 64 && value.length <= 88 && BASE58.test(value);
|
|
55731
55773
|
isIndex = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
55732
55774
|
IMPORT_KEYS = ["afterOrdinal", "instructionIndex", "record", "signature", "slot", "transactionIndex", "values"];
|
|
@@ -56299,7 +56341,7 @@ function prewarmWalletP03History(args) {
|
|
|
56299
56341
|
return false;
|
|
56300
56342
|
}
|
|
56301
56343
|
}
|
|
56302
|
-
async function loadWalletP03HistoryNow({ store, connection: given, programId, pool: pool2, deploymentIdentity, cache, forceRead = false }) {
|
|
56344
|
+
async function loadWalletP03HistoryNow({ store, connection: given, programId, pool: pool2, deploymentIdentity, cache, forceRead = false, onCompactList }) {
|
|
56303
56345
|
const { connection, source } = resolveHistorySource(given, pool2);
|
|
56304
56346
|
announceHistorySource(source);
|
|
56305
56347
|
const split5 = connection?.historyRpc;
|
|
@@ -56329,7 +56371,17 @@ async function loadWalletP03HistoryNow({ store, connection: given, programId, po
|
|
|
56329
56371
|
}
|
|
56330
56372
|
}
|
|
56331
56373
|
if (split5 && cache === void 0 && (source === "pinned" || source === "flag")) {
|
|
56332
|
-
const compact = await compactFirst({
|
|
56374
|
+
const compact = await compactFirst({
|
|
56375
|
+
store,
|
|
56376
|
+
connection,
|
|
56377
|
+
source,
|
|
56378
|
+
programId,
|
|
56379
|
+
pool: pool2,
|
|
56380
|
+
deploymentIdentity,
|
|
56381
|
+
forceRead,
|
|
56382
|
+
knownSnapshot: movedSnapshot,
|
|
56383
|
+
onCompactList
|
|
56384
|
+
});
|
|
56333
56385
|
if (compact !== void 0) {
|
|
56334
56386
|
if (runKey !== void 0) rememberRunReport(runKey, compact);
|
|
56335
56387
|
return compact;
|
|
@@ -56369,7 +56421,7 @@ async function loadWalletP03HistoryNow({ store, connection: given, programId, po
|
|
|
56369
56421
|
if (runKey !== void 0) rememberRunReport(runKey, result.report);
|
|
56370
56422
|
return result.report;
|
|
56371
56423
|
}
|
|
56372
|
-
async function compactFirst({ store, connection, source, programId, pool: pool2, deploymentIdentity, forceRead, knownSnapshot }) {
|
|
56424
|
+
async function compactFirst({ store, connection, source, programId, pool: pool2, deploymentIdentity, forceRead, knownSnapshot, onCompactList }) {
|
|
56373
56425
|
const started = Date.now();
|
|
56374
56426
|
let behindNoticed = false;
|
|
56375
56427
|
let behindTries = 0;
|
|
@@ -56380,6 +56432,8 @@ async function compactFirst({ store, connection, source, programId, pool: pool2,
|
|
|
56380
56432
|
pool: pool2,
|
|
56381
56433
|
deploymentIdentity,
|
|
56382
56434
|
forceRead,
|
|
56435
|
+
// The served list, unverified, before its fold (compact.mjs onList): a payment's memo prefetch.
|
|
56436
|
+
...typeof onCompactList === "function" ? { onList: onCompactList } : {},
|
|
56383
56437
|
cache: walletCompactHistoryCache(store),
|
|
56384
56438
|
freshMs: HISTORY_WARM_FRESH_MS,
|
|
56385
56439
|
// The walk cache's attestation, read only when the compact cache holds none.
|
|
@@ -60363,7 +60417,7 @@ async function runRecover({ store, connection, programId, digests, serviceUrl: s
|
|
|
60363
60417
|
const pool2 = new import_web3102.PublicKey(state.pool);
|
|
60364
60418
|
const chainProgramId = new import_web3102.PublicKey(programId);
|
|
60365
60419
|
const poolStateRead = (async () => {
|
|
60366
|
-
const poolState3 = await readPoolState2(connection, pool2);
|
|
60420
|
+
const poolState3 = await (deps.poolState ?? readPoolState2(connection, pool2));
|
|
60367
60421
|
if (!poolState3) throw new Error("pool account not found");
|
|
60368
60422
|
if (!poolState3.owner.equals(chainProgramId)) throw new Error("pool account owner mismatch");
|
|
60369
60423
|
markPhase("recover-pool");
|
|
@@ -62405,6 +62459,7 @@ var init_errorCodes = __esm({
|
|
|
62405
62459
|
"fetch_url_refused",
|
|
62406
62460
|
"fetch_offer_unsupported",
|
|
62407
62461
|
"fetch_challenge_invalid",
|
|
62462
|
+
"fetch_seller_unreachable",
|
|
62408
62463
|
"fetch_session_closed",
|
|
62409
62464
|
"fetch_max_payment_required",
|
|
62410
62465
|
"mcp_cap_required",
|
|
@@ -70299,11 +70354,14 @@ async function runRecoveredP03NoteExit({
|
|
|
70299
70354
|
}
|
|
70300
70355
|
wal = { ...wal, state: "confirmed", signature };
|
|
70301
70356
|
store.writeWal(walName2, wal);
|
|
70302
|
-
|
|
70303
|
-
|
|
70304
|
-
|
|
70357
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
70358
|
+
history = await walkHistory();
|
|
70359
|
+
poolState2 = await readPool2(connection, pool2, "finalized");
|
|
70360
|
+
if (!poolState2 || !poolState2.owner.equals(chainProgramId) || poolState2.version !== 3) {
|
|
70361
|
+
throw new Error("finalized note-exit pool postcondition invalid");
|
|
70362
|
+
}
|
|
70363
|
+
if (attempt >= 4 || history.finalizedPoolSnapshot.currentIndex === poolState2.currentIndex && history.finalizedPoolSnapshot.currentRoot === poolState2.currentRoot) break;
|
|
70305
70364
|
}
|
|
70306
|
-
history = await walkHistory();
|
|
70307
70365
|
await prepareFold(history);
|
|
70308
70366
|
const spentPath = buildRecoveryPath({
|
|
70309
70367
|
history,
|
|
@@ -71906,6 +71964,9 @@ async function prepareRecoveredPayment({
|
|
|
71906
71964
|
const generator = pinnedGenerator4();
|
|
71907
71965
|
const viewing = deriveWalletViewingAuthority2({ seedBytes: seedBytes5(state), generator });
|
|
71908
71966
|
const chainTime2 = deps.chainTime === void 0 ? startFinalizedChainTime(connection) : void 0;
|
|
71967
|
+
const poolState2 = deps.recover === void 0 ? readPoolState2(connection, pool2) : void 0;
|
|
71968
|
+
poolState2?.catch(() => {
|
|
71969
|
+
});
|
|
71909
71970
|
if (deps.provePayment === void 0 && proofTools !== void 0) {
|
|
71910
71971
|
(deps.prewarmProof ?? ((tools) => setImmediate(() => {
|
|
71911
71972
|
prewarmP03PaymentProofTools(tools).catch(() => {
|
|
@@ -71979,7 +72040,12 @@ async function prepareRecoveredPayment({
|
|
|
71979
72040
|
digests,
|
|
71980
72041
|
serviceUrl: serviceUrl2,
|
|
71981
72042
|
fresh: true,
|
|
71982
|
-
deps: {
|
|
72043
|
+
deps: {
|
|
72044
|
+
fetchImpl: deps.fetchImpl,
|
|
72045
|
+
finalizedHistory: history,
|
|
72046
|
+
transitionContextFor: history.transitionContextFor,
|
|
72047
|
+
...poolState2 !== void 0 ? { poolState: poolState2 } : {}
|
|
72048
|
+
}
|
|
71983
72049
|
});
|
|
71984
72050
|
markPhase("recover");
|
|
71985
72051
|
const unspentAccounts = recovery.recovered.filter((entry) => entry.kind === "account" && entry.spendStatus === "unspent");
|
|
@@ -72222,6 +72288,7 @@ var init_prepareRecoveredPayment = __esm({
|
|
|
72222
72288
|
init_recoveryPath();
|
|
72223
72289
|
init_recoveredPayment();
|
|
72224
72290
|
init_recover();
|
|
72291
|
+
init_chain2();
|
|
72225
72292
|
init_notes2();
|
|
72226
72293
|
init_accountSelection();
|
|
72227
72294
|
init_phaseTiming();
|
|
@@ -72326,7 +72393,7 @@ async function validateReceiptTransaction(connection, receipt, record, state, pr
|
|
|
72326
72393
|
[{ signature: receipt.transaction, slot: status.slot, failed: false }],
|
|
72327
72394
|
blockCache,
|
|
72328
72395
|
transactions,
|
|
72329
|
-
{ commitment }
|
|
72396
|
+
{ commitment, positionWhen: () => false }
|
|
72330
72397
|
);
|
|
72331
72398
|
const settlements = targetInstructions([...transactions.values()], program).filter((instruction) => (instruction.data[0] === 4 || instruction.data[0] === COMPRESSED_SETTLE_TAG.payment || instruction.data[0] === E1_SETTLE_TAG.payment) && instruction.accounts[0] === pool2.toBase58());
|
|
72332
72399
|
if (settlements.length !== 1) fail16("receipt_payment_instruction_missing");
|
|
@@ -91166,6 +91233,7 @@ async function readJson(response, limit) {
|
|
|
91166
91233
|
}
|
|
91167
91234
|
}
|
|
91168
91235
|
async function readFloatConfig({ origin, fetchImpl = fetch }) {
|
|
91236
|
+
const readAtMs = Date.now();
|
|
91169
91237
|
let response;
|
|
91170
91238
|
try {
|
|
91171
91239
|
response = await fetchImpl(
|
|
@@ -91199,7 +91267,7 @@ async function readFloatConfig({ origin, fetchImpl = fetch }) {
|
|
|
91199
91267
|
if (config?.schema !== FLOAT_CONFIG_SCHEMA || !DECIMAL3.test(String(config.feeAtomic ?? "")) || !DECIMAL3.test(String(config.largestAtomic ?? "")) || typeof config.network !== "string" || typeof config.asset !== "string" || !prefix || prefix.pathname !== FLOAT_PAY_PATH || prefix.href !== config.payUrlPrefix || !feePayerOk) {
|
|
91200
91268
|
fail18("p03_float_config_unreadable");
|
|
91201
91269
|
}
|
|
91202
|
-
|
|
91270
|
+
const read = {
|
|
91203
91271
|
feeAtomic: String(config.feeAtomic),
|
|
91204
91272
|
largestAtomic: String(config.largestAtomic),
|
|
91205
91273
|
network: config.network,
|
|
@@ -91207,6 +91275,23 @@ async function readFloatConfig({ origin, fetchImpl = fetch }) {
|
|
|
91207
91275
|
payUrlPrefix: config.payUrlPrefix,
|
|
91208
91276
|
pocketFeePayer: config.pocketFeePayer
|
|
91209
91277
|
};
|
|
91278
|
+
configCache.set(origin, { config: read, readAtMs });
|
|
91279
|
+
return read;
|
|
91280
|
+
}
|
|
91281
|
+
function dropFloatConfigs() {
|
|
91282
|
+
configCache.clear();
|
|
91283
|
+
}
|
|
91284
|
+
async function readFloatOffer({ origin, paymentRequired, store, fetchImpl = fetch }) {
|
|
91285
|
+
const kept = configCache.get(origin);
|
|
91286
|
+
if (kept && Date.now() - kept.readAtMs < CONFIG_CACHE_MS) {
|
|
91287
|
+
try {
|
|
91288
|
+
return { offer: floatOffer({ paymentRequired, store, config: kept.config }), config: kept.config };
|
|
91289
|
+
} catch {
|
|
91290
|
+
configCache.delete(origin);
|
|
91291
|
+
}
|
|
91292
|
+
}
|
|
91293
|
+
const config = await readFloatConfig({ origin, fetchImpl });
|
|
91294
|
+
return { offer: floatOffer({ paymentRequired, store, config }), config };
|
|
91210
91295
|
}
|
|
91211
91296
|
function floatOriginOf(floatOrigin, serviceUrl2) {
|
|
91212
91297
|
const value = floatOrigin ?? serviceUrl2;
|
|
@@ -91300,7 +91385,7 @@ function withSellerResource(xPayment, record) {
|
|
|
91300
91385
|
return patched;
|
|
91301
91386
|
}
|
|
91302
91387
|
function floatFetch(base, seen) {
|
|
91303
|
-
|
|
91388
|
+
const wrapper = async (target, init = {}) => {
|
|
91304
91389
|
const response = await base(target, keepAliveInit(init));
|
|
91305
91390
|
const paid = Object.keys(init.headers ?? {}).some((name) => name.toLowerCase() === "payment-signature");
|
|
91306
91391
|
if (paid || response.status === 402 || response.status < 400) return response;
|
|
@@ -91322,6 +91407,7 @@ function floatFetch(base, seen) {
|
|
|
91322
91407
|
};
|
|
91323
91408
|
return new Response(null, { status: 400 });
|
|
91324
91409
|
};
|
|
91410
|
+
return Object.defineProperty(wrapper, "baseFetch", { value: base });
|
|
91325
91411
|
}
|
|
91326
91412
|
function floatRefusalError(refusal2, record) {
|
|
91327
91413
|
const extra = {
|
|
@@ -91468,6 +91554,7 @@ async function payViaFloat({
|
|
|
91468
91554
|
continue;
|
|
91469
91555
|
}
|
|
91470
91556
|
dropUnsent();
|
|
91557
|
+
dropFloatConfigs();
|
|
91471
91558
|
throw floatRefusalError(seen.refusal, record);
|
|
91472
91559
|
}
|
|
91473
91560
|
if (PENDING_CODES.has(error?.sellerCode) && Date.now() < finishingUntil) {
|
|
@@ -91569,7 +91656,7 @@ function paidResult(record, replayed) {
|
|
|
91569
91656
|
float: { floatId: record.floatId }
|
|
91570
91657
|
};
|
|
91571
91658
|
}
|
|
91572
|
-
var import_web3109, FLOAT_PAYMENT_SCHEMA, REGENERATE_CODES, FLOAT_PAYMENT_WAL_PREFIX, FLOAT_CONFIG_SCHEMA, FLOAT_PAY_PATH, MAX_BODY_BYTES, FLOAT_REFUND_ETA_SECONDS, REFUND_SETTLED_AFTER_MS, FINISHING_POLL_MS, FINISHING_LIMIT_MS, SELLER_TIMEOUT_MS, CONFIG_TIMEOUT_MS, DECIMAL3, POSITIVE, PENDING_CODES, hash8, fail18, floatPaymentWalName, plainText;
|
|
91659
|
+
var import_web3109, FLOAT_PAYMENT_SCHEMA, REGENERATE_CODES, FLOAT_PAYMENT_WAL_PREFIX, FLOAT_CONFIG_SCHEMA, FLOAT_PAY_PATH, MAX_BODY_BYTES, FLOAT_REFUND_ETA_SECONDS, REFUND_SETTLED_AFTER_MS, FINISHING_POLL_MS, FINISHING_LIMIT_MS, SELLER_TIMEOUT_MS, CONFIG_TIMEOUT_MS, CONFIG_CACHE_MS, DECIMAL3, POSITIVE, PENDING_CODES, hash8, fail18, floatPaymentWalName, configCache, plainText;
|
|
91573
91660
|
var init_floatPay = __esm({
|
|
91574
91661
|
"wallet/src/pay/floatPay.mjs"() {
|
|
91575
91662
|
"use strict";
|
|
@@ -91598,6 +91685,7 @@ var init_floatPay = __esm({
|
|
|
91598
91685
|
FINISHING_LIMIT_MS = 6e4;
|
|
91599
91686
|
SELLER_TIMEOUT_MS = 12e4;
|
|
91600
91687
|
CONFIG_TIMEOUT_MS = 3e4;
|
|
91688
|
+
CONFIG_CACHE_MS = 6e4;
|
|
91601
91689
|
DECIMAL3 = /^(0|[1-9][0-9]*)$/;
|
|
91602
91690
|
POSITIVE = /^[1-9][0-9]*$/;
|
|
91603
91691
|
PENDING_CODES = /* @__PURE__ */ new Set(["float_paid_finishing", "payment_pending_retry_same_payment"]);
|
|
@@ -91606,6 +91694,7 @@ var init_floatPay = __esm({
|
|
|
91606
91694
|
throw Object.assign(new Error(code), extra);
|
|
91607
91695
|
};
|
|
91608
91696
|
floatPaymentWalName = (requestKey) => `${FLOAT_PAYMENT_WAL_PREFIX}${requestKey}`;
|
|
91697
|
+
configCache = /* @__PURE__ */ new Map();
|
|
91609
91698
|
plainText = (value) => value.replace(/[^ -~]+/g, " ").trim().slice(0, 300);
|
|
91610
91699
|
}
|
|
91611
91700
|
});
|
|
@@ -96223,6 +96312,7 @@ async function createSellerAdapter({
|
|
|
96223
96312
|
return { status: original.result.status, result: original.result, receipt: original.receipt };
|
|
96224
96313
|
}
|
|
96225
96314
|
let offer = original;
|
|
96315
|
+
let intakeChain;
|
|
96226
96316
|
try {
|
|
96227
96317
|
if (!offer.outboundJson) {
|
|
96228
96318
|
const parsed = parseSolanaP03HttpPaymentPayload(payment.payload);
|
|
@@ -96237,6 +96327,7 @@ async function createSellerAdapter({
|
|
|
96237
96327
|
const recoveredNote = await scanner.recoverMerchantNoteYielding({ parsed, authenticatedQuote: auth });
|
|
96238
96328
|
mark("intake-note-recovered");
|
|
96239
96329
|
const chain = await intakeRead;
|
|
96330
|
+
intakeChain = chain;
|
|
96240
96331
|
mark("intake-anchor-read");
|
|
96241
96332
|
const issuedAt = Number(chain.chainTimestamp);
|
|
96242
96333
|
const expiresAt = Math.min(issuedAt + 300, Number(payment.accepted.extra.validBefore));
|
|
@@ -96277,11 +96368,18 @@ async function createSellerAdapter({
|
|
|
96277
96368
|
await put(nonce, offer);
|
|
96278
96369
|
mark("intake-durable");
|
|
96279
96370
|
}
|
|
96371
|
+
const firstIntake = intakeChain !== void 0 && !offer.settleAttempted;
|
|
96372
|
+
if (firstIntake) {
|
|
96373
|
+
await readCurrentAnchor(intakeChain);
|
|
96374
|
+
offer = { ...offer, phase: "settlement_pending", settleAttempted: true };
|
|
96375
|
+
await put(nonce, offer);
|
|
96376
|
+
mark("first-intake-settle");
|
|
96377
|
+
}
|
|
96280
96378
|
const preVerifyReadAt = Date.now();
|
|
96281
96379
|
const preVerifyRead = offer.settleAttempted ? void 0 : readAnchor();
|
|
96282
96380
|
preVerifyRead?.catch(() => void 0);
|
|
96283
|
-
const claimed = await facilitator("claim", offer.outboundJson);
|
|
96284
|
-
mark("claim");
|
|
96381
|
+
const claimed = firstIntake ? void 0 : await facilitator("claim", offer.outboundJson);
|
|
96382
|
+
if (!firstIntake) mark("claim");
|
|
96285
96383
|
if (claimed) {
|
|
96286
96384
|
offer = await persistReceipt(nonce, offer, claimed, mark);
|
|
96287
96385
|
return { status: offer.result.status, result: offer.result, receipt: offer.receipt };
|
|
@@ -117778,6 +117876,7 @@ init_payResource();
|
|
|
117778
117876
|
init_quote2();
|
|
117779
117877
|
init_floatPay();
|
|
117780
117878
|
init_walletHistory();
|
|
117879
|
+
init_recover();
|
|
117781
117880
|
init_keepAlive();
|
|
117782
117881
|
init_phaseTiming();
|
|
117783
117882
|
init_chain2();
|
|
@@ -118053,8 +118152,8 @@ async function offeredPrice(paymentRequired, store, serviceUrl2) {
|
|
|
118053
118152
|
}
|
|
118054
118153
|
if (rail === "exact" && store) {
|
|
118055
118154
|
const origin = new URL(serviceUrl2).origin;
|
|
118056
|
-
const config = await
|
|
118057
|
-
return { rail, amountAtomic:
|
|
118155
|
+
const { offer, config } = await readFloatOffer({ origin, paymentRequired, store });
|
|
118156
|
+
return { rail, amountAtomic: offer.paidAtomic, floatConfig: { origin, config } };
|
|
118058
118157
|
}
|
|
118059
118158
|
let highest;
|
|
118060
118159
|
for (const offer of paymentRequired.accepts) {
|
|
@@ -118128,7 +118227,7 @@ async function payAndFetch(session, url, init = {}, opts = {}) {
|
|
|
118128
118227
|
let challenge3;
|
|
118129
118228
|
if (!rerun) {
|
|
118130
118229
|
if (store !== void 0) startHistoryPrewarm(session, store, mark);
|
|
118131
|
-
const response = await
|
|
118230
|
+
const response = await unpaidRequest(target, () => keepAliveInit({
|
|
118132
118231
|
method,
|
|
118133
118232
|
headers,
|
|
118134
118233
|
...body ? { body } : {},
|
|
@@ -118171,6 +118270,19 @@ async function payAndFetch(session, url, init = {}, opts = {}) {
|
|
|
118171
118270
|
throw error;
|
|
118172
118271
|
}
|
|
118173
118272
|
}
|
|
118273
|
+
var UNPAID_NOT_SENT = /* @__PURE__ */ new Set(["UND_ERR_CONNECT_TIMEOUT", "ECONNREFUSED"]);
|
|
118274
|
+
async function unpaidRequest(target, init) {
|
|
118275
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
118276
|
+
try {
|
|
118277
|
+
return await fetch(target, init());
|
|
118278
|
+
} catch (error) {
|
|
118279
|
+
const code = typeof error?.cause?.code === "string" && /^[A-Z][A-Z0-9_]{2,40}$/.test(error.cause.code) ? error.cause.code : void 0;
|
|
118280
|
+
if (attempt === 0 && UNPAID_NOT_SENT.has(code)) continue;
|
|
118281
|
+
const cause = error?.name === "TimeoutError" ? "no answer in 120 s" : code ?? "network error";
|
|
118282
|
+
fail20("fetch_seller_unreachable", `the seller did not answer the first, unpaid request (${cause}); nothing was paid`);
|
|
118283
|
+
}
|
|
118284
|
+
}
|
|
118285
|
+
}
|
|
118174
118286
|
function startHistoryPrewarm(session, store, mark) {
|
|
118175
118287
|
try {
|
|
118176
118288
|
withPhaseScope(mark, "prewarm", () => prewarmWalletP03History({
|
|
@@ -118178,7 +118290,16 @@ function startHistoryPrewarm(session, store, mark) {
|
|
|
118178
118290
|
connection: connectSplit(session.connection, session.historyUrl),
|
|
118179
118291
|
programId: session.programId,
|
|
118180
118292
|
pool: store.state.pool,
|
|
118181
|
-
deploymentIdentity: session.proofTools.deploymentIdentity
|
|
118293
|
+
deploymentIdentity: session.proofTools.deploymentIdentity,
|
|
118294
|
+
// The memos the proof's recovery will read, asked when the compact list arrives, beside
|
|
118295
|
+
// its fold, spot checks, and attestation (B2 #3, 2026-10-15: the recovery waited 0.18-0.44 s
|
|
118296
|
+
// for them after the walk, M). The same set the recovery asks (every listed transition
|
|
118297
|
+
// its cache lacks); it takes an answer only for a transition of the verified report
|
|
118298
|
+
// (chain.mjs createMemoReader prefetch; recover.mjs checks each bundle's digest).
|
|
118299
|
+
onCompactList: (contexts) => {
|
|
118300
|
+
markPhase("memo-prefetch");
|
|
118301
|
+
prefetchRecoveryMemos({ store, finalizedHistory: { contexts }, serviceUrl: session.memoServiceUrl, programId: session.programId });
|
|
118302
|
+
}
|
|
118182
118303
|
}));
|
|
118183
118304
|
} catch {
|
|
118184
118305
|
}
|
|
@@ -125282,8 +125403,7 @@ async function railOffer(paymentRequired, rail, store, facilitator) {
|
|
|
125282
125403
|
}
|
|
125283
125404
|
try {
|
|
125284
125405
|
if (!facilitator) throw new Error("p03_float_origin_missing");
|
|
125285
|
-
const
|
|
125286
|
-
const offer = floatOffer({ paymentRequired, store, config });
|
|
125406
|
+
const { offer } = await readFloatOffer({ origin: new URL(facilitator).origin, paymentRequired, store });
|
|
125287
125407
|
return { priceAtomic: offer.priceAtomic, feeAtomic: offer.feeAtomic, totalAtomic: offer.paidAtomic };
|
|
125288
125408
|
} catch (error) {
|
|
125289
125409
|
const refusal2 = floatRefusal(error) ?? ["p03_float_config_unreadable", "the price through Shinjuku could not be read; nothing was paid", "call x402_preview again in a minute"];
|
|
@@ -125534,15 +125654,16 @@ async function runShieldFromElsewhere({ session, depositId, amountAtomic, onStag
|
|
|
125534
125654
|
const result = await (steps.submit ?? submitRelayedDeposit)(common);
|
|
125535
125655
|
return { state: result.state, transaction: typeof result.receipt?.signature === "string" ? result.receipt.signature : null };
|
|
125536
125656
|
}
|
|
125537
|
-
|
|
125657
|
+
var walkWalletHistory = (session, store) => loadWalletP03History({
|
|
125658
|
+
store,
|
|
125659
|
+
connection: connectSplit(session.connection, session.historyUrl),
|
|
125660
|
+
programId: session.programId,
|
|
125661
|
+
pool: store.state.pool,
|
|
125662
|
+
deploymentIdentity: session.proofTools.deploymentIdentity
|
|
125663
|
+
});
|
|
125664
|
+
async function refreshWallet({ session, store, history: walked }) {
|
|
125538
125665
|
const walStates = captureWalStates(store);
|
|
125539
|
-
const history = await
|
|
125540
|
-
store,
|
|
125541
|
-
connection: connectSplit(session.connection, session.historyUrl),
|
|
125542
|
-
programId: session.programId,
|
|
125543
|
-
pool: store.state.pool,
|
|
125544
|
-
deploymentIdentity: session.proofTools.deploymentIdentity
|
|
125545
|
-
});
|
|
125666
|
+
const history = walked ?? await walkWalletHistory(session, store);
|
|
125546
125667
|
const result = await runRecover({
|
|
125547
125668
|
store,
|
|
125548
125669
|
connection: session.connection,
|
|
@@ -125788,7 +125909,9 @@ function createWalletTools({
|
|
|
125788
125909
|
let refreshRun;
|
|
125789
125910
|
let refreshFailedAt = 0;
|
|
125790
125911
|
let refreshFailedCode;
|
|
125791
|
-
|
|
125912
|
+
let refreshInBackground = false;
|
|
125913
|
+
const refreshStep = (store, history) => (ops.refresh ?? refreshWallet)({ session, store, ...history ? { history } : {} });
|
|
125914
|
+
const refreshWalk = ops.refreshWalk ?? (ops.refresh ? void 0 : (store) => walkWalletHistory(session, store));
|
|
125792
125915
|
const errorCode2 = (error, fallback) => describeError(error, { fallback, safeText: SAFE_TEXT }).split(/[\s:;(]/, 1)[0];
|
|
125793
125916
|
const underLease = (task) => session.serial(async () => {
|
|
125794
125917
|
let release;
|
|
@@ -125932,9 +126055,27 @@ function createWalletTools({
|
|
|
125932
126055
|
deps: ops.oneTimeAdopt && typeof ops.oneTimeAdopt === "object" ? ops.oneTimeAdopt : {}
|
|
125933
126056
|
});
|
|
125934
126057
|
if (ops.oneTimeAdopt !== false) adopter.start();
|
|
125935
|
-
function refreshShared() {
|
|
126058
|
+
function refreshShared({ background = false } = {}) {
|
|
125936
126059
|
if (!refreshRun) {
|
|
125937
|
-
|
|
126060
|
+
refreshInBackground = background;
|
|
126061
|
+
refreshRun = (async () => {
|
|
126062
|
+
let early;
|
|
126063
|
+
if (background && refreshWalk) {
|
|
126064
|
+
try {
|
|
126065
|
+
const store = session.openStore();
|
|
126066
|
+
const records = JSON.stringify(captureWalStates(store));
|
|
126067
|
+
const pool2 = store.state.pool;
|
|
126068
|
+
early = { records, pool: pool2, history: await refreshWalk(store) };
|
|
126069
|
+
} catch {
|
|
126070
|
+
early = void 0;
|
|
126071
|
+
}
|
|
126072
|
+
}
|
|
126073
|
+
return underLease((store) => {
|
|
126074
|
+
const same2 = early !== void 0 && early.pool === store.state.pool && early.records === JSON.stringify(captureWalStates(store));
|
|
126075
|
+
if (early !== void 0 && !same2) log("MCP_REFRESH_WALK_AGAIN");
|
|
126076
|
+
return refreshStep(store, same2 ? early.history : void 0);
|
|
126077
|
+
});
|
|
126078
|
+
})().then(() => {
|
|
125938
126079
|
refreshFailedAt = 0;
|
|
125939
126080
|
log("MCP_REFRESH_DONE");
|
|
125940
126081
|
}, (error) => {
|
|
@@ -125944,6 +126085,7 @@ function createWalletTools({
|
|
|
125944
126085
|
throw error;
|
|
125945
126086
|
}).finally(() => {
|
|
125946
126087
|
refreshRun = void 0;
|
|
126088
|
+
refreshInBackground = false;
|
|
125947
126089
|
});
|
|
125948
126090
|
}
|
|
125949
126091
|
return refreshRun;
|
|
@@ -125976,7 +126118,7 @@ function createWalletTools({
|
|
|
125976
126118
|
}
|
|
125977
126119
|
if (watched === finalityTarget && status?.confirmationStatus === "finalized") {
|
|
125978
126120
|
log("MCP_FINALITY_REFRESH");
|
|
125979
|
-
await refreshShared().catch(() => {
|
|
126121
|
+
await refreshShared({ background: true }).catch(() => {
|
|
125980
126122
|
});
|
|
125981
126123
|
return;
|
|
125982
126124
|
}
|
|
@@ -126001,6 +126143,7 @@ function createWalletTools({
|
|
|
126001
126143
|
return;
|
|
126002
126144
|
}
|
|
126003
126145
|
if (!stale || refreshFailedAt && Date.now() - refreshFailedAt < REFRESH_RETRY_MS) return;
|
|
126146
|
+
if (refreshRun && refreshInBackground) return;
|
|
126004
126147
|
await refreshShared().catch(() => {
|
|
126005
126148
|
});
|
|
126006
126149
|
}
|
|
@@ -126376,6 +126519,8 @@ function createWalletTools({
|
|
|
126376
126519
|
);
|
|
126377
126520
|
} else if (code.startsWith("wallet_spend_refused_")) {
|
|
126378
126521
|
next = "the wallet file's own budget refused it (init --max-payment / --max-cumulative); nothing was paid. Read wallet_balance detail.budget";
|
|
126522
|
+
} else if (code === "fetch_seller_unreachable") {
|
|
126523
|
+
next = `Nothing was paid and nothing was sent to the seller. Call x402_pay again with request_id "${requestId}" and the same url, method, headers, and body (it never pays twice); if it fails the same way again, the seller is down: tell your owner`;
|
|
126379
126524
|
} else if (code.startsWith("wallet_quote_refused_") || code.startsWith("fetch_")) {
|
|
126380
126525
|
next = "nothing was paid; do not retry this URL unchanged";
|
|
126381
126526
|
} else {
|
|
@@ -135589,6 +135734,7 @@ function failureHint(command, reason, deps, values) {
|
|
|
135589
135734
|
if (/fetch_offer_unsupported/.test(reason)) {
|
|
135590
135735
|
return `nothing was paid: the seller's 402 offers no scheme this wallet pays (shielded-exact, or standard exact through Shinjuku). Hidden-amount (confidential) payments are retired since 2026-10-11`;
|
|
135591
135736
|
}
|
|
135737
|
+
if (/fetch_seller_unreachable/.test(reason)) return "nothing was paid: the seller did not answer the first, unpaid request. Rerun the same command (same --request-id) later; if it fails again, the seller is down";
|
|
135592
135738
|
if (/fetch_challenge_invalid/.test(reason)) return "nothing was paid: the seller's 402 is not a valid x402 v2 challenge (PAYMENT-REQUIRED header). Do not pay this seller until it sends one";
|
|
135593
135739
|
if (/fetch_url_refused/.test(reason)) return "nothing was sent: use the https URL. Plain http goes only to a private host (localhost, 10.x, 192.168.x) or to an .onion inside a --tor run";
|
|
135594
135740
|
if (/fetch_options_invalid/.test(reason)) {
|