shinjuku-shield 0.3.111 → 0.3.113
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 +5 -5
- package/manifest.json +4 -4
- package/package.json +3 -3
- package/shinjuku-wallet.mjs +189 -102
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.
|
|
9
|
+
This is version 0.3.113. 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.
|
|
15
|
+
npm install -g shinjuku@0.3.113
|
|
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.
|
|
21
|
+
installing, type `npx shinjuku@0.3.113 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.
|
|
39
|
+
claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.113 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.
|
|
45
|
+
{ "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.113", "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": "
|
|
5
|
-
"bytes":
|
|
6
|
-
"sourceCommit": "
|
|
4
|
+
"sha256": "bfaedd12d120b4b5421cdf6c9c06b07b7e338fd6d4e74b7225f2a0d3aa150cf4",
|
|
5
|
+
"bytes": 8339853,
|
|
6
|
+
"sourceCommit": "0c37c0dea055d3c28bab9939cd5527fc290668f8",
|
|
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-
|
|
1040
|
+
"publishedAt": "2026-10-27T16:17:32.089Z"
|
|
1041
1041
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shield",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.113",
|
|
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": "
|
|
7
|
-
"shinjukuSha256": "
|
|
6
|
+
"shinjukuRelease": "bfaedd12",
|
|
7
|
+
"shinjukuSha256": "bfaedd12d120b4b5421cdf6c9c06b07b7e338fd6d4e74b7225f2a0d3aa150cf4",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
9
9
|
"author": "Shinjuku Shielded",
|
|
10
10
|
"homepage": "https://github.com/ShinjukuStaition/shinjuku-shield#readme",
|
package/shinjuku-wallet.mjs
CHANGED
|
@@ -67087,6 +67087,7 @@ var init_errorCodes = __esm({
|
|
|
67087
67087
|
"p03_float_pool_unreadable_retry_same_request",
|
|
67088
67088
|
"p03_float_body_too_large",
|
|
67089
67089
|
"p03_float_busy_retry_later",
|
|
67090
|
+
"p03_float_fee_account_low",
|
|
67090
67091
|
"p03_float_not_ready_retry_later",
|
|
67091
67092
|
"p03_float_payment_in_flight_retry_later",
|
|
67092
67093
|
"p03_float_already_paid",
|
|
@@ -81130,7 +81131,7 @@ function privateSendHold(store, { accounts, notes, selfProofWalName } = {}) {
|
|
|
81130
81131
|
const self2 = typeof selfProofWalName === "string" ? (part) => selfProofWalName === `resource-proof-${sha256Hex2(Buffer.from(selfPayRequestId(part.unshieldId), "utf8"))}` : void 0;
|
|
81131
81132
|
const unsent = unsentParts(store, self2);
|
|
81132
81133
|
if (unsent === null) return null;
|
|
81133
|
-
const hold = { accounts: /* @__PURE__ */ new
|
|
81134
|
+
const hold = { accounts: /* @__PURE__ */ new Map(), notes: /* @__PURE__ */ new Set(), sends: [], unpacked: [] };
|
|
81134
81135
|
if (unsent.length === 0) return hold;
|
|
81135
81136
|
try {
|
|
81136
81137
|
unsent.sort(bySendPart);
|
|
@@ -81148,22 +81149,27 @@ function privateSendHold(store, { accounts, notes, selfProofWalName } = {}) {
|
|
|
81148
81149
|
const { bins } = packed;
|
|
81149
81150
|
const unpacked = unsent.filter(({ plan }) => short.has(plan.sendId));
|
|
81150
81151
|
const holding = /* @__PURE__ */ new Set();
|
|
81151
|
-
|
|
81152
|
+
const owed = /* @__PURE__ */ new Map();
|
|
81153
|
+
for (const bin of bins) for (const entry of bin.parts) owed.set(entry.plan.sendId, (owed.get(entry.plan.sendId) ?? 0n) + BigInt(entry.part.amountAtomic));
|
|
81152
81154
|
for (const bin of bins) {
|
|
81153
81155
|
if (bin.parts.length === 0 || bin.parts.some((entry) => entry.self)) continue;
|
|
81154
|
-
|
|
81156
|
+
const need = [...new Set(bin.parts.map((entry) => entry.plan.sendId))].reduce((sum2, sendId) => sum2 + owed.get(sendId), 0n);
|
|
81157
|
+
const account = BigInt(bin.entry.account.b);
|
|
81158
|
+
hold.accounts.set(BigInt(bin.entry.commitment).toString(), (bin.notes.length > 0 || need > account ? account : need).toString());
|
|
81155
81159
|
for (const note of bin.notes) hold.notes.add(BigInt(note.commitment).toString());
|
|
81156
81160
|
for (const entry of bin.parts) holding.add(entry.plan.sendId);
|
|
81157
|
-
spare += bin.value - bin.used;
|
|
81158
81161
|
}
|
|
81159
81162
|
for (const { plan } of unsent) if (holding.delete(plan.sendId)) hold.sends.push(namedSend(plan));
|
|
81160
81163
|
hold.unpacked = unpacked.map(({ plan, part }) => ({ sendId: plan.sendId, index: part.index, amountAtomic: String(part.amountAtomic) }));
|
|
81161
|
-
hold.spareAtomic = spare.toString();
|
|
81162
81164
|
} catch {
|
|
81163
81165
|
return null;
|
|
81164
81166
|
}
|
|
81165
81167
|
return hold;
|
|
81166
81168
|
}
|
|
81169
|
+
function heldSpareAtomic(hold, entry) {
|
|
81170
|
+
const need = hold.accounts.get(BigInt(entry.commitment).toString());
|
|
81171
|
+
return need === void 0 ? void 0 : BigInt(entry.account.b) - BigInt(need);
|
|
81172
|
+
}
|
|
81167
81173
|
function privateSendPartsFit(store, { accounts, notes, partAmounts: partAmounts2 }) {
|
|
81168
81174
|
const unsent = unsentParts(store);
|
|
81169
81175
|
if (unsent === null) return false;
|
|
@@ -81373,7 +81379,11 @@ var init_privateSend = __esm({
|
|
|
81373
81379
|
DIRECT_EXIT_MODE = "direct-exit";
|
|
81374
81380
|
noteFitsAccount = (account, note) => account.account?.i === void 0 || note.leafIndex === void 0 || note.leafIndex === null || BigInt(note.leafIndex) >= BigInt(account.account.i);
|
|
81375
81381
|
bySendPart = (left, right) => left.plan.sendId < right.plan.sendId ? -1 : left.plan.sendId > right.plan.sendId ? 1 : left.part.index - right.part.index;
|
|
81376
|
-
namedSend = (plan) =>
|
|
81382
|
+
namedSend = (plan) => ({
|
|
81383
|
+
...typeof plan.transferTokenId === "string" ? { sendId: plan.sendId, requestId: plan.transferTokenId, tool: "wallet_transfer_token" } : typeof plan.mcpTo !== "string" ? { sendId: plan.sendId, requestId: plan.sendId, tool: "cli" } : { sendId: plan.sendId, requestId: typeof plan.mcpRequestId === "string" ? plan.mcpRequestId : String(plan.sendId).replace(/^mcp-/, ""), tool: "wallet_unshield" },
|
|
81384
|
+
to: typeof plan.mcpTo === "string" ? plan.mcpTo : plan.to,
|
|
81385
|
+
amountAtomic: String(plan.amountAtomic)
|
|
81386
|
+
});
|
|
81377
81387
|
cancelledPart = (store, plan, part) => plan.state === "cancelled" && !partMayHaveSigned(store, part);
|
|
81378
81388
|
partCancelled = (store, sendId, part) => {
|
|
81379
81389
|
const plan = store.readWal(privateSendPlanName(sendId));
|
|
@@ -81714,7 +81724,9 @@ async function everyAccountHeld({ store, connection, programId, serviceUrl: serv
|
|
|
81714
81724
|
if (freeAccounts.length === 0) return anyHeld;
|
|
81715
81725
|
const largest = freeAccounts.reduce((max, entry) => BigInt(entry.account.b) > BigInt(max.account.b) ? entry : max);
|
|
81716
81726
|
if (!anyHeld) {
|
|
81717
|
-
|
|
81727
|
+
if (!unheldAccounts.some((entry) => (heldSpareAtomic(sendHold, entry) ?? 0n) >= BigInt(amountAtomic))) {
|
|
81728
|
+
assertAccountsNotSplit({ accounts: freeAccounts, account: largest, notes: freeNotes.filter(free), amountAtomic });
|
|
81729
|
+
}
|
|
81718
81730
|
return false;
|
|
81719
81731
|
}
|
|
81720
81732
|
const notesValue = freeNotes.reduce((sum2, entry) => sum2 + BigInt(entry.note.b), 0n);
|
|
@@ -81872,10 +81884,15 @@ async function prepareRecoveredPayment({
|
|
|
81872
81884
|
};
|
|
81873
81885
|
const unheldNotes = unspentNotes.filter((entry) => !heldByPending(entry) && !exitReserved.has(BigInt(entry.commitment).toString()) && !keptNote(entry));
|
|
81874
81886
|
const held = unheldAccounts.length !== unspentAccounts.length || unspentNotes.filter((entry) => !exitReserved.has(BigInt(entry.commitment).toString()) && !keptNote(entry)).length !== unheldNotes.length;
|
|
81875
|
-
const sendHold = deps.poolMove === true ? { accounts: /* @__PURE__ */ new
|
|
81887
|
+
const sendHold = deps.poolMove === true ? { accounts: /* @__PURE__ */ new Map(), notes: /* @__PURE__ */ new Set(), sends: [], unpacked: [] } : privateSendHold(store, { accounts: unheldAccounts, notes: unheldNotes, selfProofWalName: requestedWalName });
|
|
81876
81888
|
if (sendHold === null) heldByPrivateSend([]);
|
|
81877
81889
|
const sendHeld = (entry) => (entry.kind === "account" ? sendHold.accounts : sendHold.notes).has(BigInt(entry.commitment).toString());
|
|
81878
81890
|
const accounts = sendHold.accounts.size === 0 ? unheldAccounts : unheldAccounts.filter((entry) => !sendHeld(entry));
|
|
81891
|
+
const heldAccounts = sendHold.accounts.size === 0 ? [] : unheldAccounts.filter(sendHeld);
|
|
81892
|
+
const spareSpend = (outputIndex) => {
|
|
81893
|
+
const fits = heldAccounts.filter((entry) => heldSpareAtomic(sendHold, entry) >= BigInt(witnessQuote.amountAtomic));
|
|
81894
|
+
return fits.length === 0 ? void 0 : selectSpendAccount({ accounts: fits, notes: [], outputIndex, amountAtomic: witnessQuote.amountAtomic }).account;
|
|
81895
|
+
};
|
|
81879
81896
|
const freeNotes = sendHold.notes.size === 0 ? unheldNotes : unheldNotes.filter((entry) => !sendHeld(entry));
|
|
81880
81897
|
const notes = sendHold.accounts.size === 0 && sendHold.notes.size === 0 ? unheldNotes : freeNotes.filter((entry) => accounts.some((account2) => noteFitsAccount(account2, entry)));
|
|
81881
81898
|
let refusedValues;
|
|
@@ -81887,7 +81904,7 @@ async function prepareRecoveredPayment({
|
|
|
81887
81904
|
return false;
|
|
81888
81905
|
}
|
|
81889
81906
|
};
|
|
81890
|
-
|
|
81907
|
+
let wantedNotes = selection?.noteCommitments !== void 0 ? selection.noteCommitments.map((commitment) => {
|
|
81891
81908
|
const wanted = BigInt(commitment);
|
|
81892
81909
|
const found = notes.find((entry) => BigInt(entry.commitment) === wanted);
|
|
81893
81910
|
if (!found && exitReserved.has(wanted.toString())) fail20("requested_note_reserved_by_exit");
|
|
@@ -81982,14 +81999,21 @@ async function prepareRecoveredPayment({
|
|
|
81982
81999
|
if (largest && finalizedLargest !== void 0 && (underAnchor === void 0 || BigInt(finalizedLargest.account.b) > BigInt(underAnchor.account.b))) {
|
|
81983
82000
|
throw new Error("p03_quote_anchor_older_than_note_wait_next_epoch");
|
|
81984
82001
|
}
|
|
81985
|
-
|
|
81986
|
-
|
|
82002
|
+
const spareAllowed = !pays(underAnchor) && !largest && selection?.noteCommitments === void 0;
|
|
82003
|
+
const spare = spareAllowed ? spareSpend(anchor.index) : void 0;
|
|
82004
|
+
if (spareAllowed && spare === void 0 && spareSpend(history.finalizedPoolSnapshot.currentIndex) !== void 0) {
|
|
82005
|
+
throw new Error("p03_quote_anchor_older_than_note_wait_next_epoch");
|
|
82006
|
+
}
|
|
82007
|
+
if (spare !== void 0) wantedNotes = [];
|
|
82008
|
+
account = spare ?? underAnchor ?? accounts[0];
|
|
82009
|
+
sendShort = spare === void 0 && (sendHold.accounts.size > 0 || sendHold.notes.size > 0) && !pays(underAnchor);
|
|
81987
82010
|
}
|
|
81988
82011
|
if (account) assertAccountsNotSplit({ accounts, account, notes: wantedNotes, allNotes: notes, amountAtomic: witnessQuote.amountAtomic });
|
|
81989
|
-
if (sendShort && (accounts.length === 0 || [...accounts.map((entry) => entry.account.b), ...freeNotes.map((entry) => entry.note.b)].reduce((sum2, value2) => sum2 + BigInt(value2),
|
|
82012
|
+
if (sendShort && (accounts.length === 0 || [...accounts.map((entry) => entry.account.b), ...freeNotes.map((entry) => entry.note.b)].reduce((sum2, value2) => sum2 + BigInt(value2), heldAccounts.reduce((sum2, entry) => sum2 + heldSpareAtomic(sendHold, entry), 0n)) >= BigInt(witnessQuote.amountAtomic))) {
|
|
81990
82013
|
heldByPrivateSend(sendHold.sends);
|
|
81991
82014
|
}
|
|
81992
82015
|
if (!account) fail20("no_spendable_account");
|
|
82016
|
+
if (sendHeld(account) && heldSpareAtomic(sendHold, account) + wantedNotes.reduce((sum2, note) => sum2 + BigInt(note.note.b), 0n) < BigInt(witnessQuote.amountAtomic)) heldByPrivateSend(sendHold.sends);
|
|
81993
82017
|
await prepareFold(deps.buildRecoveryPath);
|
|
81994
82018
|
accountPath = buildRecoveryPath({
|
|
81995
82019
|
history,
|
|
@@ -100854,6 +100878,14 @@ function floatOutcomeWords(code2, error, t) {
|
|
|
100854
100878
|
return [code2, "Shinjuku's shared float is busy right now; nothing was paid", t.againIn(error?.retryAfterSeconds ?? 30)];
|
|
100855
100879
|
case "p03_float_not_ready_retry_later":
|
|
100856
100880
|
return [code2, "Shinjuku's shared float is not ready yet (it is being filled); nothing was paid", t.againIn(error?.retryAfterSeconds ?? 60)];
|
|
100881
|
+
// The fee payer of Shinjuku's shared pockets is low on SOL (floatPay.mjs floatRefusalError, 0.3.113): only its operator
|
|
100882
|
+
// refills it, so the words name no time and ask for no retry soon (mcp6 0.3.112 gate: "retry in a minute" failed again).
|
|
100883
|
+
case "p03_float_fee_account_low":
|
|
100884
|
+
return [
|
|
100885
|
+
code2,
|
|
100886
|
+
"the Shinjuku account that pays the network fee of this payment is low on SOL, and its operator was alerted; nothing was paid and the balance did not change",
|
|
100887
|
+
`This is not a fault of the wallet: the payment can go after the operator adds SOL to that account, and no time is known. ${t.rerun} later`
|
|
100888
|
+
];
|
|
100857
100889
|
case "p03_float_payment_in_flight_retry_later":
|
|
100858
100890
|
return [code2, "an earlier quote for this payment is still open at Shinjuku; nothing was paid", t.againIn(error?.retryAfterSeconds ?? 60)];
|
|
100859
100891
|
case "p03_float_price_above_capacity":
|
|
@@ -101870,6 +101902,8 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
|
|
|
101870
101902
|
let spendInputs;
|
|
101871
101903
|
let sendHold;
|
|
101872
101904
|
let heldAtomic;
|
|
101905
|
+
let heldWholeAtomic;
|
|
101906
|
+
let spareMost = 0n;
|
|
101873
101907
|
const report = (status, gross, next2, cause, largest2, change) => {
|
|
101874
101908
|
const atomic4 = gross === null || privateSendPending === null ? null : gross > privateSendPending ? gross - privateSendPending : 0n;
|
|
101875
101909
|
const built = {
|
|
@@ -101899,7 +101933,11 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
|
|
|
101899
101933
|
if (spendInputs !== void 0) SPEND_INPUTS.set(built, spendInputs);
|
|
101900
101934
|
if (atomic4 !== null && sendHold && heldAtomic !== void 0) {
|
|
101901
101935
|
const aside = heldAtomic > privateSendPending ? heldAtomic : privateSendPending;
|
|
101902
|
-
|
|
101936
|
+
const whole = heldWholeAtomic > privateSendPending ? heldWholeAtomic : privateSendPending;
|
|
101937
|
+
const outside = gross > whole ? gross - whole : 0n;
|
|
101938
|
+
const most = outside > spareMost ? outside : spareMost;
|
|
101939
|
+
const cap = gross > aside ? gross - aside : 0n;
|
|
101940
|
+
SEND_HOLDS.set(built, { ...sendHold, freeAtomic: (most < cap ? most : cap).toString(), heldAtomic: aside.toString() });
|
|
101903
101941
|
}
|
|
101904
101942
|
if (largest2 !== void 0 && atomic4 !== null) {
|
|
101905
101943
|
const cap = atomic4 - BigInt(detail.successionMovableAtomic ?? "0");
|
|
@@ -102158,14 +102196,18 @@ It asks the amount, then gives a one-time address and its QR code: send USDC to
|
|
|
102158
102196
|
const entries = free.map(spendEntry);
|
|
102159
102197
|
const freeInputs = { accounts: entries.filter((entry) => entry.kind === "account"), notes: entries.filter((entry) => entry.kind === "note") };
|
|
102160
102198
|
if (!unknownInputs) spendInputs = freeInputs;
|
|
102161
|
-
sendHold = privateSendPending === 0n ? { accounts: /* @__PURE__ */ new
|
|
102199
|
+
sendHold = privateSendPending === 0n ? { accounts: /* @__PURE__ */ new Map(), notes: /* @__PURE__ */ new Set(), sends: [], unpacked: [] } : privateSendPending === null ? null : privateSendHold(store, freeInputs);
|
|
102162
102200
|
const isHeld = (output2) => sendHold.accounts.has(output2.commitment) || sendHold.notes.has(output2.commitment);
|
|
102163
102201
|
const notHeld = sendHold === null ? [] : free.filter((output2) => !isHeld(output2));
|
|
102164
102202
|
const open4 = sendHold === null || sendHold.accounts.size === 0 && sendHold.notes.size === 0 ? notHeld : notHeld.filter((output2) => output2.kind !== "note" || notHeld.some((other) => other.kind === "account" && noteFitsAccount(spendEntry(other), spendEntry(output2))));
|
|
102203
|
+
const spares = sendHold === null ? [] : free.filter((output2) => output2.kind === "account" && sendHold.accounts.has(output2.commitment)).map((output2) => ({ output: output2, spareAtomic: heldSpareAtomic(sendHold, spendEntry(output2)) }));
|
|
102165
102204
|
if (sendHold !== null) {
|
|
102166
|
-
|
|
102205
|
+
heldWholeAtomic = sum2(free.filter(isHeld).map((output2) => output2.valueAtomic)) + sum2(sendHold.unpacked.map((part) => part.amountAtomic));
|
|
102206
|
+
heldAtomic = heldWholeAtomic - sum2(spares.map((spare) => spare.spareAtomic));
|
|
102207
|
+
spareMost = spares.reduce((most, spare) => spare.spareAtomic > most ? spare.spareAtomic : most, 0n);
|
|
102167
102208
|
}
|
|
102168
|
-
const
|
|
102209
|
+
const openLargest = sendHold === null ? void 0 : largestOneSpend(open4);
|
|
102210
|
+
const largest = openLargest === void 0 || openLargest >= spareMost ? openLargest : spareMost;
|
|
102169
102211
|
if (settling.some((payment) => payment.inputs.some((commitment) => reserved.has(commitment) || joining.has(commitment))) || unknownInputs && settling.length) {
|
|
102170
102212
|
reasons.push(...settlingReasons);
|
|
102171
102213
|
return report("stale", null, refreshCommand(state, snapshot.programId));
|
|
@@ -102176,7 +102218,10 @@ It asks the amount, then gives a one-time address and its QR code: send USDC to
|
|
|
102176
102218
|
return report("stale", null, refreshCommand(state, snapshot.programId));
|
|
102177
102219
|
}
|
|
102178
102220
|
const anchorIndex = canonicalAtomic(snapshot.anchorIndex) ? BigInt(snapshot.anchorIndex) : void 0;
|
|
102179
|
-
detail.fundedAccounts = unknownInputs ? 0 : sendHold === null ? null :
|
|
102221
|
+
detail.fundedAccounts = unknownInputs ? 0 : sendHold === null ? null : [
|
|
102222
|
+
...open4.filter((output2) => output2.kind === "account" && BigInt(output2.valueAtomic) > 0n),
|
|
102223
|
+
...spares.filter((spare) => spare.spareAtomic > 0n).map((spare) => spare.output)
|
|
102224
|
+
].filter((output2) => anchorIndex === void 0 || BigInt(output2.leafIndex) < anchorIndex).length;
|
|
102180
102225
|
const answeredOnly = detail.inFlight.length > 0 && detail.inFlight.every((item) => item.answered === true);
|
|
102181
102226
|
const next = answeredOnly ? detail.inFlight.find((item) => item.next.startsWith("rerun"))?.next ?? "nothing to do: an answered unshield finishes its check by itself" : detail.inFlight.length ? "finish or cancel the work in detail.inFlight; the wallet runs one payment at a time" : pendingDeposits.length ? byAddFunds(pendingDeposits[0].depositId) ? `deposit ${pendingDeposits[0].depositId} of add-funds is not finished. ${continueAddFunds}` : `deposit ${pendingDeposits[0].depositId} is not finished: rerun the same deposit command with --submit --service <facilitator URL>` : pocketsUnscanned ? scanPockets2 : unspentAtomic === 0n && successionMovableAtomic > 0n ? "this pool was succeeded by a new pool: its value moves there (one move per funded deposit, the facilitator pays the fee) and counts in this balance until then" : unspentAtomic === 0n ? `nothing to spend. To add money, run:
|
|
102182
102227
|
${commandLine("add-funds")}
|
|
@@ -102188,9 +102233,11 @@ If a payment to this wallet settled, read the chain again with:
|
|
|
102188
102233
|
if (settling.length || movedInAtomic > 0n) {
|
|
102189
102234
|
reasons.push(...settlingReasons);
|
|
102190
102235
|
const [only] = settling;
|
|
102191
|
-
const sendHeldAtomic = sendHold === null || sendHold.
|
|
102236
|
+
const sendHeldAtomic = sendHold === null || sendHold.notes.size > 0 ? null : sum2(free.filter(isHeld).map((output2) => output2.valueAtomic));
|
|
102192
102237
|
const inputsAtomic = settling.length === 1 ? sum2(only.inputs.map((commitment) => unspent.get(commitment).valueAtomic)) : 0n;
|
|
102193
|
-
const
|
|
102238
|
+
const changeAtomic = inputsAtomic - (settling.length === 1 ? only.amountAtomic : 0n);
|
|
102239
|
+
const changeFreeAtomic = sendHold === null || sendHold.unpacked.length === 0 ? changeAtomic : changeAtomic > privateSendPending ? changeAtomic - privateSendPending : 0n;
|
|
102240
|
+
const changeOnly = settling.length === 1 && only.join !== true && only.exit !== true && reservedAtomic === 0n && detail.joiningAtomic === "0" && successionMovableAtomic === 0n && sendHeldAtomic !== null && unspentAtomic - sendHeldAtomic === inputsAtomic && inputsAtomic > only.amountAtomic && changeFreeAtomic > 0n;
|
|
102194
102241
|
return report(
|
|
102195
102242
|
"stale",
|
|
102196
102243
|
spendable + successionMovableAtomic,
|
|
@@ -102199,7 +102246,7 @@ If a payment to this wallet settled, read the chain again with:
|
|
|
102199
102246
|
// still settling" while the only answered item was a join).
|
|
102200
102247
|
settlingRecent ? movedInAtomic === 0n && settling.length > 0 && settling.every((payment) => payment.join) ? "account_join" : "payment_settling" : movedInAtomic > 0n ? "pool_move" : void 0,
|
|
102201
102248
|
largest,
|
|
102202
|
-
changeOnly ?
|
|
102249
|
+
changeOnly ? changeFreeAtomic : void 0
|
|
102203
102250
|
);
|
|
102204
102251
|
}
|
|
102205
102252
|
return report("current", spendable + successionMovableAtomic, next, void 0, largest);
|
|
@@ -102214,7 +102261,7 @@ function savedSpendInputs({ store, snapshotRead }) {
|
|
|
102214
102261
|
}
|
|
102215
102262
|
function savedSendHold({ store, snapshotRead }) {
|
|
102216
102263
|
try {
|
|
102217
|
-
if (privateSendPendingAtomic(store) === 0n) return { accounts: /* @__PURE__ */ new
|
|
102264
|
+
if (privateSendPendingAtomic(store) === 0n) return { accounts: /* @__PURE__ */ new Map(), notes: /* @__PURE__ */ new Set(), sends: [], unpacked: [] };
|
|
102218
102265
|
const report = computeBalance({ store, snapshotRead: snapshotRead ?? readBalanceSnapshot(store) });
|
|
102219
102266
|
return report.status === "current" && SPEND_INPUTS.has(report) ? sendHoldOf(report) ?? null : null;
|
|
102220
102267
|
} catch {
|
|
@@ -103214,6 +103261,7 @@ function floatFetch(base, seen) {
|
|
|
103214
103261
|
code: code2,
|
|
103215
103262
|
...Number.isFinite(retryAfter) && retryAfter > 0 ? { retryAfterSeconds: Math.min(Math.ceil(retryAfter), 3600) } : {},
|
|
103216
103263
|
...DECIMAL3.test(String(answer.largestAtomic ?? "")) ? { largestAtomic: String(answer.largestAtomic) } : {},
|
|
103264
|
+
...typeof answer.reason === "string" && /^[a-z_]{1,60}$/.test(answer.reason) ? { reason: answer.reason } : {},
|
|
103217
103265
|
...typeof answer.message === "string" ? { message: plainText(answer.message) } : {}
|
|
103218
103266
|
};
|
|
103219
103267
|
return new Response(null, { status: 400 });
|
|
@@ -103232,8 +103280,9 @@ function floatRefusalError(refusal3, record) {
|
|
|
103232
103280
|
return Object.assign(new Error("p03_float_busy_retry_later"), { retryAfterSeconds: 30, ...extra });
|
|
103233
103281
|
case "float_price_above_capacity":
|
|
103234
103282
|
return Object.assign(new Error("p03_float_price_above_capacity"), extra);
|
|
103283
|
+
// fee_payer_underfunded (0.3.113): the fee payer of the shared pockets needs the operator's SOL, so no retry soon helps.
|
|
103235
103284
|
case "float_not_ready":
|
|
103236
|
-
return Object.assign(new Error("p03_float_not_ready_retry_later"), { retryAfterSeconds: 60, ...extra });
|
|
103285
|
+
return refusal3.reason === "fee_payer_underfunded" ? Object.assign(new Error("p03_float_fee_account_low"), extra) : Object.assign(new Error("p03_float_not_ready_retry_later"), { retryAfterSeconds: 60, ...extra });
|
|
103237
103286
|
case "float_payment_in_flight":
|
|
103238
103287
|
return Object.assign(new Error("p03_float_payment_in_flight_retry_later"), { retryAfterSeconds: 60, ...extra });
|
|
103239
103288
|
case "float_already_paid":
|
|
@@ -103523,7 +103572,7 @@ async function payViaFloat({
|
|
|
103523
103572
|
};
|
|
103524
103573
|
store.writeWal(walName2, record);
|
|
103525
103574
|
mark("seller-sent");
|
|
103526
|
-
const
|
|
103575
|
+
const sentAtMs2 = Date.now();
|
|
103527
103576
|
const stopWaiting = new AbortController();
|
|
103528
103577
|
const watch = watchFloatTransfer({ record, fetchImpl, sleep: deps.floatStatusSleep, abort: () => stopWaiting.abort() });
|
|
103529
103578
|
const resendDispatchers = [];
|
|
@@ -103538,7 +103587,7 @@ async function payViaFloat({
|
|
|
103538
103587
|
if (wasKept) keptAgain();
|
|
103539
103588
|
const verdict = watch.verdict();
|
|
103540
103589
|
if (verdict?.state === "dead") {
|
|
103541
|
-
const sellerUnansweredSeconds = Math.round((Date.now() -
|
|
103590
|
+
const sellerUnansweredSeconds = Math.round((Date.now() - sentAtMs2) / 1e3);
|
|
103542
103591
|
const { ambiguous: _settled, ...rest } = record;
|
|
103543
103592
|
record = {
|
|
103544
103593
|
...rest,
|
|
@@ -103680,7 +103729,7 @@ async function payViaFloat({
|
|
|
103680
103729
|
...state?.state === "landed" ? { transferLanded: true } : {}
|
|
103681
103730
|
});
|
|
103682
103731
|
}
|
|
103683
|
-
const late2 = x402Header(response, "payment-response")?.success === false ? { sellerChargeFailed: true, sellerAnswerSeconds: Math.round((answeredAtMs -
|
|
103732
|
+
const late2 = x402Header(response, "payment-response")?.success === false ? { sellerChargeFailed: true, sellerAnswerSeconds: Math.round((answeredAtMs - sentAtMs2) / 1e3) } : {};
|
|
103684
103733
|
const fixable = floatSellerCanBeFixed({ httpStatus: response.status, ...sellerReason ? { sellerReason } : {}, ...late2 }) ? { sellerFixable: true } : {};
|
|
103685
103734
|
byVerdict(
|
|
103686
103735
|
await floatVerdict(record, fetchImpl, statusSleep, verdictUntil(answeredAtMs), watch.verdict()),
|
|
@@ -106348,28 +106397,31 @@ function promisedShortfall(store, amountAtomic) {
|
|
|
106348
106397
|
}
|
|
106349
106398
|
return void 0;
|
|
106350
106399
|
}
|
|
106351
|
-
function heldByPrivateSendText(sends) {
|
|
106400
|
+
function heldByPrivateSendText(sends, freeAtomic) {
|
|
106352
106401
|
const named = Array.isArray(sends) ? sends.filter((send3) => typeof send3?.requestId === "string") : [];
|
|
106402
|
+
const most = /^\d+$/.test(String(freeAtomic ?? "")) ? `One payment can use at most ${usdcWords(freeAtomic)} now, and this payment needs more. ` : "One payment cannot use this much now. ";
|
|
106403
|
+
const frees = "keeps nothing after its last part goes; an earlier part may free some money, and wallet_balance shows the most one payment can use (largestPaymentAtomic).";
|
|
106353
106404
|
if (named.length === 0) {
|
|
106354
|
-
return
|
|
106405
|
+
return `${most}A private send in progress keeps part of this money for its unsent parts; wallet_balance names it and its cancel call. The send ${frees} To pay now, stop the send, or add money with wallet_add_funds.`;
|
|
106355
106406
|
}
|
|
106356
106407
|
if (named.length === 1) {
|
|
106357
|
-
|
|
106408
|
+
const send3 = sendWords(named[0]);
|
|
106409
|
+
return `${most}${send3[0].toUpperCase()}${send3.slice(1)} keeps part of this money for its unsent parts. It ${frees} To pay now, stop the send with ${cancelCall(named[0])}, or add money with wallet_add_funds.`;
|
|
106358
106410
|
}
|
|
106359
|
-
return
|
|
106411
|
+
return `${most}${named.map(sendWords).join(" and ").replace(/^t/, "T")} keep part of this money for their unsent parts. Each ${frees} To pay now, stop a send with ${named.map(cancelCall).join(", or ")}, or add money with wallet_add_funds.`;
|
|
106360
106412
|
}
|
|
106361
106413
|
function promisedShortfallText(shortfall, amountAtomic) {
|
|
106362
106414
|
if (shortfall.error === "spend_private_send_unknown") {
|
|
106363
106415
|
return "spend_private_send_unknown: a private send of this wallet cannot be read, so the value it still owes is unknown; nothing was sent";
|
|
106364
106416
|
}
|
|
106365
|
-
if (shortfall.error === HELD_BY_PRIVATE_SEND) return `${HELD_BY_PRIVATE_SEND}: ${heldByPrivateSendText(shortfall.privateSends)} Nothing was sent.`;
|
|
106417
|
+
if (shortfall.error === HELD_BY_PRIVATE_SEND) return `${HELD_BY_PRIVATE_SEND}: ${heldByPrivateSendText(shortfall.privateSends, shortfall.freeAtomic)} Nothing was sent.`;
|
|
106366
106418
|
return `spend_private_send_reserved: ${usdcWords(shortfall.pendingAtomic)} of the private balance is promised to the unsent smaller payments of a private send; ${usdcWords(shortfall.freeAtomic)} is free and this unshield needs ${usdcWords(amountAtomic)}; nothing was sent`;
|
|
106367
106419
|
}
|
|
106368
106420
|
function assertUnshieldNotPromised(store, amountAtomic) {
|
|
106369
106421
|
const shortfall = promisedShortfall(store, amountAtomic);
|
|
106370
106422
|
if (shortfall) throw Object.assign(new Error(promisedShortfallText(shortfall, amountAtomic)), shortfall.privateSends ? { privateSends: shortfall.privateSends } : {});
|
|
106371
106423
|
}
|
|
106372
|
-
var HELD_BY_PRIVATE_SEND, cancelCall;
|
|
106424
|
+
var HELD_BY_PRIVATE_SEND, cancelCall, sendWords;
|
|
106373
106425
|
var init_promised = __esm({
|
|
106374
106426
|
"wallet/src/unshield/promised.mjs"() {
|
|
106375
106427
|
"use strict";
|
|
@@ -106378,6 +106430,11 @@ var init_promised = __esm({
|
|
|
106378
106430
|
init_usdcWords();
|
|
106379
106431
|
HELD_BY_PRIVATE_SEND = "p03_merchant_respend_value_held_by_private_send";
|
|
106380
106432
|
cancelCall = (send3) => send3.tool === "wallet_transfer_token" ? `wallet_transfer_token_status with request_id "${send3.requestId}" and action "cancel"` : send3.tool === "cli" ? `the command line: unshield-cancel --unshield-id ${send3.sendId}` : `wallet_cancel with request_id "${send3.requestId}"`;
|
|
106433
|
+
sendWords = (send3) => {
|
|
106434
|
+
const amount = /^[1-9][0-9]*$/.test(String(send3?.amountAtomic ?? "")) ? ` of ${usdcWords(send3.amountAtomic)}` : "";
|
|
106435
|
+
const to = typeof send3?.to === "string" && send3.to.length > 10 ? ` to ${send3.to.slice(0, 4)}...${send3.to.slice(-4)}` : "";
|
|
106436
|
+
return `the private send${amount}${to}`;
|
|
106437
|
+
};
|
|
106381
106438
|
}
|
|
106382
106439
|
});
|
|
106383
106440
|
|
|
@@ -106767,7 +106824,7 @@ async function assertNotPromised({ session, store, amountAtomic, leasedAt, mark,
|
|
|
106767
106824
|
ok: false,
|
|
106768
106825
|
error: "spend_private_send_reserved",
|
|
106769
106826
|
detail: `${usdcWords(pending)} of the private balance is promised to the unsent smaller payments of a private send; ${usdcWords(free)} is free and this payment needs ${usdcWords(amountAtomic)}; nothing was paid`,
|
|
106770
|
-
next:
|
|
106827
|
+
next: "Tell the user why nothing was paid and what they can do. This payment needs more than the money the private send does not keep, and the money it keeps leaves the wallet as its parts go, so a wait frees nothing. Stop its unsent parts with the cancel call wallet_balance names for it (that money stays in the wallet), or add money with wallet_add_funds, then pay again with the same request_id"
|
|
106771
106828
|
});
|
|
106772
106829
|
}
|
|
106773
106830
|
const hold = sendHoldOf(report);
|
|
@@ -106775,8 +106832,8 @@ async function assertNotPromised({ session, store, amountAtomic, leasedAt, mark,
|
|
|
106775
106832
|
throw Object.assign(new SpendRefusalError({
|
|
106776
106833
|
ok: false,
|
|
106777
106834
|
error: HELD_BY_PRIVATE_SEND,
|
|
106778
|
-
detail: `${heldByPrivateSendText(hold.sends)} Nothing was paid.`,
|
|
106779
|
-
next: "Tell the user why nothing was paid and what they can do.
|
|
106835
|
+
detail: `${heldByPrivateSendText(hold.sends, hold.freeAtomic)} Nothing was paid.`,
|
|
106836
|
+
next: "Tell the user why nothing was paid and what they can do. One payment cannot use this much now beside what the private send keeps for its unsent parts. The send keeps nothing after its last part goes, and an earlier part may free some money: pay again with the same request_id when wallet_balance largestPaymentAtomic covers this payment, after a stop of the send, or after new money is private",
|
|
106780
106837
|
privateSends: hold.sends
|
|
106781
106838
|
}), { privateSends: hold.sends });
|
|
106782
106839
|
}
|
|
@@ -108801,12 +108858,14 @@ function heldBySendLine(error) {
|
|
|
108801
108858
|
for (let link2 = error, depth = 0; link2 instanceof Error && depth < 8; link2 = link2.cause, depth += 1) {
|
|
108802
108859
|
if (!String(link2.message).startsWith(HELD_BY_PRIVATE_SEND)) continue;
|
|
108803
108860
|
const sends = Array.isArray(link2.privateSends) ? link2.privateSends.filter((one) => typeof one?.requestId === "string" && typeof one.sendId === "string") : [];
|
|
108861
|
+
const frees = "It keeps nothing after its last part goes; an earlier part may free some money (shinjuku balance shows it).";
|
|
108804
108862
|
if (sends.length === 0) {
|
|
108805
|
-
return
|
|
108863
|
+
return `Nothing was sent. One payment cannot use this much now. A private send in progress keeps part of this money for its unsent parts. ${frees} To send now, stop that send (shinjuku unshield-cancel --unshield-id <its id>; a token transfer: shinjuku transfer-token --id <its id> --cancel), or add money with shinjuku add-funds.`;
|
|
108806
108864
|
}
|
|
108807
108865
|
const many = sends.length > 1;
|
|
108808
|
-
const stops = sends.map((one) => one.tool === "wallet_transfer_token" ? `shinjuku transfer-token --id ${one.requestId} --cancel` : `shinjuku unshield-cancel --unshield-id ${one.sendId}`);
|
|
108809
|
-
|
|
108866
|
+
const stops = sends.map((one) => `${one.tool === "wallet_transfer_token" ? `shinjuku transfer-token --id ${one.requestId} --cancel` : `shinjuku unshield-cancel --unshield-id ${one.sendId}`} (${sendWords(one)})`);
|
|
108867
|
+
const named = sends.map(sendWords).join(" and ");
|
|
108868
|
+
return `Nothing was sent. One payment cannot use this much now. ${named[0].toUpperCase()}${named.slice(1)} ${many ? "keep" : "keeps"} part of this money for ${many ? "their" : "its"} unsent parts. ${many ? frees.replace(/^It keeps/, "Each keeps") : frees} To send now, stop the send with ${stops.join(", or ")}, or add money with shinjuku add-funds.`;
|
|
108810
108869
|
}
|
|
108811
108870
|
return void 0;
|
|
108812
108871
|
}
|
|
@@ -119435,16 +119494,15 @@ function plainSentence(next, room) {
|
|
|
119435
119494
|
}
|
|
119436
119495
|
return "";
|
|
119437
119496
|
}
|
|
119438
|
-
function heldBySendSay(
|
|
119439
|
-
|
|
119440
|
-
return send3 ? `Nothing was ${verb}. Your private send ${send3.requestId} set this money aside for its next payment; stop that send to pay now, or add money.` : `Nothing was ${verb}. A private send in progress set this money aside. Stop that send to pay now, or add money.`;
|
|
119497
|
+
function heldBySendSay(verb) {
|
|
119498
|
+
return `Nothing was ${verb}. A private send in progress set this money aside. Stop that send to pay now, or add money.`;
|
|
119441
119499
|
}
|
|
119442
119500
|
function refusalSay(a, tool, again, npmVersion) {
|
|
119443
119501
|
const code2 = str(a.error);
|
|
119444
119502
|
const detail = str(a.detail);
|
|
119445
119503
|
const next = str(a.next);
|
|
119446
119504
|
const moneyVerb = MOVE_CAP_CODES.has(code2) || tool === "wallet_shield" || tool === "wallet_unshield" ? "moved" : "paid";
|
|
119447
|
-
const ask =
|
|
119505
|
+
const ask = "Ask again";
|
|
119448
119506
|
if (/_refund_pending$/.test(code2)) {
|
|
119449
119507
|
const total2 = usdcText2(a.refundAtomic ?? a.paidAtomic);
|
|
119450
119508
|
const when = Number.isSafeInteger(a.refundEtaSeconds) && a.refundEtaSeconds > 0 ? ` within about ${minutesText(Math.ceil(a.refundEtaSeconds / 60))}` : "";
|
|
@@ -119461,14 +119519,13 @@ function refusalSay(a, tool, again, npmVersion) {
|
|
|
119461
119519
|
if (a.refundArrived === true) return `The seller did not take it. ${yours} is back in your private balance. ${other}`;
|
|
119462
119520
|
return `The seller did not take it; ${total2 ? `${total2} USDC` : "your money"} comes back by itself${when}. ${other}`;
|
|
119463
119521
|
}
|
|
119464
|
-
const askAgain =
|
|
119522
|
+
const askAgain = "Asking again pays again.";
|
|
119465
119523
|
if (code2 === "p03_float_receipt_pruned" && a.conversationNotKept === true) {
|
|
119466
119524
|
return `Paid once, not again: the wallet keeps no copy of a private conversation. ${askAgain}`;
|
|
119467
119525
|
}
|
|
119468
119526
|
if (code2 === "p03_float_receipt_pruned") return `This request was paid more than 10 minutes ago. ${askAgain}`;
|
|
119469
119527
|
if (/^p03_(float|resource_payment)_request_(id_conflict|data_mismatch)$/.test(code2)) {
|
|
119470
|
-
|
|
119471
|
-
return `Nothing was paid: this request_id belongs to an earlier payment. For this request, ask again with ${fresh}.`;
|
|
119528
|
+
return "Nothing was paid: this request matched an earlier payment with other details. Ask again to pay for this one.";
|
|
119472
119529
|
}
|
|
119473
119530
|
if (code2 === "p03_resource_payment_memory_only_needs_float") {
|
|
119474
119531
|
return "Nothing was paid: this seller now asks a payment whose record would keep your words, and a private call never pays that way. Ask again.";
|
|
@@ -119530,6 +119587,7 @@ function refusalSay(a, tool, again, npmVersion) {
|
|
|
119530
119587
|
if (/_retry_same_request$/.test(code2)) {
|
|
119531
119588
|
return a.paid === true ? `Paid, but the seller has not answered yet. ${again}` : `The result is not known yet. ${again}`;
|
|
119532
119589
|
}
|
|
119590
|
+
if (code2 === "p03_float_fee_account_low") return "Nothing was paid. The payment service's network fee account is low; its operator was alerted. Try again later.";
|
|
119533
119591
|
if (BUSY.test(code2)) {
|
|
119534
119592
|
const said = /in about ([0-9]{1,4}) s\b/.exec(next);
|
|
119535
119593
|
const seconds2 = Number.isFinite(a.readyInSeconds) && a.readyInSeconds > 0 ? Math.ceil(a.readyInSeconds) : said ? Number(said[1]) : 30;
|
|
@@ -119568,7 +119626,7 @@ function refusalSay(a, tool, again, npmVersion) {
|
|
|
119568
119626
|
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.";
|
|
119569
119627
|
if (code2 === "mcp_restart_needed") return "Nothing was paid. Restart this app, then try again.";
|
|
119570
119628
|
if (code2 === "p03_merchant_respend_value_held_by_private_send") {
|
|
119571
|
-
return heldBySendSay(
|
|
119629
|
+
return heldBySendSay(tool === "wallet_unshield" || tool === "wallet_transfer_token" || tool === "wallet_transfer_token_status" ? "sent" : "paid");
|
|
119572
119630
|
}
|
|
119573
119631
|
if (/accounts_split/.test(code2) || /accounts_split/.test(detail) || typeof a.joining === "boolean") {
|
|
119574
119632
|
const verb = tool === "wallet_unshield" ? "sent" : "paid";
|
|
@@ -119837,8 +119895,7 @@ function heldByPaymentSay(detail) {
|
|
|
119837
119895
|
if (!items.length) return "";
|
|
119838
119896
|
const held = usdcText2(detail.unspentAtomic);
|
|
119839
119897
|
const what = positive(held) ? `${held} USDC is` : "Your USDC is";
|
|
119840
|
-
|
|
119841
|
-
return id ? `${what} held by an unfinished payment (request_id ${id}). Ask me to finish it, or to close it with wallet_cancel.` : `${what} held by an unfinished payment. Ask me to finish it, or to close it with wallet_cancel.`;
|
|
119898
|
+
return `${what} held by an unfinished payment. Ask me to finish it, or to close it with wallet_cancel.`;
|
|
119842
119899
|
}
|
|
119843
119900
|
function ownWorkWords(lockedBy) {
|
|
119844
119901
|
return typeof lockedBy === "string" && Object.hasOwn(OWN_WORK_WORDS, lockedBy) ? OWN_WORK_WORDS[lockedBy] : void 0;
|
|
@@ -119914,25 +119971,29 @@ function balanceLine(a, room = SAY_MAX_WORDS) {
|
|
|
119914
119971
|
const going = sends.find((send3) => Number.isSafeInteger(send3.failedTries) && send3.failedTries > 0) ?? sends[0];
|
|
119915
119972
|
if (going && !moving) {
|
|
119916
119973
|
const left = usdcText2(going.leftAtomic) ?? "";
|
|
119974
|
+
const total = usdcText2(going.amountAtomic);
|
|
119975
|
+
const to = typeof going.to === "string" && going.to.length > 10 ? ` to ${going.to.slice(0, 4)}...${going.to.slice(-4)}` : "";
|
|
119976
|
+
const named = `your private send${total ? ` of ${total} USDC` : ""}${to}`;
|
|
119977
|
+
const short = `your private send${to}`;
|
|
119917
119978
|
if (Number.isSafeInteger(going.failedTries) && going.failedTries > 0) {
|
|
119918
119979
|
const tries = `${going.failedTries} ${going.failedTries === 1 ? "try" : "tries"}`;
|
|
119919
119980
|
return have(
|
|
119920
|
-
`;
|
|
119921
|
-
`;
|
|
119981
|
+
`; ${named} has ${left} USDC not sent: its next payment did not go through (${tries}).`,
|
|
119982
|
+
`; ${short}: next payment did not go through (${tries}).`,
|
|
119922
119983
|
"; a private send's next payment did not go through yet."
|
|
119923
119984
|
);
|
|
119924
119985
|
}
|
|
119925
119986
|
if (!(Number.isSafeInteger(going.nextPaymentInMinutes) && going.nextPaymentInMinutes > 0)) {
|
|
119926
119987
|
return have(
|
|
119927
|
-
`;
|
|
119928
|
-
`;
|
|
119988
|
+
`; ${named} has ${left} USDC not sent yet, and the wallet tries its next payment again by itself.`,
|
|
119989
|
+
`; ${short}: ${left} USDC not sent yet.`,
|
|
119929
119990
|
"; a private send is not all sent yet."
|
|
119930
119991
|
);
|
|
119931
119992
|
}
|
|
119932
119993
|
const when = `in about ${minutesText(going.nextPaymentInMinutes)}`;
|
|
119933
119994
|
return have(
|
|
119934
|
-
`;
|
|
119935
|
-
`;
|
|
119995
|
+
`; ${named} has ${left} USDC left to go, and its next payment goes ${when}.`,
|
|
119996
|
+
`; ${short}: next payment ${when}.`,
|
|
119936
119997
|
`; a private send's next payment goes ${when}.`
|
|
119937
119998
|
);
|
|
119938
119999
|
}
|
|
@@ -119986,6 +120047,7 @@ function previewReason(a, npmVersion) {
|
|
|
119986
120047
|
return raiseLine("--max-session", npmVersion, `over your 24-hour limit of ${usdcText2(a.capAtomic)} USDC.`, SAY_MAX_WORDS - 3);
|
|
119987
120048
|
}
|
|
119988
120049
|
if (OWNER_LIMIT_CODES.has(code2)) return "it is above a spending limit set for this wallet.";
|
|
120050
|
+
if (code2 === "p03_float_fee_account_low") return "the payment service's network fee account is low; try again later.";
|
|
119989
120051
|
if (BUSY.test(code2)) return "the payment service is busy; try again in a minute.";
|
|
119990
120052
|
if (code2 === "mcp_wallet_unreadable" || code2 === "p03_float_config_unreadable") return "the price could not be checked just now; try again in a minute.";
|
|
119991
120053
|
const sentence2 = plainSentence(a.detail, SAY_MAX_WORDS - 4);
|
|
@@ -120034,8 +120096,7 @@ function transferSay(a) {
|
|
|
120034
120096
|
const kept2 = a.send?.keptPrivateAtomic && a.send.keptPrivateAtomic !== "0" ? usdcText2(a.send.keptPrivateAtomic) : null;
|
|
120035
120097
|
const later = "If this chat ends first, it continues at your next request.";
|
|
120036
120098
|
if (a.replayed === true) {
|
|
120037
|
-
|
|
120038
|
-
return `This request_id belongs to an earlier transfer to ${to}; this call moved nothing. To transfer again, ask with ${fresh}.`;
|
|
120099
|
+
return `This request matched an earlier transfer to ${to}; this call moved nothing. Ask again to transfer again.`;
|
|
120039
120100
|
}
|
|
120040
120101
|
switch (a.stage) {
|
|
120041
120102
|
case "selling":
|
|
@@ -120046,7 +120107,7 @@ function transferSay(a) {
|
|
|
120046
120107
|
// At most 24 words with the kept part (SAY_MAX_WORDS 25). A send step that stopped (tools.mjs transferAnswer sendStop,
|
|
120047
120108
|
// 0.3.109 fault 5) says why first: money another send set aside, or money the wallet gets ready by itself.
|
|
120048
120109
|
case "sending":
|
|
120049
|
-
if (Array.isArray(a.privateSends)) return heldBySendSay(
|
|
120110
|
+
if (Array.isArray(a.privateSends)) return heldBySendSay("sent");
|
|
120050
120111
|
if (a.joining === true) return "Not sent yet: the wallet gets the money ready by itself. Ask again in a few minutes; do not cancel.";
|
|
120051
120112
|
return sent ? `Sending ${sent} USDC (not the token) privately to ${to}${kept2 ? `; ${kept2} USDC stays private` : ""}. ${later}` : `Sending ${usdc6} privately to ${to}. It gets USDC, not the token. ${later}`;
|
|
120052
120113
|
case "sold_waiting_room":
|
|
@@ -120089,8 +120150,7 @@ function stoppedSay(a) {
|
|
|
120089
120150
|
}
|
|
120090
120151
|
function build(a, tool, npmVersion) {
|
|
120091
120152
|
if (!a || typeof a !== "object" || Array.isArray(a)) return void 0;
|
|
120092
|
-
const
|
|
120093
|
-
const again = id ? `Ask again with request_id ${id}; it never pays twice.` : "Ask again with the same request_id; it never pays twice.";
|
|
120153
|
+
const again = "Ask again; it never pays twice.";
|
|
120094
120154
|
if (a.ok === false) return refusalSay(a, tool, again, npmVersion);
|
|
120095
120155
|
if (TRANSFER_TOOLS.has(tool) || tool === void 0 && a.delivers === "USDC" && (a.token || Array.isArray(a.transfers))) return transferSay(a);
|
|
120096
120156
|
if (tool === "wallet_receive_shielded" || tool === void 0 && typeof a.receiveShielded === "string") {
|
|
@@ -120133,7 +120193,7 @@ function build(a, tool, npmVersion) {
|
|
|
120133
120193
|
return `${what} The wallet first gets your whole balance ready to send${steps}, then sends it.`;
|
|
120134
120194
|
}
|
|
120135
120195
|
const head = `Not sent yet: the wallet is getting your balance ready to send${steps}.`;
|
|
120136
|
-
const ask =
|
|
120196
|
+
const ask = "Ask again until it sends";
|
|
120137
120197
|
return [`${head} ${ask}; it never sends twice.`, `${head} ${ask}.`].find((line) => words(line) <= SAY_MAX_WORDS) ?? head;
|
|
120138
120198
|
}
|
|
120139
120199
|
if (typeof a.to === "string" && a.to && Object.hasOwn(a, "stage")) {
|
|
@@ -120168,15 +120228,14 @@ function build(a, tool, npmVersion) {
|
|
|
120168
120228
|
if (typeof a.address === "string" && a.address && typeof a.stage === "string") return linkSay(a);
|
|
120169
120229
|
if (a.stage === "waiting_for_funds" && typeof a.depositAddress === "string") {
|
|
120170
120230
|
const send3 = usdcText2(a.sendAtomic ?? a.amountAtomic);
|
|
120171
|
-
return `Send exactly ${send3 ? `${send3} USDC` : "the amount"} on Solana to ${a.depositAddress} in one transfer. Then ask again
|
|
120231
|
+
return `Send exactly ${send3 ? `${send3} USDC` : "the amount"} on Solana to ${a.depositAddress} in one transfer. Then ask again.`;
|
|
120172
120232
|
}
|
|
120173
120233
|
const shieldJob = SHIELD_TOOLS.has(tool) || tool === void 0 && Object.hasOwn(a, "amountAtomic") && Object.hasOwn(a, "stage") && !Object.hasOwn(a, "paid");
|
|
120174
120234
|
if (shieldJob && typeof a.stage === "string") {
|
|
120175
120235
|
const amount = usdcText2(a.amountAtomic);
|
|
120176
120236
|
const what = amount ? `${amount} USDC` : "The USDC";
|
|
120177
120237
|
if (a.done === true && a.replayed === true) {
|
|
120178
|
-
|
|
120179
|
-
return `This request_id finished earlier (${what} made private then); this call moved nothing. To shield more, ask again with ${fresh}.`;
|
|
120238
|
+
return `This request finished earlier (${what} made private then); this call moved nothing. Ask again to shield more.`;
|
|
120180
120239
|
}
|
|
120181
120240
|
if (a.done === true) return withBalance(`${what} is now private.`, a);
|
|
120182
120241
|
if (a.stage === "waiting" && a.code === "mcp_balance_unknown") {
|
|
@@ -120189,14 +120248,14 @@ function build(a, tool, npmVersion) {
|
|
|
120189
120248
|
}
|
|
120190
120249
|
if (tool === "wallet_receipts" && Number.isSafeInteger(a.count)) {
|
|
120191
120250
|
const arrived = Array.isArray(a.receipts) ? a.receipts.find((row) => row?.kind === "add-funds" && /^[1-9][0-9]*$/.test(String(row.heldAtomic ?? ""))) : void 0;
|
|
120192
|
-
if (arrived) return `${a.count} ${a.count === 1 ? "entry" : "entries"}. ${usdcText2(arrived.heldAtomic)} USDC reached add-funds address
|
|
120251
|
+
if (arrived) return `${a.count} ${a.count === 1 ? "entry" : "entries"}. ${usdcText2(arrived.heldAtomic)} USDC reached an add-funds address and becomes private by itself.`;
|
|
120193
120252
|
return a.count === 0 ? "No receipts or wallet moves yet." : `${a.count} ${a.count === 1 ? "entry" : "entries, newest first"}. Each payment names its seller; pay.shinjukustaition.com is Shinjuku, the private payment service.`;
|
|
120194
120253
|
}
|
|
120195
120254
|
if (Array.isArray(a.models) && a.models.length > 0 && a.paid === void 0) {
|
|
120196
120255
|
const count2 = `${a.models.length} AI ${a.models.length === 1 ? "model is" : "models are"}`;
|
|
120197
120256
|
return a.ready === false ? `Nothing was asked or paid. ${count2} listed, but asking one needs Tor on; the next step says how to turn it on.` : `Nothing was asked or paid. ${count2} ready: ask a question, and each answer is paid privately from your balance.`;
|
|
120198
120257
|
}
|
|
120199
|
-
if (a.done === false) return
|
|
120258
|
+
if (a.done === false) return "Still running. Ask again in about 30 seconds; it never moves money twice.";
|
|
120200
120259
|
return "Done.";
|
|
120201
120260
|
}
|
|
120202
120261
|
function sayFor(answer, { tool, npmVersion } = {}) {
|
|
@@ -120210,11 +120269,20 @@ function sayFor(answer, { tool, npmVersion } = {}) {
|
|
|
120210
120269
|
const parts = line.trim().split(/\s+/);
|
|
120211
120270
|
return parts.length <= SAY_MAX_WORDS ? line : `${parts.slice(0, SAY_MAX_WORDS).join(" ").replace(/[.;:,]+$/, "")}.`;
|
|
120212
120271
|
}
|
|
120213
|
-
function
|
|
120214
|
-
if (!output2 || typeof output2 !== "object" || output2.isError) return output2;
|
|
120272
|
+
function firstText(output2) {
|
|
120215
120273
|
const blocks = Array.isArray(output2.content) && output2.content.length ? output2.content : void 0;
|
|
120216
120274
|
const first = blocks?.[0];
|
|
120217
120275
|
const text3 = blocks ? first?.type === "text" && typeof first.text === "string" ? first.text : void 0 : typeof output2.text === "string" ? output2.text : void 0;
|
|
120276
|
+
return { blocks, first, text: text3 };
|
|
120277
|
+
}
|
|
120278
|
+
function withFirstText(output2, { blocks, first, text: text3 }, value2) {
|
|
120279
|
+
const out = JSON.stringify(value2, null, /^\s*\{\s*\n/.test(text3) ? 2 : void 0);
|
|
120280
|
+
return { ...output2, text: out, ...blocks ? { content: [{ ...first, text: out }, ...blocks.slice(1)] } : {} };
|
|
120281
|
+
}
|
|
120282
|
+
function addSay(output2, toolName, { news, usdcFields: fields = usdcFields, npmVersion } = {}) {
|
|
120283
|
+
if (!output2 || typeof output2 !== "object" || output2.isError) return output2;
|
|
120284
|
+
const block = firstText(output2);
|
|
120285
|
+
const { text: text3 } = block;
|
|
120218
120286
|
if (text3 === void 0 || SAY_FIRST.test(text3.slice(0, 64)) || !/^\s*\{/.test(text3)) return output2;
|
|
120219
120287
|
let parsed2;
|
|
120220
120288
|
try {
|
|
@@ -120245,8 +120313,22 @@ function addSay(output2, toolName, { news, usdcFields: fields = usdcFields, npmV
|
|
|
120245
120313
|
if (!Array.isArray(items)) items = [];
|
|
120246
120314
|
}
|
|
120247
120315
|
const value2 = { say: say3, ...plainFields(parsed2, toolName), ...usdc6 ? { usdc: usdc6 } : {}, ...items.length ? { news: items } : {} };
|
|
120248
|
-
|
|
120249
|
-
|
|
120316
|
+
return withFirstText(output2, block, value2);
|
|
120317
|
+
}
|
|
120318
|
+
function withKeepIdNote(output2) {
|
|
120319
|
+
if (!output2 || typeof output2 !== "object" || output2.isError) return output2;
|
|
120320
|
+
const block = firstText(output2);
|
|
120321
|
+
if (block.text === void 0 || !/^\s*\{/.test(block.text)) return output2;
|
|
120322
|
+
let parsed2;
|
|
120323
|
+
try {
|
|
120324
|
+
parsed2 = JSON.parse(block.text);
|
|
120325
|
+
} catch {
|
|
120326
|
+
return output2;
|
|
120327
|
+
}
|
|
120328
|
+
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;
|
|
120331
|
+
return withFirstText(output2, block, { ...parsed2, next: `${parsed2.next.replace(/[.\s]+$/, "")}. ${KEEP_ID_NOTE}` });
|
|
120250
120332
|
}
|
|
120251
120333
|
function plainFields(parsed2, toolName) {
|
|
120252
120334
|
const a = { ...parsed2 };
|
|
@@ -120271,9 +120353,9 @@ function plainFields(parsed2, toolName) {
|
|
|
120271
120353
|
return a;
|
|
120272
120354
|
}
|
|
120273
120355
|
function withSay(tool, options = {}) {
|
|
120274
|
-
return { ...tool, run: async (args, ctx) => addSay(await tool.run(args, ctx), tool.name, options) };
|
|
120356
|
+
return { ...tool, run: async (args, ctx) => withKeepIdNote(addSay(await tool.run(args, ctx), tool.name, options)) };
|
|
120275
120357
|
}
|
|
120276
|
-
var SAY_MAX_WORDS, DECIMALS2, ATOMIC4, SAY_FIRST, SAY_BANNED, CODE_TOKEN, LONG_NUMBER, MOVE_LINE, minutesText, ageWords, MOVING_ROLES, CLOSE_LATER, PAY_CAP_CODES, raiseLine, MOVE_CAP_CODES, OWNER_LIMIT_CODES, INSUFFICIENT, BUSY, SHIELD_TOOLS, words, positive, str, OWN_WORK_WORDS, DISCOVER_LIST_NAMES, TRANSFER_TOOLS, CONFIRMED_SEND_TOOLS;
|
|
120358
|
+
var SAY_MAX_WORDS, DECIMALS2, ATOMIC4, SAY_FIRST, SAY_BANNED, CODE_TOKEN, LONG_NUMBER, MOVE_LINE, minutesText, ageWords, MOVING_ROLES, CLOSE_LATER, PAY_CAP_CODES, raiseLine, MOVE_CAP_CODES, OWNER_LIMIT_CODES, INSUFFICIENT, BUSY, SHIELD_TOOLS, words, positive, str, OWN_WORK_WORDS, DISCOVER_LIST_NAMES, TRANSFER_TOOLS, CONFIRMED_SEND_TOOLS, KEEP_ID_NOTE;
|
|
120277
120359
|
var init_say = __esm({
|
|
120278
120360
|
"wallet/src/mcp/say.mjs"() {
|
|
120279
120361
|
"use strict";
|
|
@@ -120345,6 +120427,7 @@ var init_say = __esm({
|
|
|
120345
120427
|
});
|
|
120346
120428
|
TRANSFER_TOOLS = /* @__PURE__ */ new Set(["wallet_transfer_token", "wallet_transfer_token_status"]);
|
|
120347
120429
|
CONFIRMED_SEND_TOOLS = /* @__PURE__ */ new Set(["wallet_unshield", "wallet_transfer_token", "wallet_transfer_token_status"]);
|
|
120430
|
+
KEEP_ID_NOTE = "Keep request_id values for your own calls; never show one to the user.";
|
|
120348
120431
|
}
|
|
120349
120432
|
});
|
|
120350
120433
|
|
|
@@ -122548,6 +122631,9 @@ function paidAnswerContent({
|
|
|
122548
122631
|
}
|
|
122549
122632
|
if (text3.length > maxTextChars) {
|
|
122550
122633
|
const saved2 = save(data, OTHER_EXT[declared] ?? "txt", saveDir, now, sha25610);
|
|
122634
|
+
if (typeof meta.say === "string") {
|
|
122635
|
+
meta.say = `${meta.say} The answer is long: these are its first ${maxTextChars.toLocaleString("en-US")} of ${text3.length.toLocaleString("en-US")} characters${saved2.savedPath ? `; the whole answer is in ${saved2.savedPath}` : ""}.`;
|
|
122636
|
+
}
|
|
122551
122637
|
Object.assign(meta, {
|
|
122552
122638
|
body: text3.slice(0, maxTextChars),
|
|
122553
122639
|
bodyTruncated: true,
|
|
@@ -122580,7 +122666,7 @@ var init_answer = __esm({
|
|
|
122580
122666
|
"use strict";
|
|
122581
122667
|
init_fs();
|
|
122582
122668
|
DEFAULT_MAX_INLINE_BYTES = 4e6;
|
|
122583
|
-
DEFAULT_MAX_TEXT_CHARS =
|
|
122669
|
+
DEFAULT_MAX_TEXT_CHARS = 2e4;
|
|
122584
122670
|
MAX_IMAGE_URLS = 20;
|
|
122585
122671
|
MAX_JSON_DEPTH = 8;
|
|
122586
122672
|
RASTER = Object.freeze({
|
|
@@ -125409,7 +125495,13 @@ function refusedReason(record) {
|
|
|
125409
125495
|
function heldSendsOf(error) {
|
|
125410
125496
|
for (let link2 = error, depth = 0; link2 && typeof link2 === "object" && depth < 8; link2 = link2.cause, depth += 1) {
|
|
125411
125497
|
if (!Array.isArray(link2.privateSends)) continue;
|
|
125412
|
-
return link2.privateSends.filter((send3) => typeof send3?.requestId === "string" && REQUEST_ID4.test(send3.requestId) && ["wallet_unshield", "wallet_transfer_token", "cli"].includes(send3.tool) && (send3.tool !== "cli" || REQUEST_ID4.test(String(send3.sendId ?? "")))).map((send3) => ({
|
|
125498
|
+
return link2.privateSends.filter((send3) => typeof send3?.requestId === "string" && REQUEST_ID4.test(send3.requestId) && ["wallet_unshield", "wallet_transfer_token", "cli"].includes(send3.tool) && (send3.tool !== "cli" || REQUEST_ID4.test(String(send3.sendId ?? "")))).map((send3) => ({
|
|
125499
|
+
requestId: send3.requestId,
|
|
125500
|
+
tool: send3.tool,
|
|
125501
|
+
...send3.tool === "cli" ? { sendId: send3.sendId } : {},
|
|
125502
|
+
...typeof send3.to === "string" && send3.to.length > 10 ? { to: send3.to } : {},
|
|
125503
|
+
.../^[1-9][0-9]*$/.test(String(send3.amountAtomic ?? "")) ? { amountAtomic: String(send3.amountAtomic) } : {}
|
|
125504
|
+
}));
|
|
125413
125505
|
}
|
|
125414
125506
|
return [];
|
|
125415
125507
|
}
|
|
@@ -125865,9 +125957,12 @@ async function runUnshield({
|
|
|
125865
125957
|
if (exit.settled === false && !await finishAnsweredExit({ session, store, name, exit, answer, onAnswered, onCheckPending, mark, scoped })) return answer;
|
|
125866
125958
|
mark("unshield-exited");
|
|
125867
125959
|
const exited = store.readWal(`self-pay-${unshieldId}`);
|
|
125868
|
-
store.writeWal(`self-pay-${unshieldId}`, { ...exited, state: "exited", exitTransaction: exit.signature, exitedAtMs: exited?.exitedAtMs ?? Date.now() });
|
|
125960
|
+
store.writeWal(`self-pay-${unshieldId}`, { ...exited, state: "exited", exitTransaction: exit.signature, exitedAtMs: exited?.exitedAtMs ?? exited?.exitAnsweredAtMs ?? Date.now() });
|
|
125869
125961
|
return answer;
|
|
125870
125962
|
}
|
|
125963
|
+
function sentAtMs(record) {
|
|
125964
|
+
return Number.isSafeInteger(record?.exitAnsweredAtMs) ? record.exitAnsweredAtMs : record?.exitedAtMs;
|
|
125965
|
+
}
|
|
125871
125966
|
async function finishAnsweredExit({ session, store, name, exit, answer, changeAtomic, onAnswered, onCheckPending, mark, scoped }) {
|
|
125872
125967
|
if (typeof onAnswered !== "function") {
|
|
125873
125968
|
await scoped("unshield-exit", () => exit.finish());
|
|
@@ -125972,7 +126067,7 @@ async function runDirectExit({
|
|
|
125972
126067
|
if (exit.settled === false && !await finishAnsweredExit({ session, store, name, exit, answer, changeAtomic, onAnswered, onCheckPending, mark, scoped })) return answer;
|
|
125973
126068
|
mark("unshield-exited");
|
|
125974
126069
|
const exited = store.readWal(name);
|
|
125975
|
-
store.writeWal(name, { ...exited, state: "exited", exitTransaction: exit.signature, exitedAtMs: exited?.exitedAtMs ?? Date.now() });
|
|
126070
|
+
store.writeWal(name, { ...exited, state: "exited", exitTransaction: exit.signature, exitedAtMs: exited?.exitedAtMs ?? exited?.exitAnsweredAtMs ?? Date.now() });
|
|
125976
126071
|
return answer;
|
|
125977
126072
|
}
|
|
125978
126073
|
function balanceFields(parts) {
|
|
@@ -127083,7 +127178,7 @@ function createWalletTools({
|
|
|
127083
127178
|
body: { type: "string", description: "Request body text (POST only)." },
|
|
127084
127179
|
max_payment: { type: "string", description: 'Optional: the most this call may pay, in USDC, like "0.05"; at most the spending limit.' },
|
|
127085
127180
|
max_payment_atomic: { type: "string", pattern: "^[1-9][0-9]*$", description: "The same in atomic units (1000000 = 1 USDC). Give max_payment or max_payment_atomic, not both with different values." },
|
|
127086
|
-
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "
|
|
127181
|
+
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional. Leave it out for a new payment (the answer names the id it made). Pass the request_id of an earlier answer only to resume that payment; it never pays twice." }
|
|
127087
127182
|
},
|
|
127088
127183
|
required: ["url"],
|
|
127089
127184
|
additionalProperties: false
|
|
@@ -127112,7 +127207,7 @@ ${canonical5}`;
|
|
|
127112
127207
|
log("MCP_PAY_JOINED");
|
|
127113
127208
|
return running;
|
|
127114
127209
|
}
|
|
127115
|
-
const task = payCall({ target, request, argument: argument2, requestId, given, calledAt, progress: progress3, canProgress, signal })
|
|
127210
|
+
const task = payCall({ target, request, argument: argument2, requestId, given, calledAt, progress: progress3, canProgress, signal });
|
|
127116
127211
|
if (joinKey !== void 0) {
|
|
127117
127212
|
paysRunning.set(joinKey, task);
|
|
127118
127213
|
task.then(() => paysRunning.delete(joinKey), () => paysRunning.delete(joinKey));
|
|
@@ -127336,7 +127431,6 @@ ${canonical5}`;
|
|
|
127336
127431
|
}
|
|
127337
127432
|
const { bytes: bytes2, truncated } = await readBody(response);
|
|
127338
127433
|
const payment = response.headers.get(PAYMENT_HEADER);
|
|
127339
|
-
const autoId = given ? void 0 : requestId;
|
|
127340
127434
|
if (!payment) {
|
|
127341
127435
|
const moved2 = movedTo(response, target.url);
|
|
127342
127436
|
return answerResult(paidAnswerContent({
|
|
@@ -127356,8 +127450,7 @@ ${canonical5}`;
|
|
|
127356
127450
|
detail: `the URL answered HTTP ${response.status} without asking for payment; nothing was paid`,
|
|
127357
127451
|
...moved2 ? { movedTo: moved2, next: `nothing was paid: this URL answered HTTP ${response.status}, which says it moved to ${moved2}, and gave no data. Tell the user it moved. If the user wants it, call x402_pay again with url "${moved2}", the same method, headers and body, and a NEW request_id` } : response.status >= 200 && response.status < 300 ? {} : { next: `nothing was paid: this URL answered HTTP ${response.status} and did not ask for payment, so it gave no data; check the URL, or pay another seller` }
|
|
127358
127452
|
},
|
|
127359
|
-
"x402_pay"
|
|
127360
|
-
autoId
|
|
127453
|
+
"x402_pay"
|
|
127361
127454
|
)
|
|
127362
127455
|
}));
|
|
127363
127456
|
}
|
|
@@ -127430,13 +127523,9 @@ ${canonical5}`;
|
|
|
127430
127523
|
...balanceAnswer(one),
|
|
127431
127524
|
...takeRefundNotices(),
|
|
127432
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"
|
|
127433
|
-
}, "x402_pay"
|
|
127526
|
+
}, "x402_pay")
|
|
127434
127527
|
}));
|
|
127435
127528
|
}
|
|
127436
|
-
const withIdSentence = (say3, id) => {
|
|
127437
|
-
const line = `${say3} Its request_id is ${id}.`;
|
|
127438
|
-
return line.trim().split(/\s+/).length <= SAY_MAX_WORDS ? line : say3;
|
|
127439
|
-
};
|
|
127440
127529
|
function networkFields() {
|
|
127441
127530
|
const mode = runNetworkMode();
|
|
127442
127531
|
let onion = false;
|
|
@@ -127447,9 +127536,8 @@ ${canonical5}`;
|
|
|
127447
127536
|
}
|
|
127448
127537
|
return { network: mode === "tor" ? { mode: "tor", detail: `every request of this wallet goes through Tor (checked at start)${onion ? "; the facilitator is reached over its onion service, so no Tor exit sees those requests" : ""}` } : mode === "proxy" ? { mode: "proxy", detail: "every request of this wallet goes through the proxy this wallet was started with; it is not checked as Tor" } : { mode: "direct", detail: `no Tor: the facilitator, the RPC provider and each seller see this computer's IP address. To hide it, the user runs ${terminalCommand2("setup --yes --prefer-tor")} once in a terminal (it records Tor and checks the wallet's files again; nothing else changes; if Tor is not running, it says how to start it), then closes this app and opens it again` } };
|
|
127449
127538
|
}
|
|
127450
|
-
function sayFirst(fields, tool
|
|
127451
|
-
|
|
127452
|
-
if (autoId) say3 = withIdSentence(say3, autoId);
|
|
127539
|
+
function sayFirst(fields, tool) {
|
|
127540
|
+
const say3 = sayFor(fields, { tool, npmVersion });
|
|
127453
127541
|
const usdc6 = usdcFields(fields);
|
|
127454
127542
|
let news = [];
|
|
127455
127543
|
try {
|
|
@@ -127459,21 +127547,19 @@ ${canonical5}`;
|
|
|
127459
127547
|
}
|
|
127460
127548
|
return { say: say3, ...fields, ...Object.keys(usdc6).length ? { usdc: usdc6 } : {}, ...Array.isArray(news) && news.length ? { news } : {} };
|
|
127461
127549
|
}
|
|
127462
|
-
function withAutoId(output2, tool,
|
|
127550
|
+
function withAutoId(output2, tool, nextNote) {
|
|
127463
127551
|
const said = addSay(output2, tool, { news: watcher, npmVersion });
|
|
127464
127552
|
const blocks = Array.isArray(said?.content) && said.content.length ? said.content : void 0;
|
|
127465
127553
|
const text3 = blocks ? blocks[0]?.type === "text" ? blocks[0].text : void 0 : said?.text;
|
|
127466
127554
|
if (typeof text3 !== "string" || text3.length > 262144 || !/^\s*\{\s*"say"\s*:/.test(text3.slice(0, 64))) return said;
|
|
127467
|
-
const named = text3.slice(0, 600).includes(`Its request_id is ${requestId}.`);
|
|
127468
|
-
if (named && !nextNote) return said;
|
|
127469
127555
|
let parsed2;
|
|
127470
127556
|
try {
|
|
127471
127557
|
parsed2 = JSON.parse(text3);
|
|
127472
127558
|
} catch {
|
|
127473
127559
|
return said;
|
|
127474
127560
|
}
|
|
127475
|
-
if (
|
|
127476
|
-
|
|
127561
|
+
if (typeof parsed2.next !== "string") return said;
|
|
127562
|
+
parsed2.next = `${parsed2.next.replace(/[.\s]+$/, "")}. ${nextNote}`;
|
|
127477
127563
|
const out = JSON.stringify(parsed2, null, /^\s*\{\s*\n/.test(text3) ? 2 : void 0);
|
|
127478
127564
|
return { ...said, text: out, ...blocks ? { content: [{ ...blocks[0], text: out }, ...blocks.slice(1)] } : {} };
|
|
127479
127565
|
}
|
|
@@ -128364,6 +128450,7 @@ ${canonical5}`;
|
|
|
128364
128450
|
privateSends.push({
|
|
128365
128451
|
requestId: transfer ? plan.transferTokenId : shownId(plan.mcpRequestId, recordId2),
|
|
128366
128452
|
...transfer ? { tool: "wallet_transfer_token" } : {},
|
|
128453
|
+
to: plan.mcpTo,
|
|
128367
128454
|
amountAtomic: plan.amountAtomic,
|
|
128368
128455
|
sentAtomic: send3.sentAtomic,
|
|
128369
128456
|
leftAtomic: send3.remainingAtomic,
|
|
@@ -128410,19 +128497,20 @@ ${canonical5}`;
|
|
|
128410
128497
|
})
|
|
128411
128498
|
}));
|
|
128412
128499
|
if (sendWaiting) {
|
|
128413
|
-
next = `${next}. Tell the user: the send of ${usdcText3(sendWaiting.amountAtomic)} USDC to ${sendWaiting.to.slice(0, 4)}...${sendWaiting.to.slice(-4)}
|
|
128500
|
+
next = `${next}. Tell the user: the send of ${usdcText3(sendWaiting.amountAtomic)} USDC to ${sendWaiting.to.slice(0, 4)}...${sendWaiting.to.slice(-4)} ${sendWaiting.state === "sending" ? "is being sent now" : sendWaiting.state === "retrying" ? retryWords(sendWaiting) : "waits until the wallet has the balance ready to send; each wallet request goes on with it"}; it cannot be cancelled`;
|
|
128414
128501
|
}
|
|
128415
128502
|
const goingSends = privateSends.filter((send3) => send3.failedTries === void 0);
|
|
128416
128503
|
if (goingSends.length) {
|
|
128417
|
-
next = `${next}. Tell the user: ${goingSends.map((send3) =>
|
|
128504
|
+
next = `${next}. Tell the user: ${goingSends.map((send3) => `${sendWords(send3)} sent ${usdcText3(send3.sentAtomic)} USDC so far; payment ${send3.nextPayment} of ${send3.payments} ${send3.nextPaymentInMinutes > 0 ? `goes in about ${minutesText2(send3.nextPaymentInMinutes)} (random times, for privacy)` : "is past its planned time and not sent yet; the wallet tries it again by itself"}`).join("; ")}. ${SEND_RUNS_ON} The user needs to do nothing for it. To stop the unsent payments if the user asks: ${goingSends.map((send3) => `${cancelCall(send3)} (${sendWords(send3)})`).join("; ")}`;
|
|
128418
128505
|
}
|
|
128419
128506
|
const failingSends = privateSends.filter((send3) => send3.failedTries > 0);
|
|
128420
128507
|
if (failingSends.length) {
|
|
128421
|
-
next = `${next}. Tell the user: ${failingSends.map((send3) => `payment ${send3.nextPayment} of ${send3.payments} of
|
|
128508
|
+
next = `${next}. Tell the user: ${failingSends.map((send3) => `payment ${send3.nextPayment} of ${send3.payments} of ${sendWords(send3)} did not go through in ${send3.failedTries} ${send3.failedTries === 1 ? "try" : "tries"}${send3.lastTryMinutesAgo !== void 0 ? ` (the last ${send3.lastTryMinutesAgo > 0 ? `${ageWords2(send3.lastTryMinutesAgo)} ago` : "under a minute ago"})` : ""}: ${send3.lastReason}. It sent ${usdcText3(send3.sentAtomic)} USDC so far. The wallet tries that payment again by itself at its next start`).join(". ")}. ` + failingSends.map((send3) => `To try it now: ${send3.tool === "wallet_transfer_token" ? `wallet_transfer_token_status with request_id "${send3.requestId}"` : `wallet_unshield with request_id "${send3.requestId}" and the same arguments`}; to stop the send and return the USDC not sent yet to the private balance: ${cancelCall(send3)} (${sendWords(send3)})`).join(". ");
|
|
128422
128509
|
}
|
|
128423
128510
|
if (privateSends.length && one.largestPaymentAtomic === "0" && (one.changeSettling !== true || one.changeUpToAtomic !== void 0) && /^[1-9][0-9]*$/.test(String(one.balanceAtomic ?? ""))) {
|
|
128424
128511
|
const soon = one.changeUpToAtomic === void 0 ? "" : `after the last payment settles${Number.isSafeInteger(one.changeReadyInSeconds) ? ` (about ${one.changeReadyInSeconds} s)` : ""}, one payment can use up to ${usdcText3(one.changeUpToAtomic)} USDC; the rest waits, `;
|
|
128425
|
-
|
|
128512
|
+
const many = privateSends.length > 1;
|
|
128513
|
+
next = `${next}. Tell the user: ${soon || `no payment can use the ${usdcText3(one.balanceAtomic)} USDC yet, `}because ${privateSends.map(sendWords).join(" and ")} ${many ? "keep" : "keeps"} money aside for ${many ? "their" : "its"} unsent payments. A send keeps nothing after its last payment goes, and an earlier payment may free some (wallet_balance shows it). To pay now if the user asks: ${privateSends.map((send3) => `${cancelCall(send3)} (${sendWords(send3)})`).join(" or ")} stops the send and frees its money now`;
|
|
128426
128514
|
}
|
|
128427
128515
|
const balanceParts = parts?.parts > 1 && ATOMIC_TEXT.test(String(one.balanceAtomic ?? "")) ? parts.parts : void 0;
|
|
128428
128516
|
if (balanceParts && !sendWaiting) {
|
|
@@ -128862,7 +128950,7 @@ ${canonical5}`;
|
|
|
128862
128950
|
live = "unreadable";
|
|
128863
128951
|
}
|
|
128864
128952
|
const started = Number.isSafeInteger(record.createdAtMs) ? record.createdAtMs : Number.isSafeInteger(joining?.createdAtMs) ? joining.createdAtMs : void 0;
|
|
128865
|
-
const at = Number.isSafeInteger(record
|
|
128953
|
+
const at = Number.isSafeInteger(sentAtMs(record)) ? sentAtMs(record) : record.state === "exited" ? walTimeMs(store, name) : started ?? walTimeMs(store, name);
|
|
128866
128954
|
const shown = shownId(record.mcpRequestId, idAfter(name, "self-pay-mcp-"));
|
|
128867
128955
|
if (live !== "joining") joining = void 0;
|
|
128868
128956
|
const retry = joining ? retryFields(joining) : void 0;
|
|
@@ -130381,7 +130469,7 @@ ${canonical5}`;
|
|
|
130381
130469
|
if (!record) continue;
|
|
130382
130470
|
const finished = kind !== "unshield" ? ["published", "foreign_funded", "reclaimed"].includes(record.state) : record.schema === PRIVATE_SEND_WAL_SCHEMA ? record.state === "done" || record.state === "cancelled" && privateSendStatus(store, record).done : ["exited", "released", "abandoned"].includes(record.state);
|
|
130383
130471
|
if (!finished) return void 0;
|
|
130384
|
-
const at = Date.parse(String(record.doneAt ?? "")) || record
|
|
130472
|
+
const at = Date.parse(String(record.doneAt ?? "")) || sentAtMs(record);
|
|
130385
130473
|
if (Number.isSafeInteger(at)) return at;
|
|
130386
130474
|
try {
|
|
130387
130475
|
return Math.floor(statSync(join32(store.walDirectory, `${name}.json`)).mtimeMs);
|
|
@@ -130411,7 +130499,6 @@ ${canonical5}`;
|
|
|
130411
130499
|
return withAutoId(
|
|
130412
130500
|
answer,
|
|
130413
130501
|
spec.tool,
|
|
130414
|
-
claimed.requestId,
|
|
130415
130502
|
"The same call without request_id within 10 minutes after it ends reads this same request; to do it again later, ask after 10 minutes or give a new request_id."
|
|
130416
130503
|
);
|
|
130417
130504
|
}
|
|
@@ -130569,7 +130656,7 @@ ${canonical5}`;
|
|
|
130569
130656
|
const finished = kind === "unshield" ? split4 ? record.state === "done" || record.state === "cancelled" && privateSendStatus(store, record).done : record.state === "exited" : ["published", "foreign_funded"].includes(record.state);
|
|
130570
130657
|
if (finished) {
|
|
130571
130658
|
const send3 = split4 ? privateSendStatus(store, record) : void 0;
|
|
130572
|
-
const endedAtMs = Date.parse(String(record.doneAt ?? record.cancelledAt ?? "")) || record
|
|
130659
|
+
const endedAtMs = Date.parse(String(record.doneAt ?? record.cancelledAt ?? "")) || sentAtMs(record);
|
|
130573
130660
|
const earlier = kind !== "elsewhere" ? { replayed: true, newRequestId: freshId, ...Number.isSafeInteger(endedAtMs) ? { finishedMinutesAgo: Math.max(0, Math.round((Date.now() - endedAtMs) / 6e4)) } : {} } : {};
|
|
130574
130661
|
const earlierWords = earlier.finishedMinutesAgo !== void 0 ? ` about ${minutesText2(earlier.finishedMinutesAgo)} ago` : " earlier";
|
|
130575
130662
|
return json3({
|
|
@@ -133271,7 +133358,7 @@ ${canonical5}`;
|
|
|
133271
133358
|
temperature: { type: "number", minimum: 0, maximum: 2, description: "Sampling temperature; leave it out for the model's default." },
|
|
133272
133359
|
max_payment: { type: "string", description: 'Optional: the most this call may pay, in USDC, like "0.05"; at most the spending limit.' },
|
|
133273
133360
|
max_payment_atomic: { type: "string", pattern: "^[1-9][0-9]*$", description: "The most this call may pay, in atomic units; at most the spending limit." },
|
|
133274
|
-
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "
|
|
133361
|
+
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional. Leave it out for a new question (the answer names the id it made). Pass the request_id of an earlier answer only to resume that call; it never pays twice." }
|
|
133275
133362
|
},
|
|
133276
133363
|
additionalProperties: false
|
|
133277
133364
|
},
|
|
@@ -134764,7 +134851,7 @@ var init_tools = __esm({
|
|
|
134764
134851
|
shownId = (agentId, rid) => typeof agentId === "string" && REQUEST_ID4.test(agentId) && toRecordId(agentId) === rid ? agentId : rid;
|
|
134765
134852
|
isSplitSend = (request) => Boolean(request) && !isSingleSend(request.parts ?? 1, request.maxDelayMinutes ?? 0);
|
|
134766
134853
|
sendPartId = (requestId) => (index) => `mp${index}-${toRecordId(requestId)}`;
|
|
134767
|
-
PROMISED_NEXT = "Nothing was sent. Some of the private balance is promised to the unsent payments of a private send (wallet_balance privateSends names it, and its next names the call that stops it).
|
|
134854
|
+
PROMISED_NEXT = "Nothing was sent. Some of the private balance is promised to the unsent payments of a private send (wallet_balance privateSends names it, and its next names the call that stops it). A wait frees nothing, because that money leaves the wallet as its parts go: to send this amount, stop its unsent payments with that call, then call wallet_unshield again with the same arguments; or send at most freeAtomic now with a NEW request_id";
|
|
134768
134855
|
partFailReason = (code2) => INSUFFICIENT_CODE.test(String(code2 ?? "")) ? "the wallet could not pay that amount in one payment from the private balance as it is" : reasonOf(code2) ?? "the payment did not finish";
|
|
134769
134856
|
sendAnswerOf = (status) => {
|
|
134770
134857
|
const { nextPartLastTryAt: _clock, ...shown } = status;
|