shinjuku-shield 0.3.113 → 0.3.115

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/README.md CHANGED
@@ -6,19 +6,19 @@ answers privately, in a terminal chat or for your agent app. Its `mcp`
6
6
  command runs a local MCP server (stdio) for your agent. Your keys never
7
7
  leave your machine.
8
8
 
9
- This is version 0.3.113. The npm packages `shinjuku-shield` and
9
+ This is version 0.3.115. The npm packages `shinjuku-shield` and
10
10
  `shinjuku-shielded` hold the same files. The command is `shinjuku`.
11
11
 
12
12
  ## Set up
13
13
 
14
14
  ```sh
15
- npm install -g shinjuku@0.3.113
15
+ npm install -g shinjuku@0.3.115
16
16
  shinjuku setup
17
17
  ```
18
18
 
19
19
  Type the two lines as they are. `npx install shinjuku` does not work: npx
20
20
  reads `install` as the name of another npm package. To set up without
21
- installing, type `npx shinjuku@0.3.113 setup`.
21
+ installing, type `npx shinjuku@0.3.115 setup`.
22
22
 
23
23
  Setup makes the wallet on this machine, a private passphrase file, and the
24
24
  checked proof tools (about 191 MB), and writes `config.json`. It also writes
@@ -36,13 +36,13 @@ Every wallet command works after `shinjuku`, for example `shinjuku balance`,
36
36
  Claude Code:
37
37
 
38
38
  ```sh
39
- claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.113 mcp
39
+ claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.115 mcp
40
40
  ```
41
41
 
42
42
  Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
43
43
 
44
44
  ```json
45
- { "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.113", "mcp"] } } }
45
+ { "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.115", "mcp"] } } }
46
46
  ```
47
47
 
48
48
  On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
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": "bfaedd12d120b4b5421cdf6c9c06b07b7e338fd6d4e74b7225f2a0d3aa150cf4",
5
- "bytes": 8339853,
6
- "sourceCommit": "0c37c0dea055d3c28bab9939cd5527fc290668f8",
4
+ "sha256": "148b3f5279bf4b0914aa076c617b9fd51956480a57058dfee4492c208fd72e7a",
5
+ "bytes": 8348544,
6
+ "sourceCommit": "8b4f9050d3ae61ecdd0082ee931761cc2b812f62",
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",
@@ -1037,5 +1037,5 @@
1037
1037
  "version": "1.8.0"
1038
1038
  }
1039
1039
  ],
1040
- "publishedAt": "2026-10-27T16:17:32.089Z"
1040
+ "publishedAt": "2026-10-27T18:51:07.036Z"
1041
1041
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "shinjuku-shield",
3
- "version": "0.3.113",
3
+ "version": "0.3.115",
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": "bfaedd12",
7
- "shinjukuSha256": "bfaedd12d120b4b5421cdf6c9c06b07b7e338fd6d4e74b7225f2a0d3aa150cf4",
6
+ "shinjukuRelease": "148b3f52",
7
+ "shinjukuSha256": "148b3f5279bf4b0914aa076c617b9fd51956480a57058dfee4492c208fd72e7a",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-shield#readme",
@@ -67216,7 +67216,7 @@ var init_errorCodes = __esm({
67216
67216
  "float_paid_finishing",
67217
67217
  "refund_pending",
67218
67218
  // Float record field values, not errors (floatPay.mjs): broadcastRefusal "answer_invalid" (leg 1's answer could not be
67219
- // used) and the refund outcomes returnArrivedFloatRefundBudgets writes and takeFloatRefundOutcomes returns.
67219
+ // used) and the refund outcomes returnArrivedFloatRefundBudgets writes and readFloatRefundOutcomes returns.
67220
67220
  "answer_invalid",
67221
67221
  "refund_arrived",
67222
67222
  "refund_not_seen",
@@ -102584,7 +102584,14 @@ function returnArrivedFloatRefundBudgets(store, snapshot) {
102584
102584
  }
102585
102585
  }
102586
102586
  }
