shinjuku-shielded 0.3.23 → 0.3.24

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": "10c8bdfe8bd677ce6f50d143c1af4b28d5b3f653c5c65f6356f1034e6f5840df",
5
- "bytes": 11132902,
6
- "sourceCommit": "f718d9f247df010a8e2b5045666be78877dd3933",
4
+ "sha256": "5e07378e3416f54223cbb56fc04d28bed3106dfbdef58b62570ad0469f27aade",
5
+ "bytes": 11135322,
6
+ "sourceCommit": "6427ce901fd81417ad60ea6364079db32785626c",
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.23",
3
+ "version": "0.3.24",
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": "10c8bdfe",
7
- "shinjukuSha256": "10c8bdfe8bd677ce6f50d143c1af4b28d5b3f653c5c65f6356f1034e6f5840df",
6
+ "shinjukuRelease": "5e07378e",
7
+ "shinjukuSha256": "5e07378e3416f54223cbb56fc04d28bed3106dfbdef58b62570ad0469f27aade",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
@@ -118895,7 +118895,27 @@ function snapshotFile(store) {
118895
118895
  return file;
118896
118896
  }
118897
118897
  function captureWalStates(store) {
118898
- return Object.fromEntries(store.listWal().sort().map((name) => [name, String(store.readWal(name)?.state)]));
118898
+ return Object.fromEntries(store.listWal().sort().map((name) => [name, walStateOf(name, store.readWal(name))]));
118899
+ }
118900
+ var SUCCESSION_JOB_SCHEMA = "carbon-shielded-wallet/pool-succession/v1";
118901
+ function walStateOf(name, record) {
118902
+ if (name.startsWith("succ-") && record?.schema === SUCCESSION_JOB_SCHEMA && canonicalAtomic(String(record.movedAtomic))) {
118903
+ return `${record.state}|${record.movedAtomic}`;
118904
+ }
118905
+ return String(record?.state);
118906
+ }
118907
+ function movedInAfterSnapshot(store, state, snapshot) {
118908
+ let total = 0n;
118909
+ for (const name of store.listWal()) {
118910
+ if (!name.startsWith("succ-")) continue;
118911
+ const record = store.readWal(name);
118912
+ if (record?.schema !== SUCCESSION_JOB_SCHEMA || record.to !== state.pool || !canonicalAtomic(String(record.movedAtomic))) continue;
118913
+ const before = Object.hasOwn(snapshot.walStates, name) ? String(snapshot.walStates[name]) : void 0;
118914
+ const kept = before?.includes("|") ? before.split("|")[1] : before === "moved" ? String(record.movedAtomic) : "0";
118915
+ const moved = BigInt(record.movedAtomic) - (canonicalAtomic(kept) ? BigInt(kept) : 0n);
118916
+ if (moved > 0n) total += moved;
118917
+ }
118918
+ return total;
118899
118919
  }
