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 CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schema": "carbon-shielded-wallet/bundle-manifest/v1",
3
3
  "file": "shinjuku-wallet.mjs",
4
- "sha256": "a523d67b85ebcfd6f07f653c2a9bde16a7c9d87f908874ddae71cf91083fabc8",
5
- "bytes": 11177579,
6
- "sourceCommit": "025c6a4ab1a1c3e38019cdd7843b524a6a90d62a",
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.30",
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": "a523d67b",
7
- "shinjukuSha256": "a523d67b85ebcfd6f07f653c2a9bde16a7c9d87f908874ddae71cf91083fabc8",
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",
@@ -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
- let ahead = prefetchedMemosByFetch.get(fetchImpl);
50449
- if (ahead === void 0) prefetchedMemosByFetch.set(fetchImpl, ahead = /* @__PURE__ */ new Map());
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) throw refuse3("p03_compact_history_source_behind");
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 = foldCompactLeaves(contexts.map((context) => context.outCommitment), counts);
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({ store, connection, source, programId, pool: pool2, deploymentIdentity, forceRead, knownSnapshot: movedSnapshot });
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
- poolState2 = await readPool2(connection, pool2, "finalized");
70303
- if (!poolState2 || !poolState2.owner.equals(chainProgramId) || poolState2.version !== 3) {
70304
- throw new Error("finalized note-exit pool postcondition invalid");
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: { fetchImpl: deps.fetchImpl, finalizedHistory: history, transitionContextFor: history.transitionContextFor }
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
- return {
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
- return async (target, init = {}) => {
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 readFloatConfig({ origin });
118057
- return { rail, amountAtomic: floatOffer({ paymentRequired, store, config }).paidAtomic, floatConfig: { origin, config } };
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 fetch(target, keepAliveInit({
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 config = await readFloatConfig({ origin: new URL(facilitator).origin });
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
- async function refreshWallet({ session, store }) {
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 loadWalletP03History({
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
- const refreshStep = (store) => (ops.refresh ?? refreshWallet)({ session, store });
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
- refreshRun = underLease((store) => refreshStep(store)).then(() => {
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)) {