102587
- function takeFloatRefundOutcomes(store) {
102587
+ function floatSellerHost(record) {
102588
+ try {
102589
+ return new URL(String(record?.url)).hostname || void 0;
102590
+ } catch {
102591
+ return void 0;
102592
+ }
102593
+ }
102594
+ function readFloatRefundOutcomes(store) {
102588
102595
  const outcomes = [];
102589
102596
  let names;
102590
102597
  try {
@@ -102598,13 +102605,32 @@ function takeFloatRefundOutcomes(store) {
102598
102605
  const record = store.readWal(name);
102599
102606
  if (record?.schema !== FLOAT_PAYMENT_SCHEMA2 || floatRecordState(record) !== "refund_pending") continue;
102600
102607
  if (record.refundOutcome === void 0 || record.refundOutcomeShown !== false) continue;
102601
- store.writeWal(name, { ...record, refundOutcomeShown: true });
102602
- outcomes.push({ floatId: record.floatId, paidAtomic: record.paidAtomic, outcome: record.refundOutcome, atMs: record.refundOutcomeAtMs });
102608
+ outcomes.push({ floatId: record.floatId, paidAtomic: record.paidAtomic, host: floatSellerHost(record), outcome: record.refundOutcome, atMs: record.refundOutcomeAtMs });
102603
102609
  } catch {
102604
102610
  }
102605
102611
  }
102606
102612
  return outcomes;
102607
102613
  }
102614
+ function markFloatRefundOutcomesShown(store, shown) {
102615
+ const wanted = new Map(shown.map(({ floatId, outcome }) => [floatId, outcome]));
102616
+ if (!wanted.size) return;
102617
+ let names;
102618
+ try {
102619
+ names = store.listWal();
102620
+ } catch {
102621
+ return;
102622
+ }
102623
+ for (const name of names) {
102624
+ if (!name.startsWith(FLOAT_PAYMENT_WAL_PREFIX)) continue;
102625
+ try {
102626
+ const record = store.readWal(name);
102627
+ if (record?.schema !== FLOAT_PAYMENT_SCHEMA2 || record.refundOutcomeShown !== false) continue;
102628
+ if (!wanted.has(record.floatId) || wanted.get(record.floatId) !== record.refundOutcome) continue;
102629
+ store.writeWal(name, { ...record, refundOutcomeShown: true });
102630
+ } catch {
102631
+ }
102632
+ }
102633
+ }
102608
102634
  function dropOldMemoryAnswers(now) {
102609
102635
  for (const [key, entry] of memoryAnswers) if (now >= entry.atMs + FLOAT_KEEP_BYTES_MS) memoryAnswers.delete(key);
102610
102636
  }
@@ -105922,8 +105948,10 @@ function fillsOnTheWayAtomic(store) {
105922
105948
  }
105923
105949
  function refundOf(record) {
105924
105950
  const inner = String(record.innerRequestId ?? "");
105951
+ const seller = floatSellerHost(record);
105925
105952
  return {
105926
105953
  ...inner.endsWith(":float") ? { requestId: inner.slice(0, -":float".length) } : { floatId: record.floatId ?? null },
105954
+ ...seller ? { seller } : {},
105927
105955
  refundAtomic: String(record.paidAtomic)
105928
105956
  };
105929
105957
  }
@@ -119360,7 +119388,7 @@ function withEarlyAnswer(tool, {
119360
119388
  if (open4) {
119361
119389
  log(`MCP_PAY_SECOND_REFUSED requestId=${requestId} open=${open4[0]}`);
119362
119390
  return { text: JSON.stringify({
119363
- say: `Not paid: a payment for this ${words2 === PAY_WORDS ? "URL" : "call"} is still open (request_id ${open4[0]}). Call ${tool.name} with that request_id for the result.`,
119391
+ say: `Nothing was paid for this request: a payment for this ${words2 === PAY_WORDS ? "URL" : "call"} is still open with ${words2.who}. Do not pay again; asking for its result pays nothing more.`,
119364
119392
  ok: false,
119365
119393
  error: "mcp_payment_still_open",
119366
119394
  requestId,
@@ -119423,7 +119451,7 @@ function withEarlyAnswer(tool, {
119423
119451
  log(`MCP_PAY_EARLY_ANSWER requestId=${requestId} waited=${secondsWaited}s`);
119424
119452
  entry.toldWaiting = true;
119425
119453
  const next = `The payment was sent to ${words2.who} (price + fee left the balance), and ${words2.who} ${words2.busyNext}. Do not pay again: call ${tool.name} again with request_id "${requestId}" and ${words2.same} for the result (that call waits up to ${Math.round(earlyAnswerMs / 1e3)} s for it); it never pays twice. A new request_id for the same request is refused while this one is open. The later call's answer says how it ended: ${words2.who}'s answer, or what happened to the payment.`;
119426
- const say3 = sellerWorkingSeconds < JUST_REACHED_SECONDS ? `Sent to ${words2.who}; the request just reached it. Do not pay again: call ${tool.name} with request_id ${requestId} for the result.` : `Sent to ${words2.who}; it has not answered yet. Do not pay again: call ${tool.name} with request_id ${requestId} for the result.`;
119454
+ const say3 = sellerWorkingSeconds < JUST_REACHED_SECONDS ? `Sent to ${words2.who}; the request just reached it. Do not pay again; asking for the result pays nothing more.` : `Sent to ${words2.who}; it has not answered yet. Do not pay again; asking for the result pays nothing more.`;
119427
119455
  return { text: JSON.stringify({ say: say3, ok: true, paid: false, pending: true, stage: "seller_working", requestId, secondsWaited, sellerWorkingSeconds, next }, null, 2) };
119428
119456
  } };
119429
119457
  }
@@ -119622,7 +119650,7 @@ function refusalSay(a, tool, again, npmVersion) {
119622
119650
  return `Nothing changed: this address was made for ${amount ? `${amount} USDC` : "a fixed amount"}, and its amount never changes. Read next for what to do.`;
119623
119651
  }
119624
119652
  if (code2 === "mcp_balance_unknown") return "Nothing was moved yet: the wallet is still reading its private balance. Try again in a minute.";
119625
- if (code2 === "mcp_payment_still_open") return "Not paid: a payment for this request is still open. Ask with its request_id for the result.";
119653
+ if (code2 === "mcp_payment_still_open") return "Nothing was paid for this request: a payment for it is still open. Do not pay again; asking for its result pays nothing more.";
119626
119654
  if (code2 === "mcp_setup_restart_needed") return "The wallet is set up, but it must reconnect once. Follow the steps below, then try again. Nothing was paid.";
119627
119655
  if (code2 === "mcp_restart_needed") return "Nothing was paid. Restart this app, then try again.";
119628
119656
  if (code2 === "p03_merchant_respend_value_held_by_private_send") {
@@ -120326,8 +120354,7 @@ function withKeepIdNote(output2) {
120326
120354
  return output2;
120327
120355
  }
120328
120356
  if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2) || typeof parsed2.next !== "string" || parsed2.next.includes(KEEP_ID_NOTE)) return output2;
120329
- const ids = [parsed2.requestId, parsed2.newRequestId, ...Array.isArray(parsed2.privateSends) ? parsed2.privateSends.map((send3) => send3?.requestId) : []].filter((id) => typeof id === "string" && id.length >= 4);
120330
- if (!ids.some((id) => parsed2.next.includes(id)) && !/request_id "[^"]+"/.test(parsed2.next)) return output2;
120357
+ if (!/"(?:requestId|newRequestId)"\s*:\s*"[^"]{4,}"/.test(block.text) && !/request_id "[^"]+"/.test(parsed2.next)) return output2;
120331
120358
  return withFirstText(output2, block, { ...parsed2, next: `${parsed2.next.replace(/[.\s]+$/, "")}. ${KEEP_ID_NOTE}` });
120332
120359
  }
120333
120360
  function plainFields(parsed2, toolName) {
@@ -125398,8 +125425,9 @@ async function sellerTokenAccountExists(connection, asset, payTo) {
125398
125425
  }
125399
125426
  function refundOutcomeText(outcome) {
125400
125427
  const amount = ATOMIC_TEXT.test(String(outcome?.paidAtomic ?? "")) ? `${usdcText3(outcome.paidAtomic)} USDC` : "a Shinjuku payment";
125401
- if (outcome?.outcome === "refund_arrived") return `The refund of ${amount} arrived.`;
125402
- return `The refund of ${amount} could not be matched in your balance (this balance read cannot tell refunds apart); if it came back, balanceAtomic counts it already.`;
125428
+ const payment = typeof outcome?.host === "string" && /^[a-z0-9.-]{1,253}$/i.test(outcome.host) ? ` for the payment to ${outcome.host}` : "";
125429
+ if (outcome?.outcome === "refund_arrived") return `The refund of ${amount}${payment} arrived.`;
125430
+ return `The refund of ${amount}${payment} could not be matched in your balance (this balance read cannot tell refunds apart); if it came back, balanceAtomic counts it already.`;
125403
125431
  }
125404
125432
  function floatRefusal(error) {
125405
125433
  const code2 = String(error?.message ?? "").split(/[\s:;(]/, 1)[0];
@@ -125836,9 +125864,35 @@ async function checkUnshieldRecipient({ connection, mint, owner }) {
125836
125864
  throw new Error("mcp_unshield_to_invalid: the USDC holder at this address is for another token or another owner, so it cannot take this payment; nothing was paid");
125837
125865
  }
125838
125866
  }
125867
+ async function walkBeforeLease(session, exitProofTools) {
125868
+ try {
125869
+ const store = session.openStore();
125870
+ let marks = walletHistoryHomeMarks(store);
125871
+ if (marks === void 0) {
125872
+ await new Promise((resolve35) => {
125873
+ setTimeout(resolve35, HOME_MARKS_SETTLED_MS2 + 10);
125874
+ });
125875
+ marks = walletHistoryHomeMarks(store);
125876
+ }
125877
+ if (marks === void 0) return void 0;
125878
+ const history = await loadWalletP03History({
125879
+ store,
125880
+ connection: connectSplit(session.connection, session.historyUrl),
125881
+ programId: session.programId,
125882
+ pool: store.state.pool,
125883
+ deploymentIdentity: exitProofTools.deploymentIdentity,
125884
+ share: { notBeforeMs: Date.now(), marks }
125885
+ });
125886
+ return { marks, pool: String(store.state.pool), history };
125887
+ } catch {
125888
+ return void 0;
125889
+ }
125890
+ }
125839
125891
  async function runUnshield({
125840
125892
  session,
125841
- store,
125893
+ lease,
125894
+ before = () => void 0,
125895
+ prepare = (store) => store,
125842
125896
  unshieldId,
125843
125897
  amountAtomic,
125844
125898
  recipientOwner,
@@ -125848,11 +125902,13 @@ async function runUnshield({
125848
125902
  onStage,
125849
125903
  selfPayStep = selfPay,
125850
125904
  onAnswered,
125851
- onCheckPending
125905
+ onCheckPending,
125906
+ onExited = () => {
125907
+ },
125908
+ walked,
125909
+ finalityWaits = 0
125852
125910
  }) {
125853
125911
  const owner = new import_web3132.PublicKey(recipientOwner);
125854
- const mint = new import_web3132.PublicKey(store.state.asset);
125855
- const recipient = getAssociatedTokenAddressSync(mint, owner, true, TOKEN_PROGRAM_ID);
125856
125912
  let timing;
125857
125913
  try {
125858
125914
  timing = typeof session.timing === "function" ? session.timing() : void 0;
@@ -125866,141 +125922,226 @@ async function runUnshield({
125866
125922
  }
125867
125923
  };
125868
125924
  const scoped = (prefix, fn) => phaseScopeActive() || timing === void 0 ? fn() : withPhaseScope(mark, prefix, fn);
125869
- const walk = (deploymentIdentity) => () => scoped("unshield-walk", () => loadWalletP03History({
125870
- store,
125871
- connection: connectSplit(session.connection, session.historyUrl),
125872
- programId: session.programId,
125873
- pool: store.state.pool,
125874
- deploymentIdentity
125875
- }));
125925
+ let current;
125926
+ const use = (store) => {
125927
+ current = store;
125928
+ };
125929
+ let nextWalk = walked;
125930
+ const walkNext = (report) => {
125931
+ nextWalk = report;
125932
+ };
125933
+ const walk = (deploymentIdentity) => () => {
125934
+ if (nextWalk !== void 0) {
125935
+ const report = nextWalk;
125936
+ nextWalk = void 0;
125937
+ mark("unshield-walk-before-lease");
125938
+ return Promise.resolve(report);
125939
+ }
125940
+ return scoped("unshield-walk", () => loadWalletP03History({
125941
+ store: current,
125942
+ connection: connectSplit(session.connection, session.historyUrl),
125943
+ programId: session.programId,
125944
+ pool: current.state.pool,
125945
+ deploymentIdentity
125946
+ }));
125947
+ };
125876
125948
  const name = `self-pay-${unshieldId}`;
125877
- let record = store.readWal(name);
125878
- if (record && record.mode === void 0 && !selfPayMayHaveSigned(store, unshieldId)) {
125879
- const note = chooseDirectExitNote(store, amountAtomic, unshieldId);
125880
- if (note) {
125881
- record = {
125882
- ...record,
125883
- mode: DIRECT_EXIT_MODE,
125884
- noteCommitment: BigInt(note.commitment).toString(),
125885
- memoDigest: note.digest,
125886
- noteValueAtomic: String(note.valueAtomic),
125887
- exitAmountAtomic: String(amountAtomic),
125888
- exitRecipient: recipient.toBase58()
125889
- };
125890
- store.writeWal(name, record);
125949
+ const start = await lease(async (opened) => {
125950
+ mark("unshield-lease-self-pay");
125951
+ const stop3 = await before(opened);
125952
+ if (stop3 !== void 0) return { stop: stop3 };
125953
+ const store = await prepare(opened);
125954
+ use(store);
125955
+ const mint = new import_web3132.PublicKey(store.state.asset);
125956
+ const recipient = getAssociatedTokenAddressSync(mint, owner, true, TOKEN_PROGRAM_ID);
125957
+ let record = store.readWal(name);
125958
+ if (record && record.mode === void 0 && !selfPayMayHaveSigned(store, unshieldId)) {
125959
+ const note = chooseDirectExitNote(store, amountAtomic, unshieldId);
125960
+ if (note) {
125961
+ record = {
125962
+ ...record,
125963
+ mode: DIRECT_EXIT_MODE,
125964
+ noteCommitment: BigInt(note.commitment).toString(),
125965
+ memoDigest: note.digest,
125966
+ noteValueAtomic: String(note.valueAtomic),
125967
+ exitAmountAtomic: String(amountAtomic),
125968
+ exitRecipient: recipient.toBase58()
125969
+ };
125970
+ store.writeWal(name, record);
125971
+ }
125891
125972
  }
125892
- }
125893
- if (record?.mode === DIRECT_EXIT_MODE) {
125894
- return runDirectExit({
125895
- session,
125973
+ if (record?.mode === DIRECT_EXIT_MODE) {
125974
+ return runDirectExit({
125975
+ session,
125976
+ store,
125977
+ name,
125978
+ pool: store.state.pool,
125979
+ unshieldId,
125980
+ amountAtomic,
125981
+ record,
125982
+ owner,
125983
+ mint,
125984
+ recipient,
125985
+ exitProofTools,
125986
+ facilitatorOrigin: facilitatorOrigin2,
125987
+ onStage,
125988
+ walk,
125989
+ use,
125990
+ mark,
125991
+ scoped,
125992
+ onAnswered
125993
+ });
125994
+ }
125995
+ if (record?.mode !== void 0) throw new Error("mcp_unshield_failed: this unshield's record names an exit mode this version does not know; nothing new was signed. Update the wallet");
125996
+ if (!selfPayMayHaveSigned(store, unshieldId)) {
125997
+ await checkUnshieldRecipient({ connection: session.connection, mint, owner });
125998
+ }
125999
+ const payerTools = session.proofTools;
126000
+ onStage("self-pay");
126001
+ mark("unshield-self-pay");
126002
+ const paid = await selfPayStep({
125896
126003
  store,
125897
- unshieldId,
126004
+ connection: session.connection,
126005
+ programId: session.programId,
126006
+ proofTools: payerTools,
126007
+ profile,
125898
126008
  amountAtomic,
125899
- record,
125900
- owner,
125901
- mint,
125902
- recipient,
125903
- exitProofTools,
125904
- facilitatorOrigin: facilitatorOrigin2,
125905
- onStage,
125906
- walk,
125907
- mark,
125908
- scoped,
125909
- onAnswered,
125910
- onCheckPending
126009
+ unshieldId,
126010
+ facilitatorBaseUrl: serviceUrl(facilitatorOrigin2, "/api/x402").href,
126011
+ memoServiceUrl: serviceBase(facilitatorOrigin2),
126012
+ // An owner unshield: the self-payment pays this wallet itself, so it does not use the wallet-file payment budget.
126013
+ ownerUnshield: true,
126014
+ // The self-payment waits for the next anchor itself (bounded, like x402_pay), instead of refusing.
126015
+ deps: { payDeps: { timing: session.timing(), walkHistory: walk(payerTools.deploymentIdentity), waitForAnchor: true } }
126016
+ });
126017
+ const payment = store.readWal(`${RESOURCE_PAYMENT_WAL_PREFIX2}${sha256Hex2(Buffer.from(selfPayRequestId(unshieldId), "utf8"))}`);
126018
+ if (!payment?.memoDigest || !paid.noteCommitment) throw new Error("mcp_unshield_failed: the self-payment record is incomplete; call wallet_unshield again with the same request_id");
126019
+ mark("unshield-paid");
126020
+ return { paid, memoDigest: payment.memoDigest, recipient, pool: store.state.pool };
126021
+ });
126022
+ if (start.stop !== void 0) return start.stop;
126023
+ let { tried, exitOf } = start;
126024
+ if (tried === void 0) {
126025
+ const { paid, memoDigest, recipient } = start;
126026
+ exitOf = (store) => runRecoveredP03NoteExit({
126027
+ store,
126028
+ connection: session.connection,
126029
+ programId: session.programId,
126030
+ serviceUrl: facilitatorOrigin2,
126031
+ digests: [memoDigest],
126032
+ recipientTokenAccount: recipient.toBase58(),
126033
+ proofTools: exitProofTools,
126034
+ noteCommitment: paid.noteCommitment,
126035
+ recipientOwner: owner.toBase58(),
126036
+ allowForeignRecipient: true,
126037
+ relaySubmit: facilitatorExitRelay(facilitatorOrigin2),
126038
+ requestAnchor: markedAnchorRequest(facilitatorAnchor(facilitatorOrigin2)),
126039
+ answerAtRelay: true,
126040
+ deps: { walkHistory: walk(exitProofTools.deploymentIdentity) }
125911
126041
  });
126042
+ onStage("exit");
126043
+ mark("unshield-exit");
126044
+ tried = await exitTries({ session, lease, name, pool: start.pool, use, mark, scoped, exitOf, answer: { selfPayTransaction: paid.transaction ?? null }, onAnswered });
125912
126045
  }
125913
- if (record?.mode !== void 0) throw new Error("mcp_unshield_failed: this unshield's record names an exit mode this version does not know; nothing new was signed. Update the wallet");
125914
- if (!selfPayMayHaveSigned(store, unshieldId)) {
125915
- await checkUnshieldRecipient({ connection: session.connection, mint, owner });
125916
- }
125917
- const payerTools = session.proofTools;
125918
- onStage("self-pay");
125919
- mark("unshield-self-pay");
125920
- const paid = await selfPayStep({
125921
- store,
125922
- connection: session.connection,
125923
- programId: session.programId,
125924
- proofTools: payerTools,
125925
- profile,
125926
- amountAtomic,
125927
- unshieldId,
125928
- facilitatorBaseUrl: serviceUrl(facilitatorOrigin2, "/api/x402").href,
125929
- memoServiceUrl: serviceBase(facilitatorOrigin2),
125930
- // An owner unshield: the self-payment pays this wallet itself, so it does not use the wallet-file payment budget.
125931
- ownerUnshield: true,
125932
- // The self-payment waits for the next anchor itself (bounded, like x402_pay), instead of refusing.
125933
- deps: { payDeps: { timing: session.timing(), walkHistory: walk(payerTools.deploymentIdentity), waitForAnchor: true } }
125934
- });
125935
- const payment = store.readWal(`${RESOURCE_PAYMENT_WAL_PREFIX2}${sha256Hex2(Buffer.from(selfPayRequestId(unshieldId), "utf8"))}`);
125936
- if (!payment?.memoDigest || !paid.noteCommitment) throw new Error("mcp_unshield_failed: the self-payment record is incomplete; call wallet_unshield again with the same request_id");
125937
- mark("unshield-paid");
125938
- onStage("exit");
125939
- mark("unshield-exit");
125940
- const exit = await scoped("unshield-exit", () => exitWhenAnchored(() => runRecoveredP03NoteExit({
125941
- store,
125942
- connection: session.connection,
125943
- programId: session.programId,
125944
- serviceUrl: facilitatorOrigin2,
125945
- digests: [payment.memoDigest],
125946
- recipientTokenAccount: recipient.toBase58(),
125947
- proofTools: exitProofTools,
125948
- noteCommitment: paid.noteCommitment,
125949
- recipientOwner: owner.toBase58(),
125950
- allowForeignRecipient: true,
125951
- relaySubmit: facilitatorExitRelay(facilitatorOrigin2),
125952
- requestAnchor: markedAnchorRequest(facilitatorAnchor(facilitatorOrigin2)),
125953
- answerAtRelay: true,
125954
- deps: { walkHistory: walk(exitProofTools.deploymentIdentity) }
125955
- }), { ring: { connection: session.connection, pool: store.state.pool } }));
125956
- const answer = { selfPayTransaction: paid.transaction ?? null, exitTransaction: exit.signature ?? null };
125957
- if (exit.settled === false && !await finishAnsweredExit({ session, store, name, exit, answer, onAnswered, onCheckPending, mark, scoped })) return answer;
125958
- mark("unshield-exited");
125959
- const exited = store.readWal(`self-pay-${unshieldId}`);
125960
- store.writeWal(`self-pay-${unshieldId}`, { ...exited, state: "exited", exitTransaction: exit.signature, exitedAtMs: exited?.exitedAtMs ?? exited?.exitAnsweredAtMs ?? Date.now() });
125961
- return answer;
126046
+ return exitFinish({
126047
+ lease,
126048
+ name,
126049
+ use,
126050
+ mark,
126051
+ scoped,
126052
+ exitOf,
126053
+ tried,
126054
+ onCheckPending,
126055
+ onExited,
126056
+ finalityWaits,
126057
+ walkNext,
126058
+ ...finalityWaits > 0 ? { preWalk: () => walkBeforeLease(session, exitProofTools) } : {}
126059
+ });
125962
126060
  }
125963
126061
  function sentAtMs(record) {
125964
126062
  return Number.isSafeInteger(record?.exitAnsweredAtMs) ? record.exitAnsweredAtMs : record?.exitedAtMs;
125965
126063
  }
125966
- async function finishAnsweredExit({ session, store, name, exit, answer, changeAtomic, onAnswered, onCheckPending, mark, scoped }) {
125967
- if (typeof onAnswered !== "function") {
125968
- await scoped("unshield-exit", () => exit.finish());
125969
- return true;
125970
- }
125971
- const record = store.readWal(name);
125972
- store.writeWal(name, {
125973
- ...record,
125974
- exitTransaction: exit.signature,
125975
- exitAnsweredAtMs: record?.exitAnsweredAtMs ?? Date.now(),
125976
- ...changeAtomic !== void 0 ? { changeAtomic } : {}
125977
- });
125978
- try {
125979
- await scoped("unshield-exit", () => refreshWallet({ session, store, history: exit.preExitHistory }));
125980
- } catch {
125981
- mark("unshield-exit-snapshot-failed");
125982
- }
125983
- mark("unshield-exit-answered");
125984
- try {
125985
- onAnswered(answer);
125986
- } catch {
125987
- }
125988
- try {
125989
- await scoped("unshield-exit", () => exit.finish());
125990
- return true;
125991
- } catch (error) {
126064
+ async function exitTries({ session, lease, name, pool: pool2, use, mark, scoped, exitOf, answer: shown, changeAtomic, onAnswered }) {
126065
+ const answers = typeof onAnswered === "function";
126066
+ return scoped("unshield-exit", () => exitWhenAnchored(() => lease(async (store) => {
126067
+ mark("unshield-lease-exit");
126068
+ use(store);
126069
+ const exit = await exitOf(store);
126070
+ const answer = { ...shown, exitTransaction: exit.signature ?? null };
126071
+ const early = exit.settled === false && answers;
126072
+ if (early) {
126073
+ const record = store.readWal(name);
126074
+ store.writeWal(name, {
126075
+ ...record,
126076
+ exitTransaction: exit.signature,
126077
+ exitAnsweredAtMs: record?.exitAnsweredAtMs ?? Date.now(),
126078
+ ...changeAtomic !== void 0 ? { changeAtomic } : {}
126079
+ });
126080
+ try {
126081
+ await refreshWallet({ session, store, history: exit.preExitHistory });
126082
+ } catch {
126083
+ mark("unshield-exit-snapshot-failed");
126084
+ }
126085
+ mark("unshield-exit-answered");
126086
+ try {
126087
+ onAnswered(answer);
126088
+ } catch {
126089
+ }
126090
+ }
126091
+ return { answer, signature: exit.signature, settled: exit.settled !== false, early };
126092
+ }), { ring: { connection: session.connection, pool: pool2 } }));
126093
+ }
126094
+ async function exitFinish({ lease, name, use, mark, scoped, exitOf, tried, onCheckPending, onExited, finalityWaits = 0, preWalk, walkNext }) {
126095
+ const checkPending = (store, error) => {
125992
126096
  mark("unshield-exit-check-pending");
125993
- store.writeWal(name, { ...store.readWal(name), exitCheckPendingAtMs: Date.now() });
126097
+ if (store) store.writeWal(name, { ...store.readWal(name), exitCheckPendingAtMs: Date.now() });
125994
126098
  try {
125995
126099
  onCheckPending?.(error);
125996
126100
  } catch {
125997
126101
  }
125998
- return false;
126102
+ };
126103
+ try {
126104
+ for (let waits = 0; ; waits += 1) {
126105
+ const early = !tried.settled && typeof preWalk === "function" ? await preWalk() : void 0;
126106
+ const notFinal = await lease(async (store) => {
126107
+ mark("unshield-lease-finish");
126108
+ use(store);
126109
+ if (!tried.settled) {
126110
+ walkNext?.(walkStillCurrent(store, early));
126111
+ try {
126112
+ await scoped("unshield-exit", () => exitOf(store));
126113
+ } catch (error) {
126114
+ if (waits < finalityWaits && NOT_FINAL_YET.test(String(error?.message ?? ""))) return true;
126115
+ if (!tried.early) throw error;
126116
+ checkPending(store, error);
126117
+ return false;
126118
+ } finally {
126119
+ walkNext?.(void 0);
126120
+ }
126121
+ }
126122
+ mark("unshield-exited");
126123
+ const exited = store.readWal(name);
126124
+ store.writeWal(name, { ...exited, state: "exited", exitTransaction: tried.signature, exitedAtMs: exited?.exitedAtMs ?? exited?.exitAnsweredAtMs ?? Date.now() });
126125
+ onExited();
126126
+ return false;
126127
+ });
126128
+ if (!notFinal) break;
126129
+ mark("unshield-finish-finality-wait");
126130
+ await new Promise((resolve35) => {
126131
+ setTimeout(resolve35, FINISH_FINALITY_WAIT_MS);
126132
+ });
126133
+ }
126134
+ } catch (error) {
126135
+ if (!tried.early) throw error;
126136
+ checkPending(void 0, error);
125999
126137
  }
126138
+ return tried.answer;
126000
126139
  }
126001
126140
  async function runDirectExit({
126002
126141
  session,
126003
126142
  store,
126143
+ name,
126144
+ pool: pool2,
126004
126145
  unshieldId,
126005
126146
  amountAtomic,
126006
126147
  record,
@@ -126011,13 +126152,11 @@ async function runDirectExit({
126011
126152
  facilitatorOrigin: facilitatorOrigin2,
126012
126153
  onStage,
126013
126154
  walk,
126014
- mark = () => {
126015
- },
126016
- scoped = (_prefix, fn) => fn(),
126017
- onAnswered,
126018
- onCheckPending
126155
+ use,
126156
+ mark,
126157
+ scoped,
126158
+ onAnswered
126019
126159
  }) {
126020
- const name = `self-pay-${unshieldId}`;
126021
126160
  if (record.amountAtomic !== String(amountAtomic) || record.exitAmountAtomic !== String(amountAtomic)) {
126022
126161
  throw new Error("mcp_request_id_reused: this unshield's direct exit is bound to another amount; nothing new was signed");
126023
126162
  }
@@ -126030,45 +126169,54 @@ async function runDirectExit({
126030
126169
  if (!selfPayMayHaveSigned(store, unshieldId)) await checkUnshieldRecipient({ connection: session.connection, mint, owner });
126031
126170
  onStage("exit");
126032
126171
  mark("unshield-exit");
126033
- const proveExit = async (request) => {
126034
- const proved = await proveRecoveredP03NoteExit({ request, tools: exitProofTools });
126035
- const now = store.readWal(name);
126036
- if (now?.mode === DIRECT_EXIT_MODE && now.state === "started") store.writeWal(name, { ...now, state: "paid" });
126037
- return proved;
126038
- };
126039
126172
  const exitAmountAtomic = record.exitAmountAtomic === record.noteValueAtomic ? void 0 : record.exitAmountAtomic;
126040
- let exit;
126041
- try {
126042
- exit = await scoped("unshield-exit", () => exitWhenAnchored(() => runRecoveredP03NoteExit({
126043
- store,
126044
- connection: session.connection,
126045
- programId: session.programId,
126046
- serviceUrl: facilitatorOrigin2,
126047
- digests: [record.memoDigest],
126048
- recipientTokenAccount: recipient.toBase58(),
126049
- proofTools: exitProofTools,
126050
- noteCommitment: record.noteCommitment,
126051
- exitAmountAtomic,
126052
- recipientOwner: owner.toBase58(),
126053
- allowForeignRecipient: true,
126054
- relaySubmit: facilitatorExitRelay(facilitatorOrigin2),
126055
- requestAnchor: markedAnchorRequest(facilitatorAnchor(facilitatorOrigin2)),
126056
- answerAtRelay: true,
126057
- deps: { walkHistory: walk(exitProofTools.deploymentIdentity), proveExit }
126058
- }), { ring: { connection: session.connection, pool: store.state.pool } }));
126059
- } catch (error) {
126060
- if (/requested recovered note is not uniquely spendable/.test(String(error?.message)) && store.readWal(name)?.state === "started" && !store.readWal(directExitWalName(record)) && !selfPayMayHaveSigned(store, unshieldId)) {
126173
+ const changeAtomic = exitAmountAtomic === void 0 ? void 0 : (BigInt(record.noteValueAtomic) - BigInt(record.exitAmountAtomic)).toString();
126174
+ const exitOf = (opened) => runRecoveredP03NoteExit({
126175
+ store: opened,
126176
+ connection: session.connection,
126177
+ programId: session.programId,
126178
+ serviceUrl: facilitatorOrigin2,
126179
+ digests: [record.memoDigest],
126180
+ recipientTokenAccount: recipient.toBase58(),
126181
+ proofTools: exitProofTools,
126182
+ noteCommitment: record.noteCommitment,
126183
+ exitAmountAtomic,
126184
+ recipientOwner: owner.toBase58(),
126185
+ allowForeignRecipient: true,
126186
+ relaySubmit: facilitatorExitRelay(facilitatorOrigin2),
126187
+ requestAnchor: markedAnchorRequest(facilitatorAnchor(facilitatorOrigin2)),
126188
+ answerAtRelay: true,
126189
+ deps: {
126190
+ walkHistory: walk(exitProofTools.deploymentIdentity),
126191
+ // The record reads "paid" once the proof exists, before the library stores it and before any relay call: from then
126192
+ // on the part may have reached the relay (cancel and the private send's own records see that), and the note is held.
126193
+ proveExit: async (request) => {
126194
+ const proved = await proveRecoveredP03NoteExit({ request, tools: exitProofTools });
126195
+ const now = opened.readWal(name);
126196
+ if (now?.mode === DIRECT_EXIT_MODE && now.state === "started") opened.writeWal(name, { ...now, state: "paid" });
126197
+ return proved;
126198
+ }
126199
+ }
126200
+ }).catch((error) => {
126201
+ if (/requested recovered note is not uniquely spendable/.test(String(error?.message)) && opened.readWal(name)?.state === "started" && !opened.readWal(directExitWalName(record)) && !selfPayMayHaveSigned(opened, unshieldId)) {
126061
126202
  throw new Error("mcp_unshield_received_payment_gone: the received payment this unshield chose is no longer spendable (another spend took it, or the wallet's last chain read was old); nothing was signed, and this request_id cannot pass");
126062
126203
  }
126063
126204
  throw error;
126064
- }
126065
- const answer = { selfPayTransaction: null, exitTransaction: exit.signature ?? null };
126066
- const changeAtomic = exitAmountAtomic === void 0 ? void 0 : (BigInt(record.noteValueAtomic) - BigInt(record.exitAmountAtomic)).toString();
126067
- if (exit.settled === false && !await finishAnsweredExit({ session, store, name, exit, answer, changeAtomic, onAnswered, onCheckPending, mark, scoped })) return answer;
126068
- mark("unshield-exited");
126069
- const exited = store.readWal(name);
126070
- store.writeWal(name, { ...exited, state: "exited", exitTransaction: exit.signature, exitedAtMs: exited?.exitedAtMs ?? exited?.exitAnsweredAtMs ?? Date.now() });
126071
- return answer;
126205
+ });
126206
+ const tried = await exitTries({
126207
+ session,
126208
+ lease: (task) => task(store),
126209
+ name,
126210
+ pool: pool2,
126211
+ use,
126212
+ mark,
126213
+ scoped,
126214
+ exitOf,
126215
+ answer: { selfPayTransaction: null },
126216
+ changeAtomic,
126217
+ onAnswered
126218
+ });
126219
+ return { tried, exitOf };
126072
126220
  }
126073
126221
  function balanceFields(parts) {
126074
126222
  if (!parts) return null;
@@ -126389,8 +126537,37 @@ function createWalletTools({
126389
126537
  ...history ? { history } : {},
126390
126538
  ...share ? { share } : {}
126391
126539
  });
126392
- const refundNotices = [];
126393
- const takeRefundNotices = () => refundNotices.length ? { refundNotices: refundNotices.splice(0) } : {};
126540
+ const shownRefunds = /* @__PURE__ */ new Set();
126541
+ const takeRefundNotices = (store) => {
126542
+ let outcomes;
126543
+ try {
126544
+ outcomes = readFloatRefundOutcomes(store ?? session.openStore());
126545
+ } catch {
126546
+ return {};
126547
+ }
126548
+ const fresh = outcomes.filter(({ floatId, outcome }) => !shownRefunds.has(`${floatId}:${outcome}`));
126549
+ if (!fresh.length) return {};
126550
+ for (const { floatId, outcome } of fresh) shownRefunds.add(`${floatId}:${outcome}`);
126551
+ underLease((leased) => markFloatRefundOutcomesShown(leased, fresh)).catch(() => {
126552
+ });
126553
+ return { refundNotices: fresh.map(refundOutcomeText) };
126554
+ };
126555
+ const withRefundNotices = (answer, store) => {
126556
+ let value2;
126557
+ try {
126558
+ value2 = JSON.parse(answer.text);
126559
+ } catch {
126560
+ return answer;
126561
+ }
126562
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) return answer;
126563
+ const notices = takeRefundNotices(store);
126564
+ if (!notices.refundNotices) return answer;
126565
+ return json3({
126566
+ ...value2,
126567
+ ...notices,
126568
+ ...typeof value2.next === "string" ? { next: `${value2.next.replace(/[.\s]+$/, "")}. Tell the user each refundNotices line` } : {}
126569
+ });
126570
+ };
126394
126571
  let lastWriterEndedAt = 0;
126395
126572
  let paysInFlight = 0;
126396
126573
  let payJoinWaiting = 0;
@@ -126829,7 +127006,6 @@ function createWalletTools({
126829
127006
  if (early !== void 0 && !same2) log("MCP_REFRESH_WALK_AGAIN");
126830
127007
  const share = early !== void 0 && !same2 ? { notBeforeMs: Date.now() } : void 0;
126831
127008
  let result2 = await refreshStep(store, same2 ? early.history : void 0, share);
126832
- refundNotices.push(...takeFloatRefundOutcomes(store).map(refundOutcomeText));
126833
127009
  let marksAfter = walletHomeMarks(session.walletPath);
126834
127010
  const settled = (marks) => marks !== void 0 && marks.readAtMs - marks.newestMs >= HOME_MARKS_SETTLED_MS2;
126835
127011
  if (background && settled(marksBefore) && marksAfter !== void 0 && marksAfter.marks !== marksBefore.marks && paysInFlight === 0) {
@@ -127311,8 +127487,12 @@ ${canonical5}`;
127311
127487
  };
127312
127488
  for (const [phase, at, outcome] of gateTimes) mark(phase, at, outcome);
127313
127489
  let earlyBalance;
127490
+ let earlyCorrection;
127314
127491
  const payTiming = (phase, outcome, at) => {
127315
- if (phase === "seller-sent") sellerSentAt.set(requestId, Date.now());
127492
+ if (phase === "seller-sent") {
127493
+ sellerSentAt.set(requestId, Date.now());
127494
+ earlyCorrection ??= startFloatCorrection();
127495
+ }
127316
127496
  if (timing === void 0) return;
127317
127497
  timing(phase, outcome, at);
127318
127498
  if (phase === "seller-sent" && earlyBalance === void 0) earlyBalance = earlyResultBalance(requestId);
@@ -127422,11 +127602,10 @@ ${canonical5}`;
127422
127602
  await waitWithProgress(retry.waitMs, progress3, "waiting to try the payment again; nothing was paid");
127423
127603
  continue;
127424
127604
  }
127425
- await correctFloatRecordsNow();
127605
+ await correctFloatRecordsNow(void 0, earlyCorrection);
127426
127606
  const failed = payFailure(error, requestId, "x402_pay", join39);
127427
127607
  const ready = readyInSecondsOf(error, code2);
127428
- const extra = { ...takeRefundNotices(), ...ready !== void 0 ? { readyInSeconds: ready } : {} };
127429
- return Object.keys(extra).length ? json3({ ...JSON.parse(failed.text), ...extra }) : failed;
127608
+ return withRefundNotices(ready !== void 0 ? json3({ ...JSON.parse(failed.text), readyInSeconds: ready }) : failed);
127430
127609
  }
127431
127610
  }
127432
127611
  const { bytes: bytes2, truncated } = await readBody(response);
@@ -127478,7 +127657,7 @@ ${canonical5}`;
127478
127657
  mark("mcp-result-float");
127479
127658
  const floatPaid = float?.state === "receipt";
127480
127659
  const amounts = floatPaid ? { priceAtomic: float.priceAtomic, feeAtomic: float.feeAtomic, amountAtomic: float.paidAtomic } : { priceAtomic: receipt.amountAtomic ?? null, feeAtomic: "0", amountAtomic: receipt.amountAtomic ?? null };
127481
- if (paidStore && await correctFloatRecordsNow(paidStore) > 0) {
127660
+ if (paidStore && await correctFloatRecordsNow(paidStore, earlyCorrection) > 0) {
127482
127661
  earlyBalance = void 0;
127483
127662
  try {
127484
127663
  paidStore = session.openStore();
@@ -127503,6 +127682,7 @@ ${canonical5}`;
127503
127682
  }
127504
127683
  mark("mcp-result");
127505
127684
  const shinjukuTransaction = floatPaid ? leg1Transaction(paidStore, float, requestId) : null;
127685
+ const notices = takeRefundNotices(paidStore);
127506
127686
  return answerResult(paidAnswerContent({
127507
127687
  status: response.status,
127508
127688
  headers: response.headers,
@@ -127521,8 +127701,8 @@ ${canonical5}`;
127521
127701
  // Leg 1 (this wallet's private payment to Shinjuku, a pool transaction): the seller may return no settle signature.
127522
127702
  ...floatPaid ? { via: "shinjuku", shinjukuTransaction } : {},
127523
127703
  ...balanceAnswer(one),
127524
- ...takeRefundNotices(),
127525
- next: receipt.replayed === true ? "this request id was already paid: the stored receipt came back and nothing new was paid" : floatPaid ? "paid through Shinjuku (privately: the chain shows Shinjuku paying the seller, not this wallet); tell the user the price (priceAtomic), the fee (feeAtomic), the total (amountAtomic), and the transaction (the seller's settle transaction; null when the seller returned none)" + (shinjukuTransaction ? ". shinjukuTransaction is this wallet's private payment to Shinjuku" : ". shinjukuTransaction (this wallet's private payment to Shinjuku) is not recorded yet; wallet_receipts shows it once it settles") + ". wallet_balance shows the new balance" : "paid; tell the user what was paid (amountAtomic, transaction). wallet_receipts lists this payment, wallet_balance shows the new balance"
127704
+ ...notices,
127705
+ next: (receipt.replayed === true ? "this request id was already paid: the stored receipt came back and nothing new was paid" : floatPaid ? "paid through Shinjuku (privately: the chain shows Shinjuku paying the seller, not this wallet); tell the user the price (priceAtomic), the fee (feeAtomic), the total (amountAtomic), and the transaction (the seller's settle transaction; null when the seller returned none)" + (shinjukuTransaction ? ". shinjukuTransaction is this wallet's private payment to Shinjuku" : ". shinjukuTransaction (this wallet's private payment to Shinjuku) is not recorded yet; wallet_receipts shows it once it settles") + ". wallet_balance shows the new balance" : "paid; tell the user what was paid (amountAtomic, transaction). wallet_receipts lists this payment, wallet_balance shows the new balance") + (notices.refundNotices ? ". Tell the user each refundNotices line" : "")
127526
127706
  }, "x402_pay")
127527
127707
  }));
127528
127708
  }
@@ -128669,7 +128849,21 @@ ${canonical5}`;
128669
128849
  }
128670
128850
  return names;
128671
128851
  }
128672
- async function correctFloatRecords(store, names, untilMs) {
128852
+ async function correctFloatRecords(store, names, untilMs, started = floatCorrectionReads(store, names)) {
128853
+ const { states, proven, settled } = started;
128854
+ if (settled === void 0) return { states, written: 0 };
128855
+ const until = (ms) => new Promise((resolve35) => {
128856
+ const timer = setTimeout(resolve35, Math.max(0, ms - Date.now()));
128857
+ timer.unref?.();
128858
+ });
128859
+ await Promise.race([settled, until(untilMs)]);
128860
+ if (!proven.length) return { states, written: 0 };
128861
+ const writing = underLease((leased) => Date.now() >= untilMs ? 0 : writeProven(leased, proven));
128862
+ const written = await Promise.race([writing.catch(() => 0), until(untilMs).then(() => 0)]);
128863
+ if (written > 0) log(`MCP_FLOAT_RECORDS_CORRECTED records=${written}`);
128864
+ return { states, written };
128865
+ }
128866
+ function floatCorrectionReads(store, names) {
128673
128867
  const now = Date.now();
128674
128868
  const due = [];
128675
128869
  const transfers = [];
@@ -128695,11 +128889,11 @@ ${canonical5}`;
128695
128889
  }
128696
128890
  const states = new Map(finalRefundStates);
128697
128891
  for (const [floatId, transaction] of finalTransfers) states.set(floatId, { floatState: "final", transaction });
128698
- if (!due.length && !transfers.length) return { states, written: 0 };
128892
+ const proven = [];
128893
+ if (!due.length && !transfers.length) return { states, proven, settled: void 0 };
128699
128894
  due.sort((left, right) => floatEndedAtMs(right.record) - floatEndedAtMs(left.record));
128700
128895
  transfers.sort((left, right) => floatAnsweredAtMs(right.record) - floatAnsweredAtMs(left.record));
128701
128896
  const fetchImpl = ops.fetch ?? fetch;
128702
- const proven = [];
128703
128897
  const reads = due.slice(0, REFUND_STATUS_READS).map(({ name, record }) => readFloatTransferState(record, fetchImpl).then((read) => {
128704
128898
  const state = floatRecordState(record);
128705
128899
  if (state === "submitted" && read?.state === "landed" || read?.state === "final") {
@@ -128727,26 +128921,24 @@ ${canonical5}`;
128727
128921
  proven.push({ name, from: record.state, transaction: read.transaction, fill: true });
128728
128922
  }));
128729
128923
  }
128730
- const until = (ms) => new Promise((resolve35) => {
128731
- const timer = setTimeout(resolve35, Math.max(0, ms - Date.now()));
128732
- timer.unref?.();
128733
- });
128734
- await Promise.race([Promise.all(reads).catch(() => {
128735
- }), until(untilMs)]);
128736
- if (!proven.length) return { states, written: 0 };
128737
- const writing = underLease((leased) => Date.now() >= untilMs ? 0 : writeProven(leased, proven));
128738
- const written = await Promise.race([writing.catch(() => 0), until(untilMs).then(() => 0)]);
128739
- if (written > 0) log(`MCP_FLOAT_RECORDS_CORRECTED records=${written}`);
128740
- return { states, written };
128924
+ return { states, proven, settled: Promise.all(reads).then(() => void 0, () => void 0) };
128741
128925
  }
128742
- async function correctFloatRecordsNow(store) {
128926
+ async function correctFloatRecordsNow(store, started) {
128743
128927
  try {
128744
128928
  const open4 = store ?? session.openStore();
128745
- return (await correctFloatRecords(open4, staleRefundNames(open4), Date.now() + FLOAT_CORRECT_WAIT_MS)).written;
128929
+ return (await correctFloatRecords(open4, void 0, Date.now() + FLOAT_CORRECT_WAIT_MS, started ?? floatCorrectionReads(open4, staleRefundNames(open4)))).written;
128746
128930
  } catch {
128747
128931
  return 0;
128748
128932
  }
128749
128933
  }
128934
+ function startFloatCorrection() {
128935
+ try {
128936
+ const open4 = session.openStore();
128937
+ return floatCorrectionReads(open4, staleRefundNames(open4));
128938
+ } catch {
128939
+ return void 0;
128940
+ }
128941
+ }
128750
128942
  function writeProven(store, proven) {
128751
128943
  let written = 0;
128752
128944
  for (const { name, from, verdict, transaction, refundDueAtMs, fill } of proven) {
@@ -131113,13 +131305,13 @@ ${canonical5}`;
131113
131305
  }
131114
131306
  return session.openStore();
131115
131307
  }
131116
- async function unshieldPart(opened, job, unshieldId, amountAtomic, onStage, onAnswered) {
131117
- const store = await refreshStaleBeforeUnshield(opened, onStage);
131118
- bindUnshieldRecipient(store, unshieldId, amountAtomic, job.to, unshieldId === moneyId(job.requestId) ? job.requestId : void 0);
131308
+ async function unshieldPart(job, unshieldId, amountAtomic, onStage, { before, onAnswered, firstLease = underLease, yieldMs = UNSHIELD_WINDOW_YIELD_MS } = {}) {
131309
+ const name = `self-pay-${unshieldId}`;
131310
+ let windows = 0;
131119
131311
  let backup;
131312
+ const finishing = { running: true, atMs: Date.now() };
131120
131313
  const result = await (ops.unshield ?? runUnshield)({
131121
131314
  session,
131122
- store,
131123
131315
  unshieldId,
131124
131316
  amountAtomic,
131125
131317
  recipientOwner: job.to,
@@ -131127,24 +131319,44 @@ ${canonical5}`;
131127
131319
  profile: money.profile,
131128
131320
  facilitatorOrigin: money.facilitatorOrigin,
131129
131321
  onStage,
131322
+ finalityWaits: FINISH_FINALITY_WAITS,
131323
+ lease: (task) => windows++ === 0 ? firstLease(task) : new Promise((resolve35) => {
131324
+ setTimeout(resolve35, yieldMs);
131325
+ }).then(() => withLockRetry(() => underLease(task))),
131326
+ before,
131327
+ prepare: async (opened) => {
131328
+ const store = await refreshStaleBeforeUnshield(opened, onStage);
131329
+ bindUnshieldRecipient(store, unshieldId, amountAtomic, job.to, unshieldId === moneyId(job.requestId) ? job.requestId : void 0);
131330
+ return store;
131331
+ },
131130
131332
  ...ops.selfPay ? { selfPayStep: ops.selfPay } : {},
131131
131333
  ...typeof onAnswered === "function" ? { onAnswered: (answer) => {
131334
+ answeredExitTries.set(name, finishing);
131132
131335
  backup = backupNow(session.openStore());
131133
131336
  onAnswered({ ...answer, ...backup });
131134
131337
  } } : {},
131135
131338
  onCheckPending: (error) => {
131136
131339
  log(`MCP_UNSHIELD_CHECK_PENDING requestId=${job.requestId} cause=${JSON.stringify(String(error?.message ?? error ?? "").split("\n", 1)[0].slice(0, 240))}`);
131137
- answeredExitTries.set(`self-pay-${unshieldId}`, { running: false, atMs: Date.now() });
131340
+ answeredExitTries.set(name, { running: false, atMs: Date.now() });
131138
131341
  armAnsweredExitRetry();
131342
+ },
131343
+ onExited: () => {
131344
+ backup ??= backupNow(session.openStore());
131139
131345
  }
131346
+ }).finally(() => {
131347
+ if (answeredExitTries.get(name) === finishing) answeredExitTries.delete(name);
131140
131348
  });
131141
- return { ...result, ...backup ?? backupNow(session.openStore()) };
131349
+ return backup === void 0 ? result : { ...result, ...backup };
131142
131350
  }
131143
131351
  function runUnshieldJob(job, onStage) {
131144
131352
  if (isSplitSend(job)) return runPrivateSendJob(job, onStage);
131145
- return onOwnTorTag(() => underLease(async (opened) => {
131146
- if (!opened.readWal(`self-pay-${moneyId(job.requestId)}`)) await assertNotPromisedFresh(opened, job.amountAtomic);
131147
- return unshieldPart(opened, job, moneyId(job.requestId), job.amountAtomic, onStage, (answer) => answerUnshieldEarly(job, answer));
131353
+ return onOwnTorTag(() => unshieldPart(job, moneyId(job.requestId), job.amountAtomic, onStage, {
131354
+ // A new one (no self-payment yet) never takes value an open private send still owes; a started one continues.
131355
+ before: async (opened) => {
131356
+ if (!opened.readWal(`self-pay-${moneyId(job.requestId)}`)) await assertNotPromisedFresh(opened, job.amountAtomic);
131357
+ },
131358
+ onAnswered: (answer) => answerUnshieldEarly(job, answer),
131359
+ yieldMs: 0
131148
131360
  }));
131149
131361
  }
131150
131362
  function answerUnshieldEarly(job, answer) {
@@ -131201,17 +131413,21 @@ ${canonical5}`;
131201
131413
  // A wait never keeps this server alive by itself: at stdin end the send runner takes the send (handOffSends).
131202
131414
  sleep: sendSleep,
131203
131415
  stopped: () => sendsHandedOff,
131204
- // Each part on one tag of its own (runShieldJob).
131205
- runPart: ({ part, index, total }) => onOwnTorTag(() => underLease(async (opened) => {
131206
- store = opened;
131207
- if (partCancelled(opened, sendId, part)) return { cancelled: true };
131208
- if (partState(opened, part).state === "exited") return {};
131209
- const result = await unshieldPart(opened, job, part.unshieldId, part.amountAtomic, (stage) => onStage(`payment ${index}/${total}: ${stage}`));
131416
+ // Each part on one tag of its own (runShieldJob), in lease windows (unshieldPart).
131417
+ runPart: ({ part, index, total }) => onOwnTorTag(async () => {
131418
+ const result = await unshieldPart(job, part.unshieldId, part.amountAtomic, (stage) => onStage(`payment ${index}/${total}: ${stage}`), {
131419
+ before: (opened) => {
131420
+ store = opened;
131421
+ if (partCancelled(opened, sendId, part)) return { cancelled: true };
131422
+ if (partState(opened, part).state === "exited") return {};
131423
+ return void 0;
131424
+ }
131425
+ });
131210
131426
  if (result.backupPath !== void 0) backup = { backupPath: result.backupPath };
131211
131427
  if (result.backupError !== void 0) backup = { ...backup, backupError: result.backupError };
131212
131428
  store = session.openStore();
131213
131429
  return result;
131214
- })),
131430
+ }),
131215
131431
  // The plan's last write, under the lease like every other.
131216
131432
  finish: () => underLease((opened) => {
131217
131433
  store = opened;
@@ -131665,12 +131881,14 @@ ${canonical5}`;
131665
131881
  answeredExitTries.set(name, attempt);
131666
131882
  const unshieldId = name.slice("self-pay-".length);
131667
131883
  log(`MCP_UNSHIELD_CHECK_RESUME unshieldId=${unshieldId}`);
131668
- onOwnTorTag(() => underLease((opened) => {
131884
+ const tryFinish = (waits) => walkBeforeLease(session, money.exitProofTools).then((early) => underLease((opened) => {
131669
131885
  const current = opened.readWal(name);
131670
131886
  if (current?.state === "exited" || current?.exitUnconfirmed === true || typeof current?.exitTransaction !== "string") return void 0;
131887
+ const walked = walkStillCurrent(opened, early);
131888
+ if (early !== void 0 && walked === void 0) log(`MCP_UNSHIELD_CHECK_WALK_UNDER_LEASE unshieldId=${unshieldId}`);
131671
131889
  return (ops.unshield ?? runUnshield)({
131672
131890
  session,
131673
- store: opened,
131891
+ lease: (task) => task(opened),
131674
131892
  unshieldId,
131675
131893
  amountAtomic: current.amountAtomic,
131676
131894
  recipientOwner: current.mcpTo,
@@ -131679,16 +131897,31 @@ ${canonical5}`;
131679
131897
  facilitatorOrigin: money.facilitatorOrigin,
131680
131898
  onStage: () => {
131681
131899
  },
131682
- ...ops.selfPay ? { selfPayStep: ops.selfPay } : {}
131900
+ ...ops.selfPay ? { selfPayStep: ops.selfPay } : {},
131901
+ ...walked !== void 0 ? { walked } : {}
131902
+ });
131903
+ }, { orClosed: ANSWERED_EXIT_CLOSED })).catch(async (error) => {
131904
+ let answeredAt;
131905
+ try {
131906
+ answeredAt = session.openStore().readWal(name)?.exitAnsweredAtMs;
131907
+ } catch {
131908
+ answeredAt = void 0;
131909
+ }
131910
+ if (waits >= FINISH_FINALITY_WAITS || finalityClosed || session.closed === true || !NOT_FINAL_YET.test(String(error?.message ?? "")) || !Number.isSafeInteger(answeredAt) || Date.now() - answeredAt > FINISH_FINALITY_RECENT_MS) throw error;
131911
+ log(`MCP_UNSHIELD_CHECK_FINALITY_WAIT unshieldId=${unshieldId} wait=${waits + 1}`);
131912
+ await new Promise((resolve35) => {
131913
+ setTimeout(resolve35, FINISH_FINALITY_WAIT_MS);
131683
131914
  });
131684
- }, { orClosed: ANSWERED_EXIT_CLOSED })).then((result) => {
131915
+ return tryFinish(waits + 1);
131916
+ });
131917
+ onOwnTorTag(() => tryFinish(0)).then((result) => {
131685
131918
  if (result === ANSWERED_EXIT_CLOSED) return;
131686
131919
  const now = session.openStore().readWal(name);
131687
131920
  log(now?.state === "exited" ? `MCP_UNSHIELD_CHECK_DONE unshieldId=${unshieldId}` : `MCP_UNSHIELD_CHECK_PENDING unshieldId=${unshieldId}`);
131688
131921
  if (now?.state === "exited") refreshAtFinality();
131689
131922
  }, (error) => {
131690
131923
  const cause = String(error?.message ?? error ?? "").split("\n", 1)[0];
131691
- attempt.provenUnspent = /confirmed note-exit is not finalized spent/.test(cause);
131924
+ attempt.provenUnspent = NOT_FINAL_YET.test(cause);
131692
131925
  log(`MCP_UNSHIELD_CHECK_PENDING unshieldId=${unshieldId} cause=${JSON.stringify(cause.slice(0, 240))}`);
131693
131926
  }).then(() => underLease((opened) => {
131694
131927
  const now = opened.readWal(name);
@@ -132598,21 +132831,27 @@ ${canonical5}`;
132598
132831
  }),
132599
132832
  sleep: sendSleep,
132600
132833
  stopped: () => sendsHandedOff,
132601
- // Each part on one tag of its own (runShieldJob).
132602
- runPart: ({ part, index, total }) => onOwnTorTag(() => withLockRetry(() => underLease(async (opened) => {
132603
- store = opened;
132604
- if (partCancelled(opened, plan.sendId, part)) return { cancelled: true };
132605
- if (partState(opened, part).state === "exited") return {};
132834
+ // Each part on one tag of its own (runShieldJob), in lease windows (unshieldPart); window 1 waits for this server's
132835
+ // own lease holders, as before.
132836
+ runPart: ({ part, index, total }) => onOwnTorTag(async () => {
132606
132837
  const result = await unshieldPart(
132607
- opened,
132608
132838
  job,
132609
132839
  part.unshieldId,
132610
132840
  part.amountAtomic,
132611
- (stage) => log(`MCP_TRANSFER_SEND_STAGE requestId=${plan.id} part=${index}/${total} stage=${stage}`)
132841
+ (stage) => log(`MCP_TRANSFER_SEND_STAGE requestId=${plan.id} part=${index}/${total} stage=${stage}`),
132842
+ {
132843
+ firstLease: (task) => withLockRetry(() => underLease(task)),
132844
+ before: (opened) => {
132845
+ store = opened;
132846
+ if (partCancelled(opened, plan.sendId, part)) return { cancelled: true };
132847
+ if (partState(opened, part).state === "exited") return {};
132848
+ return void 0;
132849
+ }
132850
+ }
132612
132851
  );
132613
132852
  store = session.openStore();
132614
132853
  return result;
132615
- }))),
132854
+ }),
132616
132855
  finish: () => underLease((opened) => {
132617
132856
  store = opened;
132618
132857
  return finishPrivateSend(opened, plan.sendId);
@@ -133580,7 +133819,7 @@ ${canonical5}`;
133580
133819
  { requestId, paid: false, ...facts }
133581
133820
  );
133582
133821
  }
133583
- return inferenceRefusal(error, { requestId, ...facts }) ?? payFailure(error, requestId, "inference_chat");
133822
+ return withRefundNotices(inferenceRefusal(error, { requestId, ...facts }) ?? payFailure(error, requestId, "inference_chat"));
133584
133823
  }
133585
133824
  }
133586
133825
  const receipt = result.receipt ?? {};
@@ -133629,7 +133868,7 @@ ${canonical5}`;
133629
133868
  const larger = moreTokens(args.max_tokens);
133630
133869
  const paidText = usdcText3(paidAtomic ?? "");
133631
133870
  log(`MCP_INFERENCE_OUT_OF_TOKENS requestId=${requestId} maxTokens=${args.max_tokens}`);
133632
- return json3(sayFirst(
133871
+ return withRefundNotices(json3(sayFirst(
133633
133872
  {
133634
133873
  ok: false,
133635
133874
  error: "inference_out_of_tokens",
@@ -133639,13 +133878,13 @@ ${canonical5}`;
133639
133878
  next: receipt.replayed === true ? `this request id was already paid and its stored answer is empty; nothing new was paid. For an answer, call inference_chat with a NEW request_id and max_tokens ${larger}; it pays again` : `Tell the user: the model ran out of tokens before it answered, and this call paid ${paidText ? `${paidText} USDC` : "(see paidAtomic)"}. For an answer, call inference_chat again with a NEW request_id and max_tokens ${larger}; it pays again. The same request_id returns this same empty answer`
133640
133879
  },
133641
133880
  "inference_chat"
133642
- ));
133881
+ )), paidStore);
133643
133882
  }
133644
- return json3(sayFirst({
133883
+ return withRefundNotices(json3(sayFirst({
133645
133884
  ok: true,
133646
133885
  ...paidFields,
133647
133886
  next: receipt.replayed === true ? "this request id was already paid: the stored answer came back and nothing new was paid" : "answered; give the user content, and tell them what was paid: paidAtomic (the AI provider's price, at most ceilingAtomic, plus Shinjuku's fee feeAtomic when via is shinjuku; what is not used is not refunded). wallet_balance shows the new balance"
133648
- }, "inference_chat"));
133887
+ }, "inference_chat")), paidStore);
133649
133888
  }
133650
133889
  };
133651
133890
  const addFunds2 = createAddFundsTool({
@@ -134477,7 +134716,7 @@ function createSetupTools({
134477
134716
  doneTool: sayOnRefusal(doneTool)
134478
134717
  };
134479
134718
  }
134480
- var import_web3132, shownCaps, RELEASE_RETRY_MS, STAGE_WORDS, stageWords, INTERNAL_BALANCE_DETAIL, shownBreakdown, sessionLeftShown, TOKEN_UNIT_TOOLS, RESOURCE_PAYMENT_WAL_PREFIX2, POOL_LAYOUT_CODE, POOL_LAYOUT_UPDATE, USEPOD_VIA_INFERENCE_CHAT, SEND_RUNS_ON, DEPOSIT_RUNS_ON, CLI_FUNDS_PLAN_PREFIX, CLI_FUNDS_SCHEMA, SELF_PAY_ORIGIN3, REQUEST_ID4, POSITIVE_ATOMIC6, PRIVATE_HOST3, FORBIDDEN_HEADERS3, MAX_BODY_BYTES2, PREVIEW_TIMEOUT_MS, PREVIEW_SELLER_READ_MS, CALL_BUDGET_MS, budgetLeft, PAY_ANSWER_MARGIN_MS, MONEY_FIRST_ANSWER_MS, BALANCE_AFTER_LANDING_MS, JOIN_CALL_MAX_MS, JOIN_NUDGE_QUIET_MS, JOIN_STEP_MS, sleep2, PROGRESS_EVERY_MS2, READ_BUDGET_MS, UNPAID_TOR_TRY_MS, UNPAID_CLEAR_MS, READ_BUDGET_TOOLS, FLOAT_BUSY_CODES, RETRY_MARGIN_MS, ASK_PAY_CODES, runningNpmVersion, terminalCommand2, capPlaceWords, CAP_NAMES, capName, capRaiseText, runningLimits, payCapFlag, cheaperSellerText, limitNext, SAFE_TEXT, MCP_TOOL_ALIASES, POOL_SWITCH_WHY, POOL_SWITCH_NEXT, SWITCH_STATES, quietSwitch, switchKey, ATOMIC_TEXT, movedTo, FLOAT_ID, ANSWERED_EXIT_RETRY_MS, ANSWERED_EXIT_UNCONFIRMED_MS, ANSWERED_EXIT_RETRY_WINDOW_MS, ANSWERED_EXIT_CLOSED, switchAmount, switchEta, switchRows, OWNER_CAP_CODES, JOIN_END_MCP, JOIN_END_TERMINAL_LIBRARY, JOIN_RETRY_BACKOFF_MS, WALLET_CAP_FIX, MCP_CAP_FIX, capFix, ownerOnlyNext, mcpNext, CONFIDENTIAL_RETIRED, json3, answerResult, discoverTool, LAUNCH_CAP_CODES, dayCapKind, refuse12, newRequestIdFor, payCapName, publicOffer, FLOAT_PAID_CODES, FLOAT_PRIVATE_LEG, MONEY_ID2, toRecordId, linkKindOf, moneyId, REFUSED_CODES, refusedCodeOf, PLAIN_REASONS, INSUFFICIENT_CODE, insufficientCause, INSUFFICIENT_REASONS, reasonOf, plainReason, KEPT_SEND_TRIES, shownId, isSplitSend, sendPartId, PROMISED_NEXT, partFailReason, sendAnswerOf, PUBLIC_READ_TIMEOUT_MS, RECIPIENT_CHECK_TIMEOUT_MS, withTimeout, ownKey, readFailure, OWN_KEY_TOKENS_MAX, tokenAmountText, elsewhereId, AGENT_ID_SCHEMA, agentIdName, minutesText2, ageWords2, DEPOSIT_SENT_STATES, depositLanded, usdcText3, walkWalletHistory, REFRESH_LEASE_WALK_MS, HOME_MARKS_SETTLED_MS2, AUTO_BACKUPS_KEPT, AUTO_BACKUP_NAME, AUTO_BACKUP_VERIFIED, FRONTED_SETTLE_MARGIN_SLOTS, BALANCE_REFRESH_WAIT_MS, BALANCE_REFRESH_GRACE_MS, BALANCE_REFRESH_LONG_MS, INBOUND_REFRESH_AGE_MS, changeFields, balanceAnswer, CAP_BALANCE_WAIT_MS, CAP_BALANCE_RETRY_MS, REFRESH_RETRY_MS, FINALITY_POLL_MS, FINALITY_WAIT_MS, FINALITY_REFRESH_LIMIT_MS, POOL_WATCH_MS, POOL_WATCH_POLL_MS, EARLY_BALANCE_DELAY_MS, FINALITY_SETTLE_WINDOW_SLOTS, PUBLIC_READ_ANSWER_MS, LINK_READ_ANSWER_MS, OWN_READS_AHEAD_MS, FLOAT_CORRECT_WAIT_MS, SWITCH_WAIT_MS, UNSHIELD_TO_NO_USDC_DETAIL, UNSHIELD_TO_INVALID_NEXT, INFERENCE_MIN_MAX_TOKENS, ELICIT_TIMEOUT_MS, ELICIT_UNSHOWN_MS, elicitUnshown, POLL_SECONDS2, TRANSFER_CHANGE_READ_MS, TEMP_CLEAN_DELAY_MS, KEPT_ON_DISK, MAX_SHIELDED_BALANCE_ATOMIC, receiveGenerator, MCP_TOOL_NAMES, MCP_HIDDEN_TOOL_NAMES, setupTerminalNext, SETUP_RUNNING_SAY, ACCEPTED_NEXT, SETUP_RUNNING_NEXT, SETUP_ANSWER_WAIT_MS, SETUP_CONFIRMING_SAY, SETUP_CONFIRMING_NEXT, PRIVATE_INFERENCE_WHY, RESTART_STEPS, TOR_BROWSER_PORT, SETUP_TOR_TITLE, SETUP_TOR_WHY;
134719
+ var import_web3132, shownCaps, RELEASE_RETRY_MS, STAGE_WORDS, stageWords, INTERNAL_BALANCE_DETAIL, shownBreakdown, sessionLeftShown, TOKEN_UNIT_TOOLS, RESOURCE_PAYMENT_WAL_PREFIX2, POOL_LAYOUT_CODE, POOL_LAYOUT_UPDATE, USEPOD_VIA_INFERENCE_CHAT, SEND_RUNS_ON, DEPOSIT_RUNS_ON, CLI_FUNDS_PLAN_PREFIX, CLI_FUNDS_SCHEMA, SELF_PAY_ORIGIN3, REQUEST_ID4, POSITIVE_ATOMIC6, PRIVATE_HOST3, FORBIDDEN_HEADERS3, MAX_BODY_BYTES2, PREVIEW_TIMEOUT_MS, PREVIEW_SELLER_READ_MS, CALL_BUDGET_MS, budgetLeft, PAY_ANSWER_MARGIN_MS, MONEY_FIRST_ANSWER_MS, BALANCE_AFTER_LANDING_MS, JOIN_CALL_MAX_MS, JOIN_NUDGE_QUIET_MS, JOIN_STEP_MS, sleep2, PROGRESS_EVERY_MS2, READ_BUDGET_MS, UNPAID_TOR_TRY_MS, UNPAID_CLEAR_MS, READ_BUDGET_TOOLS, FLOAT_BUSY_CODES, RETRY_MARGIN_MS, ASK_PAY_CODES, runningNpmVersion, terminalCommand2, capPlaceWords, CAP_NAMES, capName, capRaiseText, runningLimits, payCapFlag, cheaperSellerText, limitNext, SAFE_TEXT, MCP_TOOL_ALIASES, POOL_SWITCH_WHY, POOL_SWITCH_NEXT, SWITCH_STATES, quietSwitch, switchKey, ATOMIC_TEXT, movedTo, FLOAT_ID, ANSWERED_EXIT_RETRY_MS, ANSWERED_EXIT_UNCONFIRMED_MS, ANSWERED_EXIT_RETRY_WINDOW_MS, ANSWERED_EXIT_CLOSED, switchAmount, switchEta, switchRows, OWNER_CAP_CODES, JOIN_END_MCP, JOIN_END_TERMINAL_LIBRARY, JOIN_RETRY_BACKOFF_MS, WALLET_CAP_FIX, MCP_CAP_FIX, capFix, ownerOnlyNext, mcpNext, CONFIDENTIAL_RETIRED, json3, answerResult, discoverTool, LAUNCH_CAP_CODES, dayCapKind, refuse12, newRequestIdFor, payCapName, publicOffer, FLOAT_PAID_CODES, FLOAT_PRIVATE_LEG, MONEY_ID2, toRecordId, linkKindOf, moneyId, REFUSED_CODES, refusedCodeOf, PLAIN_REASONS, INSUFFICIENT_CODE, insufficientCause, INSUFFICIENT_REASONS, reasonOf, plainReason, KEPT_SEND_TRIES, shownId, isSplitSend, sendPartId, PROMISED_NEXT, partFailReason, sendAnswerOf, PUBLIC_READ_TIMEOUT_MS, RECIPIENT_CHECK_TIMEOUT_MS, withTimeout, ownKey, readFailure, OWN_KEY_TOKENS_MAX, tokenAmountText, elsewhereId, AGENT_ID_SCHEMA, agentIdName, minutesText2, ageWords2, DEPOSIT_SENT_STATES, depositLanded, usdcText3, walkWalletHistory, REFRESH_LEASE_WALK_MS, HOME_MARKS_SETTLED_MS2, AUTO_BACKUPS_KEPT, AUTO_BACKUP_NAME, AUTO_BACKUP_VERIFIED, FRONTED_SETTLE_MARGIN_SLOTS, UNSHIELD_WINDOW_YIELD_MS, NOT_FINAL_YET, FINISH_FINALITY_WAIT_MS, FINISH_FINALITY_WAITS, FINISH_FINALITY_RECENT_MS, walkStillCurrent, BALANCE_REFRESH_WAIT_MS, BALANCE_REFRESH_GRACE_MS, BALANCE_REFRESH_LONG_MS, INBOUND_REFRESH_AGE_MS, changeFields, balanceAnswer, CAP_BALANCE_WAIT_MS, CAP_BALANCE_RETRY_MS, REFRESH_RETRY_MS, FINALITY_POLL_MS, FINALITY_WAIT_MS, FINALITY_REFRESH_LIMIT_MS, POOL_WATCH_MS, POOL_WATCH_POLL_MS, EARLY_BALANCE_DELAY_MS, FINALITY_SETTLE_WINDOW_SLOTS, PUBLIC_READ_ANSWER_MS, LINK_READ_ANSWER_MS, OWN_READS_AHEAD_MS, FLOAT_CORRECT_WAIT_MS, SWITCH_WAIT_MS, UNSHIELD_TO_NO_USDC_DETAIL, UNSHIELD_TO_INVALID_NEXT, INFERENCE_MIN_MAX_TOKENS, ELICIT_TIMEOUT_MS, ELICIT_UNSHOWN_MS, elicitUnshown, POLL_SECONDS2, TRANSFER_CHANGE_READ_MS, TEMP_CLEAN_DELAY_MS, KEPT_ON_DISK, MAX_SHIELDED_BALANCE_ATOMIC, receiveGenerator, MCP_TOOL_NAMES, MCP_HIDDEN_TOOL_NAMES, setupTerminalNext, SETUP_RUNNING_SAY, ACCEPTED_NEXT, SETUP_RUNNING_NEXT, SETUP_ANSWER_WAIT_MS, SETUP_CONFIRMING_SAY, SETUP_CONFIRMING_NEXT, PRIVATE_INFERENCE_WHY, RESTART_STEPS, TOR_BROWSER_PORT, SETUP_TOR_TITLE, SETUP_TOR_WHY;
134481
134720
  var init_tools = __esm({
134482
134721
  "wallet/src/mcp/tools.mjs"() {
134483
134722
  "use strict";
@@ -134904,6 +135143,12 @@ var init_tools = __esm({
134904
135143
  AUTO_BACKUP_NAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z(-\d+)?$/;
134905
135144
  AUTO_BACKUP_VERIFIED = ".verified";
134906
135145
  FRONTED_SETTLE_MARGIN_SLOTS = 20;
135146
+ UNSHIELD_WINDOW_YIELD_MS = 1500;
135147
+ NOT_FINAL_YET = /confirmed note-exit is not finalized spent/;
135148
+ FINISH_FINALITY_WAIT_MS = 4e3;
135149
+ FINISH_FINALITY_WAITS = 8;
135150
+ FINISH_FINALITY_RECENT_MS = 6e4;
135151
+ walkStillCurrent = (store, early) => early !== void 0 && early.pool === String(store.state.pool) && walletHistoryHomeMarks(store) === early.marks ? early.history : void 0;
134907
135152
  BALANCE_REFRESH_WAIT_MS = 2e4;
134908
135153
  BALANCE_REFRESH_GRACE_MS = 2e3;
134909
135154
  BALANCE_REFRESH_LONG_MS = 6e4;