shinjuku-shield 0.3.110 → 0.3.111
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 +22 -9
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.111. 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.111
|
|
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.111 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.111 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.111", "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": "ca9504f8356a05d2a1fc36428f6443419e6943406d11e201d4fa2ff9d6c84814",
|
|
5
|
+
"bytes": 8333810,
|
|
6
|
+
"sourceCommit": "b7bf7b1d3617d779db6012f60c35e34f7e8363da",
|
|
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-27T14:
|
|
1040
|
+
"publishedAt": "2026-10-27T14:51:57.097Z"
|
|
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.111",
|
|
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": "ca9504f8",
|
|
7
|
+
"shinjukuSha256": "ca9504f8356a05d2a1fc36428f6443419e6943406d11e201d4fa2ff9d6c84814",
|
|
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
|
@@ -119461,10 +119461,11 @@ function refusalSay(a, tool, again, npmVersion) {
|
|
|
119461
119461
|
if (a.refundArrived === true) return `The seller did not take it. ${yours} is back in your private balance. ${other}`;
|
|
119462
119462
|
return `The seller did not take it; ${total2 ? `${total2} USDC` : "your money"} comes back by itself${when}. ${other}`;
|
|
119463
119463
|
}
|
|
119464
|
+
const askAgain = typeof a.newRequestId === "string" && a.newRequestId ? `To ask again, use request_id ${a.newRequestId}; it pays again.` : "A new request_id pays again.";
|
|
119464
119465
|
if (code2 === "p03_float_receipt_pruned" && a.conversationNotKept === true) {
|
|
119465
|
-
return
|
|
119466
|
+
return `Paid once, not again: the wallet keeps no copy of a private conversation. ${askAgain}`;
|
|
119466
119467
|
}
|
|
119467
|
-
if (code2 === "p03_float_receipt_pruned") return
|
|
119468
|
+
if (code2 === "p03_float_receipt_pruned") return `This request was paid more than 10 minutes ago. ${askAgain}`;
|
|
119468
119469
|
if (/^p03_(float|resource_payment)_request_(id_conflict|data_mismatch)$/.test(code2)) {
|
|
119469
119470
|
const fresh = typeof a.newRequestId === "string" && a.newRequestId ? `request_id ${a.newRequestId}` : "a new request_id";
|
|
119470
119471
|
return `Nothing was paid: this request_id belongs to an earlier payment. For this request, ask again with ${fresh}.`;
|
|
@@ -120032,6 +120033,10 @@ function transferSay(a) {
|
|
|
120032
120033
|
const sent = usdcText2(a.send?.amountAtomic);
|
|
120033
120034
|
const kept2 = a.send?.keptPrivateAtomic && a.send.keptPrivateAtomic !== "0" ? usdcText2(a.send.keptPrivateAtomic) : null;
|
|
120034
120035
|
const later = "If this chat ends first, it continues at your next request.";
|
|
120036
|
+
if (a.replayed === true) {
|
|
120037
|
+
const fresh = typeof a.newRequestId === "string" && a.newRequestId ? `request_id ${a.newRequestId}` : "a new request_id";
|
|
120038
|
+
return `This request_id belongs to an earlier transfer to ${to}; this call moved nothing. To transfer again, ask with ${fresh}.`;
|
|
120039
|
+
}
|
|
120035
120040
|
switch (a.stage) {
|
|
120036
120041
|
case "selling":
|
|
120037
120042
|
return `Selling the token for ${usdc6}; then it goes privately to ${to}. ${later}`;
|
|
@@ -127543,7 +127548,9 @@ ${canonical5}`;
|
|
|
127543
127548
|
const float = floatRefusal(error);
|
|
127544
127549
|
if (float && float[0] === code2) {
|
|
127545
127550
|
const [, detail, sharedNext] = float;
|
|
127546
|
-
const
|
|
127551
|
+
const prunedId = code2 === "p03_float_receipt_pruned" ? newRequestIdFor(requestId) : void 0;
|
|
127552
|
+
const sharedFloatNext = inference ? sharedNext.replace(/\bx402_pay\b/g, tool) : sharedNext;
|
|
127553
|
+
const floatNext = prunedId ? `${sharedFloatNext}: use the new request_id "${prunedId}"` : sharedFloatNext;
|
|
127547
127554
|
let one;
|
|
127548
127555
|
try {
|
|
127549
127556
|
one = readBalance(paidStore ?? session.openStore());
|
|
@@ -127578,6 +127585,7 @@ ${canonical5}`;
|
|
|
127578
127585
|
...typeof error?.feeAtomic === "string" ? { feeAtomic: error.feeAtomic } : {},
|
|
127579
127586
|
// conversationNotKept (floatPay.mjs finishedPruned): a private conversation, whose answer the wallet never kept.
|
|
127580
127587
|
...error?.conversationNotKept === true ? { conversationNotKept: true } : {},
|
|
127588
|
+
...prunedId ? { newRequestId: prunedId } : {},
|
|
127581
127589
|
// floatId: Shinjuku's id of this payment, which wallet_receipts shows with the refund's state and transaction (realSpeed3
|
|
127582
127590
|
// force-live 5r, 2026-10-22: the answer gave no id, so nobody could look the refund up).
|
|
127583
127591
|
// refundAtomic and refundEtaSeconds (Shinjuku's time) for a proven refund; an unproven send carries ambiguous: true.
|
|
@@ -131714,7 +131722,7 @@ ${canonical5}`;
|
|
|
131714
131722
|
properties: {
|
|
131715
131723
|
amount: { type: "string", description: 'USDC to shield, like "0.37" (up to 6 decimals). Pass this or amount_atomic.' },
|
|
131716
131724
|
amount_atomic: { type: "string", pattern: "^[1-9][0-9]*$", description: "USDC to shield, in atomic units (1000000 = 1 USDC, 370000 = 0.37 USDC): any amount from 10000 (0.01 USDC) while the balance stays at most 5 USDC." },
|
|
131717
|
-
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional.
|
|
131725
|
+
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional. Leave it out for a new deposit (the answer names the id it made). Pass the request_id of an earlier answer only to read or continue that deposit." }
|
|
131718
131726
|
},
|
|
131719
131727
|
required: [],
|
|
131720
131728
|
additionalProperties: false
|
|
@@ -131732,7 +131740,7 @@ ${canonical5}`;
|
|
|
131732
131740
|
amount: { type: "string", description: 'USDC to send, like "2" or "0.37" (up to 6 decimals). Pass this or amount_atomic.' },
|
|
131733
131741
|
amount_atomic: { type: "string", pattern: "^[1-9][0-9]*$", description: "USDC to send, in atomic units (1000000 = 1 USDC)." },
|
|
131734
131742
|
to: { type: "string", description: "The receiving Solana address (base58), exactly as the user gave it. Leave it out to send to the owner's own wallet when the owner set exactly one (wallet_balance session.unshield.to); with none or several set, pass it." },
|
|
131735
|
-
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional.
|
|
131743
|
+
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional. Leave it out for a new send (the answer names the id it made). Pass the request_id of an earlier answer only to read or continue that send." },
|
|
131736
131744
|
parts: { type: "integer", minimum: 1, maximum: 8, description: "Optional, default 1: send the amount as this many smaller payments (a private send), of random sizes in whole 0.01 USDC: the sizes differ only when the amount allows it (0.02 USDC in 2 goes as 0.01 + 0.01; privateSend lists each amount). Each one carries at least 10000 atomic (0.01 USDC). Above 1 it needs max_delay_minutes 1-60 (smaller payments with no wait are refused: they would leave together). Each one is sent after a random wait of up to max_delay_minutes (the first one too), so the chain shows no single exit of this amount at this time; max_delay_minutes alone delays one exit. " + SEND_RUNS_ON + ` Late ones never go together. While some are unsent, x402_pay may spend only the rest of the balance. The plan is saved in the wallet before the first one, so the same request_id (with the same \`parts\` and max_delay_minutes) continues after a restart and never sends one twice; the answer's privateSend lists each one (state, amount, when it may go, transactions), sentAtomic, and remainingAtomic. The user confirms the whole send once. Each one is a full unshield, so it takes as long as one, and the facilitator pays the network fee of each. Privacy limit (tell the user): every payment goes to the SAME \`to\`, so anyone who adds up that address's incoming transfers sees the total; the smaller payments hide the time and the single amount of the exit, not the sum the address received. wallet_cancel with the same request_id stops the ones not sent yet (their value stays in the private balance); while one is being sent, that call waits for it to finish, up to about ${CALL_BUDGET_MS / 1e3} s.` },
|
|
131737
131745
|
max_delay_minutes: { type: "integer", minimum: 0, maximum: 60, description: "Optional, default 0: each smaller payment, the first included, is sent after a random wait of up to this many minutes (a private send)." }
|
|
131738
131746
|
},
|
|
@@ -131773,7 +131781,7 @@ ${canonical5}`;
|
|
|
131773
131781
|
properties: {
|
|
131774
131782
|
amount: { type: "string", description: 'USDC to shield, like "0.37" (up to 6 decimals). Pass this or amount_atomic, unless action is cancel.' },
|
|
131775
131783
|
amount_atomic: { type: "string", pattern: "^[1-9][0-9]*$", description: "USDC to shield, in atomic units (1000000 = 1 USDC, 370000 = 0.37 USDC): any amount from 10000 (0.01 USDC) while the balance stays at most 5 USDC. Required unless action is cancel." },
|
|
131776
|
-
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional for a deposit, needed for cancel.
|
|
131784
|
+
request_id: { type: "string", pattern: "^[A-Za-z0-9._:-]{1,128}$", description: "Optional for a deposit, needed for cancel. Leave it out for a new deposit (the answer names the id it made). Pass the request_id of an earlier answer (with the same amount) only to read, continue, or cancel that deposit." },
|
|
131777
131785
|
action: { type: "string", enum: ["deposit", "cancel"], description: "deposit (the default): start or read this deposit. cancel: close this request's one-time address while nothing at all reached it (no amount needed)." }
|
|
131778
131786
|
},
|
|
131779
131787
|
required: [],
|
|
@@ -132674,7 +132682,10 @@ ${canonical5}`;
|
|
|
132674
132682
|
} else if (sendStop === "split") {
|
|
132675
132683
|
next = `${sentSome ? "Nothing more was sent" : "Nothing was sent yet"}: the private balance holds the next payment of this send, but the wallet must first get that money ready to send. It does that by itself, at each wallet request. Do not cancel the send: tell the user it is not stuck. In a few minutes, ${poll} again: it continues the send where it stopped (it never sends a payment twice)`;
|
|
132676
132684
|
}
|
|
132677
|
-
|
|
132685
|
+
if (extra.replayed === true) {
|
|
132686
|
+
next = `This request_id belongs to an earlier transfer; this call moved nothing new. About that transfer: ${next.replace(/\.$/, "")}. To transfer again, call wallet_transfer_token with the new request_id "${extra.newRequestId}"`;
|
|
132687
|
+
}
|
|
132688
|
+
const inBox = plan.approval?.by === "elicitation" && extra.replayed !== true;
|
|
132678
132689
|
return json3({
|
|
132679
132690
|
ok: true,
|
|
132680
132691
|
...view2,
|
|
@@ -132796,7 +132807,9 @@ ${canonical5}`;
|
|
|
132796
132807
|
const existing = readTransferToken(store, id);
|
|
132797
132808
|
if (existing) {
|
|
132798
132809
|
if (!sameTransfer(existing, request)) return transferReused(id);
|
|
132799
|
-
|
|
132810
|
+
if (TRANSFER_RUNNING_STATES.has(existing.state) && existing.state !== "sold_waiting_room" || tidyOpen(existing)) return await answerSoon(id, { reused: true }, call);
|
|
132811
|
+
const ended = ["done", "cancelled"].includes(existing.state) ? { replayed: true, newRequestId: `${id.slice(0, 31)}-${Date.now().toString(36)}` } : {};
|
|
132812
|
+
return transferAnswer(existing, { reused: true, ...ended });
|
|
132800
132813
|
}
|
|
132801
132814
|
} catch (error) {
|
|
132802
132815
|
return transferRefusal(error, "transfer_plan_unreadable", "tell your owner");
|
|
@@ -133042,7 +133055,7 @@ ${canonical5}`;
|
|
|
133042
133055
|
token_mint: { type: "string", description: "The base58 mint address of the token to sell, like DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263 (BONK). Never a symbol." },
|
|
133043
133056
|
amount_atomic: { type: "string", pattern: "^[1-9][0-9]*$", description: 'How much of the token to sell, in its own base units: "1250000" = 1.25 of a 6-decimal token.' },
|
|
133044
133057
|
to: { type: "string", description: "The receiving Solana address (base58), exactly as the user gave it. It receives USDC and must already be able to receive USDC." },
|
|
133045
|
-
request_id: { type: "string", pattern: "^[A-Za-z0-9_-]{1,40}$", description: "
|
|
133058
|
+
request_id: { type: "string", pattern: "^[A-Za-z0-9_-]{1,40}$", description: "A new name for each new transfer, like move-bonk-k7q2 (an id an earlier transfer used only reads that transfer and moves nothing); wallet_transfer_token_status takes it." },
|
|
133046
133059
|
parts: { type: "integer", minimum: 2, maximum: 8, description: "Optional, default 2: the USDC leaves as this many payments of random sizes in whole 0.01 USDC (each at least 0.01 USDC; the sizes differ only when the amount allows it: 0.02 USDC in 2 goes as 0.01 + 0.01)." },
|
|
133047
133060
|
max_delay_minutes: { type: "integer", minimum: 1, maximum: 60, description: "Optional, default 30: each payment waits a random time up to this many minutes before it leaves." },
|
|
133048
133061
|
max_slippage_bps: { type: "integer", minimum: 1, maximum: 300, description: "Optional, default 50 (0.5 %): the sell fails rather than give less than the quote minus this." },
|