@covalenthq/goldrush-cli 3.0.0 → 3.0.2
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 +2 -2
- package/dist/index.js +193 -63
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ goldrush auth
|
|
|
15
15
|
goldrush balances eth-mainnet 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
|
|
16
16
|
|
|
17
17
|
# Stream new DEX pairs
|
|
18
|
-
goldrush
|
|
18
|
+
goldrush new_pairs eth-mainnet
|
|
19
19
|
|
|
20
20
|
# Launch proxy server (for MCP bridge)
|
|
21
21
|
goldrush proxy
|
|
@@ -32,7 +32,7 @@ goldrush install
|
|
|
32
32
|
| `goldrush auth` | Set up API key (OS keychain) |
|
|
33
33
|
| `goldrush balances <chain> <address>` | Token balances with rich table |
|
|
34
34
|
| `goldrush transfers <chain> <address>` | Transfer history |
|
|
35
|
-
| `goldrush
|
|
35
|
+
| `goldrush new_pairs <chain>` | Stream new DEX pairs |
|
|
36
36
|
| `goldrush ohlcv <chain>` | OHLCV pairs stream |
|
|
37
37
|
| `goldrush search <query>` | Token search |
|
|
38
38
|
| `goldrush traders <chain>` | Top traders |
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@covalenthq/goldrush-cli",
|
|
6
|
-
version: "3.0.
|
|
6
|
+
version: "3.0.2",
|
|
7
7
|
description: "Terminal-first blockchain data & algorithmic trading CLI powered by GoldRush API",
|
|
8
8
|
type: "module",
|
|
9
9
|
bin: {
|
|
@@ -45,8 +45,8 @@ var package_default = {
|
|
|
45
45
|
homepage: "https://goldrush.dev/docs/",
|
|
46
46
|
repository: {
|
|
47
47
|
type: "git",
|
|
48
|
-
url: "https://github.com/covalenthq/
|
|
49
|
-
directory: "services/
|
|
48
|
+
url: "https://github.com/covalenthq/goldrush-services-monorepo.git",
|
|
49
|
+
directory: "services/goldrush-cli"
|
|
50
50
|
},
|
|
51
51
|
dependencies: {
|
|
52
52
|
"@covalenthq/client-sdk": "workspace:^",
|
|
@@ -100,6 +100,9 @@ async function getKeytar() {
|
|
|
100
100
|
return null;
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
+
async function isKeychainAvailable() {
|
|
104
|
+
return await getKeytar() !== null;
|
|
105
|
+
}
|
|
103
106
|
async function getApiKey() {
|
|
104
107
|
const keytar = await getKeytar();
|
|
105
108
|
if (keytar) {
|
|
@@ -186,13 +189,19 @@ import { GoldRushClient } from "@covalenthq/client-sdk";
|
|
|
186
189
|
async function validateApiKey(key) {
|
|
187
190
|
try {
|
|
188
191
|
const client = new GoldRushClient(key);
|
|
189
|
-
const response = await client.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
const response = await client.BaseService.getAllChains();
|
|
193
|
+
if (response.error) {
|
|
194
|
+
return {
|
|
195
|
+
valid: false,
|
|
196
|
+
error_message: response.error_message
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return { valid: true };
|
|
200
|
+
} catch (error) {
|
|
201
|
+
return {
|
|
202
|
+
valid: false,
|
|
203
|
+
error_message: error?.message || "The API key could not be validated.\nGet a key at https://goldrush.dev/platform/apikey/"
|
|
204
|
+
};
|
|
196
205
|
}
|
|
197
206
|
}
|
|
198
207
|
async function getMaskedApiKey() {
|
|
@@ -233,6 +242,14 @@ function infoBox(title, message) {
|
|
|
233
242
|
borderStyle: "round"
|
|
234
243
|
});
|
|
235
244
|
}
|
|
245
|
+
function warningBox(title, message) {
|
|
246
|
+
return boxen(message, {
|
|
247
|
+
title: chalk.hex("#FFE66D").bold(title),
|
|
248
|
+
borderColor: "yellow",
|
|
249
|
+
padding: 1,
|
|
250
|
+
borderStyle: "round"
|
|
251
|
+
});
|
|
252
|
+
}
|
|
236
253
|
|
|
237
254
|
// src/ui/spinner.ts
|
|
238
255
|
import ora from "ora";
|
|
@@ -287,23 +304,43 @@ var authCommand = new Command("auth").description("Set up your GoldRush API key"
|
|
|
287
304
|
}
|
|
288
305
|
const spinner = createSpinner("Validating API key...");
|
|
289
306
|
spinner.start();
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
307
|
+
const result = await validateApiKey(apiKey.trim());
|
|
308
|
+
if (result.valid) {
|
|
292
309
|
await setApiKey(apiKey.trim());
|
|
310
|
+
const keychainAvailable = await isKeychainAvailable();
|
|
293
311
|
spinner.succeed("API key validated and stored securely");
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
if (keychainAvailable) {
|
|
313
|
+
console.log(
|
|
314
|
+
successBox(
|
|
315
|
+
"Authentication Complete",
|
|
316
|
+
`API key stored in OS keychain
|
|
298
317
|
Key: ${colors.gold(apiKey.trim().slice(0, 6) + "..." + apiKey.trim().slice(-4))}`
|
|
299
|
-
|
|
300
|
-
|
|
318
|
+
)
|
|
319
|
+
);
|
|
320
|
+
} else {
|
|
321
|
+
console.log(
|
|
322
|
+
successBox(
|
|
323
|
+
"Authentication Complete",
|
|
324
|
+
`Key: ${colors.gold(apiKey.trim().slice(0, 6) + "..." + apiKey.trim().slice(-4))}`
|
|
325
|
+
)
|
|
326
|
+
);
|
|
327
|
+
console.log(
|
|
328
|
+
warningBox(
|
|
329
|
+
"Plaintext Storage Warning",
|
|
330
|
+
`The OS keychain (keytar) is not available on this system.
|
|
331
|
+
Your API key is stored in plaintext in the local config file.
|
|
332
|
+
|
|
333
|
+
To use secure storage, install the keytar native module or set
|
|
334
|
+
the ${colors.accent("GOLDRUSH_API_KEY")} environment variable instead.`
|
|
335
|
+
)
|
|
336
|
+
);
|
|
337
|
+
}
|
|
301
338
|
} else {
|
|
302
339
|
spinner.fail("Invalid API key");
|
|
303
340
|
console.log(
|
|
304
341
|
errorBox(
|
|
305
342
|
"Authentication Failed",
|
|
306
|
-
"The API key could not be validated.\nGet a key at https://goldrush.dev/platform/apikey/"
|
|
343
|
+
result.error_message || "The API key could not be validated.\nGet a key at https://goldrush.dev/platform/apikey/"
|
|
307
344
|
)
|
|
308
345
|
);
|
|
309
346
|
}
|
|
@@ -4816,7 +4853,7 @@ var configCommand = new Command4("config").description("View or update GoldRush
|
|
|
4816
4853
|
console.log(
|
|
4817
4854
|
infoBox(
|
|
4818
4855
|
"Current Settings",
|
|
4819
|
-
`Port:
|
|
4856
|
+
`Proxy Port: ${colors.gold(String(config2.port))}
|
|
4820
4857
|
Default Chain: ${colors.accent(config2.defaultChain)}
|
|
4821
4858
|
Quote Currency: ${colors.gold(config2.quoteCurrency)}`
|
|
4822
4859
|
)
|
|
@@ -4824,7 +4861,7 @@ Quote Currency: ${colors.gold(config2.quoteCurrency)}`
|
|
|
4824
4861
|
const action = await select({
|
|
4825
4862
|
message: "What would you like to update?",
|
|
4826
4863
|
choices: [
|
|
4827
|
-
{ name: `Port (${config2.port})`, value: "port" },
|
|
4864
|
+
{ name: `Proxy Port (${config2.port})`, value: "port" },
|
|
4828
4865
|
{
|
|
4829
4866
|
name: `Default Chain (${config2.defaultChain})`,
|
|
4830
4867
|
value: "chain"
|
|
@@ -4952,9 +4989,15 @@ var gasCommand = new Command5("gas").description("Get real-time gas price estima
|
|
|
4952
4989
|
if (!eventType) {
|
|
4953
4990
|
console.log(
|
|
4954
4991
|
errorBox(
|
|
4955
|
-
"Invalid Type",
|
|
4956
|
-
`
|
|
4957
|
-
|
|
4992
|
+
"Invalid Transaction Type",
|
|
4993
|
+
`"${colors.accent(options.type)}" is not a valid transaction type.
|
|
4994
|
+
|
|
4995
|
+
Valid values:
|
|
4996
|
+
${colors.gold("erc20")} \u2014 ERC-20 token transfer gas estimates
|
|
4997
|
+
${colors.gold("native")} \u2014 Native token transfer gas estimates
|
|
4998
|
+
${colors.gold("swap")} \u2014 Uniswap v3 swap gas estimates
|
|
4999
|
+
|
|
5000
|
+
Example: ${colors.accent(`goldrush gas eth-mainnet --type swap`)}`
|
|
4958
5001
|
)
|
|
4959
5002
|
);
|
|
4960
5003
|
return;
|
|
@@ -5571,7 +5614,6 @@ async function subscribeToWalletActivity(chainName, walletAddresses, callback) {
|
|
|
5571
5614
|
},
|
|
5572
5615
|
{
|
|
5573
5616
|
next: (events) => {
|
|
5574
|
-
infoBox(JSON.stringify(events, null, 2), "Wallet Activity");
|
|
5575
5617
|
for (const event of events) {
|
|
5576
5618
|
const decodedType = parseDecodedType(event.decoded_type);
|
|
5577
5619
|
const { summary, quoteUsd, tokenSymbol } = buildDetailsSummary(decodedType, event.decoded_details);
|
|
@@ -5606,9 +5648,39 @@ async function subscribeToWalletActivity(chainName, walletAddresses, callback) {
|
|
|
5606
5648
|
return unsubscribe;
|
|
5607
5649
|
}
|
|
5608
5650
|
|
|
5651
|
+
// src/utils/clipboard.ts
|
|
5652
|
+
import { execSync } from "child_process";
|
|
5653
|
+
function copyToClipboard(text) {
|
|
5654
|
+
const platform = process.platform;
|
|
5655
|
+
try {
|
|
5656
|
+
if (platform === "darwin") {
|
|
5657
|
+
execSync("pbcopy", { input: text });
|
|
5658
|
+
return true;
|
|
5659
|
+
}
|
|
5660
|
+
if (platform === "win32") {
|
|
5661
|
+
execSync(
|
|
5662
|
+
`powershell -NoProfile -Command "$input | Set-Clipboard"`,
|
|
5663
|
+
{ input: text }
|
|
5664
|
+
);
|
|
5665
|
+
return true;
|
|
5666
|
+
}
|
|
5667
|
+
if (platform === "linux") {
|
|
5668
|
+
try {
|
|
5669
|
+
execSync("xclip -selection clipboard", { input: text });
|
|
5670
|
+
return true;
|
|
5671
|
+
} catch {
|
|
5672
|
+
execSync("xsel --clipboard --input", { input: text });
|
|
5673
|
+
return true;
|
|
5674
|
+
}
|
|
5675
|
+
}
|
|
5676
|
+
return false;
|
|
5677
|
+
} catch {
|
|
5678
|
+
return false;
|
|
5679
|
+
}
|
|
5680
|
+
}
|
|
5681
|
+
|
|
5609
5682
|
// src/commands/newpairs.ts
|
|
5610
5683
|
import { Command as Command9 } from "commander";
|
|
5611
|
-
import { execSync } from "child_process";
|
|
5612
5684
|
var newpairsCommand = new Command9("new_pairs").description("Fetch the latest new DEX liquidity pairs").argument("[chain]", "Blockchain name (e.g. eth-mainnet)").argument(
|
|
5613
5685
|
"[protocols...]",
|
|
5614
5686
|
"Filter by DEX protocol(s) (e.g. uniswap-v2 raydium-amm)"
|
|
@@ -5706,14 +5778,6 @@ Supported protocols:
|
|
|
5706
5778
|
function getPairsArray() {
|
|
5707
5779
|
return [...pairMap.values()].reverse().slice(0, limit);
|
|
5708
5780
|
}
|
|
5709
|
-
function copyToClipboard(text) {
|
|
5710
|
-
try {
|
|
5711
|
-
execSync("pbcopy", { input: text });
|
|
5712
|
-
return true;
|
|
5713
|
-
} catch {
|
|
5714
|
-
return false;
|
|
5715
|
-
}
|
|
5716
|
-
}
|
|
5717
5781
|
function rerender() {
|
|
5718
5782
|
const pairs = getPairsArray();
|
|
5719
5783
|
if (selectedRow >= pairs.length) {
|
|
@@ -6175,12 +6239,19 @@ var asciiArt = [
|
|
|
6175
6239
|
" \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Terminal-first blockchain data & trading \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
|
|
6176
6240
|
" \u2550\u2550\u2550\u2550\u2550\u2550 powered by Covalent \u2550\u2550\u2550\u2550\u2550\u2550"
|
|
6177
6241
|
];
|
|
6178
|
-
function printLogo() {
|
|
6242
|
+
function printLogo(version) {
|
|
6179
6243
|
console.log();
|
|
6180
6244
|
for (let i = 0; i < asciiArt.length; i++) {
|
|
6181
6245
|
const colorIdx = Math.min(i, gradientStops.length - 1);
|
|
6182
6246
|
console.log(chalk5.hex(gradientStops[colorIdx])(asciiArt[i]));
|
|
6183
6247
|
}
|
|
6248
|
+
if (version) {
|
|
6249
|
+
console.log(
|
|
6250
|
+
chalk5.hex(gradientStops[gradientStops.length - 1])(
|
|
6251
|
+
` v${version}`
|
|
6252
|
+
)
|
|
6253
|
+
);
|
|
6254
|
+
}
|
|
6184
6255
|
console.log();
|
|
6185
6256
|
}
|
|
6186
6257
|
|
|
@@ -6404,8 +6475,11 @@ async function startProxyServer(port) {
|
|
|
6404
6475
|
);
|
|
6405
6476
|
process.exit(1);
|
|
6406
6477
|
}
|
|
6407
|
-
|
|
6408
|
-
|
|
6478
|
+
let sessionToken = await getSessionToken();
|
|
6479
|
+
if (!sessionToken) {
|
|
6480
|
+
sessionToken = crypto.randomBytes(32).toString("hex");
|
|
6481
|
+
await setSessionToken(sessionToken);
|
|
6482
|
+
}
|
|
6409
6483
|
const app = express();
|
|
6410
6484
|
app.use(express.json());
|
|
6411
6485
|
app.use(bodySizeLimit);
|
|
@@ -6415,7 +6489,7 @@ async function startProxyServer(port) {
|
|
|
6415
6489
|
app.get("/tools", toolsHandler);
|
|
6416
6490
|
app.post("/call", callHandler);
|
|
6417
6491
|
const server = app.listen(serverPort, () => {
|
|
6418
|
-
printLogo();
|
|
6492
|
+
printLogo(package_default.version);
|
|
6419
6493
|
console.log(
|
|
6420
6494
|
successBox(
|
|
6421
6495
|
"Proxy Server Running",
|
|
@@ -6452,11 +6526,19 @@ var proxyCommand = new Command11("proxy").description("Launch the GoldRush proxy
|
|
|
6452
6526
|
});
|
|
6453
6527
|
|
|
6454
6528
|
// src/api/search.ts
|
|
6529
|
+
var SearchTimeoutError = class extends Error {
|
|
6530
|
+
constructor() {
|
|
6531
|
+
super(
|
|
6532
|
+
"Search request timed out. The streaming service did not respond within 15 seconds."
|
|
6533
|
+
);
|
|
6534
|
+
this.name = "SearchTimeoutError";
|
|
6535
|
+
}
|
|
6536
|
+
};
|
|
6455
6537
|
var SEARCH_TOKEN_QUERY = `
|
|
6456
6538
|
query SearchToken($query: String!) {
|
|
6457
6539
|
searchToken(query: $query) {
|
|
6458
6540
|
pair_address
|
|
6459
|
-
|
|
6541
|
+
chain_name
|
|
6460
6542
|
quote_rate
|
|
6461
6543
|
quote_rate_usd
|
|
6462
6544
|
volume
|
|
@@ -6484,11 +6566,11 @@ async function searchTokens(query) {
|
|
|
6484
6566
|
{ query },
|
|
6485
6567
|
{
|
|
6486
6568
|
next: (data) => {
|
|
6487
|
-
const items = data?.searchToken ?? data ??
|
|
6569
|
+
const items = data?.data?.searchToken ?? data?.searchToken ?? data;
|
|
6488
6570
|
const list = Array.isArray(items) ? items : [];
|
|
6489
6571
|
results = list.map((item) => ({
|
|
6490
6572
|
pairAddress: item.pair_address ?? "",
|
|
6491
|
-
chain: item.chain ?? "",
|
|
6573
|
+
chain: item.chain_name ?? item.chain ?? "",
|
|
6492
6574
|
quoteRate: item.quote_rate ?? 0,
|
|
6493
6575
|
quoteRateUsd: item.quote_rate_usd ?? 0,
|
|
6494
6576
|
volume: item.volume ?? 0,
|
|
@@ -6515,7 +6597,13 @@ async function searchTokens(query) {
|
|
|
6515
6597
|
}
|
|
6516
6598
|
}
|
|
6517
6599
|
);
|
|
6518
|
-
setTimeout(() =>
|
|
6600
|
+
setTimeout(() => {
|
|
6601
|
+
if (results.length === 0) {
|
|
6602
|
+
reject(new SearchTimeoutError());
|
|
6603
|
+
} else {
|
|
6604
|
+
resolve2(results);
|
|
6605
|
+
}
|
|
6606
|
+
}, 15e3);
|
|
6519
6607
|
});
|
|
6520
6608
|
}
|
|
6521
6609
|
|
|
@@ -6564,8 +6652,21 @@ Results: ${colors.gold(String(results.length))} (sorted by volume)`
|
|
|
6564
6652
|
);
|
|
6565
6653
|
renderSearchResultsTable(results);
|
|
6566
6654
|
} catch (err) {
|
|
6567
|
-
|
|
6568
|
-
|
|
6655
|
+
if (err instanceof SearchTimeoutError) {
|
|
6656
|
+
spinner.warn("Request timed out");
|
|
6657
|
+
console.log(
|
|
6658
|
+
warningBox(
|
|
6659
|
+
"Search Timed Out",
|
|
6660
|
+
`No response from the streaming service within 15 seconds.
|
|
6661
|
+
|
|
6662
|
+
Try again or check your connection.
|
|
6663
|
+
Run ${colors.accent("goldrush status")} to verify your API key.`
|
|
6664
|
+
)
|
|
6665
|
+
);
|
|
6666
|
+
} else {
|
|
6667
|
+
spinner.fail("Search failed");
|
|
6668
|
+
console.log(errorBox("Error", err.message));
|
|
6669
|
+
}
|
|
6569
6670
|
}
|
|
6570
6671
|
});
|
|
6571
6672
|
|
|
@@ -6592,11 +6693,13 @@ Proxy Port: ${colors.accent(String(port))}`
|
|
|
6592
6693
|
} else {
|
|
6593
6694
|
const spinner = createSpinner("Validating API key...");
|
|
6594
6695
|
spinner.start();
|
|
6595
|
-
const
|
|
6596
|
-
if (valid) {
|
|
6696
|
+
const result = await validateApiKey(apiKey);
|
|
6697
|
+
if (result.valid) {
|
|
6597
6698
|
spinner.succeed("API key is valid");
|
|
6598
6699
|
} else {
|
|
6599
|
-
spinner.fail(
|
|
6700
|
+
spinner.fail(
|
|
6701
|
+
`API key is invalid or expired${result.error_message ? `: ${result.error_message}` : ""}`
|
|
6702
|
+
);
|
|
6600
6703
|
}
|
|
6601
6704
|
}
|
|
6602
6705
|
const proxySpinner = createSpinner(
|
|
@@ -6615,12 +6718,20 @@ Proxy Port: ${colors.accent(String(port))}`
|
|
|
6615
6718
|
}
|
|
6616
6719
|
} catch {
|
|
6617
6720
|
proxySpinner.warn(
|
|
6618
|
-
`Proxy server not reachable on port ${port}. Run \`goldrush
|
|
6721
|
+
`Proxy server not reachable on port ${port}. Run \`goldrush proxy\` to launch it.`
|
|
6619
6722
|
);
|
|
6620
6723
|
}
|
|
6621
6724
|
});
|
|
6622
6725
|
|
|
6623
6726
|
// src/api/traders.ts
|
|
6727
|
+
var TradersTimeoutError = class extends Error {
|
|
6728
|
+
constructor() {
|
|
6729
|
+
super(
|
|
6730
|
+
"Traders request timed out. The streaming service did not respond within 15 seconds."
|
|
6731
|
+
);
|
|
6732
|
+
this.name = "TradersTimeoutError";
|
|
6733
|
+
}
|
|
6734
|
+
};
|
|
6624
6735
|
var UPNL_FOR_TOKEN_QUERY = `
|
|
6625
6736
|
query UpnlForToken($chain_name: ChainName!, $token_address: String!) {
|
|
6626
6737
|
upnlForToken(chain_name: $chain_name, token_address: $token_address) {
|
|
@@ -6680,7 +6791,13 @@ async function getTopTraders(chainName, tokenAddress) {
|
|
|
6680
6791
|
}
|
|
6681
6792
|
}
|
|
6682
6793
|
);
|
|
6683
|
-
setTimeout(() =>
|
|
6794
|
+
setTimeout(() => {
|
|
6795
|
+
if (results.length === 0) {
|
|
6796
|
+
reject(new TradersTimeoutError());
|
|
6797
|
+
} else {
|
|
6798
|
+
resolve2(results);
|
|
6799
|
+
}
|
|
6800
|
+
}, 15e3);
|
|
6684
6801
|
});
|
|
6685
6802
|
}
|
|
6686
6803
|
|
|
@@ -6747,8 +6864,21 @@ Traders: ${colors.gold(String(traders.length))}`
|
|
|
6747
6864
|
);
|
|
6748
6865
|
renderTopTradersTable(traders);
|
|
6749
6866
|
} catch (err) {
|
|
6750
|
-
|
|
6751
|
-
|
|
6867
|
+
if (err instanceof TradersTimeoutError) {
|
|
6868
|
+
spinner.warn("Request timed out");
|
|
6869
|
+
console.log(
|
|
6870
|
+
warningBox(
|
|
6871
|
+
"Traders Query Timed Out",
|
|
6872
|
+
`No response from the streaming service within 15 seconds.
|
|
6873
|
+
|
|
6874
|
+
Make sure the token address is on a supported streaming chain.
|
|
6875
|
+
Run ${colors.accent("goldrush status")} to verify your API key.`
|
|
6876
|
+
)
|
|
6877
|
+
);
|
|
6878
|
+
} else {
|
|
6879
|
+
spinner.fail("Failed to fetch top traders");
|
|
6880
|
+
console.log(errorBox("Error", err.message));
|
|
6881
|
+
}
|
|
6752
6882
|
}
|
|
6753
6883
|
}
|
|
6754
6884
|
);
|
|
@@ -6850,7 +6980,6 @@ Showing: ${colors.gold(String(transfers.length))} most recent`
|
|
|
6850
6980
|
// src/commands/watch.ts
|
|
6851
6981
|
import { input as input7 } from "@inquirer/prompts";
|
|
6852
6982
|
import { Command as Command16 } from "commander";
|
|
6853
|
-
import { execSync as execSync2 } from "child_process";
|
|
6854
6983
|
var watchCommand = new Command16("watch").description("Stream live wallet activity (transactions, transfers, swaps)").argument("[address]", "Wallet address to watch").argument("[chain]", "Blockchain name (e.g. eth-mainnet)").option("-l, --limit <number>", "Max rows to display", "20").action(
|
|
6855
6984
|
async (address, chain, opts) => {
|
|
6856
6985
|
if (!await isAuthenticated()) {
|
|
@@ -6865,8 +6994,17 @@ var watchCommand = new Command16("watch").description("Stream live wallet activi
|
|
|
6865
6994
|
let walletAddress = address;
|
|
6866
6995
|
if (!walletAddress) {
|
|
6867
6996
|
walletAddress = await input7({
|
|
6868
|
-
message: colors.primary(
|
|
6869
|
-
|
|
6997
|
+
message: colors.primary(
|
|
6998
|
+
"Wallet address or ENS name to watch:"
|
|
6999
|
+
),
|
|
7000
|
+
validate: (val) => {
|
|
7001
|
+
const v = val.trim();
|
|
7002
|
+
if (!v) return "Please enter an address or ENS name.";
|
|
7003
|
+
if (/^0x[a-fA-F0-9]{40}$/.test(v) || /^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.eth$/.test(v)) {
|
|
7004
|
+
return true;
|
|
7005
|
+
}
|
|
7006
|
+
return "Enter a valid EVM address (0x\u202640 hex chars) or ENS name (e.g. vitalik.eth).";
|
|
7007
|
+
}
|
|
6870
7008
|
});
|
|
6871
7009
|
walletAddress = walletAddress.trim();
|
|
6872
7010
|
}
|
|
@@ -6931,14 +7069,6 @@ Run ${colors.accent("goldrush chains")} for details.`
|
|
|
6931
7069
|
function getDisplayActivities() {
|
|
6932
7070
|
return activities.slice(0, limit);
|
|
6933
7071
|
}
|
|
6934
|
-
function copyToClipboard(text) {
|
|
6935
|
-
try {
|
|
6936
|
-
execSync2("pbcopy", { input: text });
|
|
6937
|
-
return true;
|
|
6938
|
-
} catch {
|
|
6939
|
-
return false;
|
|
6940
|
-
}
|
|
6941
|
-
}
|
|
6942
7072
|
function rerender() {
|
|
6943
7073
|
const display = getDisplayActivities();
|
|
6944
7074
|
if (selectedRow >= display.length) {
|
|
@@ -7110,7 +7240,7 @@ program.addCommand(mcpCommand);
|
|
|
7110
7240
|
program.addCommand(chainsCommand);
|
|
7111
7241
|
program.addCommand(watchCommand);
|
|
7112
7242
|
program.action(async () => {
|
|
7113
|
-
printLogo();
|
|
7243
|
+
printLogo(package_default.version);
|
|
7114
7244
|
const action = await select3({
|
|
7115
7245
|
message: colors.primary("What would you like to do?"),
|
|
7116
7246
|
choices: [
|