shinjuku-shielded 0.3.48 → 0.3.49

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": "8d1268b754e192e52be5ba3d5cf134ed42eee552605d96c11076a6004204c737",
5
- "bytes": 11402568,
6
- "sourceCommit": "fd135a3c82678e9fa22dc8cd609cf6f818b5dd65",
4
+ "sha256": "4baf3bca327b51694452760cdb6a4f65d8e869a4c64040c832e92937f66ab395",
5
+ "bytes": 11416627,
6
+ "sourceCommit": "8b2cedd6f47d75d41eb39da9fc85caeed06be5c3",
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.48",
3
+ "version": "0.3.49",
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": "8d1268b7",
7
- "shinjukuSha256": "8d1268b754e192e52be5ba3d5cf134ed42eee552605d96c11076a6004204c737",
6
+ "shinjukuRelease": "4baf3bca",
7
+ "shinjukuSha256": "4baf3bca327b51694452760cdb6a4f65d8e869a4c64040c832e92937f66ab395",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
@@ -50460,7 +50460,7 @@ function connectSplit(own, historyUrl, commitment = "finalized", { pause: pause3
50460
50460
  const historyRpcWarm = () => {
50461
50461
  if (warmedSources.has(historyUrl)) return;
50462
50462
  warmedSources.add(historyUrl);
50463
- rpcFetch(historyUrl, { method: "GET" }).then((response) => response.body?.cancel()).catch(() => {
50463
+ rpcFetch(historyUrl, keepAliveInit({ method: "GET" })).then((response) => response.arrayBuffer()).catch(() => {
50464
50464
  });
50465
50465
  };
50466
50466
  const historyRpcIntegrity = Object.freeze({
@@ -52739,7 +52739,7 @@ var init_quote2 = __esm({
52739
52739
  return bytes2;
52740
52740
  };
52741
52741
  TICKER_MINTS = Object.freeze({ USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" });
52742
- SELF_BROADCAST_MIN_LEFT_MS = 6e4;
52742
+ SELF_BROADCAST_MIN_LEFT_MS = 16e4;
52743
52743
  QUOTE_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
52744
52744
  }
52745
52745
  });
@@ -53087,7 +53087,11 @@ async function refreshFinalizedP03HistorySnapshot({
53087
53087
  keepPoolState(refreshed, snapshot);
53088
53088
  return refreshed;
53089
53089
  }
53090
- async function readFinalizedPool(connection, program, pool2) {
53090
+ async function readFinalizedPool(connection, program, pool2, { treeSlices = false } = {}) {
53091
+ if (treeSlices) {
53092
+ const sliced = await readFinalizedPoolSliced(connection, program, pool2);
53093
+ if (sliced !== void 0) return sliced;
53094
+ }
53091
53095
  if (typeof connection.getMultipleAccountsInfoAndContext !== "function") {
53092
53096
  const response = await retryTransientRpc(() => connection.getAccountInfoAndContext(pool2, "finalized"));
53093
53097
  const only = parseFinalizedPool(response, program, pool2);
@@ -53118,6 +53122,107 @@ function withPoolStateOf(snapshot, wrapped) {
53118
53122
  if (entry !== void 0) SNAPSHOT_POOL_STATES.set(wrapped, entry);
53119
53123
  return wrapped;
53120
53124
  }
53125
+ function parseE1TreeHeader(header) {
53126
+ const invalid4 = (detail) => {
53127
+ throw new Error(`E1TreeAccountInvalid: ${detail}`);
53128
+ };
53129
+ if (!(header instanceof Uint8Array) || header.length !== E1_TREE_HEADER_BYTES) invalid4("length");
53130
+ const bytes2 = Buffer.from(header.buffer, header.byteOffset, header.byteLength);
53131
+ if (bytes2.subarray(0, 8).toString("latin1") !== E1_TREE_MAGIC) invalid4("magic");
53132
+ if (bytes2[40] !== 1 || bytes2[41] !== E1.depth || bytes2.readUInt16LE(42) !== E1.bufferSize || bytes2[44] !== E1.canopyDepth) invalid4("header");
53133
+ if (bytes2[45] !== 0 || bytes2[46] !== 0 || bytes2[47] !== 0) invalid4("reserved");
53134
+ const u642 = (offset) => {
53135
+ const value = bytes2.readBigUInt64LE(offset);
53136
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) invalid4("u64");
53137
+ return Number(value);
53138
+ };
53139
+ const activeIndex = u642(64);
53140
+ if (activeIndex >= E1.bufferSize) invalid4("activeIndex");
53141
+ return {
53142
+ pool: new import_web396.PublicKey(bytes2.subarray(8, 40)).toBase58(),
53143
+ creationSlot: u642(48),
53144
+ sequenceNumber: u642(56),
53145
+ activeIndex,
53146
+ bufferSize: u642(72)
53147
+ };
53148
+ }
53149
+ function slicesRefused(connection) {
53150
+ const endpoint2 = connection.rpcEndpoint;
53151
+ return typeof endpoint2 === "string" ? SLICES_REFUSED_ENDPOINTS.has(endpoint2) : SLICES_REFUSED_CONNECTIONS.has(connection);
53152
+ }
53153
+ function rememberSlicesRefused(connection) {
53154
+ const endpoint2 = connection.rpcEndpoint;
53155
+ if (typeof endpoint2 === "string") SLICES_REFUSED_ENDPOINTS.add(endpoint2);
53156
+ else SLICES_REFUSED_CONNECTIONS.add(connection);
53157
+ }
53158
+ function slicesMethodMissing(error) {
53159
+ const message = String(error?.message ?? "");
53160
+ return /^(404|405|501)\b/.test(message) || /-3260[12]\b/.test(message);
53161
+ }
53162
+ function slicedAccountBytes(value, accountIndex) {
53163
+ if (value === null || typeof value !== "object" || typeof value.owner !== "string" || !Number.isSafeInteger(value.space) || value.space < 0 || !Array.isArray(value.data) || value.data.length !== 2 || value.data[1] !== "base64" || typeof value.data[0] !== "string") {
53164
+ return void 0;
53165
+ }
53166
+ const bytes2 = Buffer.from(value.data[0], "base64");
53167
+ if (bytes2.toString("base64") !== value.data[0]) return void 0;
53168
+ let expected = 0;
53169
+ for (const [index, offset, length] of POOL_SLICES) {
53170
+ if (index === accountIndex) expected += Math.max(0, Math.min(offset + length, value.space) - offset);
53171
+ }
53172
+ return bytes2.length === expected ? bytes2 : void 0;
53173
+ }
53174
+ function slicedSnapshot(result, program, pool2, tree) {
53175
+ if (result === null || typeof result !== "object" || !Array.isArray(result.value) || result.value.length !== 2) return void 0;
53176
+ const [poolValue, treeValue] = result.value;
53177
+ const poolBytes2 = slicedAccountBytes(poolValue, 0);
53178
+ if (poolBytes2 === void 0 || poolValue.space > REFRESH_READ_BYTES) return void 0;
53179
+ const snapshot = parseFinalizedPool({ context: result.context, value: { owner: poolValue.owner, data: poolBytes2 } }, program, pool2);
53180
+ if (snapshot.replayStore !== REPLAY_STORE_INDEXED) return snapshot;
53181
+ const treeBytes = slicedAccountBytes(treeValue, 1);
53182
+ if (treeBytes === void 0 || treeValue.space !== E1.treeBytes) return void 0;
53183
+ const ownerProgramId = canonicalKey(treeValue.owner, "e1_tree_owner").toBase58();
53184
+ if (ownerProgramId !== b58(program)) return void 0;
53185
+ const header = Buffer.from(treeBytes.subarray(0, E1_TREE_HEADER_BYTES));
53186
+ const { activeIndex } = parseE1TreeHeader(header);
53187
+ const rootAt = SLICED_ROOTS_OFFSET + 32 * activeIndex;
53188
+ return withPoolStateOf(snapshot, Object.freeze({
53189
+ ...snapshot,
53190
+ e1TreeSlices: Object.freeze({
53191
+ slot: snapshot.slot,
53192
+ address: tree.toBase58(),
53193
+ ownerProgramId,
53194
+ space: treeValue.space,
53195
+ header,
53196
+ root: Buffer.from(treeBytes.subarray(rootAt, rootAt + 32)),
53197
+ leaves: treeBytes.readUInt32LE(SLICED_LEAVES_OFFSET)
53198
+ })
53199
+ }));
53200
+ }
53201
+ async function readFinalizedPoolSliced(connection, program, pool2) {
53202
+ if (typeof connection._rpcRequest !== "function" || slicesRefused(connection)) return void 0;
53203
+ const tree = new import_web396.PublicKey(e1TreeAddress2(b58(pool2), b58(program)));
53204
+ let response;
53205
+ try {
53206
+ response = await connection._rpcRequest(P03_POOL_SLICES_METHOD, [[b58(pool2), tree.toBase58()], { commitment: "finalized", slices: POOL_SLICES }]);
53207
+ } catch (error) {
53208
+ if (slicesMethodMissing(error)) rememberSlicesRefused(connection);
53209
+ markPhase(`pool-sliced-fallback-${reuseRefusalCause(error)}`);
53210
+ return void 0;
53211
+ }
53212
+ if (response?.error !== void 0) {
53213
+ if (response.error?.code === -32601 || response.error?.code === -32602) rememberSlicesRefused(connection);
53214
+ markPhase("pool-sliced-fallback-refused");
53215
+ return void 0;
53216
+ }
53217
+ let snapshot;
53218
+ try {
53219
+ snapshot = slicedSnapshot(response?.result, program, pool2, tree);
53220
+ } catch {
53221
+ snapshot = void 0;
53222
+ }
53223
+ markPhase(snapshot === void 0 ? "pool-sliced-fallback-answer" : "pool-sliced");
53224
+ return snapshot;
53225
+ }
53121
53226
  async function readFinalizedPoolForRefresh(connection, program, pool2) {
53122
53227
  if (typeof connection.getMultipleAccountsInfoAndContext !== "function") return readFinalizedPool(connection, program, pool2);
53123
53228
  const tree = new import_web396.PublicKey(e1TreeAddress2(b58(pool2), b58(program)));
@@ -53861,29 +53966,44 @@ function assertP03E1TreeComplete({ program, pool: pool2, poolSnapshot, settles,
53861
53966
  const mismatch = (detail) => {
53862
53967
  throw new Error(`p03_history_e1_tree_mismatch:${detail}`);
53863
53968
  };
53864
- const tree = poolSnapshot.e1TreeAccount;
53969
+ const sliced = poolSnapshot.e1TreeSlices;
53970
+ const tree = sliced ?? poolSnapshot.e1TreeAccount;
53865
53971
  if (!tree || tree.slot !== poolSnapshot.slot) mismatch("tree_snapshot_missing");
53866
53972
  if (tree.address !== e1TreeAddress2(b58(pool2), b58(program))) mismatch("tree_address");
53867
- const empty = tree.data === null || tree.ownerProgramId === null || tree.ownerProgramId === SYSTEM_PROGRAM && tree.data.every((byte) => byte === 0);
53973
+ const empty = sliced === void 0 && (tree.data === null || tree.ownerProgramId === null || tree.ownerProgramId === SYSTEM_PROGRAM && tree.data.every((byte) => byte === 0));
53868
53974
  if (closed) {
53869
53975
  if (!empty) mismatch("closed_pool_has_tree");
53870
53976
  return Object.freeze({ state: "closed", address: tree.address, slot: BigInt(poolSnapshot.slot) });
53871
53977
  }
53872
53978
  if (empty) mismatch("tree_empty_without_close");
53873
- if (tree.ownerProgramId !== b58(program) || tree.data.length !== E1.treeBytes) mismatch("tree_owner_or_length");
53979
+ const space = sliced !== void 0 ? sliced.space : tree.data.length;
53980
+ if (tree.ownerProgramId !== b58(program) || space !== E1.treeBytes) mismatch("tree_owner_or_length");
53874
53981
  let header;
53982
+ let treeRoot;
53983
+ let treeLeaves;
53875
53984
  try {
53876
- header = readE1TreeAccount(tree.data);
53985
+ if (sliced !== void 0) {
53986
+ header = parseE1TreeHeader(sliced.header);
53987
+ if (!(sliced.root instanceof Uint8Array) || sliced.root.length !== 32 || !Number.isSafeInteger(sliced.leaves)) throw new Error("E1TreeAccountInvalid: slices");
53988
+ treeRoot = sliced.root;
53989
+ treeLeaves = sliced.leaves;
53990
+ } else {
53991
+ const data = Buffer.from(tree.data.buffer, tree.data.byteOffset, tree.data.byteLength);
53992
+ header = parseE1TreeHeader(data.subarray(0, E1_TREE_HEADER_BYTES));
53993
+ const rootAt = E1_CHANGELOGS_OFFSET + E1_CHANGELOG_BYTES * header.activeIndex;
53994
+ treeRoot = data.subarray(rootAt, rootAt + 32);
53995
+ treeLeaves = data.readUInt32LE(E1_LEAF_COUNT_OFFSET);
53996
+ }
53877
53997
  } catch (error) {
53878
53998
  mismatch(`tree_header:${error?.message ?? "invalid"}`);
53879
53999
  }
53880
54000
  if (header.pool !== b58(pool2)) mismatch("tree_pool");
53881
54001
  const mirror = E1TreeMirror.fromOrderedValues(settles.flatMap((values) => e1SortValues(values)));
53882
54002
  const leaves = mirror.leaves();
53883
- if (header.leaves !== leaves) mismatch(`leaves:${header.leaves}/${leaves}`);
54003
+ if (treeLeaves !== leaves) mismatch(`leaves:${treeLeaves}/${leaves}`);
53884
54004
  if (Number(header.sequenceNumber) !== 2 * leaves - 1) mismatch(`sequence:${header.sequenceNumber}/${2 * leaves - 1}`);
53885
54005
  const root = Buffer.from(mirror.root()).toString("hex");
53886
- if (Buffer.from(header.root).toString("hex") !== root) mismatch("root");
54006
+ if (Buffer.from(treeRoot).toString("hex") !== root) mismatch("root");
53887
54007
  return Object.freeze({ state: "open", address: tree.address, slot: BigInt(poolSnapshot.slot), root, leaves });
53888
54008
  }
53889
54009
  function sameE1TreeHeader(snapshot, verified, program, pool2) {
@@ -54683,7 +54803,7 @@ function base58Decode(value) {
54683
54803
  while (zeros < value.length && value[zeros] === "1") zeros += 1;
54684
54804
  return Uint8Array.from(Buffer.concat([Buffer.alloc(zeros), body]));
54685
54805
  }
54686
- var import_web396, b58Cache, b58, REPLAY_STORE_INDEXED, CLOSE_REPLAY_TREE_TAG, EXTEND_ANCHOR_RING_TAG, WIDEN_ANCHOR_RING_TAG, WIDE_ANCHOR_RING_POOL_BYTES, LINK_SUCCESSOR_TAG, IMPORT_REPLAY_LEAVES_TAG, SETTLE_MOVE_TAG, SWEEP_PREDECESSOR_VAULT_TAG, RELINK_SUCCESSOR_TAG, ROTATE_PAYMENT_SETTLER_TAG, IMPORT_A_LEAF_BYTES, IMPORT_MEMBERSHIP_BYTES, IMPORT_PRESENT_SHIFT, IMPORT_MAX_ENTRIES, MOVE_HEAD_BYTES, MOVE_INSERTED_VALUES, DEFAULT_KEY, FIELD_BYTES2, PRIMARY_PROOF_BYTES, SUBTREE_LEAVES, PAGE_SIZE, FIELD_MODULUS3, BPF_LOADER_UPGRADEABLE_PROGRAM_ID, SYSTEM_PROGRAM, TEST_EXECUTABLES, derivationMemo, memo, reviewedExecutables, isProgramDataIdentityError, ASSUMED_ORIGINAL_EXECUTABLE, AUTHENTICATED_HISTORY_REPORTS, HISTORY_ATTESTATIONS, SNAPSHOT_POOL_STATES, REPORT_POOL_STATES, hasExecutableEvidence, P03_FINALIZED_HISTORY_SOURCE_MODEL, P03_PROGRAMDATA_COVERAGE_SOURCE_MODEL, P03_RUN_RECOVER_UNAVAILABLE_FROM_CHAIN, PROFILES, P03_SETTLEMENT_TAGS, P03_INLINE_SETTLEMENT_TAGS, P03_PAYMENT_REPLAY_INDICES, NO_CONTEXTS, REFRESH_READ_BYTES, E1_TREE_HEADER_BYTES, HISTORY_FETCH_CONCURRENCY, HISTORY_BULK_TRANSACTIONS, HISTORY_BULK_ADDRESSES, TRANSIENT_RPC_ATTEMPTS, TRANSIENT_RPC_BASE_DELAY_MS, LAGGING_NODE_STEP_OF_BASE, LAGGING_NODE_MAX_RETRIES, LAGGING_NODE_FAST_RETRIES, LAGGING_NODE_SLOW_STEP_OF_BASE, LAGGING_NODE_RPC_CODES;
54806
+ var import_web396, b58Cache, b58, REPLAY_STORE_INDEXED, CLOSE_REPLAY_TREE_TAG, EXTEND_ANCHOR_RING_TAG, WIDEN_ANCHOR_RING_TAG, WIDE_ANCHOR_RING_POOL_BYTES, LINK_SUCCESSOR_TAG, IMPORT_REPLAY_LEAVES_TAG, SETTLE_MOVE_TAG, SWEEP_PREDECESSOR_VAULT_TAG, RELINK_SUCCESSOR_TAG, ROTATE_PAYMENT_SETTLER_TAG, IMPORT_A_LEAF_BYTES, IMPORT_MEMBERSHIP_BYTES, IMPORT_PRESENT_SHIFT, IMPORT_MAX_ENTRIES, MOVE_HEAD_BYTES, MOVE_INSERTED_VALUES, DEFAULT_KEY, FIELD_BYTES2, PRIMARY_PROOF_BYTES, SUBTREE_LEAVES, PAGE_SIZE, FIELD_MODULUS3, BPF_LOADER_UPGRADEABLE_PROGRAM_ID, SYSTEM_PROGRAM, TEST_EXECUTABLES, derivationMemo, memo, reviewedExecutables, isProgramDataIdentityError, ASSUMED_ORIGINAL_EXECUTABLE, AUTHENTICATED_HISTORY_REPORTS, HISTORY_ATTESTATIONS, SNAPSHOT_POOL_STATES, REPORT_POOL_STATES, hasExecutableEvidence, P03_FINALIZED_HISTORY_SOURCE_MODEL, P03_PROGRAMDATA_COVERAGE_SOURCE_MODEL, P03_RUN_RECOVER_UNAVAILABLE_FROM_CHAIN, PROFILES, P03_SETTLEMENT_TAGS, P03_INLINE_SETTLEMENT_TAGS, P03_PAYMENT_REPLAY_INDICES, NO_CONTEXTS, REFRESH_READ_BYTES, E1_TREE_HEADER_BYTES, E1_TREE_MAGIC, E1_CHANGELOG_BYTES, E1_CHANGELOGS_OFFSET, E1_RIGHTMOST_OFFSET, E1_LEAF_COUNT_OFFSET, E1_CANOPY_OFFSET, E1_CANOPY_NODES, P03_POOL_SLICES_METHOD, POOL_SLICES, SLICED_ROOTS_OFFSET, SLICED_LEAVES_OFFSET, SLICES_REFUSED_ENDPOINTS, SLICES_REFUSED_CONNECTIONS, HISTORY_FETCH_CONCURRENCY, HISTORY_BULK_TRANSACTIONS, HISTORY_BULK_ADDRESSES, TRANSIENT_RPC_ATTEMPTS, TRANSIENT_RPC_BASE_DELAY_MS, LAGGING_NODE_STEP_OF_BASE, LAGGING_NODE_MAX_RETRIES, LAGGING_NODE_FAST_RETRIES, LAGGING_NODE_SLOW_STEP_OF_BASE, LAGGING_NODE_RPC_CODES;
54687
54807
  var init_walk = __esm({
54688
54808
  "wallet/src/history/walk.mjs"() {
54689
54809
  "use strict";
@@ -54943,6 +55063,25 @@ var init_walk = __esm({
54943
55063
  NO_CONTEXTS = Object.freeze([]);
54944
55064
  REFRESH_READ_BYTES = 4096;
54945
55065
  E1_TREE_HEADER_BYTES = 80;
55066
+ E1_TREE_MAGIC = "SX402T01";
55067
+ E1_CHANGELOG_BYTES = 32 + 32 * E1.depth + 8;
55068
+ E1_CHANGELOGS_OFFSET = E1_TREE_HEADER_BYTES;
55069
+ E1_RIGHTMOST_OFFSET = E1_CHANGELOGS_OFFSET + E1.bufferSize * E1_CHANGELOG_BYTES;
55070
+ E1_LEAF_COUNT_OFFSET = E1_RIGHTMOST_OFFSET + 32 * E1.depth + 32;
55071
+ E1_CANOPY_OFFSET = E1_RIGHTMOST_OFFSET + E1_CHANGELOG_BYTES;
55072
+ E1_CANOPY_NODES = 2 ** (E1.canopyDepth + 1) - 2;
55073
+ if (E1_CANOPY_OFFSET + 32 * E1_CANOPY_NODES !== E1.treeBytes) throw new Error("p03_history_e1_tree_mismatch:layout");
55074
+ P03_POOL_SLICES_METHOD = "getMultipleAccountsSlices";
55075
+ POOL_SLICES = Object.freeze([
55076
+ Object.freeze([0, 0, REFRESH_READ_BYTES]),
55077
+ Object.freeze([1, 0, E1_TREE_HEADER_BYTES]),
55078
+ ...Array.from({ length: E1.bufferSize }, (_, index) => Object.freeze([1, E1_CHANGELOGS_OFFSET + E1_CHANGELOG_BYTES * index, 32])),
55079
+ Object.freeze([1, E1_LEAF_COUNT_OFFSET, 4])
55080
+ ]);
55081
+ SLICED_ROOTS_OFFSET = E1_TREE_HEADER_BYTES;
55082
+ SLICED_LEAVES_OFFSET = SLICED_ROOTS_OFFSET + 32 * E1.bufferSize;
55083
+ SLICES_REFUSED_ENDPOINTS = /* @__PURE__ */ new Set();
55084
+ SLICES_REFUSED_CONNECTIONS = /* @__PURE__ */ new WeakSet();
54946
55085
  HISTORY_FETCH_CONCURRENCY = 4;
54947
55086
  HISTORY_BULK_TRANSACTIONS = 256;
54948
55087
  HISTORY_BULK_ADDRESSES = 256;
@@ -55805,6 +55944,9 @@ function withBoundedOwnReads(connection) {
55805
55944
  const value = Reflect.get(target, property);
55806
55945
  if (typeof value !== "function") return value;
55807
55946
  if (BOUNDED_OWN_METHODS.has(property)) return (...args) => boundedOwnRead(() => value.apply(target, args));
55947
+ if (property === "_rpcRequest") {
55948
+ return (...args) => args[0] === P03_POOL_SLICES_METHOD ? boundedOwnRead(() => value.apply(target, args)) : value.apply(target, args);
55949
+ }
55808
55950
  return value.bind(target);
55809
55951
  }
55810
55952
  });
@@ -55855,7 +55997,7 @@ async function readPages(history, pool2, needed, first, { wakeSlot } = {}) {
55855
55997
  return { records: records.slice(0, needed), imports, initialization, syncedSlot };
55856
55998
  }
55857
55999
  async function readCompactPoolSnapshot({ connection, programId, pool: pool2 }) {
55858
- return readFinalizedPool(withBoundedOwnReads(connection), new import_web397.PublicKey(programId), new import_web397.PublicKey(pool2));
56000
+ return readFinalizedPool(withBoundedOwnReads(connection), new import_web397.PublicKey(programId), new import_web397.PublicKey(pool2), { treeSlices: true });
55859
56001
  }
55860
56002
  function pageShapeValid(result, pool2, from) {
55861
56003
  return Boolean(result) && typeof result === "object" && result.pool === pool2 && result.fromOrdinal === from && isIndex(result.total) && isIndex(result.syncedSlot) && Array.isArray(result.records) && result.records.length === Math.max(0, Math.min(result.total, from + P03_COMPACT_PAGE) - from) && Boolean(result.initialization) && isSignature(result.initialization.signature) && isIndex(result.initialization.slot);
@@ -56156,7 +56298,7 @@ async function readCompactP03HistoryNow({
56156
56298
  markPhase("compact-pool-preread-failed");
56157
56299
  }
56158
56300
  }
56159
- snapshot ??= await readFinalizedPool(own, program, poolKey);
56301
+ snapshot ??= await readFinalizedPool(own, program, poolKey, { treeSlices: true });
56160
56302
  markPhase(knownSnapshot !== void 0 ? "compact-pool-reused" : "compact-pool");
56161
56303
  if (snapshot.terminal) throw refuse3("p03_compact_history_pool_terminal");
56162
56304
  if (snapshot.currentIndex % SUBTREE_LEAVES3 !== 0n) throw refuse3("p03_compact_history_snapshot_invalid");
@@ -56637,7 +56779,7 @@ var init_compact = __esm({
56637
56779
  IMPORT_MAX_VALUES = 3;
56638
56780
  LIST_ATTEMPTS = 6;
56639
56781
  OWN_READ_TIMEOUT_MS = HISTORY_RPC_REQUEST_TIMEOUT_MS;
56640
- BOUNDED_OWN_METHODS = /* @__PURE__ */ new Set(["getAccountInfo", "getAccountInfoAndContext", "getMultipleAccountsInfo"]);
56782
+ BOUNDED_OWN_METHODS = /* @__PURE__ */ new Set(["getAccountInfo", "getAccountInfoAndContext", "getMultipleAccountsInfo", "getMultipleAccountsInfoAndContext"]);
56641
56783
  }
56642
56784
  });
56643
56785
 
@@ -64067,6 +64209,8 @@ var init_errorCodes = __esm({
64067
64209
  "p03_float_seller_unanswered_paid_retry_same_request",
64068
64210
  "p03_float_seller_kept_payment",
64069
64211
  "p03_float_receipt_pruned",
64212
+ "p03_float_request_expired_nothing_paid",
64213
+ "request_pruned",
64070
64214
  // Our facilitator settle reasons the self-broadcast leg reads (floatPay.mjs BROADCAST_*), and its own quote-closing note.
64071
64215
  "invalid_exact_svm_transaction_simulation_failed",
64072
64216
  "p03_pocket_exact_lease_unreadable_retry",
@@ -92516,6 +92660,25 @@ var init_pay = __esm({
92516
92660
  }
92517
92661
  });
92518
92662
 
92663
+ // wallet/src/pay/floatWords.mjs
92664
+ function floatRefundWhy(error) {
92665
+ const why = error?.broadcastRefusal;
92666
+ if (why === "request_pruned") return "The wallet dropped this request 1 hour after it was made, so nothing was sent to the seller.";
92667
+ if (why === "seller_quote_closing") return "The seller's quote was about to close, so the wallet sent no transfer to the seller.";
92668
+ if (typeof why === "string" && why) return `Shinjuku's facilitator refused to send the transfer to the seller (${why}).`;
92669
+ return "Seller did not take it.";
92670
+ }
92671
+ function floatExpiredWhy(error) {
92672
+ return error?.broadcastRefusal === "request_pruned" ? "the wallet drops a request 1 hour after it was made, and this one was older" : "the seller's quote had too little time left to pay it safely (a payment needs about 2.5 minutes of it)";
92673
+ }
92674
+ var FLOAT_AMBIGUOUS_NOTE;
92675
+ var init_floatWords = __esm({
92676
+ "wallet/src/pay/floatWords.mjs"() {
92677
+ "use strict";
92678
+ FLOAT_AMBIGUOUS_NOTE = "An earlier send of this payment got no answer, from the seller or from Shinjuku's facilitator; if that send landed, the seller holds the payment and no refund comes.";
92679
+ }
92680
+ });
92681
+
92519
92682
  // wallet/src/pay/floatPay.mjs
92520
92683
  import { createHash as createHash21, createHmac as createHmac8, randomBytes as randomBytes11 } from "node:crypto";
92521
92684
  import { fileURLToPath as fileURLToPath9 } from "node:url";
@@ -92592,9 +92755,8 @@ function refundArrived(snapshot, refundTo) {
92592
92755
  function returnArrivedFloatRefundBudgets(store, snapshot) {
92593
92756
  for (const name of store.listWal()) {
92594
92757
  if (!name.startsWith(FLOAT_PAYMENT_WAL_PREFIX)) continue;
92595
- let record = store.readWal(name);
92758
+ const record = store.readWal(name);
92596
92759
  if (record?.schema !== FLOAT_PAYMENT_SCHEMA) continue;
92597
- record = pruneFloatRecord(store, name, record);
92598
92760
  if (record.state !== "refund_pending" || typeof record.innerRequestId !== "string") continue;
92599
92761
  if (refundArrived(snapshot, record.refundTo)) releaseRefundedReservation({ store, requestId: record.innerRequestId });
92600
92762
  }
@@ -92607,6 +92769,12 @@ function finishedAtMs(record) {
92607
92769
  }
92608
92770
  function pruneFloatRecord(store, walName2, record, now = Date.now()) {
92609
92771
  const at = finishedAtMs(record);
92772
+ if (at === void 0 && record.requestPruned !== true && Number.isFinite(record.createdAtMs) && now >= record.createdAtMs + FLOAT_KEEP_OPEN_REQUEST_MS) {
92773
+ const { bodyBase64: _body2, headers: _headers2, ...request2 } = record.request ?? {};
92774
+ const open3 = { ...record, request: request2, requestPruned: true, prunedAtMs: now };
92775
+ store.writeWal(walName2, open3);
92776
+ return open3;
92777
+ }
92610
92778
  if (record.pruned === true || !Number.isFinite(at) || now < at + FLOAT_KEEP_BYTES_MS) return record;
92611
92779
  const { bodyBase64: _body, headers: _headers, ...request } = record.request ?? {};
92612
92780
  const { resultBase64, sellerHeaders: _sellerHeaders, sellerReason: _reason, ...rest } = record;
@@ -92620,6 +92788,18 @@ function pruneFloatRecord(store, walName2, record, now = Date.now()) {
92620
92788
  store.writeWal(walName2, pruned);
92621
92789
  return pruned;
92622
92790
  }
92791
+ function pruneFloatRecords(store, now = Date.now()) {
92792
+ for (const name of store.listWal()) {
92793
+ if (!name.startsWith(FLOAT_PAYMENT_WAL_PREFIX)) continue;
92794
+ let record;
92795
+ try {
92796
+ record = store.readWal(name);
92797
+ } catch {
92798
+ continue;
92799
+ }
92800
+ if (record?.schema === FLOAT_PAYMENT_SCHEMA) pruneFloatRecord(store, name, record, now);
92801
+ }
92802
+ }
92623
92803
  function finishedPruned(record) {
92624
92804
  const amounts = { floatId: record.floatId, paidAtomic: record.paidAtomic, priceAtomic: record.priceAtomic, feeAtomic: record.feeAtomic };
92625
92805
  if (record.state === "receipt") {
@@ -92632,7 +92812,12 @@ function finishedPruned(record) {
92632
92812
  ...isSolanaSignature(record.broadcastSignature) ? { transaction: record.broadcastSignature } : { landedSignatureUnknown: true }
92633
92813
  });
92634
92814
  }
92635
- fail18("p03_float_refund_pending", { ...amounts, refundEtaSeconds: FLOAT_REFUND_ETA_SECONDS, ambiguous: record.ambiguous === true });
92815
+ fail18("p03_float_refund_pending", {
92816
+ ...amounts,
92817
+ refundEtaSeconds: FLOAT_REFUND_ETA_SECONDS,
92818
+ ambiguous: record.ambiguous === true,
92819
+ ...record.broadcastRefusal ? { broadcastRefusal: record.broadcastRefusal } : {}
92820
+ });
92636
92821
  }
92637
92822
  function floatRefundsInFlightAtomic(store, snapshot) {
92638
92823
  const refreshedAtMs = Date.parse(snapshot?.refreshedAt ?? "");
@@ -93023,7 +93208,9 @@ async function payViaFloat({
93023
93208
  if (record.schema !== FLOAT_PAYMENT_SCHEMA) fail18("p03_float_record_invalid");
93024
93209
  if (record.fingerprint !== fingerprint) fail18("p03_float_request_id_conflict");
93025
93210
  record = pruneFloatRecord(store, walName2, record);
93026
- if (record.pruned !== true && JSON.stringify(record.request) !== JSON.stringify(requestData)) fail18("p03_float_request_data_mismatch");
93211
+ if (record.pruned !== true && record.requestPruned !== true && JSON.stringify(record.request) !== JSON.stringify(requestData)) {
93212
+ fail18("p03_float_request_data_mismatch");
93213
+ }
93027
93214
  if (record.pruned === true) finishedPruned(record);
93028
93215
  if (record.state === "receipt") return paidResult(record, true);
93029
93216
  } else {
@@ -93066,6 +93253,15 @@ async function payViaFloat({
93066
93253
  store.writeWal(walName2, record);
93067
93254
  mark("float-quoted");
93068
93255
  }
93256
+ if (record.xPayment === void 0 && innerUnsent() && (record.requestPruned === true || record.selfBroadcast && Date.now() + SELF_BROADCAST_LEG1_LEFT_MS > record.selfBroadcast.expiresAtMs)) {
93257
+ store.removeWal(walName2);
93258
+ if (record.requestPruned === true) fail18("p03_float_request_expired_nothing_paid", {
93259
+ priceAtomic: record.priceAtomic,
93260
+ feeAtomic: record.feeAtomic,
93261
+ broadcastRefusal: "request_pruned"
93262
+ });
93263
+ quoteTooShort(record);
93264
+ }
93069
93265
  if (record.xPayment === void 0) {
93070
93266
  let regenerated = false;
93071
93267
  const finishingUntil = Date.now() + FINISHING_LIMIT_MS;
@@ -93093,7 +93289,12 @@ async function payViaFloat({
93093
93289
  ...withoutCallerBody(deps),
93094
93290
  fetchImpl: floatFetch(fetchImpl, seen),
93095
93291
  settlePriorBeforeQuote: true,
93096
- acceptFrontedReceipt: front
93292
+ acceptFrontedReceipt: front,
93293
+ // An anchor wait (up to one epoch + 60 s) can use up the seller's quote: the gate above runs again
93294
+ // before the fresh leg-1 402, while nothing of leg 1 exists (review 2026-10-16).
93295
+ ...record.selfBroadcast ? { afterAnchorWait: () => {
93296
+ if (Date.now() + SELF_BROADCAST_LEG1_LEFT_MS > record.selfBroadcast.expiresAtMs) quoteTooShort(record);
93297
+ } } : {}
93097
93298
  }
93098
93299
  });
93099
93300
  } catch (error) {
@@ -93135,6 +93336,25 @@ async function payViaFloat({
93135
93336
  if (hash8(record.xPayment) !== record.headerSha256) fail18("p03_float_record_invalid");
93136
93337
  if (record.selfBroadcast) return selfBroadcastLeg({ store, walName: walName2, record, fetchImpl, sleep: sleep5, mark });
93137
93338
  const lostAnswer = record.state === "submitted";
93339
+ if (record.requestPruned === true) {
93340
+ record = {
93341
+ ...record,
93342
+ state: "refund_pending",
93343
+ broadcastRefusal: "request_pruned",
93344
+ refundPendingAtMs: record.refundPendingAtMs ?? Date.now(),
93345
+ ...lostAnswer ? { ambiguous: true } : {}
93346
+ };
93347
+ store.writeWal(walName2, record);
93348
+ fail18("p03_float_refund_pending", {
93349
+ floatId: record.floatId,
93350
+ paidAtomic: record.paidAtomic,
93351
+ priceAtomic: record.priceAtomic,
93352
+ feeAtomic: record.feeAtomic,
93353
+ refundEtaSeconds: FLOAT_REFUND_ETA_SECONDS,
93354
+ ambiguous: record.ambiguous === true,
93355
+ broadcastRefusal: "request_pruned"
93356
+ });
93357
+ }
93138
93358
  record = { ...record, state: record.state === "refund_pending" ? "refund_pending" : "submitted", submittedAtMs: record.submittedAtMs ?? Date.now() };
93139
93359
  store.writeWal(walName2, record);
93140
93360
  mark("seller-sent");
@@ -93227,20 +93447,28 @@ async function selfBroadcastLeg({ store, walName: walName2, record, fetchImpl, s
93227
93447
  if (record.state === "seller_kept") keptUnknown();
93228
93448
  const settleUrl = new URL("/api/x402/settle", new URL(record.payUrlPrefix).origin).href;
93229
93449
  const until = Date.now() + BROADCAST_LIMIT_MS;
93230
- let unsigned = record.broadcastAtMs === void 0 || record.broadcastUnsigned === true;
93450
+ let maybeSigned = record.broadcastMaybeSigned ?? record.broadcastAtMs !== void 0;
93451
+ if (record.broadcastInFlight === true) maybeSigned = true;
93231
93452
  for (let attempt = 0; ; attempt += 1) {
93232
- if (Date.now() > record.selfBroadcast.expiresAtMs - BROADCAST_QUOTE_MARGIN_MS) {
93453
+ const landBy = (record.floatPaidAtMs ?? record.createdAtMs ?? Date.now()) + TRANSFER_LANDING_WINDOW_MS;
93454
+ if (Date.now() > record.selfBroadcast.expiresAtMs - BROADCAST_QUOTE_MARGIN_MS || landBy > record.selfBroadcast.expiresAtMs - PROOF_DELIVERY_MS) {
93233
93455
  record = {
93234
93456
  ...record,
93235
93457
  state: "refund_pending",
93236
93458
  broadcastRefusal: "seller_quote_closing",
93237
93459
  refundPendingAtMs: record.refundPendingAtMs ?? Date.now(),
93238
- ...unsigned ? {} : { ambiguous: true }
93460
+ ...maybeSigned ? { ambiguous: true } : {}
93239
93461
  };
93240
93462
  store.writeWal(walName2, record);
93241
93463
  refundPending();
93242
93464
  }
93243
- record = { ...record, state: "broadcasting", broadcastAtMs: record.broadcastAtMs ?? Date.now(), broadcastUnsigned: false };
93465
+ record = {
93466
+ ...record,
93467
+ state: "broadcasting",
93468
+ broadcastAtMs: record.broadcastAtMs ?? Date.now(),
93469
+ broadcastInFlight: true,
93470
+ broadcastMaybeSigned: maybeSigned
93471
+ };
93244
93472
  store.writeWal(walName2, record);
93245
93473
  if (attempt === 0) mark("float-broadcast-sent");
93246
93474
  let answer;
@@ -93268,14 +93496,21 @@ async function selfBroadcastLeg({ store, walName: walName2, record, fetchImpl, s
93268
93496
  store.writeWal(walName2, record);
93269
93497
  keptUnknown();
93270
93498
  }
93271
- if (BROADCAST_DEAD.has(reason) || BROADCAST_DEAD_STANDARD.test(reason)) {
93272
- record = { ...record, state: "refund_pending", broadcastRefusal: plainText(reason), refundPendingAtMs: record.refundPendingAtMs ?? Date.now() };
93499
+ const refused = BROADCAST_REFUSED.has(reason) || BROADCAST_REFUSED_STANDARD.test(reason);
93500
+ if (BROADCAST_DEAD.has(reason) || refused) {
93501
+ record = {
93502
+ ...record,
93503
+ state: "refund_pending",
93504
+ broadcastRefusal: plainText(reason),
93505
+ refundPendingAtMs: record.refundPendingAtMs ?? Date.now(),
93506
+ broadcastInFlight: false,
93507
+ ...refused && maybeSigned ? { ambiguous: true } : {}
93508
+ };
93273
93509
  store.writeWal(walName2, record);
93274
93510
  refundPending();
93275
93511
  }
93276
- if (BROADCAST_UNSIGNED.has(reason)) unsigned = true;
93277
- else if (!BROADCAST_NO_LOOKUP.has(reason)) unsigned = false;
93278
- record = { ...record, broadcastUnsigned: unsigned };
93512
+ if (!BROADCAST_UNSIGNED.has(reason) && !BROADCAST_NO_LOOKUP.has(reason)) maybeSigned = true;
93513
+ record = { ...record, broadcastInFlight: false, broadcastMaybeSigned: maybeSigned };
93279
93514
  store.writeWal(walName2, record);
93280
93515
  if (Date.now() >= until) fail18("p03_float_broadcast_pending_retry_same_request", { floatId: record.floatId });
93281
93516
  await sleep5(FINISHING_POLL_MS);
@@ -93289,6 +93524,11 @@ async function selfBroadcastLeg({ store, walName: walName2, record, fetchImpl, s
93289
93524
  signature: record.broadcastSignature
93290
93525
  })).toString("base64");
93291
93526
  const landed = { floatId: record.floatId, transaction: record.broadcastSignature, paidAtomic: record.paidAtomic };
93527
+ if (record.requestPruned === true) {
93528
+ record = { ...record, state: "seller_kept", sellerKeptAtMs: record.sellerKeptAtMs ?? Date.now() };
93529
+ store.writeWal(walName2, record);
93530
+ fail18("p03_float_seller_kept_payment", { ...landed, priceAtomic: record.priceAtomic, feeAtomic: record.feeAtomic });
93531
+ }
93292
93532
  for (let attempt = 0; ; attempt += 1) {
93293
93533
  if (record.state !== "seller_kept") {
93294
93534
  record = { ...record, state: "submitted", submittedAtMs: record.submittedAtMs ?? Date.now() };
@@ -93355,6 +93595,13 @@ async function selfBroadcastLeg({ store, walName: walName2, record, fetchImpl, s
93355
93595
  });
93356
93596
  }
93357
93597
  }
93598
+ function quoteTooShort(record) {
93599
+ fail18("p03_float_request_expired_nothing_paid", {
93600
+ priceAtomic: record.priceAtomic,
93601
+ feeAtomic: record.feeAtomic,
93602
+ broadcastRefusal: "seller_quote_closing"
93603
+ });
93604
+ }
93358
93605
  function withoutCallerBody(deps) {
93359
93606
  const {
93360
93607
  freshRequestBody: _fresh,
@@ -93372,7 +93619,7 @@ function keptSellerHeaders(headers) {
93372
93619
  let bytes2 = 0;
93373
93620
  for (const [name, value] of headers) {
93374
93621
  if (kept.length >= SELLER_HEADERS_MAX_COUNT) break;
93375
- if (SELLER_HEADERS_DROPPED.has(name) || SELLER_HEADERS_LINKING.test(name)) continue;
93622
+ if (!SELLER_HEADERS_KEPT.has(String(name).toLowerCase())) continue;
93376
93623
  const size = Buffer.byteLength(name) + Buffer.byteLength(value);
93377
93624
  if (bytes2 + size > SELLER_HEADERS_MAX_BYTES) continue;
93378
93625
  bytes2 += size;
@@ -93396,7 +93643,7 @@ function paidResult(record, replayed) {
93396
93643
  float: { floatId: record.floatId }
93397
93644
  };
93398
93645
  }
93399
- 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, FLOAT_FRONT_HEADER, hash8, fail18, floatPaymentWalName, FLOAT_KEEP_BYTES_MS, configCache, configReads, poolDomains, poolDomainReads, poolDomainWarmFailedAt, WARM_RETRY_MS, payerGenerator, etaEntry, loadPayerGenerator, plainText, BROADCAST_DEAD, BROADCAST_DEAD_STANDARD, BROADCAST_UNSIGNED, BROADCAST_NO_LOOKUP, BROADCAST_LANDED, BROADCAST_LIMIT_MS, BROADCAST_QUOTE_MARGIN_MS, SELF_BROADCAST_RESEND_MS, SELLER_HEADERS_MAX_COUNT, SELLER_HEADERS_MAX_BYTES, SELLER_HEADERS_DROPPED, SELLER_HEADERS_LINKING;
93646
+ 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, FLOAT_FRONT_HEADER, hash8, fail18, floatPaymentWalName, FLOAT_KEEP_BYTES_MS, FLOAT_KEEP_OPEN_REQUEST_MS, configCache, configReads, poolDomains, poolDomainReads, poolDomainWarmFailedAt, WARM_RETRY_MS, payerGenerator, etaEntry, loadPayerGenerator, plainText, BROADCAST_REFUSED, BROADCAST_REFUSED_STANDARD, BROADCAST_DEAD, TRANSFER_LANDING_WINDOW_MS, PROOF_DELIVERY_MS, SELF_BROADCAST_LEG1_LEFT_MS, BROADCAST_UNSIGNED, BROADCAST_NO_LOOKUP, BROADCAST_LANDED, BROADCAST_LIMIT_MS, BROADCAST_QUOTE_MARGIN_MS, SELF_BROADCAST_RESEND_MS, SELLER_HEADERS_MAX_COUNT, SELLER_HEADERS_MAX_BYTES, SELLER_HEADERS_KEPT;
93400
93647
  var init_floatPay = __esm({
93401
93648
  "wallet/src/pay/floatPay.mjs"() {
93402
93649
  "use strict";
@@ -93413,6 +93660,7 @@ var init_floatPay = __esm({
93413
93660
  init_store();
93414
93661
  init_proxy();
93415
93662
  init_payResource();
93663
+ init_floatWords();
93416
93664
  FLOAT_PAYMENT_SCHEMA = "carbon-shielded-wallet/float-payment/v1";
93417
93665
  REGENERATE_CODES = /* @__PURE__ */ new Set(["float_payment_in_flight", "float_quote_open"]);
93418
93666
  FLOAT_PAYMENT_WAL_PREFIX = "float-";
@@ -93436,6 +93684,7 @@ var init_floatPay = __esm({
93436
93684
  };
93437
93685
  floatPaymentWalName = (requestKey) => `${FLOAT_PAYMENT_WAL_PREFIX}${requestKey}`;
93438
93686
  FLOAT_KEEP_BYTES_MS = 6e5;
93687
+ FLOAT_KEEP_OPEN_REQUEST_MS = 36e5;
93439
93688
  configCache = /* @__PURE__ */ new Map();
93440
93689
  configReads = /* @__PURE__ */ new Map();
93441
93690
  poolDomains = /* @__PURE__ */ new Map();
@@ -93447,7 +93696,7 @@ var init_floatPay = __esm({
93447
93696
  new URL("__bundled_source__/wallet/src/pay/floatPay.mjs", import.meta.url).href
93448
93697
  )), "utf8")).payerKeys.generator;
93449
93698
  plainText = (value) => value.replace(/[^ -~]+/g, " ").trim().slice(0, 300);
93450
- BROADCAST_DEAD = /* @__PURE__ */ new Set([
93699
+ BROADCAST_REFUSED = /* @__PURE__ */ new Set([
93451
93700
  "unsupported_scheme",
93452
93701
  "pocket_payment_network_unsupported",
93453
93702
  "pocket_payment_asset_not_pool_mint",
@@ -93460,12 +93709,14 @@ var init_floatPay = __esm({
93460
93709
  "pocket_authority_is_facilitator_signer",
93461
93710
  "pocket_bound_to_other_payee",
93462
93711
  "pocket_payment_count_exceeded",
93463
- "pocket_credit_exceeded",
93464
- "settlement_expired",
93465
- "transaction_failed",
93466
- "settlement_reverted"
93712
+ "pocket_credit_exceeded"
93467
93713
  ]);
93468
- BROADCAST_DEAD_STANDARD = /^invalid_exact_svm_(?!.*simulation)[a-z_]+$/;
93714
+ BROADCAST_REFUSED_STANDARD = /^invalid_exact_svm_(?!.*simulation)[a-z_]+$/;
93715
+ BROADCAST_DEAD = /* @__PURE__ */ new Set(["settlement_expired", "transaction_failed", "settlement_reverted"]);
93716
+ TRANSFER_LANDING_WINDOW_MS = 12e4;
93717
+ PROOF_DELIVERY_MS = 1e4;
93718
+ SELF_BROADCAST_LEG1_LEFT_MS = TRANSFER_LANDING_WINDOW_MS + PROOF_DELIVERY_MS + 15e3;
93719
+ if (SELF_BROADCAST_MIN_LEFT_MS < SELF_BROADCAST_LEG1_LEFT_MS) throw new Error("self-broadcast offer minimum below the leg-1 minimum");
93469
93720
  BROADCAST_UNSIGNED = /* @__PURE__ */ new Set([
93470
93721
  "transaction_simulation_failed",
93471
93722
  "invalid_exact_svm_transaction_simulation_failed",
@@ -93479,27 +93730,7 @@ var init_floatPay = __esm({
93479
93730
  SELF_BROADCAST_RESEND_MS = [1e3, 2e3, 4e3, 8e3];
93480
93731
  SELLER_HEADERS_MAX_COUNT = 32;
93481
93732
  SELLER_HEADERS_MAX_BYTES = 8 * 1024;
93482
- SELLER_HEADERS_DROPPED = /* @__PURE__ */ new Set([
93483
- "set-cookie",
93484
- "set-cookie2",
93485
- "payment-response",
93486
- "x-payment-response",
93487
- "connection",
93488
- "keep-alive",
93489
- "proxy-authenticate",
93490
- "proxy-authorization",
93491
- "proxy-connection",
93492
- "te",
93493
- "trailer",
93494
- "transfer-encoding",
93495
- "upgrade",
93496
- "content-length",
93497
- "content-encoding",
93498
- "cf-ray",
93499
- "traceparent",
93500
- "tracestate"
93501
- ]);
93502
- SELLER_HEADERS_LINKING = /(^|-)(request|trace|correlation)-id$|^x-balance-|^x-pod-(?!route$)|^x-amzn?-/;
93733
+ SELLER_HEADERS_KEPT = /* @__PURE__ */ new Set(["content-type", "content-language", "cache-control", "retry-after", "x-pod-route"]);
93503
93734
  }
93504
93735
  });
93505
93736
 
@@ -94544,6 +94775,7 @@ async function payResourceOnce({
94544
94775
  { connection, pool: store.state.pool }
94545
94776
  ))) {
94546
94777
  mark("anchor-wait-done");
94778
+ deps.afterAnchorWait?.();
94547
94779
  continue;
94548
94780
  }
94549
94781
  throw error;
@@ -100762,6 +100994,15 @@ function errorBody(error) {
100762
100994
  message: `nothing was paid: usePod's price plus the Shinjuku fee${total ? ` (${total} atomic USDC)` : ""} is above this server's max payment per request. Lower max_tokens, or restart infer serve with --max-payment of at least ${total ?? "price + fee"}`
100763
100995
  } } };
100764
100996
  }
100997
+ if (code === "p03_float_request_expired_nothing_paid") {
100998
+ const why = floatExpiredWhy({ broadcastRefusal: error?.broadcastRefusal ?? error?.cause?.broadcastRefusal });
100999
+ return { status: 503, body: { error: {
101000
+ type: OPENAI_TYPE.api,
101001
+ param: null,
101002
+ code,
101003
+ message: `nothing was paid: ${why}. Send the same request again: it reads a fresh quote from usePod and pays once`
101004
+ } } };
101005
+ }
100765
101006
  if (code === "p03_float_request_data_mismatch" || code === "p03_float_request_id_conflict") {
100766
101007
  return { status: 400, body: { error: {
100767
101008
  type: OPENAI_TYPE.request,
@@ -100782,6 +101023,7 @@ function errorBody(error) {
100782
101023
  }
100783
101024
  function moneyMayHaveMoved(error, code) {
100784
101025
  if (!code) return true;
101026
+ if (/_nothing_paid$/.test(code)) return false;
100785
101027
  if (/_retry_same_request$/.test(code) || /_refund_pending$/.test(code)) return true;
100786
101028
  for (const one of [error, error?.cause]) {
100787
101029
  if (code.startsWith("p03_float_") && (one?.floatId ?? one?.details?.floatId) !== void 0) return true;
@@ -101026,6 +101268,7 @@ var INFERENCE_SERVE_HOST, INFERENCE_SERVE_PORT, BODY_LIMIT_BYTES, IDEMPOTENCY_KE
101026
101268
  var init_serve = __esm({
101027
101269
  "wallet/src/inference/serve.mjs"() {
101028
101270
  "use strict";
101271
+ init_floatWords();
101029
101272
  INFERENCE_SERVE_HOST = "127.0.0.1";
101030
101273
  INFERENCE_SERVE_PORT = 11402;
101031
101274
  BODY_LIMIT_BYTES = 1024 * 1024;
@@ -128639,13 +128882,19 @@ function floatRefusal(error) {
128639
128882
  case "p03_float_answer_invalid_refund_pending":
128640
128883
  return [
128641
128884
  code,
128642
- `Seller did not take it; refund of ${error?.paidAtomic ?? "the amount paid"} atomic on the way (up to ${Math.ceil((error?.refundEtaSeconds ?? FLOAT_REFUND_ETA_SECONDS) / 60)} min). Nothing more to do.` + (typeof error?.sellerReason === "string" ? ` The seller answered HTTP ${error.httpStatus}: ${JSON.stringify(error.sellerReason)}.` : "") + (error?.ambiguous === true ? " (An earlier call with this request_id got no answer from the seller; if that call reached it, the seller holds the payment and no refund comes.)" : ""),
128885
+ `${floatRefundWhy(error)} Refund of ${error?.paidAtomic ?? "the amount paid"} atomic on the way (up to ${Math.ceil((error?.refundEtaSeconds ?? FLOAT_REFUND_ETA_SECONDS) / 60)} min). Nothing more to do.` + (typeof error?.sellerReason === "string" ? ` The seller answered HTTP ${error.httpStatus}: ${JSON.stringify(error.sellerReason)}.` : "") + (error?.ambiguous === true ? ` (${FLOAT_AMBIGUOUS_NOTE})` : ""),
128643
128886
  "Nothing more to do: the refund comes back to balanceAtomic by itself. Do not call x402_pay again with this request_id. To try this seller again, use a NEW request_id"
128644
128887
  ];
128888
+ case "p03_float_request_expired_nothing_paid":
128889
+ return [
128890
+ code,
128891
+ `${floatExpiredWhy(error)}; nothing was paid`,
128892
+ "Nothing was paid. Call x402_pay again: it reads a fresh quote from the seller and pays once"
128893
+ ];
128645
128894
  case "p03_float_receipt_pruned":
128646
128895
  return [
128647
128896
  code,
128648
- `this request_id was paid and answered more than 10 minutes ago${typeof error?.transaction === "string" ? ` (${error.transaction})` : ""}; the wallet no longer keeps its answer (it never keeps prompts or answers longer), and nothing was paid again`,
128897
+ `this request_id was paid and answered more than 10 minutes ago${typeof error?.transaction === "string" ? ` (${error.transaction})` : ""}; the wallet keeps an answer 10 minutes after the call, then only its hash, and nothing was paid again`,
128649
128898
  "To ask again, call with a NEW request_id (it pays again)"
128650
128899
  ];
128651
128900
  case "p03_float_broadcast_pending_retry_same_request":
@@ -128930,6 +129179,10 @@ async function refreshWallet({ session, store, history: walked, share }) {
128930
129179
  });
128931
129180
  writeBalanceSnapshot(store, snapshot);
128932
129181
  returnArrivedFloatRefundBudgets(store, snapshot);
129182
+ try {
129183
+ pruneFloatRecords(store);
129184
+ } catch {
129185
+ }
128933
129186
  prepareFinalizedP03RecoveryFold(history).catch(() => {
128934
129187
  });
128935
129188
  }
@@ -137588,10 +137841,10 @@ async function offerFundNow(deps, path) {
137588
137841
  const io = deps.io;
137589
137842
  for (let attempt = 0; attempt < 3; attempt += 1) {
137590
137843
  const answer = String(await deps.ask("Fund and shield now? Amount in USDC (Enter to skip): ")).trim();
137591
- if (!answer) break;
137844
+ if (!answer || /^(n|no|skip)$/i.test(answer)) break;
137592
137845
  const atomic3 = usdcToAtomic(answer);
137593
137846
  if (!atomic3 || BigInt(atomic3) % 1000000n !== 0n) {
137594
- io.err("Type a whole number of USDC, like 2 (a relayed deposit takes whole USDC only), or press Enter to skip.\n");
137847
+ io.err("Type a whole number of USDC, like 2 (a relayed deposit takes whole USDC only), or press Enter (or n) to skip.\n");
137595
137848
  continue;
137596
137849
  }
137597
137850
  const argv = path.fund.map((word, index) => path.fund[index - 1] === "--amount" ? atomic3 : word);
@@ -137727,11 +137980,14 @@ async function runSetupCommand(values, deps) {
137727
137980
  return setupBehindTor(setupArgvOf(values), deps);
137728
137981
  }
137729
137982
  const missing = missingPieces(home, old);
137983
+ const introduced = values.has("--yes") && inProxiedRun(deps.env);
137730
137984
  io.out([
137731
- "Shinjuku Shielded: a self-custody wallet that pays x402 URLs privately from a shielded USDC balance.",
137732
- "Setup makes the wallet on this machine (your keys never leave it), downloads and checks the proof tools, and writes config.json.",
137733
- "An agent host then starts it with one command: npx -y shinjuku-shielded mcp",
137734
- "",
137985
+ ...introduced ? [] : [
137986
+ "Shinjuku Shielded: a self-custody wallet that pays x402 URLs privately from a shielded USDC balance.",
137987
+ "Setup makes the wallet on this machine (your keys never leave it), downloads and checks the proof tools, and writes config.json.",
137988
+ "An agent host then starts it with one command: npx -y shinjuku-shielded mcp",
137989
+ ""
137990
+ ],
137735
137991
  old ? `Status: ${missing.includes("pool-retired") ? `set up before for a retired pool: ${retiredPoolText(old.pool).split("; run ")[0]}. This run moves config.json to the new pool and makes its wallet` : missing.length ? `set up before; missing now: ${missing.join(", ")}` : "set up; every piece is checked again"} (home ${home}).` : `Home: ${home}`,
137736
137992
  ""
137737
137993
  ].join("\n"));
@@ -139484,6 +139740,7 @@ async function refreshSnapshot(args, values, deps) {
139484
139740
  const walStates = captureWalStates(store);
139485
139741
  const { result, history } = await deps.runRecoverCommand(args.filter((token) => token !== "--refresh"));
139486
139742
  assertAuthenticatedFinalizedP03History(history);
139743
+ let saved;
139487
139744
  const save2 = () => {
139488
139745
  const snapshot = snapshotFromRecovery({
139489
139746
  state: store.state,
@@ -139495,16 +139752,32 @@ async function refreshSnapshot(args, values, deps) {
139495
139752
  now: deps.now()
139496
139753
  });
139497
139754
  writeBalanceSnapshot(store, snapshot);
139498
- returnArrivedFloatRefundBudgets(store, snapshot);
139755
+ saved = snapshot;
139499
139756
  };
139500
- return { store, result, save: save2 };
139757
+ const prune = async () => {
139758
+ let release;
139759
+ try {
139760
+ release = await (deps.acquireLease ?? acquireWalletProcessLease)(walletLockPath(deps.walletPath(values.get("--pool"))));
139761
+ } catch {
139762
+ return;
139763
+ }
139764
+ try {
139765
+ const fresh = openPoolWallet(values, deps);
139766
+ if (saved) returnArrivedFloatRefundBudgets(fresh, saved);
139767
+ pruneFloatRecords(fresh);
139768
+ } catch {
139769
+ } finally {
139770
+ await release();
139771
+ }
139772
+ };
139773
+ return { store, result, save: save2, prune };
139501
139774
  }
139502
139775
  function warnUnsavedSync(result, io) {
139503
139776
  if (result?.memoSync?.cache !== "unwritable") return;
139504
139777
  io.err("warning: the recovery cache (recovery-cache.json beside wallet.json) was not saved; the next recover or balance --refresh reads every memo again\n");
139505
139778
  }
139506
139779
  async function runRecoverAndSave(args, values, deps, io) {
139507
- const { result, save: save2 } = await refreshSnapshot(args, values, deps);
139780
+ const { result, save: save2, prune } = await refreshSnapshot(args, values, deps);
139508
139781
  io.out(`${JSON.stringify(recoverSummary(result), null, 2)}
139509
139782
  `);
139510
139783
  warnUnsavedSync(result, io);
@@ -139519,6 +139792,7 @@ async function runRecoverAndSave(args, values, deps, io) {
139519
139792
  io.err(`warning: the balance walk was not saved (${describeCliError(error, { fallback: "balance_snapshot_unwritable" })}); balance will ask for --refresh
139520
139793
  `);
139521
139794
  }
139795
+ await prune();
139522
139796
  }
139523
139797
  var RELAYED_DEPOSIT_UNIT = Object.freeze({
139524
139798
  DFCCPHdw7pH9vKk9FEN9z6cy9M1UKjF168j7HfLwxYk3: "1000000",
@@ -139703,6 +139977,7 @@ async function runBalance(args, values, deps, io) {
139703
139977
  const refreshed = await refreshSnapshot(args, values, deps);
139704
139978
  warnUnsavedSync(refreshed.result, io);
139705
139979
  refreshed.save();
139980
+ await refreshed.prune();
139706
139981
  store = refreshed.store;
139707
139982
  earlierDeposits = await (deps.adoptOneTime ?? adoptOneTimeForBalance)({ store, values, deps, io });
139708
139983
  } else {
@@ -140197,7 +140472,10 @@ function privacyCashFailureHint(reason) {
140197
140472
  function floatFailureHint(reason) {
140198
140473
  const config = "GET <facilitator>/api/x402/float/config";
140199
140474
  if (/p03_float_refund_pending/.test(reason) && !/answer_invalid/.test(reason)) {
140200
- return "Seller did not take it; refund of the amount paid (price + fee) on the way (up to about 7 min). Nothing more to do. The refund lands in your shielded balance by itself. Only if an earlier run of this request ended with no answer from the seller, that run may have paid the seller; then no refund comes and the seller holds the payment";
140475
+ return "the payment did not reach the seller (the lines above say why); refund of the amount paid (price + fee) on the way (up to about 7 min). Nothing more to do: the refund lands in your shielded balance by itself";
140476
+ }
140477
+ if (/p03_float_request_expired_nothing_paid/.test(reason)) {
140478
+ return "nothing was paid: rerun the same command; it reads a fresh quote from the seller and pays once";
140201
140479
  }
140202
140480
  if (/p03_float_answer_invalid_refund_pending/.test(reason)) {
140203
140481
  return "Shinjuku was paid, but its answer held no valid payment for this seller, so nothing went to the seller. Refund of the amount paid (price + fee) on the way (up to about 7 min). Nothing more to do";
@@ -140243,7 +140521,7 @@ function floatFailureHint(reason) {
140243
140521
  return "the transfer to the seller landed (transaction above), but the seller did not answer (or answered with a server error). Rerun the exact same command: it sends the same proof of payment again and never pays twice";
140244
140522
  }
140245
140523
  if (/p03_float_receipt_pruned/.test(reason)) {
140246
- return "this request id was paid and answered more than 10 minutes ago; the wallet no longer keeps its answer (it never keeps prompts or answers longer), and nothing was paid again. To ask again, run the command with a new request id (it pays again)";
140524
+ return "this request id was paid and answered more than 10 minutes ago; the wallet keeps an answer 10 minutes after the call, then only its hash, and nothing was paid again. To ask again, run the command with a new request id (it pays again)";
140247
140525
  }
140248
140526
  if (/p03_float_seller_kept_payment/.test(reason)) {
140249
140527
  return "the transfer to the seller landed (its transaction is above when the wallet knows it), but the seller did not serve the request. The seller holds the payment, so no refund comes from Shinjuku. Rerun the exact same command once to resend the same proof; if it is refused again, do not pay this seller";
@@ -140520,9 +140798,15 @@ next: fund that address, then rerun the same command; it continues where it stop
140520
140798
  ` : "";
140521
140799
  const landedTx = error?.transaction ?? error?.cause?.transaction;
140522
140800
  const landedLine = /^p03_float_seller_(kept_payment|unanswered_paid)/.test(reason) && typeof landedTx === "string" ? `transfer to the seller landed: ${landedTx}
140801
+ ` : "";
140802
+ const floatError = { broadcastRefusal: error?.broadcastRefusal ?? error?.cause?.broadcastRefusal };
140803
+ const whyLine = /^p03_float_refund_pending/.test(reason) ? `why: ${floatRefundWhy(floatError)}
140804
+ ` : /^p03_float_request_expired_nothing_paid/.test(reason) ? `why: ${floatExpiredWhy(floatError)}
140805
+ ` : "";
140806
+ const ambiguousLine = /^p03_float_refund_pending/.test(reason) && (error?.ambiguous ?? error?.cause?.ambiguous) === true ? `note: ${FLOAT_AMBIGUOUS_NOTE}
140523
140807
  ` : "";
140524
140808
  io.err(`${CLI2} ${command.name} failed: ${reason}
140525
- ${sellerLine}${landedLine}${blockingLine}${hint ? `hint: ${hint}
140809
+ ${sellerLine}${landedLine}${whyLine}${ambiguousLine}${blockingLine}${hint ? `hint: ${hint}
140526
140810
  ` : ""}Help: ${CLI2} help ${command.name}
140527
140811
  `);
140528
140812
  return 1;