shinjuku-shielded 0.3.23 → 0.3.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/manifest.json +3 -3
- package/package.json +3 -3
- package/shinjuku-wallet.mjs +110 -20
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": "1505ebf0afdb67fbbe6050d5065335f3b13e94cefd356fb422ce946f4fba3253",
|
|
5
|
+
"bytes": 11138284,
|
|
6
|
+
"sourceCommit": "d34c7e8fbb9d384d53557aeeac05386f35ce2fb9",
|
|
7
7
|
"sourceDirty": false,
|
|
8
8
|
"installRecordMatchesLockfile": true,
|
|
9
9
|
"releaseRule": "valid only when two fresh npm ci --ignore-scripts builds on different OSes give the same sha256; installRecordMatchesLockfile true means every entry npm installed equals its package-lock.json entry and every entry not marked optional, devOptional included, is installed: an optional entry (a package for another platform) may be absent",
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shielded",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.25",
|
|
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": "1505ebf0",
|
|
7
|
+
"shinjukuSha256": "1505ebf0afdb67fbbe6050d5065335f3b13e94cefd356fb422ce946f4fba3253",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
9
9
|
"author": "Shinjuku Shielded",
|
|
10
10
|
"homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
|
package/shinjuku-wallet.mjs
CHANGED
|
@@ -59758,6 +59758,16 @@ var init_recoveryCache = __esm({
|
|
|
59758
59758
|
});
|
|
59759
59759
|
|
|
59760
59760
|
// wallet/src/succession/successorHistories.mjs
|
|
59761
|
+
function withoutProgramHistory(identity) {
|
|
59762
|
+
if (!identity || typeof identity !== "object" || identity.programHistory === void 0) return void 0;
|
|
59763
|
+
const { programHistory: _history, ...rest } = identity;
|
|
59764
|
+
return rest;
|
|
59765
|
+
}
|
|
59766
|
+
function errorChainText(error) {
|
|
59767
|
+
const parts = [];
|
|
59768
|
+
for (let current = error, depth = 0; current && depth < 8; current = current.cause, depth += 1) parts.push(String(current?.message ?? current));
|
|
59769
|
+
return parts.join(" ");
|
|
59770
|
+
}
|
|
59761
59771
|
async function loadSuccessorHistories({
|
|
59762
59772
|
history,
|
|
59763
59773
|
store,
|
|
@@ -59775,24 +59785,34 @@ async function loadSuccessorHistories({
|
|
|
59775
59785
|
if (typeof target !== "string") return walks;
|
|
59776
59786
|
if (seen.has(target) || walks.length >= MAX_SUCCESSOR_HOPS) throw new Error("wallet_succession_chain_invalid");
|
|
59777
59787
|
seen.add(target);
|
|
59778
|
-
const
|
|
59788
|
+
const identity = deploymentIdentityFor?.(target) ?? deploymentIdentity;
|
|
59789
|
+
const read = (given) => loadHistory({
|
|
59779
59790
|
store,
|
|
59780
59791
|
connection,
|
|
59781
59792
|
programId,
|
|
59782
59793
|
pool: target,
|
|
59783
|
-
deploymentIdentity:
|
|
59794
|
+
deploymentIdentity: given,
|
|
59784
59795
|
cache: walletSuccessorHistoryCache(store, target)
|
|
59785
59796
|
});
|
|
59797
|
+
let walk;
|
|
59798
|
+
try {
|
|
59799
|
+
walk = await read(identity);
|
|
59800
|
+
} catch (error) {
|
|
59801
|
+
const historyFree = withoutProgramHistory(identity);
|
|
59802
|
+
if (!historyFree || !HISTORY_FREE_NEEDED.test(errorChainText(error))) throw error;
|
|
59803
|
+
walk = await read(historyFree);
|
|
59804
|
+
}
|
|
59786
59805
|
if (walk?.pool !== target) throw new Error("wallet_succession_chain_invalid");
|
|
59787
59806
|
walks.push(walk);
|
|
59788
59807
|
current = walk;
|
|
59789
59808
|
}
|
|
59790
59809
|
}
|
|
59791
|
-
var MAX_SUCCESSOR_HOPS;
|
|
59810
|
+
var HISTORY_FREE_NEEDED, MAX_SUCCESSOR_HOPS;
|
|
59792
59811
|
var init_successorHistories = __esm({
|
|
59793
59812
|
"wallet/src/succession/successorHistories.mjs"() {
|
|
59794
59813
|
"use strict";
|
|
59795
59814
|
init_walletHistory();
|
|
59815
|
+
HISTORY_FREE_NEEDED = /p03_program_history_coverage_interval_invalid_pool_initialized_after_last_upgrade_use_history_free_identity/;
|
|
59796
59816
|
MAX_SUCCESSOR_HOPS = 8;
|
|
59797
59817
|
}
|
|
59798
59818
|
});
|
|
@@ -90683,14 +90703,27 @@ function floatRecordOf(store, requestId) {
|
|
|
90683
90703
|
function floatInnerRequestId(requestId) {
|
|
90684
90704
|
return requestId.length <= 122 ? `${requestId}:float` : `float:${hash8(requestId)}`;
|
|
90685
90705
|
}
|
|
90686
|
-
function floatRefundsInFlightAtomic(store,
|
|
90706
|
+
function floatRefundsInFlightAtomic(store, snapshot) {
|
|
90707
|
+
const refreshedAtMs = Date.parse(snapshot?.refreshedAt ?? "");
|
|
90708
|
+
const outputs = Array.isArray(snapshot?.outputs) ? snapshot.outputs : [];
|
|
90709
|
+
const knowsRecipients = outputs.some((output2) => output2?.kind === "note" && output2.diversifier !== void 0);
|
|
90710
|
+
const arrived = (refundTo) => {
|
|
90711
|
+
let address5;
|
|
90712
|
+
try {
|
|
90713
|
+
address5 = decodeShieldedSolanaP03Address(String(refundTo));
|
|
90714
|
+
} catch {
|
|
90715
|
+
return false;
|
|
90716
|
+
}
|
|
90717
|
+
return outputs.some((output2) => output2?.kind === "note" && output2.diversifier === address5.diversifier.toString() && output2.recipientX === address5.recipientX.toString());
|
|
90718
|
+
};
|
|
90687
90719
|
let total = 0n;
|
|
90688
90720
|
try {
|
|
90689
90721
|
for (const name of store.listWal()) {
|
|
90690
90722
|
if (!name.startsWith(FLOAT_PAYMENT_WAL_PREFIX)) continue;
|
|
90691
90723
|
const record = store.readWal(name);
|
|
90692
90724
|
if (record?.schema !== FLOAT_PAYMENT_SCHEMA || record.state !== "refund_pending" || !POSITIVE.test(String(record.paidAtomic))) continue;
|
|
90693
|
-
if (
|
|
90725
|
+
if (arrived(record.refundTo)) continue;
|
|
90726
|
+
if (!knowsRecipients && Number.isFinite(refreshedAtMs) && refreshedAtMs >= record.refundPendingAtMs + REFUND_SETTLED_AFTER_MS) continue;
|
|
90694
90727
|
total += BigInt(record.paidAtomic);
|
|
90695
90728
|
}
|
|
90696
90729
|
} catch {
|
|
@@ -118895,7 +118928,27 @@ function snapshotFile(store) {
|
|
|
118895
118928
|
return file;
|
|
118896
118929
|
}
|
|
118897
118930
|
function captureWalStates(store) {
|
|
118898
|
-
return Object.fromEntries(store.listWal().sort().map((name) => [name,
|
|
118931
|
+
return Object.fromEntries(store.listWal().sort().map((name) => [name, walStateOf(name, store.readWal(name))]));
|
|
118932
|
+
}
|
|
118933
|
+
var SUCCESSION_JOB_SCHEMA = "carbon-shielded-wallet/pool-succession/v1";
|
|
118934
|
+
function walStateOf(name, record) {
|
|
118935
|
+
if (name.startsWith("succ-") && record?.schema === SUCCESSION_JOB_SCHEMA && canonicalAtomic(String(record.movedAtomic))) {
|
|
118936
|
+
return `${record.state}|${record.movedAtomic}`;
|
|
118937
|
+
}
|
|
118938
|
+
return String(record?.state);
|
|
118939
|
+
}
|
|
118940
|
+
function movedInAfterSnapshot(store, state, snapshot) {
|
|
118941
|
+
let total = 0n;
|
|
118942
|
+
for (const name of store.listWal()) {
|
|
118943
|
+
if (!name.startsWith("succ-")) continue;
|
|
118944
|
+
const record = store.readWal(name);
|
|
118945
|
+
if (record?.schema !== SUCCESSION_JOB_SCHEMA || record.to !== state.pool || !canonicalAtomic(String(record.movedAtomic))) continue;
|
|
118946
|
+
const before = Object.hasOwn(snapshot.walStates, name) ? String(snapshot.walStates[name]) : void 0;
|
|
118947
|
+
const kept = before?.includes("|") ? before.split("|")[1] : before === "moved" ? String(record.movedAtomic) : "0";
|
|
118948
|
+
const moved = BigInt(record.movedAtomic) - (canonicalAtomic(kept) ? BigInt(kept) : 0n);
|
|
118949
|
+
if (moved > 0n) total += moved;
|
|
118950
|
+
}
|
|
118951
|
+
return total;
|
|
118899
118952
|
}
|
|
118900
118953
|
function snapshotFromRecovery({ state, programId, recovery, history, walStates, fresh, now = Date.now() }) {
|
|
118901
118954
|
if (!Array.isArray(recovery?.recovered)) throw new Error("balance_snapshot_recovery_invalid");
|
|
@@ -118908,7 +118961,10 @@ function snapshotFromRecovery({ state, programId, recovery, history, walStates,
|
|
|
118908
118961
|
leafIndex: String(entry?.leafIndex),
|
|
118909
118962
|
valueAtomic: value === void 0 ? void 0 : String(value),
|
|
118910
118963
|
spendStatus: entry?.spendStatus,
|
|
118911
|
-
digest: digestKey(entry?.digest)
|
|
118964
|
+
digest: digestKey(entry?.digest),
|
|
118965
|
+
// A note's one-time recipient (diversifier d and recipient x): a float refund is matched to its
|
|
118966
|
+
// own refund address by these (floatRefundsInFlightAtomic). Public to this wallet only (sealed cache).
|
|
118967
|
+
...entry?.kind === "note" && /^[0-9]+$/.test(String(entry.note?.d)) && /^[0-9]+$/.test(String(entry.note?.pDX)) ? { diversifier: String(entry.note.d), recipientX: String(entry.note.pDX) } : {}
|
|
118912
118968
|
};
|
|
118913
118969
|
if (!["account", "note"].includes(output2.kind) || !canonicalAtomic(output2.valueAtomic) || !canonicalAtomic(output2.commitment) || !canonicalAtomic(output2.leafIndex) || !SPEND_STATUSES.has(output2.spendStatus) || !/^[0-9a-f]{64}$/.test(output2.digest)) {
|
|
118914
118970
|
throw new Error("balance_snapshot_output_invalid");
|
|
@@ -119030,7 +119086,8 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
|
|
|
119030
119086
|
...entry.record.relay?.approvedOnChain ? { approvalStanding: true } : {}
|
|
119031
119087
|
}));
|
|
119032
119088
|
const receipts = records.filter((entry) => entry.type === "payment" && entry.phase === "done");
|
|
119033
|
-
const
|
|
119089
|
+
const refunded = new Set(records.filter((entry) => entry.type === "float-payment" && entry.state === "refund_pending").map((entry) => entry.record.innerRequestId).filter((id) => typeof id === "string"));
|
|
119090
|
+
const paid = receipts.filter((entry) => !String(entry.record.url ?? "").startsWith(SELF_PAY_ORIGIN2) && !String(entry.record.url ?? "").includes(POOL_MOVE_PATH2) && !refunded.has(entry.record.requestId));
|
|
119034
119091
|
const sum2 = (values) => values.reduce((total, value) => total + BigInt(value ?? "0"), 0n);
|
|
119035
119092
|
const config = state.config ?? {};
|
|
119036
119093
|
const capOrNone = (value) => String(value) === NO_LIMIT_ATOMIC2 ? "none" : value;
|
|
@@ -119110,7 +119167,8 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
|
|
|
119110
119167
|
detail.unspentAtomic = unspentAtomic.toString();
|
|
119111
119168
|
const settling = [];
|
|
119112
119169
|
const movable = snapshot.outputs.filter((output2) => output2.spendStatus === "succession-movable");
|
|
119113
|
-
const
|
|
119170
|
+
const movedInAtomic = movedInAfterSnapshot(store, state, snapshot);
|
|
119171
|
+
const successionMovableAtomic = sum2(movable.map((output2) => output2.valueAtomic)) + movedInAtomic;
|
|
119114
119172
|
detail.successionMovableAtomic = successionMovableAtomic.toString();
|
|
119115
119173
|
detail.unspentAccounts = [...unspent.values()].filter((output2) => output2.kind === "account").length;
|
|
119116
119174
|
detail.unspentNotes = [...unspent.values()].filter((output2) => output2.kind === "note").length;
|
|
@@ -119240,7 +119298,10 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
|
|
|
119240
119298
|
const anchorIndex = canonicalAtomic(snapshot.anchorIndex) ? BigInt(snapshot.anchorIndex) : void 0;
|
|
119241
119299
|
detail.fundedAccounts = unknownInputs ? 0 : [...unspent.values()].filter((output2) => output2.kind === "account" && BigInt(output2.valueAtomic) > 0n && !reserved.has(output2.commitment) && !settlingInputs.has(output2.commitment) && (anchorIndex === void 0 || BigInt(output2.leafIndex) < anchorIndex)).length;
|
|
119242
119300
|
const next = detail.inFlight.length ? "finish or cancel the work in detail.inFlight; the wallet runs one payment at a time" : pendingDeposits.length ? `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 (a move per account, the facilitator pays the fee) and counts in this balance until then" : unspentAtomic === 0n ? "nothing to spend: deposit (shinjuku-wallet help deposit), or run balance --refresh if a payment to this wallet settled" : void 0;
|
|
119243
|
-
if (
|
|
119301
|
+
if (movedInAtomic > 0n) {
|
|
119302
|
+
settlingReasons.push(`${formatAtomic(movedInAtomic, decimals)} moved into this pool from the old pool after the last refresh: the balance counts it; refresh again in a minute`);
|
|
119303
|
+
}
|
|
119304
|
+
if (settling.length || movedInAtomic > 0n) {
|
|
119244
119305
|
reasons.push(...settlingReasons);
|
|
119245
119306
|
return report("stale", spendable + successionMovableAtomic, next ?? refreshCommand(state, snapshot.programId));
|
|
119246
119307
|
}
|
|
@@ -122048,6 +122109,7 @@ init_store();
|
|
|
122048
122109
|
var import_web3127 = __toESM(require_index_cjs(), 1);
|
|
122049
122110
|
init_chain2();
|
|
122050
122111
|
init_walk();
|
|
122112
|
+
init_receiptTransaction();
|
|
122051
122113
|
init_serviceUrl();
|
|
122052
122114
|
import { randomInt as randomInt4 } from "node:crypto";
|
|
122053
122115
|
|
|
@@ -122417,6 +122479,18 @@ async function chainNowSeconds(connection) {
|
|
|
122417
122479
|
return info.data.readBigInt64LE(32);
|
|
122418
122480
|
}
|
|
122419
122481
|
var sameInputs = (context, inputs) => Array.isArray(context.publicInputs) && context.publicInputs.length === inputs.length && context.publicInputs.every((value, index) => fieldHex4(value) === inputs[index]);
|
|
122482
|
+
var landedIsLeg = (context, body) => {
|
|
122483
|
+
if (Array.isArray(context.publicInputs)) return sameInputs(context, body.publicInputBytesHex);
|
|
122484
|
+
try {
|
|
122485
|
+
const payload2 = Buffer.concat([
|
|
122486
|
+
Buffer.from(String(body.proofBytesHex).replace(/^0x/, ""), "hex"),
|
|
122487
|
+
...body.publicInputBytesHex.map((value) => Buffer.from(String(value).replace(/^0x/, ""), "hex"))
|
|
122488
|
+
]);
|
|
122489
|
+
return contextPayloadMatches(context, payload2);
|
|
122490
|
+
} catch {
|
|
122491
|
+
return false;
|
|
122492
|
+
}
|
|
122493
|
+
};
|
|
122420
122494
|
async function destinationMoves(deps, sourceDomain) {
|
|
122421
122495
|
if (typeof deps.loadDestinationReport !== "function") {
|
|
122422
122496
|
throw refuse7("wallet_succession_history_unavailable", "no successor-pool history to confirm the move against");
|
|
@@ -122488,6 +122562,9 @@ async function runSuccessionMove({ store, verified, source, facilitator, connect
|
|
|
122488
122562
|
let rebuilds = 0;
|
|
122489
122563
|
for (; ; ) {
|
|
122490
122564
|
if (leg.state === "confirmed" || leg.state === "dropped") return void 0;
|
|
122565
|
+
if (leg.state === "failed" && leg.lastCode === "wallet_succession_leg_receipt_invalid" && typeof leg.transaction === "string" && leg.body) {
|
|
122566
|
+
leg = save2(leg, { state: "relayed" });
|
|
122567
|
+
}
|
|
122491
122568
|
if (leg.state === "failed") leg = save2(leg, { state: "planned" });
|
|
122492
122569
|
if (leg.state === "planned") {
|
|
122493
122570
|
const inputs = [...leg.inputs.account ? [leg.inputs.account] : [], ...leg.inputs.notes];
|
|
@@ -122585,7 +122662,7 @@ async function runSuccessionMove({ store, verified, source, facilitator, connect
|
|
|
122585
122662
|
const moves = await destinationMoves(deps, sourceDomain);
|
|
122586
122663
|
const landed = moves.find((context) => context.provenance?.signature === leg.transaction);
|
|
122587
122664
|
if (landed) {
|
|
122588
|
-
if (!
|
|
122665
|
+
if (!landedIsLeg(landed, leg.body)) {
|
|
122589
122666
|
save2(leg, { state: "failed", lastCode: "wallet_succession_leg_receipt_invalid" });
|
|
122590
122667
|
throw refuse7("wallet_succession_leg_receipt_invalid", "the relay's transaction is not this leg's move; tell the operator");
|
|
122591
122668
|
}
|
|
@@ -122624,7 +122701,7 @@ async function runSuccessionMove({ store, verified, source, facilitator, connect
|
|
|
122624
122701
|
|
|
122625
122702
|
// wallet/src/succession/scheduler.mjs
|
|
122626
122703
|
init_successorHistories();
|
|
122627
|
-
var
|
|
122704
|
+
var SUCCESSION_JOB_SCHEMA2 = "carbon-shielded-wallet/pool-succession/v1";
|
|
122628
122705
|
var SUCCESSION_DELAY_MIN_MS = 5 * 6e4;
|
|
122629
122706
|
var SUCCESSION_DELAY_MAX_MS = 30 * 6e4;
|
|
122630
122707
|
var SUCCESSION_LATE_START_MAX_MS = 6e4;
|
|
@@ -122724,10 +122801,10 @@ function successionMessage(job) {
|
|
|
122724
122801
|
var SUCCESSION_WHY = "Your facilitator upgraded to a new pool. Your balance moves to the new pool so you can keep paying; the money stays yours.";
|
|
122725
122802
|
function readSuccessionJob(store, fromPool) {
|
|
122726
122803
|
const record = store.readWal(successionJobName(fromPool));
|
|
122727
|
-
return record?.schema ===
|
|
122804
|
+
return record?.schema === SUCCESSION_JOB_SCHEMA2 && record.from === fromPool ? record : void 0;
|
|
122728
122805
|
}
|
|
122729
122806
|
function successionJobs(store) {
|
|
122730
|
-
return store.listWal().filter((name) => /^succ-[0-9A-Za-z]{1,8}$/.test(name)).map((name) => store.readWal(name)).filter((record) => record?.schema ===
|
|
122807
|
+
return store.listWal().filter((name) => /^succ-[0-9A-Za-z]{1,8}$/.test(name)).map((name) => store.readWal(name)).filter((record) => record?.schema === SUCCESSION_JOB_SCHEMA2);
|
|
122731
122808
|
}
|
|
122732
122809
|
var noticeKey = (job) => job.state === "failed-retry" ? `failed:${job.lastCode ?? ""}` : PUBLIC_STATE[job.state];
|
|
122733
122810
|
var SUCCESSION_NOTICE_SCHEMA = "carbon-shielded-wallet/pool-succession-notice/v1";
|
|
@@ -122877,6 +122954,7 @@ function createSuccessionScheduler(options) {
|
|
|
122877
122954
|
const startedAtMs = now();
|
|
122878
122955
|
const lateStart = /* @__PURE__ */ new Map();
|
|
122879
122956
|
const recordCheckedAt = /* @__PURE__ */ new Map();
|
|
122957
|
+
const receiptRecheck = /* @__PURE__ */ new Set();
|
|
122880
122958
|
let active;
|
|
122881
122959
|
let closed = false;
|
|
122882
122960
|
const listEntries = () => {
|
|
@@ -122960,7 +123038,7 @@ function createSuccessionScheduler(options) {
|
|
|
122960
123038
|
return job;
|
|
122961
123039
|
}
|
|
122962
123040
|
const base = (entry, value, verified) => ({
|
|
122963
|
-
schema:
|
|
123041
|
+
schema: SUCCESSION_JOB_SCHEMA2,
|
|
122964
123042
|
from: entry.from,
|
|
122965
123043
|
to: verified?.successor ?? entry.to,
|
|
122966
123044
|
record: entry.record,
|
|
@@ -123078,8 +123156,13 @@ function createSuccessionScheduler(options) {
|
|
|
123078
123156
|
}
|
|
123079
123157
|
case "move-scheduled":
|
|
123080
123158
|
return now() >= startAt(job) ? startRun(entry) : job;
|
|
123081
|
-
case "moving":
|
|
123082
123159
|
case "failed-retry":
|
|
123160
|
+
if (job.lastCode === "wallet_succession_leg_receipt_invalid" && job.updatedAtMs < startedAtMs && !receiptRecheck.has(entry.from)) {
|
|
123161
|
+
receiptRecheck.add(entry.from);
|
|
123162
|
+
job = save2(store, job, { permanent: false, nextTryAtMs: now() });
|
|
123163
|
+
}
|
|
123164
|
+
return now() >= (job.nextTryAtMs ?? 0) ? startRun(entry) : job;
|
|
123165
|
+
case "moving":
|
|
123083
123166
|
return now() >= (job.nextTryAtMs ?? 0) ? startRun(entry) : job;
|
|
123084
123167
|
default:
|
|
123085
123168
|
return job;
|
|
@@ -124920,13 +125003,13 @@ function oneBalance(report, store) {
|
|
|
124920
125003
|
const shieldedAtomic = report?.split?.shieldedAtomic ?? null;
|
|
124921
125004
|
const pocketsAtomic = report?.split?.pocketsAtomic ?? null;
|
|
124922
125005
|
const moving = movingAtomic(store);
|
|
124923
|
-
let
|
|
125006
|
+
let snapshot;
|
|
124924
125007
|
try {
|
|
124925
|
-
|
|
125008
|
+
snapshot = readBalanceSnapshot(store).snapshot;
|
|
124926
125009
|
} catch {
|
|
124927
|
-
|
|
125010
|
+
snapshot = void 0;
|
|
124928
125011
|
}
|
|
124929
|
-
const refunds = floatRefundsInFlightAtomic(store,
|
|
125012
|
+
const refunds = floatRefundsInFlightAtomic(store, snapshot);
|
|
124930
125013
|
const known = shieldedAtomic !== null && pocketsAtomic !== null;
|
|
124931
125014
|
const setAside = known ? BigInt(pocketsAtomic) + moving : null;
|
|
124932
125015
|
const total = known ? BigInt(shieldedAtomic) + setAside + refunds : null;
|
|
@@ -125528,6 +125611,13 @@ function createWalletTools({
|
|
|
125528
125611
|
next = typeof blocking === "string" && /^[A-Za-z0-9._:-]{1,128}$/.test(blocking) ? `Nothing was paid: an earlier payment (request_id "${blocking}") is not finished, and the wallet pays one at a time. Call x402_pay again with request_id "${blocking}" and that payment's url, method, headers, and body (it finishes it and never pays twice), or close it with wallet_cancel request_id "${blocking}"; then call x402_pay again with request_id "${requestId}"` : `Nothing was paid: an earlier payment is not finished, and the wallet pays one at a time. wallet_balance lists it in detail.inFlight; finish it with x402_pay and its request_id, or close it with wallet_cancel; then call x402_pay again with request_id "${requestId}"`;
|
|
125529
125612
|
} else if (/accounts_split_merge_first/.test(line)) {
|
|
125530
125613
|
next = `Nothing was paid: the shielded balance covers this price in total, but it sits in several accounts and one payment draws only one account and at most 3 notes. Tell your owner to join them: shinjuku-wallet merge --wallet <wallet.json> --passphrase-file passphrase.txt --program <program> --proof-tools proof-tools.json --profile public-profile.json --facilitator <facilitator origin> (--dry-run shows the plan; shinjuku-wallet help merge). After it finished and the next pool anchor (up to 5 minutes; about 30 s on a pool with sub-anchors) passed, call x402_pay again with request_id "${requestId}" and the same url, method, headers, and body`;
|
|
125614
|
+
} else if (/^p03_merchant_respend_(insufficient_recovered_value|no_spendable_account)$|^(p03_payer_)?insufficient(_recovered)?_value$/.test(code)) {
|
|
125615
|
+
return refuse9(
|
|
125616
|
+
code,
|
|
125617
|
+
"the shielded balance is less than this payment needs (price + fee); nothing was paid",
|
|
125618
|
+
`Nothing was paid. Tell the user the balance is too low for this price: wallet_balance shows breakdown.shieldedAtomic (a refund still on its way shows as refundsInFlightAtomic and becomes spendable when it arrives). To pay, add USDC with wallet_shield (or wallet_shield_from_elsewhere), wait until wallet_balance counts it, then call x402_pay again with request_id "${requestId}" and the same url, method, headers, and body (it never pays twice)`,
|
|
125619
|
+
{ requestId }
|
|
125620
|
+
);
|
|
125531
125621
|
} else if (code.startsWith("wallet_spend_refused_")) {
|
|
125532
125622
|
next = "the wallet file's own budget refused it (init --max-payment / --max-cumulative); nothing was paid. Read wallet_balance detail.budget";
|
|
125533
125623
|
} else if (code.startsWith("wallet_quote_refused_") || code.startsWith("fetch_")) {
|