@vault77/summon 2.1.2 → 2.1.7

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.
Files changed (3) hide show
  1. package/README.md +5 -5
  2. package/package.json +9 -9
  3. package/summon-cli.js +92 -15
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  ![Node](https://img.shields.io/badge/node-%3E%3D18.x-brightgreen)
5
5
  ![Platform](https://img.shields.io/badge/platform-macOS-blue)
6
6
 
7
- **Version:** 2.0.2
7
+ **Version:** 2.1.7
8
8
 
9
9
  > _Relic software unearthed from VAULT77.
10
10
  > For trench operators only. macOS‑native. Handle with care._
@@ -111,10 +111,10 @@ summon man
111
111
  - `summon keychain store` — store private key in macOS Keychain
112
112
  - `summon keychain unlock` — verify key retrieval from Keychain
113
113
  - `summon keychain delete` — delete stored private key
114
- - `summon buy <TOKEN_MINT> <amount>` — buy with SOL amount (`auto` is not supported for buys)
115
- - `summon sell <TOKEN_MINT> <amount>` — sell fixed amount, percent (like `50%`), or `auto`
116
- - `summon wallet` — open your wallet page in browser
117
- - `summon doctor` — run config/Keychain/RPC/swap/notification diagnostics
114
+ - `summon buy [TOKEN_MINT] [amount]` — buy with a fixed SOL amount or percentage (like `25%`); `auto` is not supported for buys
115
+ - `summon sell [TOKEN_MINT] [amount]` — sell fixed amount, percent (like `50%`), or `auto`
116
+ - `summon wallet` (`summon w`) — open your wallet page in browser
117
+ - `summon doctor` (`summon doctor -v`) — run config/Keychain/RPC/swap/notification diagnostics with optional verbose details
118
118
  - `summon man` — display the built-in manual
119
119
 
120
120
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vault77/summon",
3
- "version": "2.1.2",
3
+ "version": "2.1.7",
4
4
  "description": "A recovered VAULT77 relic for macOS operators. summonTheWarlord is a high-performance CLI tool for ultra-fast, low-fee Solana swaps on macOS. Private keys are secured using the native macOS Keychain, never written to disk or exposed to JavaScript memory longer than required. Built for serious CLI workflows with system notifications, local-first execution, and zero browser dependency.",
5
5
  "keywords": [
6
6
  "solana",
@@ -16,17 +16,17 @@
16
16
  "author": "Humble Digital, llc <SummonTheWarlord@pm.me>",
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "git+https://github.com/monthviewsales/summonTheWarlord.git"
19
+ "url": "git+https://github.com/HumbleDigital/summonTheWarlord.git"
20
20
  },
21
- "homepage": "https://github.com/monthviewsales/summonTheWarlord#readme",
21
+ "homepage": "https://github.com/HumbleDigital/summonTheWarlord#readme",
22
22
  "bugs": {
23
- "url": "https://github.com/monthviewsales/summonTheWarlord/issues"
23
+ "url": "https://github.com/HumbleDigital/summonTheWarlord/issues"
24
24
  },
25
25
  "type": "module",
26
26
  "license": "MIT",
27
27
  "main": "summon-cli.js",
28
28
  "bin": {
29
- "summon": "./summon-cli.js"
29
+ "summon": "summon-cli.js"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"
@@ -47,15 +47,15 @@
47
47
  "lint:fix": "eslint . --fix"
48
48
  },
49
49
  "devDependencies": {
50
- "@eslint/js": "^9.39.2",
51
- "eslint": "^9.39.2",
50
+ "@eslint/js": "^9.39.4",
51
+ "eslint": "^9.39.3",
52
52
  "eslint-plugin-import": "^2.32.0",
53
- "globals": "^17.3.0",
53
+ "globals": "^17.4.0",
54
54
  "jest": "^30.2.0"
55
55
  },
56
56
  "dependencies": {
57
57
  "@solana/web3.js": "^1.98.4",
58
- "axios": "^1.13.5",
58
+ "axios": "^1.13.6",
59
59
  "bs58": "^6.0.0",
60
60
  "commander": "^14.0.3",
61
61
  "fs-extra": "^11.3.3",
package/summon-cli.js CHANGED
@@ -102,6 +102,30 @@ const WIZARD_FIELD_GUIDANCE = {
102
102
  const askQuestion = (rl, prompt) =>
103
103
  new Promise((resolve) => rl.question(prompt, (answer) => resolve(answer.trim())));
104
104
 
105
+ async function askSecretQuestion(rl, prompt) {
106
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
107
+ return askQuestion(rl, prompt);
108
+ }
109
+
110
+ const originalWrite = rl._writeToOutput?.bind(rl);
111
+ rl.output.write(prompt);
112
+ rl._writeToOutput = () => {};
113
+
114
+ try {
115
+ const answer = await new Promise((resolve) => rl.question("", resolve));
116
+ rl.output.write("\n");
117
+ return String(answer).trim();
118
+ } finally {
119
+ if (originalWrite) {
120
+ rl._writeToOutput = originalWrite;
121
+ }
122
+ }
123
+ }
124
+
125
+ function printKeychainAccessHint() {
126
+ console.log(' Check it in Keychain Access by searching for "summonTheWarlord" and opening "wallet-private-key".');
127
+ }
128
+
105
129
  const COLOR_ENABLED = process.stdout.isTTY;
106
130
  const ANSI = {
107
131
  reset: "\x1b[0m",
@@ -113,6 +137,53 @@ const ANSI = {
113
137
  };
114
138
 
115
139
  const paint = (text, color) => (COLOR_ENABLED ? `${color}${text}${ANSI.reset}` : text);
140
+ const SENSITIVE_URL_KEY_PATTERN = /key|token|secret|auth|signature|sig|password|pwd/i;
141
+
142
+ function maskSensitiveValue(value) {
143
+ const text = String(value ?? "");
144
+ if (!text) {
145
+ return text;
146
+ }
147
+ if (text.length <= 4) {
148
+ return "*".repeat(text.length);
149
+ }
150
+ return `${"*".repeat(text.length - 4)}${text.slice(-4)}`;
151
+ }
152
+
153
+ function redactSensitiveUrl(rawUrl) {
154
+ const urlText = String(rawUrl ?? "").trim();
155
+ if (!urlText) {
156
+ return urlText;
157
+ }
158
+
159
+ try {
160
+ const parsed = new URL(urlText);
161
+ if (parsed.username) {
162
+ parsed.username = maskSensitiveValue(parsed.username);
163
+ }
164
+ if (parsed.password) {
165
+ parsed.password = maskSensitiveValue(parsed.password);
166
+ }
167
+ for (const [key, value] of parsed.searchParams.entries()) {
168
+ if (SENSITIVE_URL_KEY_PATTERN.test(key)) {
169
+ parsed.searchParams.set(key, maskSensitiveValue(value));
170
+ }
171
+ }
172
+ return parsed.toString();
173
+ } catch {
174
+ return urlText.replace(
175
+ /([?&][^=]*(?:key|token|secret|auth|signature|sig|password|pwd)[^=]*=)([^&]+)/ig,
176
+ (_, prefix, value) => `${prefix}${maskSensitiveValue(value)}`
177
+ );
178
+ }
179
+ }
180
+
181
+ function formatConfigDisplayValue(key, value) {
182
+ if (key === "rpcUrl") {
183
+ return redactSensitiveUrl(value);
184
+ }
185
+ return toDisplayValue(value);
186
+ }
116
187
 
117
188
  function clearScreen() {
118
189
  if (process.stdout.isTTY) {
@@ -211,7 +282,7 @@ function renderConfigSummary(cfg, configPath, title = "CONFIG") {
211
282
  const jitoTip = cfg.jito?.enabled ? cfg.jito.tip : "-";
212
283
  const rows = [
213
284
  ["Config path", configPath],
214
- ["RPC URL", cfg.rpcUrl],
285
+ ["RPC URL", formatConfigDisplayValue("rpcUrl", cfg.rpcUrl)],
215
286
  ["Slippage", cfg.slippage],
216
287
  ["Priority fee", cfg.priorityFee],
217
288
  ["Priority level", cfg.priorityFeeLevel],
@@ -252,7 +323,7 @@ async function promptSelect(rl, label, options, { current, required = false } =
252
323
 
253
324
  async function promptNormalized(rl, label, key, { current, required = false } = {}) {
254
325
  while (true) {
255
- const suffix = current !== undefined ? ` [${toDisplayValue(current)}]` : "";
326
+ const suffix = current !== undefined ? ` [${formatConfigDisplayValue(key, current)}]` : "";
256
327
  const answer = await askQuestion(rl, `${label}${suffix}: `);
257
328
  if (!answer) {
258
329
  if (required) {
@@ -589,7 +660,10 @@ configCmd
589
660
  process.exit(1);
590
661
  }
591
662
  await saveConfig(cfg);
592
- console.log(`✅ Updated ${key} ${value} in ${configPath}`);
663
+ const displayValue = key.startsWith("jito.")
664
+ ? toDisplayValue(cfg.jito?.[key.split(".")[1]])
665
+ : formatConfigDisplayValue(key, cfg[key]);
666
+ console.log(`✅ Updated ${key} → ${displayValue} in ${configPath}`);
593
667
  renderConfigSummary(cfg, configPath);
594
668
  });
595
669
 
@@ -646,9 +720,10 @@ program
646
720
  "🔓 Private key already stored in Keychain. Would you like to replace it? (y/N): "
647
721
  );
648
722
  if (updateKey.toLowerCase() === "y") {
649
- const privKey = await askQuestion(rl, "Paste your new private key: ");
723
+ const privKey = await askSecretQuestion(rl, "Paste your new private key: ");
650
724
  await storePrivateKey(privKey);
651
725
  console.log("🔐 Private key updated.");
726
+ printKeychainAccessHint();
652
727
  } else {
653
728
  console.log("✅ Keeping existing private key.");
654
729
  }
@@ -658,9 +733,10 @@ program
658
733
  "Would you like to store your private key in the macOS Keychain now? (y/N): "
659
734
  );
660
735
  if (storeKey.toLowerCase() === "y") {
661
- const privKey = await askQuestion(rl, "Paste your private key: ");
736
+ const privKey = await askSecretQuestion(rl, "Paste your private key: ");
662
737
  await storePrivateKey(privKey);
663
738
  console.log("🔐 Private key stored securely.");
739
+ printKeychainAccessHint();
664
740
  } else {
665
741
  console.log("⚠️ No private key stored. You can add one later with `summon keychain store`.");
666
742
  }
@@ -696,21 +772,22 @@ const keychainCmd = program.command("keychain").description("Manage private key
696
772
  keychainCmd
697
773
  .command("store")
698
774
  .description("Store private key securely in macOS Keychain")
699
- .action(() => {
775
+ .action(async () => {
700
776
  const rl = readline.createInterface({
701
777
  input: process.stdin,
702
778
  output: process.stdout,
703
779
  });
704
- rl.question("Paste your wallet private key: ", async (input) => {
780
+ try {
781
+ const input = await askSecretQuestion(rl, "Paste your wallet private key: ");
705
782
  rl.close();
706
- try {
707
- await storePrivateKey(input.trim());
708
- console.log("🔐 Private key securely stored in macOS Keychain.");
709
- } catch (err) {
710
- console.error("❌ Failed to store key:", err.message);
711
- process.exitCode = 1;
712
- }
713
- });
783
+ await storePrivateKey(input);
784
+ console.log("🔐 Private key securely stored in macOS Keychain.");
785
+ printKeychainAccessHint();
786
+ } catch (err) {
787
+ rl.close();
788
+ console.error("❌ Failed to store key:", err.message);
789
+ process.exitCode = 1;
790
+ }
714
791
  });
715
792
 
716
793
  keychainCmd