httpcat-cli 0.3.0 → 0.3.1
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/.github/workflows/ci.yml +3 -0
- package/.github/workflows/rc-publish.yml +6 -0
- package/.github/workflows/release.yml +102 -0
- package/.github/workflows/sync-version.yml +31 -2
- package/README.md +1408 -109
- package/additions.txt +3 -0
- package/bun.lock +260 -25
- package/dist/agent/autonomous-trader.d.ts.map +1 -0
- package/dist/agent/autonomous-trader.js +362 -0
- package/dist/agent/autonomous-trader.js.map +1 -0
- package/dist/agent/ax-agent.d.ts.map +1 -1
- package/dist/agent/ax-agent.js +356 -18
- package/dist/agent/ax-agent.js.map +1 -1
- package/dist/agent/event-client.d.ts.map +1 -0
- package/dist/agent/event-client.js +82 -0
- package/dist/agent/event-client.js.map +1 -0
- package/dist/agent/log-stream.d.ts.map +1 -0
- package/dist/agent/log-stream.js +95 -0
- package/dist/agent/log-stream.js.map +1 -0
- package/dist/agent/memory/conversation-session.d.ts.map +1 -0
- package/dist/agent/memory/conversation-session.js +232 -0
- package/dist/agent/memory/conversation-session.js.map +1 -0
- package/dist/agent/memory/conversation-store.d.ts.map +1 -0
- package/dist/agent/memory/conversation-store.js +214 -0
- package/dist/agent/memory/conversation-store.js.map +1 -0
- package/dist/agent/memory/database-schema.d.ts.map +1 -0
- package/dist/agent/memory/database-schema.js +355 -0
- package/dist/agent/memory/database-schema.js.map +1 -0
- package/dist/agent/memory/decision-tracker.d.ts.map +1 -0
- package/dist/agent/memory/decision-tracker.js +274 -0
- package/dist/agent/memory/decision-tracker.js.map +1 -0
- package/dist/agent/memory/memory-manager.d.ts.map +1 -0
- package/dist/agent/memory/memory-manager.js +187 -0
- package/dist/agent/memory/memory-manager.js.map +1 -0
- package/dist/agent/memory/types.d.ts.map +1 -0
- package/dist/agent/memory/types.js +5 -0
- package/dist/agent/memory/types.js.map +1 -0
- package/dist/agent/message-formatter.d.ts.map +1 -0
- package/dist/agent/message-formatter.js +76 -0
- package/dist/agent/message-formatter.js.map +1 -0
- package/dist/agent/position-db.d.ts.map +1 -0
- package/dist/agent/position-db.js +154 -0
- package/dist/agent/position-db.js.map +1 -0
- package/dist/agent/simple-chat-ui-static.d.ts.map +1 -0
- package/dist/agent/simple-chat-ui-static.js +129 -0
- package/dist/agent/simple-chat-ui-static.js.map +1 -0
- package/dist/agent/simple-chat-ui.d.ts.map +1 -0
- package/dist/agent/simple-chat-ui.js +90 -0
- package/dist/agent/simple-chat-ui.js.map +1 -0
- package/dist/agent/tools.d.ts.map +1 -1
- package/dist/agent/tools.js +297 -4
- package/dist/agent/tools.js.map +1 -1
- package/dist/agent/ui.d.ts.map +1 -0
- package/dist/agent/ui.js +84 -0
- package/dist/agent/ui.js.map +1 -0
- package/dist/agent/unified-runtime.d.ts.map +1 -0
- package/dist/agent/unified-runtime.js +397 -0
- package/dist/agent/unified-runtime.js.map +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +272 -21
- package/dist/client.js.map +1 -1
- package/dist/commands/account.d.ts.map +1 -1
- package/dist/commands/account.js +187 -33
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +125 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/approve.d.ts.map +1 -0
- package/dist/commands/approve.js +505 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/automation.d.ts.map +1 -0
- package/dist/commands/automation.js +346 -0
- package/dist/commands/automation.js.map +1 -0
- package/dist/commands/balances.d.ts.map +1 -1
- package/dist/commands/balances.js +226 -73
- package/dist/commands/balances.js.map +1 -1
- package/dist/commands/buy.d.ts.map +1 -1
- package/dist/commands/buy.js +149 -146
- package/dist/commands/buy.js.map +1 -1
- package/dist/commands/call.d.ts.map +1 -0
- package/dist/commands/call.js +51 -0
- package/dist/commands/call.js.map +1 -0
- package/dist/commands/cex.d.ts.map +1 -0
- package/dist/commands/cex.js +958 -0
- package/dist/commands/cex.js.map +1 -0
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +169 -411
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/claim.d.ts.map +1 -1
- package/dist/commands/claim.js +313 -29
- package/dist/commands/claim.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +151 -43
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/gasless-swap.d.ts.map +1 -0
- package/dist/commands/gasless-swap.js +232 -0
- package/dist/commands/gasless-swap.js.map +1 -0
- package/dist/commands/health.d.ts.map +1 -1
- package/dist/commands/health.js +63 -7
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/info.d.ts.map +1 -1
- package/dist/commands/info.js +131 -47
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/launchpad.d.ts.map +1 -0
- package/dist/commands/launchpad.js +708 -0
- package/dist/commands/launchpad.js.map +1 -0
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +57 -23
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/market.d.ts.map +1 -0
- package/dist/commands/market.js +960 -0
- package/dist/commands/market.js.map +1 -0
- package/dist/commands/mcp-install.d.ts.map +1 -0
- package/dist/commands/mcp-install.js +387 -0
- package/dist/commands/mcp-install.js.map +1 -0
- package/dist/commands/opps.d.ts.map +1 -0
- package/dist/commands/opps.js +409 -0
- package/dist/commands/opps.js.map +1 -0
- package/dist/commands/perps.d.ts.map +1 -0
- package/dist/commands/perps.js +248 -0
- package/dist/commands/perps.js.map +1 -0
- package/dist/commands/portfolio.d.ts.map +1 -0
- package/dist/commands/portfolio.js +679 -0
- package/dist/commands/portfolio.js.map +1 -0
- package/dist/commands/positions.d.ts.map +1 -1
- package/dist/commands/positions.js +76 -47
- package/dist/commands/positions.js.map +1 -1
- package/dist/commands/predict.d.ts.map +1 -0
- package/dist/commands/predict.js +280 -0
- package/dist/commands/predict.js.map +1 -0
- package/dist/commands/predictions.d.ts.map +1 -0
- package/dist/commands/predictions.js +486 -0
- package/dist/commands/predictions.js.map +1 -0
- package/dist/commands/risk.d.ts.map +1 -0
- package/dist/commands/risk.js +225 -0
- package/dist/commands/risk.js.map +1 -0
- package/dist/commands/security.d.ts.map +1 -0
- package/dist/commands/security.js +244 -0
- package/dist/commands/security.js.map +1 -0
- package/dist/commands/sell.d.ts.map +1 -1
- package/dist/commands/sell.js +67 -34
- package/dist/commands/sell.js.map +1 -1
- package/dist/commands/send.d.ts.map +1 -0
- package/dist/commands/send.js +733 -0
- package/dist/commands/send.js.map +1 -0
- package/dist/commands/sign.d.ts.map +1 -0
- package/dist/commands/sign.js +1048 -0
- package/dist/commands/sign.js.map +1 -0
- package/dist/commands/swap.d.ts.map +1 -0
- package/dist/commands/swap.js +744 -0
- package/dist/commands/swap.js.map +1 -0
- package/dist/commands/system.d.ts.map +1 -0
- package/dist/commands/system.js +417 -0
- package/dist/commands/system.js.map +1 -0
- package/dist/commands/tools/index.d.ts.map +1 -0
- package/dist/commands/tools/index.js +2040 -0
- package/dist/commands/tools/index.js.map +1 -0
- package/dist/commands/trade.d.ts.map +1 -0
- package/dist/commands/trade.js +237 -0
- package/dist/commands/trade.js.map +1 -0
- package/dist/commands/transactions.d.ts.map +1 -1
- package/dist/commands/transactions.js +29 -17
- package/dist/commands/transactions.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +429 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +351 -40
- package/dist/config.js.map +1 -1
- package/dist/index.js +4524 -924
- package/dist/index.js.map +1 -1
- package/dist/interactive/art.d.ts.map +1 -1
- package/dist/interactive/art.js +33 -1
- package/dist/interactive/art.js.map +1 -1
- package/dist/interactive/shell.d.ts.map +1 -1
- package/dist/interactive/shell.js +467 -2652
- package/dist/interactive/shell.js.map +1 -1
- package/dist/mcp/context.d.ts.map +1 -0
- package/dist/mcp/context.js +211 -0
- package/dist/mcp/context.js.map +1 -0
- package/dist/mcp/onboarding.d.ts.map +1 -0
- package/dist/mcp/onboarding.js +266 -0
- package/dist/mcp/onboarding.js.map +1 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +222 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +51 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +4119 -169
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/types/agent-info.d.ts.map +1 -0
- package/dist/types/agent-info.js +11 -0
- package/dist/types/agent-info.js.map +1 -0
- package/dist/ui/components/ScrollableList.d.ts.map +1 -0
- package/dist/ui/components/ScrollableList.js +72 -0
- package/dist/ui/components/ScrollableList.js.map +1 -0
- package/dist/ui/components/ThemeProvider.d.ts.map +1 -0
- package/dist/ui/components/ThemeProvider.js +87 -0
- package/dist/ui/components/ThemeProvider.js.map +1 -0
- package/dist/ui/components/ThemedBox.d.ts.map +1 -0
- package/dist/ui/components/ThemedBox.js +24 -0
- package/dist/ui/components/ThemedBox.js.map +1 -0
- package/dist/ui/components/agent/ChatHeader.d.ts.map +1 -0
- package/dist/ui/components/agent/ChatHeader.js +39 -0
- package/dist/ui/components/agent/ChatHeader.js.map +1 -0
- package/dist/ui/components/agent/Header.d.ts.map +1 -0
- package/dist/ui/components/agent/Header.js +14 -0
- package/dist/ui/components/agent/Header.js.map +1 -0
- package/dist/ui/components/agent/Input.d.ts.map +1 -0
- package/dist/ui/components/agent/Input.js +23 -0
- package/dist/ui/components/agent/Input.js.map +1 -0
- package/dist/ui/components/agent/Output.d.ts.map +1 -0
- package/dist/ui/components/agent/Output.js +23 -0
- package/dist/ui/components/agent/Output.js.map +1 -0
- package/dist/ui/components/chat/TokenChatUI.d.ts.map +1 -0
- package/dist/ui/components/chat/TokenChatUI.js +133 -0
- package/dist/ui/components/chat/TokenChatUI.js.map +1 -0
- package/dist/ui/components/shell/ShellHeader.d.ts.map +1 -0
- package/dist/ui/components/shell/ShellHeader.js +31 -0
- package/dist/ui/components/shell/ShellHeader.js.map +1 -0
- package/dist/ui/components/shell/ShellInput.d.ts.map +1 -0
- package/dist/ui/components/shell/ShellInput.js +151 -0
- package/dist/ui/components/shell/ShellInput.js.map +1 -0
- package/dist/ui/components/shell/ShellOutput.d.ts.map +1 -0
- package/dist/ui/components/shell/ShellOutput.js +8 -0
- package/dist/ui/components/shell/ShellOutput.js.map +1 -0
- package/dist/ui/hooks/useChatWebSocket.d.ts.map +1 -0
- package/dist/ui/hooks/useChatWebSocket.js +76 -0
- package/dist/ui/hooks/useChatWebSocket.js.map +1 -0
- package/dist/ui/hooks/useCommandHistory.d.ts.map +1 -0
- package/dist/ui/hooks/useCommandHistory.js +70 -0
- package/dist/ui/hooks/useCommandHistory.js.map +1 -0
- package/dist/ui/hooks/useDebounce.d.ts.map +1 -0
- package/dist/ui/hooks/useDebounce.js +17 -0
- package/dist/ui/hooks/useDebounce.js.map +1 -0
- package/dist/ui/hooks/useLogStream.d.ts.map +1 -0
- package/dist/ui/hooks/useLogStream.js +20 -0
- package/dist/ui/hooks/useLogStream.js.map +1 -0
- package/dist/ui/hooks/useVirtualScroll.d.ts.map +1 -0
- package/dist/ui/hooks/useVirtualScroll.js +70 -0
- package/dist/ui/hooks/useVirtualScroll.js.map +1 -0
- package/dist/utils/admin.d.ts.map +1 -0
- package/dist/utils/admin.js +144 -0
- package/dist/utils/admin.js.map +1 -0
- package/dist/utils/autoSetup.d.ts.map +1 -0
- package/dist/utils/autoSetup.js +252 -0
- package/dist/utils/autoSetup.js.map +1 -0
- package/dist/utils/build-constants.d.ts.map +1 -0
- package/dist/utils/build-constants.js +10 -0
- package/dist/utils/build-constants.js.map +1 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +10 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils/formatting.js +46 -9
- package/dist/utils/formatting.js.map +1 -1
- package/dist/utils/llm-cli-config.d.ts.map +1 -0
- package/dist/utils/llm-cli-config.js +963 -0
- package/dist/utils/llm-cli-config.js.map +1 -0
- package/dist/utils/llm-cli-detector.d.ts.map +1 -0
- package/dist/utils/llm-cli-detector.js +202 -0
- package/dist/utils/llm-cli-detector.js.map +1 -0
- package/dist/utils/loading.d.ts.map +1 -1
- package/dist/utils/loading.js +25 -3
- package/dist/utils/loading.js.map +1 -1
- package/dist/utils/maintenance.d.ts.map +1 -0
- package/dist/utils/maintenance.js +17 -0
- package/dist/utils/maintenance.js.map +1 -0
- package/dist/utils/mcp-config.d.ts.map +1 -0
- package/dist/utils/mcp-config.js +77 -0
- package/dist/utils/mcp-config.js.map +1 -0
- package/dist/utils/privateKeyPrompt.d.ts.map +1 -1
- package/dist/utils/privateKeyPrompt.js +308 -129
- package/dist/utils/privateKeyPrompt.js.map +1 -1
- package/dist/utils/process-cleanup.d.ts.map +1 -0
- package/dist/utils/process-cleanup.js +136 -0
- package/dist/utils/process-cleanup.js.map +1 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +56 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/rpc-helpers.d.ts.map +1 -0
- package/dist/utils/rpc-helpers.js +70 -0
- package/dist/utils/rpc-helpers.js.map +1 -0
- package/dist/utils/rpc-transport.d.ts.map +1 -0
- package/dist/utils/rpc-transport.js +87 -0
- package/dist/utils/rpc-transport.js.map +1 -0
- package/dist/utils/shell-setup.d.ts.map +1 -0
- package/dist/utils/shell-setup.js +531 -0
- package/dist/utils/shell-setup.js.map +1 -0
- package/dist/utils/status.d.ts.map +1 -1
- package/dist/utils/status.js +34 -5
- package/dist/utils/status.js.map +1 -1
- package/dist/utils/token-resolver.d.ts.map +1 -1
- package/dist/utils/token-resolver.js +51 -8
- package/dist/utils/token-resolver.js.map +1 -1
- package/dist/utils/x402-caller.d.ts.map +1 -0
- package/dist/utils/x402-caller.js +17 -0
- package/dist/utils/x402-caller.js.map +1 -0
- package/docs/README.md +28 -0
- package/docs/agent/README.md +18 -0
- package/docs/api/README.md +41 -0
- package/docs/cli/README.md +42 -0
- package/docs/guides/README.md +26 -0
- package/docs/implementation/README.md +18 -0
- package/docs/planning/README.md +19 -0
- package/docs/testing/README.md +15 -0
- package/docs/ux/README.md +16 -0
- package/issues.txt +2 -0
- package/package.json +24 -9
- package/scripts/cat-spin.sh +417 -0
- package/scripts/deprecate-rc-versions.js +58 -0
- package/scripts/inject-build-constants.js +43 -0
- package/scripts/monitor-foobar.js +117 -0
- package/swap.logs +61 -0
- package/swapping.txt +108 -0
- package/test.txt +12 -0
- package/tests/fixtures/test-data.json +16 -0
- package/Screenshot 2025-12-21 at 8.56.02/342/200/257PM.png +0 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import inquirer from
|
|
2
|
-
import chalk from
|
|
3
|
-
import { formatEther } from
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { formatEther } from "viem";
|
|
4
4
|
// USDC balance checking using viem directly
|
|
5
|
-
import { config } from
|
|
6
|
-
import { getNetworkConfig } from
|
|
7
|
-
import { printCat } from
|
|
8
|
-
import { formatAddress, printWarning } from
|
|
9
|
-
import {
|
|
5
|
+
import { config } from "../config.js";
|
|
6
|
+
import { getNetworkConfig } from "../utils/constants.js";
|
|
7
|
+
import { printCat } from "../interactive/art.js";
|
|
8
|
+
import { formatAddress, printWarning } from "../utils/formatting.js";
|
|
9
|
+
import { retryWithBackoff } from "./retry.js";
|
|
10
|
+
import { generateSeedPhrase, validateSeedPhrase, seedPhraseToPrivateKey, getAddressFromPrivateKey, } from "./wallet.js";
|
|
11
|
+
import { createMcpConfig } from "./mcp-config.js";
|
|
12
|
+
import { detectInstalledLlms } from "./llm-cli-detector.js";
|
|
13
|
+
import { configureLLM } from "./llm-cli-config.js";
|
|
10
14
|
/**
|
|
11
15
|
* Prompts the user to set up their wallet with three options:
|
|
12
16
|
* 1. Generate new wallet (seed phrase)
|
|
@@ -19,47 +23,47 @@ import { generateSeedPhrase, validateSeedPhrase, seedPhraseToPrivateKey, getAddr
|
|
|
19
23
|
export async function promptForPrivateKey() {
|
|
20
24
|
console.log();
|
|
21
25
|
// Show wizard cat
|
|
22
|
-
printCat(
|
|
23
|
-
console.log(chalk.bold.cyan(
|
|
26
|
+
printCat("wizard");
|
|
27
|
+
console.log(chalk.bold.cyan("🔐 Let's set up your wallet...\n"));
|
|
24
28
|
// Security messaging - make it more playful and safe-feeling
|
|
25
|
-
console.log(chalk.dim(
|
|
26
|
-
console.log(chalk.dim(
|
|
27
|
-
console.log(chalk.dim(
|
|
28
|
-
console.log(chalk.dim(
|
|
29
|
-
console.log(chalk.dim(
|
|
29
|
+
console.log(chalk.dim("🔒 Security & Privacy:"));
|
|
30
|
+
console.log(chalk.dim(" • Your keys are stored locally on your machine only"));
|
|
31
|
+
console.log(chalk.dim(" • They are never sent to any server or third party"));
|
|
32
|
+
console.log(chalk.dim(" • They are only used locally to sign transactions"));
|
|
33
|
+
console.log(chalk.dim(" • Stored in:"), chalk.cyan(config.getConfigPath()));
|
|
30
34
|
console.log();
|
|
31
35
|
// Ask user what they want to do - make "generate" the default
|
|
32
36
|
const setupChoice = await inquirer.prompt([
|
|
33
37
|
{
|
|
34
|
-
type:
|
|
35
|
-
name:
|
|
36
|
-
message:
|
|
38
|
+
type: "list",
|
|
39
|
+
name: "option",
|
|
40
|
+
message: "How would you like to set up your wallet?",
|
|
37
41
|
choices: [
|
|
38
42
|
{
|
|
39
|
-
name:
|
|
40
|
-
value:
|
|
43
|
+
name: "✨ Generate new wallet (seed phrase) - Recommended for new users",
|
|
44
|
+
value: "generate",
|
|
41
45
|
},
|
|
42
46
|
{
|
|
43
|
-
name:
|
|
44
|
-
value:
|
|
47
|
+
name: "📥 Import existing seed phrase",
|
|
48
|
+
value: "import_seed",
|
|
45
49
|
},
|
|
46
50
|
{
|
|
47
|
-
name:
|
|
48
|
-
value:
|
|
51
|
+
name: "🔑 Import existing private key",
|
|
52
|
+
value: "import_key",
|
|
49
53
|
},
|
|
50
54
|
],
|
|
51
|
-
default:
|
|
55
|
+
default: "generate", // Make generate the default!
|
|
52
56
|
},
|
|
53
57
|
]);
|
|
54
58
|
let seedPhrase;
|
|
55
59
|
let privateKey;
|
|
56
60
|
let accountIndex = 0;
|
|
57
|
-
if (setupChoice.option ===
|
|
61
|
+
if (setupChoice.option === "generate") {
|
|
58
62
|
// Generate new seed phrase
|
|
59
63
|
seedPhrase = await handleGenerateSeedPhrase();
|
|
60
64
|
accountIndex = 1; // First seed-derived account
|
|
61
65
|
}
|
|
62
|
-
else if (setupChoice.option ===
|
|
66
|
+
else if (setupChoice.option === "import_seed") {
|
|
63
67
|
// Import existing seed phrase
|
|
64
68
|
seedPhrase = await handleImportSeedPhrase();
|
|
65
69
|
accountIndex = 1; // First seed-derived account
|
|
@@ -87,41 +91,41 @@ export async function promptForPrivateKey() {
|
|
|
87
91
|
*/
|
|
88
92
|
export async function handleGenerateSeedPhrase() {
|
|
89
93
|
console.log();
|
|
90
|
-
console.log(chalk.bold.cyan(
|
|
94
|
+
console.log(chalk.bold.cyan("🌱 Generating new wallet for you...\n"));
|
|
91
95
|
// Ask for word count
|
|
92
96
|
const wordChoice = await inquirer.prompt([
|
|
93
97
|
{
|
|
94
|
-
type:
|
|
95
|
-
name:
|
|
96
|
-
message:
|
|
98
|
+
type: "list",
|
|
99
|
+
name: "wordCount",
|
|
100
|
+
message: "How many words?",
|
|
97
101
|
choices: [
|
|
98
|
-
{ name:
|
|
99
|
-
{ name:
|
|
102
|
+
{ name: "12 words (recommended) 🎯", value: 12 },
|
|
103
|
+
{ name: "24 words (more secure) 🔒", value: 24 },
|
|
100
104
|
],
|
|
101
105
|
default: 12,
|
|
102
106
|
},
|
|
103
107
|
]);
|
|
104
108
|
const seedPhrase = generateSeedPhrase(wordChoice.wordCount);
|
|
105
109
|
console.log();
|
|
106
|
-
console.log(chalk.bold.green(
|
|
107
|
-
console.log(chalk.yellow(
|
|
108
|
-
console.log(chalk.yellow(
|
|
109
|
-
console.log(chalk.bold(
|
|
110
|
+
console.log(chalk.bold.green("✨ Your new wallet is ready! ✨\n"));
|
|
111
|
+
console.log(chalk.yellow("⚠️ IMPORTANT: Write down your seed phrase and keep it safe!"));
|
|
112
|
+
console.log(chalk.yellow(" If you lose it, you will lose access to your wallet.\n"));
|
|
113
|
+
console.log(chalk.bold("Your seed phrase:"));
|
|
110
114
|
console.log(chalk.cyan.bold(seedPhrase));
|
|
111
115
|
console.log();
|
|
112
116
|
// Confirm they saved it
|
|
113
117
|
const confirmed = await inquirer.prompt([
|
|
114
118
|
{
|
|
115
|
-
type:
|
|
116
|
-
name:
|
|
117
|
-
message:
|
|
119
|
+
type: "confirm",
|
|
120
|
+
name: "saved",
|
|
121
|
+
message: "Have you written down your seed phrase?",
|
|
118
122
|
default: false,
|
|
119
123
|
},
|
|
120
124
|
]);
|
|
121
125
|
if (!confirmed.saved) {
|
|
122
126
|
console.log();
|
|
123
|
-
console.log(chalk.yellow(
|
|
124
|
-
throw new Error(
|
|
127
|
+
console.log(chalk.yellow("🐱 The cat wants you to be safe! Please write it down first."));
|
|
128
|
+
throw new Error("You must save your seed phrase before continuing.");
|
|
125
129
|
}
|
|
126
130
|
return seedPhrase;
|
|
127
131
|
}
|
|
@@ -130,23 +134,23 @@ export async function handleGenerateSeedPhrase() {
|
|
|
130
134
|
*/
|
|
131
135
|
export async function handleImportSeedPhrase() {
|
|
132
136
|
console.log();
|
|
133
|
-
console.log(chalk.bold.cyan(
|
|
137
|
+
console.log(chalk.bold.cyan("📥 Importing seed phrase...\n"));
|
|
134
138
|
const answers = await inquirer.prompt([
|
|
135
139
|
{
|
|
136
|
-
type:
|
|
137
|
-
name:
|
|
138
|
-
message:
|
|
140
|
+
type: "input",
|
|
141
|
+
name: "seedPhrase",
|
|
142
|
+
message: "Enter your seed phrase (12 or 24 words):",
|
|
139
143
|
validate: (input) => {
|
|
140
144
|
const trimmed = input.trim();
|
|
141
145
|
if (!trimmed) {
|
|
142
|
-
return
|
|
146
|
+
return "Seed phrase is required";
|
|
143
147
|
}
|
|
144
148
|
const words = trimmed.split(/\s+/);
|
|
145
149
|
if (words.length !== 12 && words.length !== 24) {
|
|
146
|
-
return
|
|
150
|
+
return "Seed phrase must be 12 or 24 words";
|
|
147
151
|
}
|
|
148
152
|
if (!validateSeedPhrase(trimmed)) {
|
|
149
|
-
return
|
|
153
|
+
return "Invalid seed phrase. Please check your words.";
|
|
150
154
|
}
|
|
151
155
|
return true;
|
|
152
156
|
},
|
|
@@ -159,36 +163,46 @@ export async function handleImportSeedPhrase() {
|
|
|
159
163
|
*/
|
|
160
164
|
async function handleImportPrivateKey() {
|
|
161
165
|
console.log();
|
|
162
|
-
console.log(chalk.bold.cyan(
|
|
166
|
+
console.log(chalk.bold.cyan("🔑 Importing private key...\n"));
|
|
163
167
|
// Custom mask function: show first 5 chars, then dots
|
|
164
168
|
const maskFunction = (input) => {
|
|
165
169
|
if (!input || input.length === 0)
|
|
166
|
-
return
|
|
170
|
+
return "";
|
|
167
171
|
if (input.length <= 5)
|
|
168
172
|
return input;
|
|
169
|
-
return input.substring(0, 5) +
|
|
173
|
+
return input.substring(0, 5) + "•".repeat(input.length - 5);
|
|
170
174
|
};
|
|
171
175
|
const answers = await inquirer.prompt([
|
|
172
176
|
{
|
|
173
|
-
type:
|
|
174
|
-
name:
|
|
175
|
-
message:
|
|
177
|
+
type: "password",
|
|
178
|
+
name: "privateKey",
|
|
179
|
+
message: "Enter your private key:",
|
|
176
180
|
mask: maskFunction,
|
|
177
181
|
validate: (input) => {
|
|
178
182
|
if (!input) {
|
|
179
|
-
return
|
|
183
|
+
return "Private key is required";
|
|
180
184
|
}
|
|
181
|
-
|
|
182
|
-
|
|
185
|
+
// Normalize: add 0x if missing for validation
|
|
186
|
+
const normalized = input.startsWith("0x") ? input : "0x" + input;
|
|
187
|
+
if (normalized.length !== 66) {
|
|
188
|
+
return "Private key must be 66 characters long (0x + 64 hex chars)";
|
|
183
189
|
}
|
|
184
|
-
|
|
185
|
-
|
|
190
|
+
// Validate hex characters
|
|
191
|
+
const hexPattern = /^0x[0-9a-fA-F]{64}$/;
|
|
192
|
+
if (!hexPattern.test(normalized)) {
|
|
193
|
+
return "Private key must contain only hexadecimal characters (0-9, a-f, A-F)";
|
|
186
194
|
}
|
|
187
195
|
return true;
|
|
188
196
|
},
|
|
189
197
|
},
|
|
190
198
|
]);
|
|
191
|
-
|
|
199
|
+
// Auto-prepend 0x if missing
|
|
200
|
+
let inputPrivateKey = answers.privateKey.trim();
|
|
201
|
+
if (!inputPrivateKey.startsWith("0x")) {
|
|
202
|
+
console.log(chalk.yellow("Adding 0x prefix..."));
|
|
203
|
+
inputPrivateKey = "0x" + inputPrivateKey;
|
|
204
|
+
}
|
|
205
|
+
return inputPrivateKey;
|
|
192
206
|
}
|
|
193
207
|
/**
|
|
194
208
|
* Prompt if user wants to add more accounts after importing private key
|
|
@@ -197,9 +211,9 @@ async function promptForAccountCreation() {
|
|
|
197
211
|
console.log();
|
|
198
212
|
const answers = await inquirer.prompt([
|
|
199
213
|
{
|
|
200
|
-
type:
|
|
201
|
-
name:
|
|
202
|
-
message:
|
|
214
|
+
type: "confirm",
|
|
215
|
+
name: "addMore",
|
|
216
|
+
message: "Want to add more accounts? Generate seed phrase?",
|
|
203
217
|
default: false,
|
|
204
218
|
},
|
|
205
219
|
]);
|
|
@@ -210,67 +224,78 @@ async function promptForAccountCreation() {
|
|
|
210
224
|
*/
|
|
211
225
|
async function promptForPassword() {
|
|
212
226
|
console.log();
|
|
213
|
-
console.log(chalk.
|
|
214
|
-
console.log(
|
|
215
|
-
console.log(chalk.dim(
|
|
216
|
-
console.log(chalk.dim(
|
|
227
|
+
console.log(chalk.bold.cyan("🔐 Password Protection (Optional)"));
|
|
228
|
+
console.log();
|
|
229
|
+
console.log(chalk.dim(" • Password protection is optional"));
|
|
230
|
+
console.log(chalk.dim(" • Press Enter to skip password (your keys will still be encrypted)"));
|
|
231
|
+
console.log(chalk.dim(" • If you set a password, you'll need it to unlock your wallet"));
|
|
232
|
+
console.log(chalk.dim(" for transactions (session timeout: 15 minutes)\n"));
|
|
217
233
|
const answers = await inquirer.prompt([
|
|
218
234
|
{
|
|
219
|
-
type:
|
|
220
|
-
name:
|
|
221
|
-
message:
|
|
222
|
-
mask:
|
|
235
|
+
type: "password",
|
|
236
|
+
name: "password",
|
|
237
|
+
message: "Enter password (optional - press Enter to skip):",
|
|
238
|
+
mask: "•",
|
|
223
239
|
},
|
|
224
240
|
{
|
|
225
|
-
type:
|
|
226
|
-
name:
|
|
227
|
-
message:
|
|
228
|
-
mask:
|
|
229
|
-
when: (answers) => answers.password !==
|
|
241
|
+
type: "password",
|
|
242
|
+
name: "confirmPassword",
|
|
243
|
+
message: "Confirm password (or press Enter to skip):",
|
|
244
|
+
mask: "•",
|
|
245
|
+
when: (answers) => answers.password !== "",
|
|
230
246
|
},
|
|
231
247
|
]);
|
|
232
248
|
if (answers.password) {
|
|
233
249
|
if (answers.password !== answers.confirmPassword) {
|
|
234
|
-
throw new Error(
|
|
250
|
+
throw new Error("Passwords do not match");
|
|
235
251
|
}
|
|
236
252
|
return answers.password;
|
|
237
253
|
}
|
|
238
|
-
return
|
|
254
|
+
return "";
|
|
239
255
|
}
|
|
240
256
|
/**
|
|
241
257
|
* Save wallet configuration
|
|
242
258
|
*/
|
|
243
259
|
async function saveWalletConfig(seedPhrase, privateKey, password, activeAccountIndex) {
|
|
244
260
|
console.log();
|
|
245
|
-
console.log(chalk.dim(
|
|
261
|
+
console.log(chalk.dim("💾 Saving configuration...\n"));
|
|
246
262
|
// Set password
|
|
247
263
|
config.setPassword(password);
|
|
248
|
-
// Save
|
|
264
|
+
// Save private key first if provided (Account 0)
|
|
265
|
+
// This must be done before seed phrase to ensure Account 0 exists first
|
|
266
|
+
if (privateKey) {
|
|
267
|
+
config.setEncryptedPrivateKey(privateKey, password);
|
|
268
|
+
const account0Address = getAddressFromPrivateKey(privateKey);
|
|
269
|
+
const existingAccounts = config.getAllAccounts();
|
|
270
|
+
const account0Exists = existingAccounts.some((acc) => acc.index === 0);
|
|
271
|
+
if (!account0Exists) {
|
|
272
|
+
config.addAccount({
|
|
273
|
+
type: "custom",
|
|
274
|
+
index: 0,
|
|
275
|
+
address: account0Address,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
console.log(chalk.green("✓ Private key saved"));
|
|
279
|
+
console.log(chalk.dim(` Account 0: ${formatAddress(account0Address, 12)}\n`));
|
|
280
|
+
}
|
|
281
|
+
// Save seed phrase if provided (Account 1)
|
|
249
282
|
if (seedPhrase) {
|
|
250
283
|
config.setEncryptedSeedPhrase(seedPhrase, password);
|
|
251
284
|
// Create Account 1 (first seed-derived account)
|
|
252
285
|
const account1PrivateKey = seedPhraseToPrivateKey(seedPhrase, 0);
|
|
253
286
|
const account1Address = getAddressFromPrivateKey(account1PrivateKey);
|
|
254
|
-
config.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
287
|
+
const existingAccounts = config.getAllAccounts();
|
|
288
|
+
const account1Exists = existingAccounts.some((acc) => acc.index === 1);
|
|
289
|
+
if (!account1Exists) {
|
|
290
|
+
config.addAccount({
|
|
291
|
+
type: "seed",
|
|
292
|
+
index: 1,
|
|
293
|
+
address: account1Address,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
console.log(chalk.green("✓ Seed phrase saved"));
|
|
260
297
|
console.log(chalk.dim(` Account 1: ${formatAddress(account1Address, 12)}\n`));
|
|
261
298
|
}
|
|
262
|
-
// Save private key if provided (Account 0)
|
|
263
|
-
if (privateKey) {
|
|
264
|
-
config.setEncryptedPrivateKey(privateKey, password);
|
|
265
|
-
const account0Address = getAddressFromPrivateKey(privateKey);
|
|
266
|
-
config.addAccount({
|
|
267
|
-
type: 'custom',
|
|
268
|
-
index: 0,
|
|
269
|
-
address: account0Address,
|
|
270
|
-
});
|
|
271
|
-
console.log(chalk.green('✓ Private key saved'));
|
|
272
|
-
console.log(chalk.dim(` Account 0: ${formatAddress(account0Address, 12)}\n`));
|
|
273
|
-
}
|
|
274
299
|
// Set active account
|
|
275
300
|
config.setActiveAccount(activeAccountIndex);
|
|
276
301
|
// Show balances for active account
|
|
@@ -278,75 +303,229 @@ async function saveWalletConfig(seedPhrase, privateKey, password, activeAccountI
|
|
|
278
303
|
if (activeAccount) {
|
|
279
304
|
const activePrivateKey = config.getAccountPrivateKey(activeAccountIndex);
|
|
280
305
|
await showAccountBalances(activeAccount.address, activePrivateKey);
|
|
306
|
+
console.log(chalk.dim(" Config saved to:"), chalk.cyan(config.getConfigPath()));
|
|
307
|
+
console.log(chalk.green("✓ Configuration saved!"));
|
|
308
|
+
console.log();
|
|
309
|
+
console.log(chalk.dim("🔐 Remember: Your keys stay on your machine."));
|
|
310
|
+
console.log(chalk.dim(" They are never transmitted to any server or third party.\n"));
|
|
311
|
+
// MCP Integration Step:
|
|
312
|
+
// After successfully saving the wallet configuration, we:
|
|
313
|
+
// 1. Create the base MCP config file (~/.config/httpcat/mcp.json)
|
|
314
|
+
// 2. Detect installed LLM CLI tools that support MCP
|
|
315
|
+
// 3. Prompt user to select which tools to configure
|
|
316
|
+
// 4. Configure selected tools with the private key
|
|
317
|
+
// Step 1: Create base MCP configuration file
|
|
318
|
+
// This file serves as a reference and can be used by MCP clients
|
|
319
|
+
// Note: No private key needed - MCP server reads from config file
|
|
320
|
+
try {
|
|
321
|
+
createMcpConfig();
|
|
322
|
+
console.log(chalk.green("✓ MCP configuration file created"));
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
// Non-fatal error - continue with wizard even if MCP config creation fails
|
|
326
|
+
console.log(chalk.yellow("⚠️ Failed to create MCP config file"));
|
|
327
|
+
}
|
|
328
|
+
// Step 2 & 3: Detect and configure LLM CLI tools
|
|
329
|
+
// This will:
|
|
330
|
+
// - Scan for installed LLM CLI tools (Claude Desktop, Cursor, Codex, Gemini, etc.)
|
|
331
|
+
// - Show user a selection interface if tools are found
|
|
332
|
+
// - Configure selected tools with the httpcat MCP server
|
|
333
|
+
// Note: No private key needed - MCP server reads from config file
|
|
334
|
+
await promptForMcpIntegration();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Prompt for MCP integration with LLM CLI tools
|
|
339
|
+
*
|
|
340
|
+
* This function is called after wallet configuration is complete. It:
|
|
341
|
+
* 1. Detects installed LLM CLI tools that support MCP integration
|
|
342
|
+
* 2. Shows user a selection interface (checkbox) if tools are found
|
|
343
|
+
* 3. Configures each selected tool with the httpcat MCP server
|
|
344
|
+
* 4. Shows success/failure results for each configuration
|
|
345
|
+
*
|
|
346
|
+
* Flow:
|
|
347
|
+
* - If no LLM tools detected: Skip silently (no user interaction needed)
|
|
348
|
+
* - If tools detected: Show selection prompt
|
|
349
|
+
* - If user selects tools: Configure each one
|
|
350
|
+
* - Show results: Success (✓) or failure (✗) for each tool
|
|
351
|
+
*
|
|
352
|
+
* Error Handling:
|
|
353
|
+
* - All errors are caught and logged, but don't break the wizard
|
|
354
|
+
* - Individual tool failures don't stop other tools from being configured
|
|
355
|
+
* - If the entire step fails, it's skipped silently
|
|
356
|
+
*
|
|
357
|
+
* Note: No private key needed - MCP server reads from config file instead.
|
|
358
|
+
*/
|
|
359
|
+
async function promptForMcpIntegration() {
|
|
360
|
+
try {
|
|
361
|
+
// Step 1: Detect installed LLM CLI tools
|
|
362
|
+
// Scans system for: Claude Desktop, Cursor, Codex, Gemini, LLM Tools, MCP-Use, MCP Client
|
|
363
|
+
const detectedLlms = await detectInstalledLlms();
|
|
364
|
+
// If no LLM tools found, skip this step silently
|
|
365
|
+
// User can manually configure later if needed
|
|
366
|
+
if (detectedLlms.length === 0) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
// Step 2: Show user selection interface
|
|
370
|
+
console.log();
|
|
371
|
+
console.log(chalk.cyan("🔌 LLM CLI Integration"));
|
|
372
|
+
console.log(chalk.dim(` Found ${detectedLlms.length} LLM CLI tool(s) that support MCP integration.\n`));
|
|
373
|
+
// Present checkbox selection to user
|
|
374
|
+
// Each option shows: Tool name + config file path
|
|
375
|
+
const selection = await inquirer.prompt([
|
|
376
|
+
{
|
|
377
|
+
type: "checkbox",
|
|
378
|
+
name: "selectedLlms",
|
|
379
|
+
message: "Which LLM CLI tools would you like to configure with httpcat MCP?",
|
|
380
|
+
choices: detectedLlms.map((llm) => ({
|
|
381
|
+
name: `${llm.name} ${chalk.dim(`(${llm.configPath})`)}`,
|
|
382
|
+
value: llm.id,
|
|
383
|
+
})),
|
|
384
|
+
},
|
|
385
|
+
]);
|
|
386
|
+
// If user selected nothing, skip configuration
|
|
387
|
+
if (!selection.selectedLlms || selection.selectedLlms.length === 0) {
|
|
388
|
+
console.log(chalk.dim(" Skipping LLM CLI integration.\n"));
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
// Step 3: Configure selected LLM tools
|
|
392
|
+
console.log();
|
|
393
|
+
console.log(chalk.dim("⚙️ Configuring selected LLM CLI tools...\n"));
|
|
394
|
+
// Track results for each tool configuration
|
|
395
|
+
const results = [];
|
|
396
|
+
// Configure each selected tool
|
|
397
|
+
for (const llmId of selection.selectedLlms) {
|
|
398
|
+
const llm = detectedLlms.find((l) => l.id === llmId);
|
|
399
|
+
if (!llm)
|
|
400
|
+
continue; // Skip if LLM not found (shouldn't happen)
|
|
401
|
+
try {
|
|
402
|
+
// Call appropriate configuration function for this LLM tool
|
|
403
|
+
// Each function handles its own format (JSON, TOML, extension JSON, CLI commands)
|
|
404
|
+
// Note: No private key needed - MCP server reads from config file
|
|
405
|
+
const success = await configureLLM(llm);
|
|
406
|
+
results.push({
|
|
407
|
+
name: llm.name,
|
|
408
|
+
success,
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
// Catch and log errors for individual tools
|
|
413
|
+
// Don't let one failure stop others from being configured
|
|
414
|
+
results.push({
|
|
415
|
+
name: llm.name,
|
|
416
|
+
success: false,
|
|
417
|
+
error: error?.message || "Unknown error",
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
// Step 4: Show configuration results
|
|
422
|
+
console.log();
|
|
423
|
+
for (const result of results) {
|
|
424
|
+
if (result.success) {
|
|
425
|
+
console.log(chalk.green(`✓ ${result.name} configured successfully`));
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
console.log(chalk.red(`✗ ${result.name} configuration failed`));
|
|
429
|
+
if (result.error) {
|
|
430
|
+
console.log(chalk.dim(` Error: ${result.error}`));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
console.log();
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
// If entire step fails, skip silently
|
|
438
|
+
// Don't break the setup wizard for MCP integration issues
|
|
439
|
+
console.log(chalk.dim(" MCP integration step skipped.\n"));
|
|
281
440
|
}
|
|
282
|
-
console.log(chalk.dim(' Config saved to:'), chalk.cyan(config.getConfigPath()));
|
|
283
|
-
console.log(chalk.green('✓ Configuration saved!'));
|
|
284
|
-
console.log();
|
|
285
|
-
console.log(chalk.dim('🔐 Remember: Your keys stay on your machine.'));
|
|
286
|
-
console.log(chalk.dim(' They are never transmitted to any server or third party.\n'));
|
|
287
441
|
}
|
|
288
442
|
/**
|
|
289
443
|
* Show account balances
|
|
290
444
|
*/
|
|
291
445
|
async function showAccountBalances(address, privateKey) {
|
|
292
|
-
|
|
446
|
+
// Get network configuration
|
|
447
|
+
const network = config.get("network");
|
|
448
|
+
const networkDisplayName = config.caip2ToNetwork(network);
|
|
449
|
+
// Format network name for display (base-sepolia -> Base Sepolia, base -> Base)
|
|
450
|
+
const networkName = networkDisplayName === "base-sepolia"
|
|
451
|
+
? "Base Sepolia"
|
|
452
|
+
: networkDisplayName === "base"
|
|
453
|
+
? "Base"
|
|
454
|
+
: networkDisplayName;
|
|
455
|
+
console.log(chalk.dim(`💰 Checking balances on ${networkName}...\n`));
|
|
293
456
|
try {
|
|
294
|
-
// Get network configuration
|
|
295
|
-
const network = config.get("network");
|
|
296
457
|
const { chain, usdcAddress } = await getNetworkConfig(network);
|
|
297
458
|
// Create signer using viem for balance checks
|
|
298
|
-
const { createPublicClient,
|
|
459
|
+
const { createPublicClient, parseAbi, formatUnits } = await import("viem");
|
|
460
|
+
const { createRpcTransport } = await import("./rpc-transport.js");
|
|
299
461
|
const publicClient = createPublicClient({
|
|
300
462
|
chain,
|
|
301
|
-
transport:
|
|
463
|
+
transport: createRpcTransport({
|
|
464
|
+
chainId: chain.id,
|
|
465
|
+
// HttpcatClient not available in this context, will use public/Alchemy RPC
|
|
466
|
+
}),
|
|
467
|
+
});
|
|
468
|
+
// Check ETH balance with retry logic for network failures
|
|
469
|
+
const ethBalance = await retryWithBackoff(() => publicClient.getBalance({
|
|
470
|
+
address: address,
|
|
471
|
+
}), {
|
|
472
|
+
maxRetries: 3,
|
|
473
|
+
initialDelay: 500,
|
|
474
|
+
maxDelay: 3000,
|
|
302
475
|
});
|
|
303
|
-
// Check ETH balance
|
|
304
|
-
const ethBalance = await publicClient.getBalance({ address: address });
|
|
305
476
|
const ethFormatted = formatEther(ethBalance);
|
|
306
|
-
// Check USDC balance using ERC20 token contract
|
|
477
|
+
// Check USDC balance using ERC20 token contract with retry logic
|
|
307
478
|
const ERC20_ABI = parseAbi([
|
|
308
479
|
"function balanceOf(address owner) view returns (uint256)",
|
|
309
480
|
"function decimals() view returns (uint8)",
|
|
310
481
|
]);
|
|
311
482
|
const [usdcBalance, decimals] = await Promise.all([
|
|
312
|
-
publicClient.readContract({
|
|
483
|
+
retryWithBackoff(() => publicClient.readContract({
|
|
313
484
|
address: usdcAddress,
|
|
314
485
|
abi: ERC20_ABI,
|
|
315
486
|
functionName: "balanceOf",
|
|
316
487
|
args: [address],
|
|
488
|
+
}), {
|
|
489
|
+
maxRetries: 3,
|
|
490
|
+
initialDelay: 500,
|
|
491
|
+
maxDelay: 3000,
|
|
317
492
|
}).catch(() => BigInt(0)),
|
|
318
|
-
publicClient.readContract({
|
|
493
|
+
retryWithBackoff(() => publicClient.readContract({
|
|
319
494
|
address: usdcAddress,
|
|
320
495
|
abi: ERC20_ABI,
|
|
321
496
|
functionName: "decimals",
|
|
497
|
+
}), {
|
|
498
|
+
maxRetries: 3,
|
|
499
|
+
initialDelay: 500,
|
|
500
|
+
maxDelay: 3000,
|
|
322
501
|
}).catch(() => 6), // Default to 6 decimals for USDC
|
|
323
502
|
]);
|
|
324
|
-
const usdcFormatted =
|
|
503
|
+
const usdcFormatted = Number(formatUnits(usdcBalance, decimals)).toFixed(2);
|
|
325
504
|
// Display balances
|
|
326
|
-
console.log(chalk.dim(
|
|
327
|
-
console.log(chalk.dim(
|
|
505
|
+
console.log(chalk.dim(" ETH: "), chalk.yellow(`${ethFormatted} ETH`));
|
|
506
|
+
console.log(chalk.dim(" USDC:"), chalk.green(`$${usdcFormatted} USDC`));
|
|
328
507
|
console.log();
|
|
329
508
|
// Show warnings if balances are low
|
|
330
509
|
const ethNum = Number(ethFormatted);
|
|
331
510
|
const usdcNum = Number(usdcFormatted);
|
|
332
511
|
if (ethNum < 0.001 && usdcNum < 1) {
|
|
333
|
-
printWarning(
|
|
334
|
-
console.log(chalk.dim(
|
|
335
|
-
console.log(chalk.dim(
|
|
512
|
+
printWarning("Low balances detected!");
|
|
513
|
+
console.log(chalk.dim(` You need ${networkName} ETH for gas fees`));
|
|
514
|
+
console.log(chalk.dim(` You need ${networkName} USDC for trading\n`));
|
|
336
515
|
}
|
|
337
516
|
else if (ethNum < 0.001) {
|
|
338
|
-
printWarning(
|
|
517
|
+
printWarning("Low ETH balance - you may not have enough for gas fees\n");
|
|
339
518
|
}
|
|
340
519
|
else if (usdcNum < 1) {
|
|
341
|
-
printWarning(
|
|
520
|
+
printWarning("Low USDC balance - you may not have enough for trades\n");
|
|
342
521
|
}
|
|
343
|
-
console.log(chalk.yellow(
|
|
344
|
-
console.log(chalk.dim(
|
|
345
|
-
console.log(chalk.dim(
|
|
522
|
+
console.log(chalk.yellow("⚠️ Important:"));
|
|
523
|
+
console.log(chalk.dim(` Ensure you have ${networkName} ETH (for gas fees)`));
|
|
524
|
+
console.log(chalk.dim(` and ${networkName} USDC (for trading) in this wallet!\n`));
|
|
346
525
|
}
|
|
347
526
|
catch (error) {
|
|
348
|
-
console.log(chalk.yellow(
|
|
349
|
-
console.log(chalk.dim(
|
|
527
|
+
console.log(chalk.yellow("⚠️ Could not check balances (network may be slow)"));
|
|
528
|
+
console.log(chalk.dim(` Make sure you have ${networkName} ETH and USDC!\n`));
|
|
350
529
|
}
|
|
351
530
|
}
|
|
352
531
|
/**
|
|
@@ -356,9 +535,9 @@ export function formatEthBalance(wei) {
|
|
|
356
535
|
const eth = formatEther(wei);
|
|
357
536
|
const num = parseFloat(eth);
|
|
358
537
|
if (num === 0)
|
|
359
|
-
return
|
|
538
|
+
return "0 ETH";
|
|
360
539
|
if (num < 0.0001)
|
|
361
|
-
return
|
|
540
|
+
return "< 0.0001 ETH";
|
|
362
541
|
return `${num.toFixed(4)} ETH`;
|
|
363
542
|
}
|
|
364
543
|
/**
|