shinjuku-shielded 0.3.26 → 0.3.27
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 +86 -7
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": "adb0f68b23e192445ecb391a89f3e05dba89f05d0177aacdb092fbea3539fa85",
|
|
5
|
+
"bytes": 11154518,
|
|
6
|
+
"sourceCommit": "e8d63cd7fd58f3f334eea244fa5dc0e7b1c5c6be",
|
|
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.27",
|
|
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": "adb0f68b",
|
|
7
|
+
"shinjukuSha256": "adb0f68b23e192445ecb391a89f3e05dba89f05d0177aacdb092fbea3539fa85",
|
|
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
|
@@ -119132,7 +119132,7 @@ function publicUrl(value) {
|
|
|
119132
119132
|
return null;
|
|
119133
119133
|
}
|
|
119134
119134
|
}
|
|
119135
|
-
function computeBalance({ store, snapshotRead, source = "local", now = Date.now() }) {
|
|
119135
|
+
function computeBalance({ store, snapshotRead, source = "local", now = Date.now(), firstDepositEstimate = false }) {
|
|
119136
119136
|
const state = store.state;
|
|
119137
119137
|
const decimals = Number(state.decimals);
|
|
119138
119138
|
const records = store.listWal().sort().map((name) => {
|
|
@@ -119217,6 +119217,12 @@ function computeBalance({ store, snapshotRead, source = "local", now = Date.now(
|
|
|
119217
119217
|
}
|
|
119218
119218
|
return report("empty", 0n, proved ? `deposit ${proved.depositId} is proved but not sent: back up (shinjuku-wallet help backup-export), then rerun the same deposit command with --submit --service <facilitator URL>` : "no deposit yet: deposit one of two ways (shinjuku-wallet help deposit). 1) The more private path, shinjuku-wallet deposit --relay: no SOL is needed; its first run prints a one-time address to fund with USDC from an exchange withdrawal or an outside privacy pool. 2) Send USDC and about 0.01 SOL to your solanaFeePayer address (printed by init), then run shinjuku-wallet deposit without --relay; that deposit edge is public. If this wallet only holds restored keys or receives payments, run balance --refresh");
|
|
119219
119219
|
}
|
|
119220
|
+
const valueRecords = records.filter((entry) => !["payment-proof", "privacy-cash", "add-funds"].includes(entry.type) && !(entry.type === "deposit" && (entry.phase === "pre-chain" || entry.phase === "void")));
|
|
119221
|
+
const landedDeposits = valueRecords.filter((entry) => entry.type === "deposit" && entry.phase === "done" && typeof entry.record?.receipt?.signature === "string" && entry.record.receipt.signature.length > 0 && canonicalAtomic(entry.record.amountAtomic));
|
|
119222
|
+
if (firstDepositEstimate && !snapshotRead?.unreadable && !state.restoredFromRecoveryText && landedDeposits.length > 0 && landedDeposits.length === valueRecords.length) {
|
|
119223
|
+
reasons.push("the first check of the pool history runs now; this number is your own deposit");
|
|
119224
|
+
return report("stale", sum2(landedDeposits.map((entry) => entry.record.amountAtomic)), refreshCommand(state));
|
|
119225
|
+
}
|
|
119220
119226
|
reasons.push(snapshotRead?.unreadable ? `the saved balance walk is unreadable (${snapshotRead.unreadable}); it is only a cache` : state.restoredFromRecoveryText && !couldHoldValue ? "this wallet was rebuilt from the recovery text (restore) and has no balance walk yet: its value is on chain, not in this file" : "this wallet has deposit or payment records but no balance walk yet");
|
|
119221
119227
|
return report("unknown", null, refreshCommand(state));
|
|
119222
119228
|
}
|
|
@@ -125228,6 +125234,7 @@ async function runUnshield({
|
|
|
125228
125234
|
return { selfPayTransaction: paid.transaction ?? null, exitTransaction: exit.signature ?? null };
|
|
125229
125235
|
}
|
|
125230
125236
|
var BALANCE_REFRESH_WAIT_MS = 2e4;
|
|
125237
|
+
var BALANCE_REFRESH_GRACE_MS = 2e3;
|
|
125231
125238
|
function movingAtomic(store) {
|
|
125232
125239
|
let moving = 0n;
|
|
125233
125240
|
try {
|
|
@@ -125282,6 +125289,9 @@ function localBalanceOf(store) {
|
|
|
125282
125289
|
var CAP_BALANCE_WAIT_MS = 35e3;
|
|
125283
125290
|
var CAP_BALANCE_RETRY_MS = 5e3;
|
|
125284
125291
|
var REFRESH_RETRY_MS = 6e4;
|
|
125292
|
+
var FINALITY_POLL_MS = 2e3;
|
|
125293
|
+
var FINALITY_WAIT_MS = 6e4;
|
|
125294
|
+
var PUBLIC_READ_ANSWER_MS = 3e3;
|
|
125285
125295
|
var SWITCH_WAIT_MS = 4e4;
|
|
125286
125296
|
var ELICIT_TIMEOUT_MS = 5 * 6e4;
|
|
125287
125297
|
var POLL_SECONDS2 = 30;
|
|
@@ -125478,6 +125488,51 @@ function createWalletTools({
|
|
|
125478
125488
|
}
|
|
125479
125489
|
return refreshRun;
|
|
125480
125490
|
}
|
|
125491
|
+
let finalityWait;
|
|
125492
|
+
let finalityTarget;
|
|
125493
|
+
let finalityDeadline = 0;
|
|
125494
|
+
let finalityClosed = false;
|
|
125495
|
+
const finalityPollMs = ops.finalityPollMs ?? FINALITY_POLL_MS;
|
|
125496
|
+
const finalityWaitMs = ops.finalityWaitMs ?? FINALITY_WAIT_MS;
|
|
125497
|
+
function refreshAtFinality(signature) {
|
|
125498
|
+
if (typeof signature !== "string" || !signature || finalityClosed) return;
|
|
125499
|
+
finalityTarget = signature;
|
|
125500
|
+
finalityDeadline = Date.now() + finalityWaitMs;
|
|
125501
|
+
if (finalityWait) return;
|
|
125502
|
+
const statuses = ops.signatureStatuses ?? ((signatures) => session.connection.getSignatureStatuses(signatures));
|
|
125503
|
+
finalityWait = (async () => {
|
|
125504
|
+
for (; ; ) {
|
|
125505
|
+
const watched = finalityTarget;
|
|
125506
|
+
let status;
|
|
125507
|
+
try {
|
|
125508
|
+
status = (await statuses([watched]))?.value?.[0] ?? void 0;
|
|
125509
|
+
} catch {
|
|
125510
|
+
status = void 0;
|
|
125511
|
+
}
|
|
125512
|
+
if (finalityClosed) return;
|
|
125513
|
+
if (watched === finalityTarget && status?.err) {
|
|
125514
|
+
log("MCP_FINALITY_WAIT_FAILED_TRANSACTION");
|
|
125515
|
+
return;
|
|
125516
|
+
}
|
|
125517
|
+
if (watched === finalityTarget && status?.confirmationStatus === "finalized") {
|
|
125518
|
+
log("MCP_FINALITY_REFRESH");
|
|
125519
|
+
await refreshShared().catch(() => {
|
|
125520
|
+
});
|
|
125521
|
+
return;
|
|
125522
|
+
}
|
|
125523
|
+
if (Date.now() + finalityPollMs > finalityDeadline) {
|
|
125524
|
+
log("MCP_FINALITY_WAIT_EXPIRED");
|
|
125525
|
+
return;
|
|
125526
|
+
}
|
|
125527
|
+
await new Promise((resolve38) => {
|
|
125528
|
+
const timer = setTimeout(resolve38, finalityPollMs);
|
|
125529
|
+
timer.unref?.();
|
|
125530
|
+
});
|
|
125531
|
+
}
|
|
125532
|
+
})().finally(() => {
|
|
125533
|
+
finalityWait = void 0;
|
|
125534
|
+
});
|
|
125535
|
+
}
|
|
125481
125536
|
async function refreshIfStale() {
|
|
125482
125537
|
let stale;
|
|
125483
125538
|
try {
|
|
@@ -125760,6 +125815,7 @@ function createWalletTools({
|
|
|
125760
125815
|
const floatPaid = float?.state === "receipt";
|
|
125761
125816
|
const amounts = floatPaid ? { priceAtomic: float.priceAtomic, feeAtomic: float.feeAtomic, amountAtomic: float.paidAtomic } : { priceAtomic: receipt.amountAtomic ?? null, feeAtomic: "0", amountAtomic: receipt.amountAtomic ?? null };
|
|
125762
125817
|
const one = paidStore ? localBalanceOf(paidStore) : null;
|
|
125818
|
+
if (receipt.replayed !== true) refreshAtFinality(floatPaid ? float.floatSettleTransaction : transaction);
|
|
125763
125819
|
mark("mcp-result");
|
|
125764
125820
|
return answerResult(paidAnswerContent({
|
|
125765
125821
|
status: response.status,
|
|
@@ -125886,21 +125942,23 @@ function createWalletTools({
|
|
|
125886
125942
|
);
|
|
125887
125943
|
}
|
|
125888
125944
|
const publicRead = withTimeout((ops.readPublicBalance ?? readOwnPublicBalance)({ session, store }), PUBLIC_READ_TIMEOUT_MS).then((read2) => ({ read: read2 }), (error2) => ({ error: error2 }));
|
|
125889
|
-
let report = computeBalance({ store, snapshotRead: readBalanceSnapshot(store), source: "local" });
|
|
125945
|
+
let report = computeBalance({ store, snapshotRead: readBalanceSnapshot(store), source: "local", firstDepositEstimate: true });
|
|
125890
125946
|
let refresh = {};
|
|
125891
125947
|
const recentlyFailed = refreshFailedAt && Date.now() - refreshFailedAt < REFRESH_RETRY_MS && !refreshRun;
|
|
125892
125948
|
if (report.split?.shieldedAtomic != null && report.status === "stale") {
|
|
125893
|
-
if (!recentlyFailed) refreshShared().catch(() => {
|
|
125949
|
+
if (!recentlyFailed && !finalityWait) refreshShared().catch(() => {
|
|
125894
125950
|
});
|
|
125895
125951
|
refresh = { refreshing: true };
|
|
125896
125952
|
} else if (report.split?.shieldedAtomic == null && recentlyFailed) {
|
|
125897
125953
|
refresh = { refreshed: false, refreshError: refreshFailedCode ?? "mcp_refresh_failed" };
|
|
125898
125954
|
} else if (report.split?.shieldedAtomic == null) {
|
|
125899
125955
|
const run5 = refreshShared().then(() => "done", (error2) => ({ failed: errorCode2(error2, "mcp_refresh_failed") }));
|
|
125900
|
-
const
|
|
125901
|
-
const timer = setTimeout(() => resolve38("waiting"),
|
|
125956
|
+
const waitFor = (ms) => Promise.race([run5, new Promise((resolve38) => {
|
|
125957
|
+
const timer = setTimeout(() => resolve38("waiting"), ms);
|
|
125902
125958
|
timer.unref?.();
|
|
125903
125959
|
})]);
|
|
125960
|
+
let outcome = await waitFor(balanceRefreshWaitMs);
|
|
125961
|
+
if (outcome === "waiting") outcome = await waitFor(BALANCE_REFRESH_GRACE_MS);
|
|
125904
125962
|
if (outcome === "done") {
|
|
125905
125963
|
try {
|
|
125906
125964
|
store = session.openStore();
|
|
@@ -125914,9 +125972,28 @@ function createWalletTools({
|
|
|
125914
125972
|
refresh = { refreshed: false, refreshError: outcome.failed };
|
|
125915
125973
|
}
|
|
125916
125974
|
}
|
|
125917
|
-
const
|
|
125975
|
+
const answered = await Promise.race([
|
|
125976
|
+
publicRead,
|
|
125977
|
+
new Promise((resolve38) => {
|
|
125978
|
+
const timer = setTimeout(() => resolve38({ reading: true }), PUBLIC_READ_ANSWER_MS);
|
|
125979
|
+
timer.unref?.();
|
|
125980
|
+
})
|
|
125981
|
+
]);
|
|
125982
|
+
if (answered.reading) {
|
|
125983
|
+
publicRead.then(({ error: late2 }) => {
|
|
125984
|
+
if (late2) log(`MCP_PUBLIC_READ_FAILED_LATE ${late2?.name ?? "Error"}`);
|
|
125985
|
+
});
|
|
125986
|
+
}
|
|
125987
|
+
const { read, error } = answered;
|
|
125918
125988
|
let unshielded;
|
|
125919
|
-
if (
|
|
125989
|
+
if (answered.reading) {
|
|
125990
|
+
unshielded = {
|
|
125991
|
+
unshieldedAtomic: null,
|
|
125992
|
+
unshielded: null,
|
|
125993
|
+
unshieldedSolLamports: null,
|
|
125994
|
+
unshieldedReason: "reading: the RPC read of the wallet's own USDC account did not answer in 3 s; the shielded balance above does not wait for it. Call wallet_balance again later"
|
|
125995
|
+
};
|
|
125996
|
+
} else if (read) {
|
|
125920
125997
|
unshielded = {
|
|
125921
125998
|
unshieldedAtomic: read.unshieldedAtomic,
|
|
125922
125999
|
unshielded: formatAtomic(BigInt(read.unshieldedAtomic), Number(store.state.decimals)),
|
|
@@ -126620,6 +126697,7 @@ function createWalletTools({
|
|
|
126620
126697
|
job.result = result;
|
|
126621
126698
|
log(`MCP_${kind.toUpperCase()}_DONE requestId=${job.requestId}`);
|
|
126622
126699
|
if (kind !== "unshield") afterShield(job);
|
|
126700
|
+
else refreshAtFinality(result?.exitTransaction ?? result?.selfPayTransaction);
|
|
126623
126701
|
}, (error) => {
|
|
126624
126702
|
job.failedStage = job.stage;
|
|
126625
126703
|
job.state = "failed";
|
|
@@ -126881,6 +126959,7 @@ function createWalletTools({
|
|
|
126881
126959
|
};
|
|
126882
126960
|
Object.defineProperties(tools, {
|
|
126883
126961
|
close: { value: () => {
|
|
126962
|
+
finalityClosed = true;
|
|
126884
126963
|
autoPockets.close();
|
|
126885
126964
|
mover.close();
|
|
126886
126965
|
adopter.close();
|