shinjuku-shielded 0.3.27 → 0.3.28
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 +111 -9
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": "dd6ce54a50e0e58be863f647620b767cb760d1278ee089b74c10c98068383047",
|
|
5
|
+
"bytes": 11159107,
|
|
6
|
+
"sourceCommit": "b5316573de1f09bb207ce09a78d5ec4d02fc8035",
|
|
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.28",
|
|
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": "dd6ce54a",
|
|
7
|
+
"shinjukuSha256": "dd6ce54a50e0e58be863f647620b767cb760d1278ee089b74c10c98068383047",
|
|
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
|
@@ -121953,7 +121953,8 @@ var CHAIN_RECHECK_MS = 6 * 60 * 6e4;
|
|
|
121953
121953
|
var MCP_POLL_LIMIT_MS = 3 * 6e4;
|
|
121954
121954
|
var firstCode5 = (error) => String(error?.message ?? error ?? "").split(/[\s:;(]/, 1)[0];
|
|
121955
121955
|
function createMoveScheduler({ session, underLease, log = () => {
|
|
121956
|
-
}, env = process.env,
|
|
121956
|
+
}, env = process.env, onSettled = () => {
|
|
121957
|
+
}, deps = {} }) {
|
|
121957
121958
|
const now = deps.now ?? Date.now;
|
|
121958
121959
|
const home = deps.home ?? setupHome(env);
|
|
121959
121960
|
const readConfig = deps.readConfig ?? (() => readSetupConfig(home));
|
|
@@ -121987,6 +121988,7 @@ function createMoveScheduler({ session, underLease, log = () => {
|
|
|
121987
121988
|
let interval;
|
|
121988
121989
|
let closed = false;
|
|
121989
121990
|
const failedAt = /* @__PURE__ */ new Map();
|
|
121991
|
+
const lastCredit = /* @__PURE__ */ new Map();
|
|
121990
121992
|
const leaseFor = (pool) => async (task) => {
|
|
121991
121993
|
if (resolve21(homeWalletPath(home, pool)) === sessionPath) return underLease(() => task());
|
|
121992
121994
|
let free;
|
|
@@ -122070,6 +122072,14 @@ function createMoveScheduler({ session, underLease, log = () => {
|
|
|
122070
122072
|
withTargetLease: leaseFor(move.to.pool)
|
|
122071
122073
|
});
|
|
122072
122074
|
log(`MCP_MOVE ${move.from.pool.slice(0, 8)} ${result.state}${result.code ? ` ${result.code}` : ""}`);
|
|
122075
|
+
const credit = (result.legs ?? []).map((leg) => leg?.creditTransaction).filter((signature) => typeof signature === "string" && signature).at(-1);
|
|
122076
|
+
if (credit && credit !== lastCredit.get(move.from.pool)) {
|
|
122077
|
+
lastCredit.set(move.from.pool, credit);
|
|
122078
|
+
try {
|
|
122079
|
+
onSettled(credit);
|
|
122080
|
+
} catch {
|
|
122081
|
+
}
|
|
122082
|
+
}
|
|
122073
122083
|
} catch (error) {
|
|
122074
122084
|
const code = firstCode5(error) || "wallet_move_leg_failed";
|
|
122075
122085
|
result = { state: code === "wallet_locked" ? "waiting" : "failed", code, fromPool: move.from.pool, toPool: move.to.pool };
|
|
@@ -122909,10 +122919,16 @@ var CARRY_WAIT_CODES = /* @__PURE__ */ new Set([
|
|
|
122909
122919
|
"wallet_locked"
|
|
122910
122920
|
]);
|
|
122911
122921
|
var carryRefusedForGood = (carry) => carry?.state === "refused" && !CARRY_WAIT_CODES.has(carry.code);
|
|
122912
|
-
function
|
|
122913
|
-
if (carry
|
|
122922
|
+
function pocketCarryReason(carry) {
|
|
122923
|
+
if (carry && CARRY_DONE.has(carry.state)) return { done: true, waits: false, code: null, reason: "" };
|
|
122924
|
+
if (carry?.state !== "refused") return { done: false, waits: true, code: null, reason: "the wallet has not finished its check of the pool switch" };
|
|
122914
122925
|
const code = String(carry.code ?? "");
|
|
122915
122926
|
const reason = code === "p03_pocket_carry_source_fill_pending" || code === "p03_pocket_carry_source_payment_pending" ? "a pocket top-up or a pocket payment is not final yet" : code === "wallet_locked" ? "another wallet command uses the old pool's wallet now" : CARRY_WAIT_CODES.has(code) ? "the wallet has not finished its check of the pool switch" : code === "p03_pocket_carry_target_not_empty" ? "the new pool's wallet already has pocket accounts of its own" : "the pocket records of the two wallets do not match";
|
|
122927
|
+
return { done: false, waits: CARRY_WAIT_CODES.has(code), code, reason };
|
|
122928
|
+
}
|
|
122929
|
+
function pocketCarryText(carry) {
|
|
122930
|
+
if (carry?.state !== "refused") return "";
|
|
122931
|
+
const { code, reason } = pocketCarryReason(carry);
|
|
122916
122932
|
if (CARRY_WAIT_CODES.has(code)) {
|
|
122917
122933
|
return ` Your pocket accounts stay in the old pool's records for now (${reason}). The money in them is safe. The wallet tries again by itself in a minute.`;
|
|
122918
122934
|
}
|
|
@@ -123142,7 +123158,9 @@ function createSuccessionScheduler(options) {
|
|
|
123142
123158
|
},
|
|
123143
123159
|
log = () => {
|
|
123144
123160
|
},
|
|
123145
|
-
carry = carryPocketBook
|
|
123161
|
+
carry = carryPocketBook,
|
|
123162
|
+
onSettled = () => {
|
|
123163
|
+
}
|
|
123146
123164
|
} = options;
|
|
123147
123165
|
const now = options.now ?? Date.now;
|
|
123148
123166
|
const randomInt9 = options.randomInt ?? cryptoRandomInt;
|
|
@@ -123337,6 +123355,12 @@ function createSuccessionScheduler(options) {
|
|
|
123337
123355
|
} catch {
|
|
123338
123356
|
}
|
|
123339
123357
|
}
|
|
123358
|
+
if (counts.legsDone > (job.legsDone ?? 0) && counts.transactions.length) {
|
|
123359
|
+
try {
|
|
123360
|
+
onSettled(counts.transactions.at(-1));
|
|
123361
|
+
} catch {
|
|
123362
|
+
}
|
|
123363
|
+
}
|
|
123340
123364
|
if (result.state === "moved") {
|
|
123341
123365
|
if ((prepared.extraAccounts ?? 0) > 0) return save2(store, job, { ...counts, attempts: 0, lastCode: void 0, nextTryAtMs: now() });
|
|
123342
123366
|
return save2(store, job, { ...counts, state: "moved", attempts: 0, lastCode: void 0, nextTryAtMs: void 0 });
|
|
@@ -123539,11 +123563,30 @@ function createSuccessionScheduler(options) {
|
|
|
123539
123563
|
}
|
|
123540
123564
|
return views;
|
|
123541
123565
|
}
|
|
123566
|
+
function pocketCarries() {
|
|
123567
|
+
const carries = [];
|
|
123568
|
+
for (const entry of listEntries()) {
|
|
123569
|
+
let job;
|
|
123570
|
+
try {
|
|
123571
|
+
job = readSuccessionJob(storeOf(entry.from), entry.from);
|
|
123572
|
+
} catch {
|
|
123573
|
+
job = void 0;
|
|
123574
|
+
}
|
|
123575
|
+
if (typeof job?.to !== "string") continue;
|
|
123576
|
+
carries.push({
|
|
123577
|
+
from: job.from,
|
|
123578
|
+
to: job.to,
|
|
123579
|
+
pocketCarry: job.pocketCarry ? { state: job.pocketCarry.state, code: job.pocketCarry.code ?? null } : null
|
|
123580
|
+
});
|
|
123581
|
+
}
|
|
123582
|
+
return carries;
|
|
123583
|
+
}
|
|
123542
123584
|
return Object.freeze({
|
|
123543
123585
|
tick,
|
|
123544
123586
|
beforePay,
|
|
123545
123587
|
status,
|
|
123546
123588
|
openJobs,
|
|
123589
|
+
pocketCarries,
|
|
123547
123590
|
running: () => Boolean(active),
|
|
123548
123591
|
acknowledge(from, state) {
|
|
123549
123592
|
try {
|
|
@@ -123578,6 +123621,7 @@ function startSuccessionScheduler({ store, openStore, session, underLease, log =
|
|
|
123578
123621
|
status: () => [],
|
|
123579
123622
|
acknowledge: () => false,
|
|
123580
123623
|
openJobs: () => [],
|
|
123624
|
+
pocketCarries: () => [],
|
|
123581
123625
|
running: () => false
|
|
123582
123626
|
});
|
|
123583
123627
|
}
|
|
@@ -125356,7 +125400,7 @@ function createWalletTools({
|
|
|
125356
125400
|
deps: ops.autoPockets ?? {}
|
|
125357
125401
|
});
|
|
125358
125402
|
if (money.autoPockets === true) autoPockets.start();
|
|
125359
|
-
const mover = createMoveScheduler({ session, underLease, log, deps: ops.move && typeof ops.move === "object" ? ops.move : {} });
|
|
125403
|
+
const mover = createMoveScheduler({ session, underLease, log, onSettled: refreshAtFinality, deps: ops.move && typeof ops.move === "object" ? ops.move : {} });
|
|
125360
125404
|
if (ops.move !== false) mover.start();
|
|
125361
125405
|
const succession = ops.succession === false ? void 0 : {
|
|
125362
125406
|
successionStatus,
|
|
@@ -125462,7 +125506,9 @@ function createWalletTools({
|
|
|
125462
125506
|
...eta === void 0 ? {} : { etaSeconds: eta },
|
|
125463
125507
|
...Number.isInteger(item.legsTotal) ? { legsDone: Number.isInteger(item.legsDone) ? item.legsDone : 0, legsTotal: item.legsTotal } : {},
|
|
125464
125508
|
...typeof item.lastCode === "string" && item.lastCode ? { code: item.lastCode } : {},
|
|
125465
|
-
...Number.isFinite(item.updatedAtMs) ? { updatedAt: new Date(item.updatedAtMs).toISOString() } : {}
|
|
125509
|
+
...Number.isFinite(item.updatedAtMs) ? { updatedAt: new Date(item.updatedAtMs).toISOString() } : {},
|
|
125510
|
+
// The pocket book carry (scheduler.mjs carryPockets): a refused carry keeps the pockets in the old pool's records.
|
|
125511
|
+
...item.pocketCarry && typeof item.pocketCarry.state === "string" ? { pocketCarry: { state: item.pocketCarry.state, code: typeof item.pocketCarry.code === "string" ? item.pocketCarry.code : null } } : {}
|
|
125466
125512
|
};
|
|
125467
125513
|
});
|
|
125468
125514
|
};
|
|
@@ -126931,7 +126977,7 @@ function createWalletTools({
|
|
|
126931
126977
|
const moveStatus = {
|
|
126932
126978
|
name: "wallet_move_status",
|
|
126933
126979
|
title: "Pool switch status",
|
|
126934
|
-
description: "Use this when the user asks why their balance moved, whether the pool switch is done, or when an answer shows poolSwitch, or when wallet_balance shows movingAtomic or pools. When the facilitator switches to a new pool, this wallet moves the whole balance there by itself (no fee, no step by the user); poolSwitches lists each switch with its state (pending, scheduled, running, done, failed) and a plain message to tell the user. Also called wallet_pool_switch_status. When the facilitator retires a pool, this wallet moves its whole balance from the old pool to the new one by itself (no fee, no step by the user): each leg pays one account of the old pool to the facilitator, which credits the same amount to a one-time address of this wallet in the new pool. This tool reads the move's state and every leg (amountAtomic, state planned|paid|credited|done|failed, moveId); it pays nothing and signs nothing. state: none (no move announced), waiting or running (it continues by itself), done, failed (code, detail, and next say why and what to do).",
|
|
126980
|
+
description: "Use this when the user asks why their balance moved, whether the pool switch is done, or when an answer shows poolSwitch, or when wallet_balance shows movingAtomic or pools. When the facilitator switches to a new pool, this wallet moves the whole balance there by itself (no fee, no step by the user); poolSwitches lists each switch with its state (pending, scheduled, running, done, failed) and a plain message to tell the user, plus pocketCarry when the wallet tried to move the old pool's pocket records to the new pool (state carried, completed, already, none, or refused with a code; the message says what a refusal means). Also called wallet_pool_switch_status. When the facilitator retires a pool, this wallet moves its whole balance from the old pool to the new one by itself (no fee, no step by the user): each leg pays one account of the old pool to the facilitator, which credits the same amount to a one-time address of this wallet in the new pool. This tool reads the move's state and every leg (amountAtomic, state planned|paid|credited|done|failed, moveId); it pays nothing and signs nothing. state: none (no move announced), waiting or running (it continues by itself), done, failed (code, detail, and next say why and what to do).",
|
|
126935
126981
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
126936
126982
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
126937
126983
|
async run() {
|
|
@@ -126970,7 +127016,14 @@ function createWalletTools({
|
|
|
126970
127016
|
startSuccession: { value: () => {
|
|
126971
127017
|
if (!succession || successionHandle) return;
|
|
126972
127018
|
try {
|
|
126973
|
-
successionHandle = succession.startSuccessionScheduler({
|
|
127019
|
+
successionHandle = succession.startSuccessionScheduler({
|
|
127020
|
+
store: session.openStore(),
|
|
127021
|
+
openStore: () => session.openStore(),
|
|
127022
|
+
session,
|
|
127023
|
+
underLease,
|
|
127024
|
+
log,
|
|
127025
|
+
deps: { onSettled: refreshAtFinality }
|
|
127026
|
+
});
|
|
126974
127027
|
} catch (error) {
|
|
126975
127028
|
log(`MCP_POOL_SWITCH_SCHEDULER_NOT_STARTED: ${error?.name ?? "Error"}`);
|
|
126976
127029
|
}
|
|
@@ -132595,6 +132648,55 @@ async function spendGate(args, values, deps, io, { amountAtomic, again }) {
|
|
|
132595
132648
|
if (!followed || index < 0 || resolve37(followed) === walletFile) return args;
|
|
132596
132649
|
return [...args.slice(0, index + 1), followed, ...args.slice(index + 2)];
|
|
132597
132650
|
}
|
|
132651
|
+
async function pocketFillGate(args, values, deps, io) {
|
|
132652
|
+
if (!values.has("--wallet") || values.has("--dwell-check")) return args;
|
|
132653
|
+
const walletFile = resolve37(values.get("--wallet"));
|
|
132654
|
+
const session = lazySpendSession(walletFile, values, deps);
|
|
132655
|
+
let handle;
|
|
132656
|
+
try {
|
|
132657
|
+
handle = (deps.startSuccessionScheduler ?? startSuccessionScheduler)({
|
|
132658
|
+
session,
|
|
132659
|
+
openStore: () => session.openStore(),
|
|
132660
|
+
underLease: sessionLease(session),
|
|
132661
|
+
log: () => {
|
|
132662
|
+
},
|
|
132663
|
+
env: deps.env
|
|
132664
|
+
});
|
|
132665
|
+
} catch {
|
|
132666
|
+
return args;
|
|
132667
|
+
}
|
|
132668
|
+
let carries;
|
|
132669
|
+
try {
|
|
132670
|
+
await Promise.resolve(handle.tick?.()).catch(() => {
|
|
132671
|
+
});
|
|
132672
|
+
carries = handle.pocketCarries?.() ?? [];
|
|
132673
|
+
} catch {
|
|
132674
|
+
carries = [];
|
|
132675
|
+
} finally {
|
|
132676
|
+
handle.stop?.();
|
|
132677
|
+
}
|
|
132678
|
+
if (!carries.length) return args;
|
|
132679
|
+
const home = setupHome(deps.env);
|
|
132680
|
+
const pathOf = (pool) => resolve37(homeWalletPath(home, pool));
|
|
132681
|
+
let target = walletFile;
|
|
132682
|
+
for (let hop = 0; hop < carries.length; hop += 1) {
|
|
132683
|
+
const next = carries.find((item) => pathOf(item.from) === target && existsSync(pathOf(item.to)));
|
|
132684
|
+
if (!next) break;
|
|
132685
|
+
target = pathOf(next.to);
|
|
132686
|
+
}
|
|
132687
|
+
for (const item of carries.filter((entry) => pathOf(entry.to) === target)) {
|
|
132688
|
+
const carry = pocketCarryReason(item.pocketCarry);
|
|
132689
|
+
if (carry.done) continue;
|
|
132690
|
+
if (carry.waits) {
|
|
132691
|
+
throw new PublicFailure(`wallet_pool_switch_wait_retry_same_request: Your facilitator switched to a new pool, and your pocket records are not in the new pool's wallet yet (${carry.reason}). Your pockets and the money in them are safe; nothing was filled or signed. Run the same pocket fill command again in 60 s`);
|
|
132692
|
+
}
|
|
132693
|
+
throw new PublicFailure(`wallet_pool_switch_failed: Your facilitator switched to a new pool, and the wallet could not move your pocket records to the new pool's wallet (${carry.reason}). Your pockets and the money in them are safe; nothing was filled or signed. Tell the operator this code. lastCode: ${carry.code}`);
|
|
132694
|
+
}
|
|
132695
|
+
if (target === walletFile) return args;
|
|
132696
|
+
io.err("pool switch: pocket fill uses your wallet of the facilitator's new pool\n");
|
|
132697
|
+
const index = args.indexOf("--wallet");
|
|
132698
|
+
return index < 0 ? args : [...args.slice(0, index + 1), target, ...args.slice(index + 2)];
|
|
132699
|
+
}
|
|
132598
132700
|
async function runCurl(values, deps) {
|
|
132599
132701
|
const io = deps.io;
|
|
132600
132702
|
const policy = createSpendPolicy({
|
|
@@ -133943,7 +134045,7 @@ var COMMANDS = [
|
|
|
133943
134045
|
}
|
|
133944
134046
|
}
|
|
133945
134047
|
},
|
|
133946
|
-
run: (args, values, deps) => deps.pocketMain(["fill", ...args])
|
|
134048
|
+
run: async (args, values, deps, io) => deps.pocketMain(["fill", ...await pocketFillGate(args, values, deps, io)])
|
|
133947
134049
|
},
|
|
133948
134050
|
{
|
|
133949
134051
|
name: "pocket release",
|