shinjuku-shielded 0.3.9 → 0.3.11

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 CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schema": "carbon-shielded-wallet/bundle-manifest/v1",
3
3
  "file": "shinjuku-wallet.mjs",
4
- "sha256": "701809bdf80ea16a9d16105f067998029d2a0f03d69b885720a08d806eae30d4",
5
- "bytes": 10943907,
6
- "sourceCommit": "88b144748643ad89029b53d4feeb52ee9b26f13a",
4
+ "sha256": "a9b9ea19ca82a7e4fe991f01050aae148bea45db0bb46be31c22df310e081969",
5
+ "bytes": 10949292,
6
+ "sourceCommit": "043825750e3f2f6138f265ad8b909764455bc24d",
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.9",
3
+ "version": "0.3.11",
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": "701809bd",
7
- "shinjukuSha256": "701809bdf80ea16a9d16105f067998029d2a0f03d69b885720a08d806eae30d4",
6
+ "shinjukuRelease": "a9b9ea19",
7
+ "shinjukuSha256": "a9b9ea19ca82a7e4fe991f01050aae148bea45db0bb46be31c22df310e081969",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
@@ -50517,11 +50517,15 @@ var init_chain2 = __esm({
50517
50517
  // Production E1 pool 45mh (since the tag-28 window): the same proxy
50518
50518
  // (UNDERMARKET_HISTORY_PROXY_POOLS = AAG16,45mh). AAG16 stays: an old
50519
50519
  // wallet home still reads its retired pool.
50520
- "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR": "http://d6xg3phhurxhzqcsgh2mh52yf744labhrnd7mducwynlertfsjzyslqd.onion/"
50520
+ "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR": "http://d6xg3phhurxhzqcsgh2mh52yf744labhrnd7mducwynlertfsjzyslqd.onion/",
50521
+ // Production E1 pool F7MW (since 2026-10-12): the same proxy serves it beside 45mh, which
50522
+ // stays while its wallets move out (the move walks 45mh).
50523
+ F7MWGF8vG8Bv3Y4pRRFqky5YzZndGtQaUXbMMvpmtoRV: "http://d6xg3phhurxhzqcsgh2mh52yf744labhrnd7mducwynlertfsjzyslqd.onion/"
50521
50524
  });
50522
50525
  PINNED_HISTORY_HTTPS = Object.freeze({
50523
50526
  AAG16mNWTtC1sBeu2tTVTwWjqWXCefLTCByVPj5X3kV8: "https://pay.shinjukustaition.com/history-proxy/",
50524
- "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR": "https://pay.shinjukustaition.com/history-proxy/"
50527
+ "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR": "https://pay.shinjukustaition.com/history-proxy/",
50528
+ F7MWGF8vG8Bv3Y4pRRFqky5YzZndGtQaUXbMMvpmtoRV: "https://pay.shinjukustaition.com/history-proxy/"
50525
50529
  });
50526
50530
  HISTORY_RPC_OWN = "own";
50527
50531
  historyRpcErrors = /* @__PURE__ */ new WeakSet();