118900
118920
  function snapshotFromRecovery({ state, programId, recovery, history, walStates, fresh, now = Date.now() }) {
118901
118921
  if (!Array.isArray(recovery?.recovered)) throw new Error("balance_snapshot_recovery_invalid");
@@ -119110,7 +119130,8 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
119110
119130
  detail.unspentAtomic = unspentAtomic.toString();
119111
119131
  const settling = [];
119112
119132
  const movable = snapshot.outputs.filter((output2) => output2.spendStatus === "succession-movable");
119113
- const successionMovableAtomic = sum2(movable.map((output2) => output2.valueAtomic));
119133
+ const movedInAtomic = movedInAfterSnapshot(store, state, snapshot);
119134
+ const successionMovableAtomic = sum2(movable.map((output2) => output2.valueAtomic)) + movedInAtomic;
119114
119135
  detail.successionMovableAtomic = successionMovableAtomic.toString();
119115
119136
  detail.unspentAccounts = [...unspent.values()].filter((output2) => output2.kind === "account").length;
119116
119137
  detail.unspentNotes = [...unspent.values()].filter((output2) => output2.kind === "note").length;
@@ -119240,7 +119261,10 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
119240
119261
  const anchorIndex = canonicalAtomic(snapshot.anchorIndex) ? BigInt(snapshot.anchorIndex) : void 0;
119241
119262
  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
119263
  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 (settling.length) {
119264
+ if (movedInAtomic > 0n) {
119265
+ 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`);
119266
+ }
119267
+ if (settling.length || movedInAtomic > 0n) {
119244
119268
  reasons.push(...settlingReasons);
119245
119269
  return report("stale", spendable + successionMovableAtomic, next ?? refreshCommand(state, snapshot.programId));
119246
119270
  }
@@ -122048,6 +122072,7 @@ init_store();
122048
122072
  var import_web3127 = __toESM(require_index_cjs(), 1);
122049
122073
  init_chain2();
122050
122074
  init_walk();
122075
+ init_receiptTransaction();
122051
122076
  init_serviceUrl();
122052
122077
  import { randomInt as randomInt4 } from "node:crypto";
122053
122078
 
@@ -122417,6 +122442,18 @@ async function chainNowSeconds(connection) {
122417
122442
  return info.data.readBigInt64LE(32);
122418
122443
  }
122419
122444
  var sameInputs = (context, inputs) => Array.isArray(context.publicInputs) && context.publicInputs.length === inputs.length && context.publicInputs.every((value, index) => fieldHex4(value) === inputs[index]);
122445
+ var landedIsLeg = (context, body) => {
122446
+ if (Array.isArray(context.publicInputs)) return sameInputs(context, body.publicInputBytesHex);
122447
+ try {
122448
+ const payload2 = Buffer.concat([
122449
+ Buffer.from(String(body.proofBytesHex).replace(/^0x/, ""), "hex"),
122450
+ ...body.publicInputBytesHex.map((value) => Buffer.from(String(value).replace(/^0x/, ""), "hex"))
122451
+ ]);
122452
+ return contextPayloadMatches(context, payload2);
122453
+ } catch {
122454
+ return false;
122455
+ }
122456
+ };
122420
122457
  async function destinationMoves(deps, sourceDomain) {
122421
122458
  if (typeof deps.loadDestinationReport !== "function") {
122422
122459
  throw refuse7("wallet_succession_history_unavailable", "no successor-pool history to confirm the move against");
@@ -122488,6 +122525,9 @@ async function runSuccessionMove({ store, verified, source, facilitator, connect
122488
122525
  let rebuilds = 0;
122489
122526
  for (; ; ) {
122490
122527
  if (leg.state === "confirmed" || leg.state === "dropped") return void 0;
122528
+ if (leg.state === "failed" && leg.lastCode === "wallet_succession_leg_receipt_invalid" && typeof leg.transaction === "string" && leg.body) {
122529
+ leg = save2(leg, { state: "relayed" });
122530
+ }
122491
122531
  if (leg.state === "failed") leg = save2(leg, { state: "planned" });
122492
122532
  if (leg.state === "planned") {
122493
122533
  const inputs = [...leg.inputs.account ? [leg.inputs.account] : [], ...leg.inputs.notes];
@@ -122585,7 +122625,7 @@ async function runSuccessionMove({ store, verified, source, facilitator, connect
122585
122625
  const moves = await destinationMoves(deps, sourceDomain);
122586
122626
  const landed = moves.find((context) => context.provenance?.signature === leg.transaction);
122587
122627
  if (landed) {
122588
- if (!sameInputs(landed, leg.body.publicInputBytesHex)) {
122628
+ if (!landedIsLeg(landed, leg.body)) {
122589
122629
  save2(leg, { state: "failed", lastCode: "wallet_succession_leg_receipt_invalid" });
122590
122630
  throw refuse7("wallet_succession_leg_receipt_invalid", "the relay's transaction is not this leg's move; tell the operator");
122591
122631
  }
@@ -122624,7 +122664,7 @@ async function runSuccessionMove({ store, verified, source, facilitator, connect
122624
122664
 
122625
122665
  // wallet/src/succession/scheduler.mjs
122626
122666
  init_successorHistories();
122627
- var SUCCESSION_JOB_SCHEMA = "carbon-shielded-wallet/pool-succession/v1";
122667
+ var SUCCESSION_JOB_SCHEMA2 = "carbon-shielded-wallet/pool-succession/v1";
122628
122668
  var SUCCESSION_DELAY_MIN_MS = 5 * 6e4;
122629
122669
  var SUCCESSION_DELAY_MAX_MS = 30 * 6e4;
122630
122670
  var SUCCESSION_LATE_START_MAX_MS = 6e4;
@@ -122724,10 +122764,10 @@ function successionMessage(job) {
122724
122764
  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
122765
  function readSuccessionJob(store, fromPool) {
122726
122766
  const record = store.readWal(successionJobName(fromPool));
122727
- return record?.schema === SUCCESSION_JOB_SCHEMA && record.from === fromPool ? record : void 0;
122767
+ return record?.schema === SUCCESSION_JOB_SCHEMA2 && record.from === fromPool ? record : void 0;
122728
122768
  }
122729
122769
  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 === SUCCESSION_JOB_SCHEMA);
122770
+ 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
122771
  }
122732
122772
  var noticeKey = (job) => job.state === "failed-retry" ? `failed:${job.lastCode ?? ""}` : PUBLIC_STATE[job.state];
122733
122773
  var SUCCESSION_NOTICE_SCHEMA = "carbon-shielded-wallet/pool-succession-notice/v1";
@@ -122877,6 +122917,7 @@ function createSuccessionScheduler(options) {
122877
122917
  const startedAtMs = now();
122878
122918
  const lateStart = /* @__PURE__ */ new Map();
122879
122919
  const recordCheckedAt = /* @__PURE__ */ new Map();
122920
+ const receiptRecheck = /* @__PURE__ */ new Set();
122880
122921
  let active;
122881
122922
  let closed = false;
122882
122923
  const listEntries = () => {
@@ -122960,7 +123001,7 @@ function createSuccessionScheduler(options) {
122960
123001
  return job;
122961
123002
  }
122962
123003
  const base = (entry, value, verified) => ({
122963
- schema: SUCCESSION_JOB_SCHEMA,
123004
+ schema: SUCCESSION_JOB_SCHEMA2,
122964
123005
  from: entry.from,
122965
123006
  to: verified?.successor ?? entry.to,
122966
123007
  record: entry.record,
@@ -123078,8 +123119,13 @@ function createSuccessionScheduler(options) {
123078
123119
  }
123079
123120
  case "move-scheduled":
123080
123121
  return now() >= startAt(job) ? startRun(entry) : job;
123081
- case "moving":
123082
123122
  case "failed-retry":
123123
+ if (job.lastCode === "wallet_succession_leg_receipt_invalid" && job.updatedAtMs < startedAtMs && !receiptRecheck.has(entry.from)) {
123124
+ receiptRecheck.add(entry.from);
123125
+ job = save2(store, job, { permanent: false, nextTryAtMs: now() });
123126
+ }
123127
+ return now() >= (job.nextTryAtMs ?? 0) ? startRun(entry) : job;
123128
+ case "moving":
123083
123129
  return now() >= (job.nextTryAtMs ?? 0) ? startRun(entry) : job;
123084
123130
  default:
123085
123131
  return job;