shinjuku-shielded 0.3.31 → 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": "c8c82dc4ce0277f8c560adec5cb16119709d00240a8efa4ebbb2a426e5161b6a",
5
- "bytes": 11178235,
6
- "sourceCommit": "206a11827c4c668d65b7e8e2040a344f17aad1d0",
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.31",
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": "c8c82dc4",
7
- "shinjukuSha256": "c8c82dc4ce0277f8c560adec5cb16119709d00240a8efa4ebbb2a426e5161b6a",
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",
@@ -71909,6 +71964,9 @@ async function prepareRecoveredPayment({
71909
71964
  const generator = pinnedGenerator4();
71910
71965
  const viewing = deriveWalletViewingAuthority2({ seedBytes: seedBytes5(state), generator });
71911
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
+ });
71912
71970
  if (deps.provePayment === void 0 && proofTools !== void 0) {
71913
71971
  (deps.prewarmProof ?? ((tools) => setImmediate(() => {
71914
71972
  prewarmP03PaymentProofTools(tools).catch(() => {
@@ -71982,7 +72040,12 @@ async function prepareRecoveredPayment({
71982
72040
  digests,
71983
72041
  serviceUrl: serviceUrl2,
71984
72042
  fresh: true,
71985
- 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
+ }
71986
72049
  });
71987
72050
  markPhase("recover");
71988
72051
  const unspentAccounts = recovery.recovered.filter((entry) => entry.kind === "account" && entry.spendStatus === "unspent");
@@ -72225,6 +72288,7 @@ var init_prepareRecoveredPayment = __esm({
72225
72288
  init_recoveryPath();
72226
72289
  init_recoveredPayment();
72227
72290
  init_recover();
72291
+ init_chain2();
72228
72292
  init_notes2();
72229
72293
  init_accountSelection();
72230
72294
  init_phaseTiming();
@@ -91169,6 +91233,7 @@ async function readJson(response, limit) {
91169
91233
  }
91170
91234
  }
91171
91235
  async function readFloatConfig({ origin, fetchImpl = fetch }) {
91236
+ const readAtMs = Date.now();
91172
91237
  let response;
91173
91238
  try {
91174
91239
  response = await fetchImpl(
@@ -91202,7 +91267,7 @@ async function readFloatConfig({ origin, fetchImpl = fetch }) {
91202
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) {
91203
91268
  fail18("p03_float_config_unreadable");
91204
91269
  }
91205
- return {
91270
+ const read = {
91206
91271
  feeAtomic: String(config.feeAtomic),
91207
91272
  largestAtomic: String(config.largestAtomic),
91208
91273
  network: config.network,
@@ -91210,6 +91275,23 @@ async function readFloatConfig({ origin, fetchImpl = fetch }) {
91210
91275
  payUrlPrefix: config.payUrlPrefix,
91211
91276
  pocketFeePayer: config.pocketFeePayer
91212
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 };
91213
91295
  }
91214
91296
  function floatOriginOf(floatOrigin, serviceUrl2) {
91215
91297
  const value = floatOrigin ?? serviceUrl2;
@@ -91303,7 +91385,7 @@ function withSellerResource(xPayment, record) {
91303
91385
  return patched;
91304
91386
  }
91305
91387
  function floatFetch(base, seen) {
91306
- return async (target, init = {}) => {
91388
+ const wrapper = async (target, init = {}) => {
91307
91389
  const response = await base(target, keepAliveInit(init));
91308
91390
  const paid = Object.keys(init.headers ?? {}).some((name) => name.toLowerCase() === "payment-signature");
91309
91391
  if (paid || response.status === 402 || response.status < 400) return response;
@@ -91325,6 +91407,7 @@ function floatFetch(base, seen) {
91325
91407
  };
91326
91408
  return new Response(null, { status: 400 });
91327
91409
  };
91410
+ return Object.defineProperty(wrapper, "baseFetch", { value: base });
91328
91411
  }
91329
91412
  function floatRefusalError(refusal2, record) {
91330
91413
  const extra = {
@@ -91471,6 +91554,7 @@ async function payViaFloat({
91471
91554
  continue;
91472
91555
  }
91473
91556
  dropUnsent();
91557
+ dropFloatConfigs();
91474
91558
  throw floatRefusalError(seen.refusal, record);
91475
91559
  }
91476
91560
  if (PENDING_CODES.has(error?.sellerCode) && Date.now() < finishingUntil) {
@@ -91572,7 +91656,7 @@ function paidResult(record, replayed) {
91572
91656
  float: { floatId: record.floatId }
91573
91657
  };
91574
91658
  }
91575
- 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;
91576
91660
  var init_floatPay = __esm({
91577
91661
  "wallet/src/pay/floatPay.mjs"() {
91578
91662
  "use strict";
@@ -91601,6 +91685,7 @@ var init_floatPay = __esm({
91601
91685
  FINISHING_LIMIT_MS = 6e4;
91602
91686
  SELLER_TIMEOUT_MS = 12e4;
91603
91687
  CONFIG_TIMEOUT_MS = 3e4;
91688
+ CONFIG_CACHE_MS = 6e4;
91604
91689
  DECIMAL3 = /^(0|[1-9][0-9]*)$/;
91605
91690
  POSITIVE = /^[1-9][0-9]*$/;
91606
91691
  PENDING_CODES = /* @__PURE__ */ new Set(["float_paid_finishing", "payment_pending_retry_same_payment"]);
@@ -91609,6 +91694,7 @@ var init_floatPay = __esm({
91609
91694
  throw Object.assign(new Error(code), extra);
91610
91695
  };
91611
91696
  floatPaymentWalName = (requestKey) => `${FLOAT_PAYMENT_WAL_PREFIX}${requestKey}`;
91697
+ configCache = /* @__PURE__ */ new Map();
91612
91698
  plainText = (value) => value.replace(/[^ -~]+/g, " ").trim().slice(0, 300);
91613
91699
  }
91614
91700
  });
@@ -117790,6 +117876,7 @@ init_payResource();
117790
117876
  init_quote2();
117791
117877
  init_floatPay();
117792
117878
  init_walletHistory();
117879
+ init_recover();
117793
117880
  init_keepAlive();
117794
117881
  init_phaseTiming();
117795
117882
  init_chain2();
@@ -118065,8 +118152,8 @@ async function offeredPrice(paymentRequired, store, serviceUrl2) {
118065
118152
  }
118066
118153
  if (rail === "exact" && store) {
118067
118154
  const origin = new URL(serviceUrl2).origin;
118068
- const config = await readFloatConfig({ origin });
118069
- 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 } };
118070
118157
  }
118071
118158
  let highest;
118072
118159
  for (const offer of paymentRequired.accepts) {
@@ -118140,7 +118227,7 @@ async function payAndFetch(session, url, init = {}, opts = {}) {
118140
118227
  let challenge3;
118141
118228
  if (!rerun) {
118142
118229
  if (store !== void 0) startHistoryPrewarm(session, store, mark);
118143
- const response = await fetch(target, keepAliveInit({
118230
+ const response = await unpaidRequest(target, () => keepAliveInit({
118144
118231
  method,
118145
118232
  headers,
118146
118233
  ...body ? { body } : {},
@@ -118183,6 +118270,19 @@ async function payAndFetch(session, url, init = {}, opts = {}) {
118183
118270
  throw error;
118184
118271
  }
118185
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
+ }
118186
118286
  function startHistoryPrewarm(session, store, mark) {
118187
118287
  try {
118188
118288
  withPhaseScope(mark, "prewarm", () => prewarmWalletP03History({
@@ -118190,7 +118290,16 @@ function startHistoryPrewarm(session, store, mark) {
118190
118290
  connection: connectSplit(session.connection, session.historyUrl),
118191
118291
  programId: session.programId,
118192
118292
  pool: store.state.pool,
118193
- 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
+ }
118194
118303
  }));
118195
118304
  } catch {
118196
118305
  }
@@ -125294,8 +125403,7 @@ async function railOffer(paymentRequired, rail, store, facilitator) {
125294
125403
  }
125295
125404
  try {
125296
125405
  if (!facilitator) throw new Error("p03_float_origin_missing");
125297
- const config = await readFloatConfig({ origin: new URL(facilitator).origin });
125298
- const offer = floatOffer({ paymentRequired, store, config });
125406
+ const { offer } = await readFloatOffer({ origin: new URL(facilitator).origin, paymentRequired, store });
125299
125407
  return { priceAtomic: offer.priceAtomic, feeAtomic: offer.feeAtomic, totalAtomic: offer.paidAtomic };
125300
125408
  } catch (error) {
125301
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"];
@@ -125546,15 +125654,16 @@ async function runShieldFromElsewhere({ session, depositId, amountAtomic, onStag
125546
125654
  const result = await (steps.submit ?? submitRelayedDeposit)(common);
125547
125655
  return { state: result.state, transaction: typeof result.receipt?.signature === "string" ? result.receipt.signature : null };
125548
125656
  }
125549
- 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 }) {
125550
125665
  const walStates = captureWalStates(store);
125551
- const history = await loadWalletP03History({
125552
- store,
125553
- connection: connectSplit(session.connection, session.historyUrl),
125554
- programId: session.programId,
125555
- pool: store.state.pool,
125556
- deploymentIdentity: session.proofTools.deploymentIdentity
125557
- });
125666
+ const history = walked ?? await walkWalletHistory(session, store);
125558
125667
  const result = await runRecover({
125559
125668
  store,
125560
125669
  connection: session.connection,
@@ -125800,7 +125909,9 @@ function createWalletTools({
125800
125909
  let refreshRun;
125801
125910
  let refreshFailedAt = 0;
125802
125911
  let refreshFailedCode;
125803
- 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));
125804
125915
  const errorCode2 = (error, fallback) => describeError(error, { fallback, safeText: SAFE_TEXT }).split(/[\s:;(]/, 1)[0];
125805
125916
  const underLease = (task) => session.serial(async () => {
125806
125917
  let release;
@@ -125944,9 +126055,27 @@ function createWalletTools({
125944
126055
  deps: ops.oneTimeAdopt && typeof ops.oneTimeAdopt === "object" ? ops.oneTimeAdopt : {}
125945
126056
  });
125946
126057
  if (ops.oneTimeAdopt !== false) adopter.start();
125947
- function refreshShared() {
126058
+ function refreshShared({ background = false } = {}) {
125948
126059
  if (!refreshRun) {
125949
- 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(() => {
125950
126079
  refreshFailedAt = 0;
125951
126080
  log("MCP_REFRESH_DONE");
125952
126081
  }, (error) => {
@@ -125956,6 +126085,7 @@ function createWalletTools({
125956
126085
  throw error;
125957
126086
  }).finally(() => {
125958
126087
  refreshRun = void 0;
126088
+ refreshInBackground = false;
125959
126089
  });
125960
126090
  }
125961
126091
  return refreshRun;
@@ -125988,7 +126118,7 @@ function createWalletTools({
125988
126118
  }
125989
126119
  if (watched === finalityTarget && status?.confirmationStatus === "finalized") {
125990
126120
  log("MCP_FINALITY_REFRESH");
125991
- await refreshShared().catch(() => {
126121
+ await refreshShared({ background: true }).catch(() => {
125992
126122
  });
125993
126123
  return;
125994
126124
  }
@@ -126013,6 +126143,7 @@ function createWalletTools({
126013
126143
  return;
126014
126144
  }
126015
126145
  if (!stale || refreshFailedAt && Date.now() - refreshFailedAt < REFRESH_RETRY_MS) return;
126146
+ if (refreshRun && refreshInBackground) return;
126016
126147
  await refreshShared().catch(() => {
126017
126148
  });
126018
126149
  }
@@ -126388,6 +126519,8 @@ function createWalletTools({
126388
126519
  );
126389
126520
  } else if (code.startsWith("wallet_spend_refused_")) {
126390
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`;
126391
126524
  } else if (code.startsWith("wallet_quote_refused_") || code.startsWith("fetch_")) {
126392
126525
  next = "nothing was paid; do not retry this URL unchanged";
126393
126526
  } else {
@@ -135601,6 +135734,7 @@ function failureHint(command, reason, deps, values) {
135601
135734
  if (/fetch_offer_unsupported/.test(reason)) {
135602
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`;
135603
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";
135604
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";
135605
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";
135606
135740
  if (/fetch_options_invalid/.test(reason)) {