shinjuku-shielded 0.3.70 → 0.3.72

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": "ae568c800e9c2e6ccaf4cad6958cf133aa07469a93428827e679d3a1be89505f",
5
- "bytes": 12197454,
6
- "sourceCommit": "dc07c3b2f68a0358fc8137b8ba3773c533856117",
4
+ "sha256": "07990722e8c34815b7af576fe293f456c602895b74cbe6f75d5ea3d8b5a1d578",
5
+ "bytes": 12201104,
6
+ "sourceCommit": "1fbac7a5425ed727041cc29b69fd7b31e8fba117",
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",
@@ -1282,5 +1282,5 @@
1282
1282
  "version": "1.8.0"
1283
1283
  }
1284
1284
  ],
1285
- "publishedAt": "2026-10-22T15:46:57.559Z"
1285
+ "publishedAt": "2026-10-22T17:29:13.245Z"
1286
1286
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "shinjuku-shielded",
3
- "version": "0.3.70",
3
+ "version": "0.3.72",
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": "ae568c80",
7
- "shinjukuSha256": "ae568c800e9c2e6ccaf4cad6958cf133aa07469a93428827e679d3a1be89505f",
6
+ "shinjukuRelease": "07990722",
7
+ "shinjukuSha256": "07990722e8c34815b7af576fe293f456c602895b74cbe6f75d5ea3d8b5a1d578",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
@@ -51938,13 +51938,7 @@ function createCompactHistoryCacheStore({ path, hmacKey, now }) {
51938
51938
  accounts: [...state.initialization.accounts],
51939
51939
  data: Buffer.from(state.initialization.data).toString("hex")
51940
51940
  },
51941
- ...state.attestation ? {
51942
- attestation: {
51943
- key: state.attestation.key,
51944
- newestSignature: state.attestation.newestSignature,
51945
- coverage: encodeTagged(state.attestation.coverage)
51946
- }
51947
- } : {},
51941
+ ...state.attestation ? { attestation: serializeAttestation(state.attestation) } : {},
51948
51942
  // 2026-10-16: the append root after each served record (hex, count 1..n) and the empty
51949
51943
  // tree's root, a fold hint for a new process (compact.mjs hintCompactFold). Optional: an
51950
51944
  // older build reads the file and drops it; a file without it folds as before.
@@ -51986,7 +51980,7 @@ function createCompactHistoryCacheStore({ path, hmacKey, now }) {
51986
51980
  }
51987
51981
  });
51988
51982
  }
