shinjuku-shielded 0.3.166 → 0.3.168
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/manifest.json +4 -4
- package/package.json +3 -3
- package/shinjuku-wallet.mjs +360 -242
package/README.md
CHANGED
|
@@ -6,19 +6,19 @@ answers privately, in a terminal chat or for your agent app. Its `mcp`
|
|
|
6
6
|
command runs a local MCP server (stdio) for your agent. Your keys never
|
|
7
7
|
leave your machine.
|
|
8
8
|
|
|
9
|
-
This is version 0.3.
|
|
9
|
+
This is version 0.3.168. The npm packages `shinjuku-shield` and
|
|
10
10
|
`shinjuku-shielded` hold the same files. The command is `shinjuku`.
|
|
11
11
|
|
|
12
12
|
## Set up
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
|
-
npm install -g shinjuku@0.3.
|
|
15
|
+
npm install -g shinjuku@0.3.168
|
|
16
16
|
shinjuku setup
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Type the two lines as they are. `npx install shinjuku` does not work: npx
|
|
20
20
|
reads `install` as the name of another npm package. To set up without
|
|
21
|
-
installing, type `npx shinjuku@0.3.
|
|
21
|
+
installing, type `npx shinjuku@0.3.168 setup`.
|
|
22
22
|
|
|
23
23
|
Setup makes the wallet on this machine, a private passphrase file, and the
|
|
24
24
|
checked proof tools (about 191 MB), and writes `config.json`. It also writes
|
|
@@ -36,13 +36,13 @@ Every wallet command works after `shinjuku`, for example `shinjuku balance`,
|
|
|
36
36
|
Claude Code:
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.
|
|
39
|
+
claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.168 mcp
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
|
|
43
43
|
|
|
44
44
|
```json
|
|
45
|
-
{ "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.
|
|
45
|
+
{ "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.168", "mcp"] } } }
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
|
|
@@ -55,7 +55,7 @@ Codex (the Codex app and Codex CLI read the same file, `~/.codex/config.toml`):
|
|
|
55
55
|
```toml
|
|
56
56
|
[mcp_servers.shinjuku]
|
|
57
57
|
command = "npx"
|
|
58
|
-
args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.
|
|
58
|
+
args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.168", "mcp"]
|
|
59
59
|
startup_timeout_sec = 120
|
|
60
60
|
tool_timeout_sec = 300
|
|
61
61
|
```
|
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": "7320b9c07d69b0d94e0ee25c1821e1f674dde5964c65e84fe3de3be6c1ff7170",
|
|
5
|
+
"bytes": 9306006,
|
|
6
|
+
"sourceCommit": "f3e7665265b2adae937b45163fff7116c6c7bd00",
|
|
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",
|
|
@@ -1038,5 +1038,5 @@
|
|
|
1038
1038
|
"version": "1.8.0"
|
|
1039
1039
|
}
|
|
1040
1040
|
],
|
|
1041
|
-
"publishedAt": "2026-11-
|
|
1041
|
+
"publishedAt": "2026-11-05T04:16:16.938Z"
|
|
1042
1042
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shielded",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.168",
|
|
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": "7320b9c0",
|
|
7
|
+
"shinjukuSha256": "7320b9c07d69b0d94e0ee25c1821e1f674dde5964c65e84fe3de3be6c1ff7170",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
9
9
|
"author": "Shinjuku Shielded",
|
|
10
10
|
"homepage": "https://github.com/ShinjukuStaition/shinjuku-shield#readme",
|
package/shinjuku-wallet.mjs
CHANGED
|
@@ -53952,28 +53952,175 @@ var init_processLock = __esm({
|
|
|
53952
53952
|
}
|
|
53953
53953
|
});
|
|
53954
53954
|
|
|
53955
|
+
// wallet/src/setup/userPath.mjs
|
|
53956
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
53957
|
+
import { basename as basename3, join as join8 } from "node:path";
|
|
53958
|
+
function commandFolder({ env = process.env, platform = process.platform } = {}) {
|
|
53959
|
+
const prefix = env.npm_config_global_prefix || env.npm_config_prefix;
|
|
53960
|
+
if (platform === "win32") return prefix || (env.APPDATA ? join8(env.APPDATA, "npm") : void 0);
|
|
53961
|
+
return prefix ? `${String(prefix).replace(/\/+$/, "")}/bin` : void 0;
|
|
53962
|
+
}
|
|
53963
|
+
function commandFileIn(folder, platform = process.platform) {
|
|
53964
|
+
if (!folder) return void 0;
|
|
53965
|
+
const file = join8(folder, platform === "win32" ? `${COMMAND_PACKAGE}.cmd` : COMMAND_PACKAGE);
|
|
53966
|
+
try {
|
|
53967
|
+
if (!statSync(file).isFile()) return void 0;
|
|
53968
|
+
if (platform !== "win32") accessSync(file, constants.X_OK);
|
|
53969
|
+
return file;
|
|
53970
|
+
} catch {
|
|
53971
|
+
return void 0;
|
|
53972
|
+
}
|
|
53973
|
+
}
|
|
53974
|
+
function shellPathEntries({ env = process.env, platform = process.platform } = {}) {
|
|
53975
|
+
const pathValue = env.PATH ?? env.Path ?? env.path ?? "";
|
|
53976
|
+
const entries = String(pathValue).split(platform === "win32" ? ";" : ":");
|
|
53977
|
+
let last = -1;
|
|
53978
|
+
entries.forEach((each, index) => {
|
|
53979
|
+
if (/[\\/]node-gyp-bin[\\/]*$/i.test(each.trim())) last = index;
|
|
53980
|
+
});
|
|
53981
|
+
return entries.slice(last + 1);
|
|
53982
|
+
}
|
|
53983
|
+
function folderOnPath(folder, { env = process.env, platform = process.platform } = {}) {
|
|
53984
|
+
const key = folderKey(folder, platform);
|
|
53985
|
+
return shellPathEntries({ env, platform }).some((each) => each.trim() && folderKey(each, platform) === key);
|
|
53986
|
+
}
|
|
53987
|
+
function addFolderToUserPath(folder, { run: run2 = spawnSync2, env = process.env } = {}) {
|
|
53988
|
+
let result;
|
|
53989
|
+
try {
|
|
53990
|
+
result = run2(
|
|
53991
|
+
"powershell.exe",
|
|
53992
|
+
[
|
|
53993
|
+
"-NoProfile",
|
|
53994
|
+
"-NonInteractive",
|
|
53995
|
+
"-ExecutionPolicy",
|
|
53996
|
+
"Bypass",
|
|
53997
|
+
"-EncodedCommand",
|
|
53998
|
+
Buffer.from(ADD_SCRIPT, "utf16le").toString("base64")
|
|
53999
|
+
],
|
|
54000
|
+
{ windowsHide: true, encoding: "utf8", timeout: 6e4, env: { ...env, SHINJUKU_PATH_FOLDER: folder } }
|
|
54001
|
+
);
|
|
54002
|
+
} catch {
|
|
54003
|
+
return { state: "failed", reason: "Windows PowerShell did not start" };
|
|
54004
|
+
}
|
|
54005
|
+
const line = String(result?.stdout ?? "").trim().split(/\r?\n/).reverse().find((each) => each.startsWith("{"));
|
|
54006
|
+
try {
|
|
54007
|
+
const answer = JSON.parse(line ?? "");
|
|
54008
|
+
if (["present", "added", "failed"].includes(answer?.state)) return answer;
|
|
54009
|
+
} catch {
|
|
54010
|
+
}
|
|
54011
|
+
return { state: "failed", reason: "Windows PowerShell gave no answer" };
|
|
54012
|
+
}
|
|
54013
|
+
function shellProfileLine(folder, { env = process.env, platform = process.platform } = {}) {
|
|
54014
|
+
const shell = basename3(String(env.SHELL ?? ""));
|
|
54015
|
+
if (shell === "fish") return { file: "~/.config/fish/config.fish", line: `fish_add_path '${String(folder).replace(/[\\']/g, "\\$&")}'` };
|
|
54016
|
+
const file = shell === "zsh" ? "~/.zshrc" : shell === "bash" ? platform === "darwin" ? "~/.bash_profile" : "~/.bashrc" : "~/.profile";
|
|
54017
|
+
return { file, line: `export PATH='${String(folder).replace(/'/g, "'\\''")}':"$PATH"` };
|
|
54018
|
+
}
|
|
54019
|
+
function commandPathStep({ env = process.env, platform = process.platform, run: run2 = spawnSync2 } = {}) {
|
|
54020
|
+
const folder = commandFolder({ env, platform });
|
|
54021
|
+
if (!commandFileIn(folder, platform)) return { state: "no-command", folder };
|
|
54022
|
+
if (platform !== "win32") {
|
|
54023
|
+
return folderOnPath(folder, { env, platform }) ? { state: "on-path", folder } : { state: "profile", folder, ...shellProfileLine(folder, { env, platform }) };
|
|
54024
|
+
}
|
|
54025
|
+
return { folder, ...addFolderToUserPath(folder, { run: run2, env }), thisWindow: folderOnPath(folder, { env, platform }) };
|
|
54026
|
+
}
|
|
54027
|
+
function pathStepSays(step) {
|
|
54028
|
+
return ["added", "failed", "profile"].includes(step?.state) || step?.state === "present" && step.thisWindow === false;
|
|
54029
|
+
}
|
|
54030
|
+
function commandPathLines(step, hereLine) {
|
|
54031
|
+
const here3 = ["In this window, type the longer command, for example:", ` ${hereLine}`];
|
|
54032
|
+
if (step?.state === "added") {
|
|
54033
|
+
return [step.broadcast === false ? "Added Shinjuku to your PATH. Sign out of Windows and in again, then type shinjuku in a new window." : "Added Shinjuku to your PATH. Open a new window to type shinjuku.", ...here3];
|
|
54034
|
+
}
|
|
54035
|
+
if (step?.state === "present") return ["Shinjuku is on your PATH. Open a new window to type shinjuku.", ...here3];
|
|
54036
|
+
if (step?.state === "failed") {
|
|
54037
|
+
return [
|
|
54038
|
+
`Setup could not add Shinjuku to your PATH (${step.reason}). To add it yourself: open Start, type environment variables, open "Edit environment variables for your account", pick Path, choose Edit, then New, and paste this folder:`,
|
|
54039
|
+
` ${step.folder}`,
|
|
54040
|
+
"Then open a new window to type shinjuku.",
|
|
54041
|
+
...here3
|
|
54042
|
+
];
|
|
54043
|
+
}
|
|
54044
|
+
if (step?.state === "profile") {
|
|
54045
|
+
return [
|
|
54046
|
+
`Your terminal does not look in the folder where npm put the shinjuku command. Add this line to the end of ${step.file}, then open a new terminal to type shinjuku:`,
|
|
54047
|
+
` ${step.line}`,
|
|
54048
|
+
...here3
|
|
54049
|
+
];
|
|
54050
|
+
}
|
|
54051
|
+
return [];
|
|
54052
|
+
}
|
|
54053
|
+
var folderKey, ADD_SCRIPT;
|
|
54054
|
+
var init_userPath = __esm({
|
|
54055
|
+
"wallet/src/setup/userPath.mjs"() {
|
|
54056
|
+
"use strict";
|
|
54057
|
+
init_fs();
|
|
54058
|
+
init_config();
|
|
54059
|
+
folderKey = (folder, platform) => {
|
|
54060
|
+
const key = String(folder).trim().replace(/^"(.*)"$/, "$1").replace(/[\\/]+$/, "");
|
|
54061
|
+
return platform === "win32" || platform === "darwin" ? key.toLowerCase() : key;
|
|
54062
|
+
};
|
|
54063
|
+
ADD_SCRIPT = String.raw`
|
|
54064
|
+
$ErrorActionPreference = 'Stop'
|
|
54065
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
54066
|
+
$folder = $env:SHINJUKU_PATH_FOLDER
|
|
54067
|
+
function Key([string]$p) { ([Environment]::ExpandEnvironmentVariables($p.Trim().Trim('"'))).TrimEnd('\', '/').ToLowerInvariant() }
|
|
54068
|
+
try {
|
|
54069
|
+
$raw = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
|
|
54070
|
+
$want = Key $folder
|
|
54071
|
+
$machineKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SYSTEM\CurrentControlSet\Control\Session Manager\Environment')
|
|
54072
|
+
$machine = if ($machineKey) { [string]$machineKey.GetValue('Path', '', $raw) } else { '' }
|
|
54073
|
+
$key = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment')
|
|
54074
|
+
$user = $key.GetValue('Path', $null, $raw)
|
|
54075
|
+
$kind = if ($null -ne $user) { $key.GetValueKind('Path') } else { [Microsoft.Win32.RegistryValueKind]::ExpandString }
|
|
54076
|
+
$entries = @(([string]$user).Split(';')) + @($machine.Split(';'))
|
|
54077
|
+
if (@($entries | Where-Object { $_.Trim() -and (Key $_) -eq $want }).Count -gt 0) {
|
|
54078
|
+
'{"state":"present"}'; exit 0
|
|
54079
|
+
}
|
|
54080
|
+
if ($kind -ne [Microsoft.Win32.RegistryValueKind]::ExpandString -and $kind -ne [Microsoft.Win32.RegistryValueKind]::String) {
|
|
54081
|
+
'{"state":"failed","reason":"your PATH setting has a type setup does not change"}'; exit 0
|
|
54082
|
+
}
|
|
54083
|
+
$old = [string]$user
|
|
54084
|
+
$new = if ($old -eq '') { $folder } elseif ($old.EndsWith(';')) { $old + $folder } else { $old + ';' + $folder }
|
|
54085
|
+
if ($new.Length -ge 32767) { '{"state":"failed","reason":"your PATH setting is full"}'; exit 0 }
|
|
54086
|
+
$key.SetValue('Path', $new, $kind)
|
|
54087
|
+
if ([string]$key.GetValue('Path', '', $raw) -ne $new) { '{"state":"failed","reason":"the new PATH did not read back"}'; exit 0 }
|
|
54088
|
+
$broadcast = $false
|
|
54089
|
+
try {
|
|
54090
|
+
Add-Type -Namespace ShinjukuPath -Name Native -MemberDefinition '[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);'
|
|
54091
|
+
$result = [UIntPtr]::Zero
|
|
54092
|
+
$broadcast = [ShinjukuPath.Native]::SendMessageTimeout([IntPtr]0xffff, 0x1A, [UIntPtr]::Zero, 'Environment', 2, 5000, [ref]$result) -ne [IntPtr]::Zero
|
|
54093
|
+
} catch { $broadcast = $false }
|
|
54094
|
+
'{"state":"added","kind":"' + $kind + '","broadcast":' + $(if ($broadcast) { 'true' } else { 'false' }) + '}'
|
|
54095
|
+
} catch {
|
|
54096
|
+
'{"state":"failed","reason":"Windows did not let setup change your PATH setting"}'
|
|
54097
|
+
}
|
|
54098
|
+
`;
|
|
54099
|
+
}
|
|
54100
|
+
});
|
|
54101
|
+
|
|
53955
54102
|
// wallet/src/setup/config.mjs
|
|
53956
54103
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
53957
54104
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
53958
54105
|
import { homedir } from "node:os";
|
|
53959
|
-
import { dirname as dirname6, isAbsolute as isAbsolute2, join as
|
|
54106
|
+
import { dirname as dirname6, isAbsolute as isAbsolute2, join as join9, resolve as resolve6 } from "node:path";
|
|
53960
54107
|
function retiredPoolText(pool2, npmVersion) {
|
|
53961
54108
|
const next = RETIRED_POOLS[pool2];
|
|
53962
54109
|
if (!next) return void 0;
|
|
53963
54110
|
return `pool ${pool2} is retired: Shinjuku runs a newer pool now, and nothing serves the old pool. It held no user balance when it was retired. Your old wallet file stays where it is; run ${oneTimeCommandLine("setup", npmVersion)} to make a wallet for the new pool`;
|
|
53964
54111
|
}
|
|
53965
54112
|
function holdsWallet(dir) {
|
|
53966
|
-
if (existsSync(
|
|
54113
|
+
if (existsSync(join9(dir, CONFIG_FILE))) return true;
|
|
53967
54114
|
try {
|
|
53968
|
-
return readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isDirectory() && existsSync(
|
|
54115
|
+
return readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isDirectory() && existsSync(join9(dir, entry.name, "wallet.json")));
|
|
53969
54116
|
} catch {
|
|
53970
54117
|
return false;
|
|
53971
54118
|
}
|
|
53972
54119
|
}
|
|
53973
54120
|
function setupHome(env = process.env, home = homedir()) {
|
|
53974
54121
|
if (env.SHIELDED_WALLET_HOME) return resolve6(env.SHIELDED_WALLET_HOME);
|
|
53975
|
-
const current =
|
|
53976
|
-
const older =
|
|
54122
|
+
const current = join9(home, HOME_FOLDER);
|
|
54123
|
+
const older = join9(home, OLDER_HOME_FOLDER);
|
|
53977
54124
|
return !holdsWallet(current) && holdsWallet(older) ? older : current;
|
|
53978
54125
|
}
|
|
53979
54126
|
function checkConfig(value2) {
|
|
@@ -54067,7 +54214,7 @@ async function setAsideInvalidConfig(home, now = /* @__PURE__ */ new Date()) {
|
|
|
54067
54214
|
function setAsideNow(home, now) {
|
|
54068
54215
|
const path = configPath(home);
|
|
54069
54216
|
const text3 = readFileSync(path, "utf8");
|
|
54070
|
-
const keptAs =
|
|
54217
|
+
const keptAs = join9(home, `config.invalid-${now.toISOString().replace(/[:.]/g, "-")}.json`);
|
|
54071
54218
|
copyFileSync(path, keptAs, constants.COPYFILE_EXCL);
|
|
54072
54219
|
rmSync(path);
|
|
54073
54220
|
let loose;
|
|
@@ -54275,11 +54422,57 @@ function claudeCodeCommand(options = {}) {
|
|
|
54275
54422
|
const platform = options.platform ?? process.platform;
|
|
54276
54423
|
const gitBash = options.gitBash ?? inGitBash(options);
|
|
54277
54424
|
const words2 = claudeCodeArgs(options).map((word, index, all) => gitBash && platform === "win32" && word === "/c" && all[index - 1] === "cmd" ? "//c" : word);
|
|
54278
|
-
|
|
54425
|
+
const program = claudeProgramWord(programOf(options), platform, options.shell ?? (gitBash ? "bash" : "cmd"));
|
|
54426
|
+
return program === void 0 ? void 0 : [program, ...words2.map((word) => hostShellWord(word, platform))].join(" ");
|
|
54427
|
+
}
|
|
54428
|
+
function claudeCodeProgram({ env = process.env, platform = process.platform, userHome = homedir(), isProgram = programFileAt } = {}) {
|
|
54429
|
+
const windows = platform === "win32";
|
|
54430
|
+
const pathValue = String(env.PATH ?? env.Path ?? "");
|
|
54431
|
+
if (windows) {
|
|
54432
|
+
const endings = String(env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((each) => each.trim()).filter(Boolean);
|
|
54433
|
+
for (const folder of pathValue.split(";").map((each) => each.trim().replace(/^"(.*)"$/, "$1")).filter(Boolean)) {
|
|
54434
|
+
if (endings.some((ending) => isProgram(join9(folder, `claude${ending.toLowerCase()}`), platform))) return "claude";
|
|
54435
|
+
}
|
|
54436
|
+
} else {
|
|
54437
|
+
for (const folder of pathValue.split(":")) {
|
|
54438
|
+
if (isProgram(join9(folder === "" ? "." : folder, "claude"), platform)) return "claude";
|
|
54439
|
+
}
|
|
54440
|
+
}
|
|
54441
|
+
const npmFolder = commandFolder({ env, platform });
|
|
54442
|
+
const places = windows ? [join9(env.USERPROFILE || userHome, ".local", "bin", "claude.exe"), ...npmFolder ? [join9(npmFolder, "claude.cmd")] : []] : [join9(userHome, ".local", "bin", "claude"), ...npmFolder ? [join9(npmFolder, "claude")] : []];
|
|
54443
|
+
return places.find((file) => isProgram(file, platform));
|
|
54444
|
+
}
|
|
54445
|
+
function programFileAt(file, platform = process.platform) {
|
|
54446
|
+
try {
|
|
54447
|
+
if (!statSync(file).isFile()) return false;
|
|
54448
|
+
if (platform !== "win32") accessSync(file, constants.X_OK);
|
|
54449
|
+
return true;
|
|
54450
|
+
} catch {
|
|
54451
|
+
return false;
|
|
54452
|
+
}
|
|
54453
|
+
}
|
|
54454
|
+
function claudeProgramWord(program, platform, shell = "cmd") {
|
|
54455
|
+
if (!program || program === "claude") return "claude";
|
|
54456
|
+
if (platform !== "win32") return hostShellWord(program, platform);
|
|
54457
|
+
const slashed = program.replace(/\\/g, "/");
|
|
54458
|
+
if (/^[A-Za-z0-9_./:=@-]+$/.test(slashed)) return slashed;
|
|
54459
|
+
if (shell === "bash") return hostShellWord(slashed, "linux");
|
|
54460
|
+
if (shell === "powershell") return `& '${program.replace(/'/g, "''")}'`;
|
|
54461
|
+
return CMD_UNSAFE.test(program) ? void 0 : `"${program}"`;
|
|
54462
|
+
}
|
|
54463
|
+
function claudeProgramRunWhy(program, platform = process.platform) {
|
|
54464
|
+
if (platform !== "win32" || !program || program === "claude" || /\.exe$/i.test(program) || !CMD_UNSAFE.test(program)) return null;
|
|
54465
|
+
return `its folder path (${program}) holds a character that cmd reads as code, so setup cannot start it`;
|
|
54279
54466
|
}
|
|
54280
54467
|
function claudeCodeLines(options = {}) {
|
|
54281
54468
|
if ((options.platform ?? process.platform) !== "win32") return ["Claude Code (run once):", ` ${claudeCodeCommand(options)}`];
|
|
54282
|
-
const
|
|
54469
|
+
const split4 = claudeLineDiffers(options);
|
|
54470
|
+
const cmdLine = claudeCodeCommand({ ...options, gitBash: false, shell: "cmd" });
|
|
54471
|
+
const powershell = split4 ? [
|
|
54472
|
+
"Claude Code (run once; in PowerShell):",
|
|
54473
|
+
` ${claudeCodeCommand({ ...options, gitBash: false, shell: "powershell" })}`,
|
|
54474
|
+
...cmdLine ? ["Claude Code (run once; in cmd):", ` ${cmdLine}`] : ["Claude Code in cmd: its folder path holds %, which cmd reads as code; use the PowerShell or Git Bash line."]
|
|
54475
|
+
] : ["Claude Code (run once; in PowerShell or cmd):", ` ${cmdLine}`];
|
|
54283
54476
|
const gitBash = ["Claude Code (run once; in Git Bash):", ` ${claudeCodeCommand({ ...options, gitBash: true })}`];
|
|
54284
54477
|
return inGitBash(options) ? [...gitBash, ...powershell] : [...powershell, ...gitBash];
|
|
54285
54478
|
}
|
|
@@ -54298,28 +54491,45 @@ function hostShellWord(word, platform = process.platform) {
|
|
|
54298
54491
|
}
|
|
54299
54492
|
function hostConfigFile(target, { platform = process.platform, env = process.env, home = homedir() } = {}) {
|
|
54300
54493
|
const set = (name) => typeof env[name] === "string" && env[name].trim() ? env[name].trim() : void 0;
|
|
54301
|
-
if (target === "cursor") return
|
|
54302
|
-
if (target === "codex") return
|
|
54494
|
+
if (target === "cursor") return join9(home, ".cursor", "mcp.json");
|
|
54495
|
+
if (target === "codex") return join9(env.CODEX_HOME || join9(home, ".codex"), "config.toml");
|
|
54303
54496
|
if (target === "vscode") {
|
|
54304
|
-
const appData = platform === "win32" ? env.APPDATA ||
|
|
54305
|
-
return
|
|
54497
|
+
const appData = platform === "win32" ? env.APPDATA || join9(home, "AppData", "Roaming") : platform === "darwin" ? join9(home, "Library", "Application Support") : env.XDG_CONFIG_HOME || join9(home, ".config");
|
|
54498
|
+
return join9(appData, "Code", "User", "mcp.json");
|
|
54306
54499
|
}
|
|
54307
54500
|
if (target === "devin") {
|
|
54308
|
-
return
|
|
54501
|
+
return join9(platform === "win32" ? join9(home, "AppData", "Roaming", "devin") : join9(env.XDG_CONFIG_HOME || join9(home, ".config"), "devin"), "mcp_config.json");
|
|
54309
54502
|
}
|
|
54310
54503
|
if (target === "cline") {
|
|
54311
|
-
return set("CLINE_MCP_SETTINGS_PATH") ??
|
|
54504
|
+
return set("CLINE_MCP_SETTINGS_PATH") ?? join9(set("CLINE_DATA_DIR") ?? join9(set("CLINE_DIR") ?? join9(home, ".cline"), "data"), "settings", "cline_mcp_settings.json");
|
|
54312
54505
|
}
|
|
54313
|
-
if (target === "continue") return
|
|
54314
|
-
if (target === "gemini") return
|
|
54315
|
-
if (target === "antigravity") return
|
|
54506
|
+
if (target === "continue") return join9(set("CONTINUE_GLOBAL_DIR") ? resolve6(set("CONTINUE_GLOBAL_DIR")) : join9(home, ".continue"), "mcpServers", `${MCP_SERVER_NAME}.yaml`);
|
|
54507
|
+
if (target === "gemini") return join9(set("GEMINI_CLI_HOME") ?? home, ".gemini", "settings.json");
|
|
54508
|
+
if (target === "antigravity") return join9(home, ".gemini", "config", "mcp_config.json");
|
|
54316
54509
|
if (target === "claude-desktop") {
|
|
54317
|
-
if (platform === "win32") return
|
|
54318
|
-
if (platform === "darwin") return
|
|
54319
|
-
return
|
|
54510
|
+
if (platform === "win32") return packagedClaudeDesktopFile(env, home) ?? join9(env.APPDATA || join9(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
|
|
54511
|
+
if (platform === "darwin") return join9(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
54512
|
+
return join9(env.XDG_CONFIG_HOME || join9(home, ".config"), "Claude", "claude_desktop_config.json");
|
|
54320
54513
|
}
|
|
54321
54514
|
return void 0;
|
|
54322
54515
|
}
|
|
54516
|
+
function packagedClaudeDesktopFile(env, home) {
|
|
54517
|
+
const packages = join9(env.LOCALAPPDATA || join9(home, "AppData", "Local"), "Packages");
|
|
54518
|
+
let names;
|
|
54519
|
+
try {
|
|
54520
|
+
names = readdirSync(packages);
|
|
54521
|
+
} catch {
|
|
54522
|
+
return void 0;
|
|
54523
|
+
}
|
|
54524
|
+
const files = names.filter((each) => /^Claude_[a-z0-9]+$/i.test(each)).map((name) => join9(packages, name, "LocalCache", "Roaming", "Claude", "claude_desktop_config.json")).filter((file) => existsSync(file));
|
|
54525
|
+
if (files.length > 1) {
|
|
54526
|
+
throw Object.assign(
|
|
54527
|
+
new Error(`setup_host_config_ambiguous: this computer has ${files.length} Claude Desktop settings files (${files.join("; ")}), so the wallet did not pick one`),
|
|
54528
|
+
{ files }
|
|
54529
|
+
);
|
|
54530
|
+
}
|
|
54531
|
+
return files[0];
|
|
54532
|
+
}
|
|
54323
54533
|
function hostConfigText({ home, env = process.env, platform = process.platform, npmVersion, skip = /* @__PURE__ */ new Set(), userHome = homedir() } = {}) {
|
|
54324
54534
|
const entry = mcpServerEntry({ home, platform, npmVersion });
|
|
54325
54535
|
const more = ["vscode", "devin", "cline", "continue", "gemini", "antigravity"].filter((target) => !skip.has(target)).flatMap((target) => {
|
|
@@ -54332,7 +54542,10 @@ function hostConfigText({ home, env = process.env, platform = process.platform,
|
|
|
54332
54542
|
];
|
|
54333
54543
|
});
|
|
54334
54544
|
const member = `${JSON.stringify(MCP_SERVER_NAME)}: ${JSON.stringify(entry, null, 2)}`;
|
|
54335
|
-
const files = [
|
|
54545
|
+
const files = [
|
|
54546
|
+
["claude-desktop", "Claude Desktop (claude_desktop_config.json: in Claude Desktop, Settings > Developer > Edit Config opens it)"],
|
|
54547
|
+
["cursor", "Cursor (~/.cursor/mcp.json)"]
|
|
54548
|
+
].filter(([target]) => !skip.has(target)).map(([, label]) => label);
|
|
54336
54549
|
return [
|
|
54337
54550
|
...skip.has("claude-code") ? [] : claudeCodeShellWhy({ home, env, platform }) ? ["Claude Code:", ` ${claudeCodeShellWhy({ home, env, platform })}`] : claudeCodeLines({ home, env, platform, npmVersion }),
|
|
54338
54551
|
...files.length ? [
|
|
@@ -54340,7 +54553,7 @@ function hostConfigText({ home, env = process.env, platform = process.platform,
|
|
|
54340
54553
|
...member.split("\n").map((line) => ` ${line}`)
|
|
54341
54554
|
] : [],
|
|
54342
54555
|
...skip.has("codex") ? [] : [
|
|
54343
|
-
"Codex (the Codex app and Codex CLI), at the end of ~/.codex/config.toml:",
|
|
54556
|
+
"Codex (the Codex side of the ChatGPT desktop app, and Codex CLI), at the end of ~/.codex/config.toml:",
|
|
54344
54557
|
...codexTomlBlock(entry).trimEnd().split("\n").map((line) => ` ${line}`)
|
|
54345
54558
|
],
|
|
54346
54559
|
...more
|
|
@@ -54658,12 +54871,12 @@ function isSameClaudeCodeEntry(existing, options = {}) {
|
|
|
54658
54871
|
return entry !== void 0 && sameJson(entry, mcpServerEntry(options));
|
|
54659
54872
|
}
|
|
54660
54873
|
function restrictToOwnerWindows(file, { run: run2 = execFileSync2 } = {}) {
|
|
54661
|
-
const system32 =
|
|
54874
|
+
const system32 = join9(process.env.SystemRoot || "C:/Windows", "System32");
|
|
54662
54875
|
try {
|
|
54663
|
-
const line = String(run2(
|
|
54876
|
+
const line = String(run2(join9(system32, "whoami.exe"), ["/user", "/fo", "csv", "/nh"], { encoding: "utf8", windowsHide: true }));
|
|
54664
54877
|
const sid = line.match(/"(S-1-[0-9-]+)"/)?.[1];
|
|
54665
54878
|
if (!sid) throw new Error("no sid");
|
|
54666
|
-
run2(
|
|
54879
|
+
run2(join9(system32, "icacls.exe"), [file, "/inheritance:r", "/grant:r", `*${sid}:F`], { stdio: "ignore", windowsHide: true });
|
|
54667
54880
|
} catch {
|
|
54668
54881
|
throw new Error("setup_host_config_acl_failed: setup could not limit the file to only you on this computer (icacls), so it did not write it; add the printed entry by hand");
|
|
54669
54882
|
}
|
|
@@ -54936,7 +55149,7 @@ function changeFileOnce(file, change, { now, platform, restrict, codec = JSON_CO
|
|
|
54936
55149
|
}
|
|
54937
55150
|
return { changed: true, ...backup ? { backup } : {} };
|
|
54938
55151
|
}
|
|
54939
|
-
var import_web396, CONFIG_SCHEMA, CONFIG_FILE, NPM_PACKAGE_NAMES, COMMAND_PACKAGE, NPX_PACKAGE, NPX_INSTALL_FLAGS, MCP_SERVER_NAME, OLD_MCP_SERVER_NAMES, P03_BINDING, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC, HOME_FOLDER, OLDER_HOME_FOLDER, defaultHomeWords, configPath, homeWalletPath, invalid, isPubkey, MAX_OWN_ADDRESSES, isOwnAddressText, salvagePath, clearConfigSalvage, HOST_TARGETS, HOST_NAMES, hostServersKey, hostEntry, CODEX_STARTUP_TIMEOUT_SEC, CODEX_TOOL_TIMEOUT_SEC, PINNED_PACKAGE, LAUNCHER_PACKAGE, NPM_VERSION, knownNpmVersion, RECOVERY_WORDS, NPX_WALLET_LINE, RELEASES_URL, npmStartEnvironment, NPM_START_KEYS, defaultWalletHome, WINDOWS_SHELL_CODE, CONTINUE_HEADER, tomlString, tomlKey, codexEntryOf, isPlainObject, sameJson, claudeCodeEntry, READ_ONLY_TOOL_NAMES, claudeCodeAllowRules, claudeCodeSettingsFile, UNREADABLE_JSON, JSON_CODEC, indentAt, TEXT_CODEC, RACED;
|
|
55152
|
+
var import_web396, CONFIG_SCHEMA, CONFIG_FILE, NPM_PACKAGE_NAMES, COMMAND_PACKAGE, NPX_PACKAGE, NPX_INSTALL_FLAGS, MCP_SERVER_NAME, OLD_MCP_SERVER_NAMES, P03_BINDING, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC, HOME_FOLDER, OLDER_HOME_FOLDER, defaultHomeWords, configPath, homeWalletPath, invalid, isPubkey, MAX_OWN_ADDRESSES, isOwnAddressText, salvagePath, clearConfigSalvage, HOST_TARGETS, HOST_NAMES, hostServersKey, hostEntry, CODEX_STARTUP_TIMEOUT_SEC, CODEX_TOOL_TIMEOUT_SEC, PINNED_PACKAGE, LAUNCHER_PACKAGE, NPM_VERSION, knownNpmVersion, RECOVERY_WORDS, NPX_WALLET_LINE, RELEASES_URL, npmStartEnvironment, NPM_START_KEYS, defaultWalletHome, CMD_UNSAFE, programOf, claudeLineDiffers, WINDOWS_SHELL_CODE, CONTINUE_HEADER, tomlString, tomlKey, codexEntryOf, isPlainObject, sameJson, claudeCodeEntry, READ_ONLY_TOOL_NAMES, claudeCodeAllowRules, claudeCodeSettingsFile, UNREADABLE_JSON, JSON_CODEC, indentAt, TEXT_CODEC, RACED;
|
|
54940
55153
|
var init_config = __esm({
|
|
54941
55154
|
"wallet/src/setup/config.mjs"() {
|
|
54942
55155
|
"use strict";
|
|
@@ -54944,6 +55157,7 @@ var init_config = __esm({
|
|
|
54944
55157
|
import_web396 = __toESM(require_index_cjs(), 1);
|
|
54945
55158
|
init_rpcDefault();
|
|
54946
55159
|
init_processLock();
|
|
55160
|
+
init_userPath();
|
|
54947
55161
|
CONFIG_SCHEMA = "shinjuku-shielded/config/v1";
|
|
54948
55162
|
CONFIG_FILE = "config.json";
|
|
54949
55163
|
NPM_PACKAGE_NAMES = Object.freeze(["shinjuku-shield", "shinjuku-shielded"]);
|
|
@@ -54981,9 +55195,9 @@ var init_config = __esm({
|
|
|
54981
55195
|
POSITIVE_ATOMIC = /^[1-9][0-9]{0,30}$/;
|
|
54982
55196
|
HOME_FOLDER = ".shinjuku-shield";
|
|
54983
55197
|
OLDER_HOME_FOLDER = ".carbon-shielded-wallet";
|
|
54984
|
-
defaultHomeWords = (home = homedir()) => `~/${setupHome({}, home) ===
|
|
54985
|
-
configPath = (home) =>
|
|
54986
|
-
homeWalletPath = (home, pool2) =>
|
|
55198
|
+
defaultHomeWords = (home = homedir()) => `~/${setupHome({}, home) === join9(home, HOME_FOLDER) ? HOME_FOLDER : OLDER_HOME_FOLDER}`;
|
|
55199
|
+
configPath = (home) => join9(home, CONFIG_FILE);
|
|
55200
|
+
homeWalletPath = (home, pool2) => join9(home, pool2, "wallet.json");
|
|
54987
55201
|
invalid = (why) => new Error(`setup_config_invalid: config.json ${why}; rerun shinjuku setup (it keeps the wallet) or fix the file`);
|
|
54988
55202
|
isPubkey = (value2) => {
|
|
54989
55203
|
try {
|
|
@@ -54994,7 +55208,7 @@ var init_config = __esm({
|
|
|
54994
55208
|
};
|
|
54995
55209
|
MAX_OWN_ADDRESSES = 8;
|
|
54996
55210
|
isOwnAddressText = (value2) => isPubkey(value2);
|
|
54997
|
-
salvagePath = (home) =>
|
|
55211
|
+
salvagePath = (home) => join9(home, "config.salvage.json");
|
|
54998
55212
|
clearConfigSalvage = (home) => rmSync(salvagePath(home), { force: true });
|
|
54999
55213
|
HOST_TARGETS = Object.freeze(["claude-code", "claude-desktop", "cursor", "codex", "vscode", "devin", "cline", "continue", "gemini", "antigravity"]);
|
|
55000
55214
|
HOST_NAMES = Object.freeze({
|
|
@@ -55023,6 +55237,9 @@ var init_config = __esm({
|
|
|
55023
55237
|
npmStartEnvironment = (tor) => tor ? { npm_config_offline: "true" } : { npm_config_prefer_offline: "true" };
|
|
55024
55238
|
NPM_START_KEYS = ["npm_config_offline", "npm_config_prefer_offline"];
|
|
55025
55239
|
defaultWalletHome = (home = homedir()) => setupHome({}, home);
|
|
55240
|
+
CMD_UNSAFE = /[%"\r\n]/;
|
|
55241
|
+
programOf = (options) => "claudeProgram" in options ? options.claudeProgram : claudeCodeProgram(options);
|
|
55242
|
+
claudeLineDiffers = (options) => claudeProgramWord(programOf(options), "win32", "cmd") !== claudeProgramWord(programOf(options), "win32", "powershell");
|
|
55026
55243
|
WINDOWS_SHELL_CODE = /[%$`"\r\n]/;
|
|
55027
55244
|
CONTINUE_HEADER = Object.freeze(["name: Shinjuku Shield", "version: 0.0.1", "schema: v1", "mcpServers:"]);
|
|
55028
55245
|
tomlString = (value2) => `"${String(value2).replace(/[\\"]/g, (c) => `\\${c}`).replace(/[\u0000-\u001f\u007f]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`)}"`;
|
|
@@ -55047,7 +55264,7 @@ var init_config = __esm({
|
|
|
55047
55264
|
"inference_models"
|
|
55048
55265
|
]);
|
|
55049
55266
|
claudeCodeAllowRules = () => READ_ONLY_TOOL_NAMES.map((name) => `mcp__${MCP_SERVER_NAME}__${name}`);
|
|
55050
|
-
claudeCodeSettingsFile = ({ env = process.env, home = homedir() } = {}) =>
|
|
55267
|
+
claudeCodeSettingsFile = ({ env = process.env, home = homedir() } = {}) => join9(env.CLAUDE_CONFIG_DIR || join9(home, ".claude"), "settings.json");
|
|
55051
55268
|
UNREADABLE_JSON = "setup_host_config_unreadable: the host's config file is not a JSON object, so setup left it alone; add the printed entry by hand";
|
|
55052
55269
|
JSON_CODEC = Object.freeze({
|
|
55053
55270
|
empty: () => ({}),
|
|
@@ -55085,7 +55302,7 @@ var init_config = __esm({
|
|
|
55085
55302
|
|
|
55086
55303
|
// wallet/src/setup/channel.mjs
|
|
55087
55304
|
import { createPublicKey as createPublicKey2, randomBytes as randomBytes8, verify } from "node:crypto";
|
|
55088
|
-
import { join as
|
|
55305
|
+
import { join as join10 } from "node:path";
|
|
55089
55306
|
function canonicalJson(value2) {
|
|
55090
55307
|
if (value2 === null || typeof value2 !== "object") {
|
|
55091
55308
|
if (typeof value2 === "number" && !Number.isFinite(value2)) throw fail7("wallet_channel_invalid", "the channel body holds a number JSON cannot carry");
|
|
@@ -55170,7 +55387,7 @@ function verifyChannelDocument(document2, { publicKeyHex = CHANNEL_PUBLIC_KEY_HE
|
|
|
55170
55387
|
return checkBody(document2.body);
|
|
55171
55388
|
}
|
|
55172
55389
|
function readSeq(home) {
|
|
55173
|
-
const path =
|
|
55390
|
+
const path = join10(home, CHANNEL_SEQ_FILE);
|
|
55174
55391
|
if (!existsSync(path)) return -1;
|
|
55175
55392
|
let value2;
|
|
55176
55393
|
try {
|
|
@@ -55198,9 +55415,9 @@ function acceptSeq(home, body, documentBytes) {
|
|
|
55198
55415
|
throw fail7("wallet_channel_rollback", `Shinjuku serves channel ${body.seq}, older than channel ${seen} this wallet already saw; nothing was installed and the old setup files stay`);
|
|
55199
55416
|
}
|
|
55200
55417
|
mkdirSync(home, { recursive: true, mode: 448 });
|
|
55201
|
-
if (body.seq > seen) writeAtomic(
|
|
55418
|
+
if (body.seq > seen) writeAtomic(join10(home, CHANNEL_SEQ_FILE), `${JSON.stringify({ seq: body.seq })}
|
|
55202
55419
|
`);
|
|
55203
|
-
if (documentBytes) writeAtomic(
|
|
55420
|
+
if (documentBytes) writeAtomic(join10(home, CHANNEL_FILE), documentBytes);
|
|
55204
55421
|
}
|
|
55205
55422
|
function onChannelRegistered(listener) {
|
|
55206
55423
|
registrationListeners.add(listener);
|
|
@@ -55275,7 +55492,7 @@ function applyStoredChannel({ home, publicKeyHex = CHANNEL_PUBLIC_KEY_HEX }) {
|
|
|
55275
55492
|
} catch {
|
|
55276
55493
|
return void 0;
|
|
55277
55494
|
}
|
|
55278
|
-
const path =
|
|
55495
|
+
const path = join10(home, CHANNEL_FILE);
|
|
55279
55496
|
if (!existsSync(path)) return void 0;
|
|
55280
55497
|
let document2;
|
|
55281
55498
|
try {
|
|
@@ -61655,16 +61872,16 @@ var init_incremental = __esm({
|
|
|
61655
61872
|
// wallet/src/history/walletHistory.mjs
|
|
61656
61873
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
|
|
61657
61874
|
import { createHmac as createHmac5 } from "node:crypto";
|
|
61658
|
-
import { dirname as dirname8, join as
|
|
61875
|
+
import { dirname as dirname8, join as join11, resolve as resolve7 } from "node:path";
|
|
61659
61876
|
function walletHistoryCache(store) {
|
|
61660
|
-
return createHistoryCacheStore({ path:
|
|
61877
|
+
return createHistoryCacheStore({ path: join11(dirname8(store.path), "history-cache.json"), hmacKey: historyCacheKey(store) });
|
|
61661
61878
|
}
|
|
61662
61879
|
function walletSuccessorHistoryCache(store, pool2) {
|
|
61663
61880
|
if (!/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(String(pool2))) throw new Error("wallet_succession_chain_invalid");
|
|
61664
|
-
return createHistoryCacheStore({ path:
|
|
61881
|
+
return createHistoryCacheStore({ path: join11(dirname8(store.path), `history-cache-successor-${pool2}.json`), hmacKey: historyCacheKey(store) });
|
|
61665
61882
|
}
|
|
61666
61883
|
function walletCompactHistoryCache(store) {
|
|
61667
|
-
return createCompactHistoryCacheStore({ path:
|
|
61884
|
+
return createCompactHistoryCacheStore({ path: join11(dirname8(store.path), "history-compact-cache.json"), hmacKey: historyCacheKey(store) });
|
|
61668
61885
|
}
|
|
61669
61886
|
async function loadWalletP03History(args) {
|
|
61670
61887
|
const runKey = lastRunReportKey(args.store, args.programId, args.pool, args.deploymentIdentity, args.cache);
|
|
@@ -63210,7 +63427,7 @@ var init_production_proof_bundle = __esm({
|
|
|
63210
63427
|
// wallet/src/prove/recoveredPayment.mjs
|
|
63211
63428
|
import { spawn as spawn2 } from "node:child_process";
|
|
63212
63429
|
import { createHash as createHash15 } from "node:crypto";
|
|
63213
|
-
import { dirname as dirname10, isAbsolute as isAbsolute4, join as
|
|
63430
|
+
import { dirname as dirname10, isAbsolute as isAbsolute4, join as join12, relative as relative4, resolve as resolve10 } from "node:path";
|
|
63214
63431
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
63215
63432
|
function fail9(reason) {
|
|
63216
63433
|
throw new Error(`p03_recovered_payment_${reason}`);
|
|
@@ -63597,7 +63814,7 @@ async function proveRecoveredP03Payment({ request, tools, onMemoBundle }) {
|
|
|
63597
63814
|
const bundle = loadBundle(tools);
|
|
63598
63815
|
markPhase("bundle");
|
|
63599
63816
|
const started = await takeEarlyTools(tools);
|
|
63600
|
-
const scratch = started?.scratch ?? mkdtempSync(
|
|
63817
|
+
const scratch = started?.scratch ?? mkdtempSync(join12(tmpdir2(), "sx402-wallet-payment-"));
|
|
63601
63818
|
try {
|
|
63602
63819
|
const { vectors, primaryProofs } = scratchDirectories(scratch);
|
|
63603
63820
|
if (!started) {
|
|
@@ -63653,7 +63870,7 @@ async function proveRecoveredP03Payment({ request, tools, onMemoBundle }) {
|
|
|
63653
63870
|
} catch {
|
|
63654
63871
|
}
|
|
63655
63872
|
markPhase("payment-prover", Number.isSafeInteger(ownMs) && ownMs >= 0 ? `proof_ms${ownMs}` : void 0);
|
|
63656
|
-
const primary = JSON.parse(readFileSync(
|
|
63873
|
+
const primary = JSON.parse(readFileSync(join12(primaryProofs, "shielded-exact-v2.json"), "utf8"));
|
|
63657
63874
|
if (JSON.stringify(primary.publicInputBytesHex) !== JSON.stringify(output2.primaryWitness.publicInputBytesHex)) {
|
|
63658
63875
|
fail9("proof_public_inputs_mismatch");
|
|
63659
63876
|
}
|
|
@@ -63689,7 +63906,7 @@ function startRecoveredPaymentTools(tools, { maxAgeMs = EARLY_TOOLS_MAX_AGE_MS }
|
|
|
63689
63906
|
}
|
|
63690
63907
|
async function launchEarlyTools(tools) {
|
|
63691
63908
|
const bundle = loadBundle(tools);
|
|
63692
|
-
const scratch = mkdtempSync(
|
|
63909
|
+
const scratch = mkdtempSync(join12(tmpdir2(), "sx402-wallet-payment-"));
|
|
63693
63910
|
const runs = [];
|
|
63694
63911
|
const stop3 = async () => {
|
|
63695
63912
|
for (const run2 of runs) run2.send("");
|
|
@@ -63744,10 +63961,10 @@ async function proveP03Vector({ tools, relation, vector }) {
|
|
|
63744
63961
|
const [toolName, outputName] = RELATION_PROVERS[relation] ?? fail9("relation_invalid");
|
|
63745
63962
|
const tool = tools[toolName] ?? fail9(`${toolName}_missing`);
|
|
63746
63963
|
const bundle = loadBundle(tools);
|
|
63747
|
-
const scratch = mkdtempSync(
|
|
63964
|
+
const scratch = mkdtempSync(join12(tmpdir2(), "sx402-wallet-vector-"));
|
|
63748
63965
|
try {
|
|
63749
|
-
const vectorPath =
|
|
63750
|
-
const proofs =
|
|
63966
|
+
const vectorPath = join12(scratch, "vector.json");
|
|
63967
|
+
const proofs = join12(scratch, "proof");
|
|
63751
63968
|
mkdirSync(proofs, { mode: 448 });
|
|
63752
63969
|
writeFileSync(vectorPath, jsonBytes(vector), { mode: 384 });
|
|
63753
63970
|
try {
|
|
@@ -63760,7 +63977,7 @@ async function proveP03Vector({ tools, relation, vector }) {
|
|
|
63760
63977
|
} catch (error) {
|
|
63761
63978
|
throw new Error(`p03_recovered_payment_${relation.replaceAll("-", "_")}_prover_failed`, { cause: error });
|
|
63762
63979
|
}
|
|
63763
|
-
const proof = JSON.parse(readFileSync(
|
|
63980
|
+
const proof = JSON.parse(readFileSync(join12(proofs, outputName), "utf8"));
|
|
63764
63981
|
return Object.freeze({ proofBytesHex: proof.proofBytesHex, publicInputBytesHex: proof.publicInputBytesHex });
|
|
63765
63982
|
} finally {
|
|
63766
63983
|
removeScratch(scratch);
|
|
@@ -63789,9 +64006,9 @@ var init_recoveredPayment = __esm({
|
|
|
63789
64006
|
${stamp}`;
|
|
63790
64007
|
bundleStamps = (files) => files.map((file) => fileStamp(file)).join("\n");
|
|
63791
64008
|
OPTIONAL_TOOL_KEYS = /* @__PURE__ */ new Set(["depositProver", "solanaCli", "moveWitness", "moveProver"]);
|
|
63792
|
-
scratchDirectories = (scratch) => ({ vectors:
|
|
64009
|
+
scratchDirectories = (scratch) => ({ vectors: join12(scratch, "vectors"), primaryProofs: join12(scratch, "payment-proof") });
|
|
63793
64010
|
paymentProverEnvironment = (bundle, vectors, primaryProofs) => ({
|
|
63794
|
-
SHIELDED_X402_VECTOR_PATH:
|
|
64011
|
+
SHIELDED_X402_VECTOR_PATH: join12(vectors, "shielded-exact-v2.json"),
|
|
63795
64012
|
SHIELDED_X402_PRODUCTION_PROOF_DIR: primaryProofs,
|
|
63796
64013
|
SHIELDED_X402_PARAMETER_MANIFEST_SHA256: bundle.manifestSha256,
|
|
63797
64014
|
SHIELDED_X402_PARAMETER_PATH: bundle.relations["shielded-exact-v2"].parameterPath
|
|
@@ -65945,10 +66162,10 @@ var init_deposit = __esm({
|
|
|
65945
66162
|
|
|
65946
66163
|
// wallet/src/store/sealedCache.mjs
|
|
65947
66164
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, createHmac as createHmac7, randomBytes as randomBytes11 } from "node:crypto";
|
|
65948
|
-
import { dirname as dirname12, join as
|
|
66165
|
+
import { dirname as dirname12, join as join13 } from "node:path";
|
|
65949
66166
|
function sealedCacheFile(store, { file, schema, keyLabel }) {
|
|
65950
66167
|
if (typeof store?.path !== "string" || !/^[0-9a-f]{64}$/i.test(store?.state?.seedHex ?? "")) return void 0;
|
|
65951
|
-
const path =
|
|
66168
|
+
const path = join13(dirname12(store.path), file);
|
|
65952
66169
|
const key = createHmac7("sha256", Buffer.from(store.state.seedHex, "hex")).update(keyLabel).digest();
|
|
65953
66170
|
const aad = Buffer.from(schema, "utf8");
|
|
65954
66171
|
return Object.freeze({
|
|
@@ -66570,14 +66787,14 @@ var init_successorHistories = __esm({
|
|
|
66570
66787
|
|
|
66571
66788
|
// wallet/src/recovery/recover.mjs
|
|
66572
66789
|
import { createHash as createHash16 } from "node:crypto";
|
|
66573
|
-
import { join as
|
|
66790
|
+
import { join as join14, resolve as resolve11 } from "node:path";
|
|
66574
66791
|
import { performance as performance4 } from "node:perf_hooks";
|
|
66575
66792
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
66576
66793
|
function pinnedGenerator2(profileVector) {
|
|
66577
66794
|
if (profileVector?.payerKeys?.generator) return profileVector.payerKeys.generator;
|
|
66578
66795
|
if (!committedGenerator) {
|
|
66579
66796
|
const committed2 = JSON.parse(readFileSync(
|
|
66580
|
-
|
|
66797
|
+
join14(MODEL_DIR, "vectors", "rust-vectors.json"),
|
|
66581
66798
|
"utf8"
|
|
66582
66799
|
));
|
|
66583
66800
|
committedGenerator = Object.freeze(committed2.payerKeys.generator);
|
|
@@ -75621,7 +75838,7 @@ var init_production_proof_bundle2 = __esm({
|
|
|
75621
75838
|
// spikes/shielded-x402-wallet/lib/p03-recovered-exit.mjs
|
|
75622
75839
|
import { spawn as spawn3 } from "node:child_process";
|
|
75623
75840
|
import { createHash as createHash18 } from "node:crypto";
|
|
75624
|
-
import { dirname as dirname14, isAbsolute as isAbsolute6, join as
|
|
75841
|
+
import { dirname as dirname14, isAbsolute as isAbsolute6, join as join15, relative as relative6, resolve as resolve14 } from "node:path";
|
|
75625
75842
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
75626
75843
|
function fail15(reason) {
|
|
75627
75844
|
throw new Error(`p03_recovered_exit_${reason}`);
|
|
@@ -75909,11 +76126,11 @@ function proveRecoveredP03Exit({ request, tools }) {
|
|
|
75909
76126
|
return proveLoadedExit({ request, tools, kind, primaryProver, bundle });
|
|
75910
76127
|
}
|
|
75911
76128
|
async function proveLoadedExit({ request, tools, kind, primaryProver, bundle }) {
|
|
75912
|
-
const scratch = mkdtempSync(
|
|
76129
|
+
const scratch = mkdtempSync(join15(tmpdir3(), kind.scratchPrefix));
|
|
75913
76130
|
try {
|
|
75914
|
-
const vectors =
|
|
75915
|
-
const primaryProofs =
|
|
75916
|
-
const appendProofs =
|
|
76131
|
+
const vectors = join15(scratch, "vectors");
|
|
76132
|
+
const primaryProofs = join15(scratch, "primary-proof");
|
|
76133
|
+
const appendProofs = join15(scratch, "append-proof");
|
|
75917
76134
|
mkdirSync(vectors, { recursive: true, mode: 448 });
|
|
75918
76135
|
mkdirSync(primaryProofs, { recursive: true, mode: 448 });
|
|
75919
76136
|
mkdirSync(appendProofs, { recursive: true, mode: 448 });
|
|
@@ -75931,10 +76148,10 @@ async function proveLoadedExit({ request, tools, kind, primaryProver, bundle })
|
|
|
75931
76148
|
if (output2?.schema !== "carbon-shielded-x402/p03-recovered-exit-witness/v1" || output2.relation !== request.exitKind || output2.ownerRole !== kind.ownerRole) {
|
|
75932
76149
|
fail15("witness_output_invalid");
|
|
75933
76150
|
}
|
|
75934
|
-
const primaryVector =
|
|
76151
|
+
const primaryVector = join15(vectors, kind.vectorName);
|
|
75935
76152
|
const appendVector = oneItemAppendVector(
|
|
75936
|
-
|
|
75937
|
-
|
|
76153
|
+
join15(vectors, "tree-append-v1.json"),
|
|
76154
|
+
join15(vectors, "tree-append-sequence.json")
|
|
75938
76155
|
);
|
|
75939
76156
|
try {
|
|
75940
76157
|
await runTool2(primaryProver, [kind.command], {
|
|
@@ -75956,8 +76173,8 @@ async function proveLoadedExit({ request, tools, kind, primaryProver, bundle })
|
|
|
75956
76173
|
} catch (error) {
|
|
75957
76174
|
throw new Error("p03_recovered_exit_append_prover_phase_failed", { cause: error });
|
|
75958
76175
|
}
|
|
75959
|
-
const primary = JSON.parse(readFileSync(
|
|
75960
|
-
const append = JSON.parse(readFileSync(
|
|
76176
|
+
const primary = JSON.parse(readFileSync(join15(primaryProofs, kind.proofName), "utf8"));
|
|
76177
|
+
const append = JSON.parse(readFileSync(join15(appendProofs, "tree-append-v1-deposit.json"), "utf8"));
|
|
75961
76178
|
if (JSON.stringify(primary.publicInputBytesHex) !== JSON.stringify(output2.primaryWitness.publicInputBytesHex) || JSON.stringify(append.publicInputBytesHex) !== JSON.stringify(output2.treeAppendWitness.publicInputBytesHex)) {
|
|
75962
76179
|
fail15("proof_public_inputs_mismatch");
|
|
75963
76180
|
}
|
|
@@ -76018,13 +76235,13 @@ var init_p03_recovered_exit = __esm({
|
|
|
76018
76235
|
|
|
76019
76236
|
// spikes/shielded-x402-wallet/bin/shielded-wallet.mjs
|
|
76020
76237
|
import { createHash as createHash19 } from "node:crypto";
|
|
76021
|
-
import { join as
|
|
76238
|
+
import { join as join16, resolve as resolve15 } from "node:path";
|
|
76022
76239
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
76023
76240
|
function walletHome() {
|
|
76024
76241
|
return setupHome(process.env);
|
|
76025
76242
|
}
|
|
76026
76243
|
function walletPath(pool2) {
|
|
76027
|
-
return
|
|
76244
|
+
return join16(walletHome(), pool2, "wallet.json");
|
|
76028
76245
|
}
|
|
76029
76246
|
function initialWalletState({ pool: pool2, network, asset, decimals, binding, config, keys: keys3, memoStart }) {
|
|
76030
76247
|
const seedHex = keys3?.seedHex ?? Buffer.from(generateSeed()).toString("hex");
|
|
@@ -76082,16 +76299,16 @@ function readCallerJson(path, code2) {
|
|
|
76082
76299
|
}
|
|
76083
76300
|
function loadProfileDirectory(profileDir) {
|
|
76084
76301
|
const directory = resolve15(profileDir);
|
|
76085
|
-
const profile = readCallerJson(
|
|
76086
|
-
const vector = readCallerJson(
|
|
76302
|
+
const profile = readCallerJson(join16(directory, "profile.json"), "profile_json_invalid");
|
|
76303
|
+
const vector = readCallerJson(join16(directory, "rust-vectors.json"), "profile_vectors_json_invalid");
|
|
76087
76304
|
const production = profile.schema === "carbon-shielded-exact/svm-mainnet-bounded-alpha-profile/v4";
|
|
76088
|
-
const artifactDir =
|
|
76305
|
+
const artifactDir = join16(directory, production ? "proofs" : "artifacts");
|
|
76089
76306
|
return { directory, profile, vector, production, artifactDir };
|
|
76090
76307
|
}
|
|
76091
76308
|
function pinnedGenerator3(profileVector) {
|
|
76092
76309
|
if (profileVector?.payerKeys?.generator) return profileVector.payerKeys.generator;
|
|
76093
76310
|
const committed2 = JSON.parse(readFileSync(
|
|
76094
|
-
|
|
76311
|
+
join16(MODEL_DIR2, "vectors", "rust-vectors.json"),
|
|
76095
76312
|
"utf8"
|
|
76096
76313
|
));
|
|
76097
76314
|
return committed2.payerKeys.generator;
|
|
@@ -76251,7 +76468,7 @@ function proveFromProfile({ binding, profileDir }) {
|
|
|
76251
76468
|
const proved = provePayment({
|
|
76252
76469
|
binding,
|
|
76253
76470
|
modelDir: MODEL_DIR2,
|
|
76254
|
-
vectorPath:
|
|
76471
|
+
vectorPath: join16(resolve15(profileDir), "rust-vectors.json"),
|
|
76255
76472
|
artifactDir,
|
|
76256
76473
|
production: production ? {
|
|
76257
76474
|
parameterPathByRelation: profile.parameterBundle?.parameterPathByRelation,
|
|
@@ -77549,7 +77766,7 @@ async function main(argv2 = process.argv.slice(2)) {
|
|
|
77549
77766
|
case "backup-verify": {
|
|
77550
77767
|
const pool2 = flag(args, "--pool") ?? requiredPoolFromHome();
|
|
77551
77768
|
const backupDir = flag(args, "--backup-dir");
|
|
77552
|
-
const path = backupDir ?
|
|
77769
|
+
const path = backupDir ? join16(backupDir, "wallet.json") : walletPath(pool2);
|
|
77553
77770
|
const store = openWalletStore(path, passphrase());
|
|
77554
77771
|
if (store.state.pool !== pool2) throw new Error("backup-verify pool does not match wallet");
|
|
77555
77772
|
const bundle = backupDir ? verifyWalletRecoveryBundle(backupDir, passphrase()) : void 0;
|
|
@@ -77715,7 +77932,7 @@ async function runValueMove(command, args) {
|
|
|
77715
77932
|
const vault = vaultAddress(programId, pool2, mint);
|
|
77716
77933
|
const poolState2 = await readPoolState(connection, pool2);
|
|
77717
77934
|
if (!poolState2) throw new Error("pool account not found");
|
|
77718
|
-
const readProof = (name) => JSON.parse(readFileSync(
|
|
77935
|
+
const readProof = (name) => JSON.parse(readFileSync(join16(artifactDir, name), "utf8"));
|
|
77719
77936
|
if (command === "deposit") {
|
|
77720
77937
|
const proofName = production ? "deposit-v1.json" : "UNSAFE_TEST_ONLY-deposit-v1-proof.json";
|
|
77721
77938
|
const appendName2 = production ? "tree-append-v1-deposit.json" : "UNSAFE_TEST_ONLY-tree-append-v1-deposit-proof.json";
|
|
@@ -78103,153 +78320,6 @@ var init_secretFile = __esm({
|
|
|
78103
78320
|
}
|
|
78104
78321
|
});
|
|
78105
78322
|
|
|
78106
|
-
// wallet/src/setup/userPath.mjs
|
|
78107
|
-
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
78108
|
-
import { basename as basename3, join as join16 } from "node:path";
|
|
78109
|
-
function commandFolder({ env = process.env, platform = process.platform } = {}) {
|
|
78110
|
-
const prefix = env.npm_config_global_prefix || env.npm_config_prefix;
|
|
78111
|
-
if (platform === "win32") return prefix || (env.APPDATA ? join16(env.APPDATA, "npm") : void 0);
|
|
78112
|
-
return prefix ? `${String(prefix).replace(/\/+$/, "")}/bin` : void 0;
|
|
78113
|
-
}
|
|
78114
|
-
function commandFileIn(folder, platform = process.platform) {
|
|
78115
|
-
if (!folder) return void 0;
|
|
78116
|
-
const file = join16(folder, platform === "win32" ? `${COMMAND_PACKAGE}.cmd` : COMMAND_PACKAGE);
|
|
78117
|
-
try {
|
|
78118
|
-
if (!statSync(file).isFile()) return void 0;
|
|
78119
|
-
if (platform !== "win32") accessSync(file, constants.X_OK);
|
|
78120
|
-
return file;
|
|
78121
|
-
} catch {
|
|
78122
|
-
return void 0;
|
|
78123
|
-
}
|
|
78124
|
-
}
|
|
78125
|
-
function shellPathEntries({ env = process.env, platform = process.platform } = {}) {
|
|
78126
|
-
const pathValue = env.PATH ?? env.Path ?? env.path ?? "";
|
|
78127
|
-
const entries = String(pathValue).split(platform === "win32" ? ";" : ":");
|
|
78128
|
-
let last = -1;
|
|
78129
|
-
entries.forEach((each, index) => {
|
|
78130
|
-
if (/[\\/]node-gyp-bin[\\/]*$/i.test(each.trim())) last = index;
|
|
78131
|
-
});
|
|
78132
|
-
return entries.slice(last + 1);
|
|
78133
|
-
}
|
|
78134
|
-
function folderOnPath(folder, { env = process.env, platform = process.platform } = {}) {
|
|
78135
|
-
const key = folderKey(folder, platform);
|
|
78136
|
-
return shellPathEntries({ env, platform }).some((each) => each.trim() && folderKey(each, platform) === key);
|
|
78137
|
-
}
|
|
78138
|
-
function addFolderToUserPath(folder, { run: run2 = spawnSync2, env = process.env } = {}) {
|
|
78139
|
-
let result;
|
|
78140
|
-
try {
|
|
78141
|
-
result = run2(
|
|
78142
|
-
"powershell.exe",
|
|
78143
|
-
[
|
|
78144
|
-
"-NoProfile",
|
|
78145
|
-
"-NonInteractive",
|
|
78146
|
-
"-ExecutionPolicy",
|
|
78147
|
-
"Bypass",
|
|
78148
|
-
"-EncodedCommand",
|
|
78149
|
-
Buffer.from(ADD_SCRIPT, "utf16le").toString("base64")
|
|
78150
|
-
],
|
|
78151
|
-
{ windowsHide: true, encoding: "utf8", timeout: 6e4, env: { ...env, SHINJUKU_PATH_FOLDER: folder } }
|
|
78152
|
-
);
|
|
78153
|
-
} catch {
|
|
78154
|
-
return { state: "failed", reason: "Windows PowerShell did not start" };
|
|
78155
|
-
}
|
|
78156
|
-
const line = String(result?.stdout ?? "").trim().split(/\r?\n/).reverse().find((each) => each.startsWith("{"));
|
|
78157
|
-
try {
|
|
78158
|
-
const answer = JSON.parse(line ?? "");
|
|
78159
|
-
if (["present", "added", "failed"].includes(answer?.state)) return answer;
|
|
78160
|
-
} catch {
|
|
78161
|
-
}
|
|
78162
|
-
return { state: "failed", reason: "Windows PowerShell gave no answer" };
|
|
78163
|
-
}
|
|
78164
|
-
function shellProfileLine(folder, { env = process.env, platform = process.platform } = {}) {
|
|
78165
|
-
const shell = basename3(String(env.SHELL ?? ""));
|
|
78166
|
-
if (shell === "fish") return { file: "~/.config/fish/config.fish", line: `fish_add_path '${String(folder).replace(/[\\']/g, "\\$&")}'` };
|
|
78167
|
-
const file = shell === "zsh" ? "~/.zshrc" : shell === "bash" ? platform === "darwin" ? "~/.bash_profile" : "~/.bashrc" : "~/.profile";
|
|
78168
|
-
return { file, line: `export PATH='${String(folder).replace(/'/g, "'\\''")}':"$PATH"` };
|
|
78169
|
-
}
|
|
78170
|
-
function commandPathStep({ env = process.env, platform = process.platform, run: run2 = spawnSync2 } = {}) {
|
|
78171
|
-
const folder = commandFolder({ env, platform });
|
|
78172
|
-
if (!commandFileIn(folder, platform)) return { state: "no-command", folder };
|
|
78173
|
-
if (platform !== "win32") {
|
|
78174
|
-
return folderOnPath(folder, { env, platform }) ? { state: "on-path", folder } : { state: "profile", folder, ...shellProfileLine(folder, { env, platform }) };
|
|
78175
|
-
}
|
|
78176
|
-
return { folder, ...addFolderToUserPath(folder, { run: run2, env }), thisWindow: folderOnPath(folder, { env, platform }) };
|
|
78177
|
-
}
|
|
78178
|
-
function pathStepSays(step) {
|
|
78179
|
-
return ["added", "failed", "profile"].includes(step?.state) || step?.state === "present" && step.thisWindow === false;
|
|
78180
|
-
}
|
|
78181
|
-
function commandPathLines(step, hereLine) {
|
|
78182
|
-
const here3 = ["In this window, type the longer command, for example:", ` ${hereLine}`];
|
|
78183
|
-
if (step?.state === "added") {
|
|
78184
|
-
return [step.broadcast === false ? "Added Shinjuku to your PATH. Sign out of Windows and in again, then type shinjuku in a new window." : "Added Shinjuku to your PATH. Open a new window to type shinjuku.", ...here3];
|
|
78185
|
-
}
|
|
78186
|
-
if (step?.state === "present") return ["Shinjuku is on your PATH. Open a new window to type shinjuku.", ...here3];
|
|
78187
|
-
if (step?.state === "failed") {
|
|
78188
|
-
return [
|
|
78189
|
-
`Setup could not add Shinjuku to your PATH (${step.reason}). To add it yourself: open Start, type environment variables, open "Edit environment variables for your account", pick Path, choose Edit, then New, and paste this folder:`,
|
|
78190
|
-
` ${step.folder}`,
|
|
78191
|
-
"Then open a new window to type shinjuku.",
|
|
78192
|
-
...here3
|
|
78193
|
-
];
|
|
78194
|
-
}
|
|
78195
|
-
if (step?.state === "profile") {
|
|
78196
|
-
return [
|
|
78197
|
-
`Your terminal does not look in the folder where npm put the shinjuku command. Add this line to the end of ${step.file}, then open a new terminal to type shinjuku:`,
|
|
78198
|
-
` ${step.line}`,
|
|
78199
|
-
...here3
|
|
78200
|
-
];
|
|
78201
|
-
}
|
|
78202
|
-
return [];
|
|
78203
|
-
}
|
|
78204
|
-
var folderKey, ADD_SCRIPT;
|
|
78205
|
-
var init_userPath = __esm({
|
|
78206
|
-
"wallet/src/setup/userPath.mjs"() {
|
|
78207
|
-
"use strict";
|
|
78208
|
-
init_fs();
|
|
78209
|
-
init_config();
|
|
78210
|
-
folderKey = (folder, platform) => {
|
|
78211
|
-
const key = String(folder).trim().replace(/^"(.*)"$/, "$1").replace(/[\\/]+$/, "");
|
|
78212
|
-
return platform === "win32" || platform === "darwin" ? key.toLowerCase() : key;
|
|
78213
|
-
};
|
|
78214
|
-
ADD_SCRIPT = String.raw`
|
|
78215
|
-
$ErrorActionPreference = 'Stop'
|
|
78216
|
-
$ProgressPreference = 'SilentlyContinue'
|
|
78217
|
-
$folder = $env:SHINJUKU_PATH_FOLDER
|
|
78218
|
-
function Key([string]$p) { ([Environment]::ExpandEnvironmentVariables($p.Trim().Trim('"'))).TrimEnd('\', '/').ToLowerInvariant() }
|
|
78219
|
-
try {
|
|
78220
|
-
$raw = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
|
|
78221
|
-
$want = Key $folder
|
|
78222
|
-
$machineKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SYSTEM\CurrentControlSet\Control\Session Manager\Environment')
|
|
78223
|
-
$machine = if ($machineKey) { [string]$machineKey.GetValue('Path', '', $raw) } else { '' }
|
|
78224
|
-
$key = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment')
|
|
78225
|
-
$user = $key.GetValue('Path', $null, $raw)
|
|
78226
|
-
$kind = if ($null -ne $user) { $key.GetValueKind('Path') } else { [Microsoft.Win32.RegistryValueKind]::ExpandString }
|
|
78227
|
-
$entries = @(([string]$user).Split(';')) + @($machine.Split(';'))
|
|
78228
|
-
if (@($entries | Where-Object { $_.Trim() -and (Key $_) -eq $want }).Count -gt 0) {
|
|
78229
|
-
'{"state":"present"}'; exit 0
|
|
78230
|
-
}
|
|
78231
|
-
if ($kind -ne [Microsoft.Win32.RegistryValueKind]::ExpandString -and $kind -ne [Microsoft.Win32.RegistryValueKind]::String) {
|
|
78232
|
-
'{"state":"failed","reason":"your PATH setting has a type setup does not change"}'; exit 0
|
|
78233
|
-
}
|
|
78234
|
-
$old = [string]$user
|
|
78235
|
-
$new = if ($old -eq '') { $folder } elseif ($old.EndsWith(';')) { $old + $folder } else { $old + ';' + $folder }
|
|
78236
|
-
if ($new.Length -ge 32767) { '{"state":"failed","reason":"your PATH setting is full"}'; exit 0 }
|
|
78237
|
-
$key.SetValue('Path', $new, $kind)
|
|
78238
|
-
if ([string]$key.GetValue('Path', '', $raw) -ne $new) { '{"state":"failed","reason":"the new PATH did not read back"}'; exit 0 }
|
|
78239
|
-
$broadcast = $false
|
|
78240
|
-
try {
|
|
78241
|
-
Add-Type -Namespace ShinjukuPath -Name Native -MemberDefinition '[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);'
|
|
78242
|
-
$result = [UIntPtr]::Zero
|
|
78243
|
-
$broadcast = [ShinjukuPath.Native]::SendMessageTimeout([IntPtr]0xffff, 0x1A, [UIntPtr]::Zero, 'Environment', 2, 5000, [ref]$result) -ne [IntPtr]::Zero
|
|
78244
|
-
} catch { $broadcast = $false }
|
|
78245
|
-
'{"state":"added","kind":"' + $kind + '","broadcast":' + $(if ($broadcast) { 'true' } else { 'false' }) + '}'
|
|
78246
|
-
} catch {
|
|
78247
|
-
'{"state":"failed","reason":"Windows did not let setup change your PATH setting"}'
|
|
78248
|
-
}
|
|
78249
|
-
`;
|
|
78250
|
-
}
|
|
78251
|
-
});
|
|
78252
|
-
|
|
78253
78323
|
// wallet/src/cli/commandName.mjs
|
|
78254
78324
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
78255
78325
|
import { basename as basename4, dirname as dirname15, join as join17 } from "node:path";
|
|
@@ -142299,7 +142369,7 @@ var init_tools = __esm({
|
|
|
142299
142369
|
"--max-shield / --max-unshield": "shield and unshield limits"
|
|
142300
142370
|
};
|
|
142301
142371
|
capName = (flag3) => CAP_NAMES[flag3] ?? "spending limit";
|
|
142302
|
-
entryPlaces = (change) => `Where the entry is: Claude Desktop: claude_desktop_config.json; Cursor: ~/.cursor/mcp.json; Claude Code: claude mcp get ${MCP_SERVER_NAME} shows the entry (an entry added by hand can have another name: claude mcp list shows it), then claude mcp remove ${MCP_SERVER_NAME} and claude mcp add it again ${change}; Hermes: config.yaml.`;
|
|
142372
|
+
entryPlaces = (change) => `Where the entry is: Claude Desktop: claude_desktop_config.json (Settings > Developer > Edit Config opens it); Cursor: ~/.cursor/mcp.json; Claude Code: claude mcp get ${MCP_SERVER_NAME} shows the entry (an entry added by hand can have another name: claude mcp list shows it), then claude mcp remove ${MCP_SERVER_NAME} and claude mcp add it again ${change}; Hermes: config.yaml.`;
|
|
142303
142373
|
capRaiseText = (flag3) => {
|
|
142304
142374
|
if (capFlagFromLaunchLine(flag3)) {
|
|
142305
142375
|
const both = flag3 === "--max-payment" ? " (raise the 24-hour payment limit there too when it is below the new amount: the wallet does not start with it lower)" : "";
|
|
@@ -156835,7 +156905,13 @@ function claudeCodeState(env, home) {
|
|
|
156835
156905
|
}
|
|
156836
156906
|
function agentHostsOf(env, home) {
|
|
156837
156907
|
const jsonHost = (target) => {
|
|
156838
|
-
|
|
156908
|
+
let file;
|
|
156909
|
+
try {
|
|
156910
|
+
file = hostConfigFile(target, { env, home: homedir3() });
|
|
156911
|
+
} catch {
|
|
156912
|
+
return null;
|
|
156913
|
+
}
|
|
156914
|
+
const config = readJsonFile(file);
|
|
156839
156915
|
return config === void 0 ? false : config === null ? null : runsThisWallet(config[hostServersKey(target)], home);
|
|
156840
156916
|
};
|
|
156841
156917
|
const continueHost = () => {
|
|
@@ -159631,7 +159707,7 @@ function agentAppLines({ skip = /* @__PURE__ */ new Set() }) {
|
|
|
159631
159707
|
function hostLines(targets) {
|
|
159632
159708
|
const commands = targets.map((target) => `${setupCli2()} setup --add-to ${target}`);
|
|
159633
159709
|
const width = Math.max(...commands.map((command) => command.length));
|
|
159634
|
-
const label = { codex: "Codex (the
|
|
159710
|
+
const label = { codex: "Codex (the ChatGPT desktop app's Codex side, or Codex CLI)", devin: "Devin Desktop (the app that was Windsurf)", vscode: "VS Code (GitHub Copilot)" };
|
|
159635
159711
|
return targets.map((target, index) => ` ${commands[index].padEnd(width)} ${label[target] ?? HOST_NAMES[target]}`);
|
|
159636
159712
|
}
|
|
159637
159713
|
function setupNextText({ home, deps, npmVersion, config, fundAsked, rerun, targets = [], added = /* @__PURE__ */ new Set() }) {
|
|
@@ -160056,7 +160132,33 @@ function claudeCodeEntryOf(deps) {
|
|
|
160056
160132
|
return void 0;
|
|
160057
160133
|
}
|
|
160058
160134
|
}
|
|
160135
|
+
function runClaude(args, program = "claude", stdio = "inherit") {
|
|
160136
|
+
const options = { stdio, windowsHide: true, timeout: 12e4 };
|
|
160137
|
+
const programWord = program === "claude" ? program : `"${program}"`;
|
|
160138
|
+
const result = process.platform === "win32" && !/\.exe$/i.test(program) ? spawnSync10([programWord, ...args.map((word) => hostShellWord(word, "win32"))].join(" "), { ...options, shell: true }) : spawnSync10(program, args, options);
|
|
160139
|
+
return result.status ?? 1;
|
|
160140
|
+
}
|
|
160141
|
+
function claudeRemoveLines(program, platform) {
|
|
160142
|
+
const tail = `mcp remove --scope user ${MCP_SERVER_NAME}`;
|
|
160143
|
+
const shells = platform === "win32" ? ["powershell", "cmd", "bash"] : ["bash"];
|
|
160144
|
+
const words2 = shells.map((shell) => claudeProgramWord(program, platform, shell));
|
|
160145
|
+
if (new Set(words2).size === 1) return ` ${words2[0]} ${tail}`;
|
|
160146
|
+
const names = { powershell: "PowerShell", cmd: "cmd", bash: "Git Bash" };
|
|
160147
|
+
return shells.map((shell, index) => words2[index] === void 0 ? void 0 : ` In ${names[shell]}:
|
|
160148
|
+
${words2[index]} ${tail}`).filter((line) => line !== void 0).join("\n");
|
|
160149
|
+
}
|
|
160059
160150
|
var RESTART_APP = (app) => `If ${app} is open now, quit it and start it again.`;
|
|
160151
|
+
function hostAddedNext(target, app, platform) {
|
|
160152
|
+
const ask = 'then ask in plain words, for example "what is my Shinjuku balance".';
|
|
160153
|
+
if (target === "claude-desktop") {
|
|
160154
|
+
const quit = platform === "win32" ? "If Claude Desktop is open now, quit it: right-click its icon by the clock and choose Quit (closing its window does not quit it). Then open it again" : platform === "darwin" ? "If Claude Desktop is open now, quit it (Claude > Quit Claude, or Command+Q) and open it again" : `${RESTART_APP(app).slice(0, -1)}`;
|
|
160155
|
+
return `${quit}. In a new chat, click + and choose Connectors to see Shinjuku there, ${ask}`;
|
|
160156
|
+
}
|
|
160157
|
+
if (target === "codex") {
|
|
160158
|
+
return `If the ChatGPT desktop app or Codex CLI is open now, quit it and start it again. In the app, use its Codex side (ChatGPT's own chat cannot start a server on this computer). In Codex, type /mcp to see the wallet's tools, ${ask}`;
|
|
160159
|
+
}
|
|
160160
|
+
return RESTART_APP(app);
|
|
160161
|
+
}
|
|
160060
160162
|
function allowWalletChecks(deps) {
|
|
160061
160163
|
const file = claudeCodeSettingsFile({ env: deps.env, home: deps.homedir() });
|
|
160062
160164
|
try {
|
|
@@ -160150,7 +160252,23 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
|
|
|
160150
160252
|
`);
|
|
160151
160253
|
continue;
|
|
160152
160254
|
}
|
|
160153
|
-
const
|
|
160255
|
+
const claudeProgram = claudeCodeProgram({ env: deps.env ?? process.env, platform: options.platform, userHome: deps.homedir() });
|
|
160256
|
+
const claudeOptions = { ...options, userHome: deps.homedir() };
|
|
160257
|
+
if (claudeProgram === void 0) {
|
|
160258
|
+
io.out(`Not added to Claude Code: its command, claude, is not on this computer's PATH and not in the folders where Claude Code's installers put it (${options.platform === "win32" ? "%USERPROFILE%\\.local\\bin, or npm's folder" : "~/.local/bin"}). If Claude Code is not installed, install it (https://code.claude.com/docs/en/setup), then do this step again. If it is in another folder, run this line in a window where claude works:
|
|
160259
|
+
${claudeCodeCommand({ ...claudeOptions, claudeProgram: "claude" })}
|
|
160260
|
+
`);
|
|
160261
|
+
continue;
|
|
160262
|
+
}
|
|
160263
|
+
const runWhy = claudeProgramRunWhy(claudeProgram, options.platform);
|
|
160264
|
+
if (runWhy) {
|
|
160265
|
+
io.out(`Not added to Claude Code: ${runWhy}. Run this yourself:
|
|
160266
|
+
${claudeCodeLines({ ...claudeOptions, claudeProgram }).map((line) => ` ${line}`).join("\n")}
|
|
160267
|
+
`);
|
|
160268
|
+
continue;
|
|
160269
|
+
}
|
|
160270
|
+
const quiet = (args) => (deps.runClaudeCliQuiet ?? deps.runClaudeCli)(args, claudeProgram);
|
|
160271
|
+
const runClaudeCli = (args) => deps.runClaudeCli(args, claudeProgram);
|
|
160154
160272
|
for (const old of OLD_MCP_SERVER_NAMES) {
|
|
160155
160273
|
if (quiet(["mcp", "remove", "--scope", "user", old]) === 0) io.out(`Replaced the old ${old} entry in Claude Code.
|
|
160156
160274
|
`);
|
|
@@ -160173,9 +160291,9 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
|
|
|
160173
160291
|
continue;
|
|
160174
160292
|
}
|
|
160175
160293
|
const replacedOther = replace === true && quiet(["mcp", "remove", "--scope", "user", MCP_SERVER_NAME]) === 0;
|
|
160176
|
-
let status =
|
|
160294
|
+
let status = runClaudeCli(claudeCodeArgs(options));
|
|
160177
160295
|
const removed = olderOwn || replacedOther || status !== 0 && force && quiet(["mcp", "remove", "--scope", "user", MCP_SERVER_NAME]) === 0;
|
|
160178
|
-
if (removed && status !== 0) status =
|
|
160296
|
+
if (removed && status !== 0) status = runClaudeCli(claudeCodeArgs(options));
|
|
160179
160297
|
if (status === 0) done.add(target);
|
|
160180
160298
|
const check = status === 0 ? await hostStartCheck("Claude Code", options, deps, { terminal: true, noTor }) : void 0;
|
|
160181
160299
|
if (check && !check.ok) io.out(`${hostCheckWords("Claude Code", check)}
|
|
@@ -160183,15 +160301,23 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
|
|
|
160183
160301
|
const homeNow = replacedOther ? ` Claude Code now uses the wallet in ${home}; the wallet in ${otherHome} is unchanged.` : "";
|
|
160184
160302
|
io.out(status === 0 ? `${removed ? "Replaced the wallet in" : "Added the wallet to"} Claude Code, for all your folders.${homeNow} ${allowWalletChecks(deps).say} ${RESTART_APP("Claude Code")}
|
|
160185
160303
|
` : `Claude Code did not take the server; its message is above. Run this yourself:
|
|
160186
|
-
${
|
|
160304
|
+
${claudeCodeLines({ ...claudeOptions, claudeProgram }).map((line) => ` ${line}`).join("\n")}
|
|
160187
160305
|
` + (removed ? `Setup removed the old ${MCP_SERVER_NAME} entry first, so Claude Code has none until that line runs.
|
|
160188
160306
|
` : `If it says the server already exists, remove that entry with this command, then run the line above:
|
|
160189
|
-
|
|
160307
|
+
${claudeRemoveLines(claudeProgram, options.platform)}
|
|
160190
160308
|
`));
|
|
160191
160309
|
continue;
|
|
160192
160310
|
}
|
|
160193
|
-
const file = hostConfigFile(target, { ...options, home: deps.homedir() });
|
|
160194
160311
|
const app = HOST_NAMES[target];
|
|
160312
|
+
let file;
|
|
160313
|
+
try {
|
|
160314
|
+
file = hostConfigFile(target, { ...options, home: deps.homedir() });
|
|
160315
|
+
} catch (error) {
|
|
160316
|
+
if (!String(error?.message).startsWith("setup_host_config_ambiguous:")) throw error;
|
|
160317
|
+
io.out(`Not added to ${app}: this computer has more than one ${app} settings file (${error.files.join("; ")}), so the wallet did not pick one. In ${app}, Settings > Developer > Edit Config opens the file it reads: add the entry below to it by hand.
|
|
160318
|
+
`);
|
|
160319
|
+
continue;
|
|
160320
|
+
}
|
|
160195
160321
|
const first = torOn ? await hostStartCheck(app, options, deps, { terminal: false, noTor }) : void 0;
|
|
160196
160322
|
if (first && !first.ok) {
|
|
160197
160323
|
io.out(`Not added to ${app}: ${hostCheckWords(app, first)}
|
|
@@ -160205,8 +160331,8 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
|
|
|
160205
160331
|
`);
|
|
160206
160332
|
const check = await hostStartCheck(app, options, deps, { terminal: false, noTor });
|
|
160207
160333
|
if (check.path) added = { ...write(mcpServerEntry({ ...options, path: check.path }), false), changed: true };
|
|
160208
|
-
io.out(!added.changed ? `${app} already has the wallet: ${file} (nothing changed).${check.ok ? ` ${app} starts it (checked).` : ""}
|
|
160209
|
-
` : `Added the wallet to ${app}: ${file}${added.backup ? ` (the old file was copied to ${added.backup}, readable by you alone)` : ""}.${check.ok ? ` ${app} starts it (checked).` : ""} ${
|
|
160334
|
+
io.out(!added.changed ? `${app} already has the wallet: ${file} (nothing changed).${check.ok ? ` ${app} starts it (checked).` : ""} If ${app} does not show the wallet yet: ${hostAddedNext(target, app, options.platform)}
|
|
160335
|
+
` : `Added the wallet to ${app}: ${file}${added.backup ? ` (the old file was copied to ${added.backup}, readable by you alone)` : ""}.${check.ok ? ` ${app} starts it (checked).` : ""} ${hostAddedNext(target, app, options.platform)}
|
|
160210
160336
|
`);
|
|
160211
160337
|
if (!check.ok) io.out(`${hostCheckWords(app, check)}
|
|
160212
160338
|
`);
|
|
@@ -161593,7 +161719,7 @@ var COMMANDS = [
|
|
|
161593
161719
|
"Your own --passphrase-file must be private: on Linux and macOS setup refuses a file that group or other may read or write, or that another user owns (setup_passphrase_file_insecure: chmod 600 <file>). On Windows setup cannot read the access list; it accepts the file with a warning.",
|
|
161594
161720
|
`--add-to writes each app's own user file: vscode (VS Code with Copilot) mcp.json in VS Code's User folder, under "servers"; devin (Devin Desktop, the app that was Windsurf) mcp_config.json in AppData\\Roaming\\devin on Windows, else ~/.config/devin; cline ~/.cline/data/settings/cline_mcp_settings.json (or CLINE_MCP_SETTINGS_PATH, CLINE_DATA_DIR, CLINE_DIR); continue its own block file ~/.continue/mcpServers/shinjuku.yaml (or in CONTINUE_GLOBAL_DIR); gemini (Gemini CLI) ~/.gemini/settings.json (or in GEMINI_CLI_HOME); antigravity (Antigravity) ~/.gemini/config/mcp_config.json. Every other key and server in a file stays as it is.`,
|
|
161595
161721
|
`--add-to for a JSON file (Claude Desktop, Cursor and the apps above): a host config whose server list is not a JSON object, or that has a different ${MCP_SERVER_NAME} 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. An entry an older setup wrote (no version, another version, or an old package name, shinjuku or shinjuku-shielded; the same home) is replaced without --force, in a JSON host and in Claude Code. An entry under an old key (${OLD_MCP_SERVER_NAMES.join(" or ")}) is replaced by itself, in every host, so the host never starts two wallet servers. For Claude Code, a different ${MCP_SERVER_NAME} server (not an older entry of this wallet) needs --force.`,
|
|
161596
|
-
`--add-to codex: the
|
|
161722
|
+
`--add-to codex: the ChatGPT desktop app (its Codex side) and Codex CLI read one file, config.toml in CODEX_HOME (else ~/.codex). Setup writes the [mcp_servers.${MCP_SERVER_NAME}] tables at its end with startup_timeout_sec = 120 (a first start downloads the wallet) and tool_timeout_sec = 300, and keeps every other line; the same rules as a JSON host (a different entry stays without --force; the old file is backed up first). Then type /mcp in Codex to see the tools.`,
|
|
161597
161723
|
"The proof programs run natively: Windows x64, Linux x64 and Linux arm64 each download their own set (no WSL). Setup downloads the programs first and starts each one once before it makes a key; when Windows app control or an antivirus blocks one, setup stops and says which. macOS and other systems: not supported yet; setup says so and creates nothing.",
|
|
161598
161724
|
"Run it again at any time: it never changes an existing wallet, keeps the recorded caps unless you pass new ones, checks every setup file again, downloads what is missing or newer, and rewrites config.json.",
|
|
161599
161725
|
`A wallet that ${SETUP_CLI_WORD} restore made and did not read back yet (the restore stopped): setup reads its money back from the chain in place of the add-money question, so setup finishes that restore.`,
|
|
@@ -165386,16 +165512,8 @@ function defaultDependencies() {
|
|
|
165386
165512
|
});
|
|
165387
165513
|
}),
|
|
165388
165514
|
/** claude with no output on the terminal (setup's probe of an old entry, and its remove); the exit status. */
|
|
165389
|
-
runClaudeCliQuiet: (args) =>
|
|
165390
|
-
|
|
165391
|
-
const result = windows ? spawnSync10(["claude", ...args].map((word) => hostShellWord(word, "win32")).join(" "), { stdio: "ignore", shell: true, windowsHide: true, timeout: 12e4 }) : spawnSync10("claude", args, { stdio: "ignore", windowsHide: true, timeout: 12e4 });
|
|
165392
|
-
return result.status ?? 1;
|
|
165393
|
-
},
|
|
165394
|
-
runClaudeCli: (args) => {
|
|
165395
|
-
const windows = process.platform === "win32";
|
|
165396
|
-
const result = windows ? spawnSync10(["claude", ...args].map((word) => hostShellWord(word, "win32")).join(" "), { stdio: "inherit", shell: true, windowsHide: true, timeout: 12e4 }) : spawnSync10("claude", args, { stdio: "inherit", windowsHide: true, timeout: 12e4 });
|
|
165397
|
-
return result.status ?? 1;
|
|
165398
|
-
},
|
|
165515
|
+
runClaudeCliQuiet: (args, program) => runClaude(args, program, "ignore"),
|
|
165516
|
+
runClaudeCli: (args, program) => runClaude(args, program, "inherit"),
|
|
165399
165517
|
/**
|
|
165400
165518
|
* The --tor entry of this CLI: re-execute `args` behind Tor (proxy.mjs proves Tor first). `startedFile`
|
|
165401
165519
|
* (torRunOf) reaches the Tor run in its environment, which proxy.mjs copies from this process at the spawn.
|