shinjuku-shielded 0.3.54 → 0.3.55
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 +4 -4
- package/package.json +3 -3
- package/shinjuku-wallet.mjs +221 -43
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": "70ff655b113c19d39c8594566c77d38fe7d459ea415f66cda1c09919841ad1a9",
|
|
5
|
+
"bytes": 12128720,
|
|
6
|
+
"sourceCommit": "d13f57d40a91eecbd9b06acd4f8c587d34bc256a",
|
|
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",
|
|
@@ -1282,5 +1282,5 @@
|
|
|
1282
1282
|
"version": "1.8.0"
|
|
1283
1283
|
}
|
|
1284
1284
|
],
|
|
1285
|
-
"publishedAt": "2026-10-
|
|
1285
|
+
"publishedAt": "2026-10-21T23:25:11.303Z"
|
|
1286
1286
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shielded",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.55",
|
|
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": "70ff655b",
|
|
7
|
+
"shinjukuSha256": "70ff655b113c19d39c8594566c77d38fe7d459ea415f66cda1c09919841ad1a9",
|
|
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
|
@@ -42692,7 +42692,7 @@ async function routeFacilitatorsOverOnion(argv2, {
|
|
|
42692
42692
|
if (!groups.has(key)) groups.set(key, { onions });
|
|
42693
42693
|
routes.set(origin, groups.get(key));
|
|
42694
42694
|
routes.set(payHostOf(origin), groups.get(key));
|
|
42695
|
-
const hosts = onions.map((onion) => `${new URL(onion).host.slice(0, 8)}
|
|
42695
|
+
const hosts = onions.map((onion) => `${new URL(onion).host.slice(0, 8)}...`).join(", ");
|
|
42696
42696
|
const source = pinned ? "pinned in this wallet" : `published by ${origin}`;
|
|
42697
42697
|
err(`tor: ${origin} is reached over its onion service ${hosts} (${onions.length > 1 ? `${source}; the first to answer serves this run` : source}), so no Tor exit and no front such as Cloudflare sees these requests
|
|
42698
42698
|
`);
|
|
@@ -42702,7 +42702,7 @@ async function routeFacilitatorsOverOnion(argv2, {
|
|
|
42702
42702
|
}
|
|
42703
42703
|
}
|
|
42704
42704
|
for (const [origin, onions] of Object.entries(PINNED_HISTORY_ONIONS)) {
|
|
42705
|
-
const group = { onions, path: HISTORY_PROBE_PATH, onNone: () => err(`tor: no history-proxy onion answered its start probe (${onions.length} tried); the pool history reads go to the pinned onion ${new URL(onions[0]).host.slice(0, 8)}
|
|
42705
|
+
const group = { onions, path: HISTORY_PROBE_PATH, onNone: () => err(`tor: no history-proxy onion answered its start probe (${onions.length} tried); the pool history reads go to the pinned onion ${new URL(onions[0]).host.slice(0, 8)}... and wait for it
|
|
42706
42706
|
`) };
|
|
42707
42707
|
groups.set(onions.join(" "), group);
|
|
42708
42708
|
routes.set(origin, group);
|
|
@@ -42757,7 +42757,7 @@ async function routeFacilitatorsOverOnion(argv2, {
|
|
|
42757
42757
|
}
|
|
42758
42758
|
};
|
|
42759
42759
|
}
|
|
42760
|
-
var SITE_ONIONS, PINNED_FACILITATOR_ONIONS, HISTORY_ONIONS, PINNED_HISTORY_ONIONS, HISTORY_PROBE_PATH, FACILITATOR_FLAGS, V3_ONION, DISCOVERY_TIMEOUT_MS, WARM_TIMEOUT_MS, RACE_TIMEOUT_MS, routedGroups, routedOnions, routedOrigins, onionsOfOrigin, GLOBAL_DISPATCHER, onionDispatchers;
|
|
42760
|
+
var SITE_ONIONS, PINNED_FACILITATOR_ONIONS, HISTORY_ONIONS, PINNED_HISTORY_ONIONS, HISTORY_PROBE_PATH, FACILITATOR_FLAGS, V3_ONION, DISCOVERY_TIMEOUT_MS, WARM_TIMEOUT_MS, RACE_TIMEOUT_MS, routedGroups, routedOnions, routedOrigins, onionsOfOrigin, routesOverOnion, GLOBAL_DISPATCHER, onionDispatchers;
|
|
42761
42761
|
var init_facilitatorOnion = __esm({
|
|
42762
42762
|
"wallet/src/net/facilitatorOnion.mjs"() {
|
|
42763
42763
|
"use strict";
|
|
@@ -42788,6 +42788,7 @@ var init_facilitatorOnion = __esm({
|
|
|
42788
42788
|
routedOnions = () => [...new Set(routedGroups.flatMap((group) => group.winner ? [group.winner] : group.onions))];
|
|
42789
42789
|
routedOrigins = /* @__PURE__ */ new Map();
|
|
42790
42790
|
onionsOfOrigin = (origin) => routedOrigins.get(origin) ?? PINNED_FACILITATOR_ONIONS[origin] ?? [];
|
|
42791
|
+
routesOverOnion = (origin) => routedOrigins.has(origin);
|
|
42791
42792
|
GLOBAL_DISPATCHER = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.1");
|
|
42792
42793
|
onionDispatchers = /* @__PURE__ */ new Map();
|
|
42793
42794
|
}
|
|
@@ -47037,7 +47038,7 @@ async function proxyEntry(argv2, run5, { err = (text3) => process.stderr.write(t
|
|
|
47037
47038
|
}
|
|
47038
47039
|
return reexec(options.args, options.mode, options.proxy);
|
|
47039
47040
|
}
|
|
47040
|
-
var TOR_HTTP_TUNNEL, TOR_CHECK, PROOF_TIMEOUT_MS, LOCAL_PROOF_TIMEOUT_MS, LOCAL_PROOF_MAX_BYTES, torProvenAt, proxyProvenAt, MARK, TOR_RUN_STARTED_ENV, ownProxyRefused, ONION_V3, RETRY_AFTER_CAP_MS, RETRY_AFTER_FLOOR_MS, RETRY_AFTER_DEFAULT_MS, RPC_NO_ANSWER_LIMIT_MS, RPC_PACING_CAP_MS, PACING_NOTICE_EVERY_MS, PACING_RATE_WINDOW_MS, TOR_MAX_ROTATIONS, runStartedAt, rpcNotBefore, pacingWaiters, pacingSince, pacedMs, rpcAnswered, lastAnswerAt, readSteps, pacingNoticeAt, pacingSamples, torRotations, torCircuitId, torRotationsRefused, pendingMove, inTorRun, isOnionOrigin, ProxyUsageError, isOnionHost, TOR_EXPERT_BUNDLE, TUNNEL_LINE, TOR_INSTALL, OS_NAMES, osKey, torNotRunningMessage, NOTICE, withRunTag, proxyEnv, pacedSoFar, RESENDABLE_METHOD, torCircuit, GLOBAL_DISPATCHER2, laneDispatchers, paymentWarmStop;
|
|
47041
|
+
var TOR_HTTP_TUNNEL, TOR_CHECK, PROOF_TIMEOUT_MS, LOCAL_PROOF_TIMEOUT_MS, LOCAL_PROOF_MAX_BYTES, torProvenAt, proxyProvenAt, MARK, TOR_RUN_STARTED_ENV, ownProxyRefused, ONION_V3, RETRY_AFTER_CAP_MS, RETRY_AFTER_FLOOR_MS, RETRY_AFTER_DEFAULT_MS, RPC_NO_ANSWER_LIMIT_MS, RPC_PACING_CAP_MS, PACING_NOTICE_EVERY_MS, PACING_RATE_WINDOW_MS, TOR_MAX_ROTATIONS, runStartedAt, rpcNotBefore, pacingWaiters, pacingSince, pacedMs, rpcAnswered, lastAnswerAt, readSteps, pacingNoticeAt, pacingSamples, torRotations, torCircuitId, torRotationsRefused, pendingMove, inTorRun, runNetworkMode, isOnionOrigin, ProxyUsageError, isOnionHost, TOR_EXPERT_BUNDLE, TUNNEL_LINE, TOR_INSTALL, OS_NAMES, osKey, torNotRunningMessage, NOTICE, withRunTag, proxyEnv, pacedSoFar, RESENDABLE_METHOD, torCircuit, GLOBAL_DISPATCHER2, laneDispatchers, paymentWarmStop;
|
|
47041
47042
|
var init_proxy = __esm({
|
|
47042
47043
|
"wallet/src/net/proxy.mjs"() {
|
|
47043
47044
|
"use strict";
|
|
@@ -47075,6 +47076,10 @@ var init_proxy = __esm({
|
|
|
47075
47076
|
torCircuitId = 0;
|
|
47076
47077
|
torRotationsRefused = false;
|
|
47077
47078
|
inTorRun = () => String(process.env[MARK] ?? "").startsWith("tor ");
|
|
47079
|
+
runNetworkMode = () => {
|
|
47080
|
+
const mode = String(process.env[MARK] ?? "").split(" ")[0];
|
|
47081
|
+
return mode === "tor" || mode === "proxy" ? mode : null;
|
|
47082
|
+
};
|
|
47078
47083
|
isOnionOrigin = (url) => inTorRun() && url?.protocol === "http:" && ONION_V3.test(url.hostname);
|
|
47079
47084
|
ProxyUsageError = class extends Error {
|
|
47080
47085
|
};
|
|
@@ -104623,7 +104628,8 @@ async function getRangeOnce(fetchImpl, url, start, end, label, { lane, signal, s
|
|
|
104623
104628
|
if (at !== length) throw passing(fail26("setup_download_failed", `${label} answered a range of the wrong length; rerun setup: it keeps what it already checked`));
|
|
104624
104629
|
return { bytes: bytes2, start, total };
|
|
104625
104630
|
}
|
|
104626
|
-
async function downloadSet({ fetchImpl, base, entries, budget, onFile
|
|
104631
|
+
async function downloadSet({ fetchImpl, base, entries, budget, onFile, onBytes = () => {
|
|
104632
|
+
} }) {
|
|
104627
104633
|
const stop3 = new AbortController();
|
|
104628
104634
|
const files = entries.map((entry) => ({ entry, url: new URL(entry.path, base).href, label: `the proof-tool file ${entry.path}`, buffer: void 0, left: 0 }));
|
|
104629
104635
|
const queue = files.map((file) => ({ file, start: 0, end: RANGE_BYTES - 1, head: true, attempts: 0 })).sort((x, y) => Number(y.file.entry.path.endsWith(".params")) - Number(x.file.entry.path.endsWith(".params")));
|
|
@@ -104660,6 +104666,7 @@ async function downloadSet({ fetchImpl, base, entries, budget, onFile }) {
|
|
|
104660
104666
|
}
|
|
104661
104667
|
if (answer.whole) {
|
|
104662
104668
|
const bytes2 = await getBytes(fetchImpl, file.url, FILE_TIMEOUT_MS, file.label, LIMITS.file, budget, { lane: task.lane, stop: stop3.signal });
|
|
104669
|
+
onBytes(bytes2.length);
|
|
104663
104670
|
await finish(file, bytes2);
|
|
104664
104671
|
return;
|
|
104665
104672
|
}
|
|
@@ -104669,6 +104676,7 @@ async function downloadSet({ fetchImpl, base, entries, budget, onFile }) {
|
|
|
104669
104676
|
throw fail26("setup_download_failed", `${file.label} changed size during the download; rerun setup: it keeps what it already checked`);
|
|
104670
104677
|
}
|
|
104671
104678
|
answer.bytes.copy(file.buffer, answer.start);
|
|
104679
|
+
onBytes(answer.bytes.length);
|
|
104672
104680
|
file.left -= 1;
|
|
104673
104681
|
if (file.left === 0) await finish(file, file.buffer);
|
|
104674
104682
|
};
|
|
@@ -104721,6 +104729,7 @@ async function downloadSet({ fetchImpl, base, entries, budget, onFile }) {
|
|
|
104721
104729
|
}
|
|
104722
104730
|
if (got) {
|
|
104723
104731
|
got.copy(task.file.buffer, error.from);
|
|
104732
|
+
onBytes(got.length);
|
|
104724
104733
|
task.start = Math.max(task.start, error.from + got.length);
|
|
104725
104734
|
}
|
|
104726
104735
|
if (!got || got.length < RANGE_FLOOR_BYTES) task.attempts += 1;
|
|
@@ -104760,6 +104769,8 @@ async function fetchRelease(facilitator, { fetchImpl = fetch } = {}) {
|
|
|
104760
104769
|
if (!HEX643.test(String(tools.sumsSha256)) || !DIR2.test(String(tools.dir)) || tools.sumsSha256.slice(0, 8) !== tools.dir) {
|
|
104761
104770
|
throw fail26("setup_release_invalid", "the release document names a proof-tool set whose folder is not the first 8 hex of its list hash");
|
|
104762
104771
|
}
|
|
104772
|
+
const setBytes = Number(tools.bytes);
|
|
104773
|
+
if (Number.isSafeInteger(setBytes) && setBytes > 0 && setBytes <= LIMITS.total) releasedBytes.set(`${new URL(facilitator).origin} ${tools.sumsSha256}`, setBytes);
|
|
104763
104774
|
return release;
|
|
104764
104775
|
}
|
|
104765
104776
|
function expectedProofTools(facilitator, trust, pins = PINNED_PROOF_TOOLS) {
|
|
@@ -104810,8 +104821,16 @@ function verifyToolsFolder(folder, sumsSha256) {
|
|
|
104810
104821
|
return false;
|
|
104811
104822
|
}
|
|
104812
104823
|
}
|
|
104813
|
-
async function installProofTools({
|
|
104814
|
-
|
|
104824
|
+
async function installProofTools({
|
|
104825
|
+
facilitator,
|
|
104826
|
+
toolsRoot,
|
|
104827
|
+
expected,
|
|
104828
|
+
fetchImpl = fetch,
|
|
104829
|
+
onProgress = () => {
|
|
104830
|
+
},
|
|
104831
|
+
progressLine = (text3) => process.stderr.write(text3),
|
|
104832
|
+
progressEveryMs = PROGRESS_EVERY_MS
|
|
104833
|
+
}) {
|
|
104815
104834
|
const { dir, sumsSha256 } = expected;
|
|
104816
104835
|
if (!HEX643.test(String(sumsSha256)) || dir !== sumsSha256.slice(0, 8)) throw fail26("setup_release_invalid", "the expected proof-tool set is not a 64-hex list hash");
|
|
104817
104836
|
const folder = join21(toolsRoot, dir);
|
|
@@ -104870,12 +104889,45 @@ async function installProofTools({ facilitator, toolsRoot, expected, fetchImpl =
|
|
|
104870
104889
|
budget.left -= bytes2.length;
|
|
104871
104890
|
}
|
|
104872
104891
|
const keptPaths = new Set(kept.map(({ entry }) => entry.path));
|
|
104873
|
-
|
|
104874
|
-
|
|
104875
|
-
|
|
104876
|
-
|
|
104877
|
-
|
|
104878
|
-
|
|
104892
|
+
const missing = entries.filter((entry) => !keptPaths.has(entry.path));
|
|
104893
|
+
const keptBytes = kept.reduce((sum2, { bytes: bytes2 }) => sum2 + bytes2.length, 0);
|
|
104894
|
+
const named = releasedBytes.get(`${new URL(facilitator).origin} ${sumsSha256}`);
|
|
104895
|
+
const totalBytes = named !== void 0 && named >= keptBytes ? named : void 0;
|
|
104896
|
+
const torNote = inTorRun() ? "over Tor this takes a few minutes" : void 0;
|
|
104897
|
+
let arrived = 0;
|
|
104898
|
+
const say6 = (text3, notes) => {
|
|
104899
|
+
const shown = notes.filter(Boolean);
|
|
104900
|
+
try {
|
|
104901
|
+
progressLine(`downloading the proof tools: ${text3}${shown.length ? ` (${shown.join("; ")})` : ""}
|
|
104902
|
+
`);
|
|
104903
|
+
} catch {
|
|
104904
|
+
}
|
|
104905
|
+
};
|
|
104906
|
+
let ticker;
|
|
104907
|
+
if (missing.length > 0) {
|
|
104908
|
+
say6(
|
|
104909
|
+
`${totalBytes === void 0 ? "" : `${megabytes(totalBytes)} MB in `}${entries.length} files`,
|
|
104910
|
+
[kept.length ? `${kept.length} files, ${megabytes(keptBytes)} MB, already here from a stopped run` : void 0, torNote]
|
|
104911
|
+
);
|
|
104912
|
+
ticker = setInterval(() => {
|
|
104913
|
+
const done = keptBytes + arrived;
|
|
104914
|
+
const files = `${kept.length + downloaded} of ${entries.length} files`;
|
|
104915
|
+
say6(totalBytes !== void 0 ? `${megabytes(Math.min(done, totalBytes))} of ${megabytes(totalBytes)} MB, ${files}` : `${megabytes(done)} MB so far, ${files}`, [torNote]);
|
|
104916
|
+
}, progressEveryMs);
|
|
104917
|
+
ticker.unref?.();
|
|
104918
|
+
}
|
|
104919
|
+
try {
|
|
104920
|
+
await downloadSet({ fetchImpl, base, entries: missing, budget, onBytes: (count2) => {
|
|
104921
|
+
arrived += count2;
|
|
104922
|
+
}, onFile: (entry, bytes2) => {
|
|
104923
|
+
write(entry, bytes2);
|
|
104924
|
+
bytesDone += bytes2.length;
|
|
104925
|
+
downloaded += 1;
|
|
104926
|
+
onProgress({ filesDone: kept.length + downloaded, filesTotal: entries.length, bytesDone });
|
|
104927
|
+
} });
|
|
104928
|
+
} finally {
|
|
104929
|
+
clearInterval(ticker);
|
|
104930
|
+
}
|
|
104879
104931
|
writeFileSync(join21(partial, "SHA256SUMS"), sums, { flag: "wx", mode: 384 });
|
|
104880
104932
|
if (!verifyToolsFolder(partial, sumsSha256)) throw fail26("setup_file_hash_mismatch", "the downloaded proof-tools folder did not check out on disk; rerun setup");
|
|
104881
104933
|
if (existsSync(folder)) rmSync(folder, { recursive: true, force: true });
|
|
@@ -104946,7 +104998,7 @@ async function refreshTrustedProofTools({ home, facilitator, pool: pool2, fetchI
|
|
|
104946
104998
|
});
|
|
104947
104999
|
return Object.freeze({ changed: true, dir: tools.dir, sumsSha256: tools.sumsSha256, downloaded: tools.downloaded });
|
|
104948
105000
|
}
|
|
104949
|
-
var PINNED_PROOF_TOOLS, UPDATE_NEXT, HEX643, DIR2, SUMS_LINE, MAX_FILES, LIMITS, RELEASE_TIMEOUT_MS, FILE_TIMEOUT_MS, DOWNLOAD_LANES, RANGE_BYTES, RANGE_TIMEOUT_MS, RANGE_STALL_MS, RANGE_FLOOR_BYTES, RANGE_ATTEMPTS, HEDGE_AFTER_MS, CONTENT_RANGE, REQUIRED_FILES, sha2569, fail26, SMALL_HEDGE_MS, SMALL_LANES, LOST, passing, localPath, executable, toolPaths;
|
|
105001
|
+
var PINNED_PROOF_TOOLS, UPDATE_NEXT, HEX643, DIR2, SUMS_LINE, MAX_FILES, LIMITS, RELEASE_TIMEOUT_MS, FILE_TIMEOUT_MS, DOWNLOAD_LANES, RANGE_BYTES, RANGE_TIMEOUT_MS, RANGE_STALL_MS, RANGE_FLOOR_BYTES, RANGE_ATTEMPTS, HEDGE_AFTER_MS, CONTENT_RANGE, PROGRESS_EVERY_MS, releasedBytes, megabytes, REQUIRED_FILES, sha2569, fail26, SMALL_HEDGE_MS, SMALL_LANES, LOST, passing, localPath, executable, toolPaths;
|
|
104950
105002
|
var init_proofTools = __esm({
|
|
104951
105003
|
"wallet/src/setup/proofTools.mjs"() {
|
|
104952
105004
|
"use strict";
|
|
@@ -104977,6 +105029,9 @@ var init_proofTools = __esm({
|
|
|
104977
105029
|
RANGE_ATTEMPTS = 8;
|
|
104978
105030
|
HEDGE_AFTER_MS = 3e3;
|
|
104979
105031
|
CONTENT_RANGE = /^bytes (\d+)-(\d+)\/(\d+)$/;
|
|
105032
|
+
PROGRESS_EVERY_MS = 1e4;
|
|
105033
|
+
releasedBytes = /* @__PURE__ */ new Map();
|
|
105034
|
+
megabytes = (bytes2) => Math.round(bytes2 / 1e6);
|
|
104980
105035
|
REQUIRED_FILES = Object.freeze(["proof-tools.json", "exit-proof-tools.json", "public-profile.json"]);
|
|
104981
105036
|
sha2569 = (bytes2) => createHash26("sha256").update(bytes2).digest("hex");
|
|
104982
105037
|
fail26 = (code2, detail) => new Error(`${code2}: ${detail}`);
|
|
@@ -107669,6 +107724,7 @@ function addFundsHeldSay(entries, have = "") {
|
|
|
107669
107724
|
let startMinutes = null;
|
|
107670
107725
|
for (const entry of entries) {
|
|
107671
107726
|
if (!entry || typeof entry !== "object") continue;
|
|
107727
|
+
if (entry.landed === true) continue;
|
|
107672
107728
|
const amount = ATOMIC3.test(String(entry.heldAtomic ?? "")) ? BigInt(entry.heldAtomic) : 0n;
|
|
107673
107729
|
const left = Number.isSafeInteger(entry.privateInMinutes) ? entry.privateInMinutes : null;
|
|
107674
107730
|
if (entry.state === "shielding" && entry.startsAtNextRequest === true) {
|
|
@@ -107705,9 +107761,10 @@ function addFundsHeldSay(entries, have = "") {
|
|
|
107705
107761
|
const lead = (text3) => have ? `${have}; ${text3}` : `${text3[0].toUpperCase()}${text3.slice(1)}`;
|
|
107706
107762
|
const now = !nowUnknown ? `${usdcText(nowHeld)} USDC is becoming private now` : nowHeld > 0n ? `${usdcText(nowHeld)} USDC and an amount still being read are becoming private now` : "an amount still being read is becoming private now";
|
|
107707
107763
|
const later = startMinutes !== null ? `within about 1 minute of your next wallet request${startMinutes > 0 ? ` after about ${minutesText(startMinutes)}` : ""}` : minutesKnown && minutes !== null ? `in about ${minutesText(minutes)}` : "in a few minutes";
|
|
107708
|
-
|
|
107764
|
+
const askLater = startMinutes !== null && startMinutes > 0 ? `ask again in about ${minutesText(startMinutes)}, and it becomes private within about 1 minute of that request` : null;
|
|
107765
|
+
if (nowAny && waiting > 0n) return askLater ? `${lead(`${now}; ${usdcText(waiting)} USDC more arrived: ask again in about ${minutesText(startMinutes)} for it`)}.` : `${lead(`${now}, and ${usdcText(waiting)} USDC more ${later}`)}.`;
|
|
107709
107766
|
if (nowAny) return `${lead(now)}. Nothing to do.`;
|
|
107710
|
-
const arrived = `${usdcText(waiting)} USDC arrived and becomes private ${later === "in a few minutes" ? "within a few minutes of your next wallet request" : later}`;
|
|
107767
|
+
const arrived = askLater ? `${usdcText(waiting)} USDC arrived: ${askLater}` : `${usdcText(waiting)} USDC arrived and becomes private ${later === "in a few minutes" ? "within a few minutes of your next wallet request" : later}`;
|
|
107711
107768
|
if (startMinutes !== null) return `${lead(arrived)}.`;
|
|
107712
107769
|
if (!minutesKnown || minutes === null) {
|
|
107713
107770
|
return have ? `${lead(arrived)}. Nothing to do.` : `${lead(arrived)}. A random wait hides the link to your deposit. Nothing to do.`;
|
|
@@ -107757,6 +107814,11 @@ function refreshErrorWords(code2) {
|
|
|
107757
107814
|
function balanceSay(a) {
|
|
107758
107815
|
const balance = usdcText(a.balanceAtomic);
|
|
107759
107816
|
const pub = usdcText(a.unshieldedAtomic);
|
|
107817
|
+
const landing = usdcText(a.landingAtomic);
|
|
107818
|
+
if (positive(landing) && !a.refreshError) {
|
|
107819
|
+
const line = `${landing} USDC you added landed and is being counted. Ask again in about 30 seconds.`;
|
|
107820
|
+
return balance !== void 0 && a.refreshing !== true ? `You have ${balance} USDC private; ${line}` : line;
|
|
107821
|
+
}
|
|
107760
107822
|
const arriving = addFundsHeldSay(a.addFunds);
|
|
107761
107823
|
if (arriving) {
|
|
107762
107824
|
const both = balance !== void 0 && a.refreshing !== true ? addFundsHeldSay(a.addFunds, `You have ${balance} USDC private`) : "";
|
|
@@ -107845,13 +107907,15 @@ function transferSay(a) {
|
|
|
107845
107907
|
const about = usdcText(a.quote?.outAtomic);
|
|
107846
107908
|
const usdc8 = sold ? `${sold} USDC` : about ? `about ${about} USDC` : "USDC";
|
|
107847
107909
|
const to = str(a.to) || "the address";
|
|
107910
|
+
const later = "If this chat ends first, it continues at your next request.";
|
|
107848
107911
|
switch (a.stage) {
|
|
107849
107912
|
case "selling":
|
|
107850
|
-
return `Selling the token for ${usdc8}
|
|
107913
|
+
return `Selling the token for ${usdc8}; then it goes privately to ${to}. ${later}`;
|
|
107914
|
+
// J-3: a shield that already landed is not "making it private now" (the resumed run is about to plan the send).
|
|
107851
107915
|
case "shielding":
|
|
107852
|
-
return `Sold for ${usdc8}. Making it private now; then it goes to ${to}
|
|
107916
|
+
return a.shield?.landed === true ? `Sold for ${usdc8} and made private; the send to ${to} starts now. ${later}` : `Sold for ${usdc8}. Making it private now; then it goes to ${to}. ${later}`;
|
|
107853
107917
|
case "sending":
|
|
107854
|
-
return `Sending ${usdc8} privately to ${to}.
|
|
107918
|
+
return `Sending ${usdc8} privately to ${to}. It gets USDC, not the token. ${later}`;
|
|
107855
107919
|
case "sold_waiting_room":
|
|
107856
107920
|
return `Sold for ${usdc8}, but it does not fit the 5 USDC private balance limit yet. Read next for what to do.`;
|
|
107857
107921
|
case "done":
|
|
@@ -114048,8 +114112,11 @@ function transferTokenView(plan) {
|
|
|
114048
114112
|
parts: plan.parts,
|
|
114049
114113
|
maxDelayMinutes: plan.maxDelayMinutes,
|
|
114050
114114
|
delivers: "USDC",
|
|
114051
|
-
|
|
114052
|
-
|
|
114115
|
+
// Real-user pass J-1 (2026-10-21): "B" is an internal name; the answer names the address the user gave.
|
|
114116
|
+
limit: "the address in to receives USDC, not the token. Swap it there yourself; an automatic swap there is not built yet.",
|
|
114117
|
+
// J-4: a plan exists only after the address's USDC account was read (tools.mjs beginTransfer refuses mcp_unshield_to_invalid before the sell).
|
|
114118
|
+
receiving: "the address in to already has a USDC account (checked before the sell), so it can receive this USDC",
|
|
114119
|
+
privacy: "the total the address in to receives equals the deposit, and the pool's crowd is small today: a longer max_delay_minutes hides better",
|
|
114053
114120
|
...plan.stopCode ? { stopCode: plan.stopCode, stopReason: plan.stopReason } : {},
|
|
114054
114121
|
...plan.state === "sold_waiting_room" && plan.waitCode ? { waitCode: plan.waitCode, waitReason: plan.waitReason } : {},
|
|
114055
114122
|
...plan.cancelRequested ? { cancelRequested: true } : {}
|
|
@@ -114496,7 +114563,7 @@ function safeHttpUrl(value) {
|
|
|
114496
114563
|
}
|
|
114497
114564
|
}
|
|
114498
114565
|
function clip(text3, max) {
|
|
114499
|
-
return text3.length > max ? `${text3.slice(0, max -
|
|
114566
|
+
return text3.length > max ? `${text3.slice(0, max - 3)}...` : text3;
|
|
114500
114567
|
}
|
|
114501
114568
|
function cachePath(key, cacheDir) {
|
|
114502
114569
|
return join27(cacheDir, `x402-discover-${createHash29("sha256").update(key).digest("hex").slice(0, 24)}.json`);
|
|
@@ -115470,7 +115537,7 @@ async function waitWithProgress(ms, progress3, message) {
|
|
|
115470
115537
|
await sleep2(Math.min(1e4, left));
|
|
115471
115538
|
}
|
|
115472
115539
|
}
|
|
115473
|
-
function waitOrProgress(promises, ms, { progress: progress3, message, everyMs =
|
|
115540
|
+
function waitOrProgress(promises, ms, { progress: progress3, message, everyMs = PROGRESS_EVERY_MS2 } = {}) {
|
|
115474
115541
|
return new Promise((resolve38, reject) => {
|
|
115475
115542
|
let timer;
|
|
115476
115543
|
let beat;
|
|
@@ -116438,7 +116505,7 @@ function createWalletTools({
|
|
|
116438
116505
|
return { ok: false, why: error?.timedOut === true ? "timeout" : "error" };
|
|
116439
116506
|
}
|
|
116440
116507
|
}
|
|
116441
|
-
const progressEveryMs = Number.isSafeInteger(ops.progressEveryMs) && ops.progressEveryMs > 0 ? ops.progressEveryMs :
|
|
116508
|
+
const progressEveryMs = Number.isSafeInteger(ops.progressEveryMs) && ops.progressEveryMs > 0 ? ops.progressEveryMs : PROGRESS_EVERY_MS2;
|
|
116442
116509
|
const statusWait = (promises, ms, progress3, message) => waitOrProgress(promises, ms, { progress: progress3, message, everyMs: progressEveryMs });
|
|
116443
116510
|
const notAllowedNext = (why, requestId, numbers, words2) => why === "timeout" ? `No answer yet. Ask again with request_id ${requestId} to ask the user again.` : `${limitNext(numbers, words2)} The user did not allow it once${why === "not_ticked" ? " (the box was not ticked)" : ""}.`;
|
|
116444
116511
|
const cancels = /* @__PURE__ */ new Map();
|
|
@@ -117303,6 +117370,7 @@ function createWalletTools({
|
|
|
117303
117370
|
status: 402,
|
|
117304
117371
|
accepts,
|
|
117305
117372
|
rail,
|
|
117373
|
+
...networkFields(),
|
|
117306
117374
|
caps: shownCaps({ ...limits, sessionLeftAtomic: sessionLeftShown(policy, (() => {
|
|
117307
117375
|
try {
|
|
117308
117376
|
return session.openStore();
|
|
@@ -117745,6 +117813,16 @@ ${canonical5}`;
|
|
|
117745
117813
|
const line = `${say6} Its request_id is ${id}.`;
|
|
117746
117814
|
return line.trim().split(/\s+/).length <= SAY_MAX_WORDS ? line : say6;
|
|
117747
117815
|
};
|
|
117816
|
+
function networkFields() {
|
|
117817
|
+
const mode = runNetworkMode();
|
|
117818
|
+
let onion = false;
|
|
117819
|
+
try {
|
|
117820
|
+
onion = mode === "tor" && Boolean(session.memoServiceUrl) && routesOverOnion(new URL(session.memoServiceUrl).origin);
|
|
117821
|
+
} catch {
|
|
117822
|
+
onion = false;
|
|
117823
|
+
}
|
|
117824
|
+
return { network: mode === "tor" ? { mode: "tor", detail: `every request of this wallet goes through Tor (checked at start)${onion ? "; the facilitator is reached over its onion service, so no Tor exit sees those requests" : ""}` } : mode === "proxy" ? { mode: "proxy", detail: "every request of this wallet goes through the proxy in its launch line (--proxy); it is not checked as Tor" } : { mode: "direct", detail: "no Tor: the facilitator, the RPC provider and each seller see this computer's IP address; start the MCP with --tor (or run setup --prefer-tor) to hide it" } };
|
|
117825
|
+
}
|
|
117748
117826
|
function sayFirst(fields, tool, autoId) {
|
|
117749
117827
|
let say6 = sayFor(fields, { tool });
|
|
117750
117828
|
if (autoId) say6 = withIdSentence(say6, autoId);
|
|
@@ -117993,11 +118071,13 @@ ${canonical5}`;
|
|
|
117993
118071
|
const startAt = record.state === "open" ? watcher?.startAtOf(linkKindOf(record.id), record.id) ?? null : null;
|
|
117994
118072
|
let shieldingAtomic = null;
|
|
117995
118073
|
let depositSent = false;
|
|
118074
|
+
let landed = false;
|
|
117996
118075
|
if (record.state === "shielding") {
|
|
117997
118076
|
try {
|
|
117998
118077
|
const deposit = store.readWal(`deposit-${record.depositId ?? payMeRoundDepositId(record.id, record.round ?? 1)}`);
|
|
117999
118078
|
if (/^[1-9][0-9]*$/.test(String(deposit?.amountAtomic ?? ""))) shieldingAtomic = String(deposit.amountAtomic);
|
|
118000
|
-
|
|
118079
|
+
landed = depositLanded(deposit);
|
|
118080
|
+
depositSent = landed || DEPOSIT_SENT_STATES.has(deposit?.state);
|
|
118001
118081
|
} catch {
|
|
118002
118082
|
shieldingAtomic = null;
|
|
118003
118083
|
}
|
|
@@ -118009,6 +118089,7 @@ ${canonical5}`;
|
|
|
118009
118089
|
state: record.state,
|
|
118010
118090
|
heldAtomic: held,
|
|
118011
118091
|
...record.state === "shielding" ? { shieldingAtomic } : {},
|
|
118092
|
+
...landed ? { landed: true } : {},
|
|
118012
118093
|
// The one number say and next name (real-user pass D1: say 6, privateInMinutes 5): the random wait left, plus
|
|
118013
118094
|
// about a minute for the deposit itself; 0 once the wait is over (the deposit starts at the next request).
|
|
118014
118095
|
...startAt !== null ? { privateInMinutes: startAt <= Date.now() ? 0 : Math.ceil((startAt - Date.now()) / 6e4) + 1 } : {},
|
|
@@ -118019,10 +118100,58 @@ ${canonical5}`;
|
|
|
118019
118100
|
};
|
|
118020
118101
|
});
|
|
118021
118102
|
}
|
|
118103
|
+
function finishSentDeposits(store) {
|
|
118104
|
+
if (!elsewhereEnabled || paysInFlight > 0 || moneyCallsInFlight > 0) return [];
|
|
118105
|
+
const passes = [];
|
|
118106
|
+
for (const record of listPayMe(store)) {
|
|
118107
|
+
if (record.state !== "shielding") continue;
|
|
118108
|
+
let deposit;
|
|
118109
|
+
try {
|
|
118110
|
+
deposit = store.readWal(`deposit-${record.depositId ?? payMeRoundDepositId(record.id, record.round ?? 1)}`);
|
|
118111
|
+
} catch {
|
|
118112
|
+
continue;
|
|
118113
|
+
}
|
|
118114
|
+
if (deposit?.schema !== DEPOSIT_WAL_SCHEMA || !DEPOSIT_FINISH_STATES.has(deposit.state)) continue;
|
|
118115
|
+
passes.push(payMePass(record.id).then((outcome) => {
|
|
118116
|
+
const round = outcome?.record?.round ?? 1;
|
|
118117
|
+
if ((outcome?.stage === "done" || outcome?.stage === "partly_shielded") && outcome.record?.doneAt && !payMeRefreshed.has(`${record.id}:${round}`)) {
|
|
118118
|
+
payMeRefreshed.add(`${record.id}:${round}`);
|
|
118119
|
+
afterShield({ requestId: record.id });
|
|
118120
|
+
log(`MCP_PAY_ME_DONE requestId=${record.id} by=balance`);
|
|
118121
|
+
}
|
|
118122
|
+
return outcome;
|
|
118123
|
+
}));
|
|
118124
|
+
}
|
|
118125
|
+
return passes;
|
|
118126
|
+
}
|
|
118127
|
+
function landedNotCounted(store) {
|
|
118128
|
+
let snapshot;
|
|
118129
|
+
try {
|
|
118130
|
+
snapshot = readBalanceSnapshot(store)?.snapshot;
|
|
118131
|
+
} catch {
|
|
118132
|
+
snapshot = void 0;
|
|
118133
|
+
}
|
|
118134
|
+
const walkedDigests = new Set((snapshot?.outputs ?? []).map((output2) => output2.digest));
|
|
118135
|
+
const finishedHere = new Set(listPayMe(store).filter((record) => record.state === "shielding").map((record) => `deposit-${record.depositId ?? payMeRoundDepositId(record.id, record.round ?? 1)}`));
|
|
118136
|
+
let total = 0n;
|
|
118137
|
+
for (const name of store.listWal()) {
|
|
118138
|
+
if (!name.startsWith("deposit-")) continue;
|
|
118139
|
+
let deposit;
|
|
118140
|
+
try {
|
|
118141
|
+
deposit = store.readWal(name);
|
|
118142
|
+
} catch {
|
|
118143
|
+
continue;
|
|
118144
|
+
}
|
|
118145
|
+
if (!depositLanded(deposit) || !/^[1-9][0-9]*$/.test(String(deposit.amountAtomic ?? ""))) continue;
|
|
118146
|
+
const landing = deposit.state === "submitted" ? finishedHere.has(name) && !walkedDigests.has(String(deposit.memoDigest ?? "").replace(/^0x/i, "").toLowerCase()) : snapshot !== void 0 && !["finalized", "published"].includes(snapshot.walStates?.[name]);
|
|
118147
|
+
if (landing) total += BigInt(deposit.amountAtomic);
|
|
118148
|
+
}
|
|
118149
|
+
return total;
|
|
118150
|
+
}
|
|
118022
118151
|
const balance = {
|
|
118023
118152
|
name: "wallet_balance",
|
|
118024
118153
|
title: "Balance",
|
|
118025
|
-
description: `Use this when the user asks "what is my balance" or "how much USDC do I have": it answers ONE balance (balanceAtomic, what x402_pay can spend) and the public (unshielded) USDC. Pays nothing and signs nothing. balanceAtomic is one number; breakdown names its parts (breakdown.shieldedAtomic is what wallet_unshield can send; privateSendPendingAtomic is the part of a running private send (wallet_unshield with parts or max_delay_minutes) not sent yet, already taken off shieldedAtomic; refundsInFlightAtomic is a Shinjuku refund on its way back; setAsideAtomic (only when not 0) is value an older version of this wallet set aside to pay sellers; during a pool move, pools lists each pool's part and movingAtomic is value on its way from the old pool to the new one; the move field shows the move, poolSwitches each switch). UNSHIELDED (unshieldedAtomic) is the plain public USDC on the wallet's own Solana key (ownAddress), the USDC wallet_shield makes private; unshieldedSolLamports is that key's SOL, information only: wallet_shield needs none (the facilitator's relayer pays every fee and rent). When the local balance is stale (a new deposit, a received payment), it reads the chain by itself first; when that takes longer than about 20 s it answers the last balance with refreshing: true and finishes in the background (call wallet_balance again in 30 s). A balance with refreshing: true and refreshReason is exact (payment_settling: a payment settles and the number counts it; account_join: the wallet joins its own balance parts and the number counts them; pool_move: value from the old pool arrives and the number counts it; first_check: a new wallet's first history check, the number is its own landed deposits). status reading (balanceAtomic null): the first balance read of a wallet that may hold money is not done; call wallet_balance again in 30 s. If the public read fails, unshieldedAtomic is null with unshieldedReason; the rest still answers. earlierDeposits (only when there are any): USDC found at a one-time deposit address of an earlier pool, each with a notice line to tell the user; the wallet moves it into the current pool by itself. addFunds (only when there are any): each wallet_add_funds address still open, with its state and the USDC known to wait there (heldAtomic; null with heldNote when the address was not checked yet). session shows the spending limits (null or "none": no limit), what is left, where the limits come from, and how to change them (session.summary). verbose: true adds \`internal\` (accounts, notes, and other engineering numbers); the default answer leaves them out. To add money, use wallet_add_funds. Amounts are atomic units (USDC: 1000000 = 1 USDC); say and usdc give them in USDC.`,
|
|
118154
|
+
description: `Use this when the user asks "what is my balance" or "how much USDC do I have": it answers ONE balance (balanceAtomic, what x402_pay can spend) and the public (unshielded) USDC. Pays nothing and signs nothing. balanceAtomic is one number; breakdown names its parts (breakdown.shieldedAtomic is what wallet_unshield can send; privateSendPendingAtomic is the part of a running private send (wallet_unshield with parts or max_delay_minutes) not sent yet, already taken off shieldedAtomic; refundsInFlightAtomic is a Shinjuku refund on its way back; setAsideAtomic (only when not 0) is value an older version of this wallet set aside to pay sellers; during a pool move, pools lists each pool's part and movingAtomic is value on its way from the old pool to the new one; the move field shows the move, poolSwitches each switch). UNSHIELDED (unshieldedAtomic) is the plain public USDC on the wallet's own Solana key (ownAddress), the USDC wallet_shield makes private; unshieldedSolLamports is that key's SOL, information only: wallet_shield needs none (the facilitator's relayer pays every fee and rent). When the local balance is stale (a new deposit, a received payment), it reads the chain by itself first; when that takes longer than about 20 s it answers the last balance with refreshing: true and finishes in the background (call wallet_balance again in 30 s). A balance with refreshing: true and refreshReason is exact (payment_settling: a payment settles and the number counts it; account_join: the wallet joins its own balance parts and the number counts them; pool_move: value from the old pool arrives and the number counts it; first_check: a new wallet's first history check, the number is its own landed deposits). status reading (balanceAtomic null): the first balance read of a wallet that may hold money is not done; call wallet_balance again in 30 s. If the public read fails, unshieldedAtomic is null with unshieldedReason; the rest still answers. earlierDeposits (only when there are any): USDC found at a one-time deposit address of an earlier pool, each with a notice line to tell the user; the wallet moves it into the current pool by itself. addFunds (only when there are any): each wallet_add_funds address still open, with its state and the USDC known to wait there (heldAtomic; null with heldNote when the address was not checked yet). landingAtomic (only when not 0): USDC you added whose deposit landed on chain and that balanceAtomic does not count yet; this call finishes it and waits about 20 s for it, past that it is being counted: call wallet_balance again in 30 s. session shows the spending limits (null or "none": no limit), what is left, where the limits come from, and how to change them (session.summary). verbose: true adds \`internal\` (accounts, notes, and other engineering numbers); the default answer leaves them out. To add money, use wallet_add_funds. Amounts are atomic units (USDC: 1000000 = 1 USDC); say and usdc give them in USDC.`,
|
|
118026
118155
|
inputSchema: { type: "object", properties: {
|
|
118027
118156
|
verbose: { type: "boolean", description: "Optional. true adds `internal`: the engineering numbers (funded accounts, notes, payments without waiting, a 0 set-aside value). Default false." }
|
|
118028
118157
|
}, additionalProperties: false },
|
|
@@ -118047,6 +118176,24 @@ ${canonical5}`;
|
|
|
118047
118176
|
const balanceStartedAt = Date.now();
|
|
118048
118177
|
const publicRead = withTimeout((ops.readPublicBalance ?? readOwnPublicBalance)({ session, store }), PUBLIC_READ_TIMEOUT_MS).then((read2) => ({ read: read2 }), (error2) => ({ error: error2 }));
|
|
118049
118178
|
const linkReads = readOpenLinkHeld(store);
|
|
118179
|
+
const finishing = finishSentDeposits(store);
|
|
118180
|
+
const finishDeadline = finishing.length ? balanceStartedAt + balanceRefreshWaitMs : void 0;
|
|
118181
|
+
if (finishing.length) {
|
|
118182
|
+
const finished = Promise.all(finishing).then((outcomes) => outcomes.some((outcome2) => outcome2?.stage === "done" || outcome2?.stage === "partly_shielded") ? refreshShared().then(() => "done") : "passed").catch(() => "failed");
|
|
118183
|
+
const outcome = await Promise.race([
|
|
118184
|
+
finished,
|
|
118185
|
+
new Promise((resolve38) => {
|
|
118186
|
+
const timer = setTimeout(() => resolve38("waiting"), Math.max(0, finishDeadline - Date.now()));
|
|
118187
|
+
timer.unref?.();
|
|
118188
|
+
})
|
|
118189
|
+
]);
|
|
118190
|
+
if (outcome !== "waiting") {
|
|
118191
|
+
try {
|
|
118192
|
+
store = session.openStore();
|
|
118193
|
+
} catch {
|
|
118194
|
+
}
|
|
118195
|
+
}
|
|
118196
|
+
}
|
|
118050
118197
|
let report = computeBalance({ store, snapshotRead: readBalanceSnapshot(store), source: "local", firstDepositEstimate: true });
|
|
118051
118198
|
let refresh = {};
|
|
118052
118199
|
const recentlyFailed = refreshFailedAt && Date.now() - refreshFailedAt < REFRESH_RETRY_MS && !refreshRun;
|
|
@@ -118067,7 +118214,7 @@ ${canonical5}`;
|
|
|
118067
118214
|
const timer = setTimeout(() => resolve38("waiting"), ms);
|
|
118068
118215
|
timer.unref?.();
|
|
118069
118216
|
})]);
|
|
118070
|
-
let outcome = await waitFor(longRead ? 0 : balanceRefreshWaitMs);
|
|
118217
|
+
let outcome = await waitFor(longRead ? 0 : finishDeadline === void 0 ? balanceRefreshWaitMs : Math.max(0, finishDeadline - Date.now()));
|
|
118071
118218
|
if (outcome === "waiting" && !longRead) outcome = await waitFor(BALANCE_REFRESH_GRACE_MS);
|
|
118072
118219
|
if (outcome === "done") {
|
|
118073
118220
|
try {
|
|
@@ -118156,6 +118303,14 @@ ${canonical5}`;
|
|
|
118156
118303
|
else if (one.balanceAtomic === "0" && shieldEnabled) {
|
|
118157
118304
|
next = elsewhereEnabled ? `the shielded balance is 0, so x402_pay cannot pay yet. To add funds, call wallet_add_funds: it gives a one-time address; up to ${usdcText2(payMeRoundMax())} USDC sent there on Solana becomes private a few minutes after it arrives while this MCP server runs (or call wallet_add_funds with its request_id to finish it at once)` : `the shielded balance is 0, so x402_pay cannot pay yet. To add funds: send USDC on Solana to ownAddress (this wallet's own key), then call wallet_shield with amount (any amount from ${usdcText2(10000n)} to ${usdcText2(MAX_SHIELDED_BALANCE_ATOMIC)} USDC)`;
|
|
118158
118305
|
} else next = "nothing to do; x402_pay pays from balanceAtomic, wallet_unshield sends from breakdown.shieldedAtomic";
|
|
118306
|
+
let landingAtomic = 0n;
|
|
118307
|
+
try {
|
|
118308
|
+
landingAtomic = landedNotCounted(store);
|
|
118309
|
+
} catch {
|
|
118310
|
+
landingAtomic = 0n;
|
|
118311
|
+
}
|
|
118312
|
+
const landedNext = landingAtomic > 0n && !refresh.refreshError ? `${usdcText2(landingAtomic)} USDC you added landed on chain and is being counted (landingAtomic, not in balanceAtomic yet): call wallet_balance again in ${POLL_SECONDS3} s; that call waits up to ${waitSeconds} s for it. Tell the user it needs no step from them` : void 0;
|
|
118313
|
+
if (landedNext) next = landedNext;
|
|
118159
118314
|
const stalled = [...resumeRefusals].map(([requestId, error2]) => `"${requestId}" (${error2})`);
|
|
118160
118315
|
if (stalled.length && one.breakdown?.privateSendPendingAtomic !== "0") {
|
|
118161
118316
|
next = `${next}. A private send did not continue after this server started: ${stalled.join(", ")}. Its unsent parts (breakdown.privateSendPendingAtomic) stay off balanceAtomic: call wallet_unshield with its request_id and the same arguments to see why and run it, or stop them with wallet_cancel and its request_id`;
|
|
@@ -118213,16 +118368,16 @@ ${canonical5}`;
|
|
|
118213
118368
|
} catch {
|
|
118214
118369
|
sendWaiting = void 0;
|
|
118215
118370
|
}
|
|
118216
|
-
const arrivingAll = addFundsOpen.filter((link2) => link2.state === "shielding" || /^[1-9][0-9]*$/.test(String(link2.heldAtomic ?? "")));
|
|
118371
|
+
const arrivingAll = addFundsOpen.filter((link2) => link2.landed !== true && (link2.state === "shielding" || /^[1-9][0-9]*$/.test(String(link2.heldAtomic ?? ""))));
|
|
118217
118372
|
const arrivingLine = (arriving) => {
|
|
118218
118373
|
const amount = /^[1-9][0-9]*$/.test(String(arriving.shieldingAtomic ?? "")) ? `${usdcText2(arriving.shieldingAtomic)} USDC` : /^[1-9][0-9]*$/.test(String(arriving.heldAtomic ?? "")) ? `${usdcText2(arriving.heldAtomic)} USDC` : "USDC (an amount still being read)";
|
|
118219
|
-
const when = arriving.state === "shielding" && !arriving.startsAtNextRequest ? "is becoming private now (its deposit transaction was sent; about 1 minute)" : arriving.startsInMinutes > 0 ? `
|
|
118374
|
+
const when = arriving.state === "shielding" && !arriving.startsAtNextRequest ? "is becoming private now (its deposit transaction was sent; about 1 minute)" : arriving.startsInMinutes > 0 ? `waits about ${minutesText2(arriving.startsInMinutes)} (a random wait hides the link to the deposit); call wallet_balance again after that, and it becomes private within about 1 minute of that request; no step for the user` : "becomes private: its deposit starts after this answer and takes about 1 minute; if this wallet process ends first, the next wallet request continues it";
|
|
118220
118375
|
return `${amount} arrived at add-funds address "${arriving.requestId}" and ${when}`;
|
|
118221
118376
|
};
|
|
118222
118377
|
if (arrivingAll.length === 1) {
|
|
118223
|
-
next = `${arrivingLine(arrivingAll[0])}. Tell the user it needs no step from them; do not hurry it. If balanceAtomic does not show it 10 minutes after that, call wallet_add_funds with request_id "${arrivingAll[0].requestId}": it finishes it now. Do not ask for a new address`;
|
|
118378
|
+
next = `${landedNext ? `${landedNext}. ` : ""}${arrivingLine(arrivingAll[0])}. Tell the user it needs no step from them; do not hurry it. If balanceAtomic does not show it 10 minutes after that, call wallet_add_funds with request_id "${arrivingAll[0].requestId}": it finishes it now. Do not ask for a new address`;
|
|
118224
118379
|
} else if (arrivingAll.length > 1) {
|
|
118225
|
-
next = `${arrivingAll.map(arrivingLine).join("; ")}. Tell the user the total and that it needs no step from them; do not hurry it. If balanceAtomic does not show one 10 minutes after its time, call wallet_add_funds with its request_id: it finishes it now. Do not ask for a new address`;
|
|
118380
|
+
next = `${landedNext ? `${landedNext}. ` : ""}${arrivingAll.map(arrivingLine).join("; ")}. Tell the user the total and that it needs no step from them; do not hurry it. If balanceAtomic does not show one 10 minutes after its time, call wallet_add_funds with its request_id: it finishes it now. Do not ask for a new address`;
|
|
118226
118381
|
}
|
|
118227
118382
|
const earlierDeposits = (ops.oneTimeAdopt === false ? [] : adopter.outcomes()).map((outcome) => ({
|
|
118228
118383
|
pool: outcome.pool,
|
|
@@ -118304,8 +118459,10 @@ ${canonical5}`;
|
|
|
118304
118459
|
...move ? { move } : {},
|
|
118305
118460
|
...openSwitches.length ? { poolSwitches: openSwitches } : {},
|
|
118306
118461
|
...addFundsOpen.length ? { addFunds: addFundsOpen } : {},
|
|
118462
|
+
...landingAtomic > 0n ? { landingAtomic: landingAtomic.toString() } : {},
|
|
118307
118463
|
...sendWaiting ? { sendWaiting } : {},
|
|
118308
118464
|
...notices,
|
|
118465
|
+
...networkFields(),
|
|
118309
118466
|
session: {
|
|
118310
118467
|
...shownCaps({ ...policy.limits, sessionLeftAtomic: sessionLeft }),
|
|
118311
118468
|
sessionSpentAtomic: policy.sessionSpentAtomic,
|
|
@@ -120851,6 +121008,7 @@ ${canonical5}`;
|
|
|
120851
121008
|
id,
|
|
120852
121009
|
canShield: elsewhereEnabled,
|
|
120853
121010
|
allowance: async ({ record }) => payMeRoom(record),
|
|
121011
|
+
...ops.payMeSteps ?? {},
|
|
120854
121012
|
// Counted against --max-shield once per round, when it is proved and about to be submitted (as a deposit from elsewhere is).
|
|
120855
121013
|
onShield: ({ amountAtomic, round }) => {
|
|
120856
121014
|
const key = `${id}:${round}`;
|
|
@@ -121502,10 +121660,23 @@ ${canonical5}`;
|
|
|
121502
121660
|
}
|
|
121503
121661
|
const code2 = transferCodes.get(plan.id);
|
|
121504
121662
|
const poll = `call wallet_transfer_token_status with request_id "${plan.id}"`;
|
|
121663
|
+
let landed = false;
|
|
121664
|
+
if (view2.stage === "shielding") {
|
|
121665
|
+
try {
|
|
121666
|
+
landed = ["finalized", "published"].includes(session.openStore().readWal(`deposit-${plan.depositId}`)?.state);
|
|
121667
|
+
} catch {
|
|
121668
|
+
landed = false;
|
|
121669
|
+
}
|
|
121670
|
+
if (landed) view2.shield = { ...view2.shield, landed: true };
|
|
121671
|
+
}
|
|
121672
|
+
const kept = "; if the host ends this server first, the next start of the wallet continues it (nothing runs twice)";
|
|
121505
121673
|
const next = {
|
|
121506
|
-
selling: `${poll} in ${POLL_SECONDS3} s: the sell lands in about 15 s and then the shield starts at the next poll`,
|
|
121507
|
-
shielding: `${poll} in ${POLL_SECONDS3} s: the deposit takes a few minutes, then the private send starts at the next poll`,
|
|
121508
|
-
|
|
121674
|
+
selling: `${poll} in ${POLL_SECONDS3} s: the sell lands in about 15 s and then the shield starts at the next poll${kept}`,
|
|
121675
|
+
shielding: landed ? `${poll} in 10 s: the deposit landed and the private send starts now${kept}` : `${poll} in ${POLL_SECONDS3} s: the deposit takes a few minutes, then the private send starts at the next poll${kept}`,
|
|
121676
|
+
// J-5 (2026-10-21): a part whose time passed while no wallet server ran draws a new wait of up to the delay from the next
|
|
121677
|
+
// start (privateSend.mjs runPrivateSend late redraw: its leave time never shows when the wallet came back), so the
|
|
121678
|
+
// "up to N min" counts from the last start, not from the call.
|
|
121679
|
+
sending: `${poll} in ${POLL_SECONDS3} s; the parts leave after random waits of up to ${plan.maxDelayMinutes} min each${kept}. A part whose time passed while the wallet did not run waits again, up to ${plan.maxDelayMinutes} min from the next start, so its leave time does not show when the wallet came back: tell the user the time counts while the wallet runs. Tell the user the address receives USDC, not the token`,
|
|
121509
121680
|
sold_waiting_room: `the sold USDC (${/^\d+$/.test(String(plan.sell?.usdcAtomic ?? "")) ? usdcText2(plan.sell.usdcAtomic) : "an unknown amount of"} USDC) no longer fits the 5 USDC shielded balance cap, so it waits on the wallet's own key and nothing was shielded. Spend some with x402_pay or send some out with wallet_unshield, then ${poll}; or cancel with action "cancel" and keep the USDC on the own key`,
|
|
121510
121681
|
done: "the transfer is done: tell the user the address received USDC, not the token (swap it there); wallet_balance shows the shielded balance",
|
|
121511
121682
|
cancelled: (() => {
|
|
@@ -122912,7 +123083,7 @@ function createSetupTools({
|
|
|
122912
123083
|
};
|
|
122913
123084
|
return { tools: [setupTool, statusTool, ...MCP_TOOL_NAMES.map((name) => name === "x402_discover" ? discoverTool(discoverCacheDir) : notSetUp(name))], doneTool };
|
|
122914
123085
|
}
|
|
122915
|
-
var import_web3132, shownCaps, RELEASE_RETRY_MS, STAGE_WORDS, stageWords, INTERNAL_BALANCE_DETAIL, shownBreakdown, sessionLeftShown, TOKEN_UNIT_TOOLS, RESOURCE_PAYMENT_WAL_PREFIX2, POOL_LAYOUT_CODE, POOL_LAYOUT_UPDATE, USEPOD_VIA_INFERENCE_CHAT, SELF_PAY_ORIGIN3, REQUEST_ID4, POSITIVE_ATOMIC6, PRIVATE_HOST3, FORBIDDEN_HEADERS3, MAX_BODY_BYTES2, PREVIEW_TIMEOUT_MS, PREVIEW_SELLER_READ_MS, CALL_BUDGET_MS, budgetLeft, MONEY_FIRST_ANSWER_MS, JOIN_CALL_MAX_MS, JOIN_STEP_MS, sleep2,
|
|
123086
|
+
var import_web3132, shownCaps, RELEASE_RETRY_MS, STAGE_WORDS, stageWords, INTERNAL_BALANCE_DETAIL, shownBreakdown, sessionLeftShown, TOKEN_UNIT_TOOLS, RESOURCE_PAYMENT_WAL_PREFIX2, POOL_LAYOUT_CODE, POOL_LAYOUT_UPDATE, USEPOD_VIA_INFERENCE_CHAT, SELF_PAY_ORIGIN3, REQUEST_ID4, POSITIVE_ATOMIC6, PRIVATE_HOST3, FORBIDDEN_HEADERS3, MAX_BODY_BYTES2, PREVIEW_TIMEOUT_MS, PREVIEW_SELLER_READ_MS, CALL_BUDGET_MS, budgetLeft, MONEY_FIRST_ANSWER_MS, JOIN_CALL_MAX_MS, JOIN_STEP_MS, sleep2, PROGRESS_EVERY_MS2, READ_BUDGET_MS, UNPAID_TOR_TRY_MS, UNPAID_CLEAR_MS, READ_BUDGET_TOOLS, FLOAT_BUSY_CODES, RETRY_MARGIN_MS, ASK_PAY_CODES, limitNext, SAFE_TEXT, MCP_TOOL_ALIASES, POOL_SWITCH_WHY, POOL_SWITCH_NEXT, SWITCH_STATES, quietSwitch, switchKey, ATOMIC_TEXT, switchAmount, switchEta, switchRows, OWNER_CAP_CODES, JOIN_END_MCP, JOIN_END_TERMINAL_LIBRARY, JOIN_RETRY_BACKOFF_MS, WALLET_CAP_FIX, capFix, ownerOnlyNext, mcpNext, CONFIDENTIAL_RETIRED, json2, answerResult, discoverTool, refuse11, publicOffer, FLOAT_PAID_CODES, floatStillSettling, MONEY_ID2, toRecordId, linkKindOf, moneyId, REFUSED_CODES, refusedCodeOf, PLAIN_REASONS, plainReason, KEPT_SEND_TRIES, shownId, isSplitSend, sendPartId, PROMISED_NEXT, PUBLIC_READ_TIMEOUT_MS, withTimeout, ownKey, readFailure, elsewhereId, AGENT_ID_SCHEMA, agentIdName, minutesText2, DEPOSIT_SENT_STATES, depositLanded, DEPOSIT_FINISH_STATES, usdcText2, walkWalletHistory, REFRESH_LEASE_WALK_MS, HOME_MARKS_SETTLED_MS2, AUTO_BACKUPS_KEPT, AUTO_BACKUP_NAME, AUTO_BACKUP_VERIFIED, FRONTED_SETTLE_MARGIN_SLOTS, BALANCE_REFRESH_WAIT_MS, BALANCE_REFRESH_GRACE_MS, BALANCE_REFRESH_LONG_MS, INBOUND_REFRESH_AGE_MS, CAP_BALANCE_WAIT_MS, CAP_BALANCE_RETRY_MS, REFRESH_RETRY_MS, FINALITY_POLL_MS, FINALITY_WAIT_MS, FINALITY_REFRESH_LIMIT_MS, POOL_WATCH_MS, POOL_WATCH_POLL_MS, EARLY_BALANCE_DELAY_MS, FINALITY_SETTLE_WINDOW_SLOTS, PUBLIC_READ_ANSWER_MS, SWITCH_WAIT_MS, UNSHIELD_TO_NO_USDC_DETAIL, UNSHIELD_TO_INVALID_NEXT, INFERENCE_MIN_MAX_TOKENS, ELICIT_TIMEOUT_MS, ELICIT_UNSHOWN_MS, elicitUnshown, POLL_SECONDS3, TEMP_CLEAN_DELAY_MS, KEPT_ON_DISK, MAX_SHIELDED_BALANCE_ATOMIC, receiveGenerator, MCP_TOOL_NAMES, MCP_HIDDEN_TOOL_NAMES, SETUP_TERMINAL_NEXT, SETUP_POLL_NEXT, PRIVATE_INFERENCE_WHY, PRIVATE_INFERENCE_NEXT;
|
|
122916
123087
|
var init_tools = __esm({
|
|
122917
123088
|
"wallet/src/mcp/tools.mjs"() {
|
|
122918
123089
|
"use strict";
|
|
@@ -122936,6 +123107,7 @@ var init_tools = __esm({
|
|
|
122936
123107
|
init_processLease();
|
|
122937
123108
|
init_store();
|
|
122938
123109
|
init_proxy();
|
|
123110
|
+
init_facilitatorOnion();
|
|
122939
123111
|
init_book();
|
|
122940
123112
|
init_errorLine();
|
|
122941
123113
|
init_spendPolicy();
|
|
@@ -123024,7 +123196,7 @@ var init_tools = __esm({
|
|
|
123024
123196
|
const timer = setTimeout(resolve38, Math.max(0, ms));
|
|
123025
123197
|
timer.unref?.();
|
|
123026
123198
|
});
|
|
123027
|
-
|
|
123199
|
+
PROGRESS_EVERY_MS2 = 1e4;
|
|
123028
123200
|
READ_BUDGET_MS = 3e4;
|
|
123029
123201
|
UNPAID_TOR_TRY_MS = 12e3;
|
|
123030
123202
|
UNPAID_CLEAR_MS = 25e3;
|
|
@@ -123218,6 +123390,8 @@ var init_tools = __esm({
|
|
|
123218
123390
|
agentIdName = (kind, recordId2) => `mcp-agent-id-${kind}-${recordId2}`;
|
|
123219
123391
|
minutesText2 = (n) => `${n} minute${Number(n) === 1 ? "" : "s"}`;
|
|
123220
123392
|
DEPOSIT_SENT_STATES = /* @__PURE__ */ new Set(["signed", "finalized", "published"]);
|
|
123393
|
+
depositLanded = (deposit) => deposit?.schema === DEPOSIT_WAL_SCHEMA && (["finalized", "published"].includes(deposit.state) || deposit.state === "submitted" && typeof deposit.relay?.result?.signature === "string" && deposit.relay.result.signature.length > 0);
|
|
123394
|
+
DEPOSIT_FINISH_STATES = /* @__PURE__ */ new Set(["signed", "submitted", "finalized", "published"]);
|
|
123221
123395
|
usdcText2 = (atomic4, decimals = 6) => {
|
|
123222
123396
|
const text3 = formatAtomic(BigInt(atomic4), decimals);
|
|
123223
123397
|
return text3.includes(".") ? text3.replace(/0+$/, "").replace(/\.$/, "") : text3;
|
|
@@ -150706,9 +150880,11 @@ async function runSetupCommand(values, deps) {
|
|
|
150706
150880
|
}
|
|
150707
150881
|
const home = setupHome(deps.env);
|
|
150708
150882
|
const interactive = !values.has("--yes");
|
|
150883
|
+
const torRunRecords = !values.has("--prefer-tor") && !values.has("--no-tor") && childRunProxy(deps.env).args[0] === "--tor";
|
|
150709
150884
|
if (interactive && !deps.stdinIsTTY()) {
|
|
150885
|
+
const line = ["setup", "--yes", ...setupArgvOf(values), ...childRunProxy(deps.env).args].map(shellWord).join(" ");
|
|
150710
150886
|
throw new UsageError(
|
|
150711
|
-
|
|
150887
|
+
`setup asks its questions in a terminal; in a script or a pipe pass --yes: npx -y shinjuku-shielded ${line} (add any of --max-payment, --max-session, --max-cumulative, --prefer-tor, --private-inference)`,
|
|
150712
150888
|
COMMAND_BY_NAME.get("setup")
|
|
150713
150889
|
);
|
|
150714
150890
|
}
|
|
@@ -150736,7 +150912,7 @@ async function runSetupCommand(values, deps) {
|
|
|
150736
150912
|
...values.has("--max-cumulative") ? { maxTotal: values.get("--max-cumulative") } : {},
|
|
150737
150913
|
...values.has("--max-shield") ? { maxShield: values.get("--max-shield") } : {},
|
|
150738
150914
|
...values.has("--max-unshield") ? { maxUnshield: values.get("--max-unshield") } : {},
|
|
150739
|
-
...values.has("--prefer-tor") ? { tor: true } : {},
|
|
150915
|
+
...values.has("--prefer-tor") || torRunRecords ? { tor: true } : {},
|
|
150740
150916
|
...values.has("--passphrase-file") ? { passphraseFile: values.get("--passphrase-file") } : {},
|
|
150741
150917
|
...values.has("--facilitator") ? { facilitator: values.get("--facilitator") } : {},
|
|
150742
150918
|
...values.has("--trust-proof-tools") ? { trustProofTools: values.get("--trust-proof-tools") } : {}
|
|
@@ -150747,7 +150923,7 @@ async function runSetupCommand(values, deps) {
|
|
|
150747
150923
|
io.out(`No spending limit is set. To add one later: ${CLI2} limits --max-payment <usdc> --max-cumulative <usdc> (in USDC, like 0.05; --max-payment caps one payment, --max-cumulative all payments together). A limit for any 24 hours: --max-session <usdc> in the MCP entry of your agent app.
|
|
150748
150924
|
`);
|
|
150749
150925
|
}
|
|
150750
|
-
if (!values.has("--prefer-tor")) {
|
|
150926
|
+
if (!values.has("--prefer-tor") && !torRunRecords) {
|
|
150751
150927
|
const tor = String(await deps.ask("Send every request through Tor (needs Tor running with HTTPTunnelPort 127.0.0.1:9080)? [y/N] ")).trim();
|
|
150752
150928
|
options.tor = /^y(es)?$/i.test(tor);
|
|
150753
150929
|
}
|
|
@@ -150757,8 +150933,10 @@ async function runSetupCommand(values, deps) {
|
|
|
150757
150933
|
}
|
|
150758
150934
|
}
|
|
150759
150935
|
const inference = inferenceRecordOf(old, privateInference);
|
|
150760
|
-
if (privateInference === true && options.tor !== true && old?.tor !== true) {
|
|
150936
|
+
if (privateInference === true && (options.tor !== true || torRunRecords) && old?.tor !== true) {
|
|
150761
150937
|
io.out('Private inference needs Tor, so setup records Tor for mcp (Tor must run with HTTPTunnelPort 127.0.0.1:9080), and the commands below use --tor. To turn both off later: set "tor": false and "inference": { "enabled": false } in config.json (mcp --no-tor skips Tor for one run).\n\n');
|
|
150938
|
+
} else if (torRunRecords && old?.tor !== true) {
|
|
150939
|
+
io.out('Tor is recorded for mcp: this setup runs with --tor, so config.json gets "tor": true and the MCP runs behind Tor too (Tor must run with HTTPTunnelPort 127.0.0.1:9080; mcp --no-tor skips it for one run).\n\n');
|
|
150762
150940
|
}
|
|
150763
150941
|
if (behindTor(options.tor === true || privateInference === true || options.tor === void 0 && old?.tor === true)) {
|
|
150764
150942
|
io.out("Setup continues behind Tor: the release, the proof tools, and the RPC requests go over Tor.\n");
|
|
@@ -151535,8 +151713,8 @@ var COMMANDS = [
|
|
|
151535
151713
|
flag2("--max-total", "<usdc>", "the older name of --max-cumulative", { check: "atomic", usdc: true, hidden: true }),
|
|
151536
151714
|
flag2("--max-shield", "<usdc>", "optional: the mcp --max-shield cap, in USDC (one wallet_shield deposit, and this wallet in any 24 hours)", { check: "atomic", usdc: true }),
|
|
151537
151715
|
flag2("--max-unshield", "<usdc>", "optional: the mcp --max-unshield cap, in USDC (one wallet_unshield send, and this wallet in any 24 hours)", { check: "atomic", usdc: true }),
|
|
151538
|
-
bool2("--prefer-tor", "record Tor for mcp: it then runs behind Tor (needs Tor with HTTPTunnelPort 127.0.0.1:9080); mcp --no-tor skips it for one run. Setup itself then runs behind Tor too"),
|
|
151539
|
-
bool2("--no-tor", "run this setup without Tor although Tor is recorded or asked for (the facilitator then sees this machine's IP address download the release and the proof tools); config.json still records Tor"),
|
|
151716
|
+
bool2("--prefer-tor", "record Tor for mcp: it then runs behind Tor (needs Tor with HTTPTunnelPort 127.0.0.1:9080); mcp --no-tor skips it for one run. Setup itself then runs behind Tor too. setup --tor does the same: it runs setup behind Tor and records Tor for mcp"),
|
|
151717
|
+
bool2("--no-tor", "run this setup without Tor although Tor is recorded or asked for (the facilitator then sees this machine's IP address download the release and the proof tools); config.json still records Tor. With --tor it only stops --tor from recording Tor (the run itself still goes over Tor)"),
|
|
151540
151718
|
bool2("--private-inference", 'answer yes to "Set your LLM to private inference now?": your agent buys AI answers from usePod, paid from your shielded balance over Tor. Records inference.enabled and Tor (as --prefer-tor) in config.json, and prints the path to the first private call. Without it, --yes keeps what config.json records'),
|
|
151541
151719
|
flag2("--passphrase-file", "<file>", "your own passphrase file (8 or more characters); default: setup writes a new random passphrase to <home>/passphrase.txt, readable by you alone. Needed for a wallet that exists already"),
|
|
151542
151720
|
flag2("--facilitator", "<https origin>", `the facilitator whose release, pool, and proof tools setup uses; default ${GUIDE.facilitator}`, { check: "origin" }),
|
|
@@ -151551,7 +151729,7 @@ var COMMANDS = [
|
|
|
151551
151729
|
],
|
|
151552
151730
|
notes: [
|
|
151553
151731
|
"npx -y shinjuku-shielded setup runs the same command. Without --yes it asks in the terminal: the caps (Enter keeps the default), Tor, and private inference.",
|
|
151554
|
-
|
|
151732
|
+
`When Tor is recorded or asked for (a yes, --tor, --prefer-tor, or --private-inference), setup itself runs behind Tor: the release, the proof-tool downloads, and the RPC requests go over Tor, so the facilitator never sees this machine's IP address make the wallet. config.json then records Tor for mcp ("tor": true), so the MCP runs behind Tor too. Tor must run first (torrc: HTTPTunnelPort 127.0.0.1:9080); --no-tor runs it without Tor.`,
|
|
151555
151733
|
`Private inference (a yes, or --private-inference): ${PRIVATE_INFERENCE_WHY} Setup records Tor, then prints five steps with real commands: add-funds (it shields the USDC), the first call (${CLI2} infer - --model qwen3-8-flash ... --tor, about 0.0011 USDC = 1100 atomic; its --max-payment must cover the 10000 = 0.01 USDC ceiling plus the fee), infer serve for an OpenAI client, and an MCP restart for inference_chat. In a terminal it then offers to run add-funds; it never pays an inference call.`,
|
|
151556
151734
|
"The wallet home is SHIELDED_WALLET_HOME, default ~/.carbon-shielded-wallet (every command of this CLI uses it). setup writes there: config.json, passphrase.txt (mode 0600; on Windows an access list of your account alone), the wallet (<pool>/wallet.json, made by init with the production pool, program, network, and USDC), a recovery file recovery-<time>.txt, and proof-tools/<dir>/.",
|
|
151557
151735
|
"The passphrase is never printed and no MCP tool takes or returns it. The recovery file holds the seed and the key: copy it to two offline places, then delete it from this machine.",
|