51989
- var P03_HISTORY_CACHE_SCHEMA, positionOrNull, encodeTagged, decodeTagged, deserializeAttestation, serializeState, deserializeState, P03_COMPACT_HISTORY_CACHE_SCHEMA;
51983
+ var P03_HISTORY_CACHE_SCHEMA, positionOrNull, encodeTagged, decodeTagged, deserializeAttestation, serializeAttestation, serializeState, deserializeState, P03_COMPACT_HISTORY_CACHE_SCHEMA;
51990
51984
  var init_cacheStore = __esm({
51991
51985
  "wallet/src/history/cacheStore.mjs"() {
51992
51986
  "use strict";
@@ -52019,8 +52013,22 @@ var init_cacheStore = __esm({
52019
52013
  if (coverage.complete !== true || typeof coverage.programDataAddress !== "string" || typeof coverage.programDataSha256 !== "string" || typeof coverage.deployedAtSlot !== "bigint" || typeof coverage.throughFinalizedSlot !== "bigint") {
52020
52014
  throw new Error("p03_history_cache_attestation_invalid");
52021
52015
  }
52022
- return { key: value.key, newestSignature: value.newestSignature, coverage };
52016
+ if (value.newestSignatureSlot !== void 0 && (!Number.isSafeInteger(value.newestSignatureSlot) || value.newestSignatureSlot < 0 || BigInt(value.newestSignatureSlot) > coverage.throughFinalizedSlot)) {
52017
+ throw new Error("p03_history_cache_attestation_invalid");
52018
+ }
52019
+ return {
52020
+ key: value.key,
52021
+ newestSignature: value.newestSignature,
52022
+ ...value.newestSignatureSlot === void 0 ? {} : { newestSignatureSlot: value.newestSignatureSlot },
52023
+ coverage
52024
+ };
52023
52025
  };
52026
+ serializeAttestation = (attestation) => ({
52027
+ key: attestation.key,
52028
+ newestSignature: attestation.newestSignature,
52029
+ ...Number.isSafeInteger(attestation.newestSignatureSlot) ? { newestSignatureSlot: attestation.newestSignatureSlot } : {},
52030
+ coverage: encodeTagged(attestation.coverage)
52031
+ });
52024
52032
  serializeState = (state) => ({
52025
52033
  schema: P03_HISTORY_CACHE_SCHEMA,
52026
52034
  programId: state.programId,
@@ -52028,13 +52036,7 @@ var init_cacheStore = __esm({
52028
52036
  cursor: { ...state.cursor },
52029
52037
  snapshot: { ...state.snapshot },
52030
52038
  transactions: state.transactions.map(serializeTransactionEntry),
52031
- ...state.attestation ? {
52032
- attestation: {
52033
- key: state.attestation.key,
52034
- newestSignature: state.attestation.newestSignature,
52035
- coverage: encodeTagged(state.attestation.coverage)
52036
- }
52037
- } : {}
52039
+ ...state.attestation ? { attestation: serializeAttestation(state.attestation) } : {}
52038
52040
  });
52039
52041
  deserializeState = (value) => {
52040
52042
  if (!value || value.schema !== P03_HISTORY_CACHE_SCHEMA || typeof value.programId !== "string" || typeof value.pool !== "string" || !value.cursor || typeof value.cursor.lastPoolSignature !== "string" || !Number.isSafeInteger(value.cursor.lastSlot) || !value.snapshot || !Number.isSafeInteger(value.snapshot.slot) || typeof value.snapshot.terminal !== "boolean" || typeof value.snapshot.currentIndex !== "string" || typeof value.snapshot.currentRoot !== "string" || !Array.isArray(value.transactions)) {
@@ -54061,7 +54063,8 @@ function slicedSnapshot(result, program, pool2, tree, programData) {
54061
54063
  owner: value.owner,
54062
54064
  executable: value.executable,
54063
54065
  data,
54064
- newestSignature: newest.signature
54066
+ newestSignature: newest.signature,
54067
+ newestSignatureSlot: newest.slot
54065
54068
  })
54066
54069
  }));
54067
54070
  }
@@ -54326,12 +54329,21 @@ async function programDataCoverageFor(args) {
54326
54329
  let priorRefused = false;
54327
54330
  let cause;
54328
54331
  const key = coverageKey({ program, initialization, deploymentIdentity });
54332
+ if (key !== void 0 && prior?.key === key && typeof prior.newestSignature === "string" && Number.isSafeInteger(prior.newestSignatureSlot) && typeof prior.coverage?.throughFinalizedSlot === "bigint" && BigInt(prior.newestSignatureSlot) <= BigInt(snapshotSlot) && prior.coverage.throughFinalizedSlot > BigInt(snapshotSlot)) {
54333
+ markPhase("attest-reuse-older-snapshot");
54334
+ return { coverage: Object.freeze({ ...prior.coverage, throughFinalizedSlot: BigInt(snapshotSlot) }), attestation: prior, reused: true };
54335
+ }
54329
54336
  if (key !== void 0 && prior?.key === key && typeof prior.newestSignature === "string" && prior.coverage?.throughFinalizedSlot <= BigInt(snapshotSlot)) {
54330
54337
  const address5 = new import_web396.PublicKey(prior.coverage.programDataAddress);
54331
54338
  const deployedAtSlot = BigInt(prior.coverage.deployedAtSlot);
54332
- const reuse = (signature2) => {
54339
+ const reuse = (signature2, signatureSlot) => {
54333
54340
  const coverage = Object.freeze({ ...prior.coverage, throughFinalizedSlot: BigInt(snapshotSlot) });
54334
- return { coverage, attestation: { key, newestSignature: signature2, coverage }, reused: true };
54341
+ return { coverage, attestation: {
54342
+ key,
54343
+ newestSignature: signature2,
54344
+ ...Number.isSafeInteger(signatureSlot) && signatureSlot <= snapshotSlot ? { newestSignatureSlot: signatureSlot } : {},
54345
+ coverage
54346
+ }, reused: true };
54335
54347
  };
54336
54348
  const pooled = reuseAnswer !== void 0 && reuseAnswer.slot === snapshotSlot && reuseAnswer.address === address5.toBase58() ? reuseAnswer : void 0;
54337
54349
  if (pooled !== void 0) {
@@ -54339,7 +54351,7 @@ async function programDataCoverageFor(args) {
54339
54351
  assertProgramDataHeader(pooled.slot, pooled, { snapshotSlot, deployedAtSlot });
54340
54352
  if (pooled.newestSignature === prior.newestSignature) {
54341
54353
  markPhase("attest-reuse-in-pool-read");
54342
- return reuse(pooled.newestSignature);
54354
+ return reuse(pooled.newestSignature, pooled.newestSignatureSlot);
54343
54355
  }
54344
54356
  cause = "programdata_newest_signature_changed";
54345
54357
  } catch (error) {
@@ -54357,7 +54369,7 @@ async function programDataCoverageFor(args) {
54357
54369
  }),
54358
54370
  newestSignature(reuseConnection, address5, snapshotSlot)
54359
54371
  ]);
54360
- if (newest.signature === prior.newestSignature) return reuse(newest.signature);
54372
+ if (newest.signature === prior.newestSignature) return reuse(newest.signature, newest.slot);
54361
54373
  cause = "programdata_newest_signature_changed";
54362
54374
  break;
54363
54375
  } catch (error) {
@@ -54403,7 +54415,7 @@ async function programDataCoverageFor(args) {
54403
54415
  const newest = await newestSignature(connection, new import_web396.PublicKey(coverage.programDataAddress), snapshotSlot);
54404
54416
  return {
54405
54417
  coverage,
54406
- attestation: key !== void 0 && newest.slot <= snapshotSlot ? { key, newestSignature: newest.signature, coverage } : void 0,
54418
+ attestation: key !== void 0 && newest.slot <= snapshotSlot ? { key, newestSignature: newest.signature, newestSignatureSlot: newest.slot, coverage } : void 0,
54407
54419
  reused: false
54408
54420
  };
54409
54421
  })();
@@ -57353,18 +57365,18 @@ function validateRecord(raw, ordinal, { programId, pool: pool2, poolDomain, snap
57353
57365
  })
57354
57366
  });
57355
57367
  }
57356
- function requestPage(history, pool2, from) {
57357
- return from === 0 ? requestPageZero(history, pool2) : requestPageNow(history, pool2, from);
57368
+ function requestPage(history, pool2, from, signal) {
57369
+ return from === 0 ? requestPageZero(history, pool2, signal) : requestPageNow(history, pool2, from);
57358
57370
  }
57359
- function requestPageZero(history, pool2) {
57371
+ function requestPageZero(history, pool2, signal) {
57360
57372
  const source = typeof history?.rpcEndpoint === "string" ? history.rpcEndpoint : history;
57361
57373
  let byPool = pageZeroInFlight.get(source);
57362
57374
  const joined = byPool?.get(pool2);
57363
57375
  if (joined !== void 0) {
57364
57376
  markPhase("compact-page0-joined");
57365
- return joined.then((answer) => answer.error === void 0 ? answer : requestPageNow(history, pool2, 0));
57377
+ return joined.then((answer) => answer.error === void 0 ? answer : signal?.aborted ? answer : requestPageNow(history, pool2, 0, signal));
57366
57378
  }
57367
- const pending = requestPageNow(history, pool2, 0);
57379
+ const pending = requestPageNow(history, pool2, 0, signal);
57368
57380
  if (byPool === void 0) pageZeroInFlight.set(source, byPool = /* @__PURE__ */ new Map());
57369
57381
  byPool.set(pool2, pending);
57370
57382
  pending.then(() => {
@@ -57373,16 +57385,14 @@ function requestPageZero(history, pool2) {
57373
57385
  });
57374
57386
  return pending;
57375
57387
  }
57376
- function requestPageNow(history, pool2, from) {
57388
+ function requestPageNow(history, pool2, from, signal) {
57389
+ const params = [pool2, { commitment: "finalized", fromOrdinal: from, toOrdinal: from + P03_COMPACT_PAGE }];
57390
+ const read = signal !== void 0 && typeof history.abortableRpcRequest === "function" ? () => history.abortableRpcRequest("getP03Transitions", params, signal, void 0, { rejectHttpError: true }) : () => history._rpcRequest("getP03Transitions", params);
57377
57391
  const attempt = async (index) => {
57378
57392
  try {
57379
- return { response: await history._rpcRequest("getP03Transitions", [pool2, {
57380
- commitment: "finalized",
57381
- fromOrdinal: from,
57382
- toOrdinal: from + P03_COMPACT_PAGE
57383
- }]) };
57393
+ return { response: await read() };
57384
57394
  } catch (error) {
57385
- if (index + 1 >= LIST_ATTEMPTS || proxyRefusedConnection(error)) return { error };
57395
+ if (index + 1 >= LIST_ATTEMPTS || proxyRefusedConnection(error) || signal?.aborted) return { error };
57386
57396
  markPhase("compact-list-retry");
57387
57397
  await new Promise((resolve38) => setTimeout(resolve38, Math.min(8e3, 1e3 * 2 ** index)));
57388
57398
  return attempt(index + 1);
@@ -57429,7 +57439,7 @@ function withBoundedOwnReads(connection) {
57429
57439
  if (typeof value !== "function") return value;
57430
57440
  if (BOUNDED_OWN_METHODS.has(property)) return (...args) => boundedOwnRead(() => value.apply(target, args));
57431
57441
  if (property === "_rpcRequest") {
57432
- return (...args) => args[0] === P03_POOL_SLICES_METHOD ? boundedOwnRead(() => value.apply(target, args)) : value.apply(target, args);
57442
+ return (...args) => args[0] === P03_POOL_SLICES_METHOD ? boundedOwnRead((stalled) => hedgedOwnPoolSlicesRead(target, args[1], { stalled })) : value.apply(target, args);
57433
57443
  }
57434
57444
  return value.bind(target);
57435
57445
  }
@@ -57490,11 +57500,11 @@ function startCompactPoolSnapshot({ connection, programId, pool: pool2 }) {
57490
57500
  });
57491
57501
  return { sliced, full };
57492
57502
  }
57493
- function requestCompactFirstPage({ history, pool: pool2 }) {
57503
+ function requestCompactFirstPage({ history, pool: pool2, signal }) {
57494
57504
  try {
57495
57505
  const source = typeof history === "string" ? connect2(history, "finalized", { timeoutMs: HISTORY_RPC_REQUEST_TIMEOUT_MS }) : history;
57496
57506
  if (!source || typeof source._rpcRequest !== "function") return Promise.resolve({ error: refuse3("p03_compact_history_connection_invalid") });
57497
- return requestPage(source, new import_web397.PublicKey(pool2).toBase58(), 0);
57507
+ return requestPage(source, new import_web397.PublicKey(pool2).toBase58(), 0, signal);
57498
57508
  } catch (error) {
57499
57509
  return Promise.resolve({ error });
57500
57510
  }
@@ -57556,15 +57566,40 @@ async function ownTransaction(own, signature2) {
57556
57566
  }
57557
57567
  async function hedgedOwnTransactionRead(own, signature2, { stalled, hedge = inTorRun, afterMs = SPOT_HEDGE_AFTER_MS } = {}) {
57558
57568
  const params = [signature2, { commitment: "finalized", maxSupportedTransactionVersion: 1, encoding: "base64" }];
57559
- if (typeof own.abortableRpcRequest !== "function") return own._rpcRequest("getTransaction", params);
57560
- const id = `spot-${spotReadId += 1}`;
57569
+ return hedgedOwnRead(own, "getTransaction", params, {
57570
+ stalled,
57571
+ hedge,
57572
+ afterMs,
57573
+ id: `spot-${spotReadId += 1}`,
57574
+ lane: SPOT_HEDGE_LANE,
57575
+ mark: "spot-hedge",
57576
+ passes: (response) => {
57577
+ checkedOwnTransaction(response, signature2);
57578
+ }
57579
+ });
57580
+ }
57581
+ function hedgedOwnPoolSlicesRead(own, params, { stalled, hedge = inTorRun, afterMs = POOL_HEDGE_AFTER_MS } = {}) {
57582
+ return hedgedOwnRead(own, P03_POOL_SLICES_METHOD, params, {
57583
+ stalled,
57584
+ hedge,
57585
+ afterMs,
57586
+ id: `pool-${poolReadId += 1}`,
57587
+ lane: POOL_HEDGE_LANE,
57588
+ mark: "pool-hedge",
57589
+ passes: (response) => {
57590
+ if (response === null || typeof response !== "object" || !("result" in response || "error" in response)) throw new Error("no answer");
57591
+ }
57592
+ });
57593
+ }
57594
+ async function hedgedOwnRead(own, method, params, { stalled, hedge, afterMs, id, lane: hedgeLane, mark, passes: check }) {
57595
+ if (typeof own.abortableRpcRequest !== "function") return own._rpcRequest(method, params);
57561
57596
  const copies = [];
57562
57597
  const send3 = (lane) => {
57563
57598
  const controller = new AbortController();
57564
57599
  const signal = stalled === void 0 ? controller.signal : AbortSignal.any([stalled, controller.signal]);
57565
57600
  const copy = { controller, lane, outcome: void 0 };
57566
57601
  copy.read = own.abortableRpcRequest(
57567
- "getTransaction",
57602
+ method,
57568
57603
  params,
57569
57604
  signal,
57570
57605
  void 0,
@@ -57591,14 +57626,14 @@ async function hedgedOwnTransactionRead(own, signature2, { stalled, hedge = inTo
57591
57626
  const follow = (copy, which) => copy.read.then((response) => {
57592
57627
  let passes = false;
57593
57628
  try {
57594
- checkedOwnTransaction(response, signature2);
57629
+ check(response);
57595
57630
  passes = true;
57596
57631
  } catch {
57597
57632
  passes = false;
57598
57633
  }
57599
57634
  copy.outcome = { response, passes };
57600
57635
  if (passes && !done) {
57601
- if (copies.length > 1) markPhase(`spot-hedge-won-${which}`);
57636
+ if (copies.length > 1) markPhase(`${mark}-won-${which}`);
57602
57637
  finish(() => resolve38(response));
57603
57638
  return;
57604
57639
  }
@@ -57615,8 +57650,8 @@ async function hedgedOwnTransactionRead(own, signature2, { stalled, hedge = inTo
57615
57650
  clearTimeout(timer);
57616
57651
  timer = void 0;
57617
57652
  if (done || copies.length > 1) return;
57618
- markPhase("spot-hedge-sent");
57619
- follow(send3(SPOT_HEDGE_LANE), "hedge");
57653
+ markPhase(`${mark}-sent`);
57654
+ follow(send3(hedgeLane), "hedge");
57620
57655
  };
57621
57656
  follow(send3(void 0), "first");
57622
57657
  timer = hedging ? setTimeout(sendHedge, afterMs) : void 0;
@@ -58269,7 +58304,7 @@ async function tryCompactP03HistoryReport(options) {
58269
58304
  return { ok: false, reason, ...detail ? { detail } : {}, error };
58270
58305
  }
58271
58306
  }
58272
- 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, PRE_FOLD_SLICE_MS, preFolds, hex64, droppedPools, verifyQuietMs, VERIFY_SLICE_MS, VERIFY_POLL_MS, verifying, unrefTurn, isSignature, isIndex, IMPORT_KEYS, IMPORT_MAX_VALUES, LIST_ATTEMPTS, pageZeroInFlight, OWN_READ_TIMEOUT_MS, BOUNDED_OWN_METHODS, SPOT_HEDGE_AFTER_MS, SPOT_HEDGE_LANE, spotReadId, compactReportsRunning, compactHistoryReadsRunning;
58307
+ 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, PRE_FOLD_SLICE_MS, preFolds, hex64, droppedPools, verifyQuietMs, VERIFY_SLICE_MS, VERIFY_POLL_MS, verifying, unrefTurn, isSignature, isIndex, IMPORT_KEYS, IMPORT_MAX_VALUES, LIST_ATTEMPTS, pageZeroInFlight, OWN_READ_TIMEOUT_MS, BOUNDED_OWN_METHODS, SPOT_HEDGE_AFTER_MS, SPOT_HEDGE_LANE, spotReadId, POOL_HEDGE_AFTER_MS, POOL_HEDGE_LANE, poolReadId, compactReportsRunning, compactHistoryReadsRunning;
58273
58308
  var init_compact = __esm({
58274
58309
  "wallet/src/history/compact.mjs"() {
58275
58310
  "use strict";
@@ -58405,6 +58440,9 @@ var init_compact = __esm({
58405
58440
  SPOT_HEDGE_AFTER_MS = 4e3;
58406
58441
  SPOT_HEDGE_LANE = "spot-hedge";
58407
58442
  spotReadId = 0;
58443
+ POOL_HEDGE_AFTER_MS = 5e3;
58444
+ POOL_HEDGE_LANE = "pool-hedge";
58445
+ poolReadId = 0;
58408
58446
  compactReportsRunning = 0;
58409
58447
  compactHistoryReadsRunning = () => compactReportsRunning;
58410
58448
  }
@@ -59203,13 +59241,19 @@ async function walkWalletP03HistoryNow({ store, connection: given, programId, po
59203
59241
  } else if (earlier !== void 0) {
59204
59242
  markPhase("refresh-start");
59205
59243
  let slicedPreRead;
59244
+ let page0Stop;
59245
+ let page0Answered = false;
59206
59246
  if (compactNext) {
59207
59247
  const started = startCompactPoolSnapshot({ connection, programId, pool: pool2 });
59208
59248
  slicedPreRead = started.sliced;
59209
59249
  poolPreRead = started.full;
59210
59250
  markPhase("compact-pool-prestarted");
59211
- if (!inTorRun() && Date.now() - remembered.at > PAGE0_PREREAD_AFTER_MS) {
59212
- firstPreRead = requestCompactFirstPage({ history: connection.historyRpcSource, pool: pool2 });
59251
+ if (inTorRun() || Date.now() - remembered.at > PAGE0_PREREAD_AFTER_MS) {
59252
+ page0Stop = inTorRun() ? new AbortController() : void 0;
59253
+ firstPreRead = requestCompactFirstPage({ history: connection.historyRpcSource, pool: pool2, signal: page0Stop?.signal });
59254
+ firstPreRead.then(() => {
59255
+ page0Answered = true;
59256
+ });
59213
59257
  markPhase("compact-page0-prestarted");
59214
59258
  }
59215
59259
  }
@@ -59235,6 +59279,10 @@ async function walkWalletP03HistoryNow({ store, connection: given, programId, po
59235
59279
  try {
59236
59280
  const refreshed = await refreshing;
59237
59281
  markPhase("walk-refreshed");
59282
+ if (page0Stop !== void 0) {
59283
+ markPhase(page0Answered ? "compact-page0-answered-before-hit" : "compact-page0-stopped-on-hit");
59284
+ page0Stop.abort();
59285
+ }
59238
59286
  rememberRunReport(runKey, refreshed);
59239
59287
  writeStderr("history: the pool made no transition since this run's last walk; that history was moved to the current pool account " + (fromSliced ? "(your own RPC read the pool account and the program's deployment account in one request)\n" : "(your own RPC read the pool account and the program's deployment account; the history source answered one signature read)\n"));
59240
59288
  return refreshed;
@@ -73896,6 +73944,7 @@ async function runRecoveredP03NoteExit({
73896
73944
  pool: pool2,
73897
73945
  history
73898
73946
  });
73947
+ markPhase("exit-anchor-refreshed");
73899
73948
  timestamp = await readChainTime();
73900
73949
  epoch = BigInt(Math.floor(timestamp / 300));
73901
73950
  }
@@ -74037,6 +74086,7 @@ async function runRecoveredP03NoteExit({
74037
74086
  epoch = BigInt(Math.floor(timestamp / 300));
74038
74087
  }
74039
74088
  await ensureCurrentAnchor();
74089
+ markPhase("exit-anchor-current");
74040
74090
  const buildRecoveryPath = deps.buildRecoveryPath ?? buildFinalizedP03RecoveryPath;
74041
74091
  const prepareFold = deps.buildRecoveryPath === void 0 ? prepareFinalizedP03RecoveryFold : async () => {
74042
74092
  };
@@ -74119,8 +74169,10 @@ async function runRecoveredP03NoteExit({
74119
74169
  store.writeWal(walName2, wal);
74120
74170
  }
74121
74171
  let proved = wal.proved;
74172
+ markPhase("exit-request-built");
74122
74173
  if (!proved) {
74123
74174
  proved = await proveExit(request);
74175
+ markPhase("exit-proved");
74124
74176
  assertProvedExitBinding(proved, request);
74125
74177
  wal = {
74126
74178
  ...wal,
@@ -74148,6 +74200,7 @@ async function runRecoveredP03NoteExit({
74148
74200
  memoBundleHex: proved.output.memoBundleHex,
74149
74201
  recipientTokenAccount: recipient.toBase58()
74150
74202
  }) : await selfBroadcastExit();
74203
+ markPhase(relaySubmit ? "exit-relay-answered" : "exit-sent");
74151
74204
  async function selfBroadcastExit() {
74152
74205
  if (poolState2.replayStore === REPLAY_STORE.indexedTree) return selfBroadcastE1Exit();
74153
74206
  const replayValues = [proved.primary.publicInputBytesHex[3]];
@@ -74244,6 +74297,7 @@ async function runRecoveredP03NoteExit({
74244
74297
  store.writeWal(walName2, wal);
74245
74298
  for (let attempt = 1; ; attempt += 1) {
74246
74299
  history = await walkHistory();
74300
+ markPhase("exit-post-walk");
74247
74301
  poolState2 = await readPool2(connection, pool2, "finalized");
74248
74302
  if (!poolState2 || !poolState2.owner.equals(chainProgramId) || poolState2.version !== 3) {
74249
74303
  throw new Error("finalized note-exit pool postcondition invalid");
@@ -75039,6 +75093,7 @@ var init_shielded_wallet = __esm({
75039
75093
  init_settlement_receipt();
75040
75094
  init_safe_exit();
75041
75095
  init_walletHistory();
75096
+ init_phaseTiming();
75042
75097
  init_chain2();
75043
75098
  init_compressedReplay();
75044
75099
  init_e1Exit();
@@ -108693,7 +108748,7 @@ function balanceLine(a) {
108693
108748
  const pub = usdcText(a.unshieldedAtomic);
108694
108749
  const landing = usdcText(a.landingAtomic);
108695
108750
  if (positive(landing) && !a.refreshError) {
108696
- const line = `${landing} USDC you added landed and is being counted. Ask again in about 30 seconds.`;
108751
+ const line = `${landing} USDC you added landed and is being counted. It needs no step from you.`;
108697
108752
  return balance !== void 0 && a.refreshing !== true ? `You have ${balance} USDC private; ${line}` : line;
108698
108753
  }
108699
108754
  const arriving = addFundsHeldSay(a.addFunds);
@@ -119327,7 +119382,7 @@ ${canonical5}`;
119327
119382
  const balance = {
119328
119383
  name: "wallet_balance",
119329
119384
  title: "Balance",
119330
- description: `Use this when the user asks "what is my balance" or "how much USDC do I have": it answers ONE balance (balanceAtomic, what x402_pay can spend) and the public (unshielded) USDC. Pays nothing and signs nothing. balanceAtomic is one number; breakdown names its parts (breakdown.shieldedAtomic is what wallet_unshield can send; privateSendPendingAtomic is the part of a running private send (wallet_unshield with parts or max_delay_minutes) not sent yet, already taken off shieldedAtomic; refundsInFlightAtomic is a Shinjuku refund on its way back; setAsideAtomic (only when not 0) is value an older version of this wallet set aside to pay sellers; during a pool move, pools lists each pool's part and movingAtomic is value on its way from the old pool to the new one; the move field shows the move, poolSwitches each switch). UNSHIELDED (unshieldedAtomic) is the plain public USDC on the wallet's own Solana key (ownAddress), the USDC wallet_shield makes private; unshieldedSolLamports is that key's SOL, information only: wallet_shield needs none (the facilitator's relayer pays every fee and rent). When the local balance is stale (a new deposit, a received payment), it reads the chain by itself first; when that takes longer than about 20 s it answers the last balance with refreshing: true and finishes in the background (call wallet_balance again in 30 s). A balance with refreshing: true and refreshReason is exact (payment_settling: a payment settles and the number counts it; account_join: the wallet joins its own balance parts and the number counts them; pool_move: value from the old pool arrives and the number counts it; first_check: a new wallet's first history check, the number is its own landed deposits). status reading (balanceAtomic null): the first balance read of a wallet that may hold money is not done; call wallet_balance again in 30 s. If the public read fails, unshieldedAtomic is null with unshieldedReason; the rest still answers. ownKeyTokens (only when there are any): the other tokens on ownAddress (not its USDC), each { mint, amountAtomic, decimals, amount }, at most 10 (ownKeyTokensMore counts the rest); a token is its mint, never a name or symbol; wallet_transfer_token with that mint as token_mint sells one and sends the USDC privately. earlierDeposits (only when there are any): USDC found at a one-time deposit address of an earlier pool, each with a notice line to tell the user; the wallet moves it into the current pool by itself. addFunds (only when there are any): each wallet_add_funds address still open, with its state and the USDC known to wait there (heldAtomic; null with heldNote when the address was not checked yet). landingAtomic (only when not 0): USDC you added whose deposit landed on chain and that balanceAtomic does not count yet; this call finishes it and waits about 20 s for it, past that it is being counted: call wallet_balance again in 30 s. session shows the spending limits (null or "none": no limit), what is left, where the limits come from, and how to change them (session.summary). verbose: true adds \`internal\` (accounts, notes, and other engineering numbers); the default answer leaves them out. To add money, use wallet_add_funds. Amounts are atomic units (USDC: 1000000 = 1 USDC); say and usdc give them in USDC.`,
119385
+ description: `Use this when the user asks "what is my balance" or "how much USDC do I have": it answers ONE balance (balanceAtomic, what x402_pay can spend) and the public (unshielded) USDC. Pays nothing and signs nothing. balanceAtomic is one number; breakdown names its parts (breakdown.shieldedAtomic is what wallet_unshield can send; privateSendPendingAtomic is the part of a running private send (wallet_unshield with parts or max_delay_minutes) not sent yet, already taken off shieldedAtomic; refundsInFlightAtomic is a Shinjuku refund on its way back; setAsideAtomic (only when not 0) is value an older version of this wallet set aside to pay sellers; during a pool move, pools lists each pool's part and movingAtomic is value on its way from the old pool to the new one; the move field shows the move, poolSwitches each switch). UNSHIELDED (unshieldedAtomic) is the plain public USDC on the wallet's own Solana key (ownAddress), the USDC wallet_shield makes private; unshieldedSolLamports is that key's SOL, information only: wallet_shield needs none (the facilitator's relayer pays every fee and rent). When the local balance is stale (a new deposit, a received payment), it reads the chain by itself first; when that takes longer than about 20 s it answers the last balance with refreshing: true and finishes in the background (call wallet_balance again in 30 s). A balance with refreshing: true and refreshReason is exact (payment_settling: a payment settles and the number counts it; account_join: the wallet joins its own balance parts and the number counts them; pool_move: value from the old pool arrives and the number counts it; first_check: a new wallet's first history check, the number is its own landed deposits). status reading (balanceAtomic null): the first balance read of a wallet that may hold money is not done; call wallet_balance again in 30 s. If the public read fails, unshieldedAtomic is null with unshieldedReason; the rest still answers. ownKeyTokens (only when there are any): the other tokens on ownAddress (not its USDC), each { mint, amountAtomic, decimals, amount }, at most 10 (ownKeyTokensMore counts the rest); a token is its mint, never a name or symbol; wallet_transfer_token with that mint as token_mint sells one and sends the USDC privately. earlierDeposits (only when there are any): USDC found at a one-time deposit address of an earlier pool, each with a notice line to tell the user; the wallet moves it into the current pool by itself. addFunds (only when there are any): each wallet_add_funds address still open, with its state and the USDC known to wait there (heldAtomic; null with heldNote when the address was not checked yet). landingAtomic (only when not 0): USDC you added whose deposit landed on chain and that balanceAtomic does not count yet; this call finishes it and waits about 20 s for it, past that it is being counted: call wallet_balance again as next says (at once in the same turn when this call waited its 20 s, else in 30 s). session shows the spending limits (null or "none": no limit), what is left, where the limits come from, and how to change them (session.summary). verbose: true adds \`internal\` (accounts, notes, and other engineering numbers); the default answer leaves them out. To add money, use wallet_add_funds. Amounts are atomic units (USDC: 1000000 = 1 USDC); say and usdc give them in USDC.`,
119331
119386
  inputSchema: { type: "object", properties: {
119332
119387
  verbose: { type: "boolean", description: "Optional. true adds `internal`: the engineering numbers (funded accounts, notes, payments without waiting, a 0 set-aside value). Default false." }
119333
119388
  }, additionalProperties: false },
@@ -119528,7 +119583,8 @@ ${canonical5}`;
119528
119583
  if (typeof amount === "bigint" && amount > 0n) landingAtomic += amount;
119529
119584
  }
119530
119585
  }
119531
- const landedNext = landingAtomic > 0n && !refresh.refreshError ? `${usdcText2(landingAtomic)} USDC you added landed on chain and is being counted (landingAtomic, not in balanceAtomic yet): call wallet_balance again in ${POLL_SECONDS3} s; that call waits up to ${waitSeconds} s for it. Tell the user it needs no step from them` : void 0;
119586
+ const landedWaitedFull = Date.now() - balanceStartedAt >= balanceRefreshWaitMs;
119587
+ const landedNext = landingAtomic > 0n && !refresh.refreshError ? landedWaitedFull ? `${usdcText2(landingAtomic)} USDC you added landed on chain and is being counted (landingAtomic, not in balanceAtomic yet): call wallet_balance again now, in this same turn; that call waits up to ${waitSeconds} s for it. Do not end the turn or ask the user: it needs no step from them` : `${usdcText2(landingAtomic)} USDC you added landed on chain and is being counted (landingAtomic, not in balanceAtomic yet): call wallet_balance again in ${POLL_SECONDS3} s; that call waits up to ${waitSeconds} s for it. Tell the user it needs no step from them` : void 0;
119532
119588
  if (landedNext) next = landedNext;
119533
119589
  const stalled = [...resumeRefusals].map(([requestId, error2]) => `"${requestId}" (${error2})`);
119534
119590
  if (stalled.length && one.breakdown?.privateSendPendingAtomic !== "0") {