@@ -61582,7 +61586,9 @@ var init_errorCodes = __esm({
61582
61586
  "move_body_invalid",
61583
61587
  "move_liquidity_wait",
61584
61588
  "move_payer_unavailable_retry_later",
61589
+ "move_payment_in_flight",
61585
61590
  "move_pool_not_draining",
61591
+ "move_quote_open",
61586
61592
  "move_refund_to_invalid",
61587
61593
  "move_to_pool_unknown",
61588
61594
  "move_unknown",
@@ -116601,14 +116607,15 @@ var NPX_PACKAGE = "shinjuku-shielded";
116601
116607
  var MCP_SERVER_NAME = "shinjuku-shielded";
116602
116608
  var P03_BINDING2 = "carbon-shielded-exact/svm-v3";
116603
116609
  var PRODUCTION = Object.freeze({
116604
- pool: "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR",
116610
+ pool: "F7MWGF8vG8Bv3Y4pRRFqky5YzZndGtQaUXbMMvpmtoRV",
116605
116611
  program: "8PYPw3FSFTMbvSneXdcoH6jNoN4VD23nHwPY2A2riUy1",
116606
116612
  network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
116607
116613
  asset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
116608
116614
  memoService: DEFAULT_FACILITATOR_ORIGIN
116609
116615
  });
116610
116616
  var RETIRED_POOLS = Object.freeze({
116611
- AAG16mNWTtC1sBeu2tTVTwWjqWXCefLTCByVPj5X3kV8: "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR"
116617
+ // Setup moves an AAG16 config.json to the pool the facilitator runs NOW (setup.mjs compares with the release's pool).
116618
+ AAG16mNWTtC1sBeu2tTVTwWjqWXCefLTCByVPj5X3kV8: "F7MWGF8vG8Bv3Y4pRRFqky5YzZndGtQaUXbMMvpmtoRV"
116612
116619
  });
116613
116620
  function retiredPoolText(pool) {
116614
116621
  const next = RETIRED_POOLS[pool];
@@ -116875,6 +116882,7 @@ var TIMEOUT_MS = 3e4;
116875
116882
  var HEX642 = /^[0-9a-f]{64}$/;
116876
116883
  var DIR = /^[0-9a-f]{8}$/;
116877
116884
  var BASE58_KEY2 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
116885
+ var V3_ONION_KEY = /^http:\/\/[a-z2-7]{56}\.onion(\/|$)/;
116878
116886
  var ED25519_SPKI_PREFIX3 = Buffer.from("302a300506032b6570032100", "hex");
116879
116887
  var fail21 = (code, detail) => new Error(`${code}: ${detail}`);
116880
116888
  function canonicalJson(value) {
@@ -116913,8 +116921,8 @@ function checkBody(body) {
116913
116921
  } catch {
116914
116922
  key = void 0;
116915
116923
  }
116916
- if (!key || !key.startsWith("https://") && !/^http:\/\/(127\.0\.0\.1|localhost)(:|\/|$)/.test(key)) {
116917
- throw fail21("wallet_channel_invalid", "a channel proof-tool set names a facilitator that is not an https URL");
116924
+ if (!key || !key.startsWith("https://") && !V3_ONION_KEY.test(key) && !/^http:\/\/(127\.0\.0\.1|localhost)(:|\/|$)/.test(key)) {
116925
+ throw fail21("wallet_channel_invalid", "a channel proof-tool set names a facilitator that is not an https URL or a v3 onion");
116918
116926
  }
116919
116927
  return Object.freeze({ facilitator: key, pool: set.pool, dir: set.dir, sumsSha256: set.sumsSha256 });
116920
116928
  });
@@ -117073,8 +117081,8 @@ function channelListsSet(body, { facilitator, pool, dir, sumsSha256 }) {
117073
117081
  // wallet/src/setup/proofTools.mjs
117074
117082
  var PINNED_PROOF_TOOLS = Object.freeze({
117075
117083
  [DEFAULT_FACILITATOR_ORIGIN]: Object.freeze({
117076
- dir: "47678912",
117077
- sumsSha256: "47678912949d7da8b705c399edf03d2367465f6eb581b00a059356373baed28e"
117084
+ dir: "5bed238f",
117085
+ sumsSha256: "5bed238f3696208ca3a8e66d206e5fffc85f1823e959abe1901c2d57c17bcdf3"
117078
117086
  })
117079
117087
  });
117080
117088
  var UPDATE_NEXT = "update the wallet: npx -y shinjuku-shielded@latest setup";
@@ -119548,7 +119556,11 @@ var MOVE_SERVER_CODES = Object.freeze([
119548
119556
  "move_payer_unavailable_retry_later",
119549
119557
  "move_liquidity_wait",
119550
119558
  "move_unknown",
119551
- "pool_draining"
119559
+ "pool_draining",
119560
+ // 409s of an UNPAID leg (production 2026-10-12 20:48Z: a re-quote of the same body met the open quote and the leg failed
119561
+ // challenge_missing:409). Both mean "this body is quoted or being paid now"; the leg waits with the same body.
119562
+ "move_quote_open",
119563
+ "move_payment_in_flight"
119552
119564
  ]);
119553
119565
  var hash11 = (value) => sha256Hex2(Buffer.from(value, "utf8"));
119554
119566
  var sum = (values) => values.reduce((total, value) => total + BigInt(value ?? 0), 0n);
@@ -119826,6 +119838,13 @@ function refusalOf(serverCode3) {
119826
119838
  return { code: "wallet_move_payer_busy_retry_later", transient: true };
119827
119839
  case "move_liquidity_wait":
119828
119840
  return { code: "wallet_move_payer_busy_retry_later", transient: true };
119841
+ // The drain holds an open quote for this exact body until its validBefore + 60 s: ask again after that, same body.
119842
+ case "move_quote_open":
119843
+ return { code: "wallet_move_leg_paused", transient: true };
119844
+ // Only an unpaid request reaches here (moveFetch passes every request that carries payment bytes), so this wallet
119845
+ // holds no bytes for the leg: it never asks for a new quote to pay; it keeps the leg and asks again later.
119846
+ case "move_payment_in_flight":
119847
+ return { code: "wallet_move_leg_paused", transient: true };
119829
119848
  case "pool_draining":
119830
119849
  return { code: "wallet_move_route_missing", transient: true };
119831
119850
  case "move_pool_not_draining":
@@ -120051,10 +120070,11 @@ async function runMove({
120051
120070
  if (seen.refusal) {
120052
120071
  const refusal2 = refusalOf(seen.refusal);
120053
120072
  if (unsent && !refusal2.transient) open3(sourcePath, passphrase2).removeWal(moveWalName(from.pool, leg.n));
120054
- log(`MOVE_LEG_REFUSED n=${leg.n} ${seen.refusal}`);
120073
+ log(`${refusal2.transient ? "MOVE_LEG_WAIT" : "MOVE_LEG_REFUSED"} n=${leg.n} ${seen.refusal}`);
120055
120074
  return answer(refusal2.transient ? "waiting" : "failed", refusal2.code, { ...base, serverCode: seen.refusal });
120056
120075
  }
120057
120076
  const code = firstCode4(error);
120077
+ const shown = /^[a-z0-9_]+:[0-9]{3}(?=$|[\s;(])/.exec(String(error?.message ?? ""))?.[0] ?? code;
120058
120078
  if (LEG_REFUSED_CODES.has(code)) {
120059
120079
  save2({ state: "refused", code, refusedAtMs: now() });
120060
120080
  log(`MOVE_LEG_REFUSED n=${leg.n} ${code}`);
@@ -120065,8 +120085,8 @@ async function runMove({
120065
120085
  return answer("waiting", "wallet_move_leg_paused", { ...base, payCode: code });
120066
120086
  }
120067
120087
  if (unsent) open3(sourcePath, passphrase2).removeWal(moveWalName(from.pool, leg.n));
120068
- log(`MOVE_LEG_FAILED n=${leg.n} ${code}`);
120069
- return answer(unsent ? "failed" : "waiting", unsent ? "wallet_move_leg_failed" : "wallet_move_leg_paused", { ...base, payCode: code });
120088
+ log(`MOVE_LEG_FAILED n=${leg.n} ${shown}`);
120089
+ return answer(unsent ? "failed" : "waiting", unsent ? "wallet_move_leg_failed" : "wallet_move_leg_paused", { ...base, payCode: shown });
120070
120090
  }
120071
120091
  save2({ state: "paid", paidAtMs: now(), ...isSolanaSignature(result?.receipt?.transaction) ? { settleTransaction: result.receipt.transaction } : {} });
120072
120092
  log(`MOVE_LEG_PAID n=${leg.n}`);
@@ -128221,7 +128241,7 @@ var CLI2 = "shinjuku-wallet";
128221
128241
  var P03_BINDING3 = "carbon-shielded-exact/svm-v3";
128222
128242
  var GUIDE = Object.freeze({
128223
128243
  program: "8PYPw3FSFTMbvSneXdcoH6jNoN4VD23nHwPY2A2riUy1",
128224
- pool: "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR",
128244
+ pool: "F7MWGF8vG8Bv3Y4pRRFqky5YzZndGtQaUXbMMvpmtoRV",
128225
128245
  mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
128226
128246
  network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
128227
128247
  facilitator: DEFAULT_FACILITATOR_ORIGIN
@@ -129571,7 +129591,8 @@ var COMMANDS = [
129571
129591
  "--add-to for Claude Desktop or Cursor: a host config whose mcpServers is not a JSON object, or that has a different shinjuku-shielded entry (without --force), is left alone. Otherwise the old file is copied to <file>.bak-<time> (mode 0600 on Linux and macOS; on Windows the folder's access list) and the new file replaces it in one rename.",
129572
129592
  "The provers are Linux programs. Linux: ready. Windows: the wallet runs them through WSL; setup checks that wsl.exe runs (wsl --install -d Ubuntu otherwise). macOS: not supported; setup says so and creates nothing.",
129573
129593
  "Run it again at any time: it never changes an existing wallet, keeps the recorded caps unless you pass new ones, checks every proof-tool file again, downloads what is missing or newer, and rewrites config.json.",
129574
- "Then mcp needs no flags: npx -y shinjuku-shielded mcp reads config.json (a flag on the command line still wins). Before setup, mcp in a terminal offers to run setup; started by an agent host, it serves shinjuku_setup, which runs this same setup after you confirm in the host."
129594
+ "Then mcp needs no flags: npx -y shinjuku-shielded mcp reads config.json (a flag on the command line still wins). Before setup, mcp in a terminal offers to run setup; started by an agent host, it serves shinjuku_setup, which runs this same setup after you confirm in the host.",
129595
+ "A command that takes --pool (balance, recover, deposit, add-funds, and others) takes it, and the passphrase of this home's wallet, from config.json when you leave them out: shinjuku-wallet balance needs no flags. A flag or SHIELDED_WALLET_PASSPHRASE still wins; init and restore never use config.json, and move reads it itself."
129575
129596
  ],
129576
129597
  next: `start it from your agent host with npx -y shinjuku-shielded mcp (or ${CLI2} mcp), then ask your agent "what is my balance"`,
129577
129598
  run: (args, values, deps, io) => deps.setupMain(values, { ...deps, io })
@@ -130237,6 +130258,55 @@ function checkValue(spec, value) {
130237
130258
  }
130238
130259
  return void 0;
130239
130260
  }
130261
+ var NO_CONFIG_DEFAULTS = /* @__PURE__ */ new Set(["mcp", "setup", "init", "restore", "move"]);
130262
+ function configDefaults(command, args, deps) {
130263
+ const unchanged = { args, passphrase: void 0 };
130264
+ if (NO_CONFIG_DEFAULTS.has(command.name) || command.beforeValidate) return unchanged;
130265
+ const has2 = (name) => command.flags.some((spec) => spec.name === name);
130266
+ const given = parseFlags(command, args);
130267
+ const passphraseFileSpec = command.flags.find((spec) => spec.name === "--passphrase-file");
130268
+ const envPassphrase = Boolean(deps.env[PASSPHRASE_ENV2]);
130269
+ const wantPool = has2("--pool") && !given.has("--pool") && !given.has("--wallet");
130270
+ const wantFile = Boolean(passphraseFileSpec) && !given.has("--passphrase-file") && (passphraseFileSpec.required || !envPassphrase);
130271
+ const wantEnv = !passphraseFileSpec && command.env.includes(PASSPHRASE_ENV2) && !envPassphrase;
130272
+ if (!wantPool && !wantFile && !wantEnv) return unchanged;
130273
+ const home = setupHome(deps.env);
130274
+ const config = setupConfigOf(home);
130275
+ if (!config) return unchanged;
130276
+ const added = wantPool ? ["--pool", config.pool] : [];
130277
+ const pool = wantPool ? config.pool : given.get("--pool");
130278
+ const homePools = [config.pool, ...(config.previousPools ?? []).map((entry) => entry.pool)];
130279
+ const ownWallet = given.has("--wallet") ? homePools.some((entry) => resolve33(given.get("--wallet")) === resolve33(homeWalletPath(home, entry))) : homePools.includes(pool);
130280
+ if (!ownWallet || !wantFile && !wantEnv) return { args: [...args, ...added], passphrase: void 0 };
130281
+ const where = `config.json (${join32(home, "config.json")})`;
130282
+ if (wantFile) {
130283
+ if (!config.passphraseFile) {
130284
+ throw new UsageError(`${command.name} needs the wallet passphrase: ${where} names no passphrase file; pass --passphrase-file <file>, or rerun ${CLI2} setup (it keeps the wallet)`, command);
130285
+ }
130286
+ return { args: [...args, ...added, "--passphrase-file", config.passphraseFile], passphrase: void 0 };
130287
+ }
130288
+ let text3;
130289
+ try {
130290
+ text3 = config.passphraseFile ? readSecretText(config.passphraseFile, "the passphrase file") : void 0;
130291
+ } catch (error) {
130292
+ if (error instanceof SecretFileEncodingError) throw new PublicFailure(error.message);
130293
+ text3 = void 0;
130294
+ }
130295
+ if (!text3) {
130296
+ throw new UsageError(`${PASSPHRASE_ENV2} is not set, and the passphrase file that ${where} names (${config.passphraseFile ?? "none"}) could not be read or is empty: export ${PASSPHRASE_ENV2}=<your wallet passphrase>, or rerun ${CLI2} setup (it keeps the wallet)`, command);
130297
+ }
130298
+ return { args: [...args, ...added], passphrase: text3 };
130299
+ }
130300
+ function lendPassphrase(passphrase2) {
130301
+ if (passphrase2 === void 0) return () => {
130302
+ };
130303
+ const saved = process.env[PASSPHRASE_ENV2];
130304
+ process.env[PASSPHRASE_ENV2] = passphrase2;
130305
+ return () => {
130306
+ if (saved === void 0) delete process.env[PASSPHRASE_ENV2];
130307
+ else process.env[PASSPHRASE_ENV2] = saved;
130308
+ };
130309
+ }
130240
130310
  function validate3(command, values, env) {
130241
130311
  const missing = command.flags.filter((spec) => (spec.required || spec.requiredUnless && !values.has(spec.requiredUnless)) && !values.has(spec.name));
130242
130312
  if (missing.length === 1) {
@@ -130447,7 +130517,9 @@ var RELAYED_DEPOSIT_UNIT = Object.freeze({
130447
130517
  DFCCPHdw7pH9vKk9FEN9z6cy9M1UKjF168j7HfLwxYk3: "1000000",
130448
130518
  AAG16mNWTtC1sBeu2tTVTwWjqWXCefLTCByVPj5X3kV8: "1000000",
130449
130519
  // The production E1 pool since the tag-28 window (its pool plan: poolDenominationAtomic 1000000).
130450
- "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR": "1000000"
130520
+ "45mhosfA2MuygZWeqYRVcEZX2Q3gA8KR8FwP6AZkK1zR": "1000000",
130521
+ // The production E1 pool since 2026-10-12 (GET /api/x402/deposit: depositUnitAtomic 1000000).
130522
+ F7MWGF8vG8Bv3Y4pRRFqky5YzZndGtQaUXbMMvpmtoRV: "1000000"
130451
130523
  });
130452
130524
  async function runDeposit(args, values, deps) {
130453
130525
  const unit = values.has("--relay") && !values.has("--pool-denomination") ? RELAYED_DEPOSIT_UNIT[values.get("--pool")] : void 0;
@@ -131309,17 +131381,24 @@ async function runShinjukuWallet(argv, overrides = {}) {
131309
131381
  io.out(commandHelp(command));
131310
131382
  return 0;
131311
131383
  }
131312
- const commandArgs = command.normalizeArgs ? command.normalizeArgs(command, args) : args;
131384
+ const defaults = configDefaults(command, command.normalizeArgs ? command.normalizeArgs(command, args) : args, deps);
131385
+ const commandArgs = defaults.args;
131386
+ const runDeps = defaults.passphrase === void 0 ? deps : { ...deps, env: { ...deps.env, [PASSPHRASE_ENV2]: defaults.passphrase } };
131313
131387
  values = parseFlags(command, commandArgs);
131314
- const skip = command.beforeValidate?.(values, deps, commandArgs) === SKIP_VALIDATE;
131315
- if (!skip) validate3(command, values, deps.env);
131388
+ const skip = command.beforeValidate?.(values, runDeps, commandArgs) === SKIP_VALIDATE;
131389
+ if (!skip) validate3(command, values, runDeps.env);
131316
131390
  retiredPoolGuard(command, values, io);
131317
- const rpc2 = skip ? { args: commandArgs } : rpcFileArgs(command, commandArgs, values, deps, io);
131391
+ const rpc2 = skip ? { args: commandArgs } : rpcFileArgs(command, commandArgs, values, runDeps, io);
131318
131392
  try {
131319
- applyStoredChannel({ home: setupHome(deps.env) });
131393
+ applyStoredChannel({ home: setupHome(runDeps.env) });
131320
131394
  } catch {
131321
131395
  }
131322
- await command.run(rpc2.args, values, rpc2.url === void 0 ? deps : { ...deps, rpcUrlFromFile: rpc2.url }, io);
131396
+ const restorePassphrase = lendPassphrase(defaults.passphrase);
131397
+ try {
131398
+ await command.run(rpc2.args, values, rpc2.url === void 0 ? runDeps : { ...runDeps, rpcUrlFromFile: rpc2.url }, io);
131399
+ } finally {
131400
+ restorePassphrase();
131401
+ }
131323
131402
  if (!command.nextInOutput) io.err(`next: ${hintForThisRun(command.nextAfterRun?.(values, deps) ?? command.next, values)}
131324
131403
  `);
131325
131404
  writeRunResult(deps, command, 0);