httpcat-cli 0.0.27 → 0.1.1-rc.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/dependabot.yml +2 -0
- package/.github/workflows/README.md +37 -4
- package/.github/workflows/ci.yml +31 -20
- package/.github/workflows/homebrew-tap.yml +1 -1
- package/.github/workflows/publish-switch.yml +41 -0
- package/.github/workflows/rc-publish.yml +196 -0
- package/.github/workflows/release.yml +267 -85
- package/README.md +107 -108
- package/bun.lock +2933 -0
- package/dist/commands/account.d.ts.map +1 -1
- package/dist/commands/account.js +14 -7
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/balances.d.ts.map +1 -0
- package/dist/commands/balances.js +171 -0
- package/dist/commands/balances.js.map +1 -0
- package/dist/commands/buy.d.ts.map +1 -1
- package/dist/commands/buy.js +743 -35
- package/dist/commands/buy.js.map +1 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +467 -906
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/claim.d.ts.map +1 -0
- package/dist/commands/claim.js +65 -0
- package/dist/commands/claim.js.map +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +0 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/info.d.ts.map +1 -1
- package/dist/commands/info.js +143 -38
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +31 -27
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/positions.d.ts.map +1 -1
- package/dist/commands/positions.js +178 -106
- package/dist/commands/positions.js.map +1 -1
- package/dist/commands/sell.d.ts.map +1 -1
- package/dist/commands/sell.js +720 -28
- package/dist/commands/sell.js.map +1 -1
- package/dist/index.js +321 -104
- package/dist/index.js.map +1 -1
- package/dist/interactive/shell.d.ts.map +1 -1
- package/dist/interactive/shell.js +328 -179
- package/dist/interactive/shell.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +8 -8
- package/dist/mcp/tools.js.map +1 -1
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +66 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils/formatting.js +3 -5
- package/dist/utils/formatting.js.map +1 -1
- package/dist/utils/token-resolver.d.ts.map +1 -1
- package/dist/utils/token-resolver.js +70 -68
- package/dist/utils/token-resolver.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +4 -3
- package/dist/utils/validation.js.map +1 -1
- package/jest.config.js +1 -1
- package/package.json +19 -13
- package/tests/README.md +0 -1
- package/.claude/settings.local.json +0 -41
- package/dist/commands/balance.d.ts.map +0 -1
- package/dist/commands/balance.js +0 -112
- package/dist/commands/balance.js.map +0 -1
- package/homebrew-httpcat/Formula/httpcat.rb +0 -18
- package/homebrew-httpcat/README.md +0 -31
- package/homebrew-httpcat/homebrew-httpcat/Formula/httpcat.rb +0 -18
- package/homebrew-httpcat/homebrew-httpcat/README.md +0 -31
|
@@ -1,99 +1,193 @@
|
|
|
1
|
-
import { createInterface } from "readline";
|
|
2
1
|
import chalk from "chalk";
|
|
3
|
-
|
|
2
|
+
// @ts-ignore - neo-blessed doesn't have types, but @types/blessed provides compatible types
|
|
3
|
+
import blessed from "neo-blessed";
|
|
4
4
|
import { config } from "../config.js";
|
|
5
|
-
import {
|
|
6
|
-
import { handleError } from "../utils/errors.js";
|
|
7
|
-
import { withLoading } from "../utils/loading.js";
|
|
5
|
+
import { printCat } from "./art.js";
|
|
8
6
|
import { validateAmount } from "../utils/validation.js";
|
|
9
7
|
// Import commands
|
|
10
|
-
import { createToken
|
|
11
|
-
import { buyToken,
|
|
12
|
-
import { sellToken,
|
|
13
|
-
import { getTokenInfo
|
|
14
|
-
import { listTokens
|
|
15
|
-
import { getPositions
|
|
8
|
+
import { createToken } from "../commands/create.js";
|
|
9
|
+
import { buyToken, TEST_AMOUNTS, PROD_AMOUNTS } from "../commands/buy.js";
|
|
10
|
+
import { sellToken, parseTokenAmount } from "../commands/sell.js";
|
|
11
|
+
import { getTokenInfo } from "../commands/info.js";
|
|
12
|
+
import { listTokens } from "../commands/list.js";
|
|
13
|
+
import { getPositions } from "../commands/positions.js";
|
|
16
14
|
import { privateKeyToAccount } from "viem/accounts";
|
|
17
|
-
import { checkHealth
|
|
15
|
+
import { checkHealth } from "../commands/health.js";
|
|
18
16
|
import { startChatStream } from "../commands/chat.js";
|
|
19
|
-
import { checkBalance
|
|
17
|
+
import { checkBalance } from "../commands/balances.js";
|
|
20
18
|
export async function startInteractiveShell(client) {
|
|
21
|
-
//
|
|
22
|
-
|
|
19
|
+
// Create blessed screen
|
|
20
|
+
const screen = blessed.screen({
|
|
21
|
+
smartCSR: true,
|
|
22
|
+
title: "httpcat Interactive Shell",
|
|
23
|
+
fullUnicode: true,
|
|
24
|
+
});
|
|
23
25
|
const network = client.getNetwork();
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
// Create header box
|
|
27
|
+
const headerBox = blessed.box({
|
|
28
|
+
top: 0,
|
|
29
|
+
left: 0,
|
|
30
|
+
width: "100%",
|
|
31
|
+
height: 8,
|
|
32
|
+
content: "",
|
|
33
|
+
tags: false,
|
|
34
|
+
style: {
|
|
35
|
+
fg: "white",
|
|
36
|
+
bg: "black",
|
|
37
|
+
},
|
|
38
|
+
padding: {
|
|
39
|
+
left: 1,
|
|
40
|
+
right: 1,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
// Build welcome content
|
|
44
|
+
const welcomeLines = [];
|
|
45
|
+
welcomeLines.push(" /\\_/\\");
|
|
46
|
+
welcomeLines.push(" ( ^.^ )");
|
|
47
|
+
welcomeLines.push(" > ^ <");
|
|
48
|
+
welcomeLines.push("");
|
|
49
|
+
welcomeLines.push("Welcome to httpcat!");
|
|
50
|
+
welcomeLines.push(`Connected to: ${network}`);
|
|
51
|
+
welcomeLines.push('Type "help" for available commands or "exit" to quit');
|
|
52
|
+
headerBox.setContent(welcomeLines.join("\n"));
|
|
53
|
+
// Create output log box (scrollable)
|
|
54
|
+
const outputBox = blessed.log({
|
|
55
|
+
top: 8,
|
|
56
|
+
left: 0,
|
|
57
|
+
width: "100%",
|
|
58
|
+
height: "100%-11",
|
|
59
|
+
tags: true,
|
|
60
|
+
scrollable: true,
|
|
61
|
+
alwaysScroll: true,
|
|
62
|
+
scrollbar: {
|
|
63
|
+
ch: " ",
|
|
64
|
+
inverse: true,
|
|
65
|
+
},
|
|
66
|
+
style: {
|
|
67
|
+
fg: "white",
|
|
68
|
+
bg: "black",
|
|
69
|
+
},
|
|
70
|
+
padding: {
|
|
71
|
+
left: 1,
|
|
72
|
+
right: 1,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
// Create input box at bottom
|
|
76
|
+
const inputBox = blessed.textbox({
|
|
77
|
+
bottom: 0,
|
|
78
|
+
left: 0,
|
|
79
|
+
width: "100%",
|
|
80
|
+
height: 3,
|
|
81
|
+
inputOnFocus: true,
|
|
82
|
+
keys: true,
|
|
83
|
+
style: {
|
|
84
|
+
fg: "cyan",
|
|
85
|
+
bg: "black",
|
|
86
|
+
focus: {
|
|
87
|
+
fg: "white",
|
|
88
|
+
bg: "blue",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
padding: {
|
|
92
|
+
left: 1,
|
|
93
|
+
right: 1,
|
|
94
|
+
},
|
|
29
95
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
96
|
+
// Create a prompt label
|
|
97
|
+
const promptLabel = blessed.text({
|
|
98
|
+
bottom: 1,
|
|
99
|
+
left: 1,
|
|
100
|
+
content: "httpcat> ",
|
|
101
|
+
style: {
|
|
102
|
+
fg: "cyan",
|
|
103
|
+
bg: "black",
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
// Append all widgets
|
|
107
|
+
screen.append(headerBox);
|
|
108
|
+
screen.append(outputBox);
|
|
109
|
+
screen.append(promptLabel);
|
|
110
|
+
screen.append(inputBox);
|
|
111
|
+
// Helper to log output
|
|
112
|
+
const log = (text) => {
|
|
113
|
+
outputBox.log(text);
|
|
114
|
+
outputBox.setScrollPerc(100);
|
|
115
|
+
screen.render();
|
|
116
|
+
};
|
|
117
|
+
// Helper to log multiple lines
|
|
118
|
+
const logLines = (lines) => {
|
|
119
|
+
lines.forEach((line) => outputBox.log(line));
|
|
120
|
+
outputBox.setScrollPerc(100);
|
|
121
|
+
screen.render();
|
|
122
|
+
};
|
|
123
|
+
// Handle input submission
|
|
124
|
+
inputBox.on("submit", async (value) => {
|
|
125
|
+
const trimmed = value.trim();
|
|
126
|
+
inputBox.clearValue();
|
|
36
127
|
if (!trimmed) {
|
|
37
|
-
|
|
128
|
+
inputBox.focus();
|
|
129
|
+
screen.render();
|
|
38
130
|
return;
|
|
39
131
|
}
|
|
132
|
+
log(`httpcat> ${trimmed}`);
|
|
40
133
|
const [command, ...args] = trimmed.split(/\s+/);
|
|
41
|
-
// Pause readline to prevent input during command execution
|
|
42
|
-
rl.pause();
|
|
43
134
|
try {
|
|
44
|
-
await handleCommand(client, command.toLowerCase(), args,
|
|
135
|
+
await handleCommand(client, command.toLowerCase(), args, log, logLines, screen, inputBox);
|
|
45
136
|
}
|
|
46
137
|
catch (error) {
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
finally {
|
|
50
|
-
// Always resume readline after command completes
|
|
51
|
-
rl.resume();
|
|
138
|
+
log(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
52
139
|
}
|
|
53
|
-
|
|
54
|
-
|
|
140
|
+
log(""); // Empty line after command output
|
|
141
|
+
inputBox.focus();
|
|
142
|
+
screen.render();
|
|
55
143
|
});
|
|
56
|
-
|
|
57
|
-
|
|
144
|
+
// Handle Ctrl+C
|
|
145
|
+
screen.key(["C-c"], () => {
|
|
146
|
+
screen.destroy();
|
|
58
147
|
printCat("sleeping");
|
|
59
148
|
console.log(chalk.cyan("Goodbye! 👋"));
|
|
60
149
|
process.exit(0);
|
|
61
150
|
});
|
|
151
|
+
// Handle escape to clear input
|
|
152
|
+
inputBox.key(["escape"], () => {
|
|
153
|
+
inputBox.clearValue();
|
|
154
|
+
screen.render();
|
|
155
|
+
});
|
|
156
|
+
// Focus input and render
|
|
157
|
+
inputBox.focus();
|
|
158
|
+
screen.render();
|
|
62
159
|
}
|
|
63
|
-
async function handleCommand(client, command, args,
|
|
160
|
+
async function handleCommand(client, command, args, log, logLines, screen, inputBox) {
|
|
64
161
|
switch (command) {
|
|
65
162
|
case "help":
|
|
66
|
-
displayHelp();
|
|
163
|
+
displayHelp(log, logLines);
|
|
67
164
|
break;
|
|
68
165
|
case "create": {
|
|
69
166
|
if (args.length < 2) {
|
|
70
|
-
|
|
167
|
+
log(chalk.red("Usage: create <name> <symbol> [--photo URL] [--banner URL] [--website URL]"));
|
|
71
168
|
return;
|
|
72
169
|
}
|
|
73
170
|
const [name, symbol] = args;
|
|
74
171
|
const photoUrl = extractFlag(args, "--photo");
|
|
75
172
|
const bannerUrl = extractFlag(args, "--banner");
|
|
76
173
|
const websiteUrl = extractFlag(args, "--website");
|
|
77
|
-
|
|
174
|
+
log(chalk.dim("Creating token..."));
|
|
175
|
+
screen.render();
|
|
176
|
+
const result = await createToken(client, {
|
|
78
177
|
name,
|
|
79
178
|
symbol,
|
|
80
179
|
photoUrl,
|
|
81
180
|
bannerUrl,
|
|
82
181
|
websiteUrl,
|
|
83
|
-
}), {
|
|
84
|
-
message: "Creating token...",
|
|
85
|
-
json: false,
|
|
86
|
-
quiet: false,
|
|
87
|
-
spinner: "cat",
|
|
88
182
|
});
|
|
89
|
-
|
|
183
|
+
displayCreateResultToLog(result, log, logLines);
|
|
90
184
|
break;
|
|
91
185
|
}
|
|
92
186
|
case "buy": {
|
|
93
187
|
if (args.length < 2) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
188
|
+
log(chalk.red("Usage: buy <address|name|symbol> <amount>"));
|
|
189
|
+
log(chalk.dim(" amount: 0.05, 0.10, or 0.20 (test mode) or 50, 100, 200 (production)"));
|
|
190
|
+
log(chalk.dim(' Examples: buy 0x1234... 0.20, buy "My Token" 0.10, buy MTK 0.05'));
|
|
97
191
|
return;
|
|
98
192
|
}
|
|
99
193
|
const [identifier, amountInput] = args;
|
|
@@ -105,183 +199,158 @@ async function handleCommand(client, command, args, rl) {
|
|
|
105
199
|
amount = validateAmount(amountInput, validAmounts, isTestMode);
|
|
106
200
|
}
|
|
107
201
|
catch (error) {
|
|
108
|
-
// Validation failed -
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
{
|
|
113
|
-
type: 'list',
|
|
114
|
-
name: 'amount',
|
|
115
|
-
message: 'Please select a valid amount:',
|
|
116
|
-
choices: validAmounts.map(amt => ({
|
|
117
|
-
name: `$${amt} USDC`,
|
|
118
|
-
value: amt
|
|
119
|
-
}))
|
|
120
|
-
}
|
|
121
|
-
]);
|
|
122
|
-
amount = answer.amount;
|
|
202
|
+
// Validation failed - show error and return
|
|
203
|
+
log(chalk.yellow(`Invalid amount: ${amountInput}`));
|
|
204
|
+
log(chalk.dim(`Valid amounts: ${validAmounts.join(", ")}`));
|
|
205
|
+
return;
|
|
123
206
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
spinner: "cat",
|
|
129
|
-
});
|
|
130
|
-
displayBuyResult(result);
|
|
207
|
+
log(chalk.dim("Buying tokens..."));
|
|
208
|
+
screen.render();
|
|
209
|
+
const result = await buyToken(client, identifier, amount, isTestMode, false);
|
|
210
|
+
displayBuyResultToLog(result, log, logLines);
|
|
131
211
|
break;
|
|
132
212
|
}
|
|
133
213
|
case "sell": {
|
|
134
214
|
if (args.length < 2) {
|
|
135
|
-
|
|
136
|
-
|
|
215
|
+
log(chalk.red("Usage: sell <address|name|symbol> <amount|percentage|all>"));
|
|
216
|
+
log(chalk.dim(' Examples: sell 0x1234... 1000, sell "My Token" 50%, sell MTK all'));
|
|
137
217
|
return;
|
|
138
218
|
}
|
|
139
219
|
const [identifier, amountInput] = args;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
json: false,
|
|
144
|
-
quiet: false,
|
|
145
|
-
spinner: "cat",
|
|
146
|
-
});
|
|
220
|
+
log(chalk.dim("Checking token info..."));
|
|
221
|
+
screen.render();
|
|
222
|
+
const info = await getTokenInfo(client, identifier);
|
|
147
223
|
if (!info.userPosition || info.userPosition.tokensOwned === "0") {
|
|
148
|
-
|
|
224
|
+
log(chalk.yellow("You do not own any of this token."));
|
|
149
225
|
return;
|
|
150
226
|
}
|
|
151
227
|
const tokenAmount = parseTokenAmount(amountInput, info.userPosition.tokensOwned);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
spinner: "cat",
|
|
157
|
-
});
|
|
158
|
-
displaySellResult(result);
|
|
228
|
+
log(chalk.dim("Selling tokens..."));
|
|
229
|
+
screen.render();
|
|
230
|
+
const result = await sellToken(client, identifier, tokenAmount, false);
|
|
231
|
+
displaySellResultToLog(result, log, logLines);
|
|
159
232
|
break;
|
|
160
233
|
}
|
|
161
234
|
case "info": {
|
|
162
235
|
if (args.length < 1) {
|
|
163
|
-
|
|
164
|
-
|
|
236
|
+
log(chalk.red("Usage: info <address|name|symbol>"));
|
|
237
|
+
log(chalk.dim(' Examples: info 0x1234..., info "My Token", info MTK'));
|
|
165
238
|
return;
|
|
166
239
|
}
|
|
167
240
|
const [identifier] = args;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
241
|
+
// Get user address from private key for balance checking
|
|
242
|
+
const privateKey = config.getPrivateKey();
|
|
243
|
+
const account = privateKeyToAccount(privateKey);
|
|
244
|
+
const userAddress = account.address;
|
|
245
|
+
log(chalk.dim("Fetching token info..."));
|
|
246
|
+
screen.render();
|
|
247
|
+
const info = await getTokenInfo(client, identifier, userAddress);
|
|
248
|
+
displayTokenInfoToLog(info, log, logLines);
|
|
175
249
|
break;
|
|
176
250
|
}
|
|
177
251
|
case "list": {
|
|
178
252
|
const page = parseInt(extractFlag(args, "--page") || "1");
|
|
179
253
|
const limit = parseInt(extractFlag(args, "--limit") || "20");
|
|
180
254
|
const sortBy = (extractFlag(args, "--sort") || "mcap");
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
spinner: "cat",
|
|
186
|
-
});
|
|
187
|
-
displayTokenList(result);
|
|
255
|
+
log(chalk.dim("Fetching token list..."));
|
|
256
|
+
screen.render();
|
|
257
|
+
const result = await listTokens(client, page, limit, sortBy);
|
|
258
|
+
displayTokenListToLog(result, log, logLines);
|
|
188
259
|
break;
|
|
189
260
|
}
|
|
190
261
|
case "positions": {
|
|
191
|
-
// Get user address from private key
|
|
192
262
|
const privateKey = config.getPrivateKey();
|
|
193
263
|
const account = privateKeyToAccount(privateKey);
|
|
194
264
|
const userAddress = account.address;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
spinner: "cat",
|
|
200
|
-
});
|
|
201
|
-
displayPositions(result);
|
|
265
|
+
log(chalk.dim("Fetching positions..."));
|
|
266
|
+
screen.render();
|
|
267
|
+
const result = await getPositions(client, userAddress);
|
|
268
|
+
displayPositionsToLog(result, log, logLines);
|
|
202
269
|
break;
|
|
203
270
|
}
|
|
204
271
|
case "health": {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
spinner: "cat",
|
|
210
|
-
});
|
|
211
|
-
displayHealthStatus(health);
|
|
272
|
+
log(chalk.dim("Checking health..."));
|
|
273
|
+
screen.render();
|
|
274
|
+
const health = await checkHealth(client);
|
|
275
|
+
displayHealthStatusToLog(health, log, logLines);
|
|
212
276
|
break;
|
|
213
277
|
}
|
|
214
|
-
case "
|
|
278
|
+
case "balances": {
|
|
215
279
|
try {
|
|
216
280
|
const privateKey = config.getPrivateKey();
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
spinner: "cat",
|
|
222
|
-
});
|
|
223
|
-
displayBalance(balance);
|
|
281
|
+
log(chalk.dim("Checking balance..."));
|
|
282
|
+
screen.render();
|
|
283
|
+
const balance = await checkBalance(privateKey);
|
|
284
|
+
displayBalanceToLog(balance, log, logLines);
|
|
224
285
|
}
|
|
225
286
|
catch (error) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
quiet: false,
|
|
231
|
-
spinner: "cat",
|
|
232
|
-
});
|
|
233
|
-
displayBalance(balance);
|
|
287
|
+
log(chalk.dim("Checking balance..."));
|
|
288
|
+
screen.render();
|
|
289
|
+
const balance = await checkBalance();
|
|
290
|
+
displayBalanceToLog(balance, log, logLines);
|
|
234
291
|
}
|
|
235
292
|
break;
|
|
236
293
|
}
|
|
237
294
|
case "config": {
|
|
238
295
|
if (args[0] === "--show") {
|
|
239
|
-
|
|
296
|
+
displayConfigToLog(log, logLines);
|
|
240
297
|
}
|
|
241
298
|
else if (args[0] === "--set" && args[1]) {
|
|
242
299
|
const [key, value] = args[1].split("=");
|
|
243
300
|
config.set(key, value);
|
|
244
|
-
|
|
301
|
+
log(chalk.green(`${key} set to ${value}`));
|
|
245
302
|
}
|
|
246
303
|
else if (args[0] === "--reset") {
|
|
247
|
-
|
|
304
|
+
log(chalk.yellow("Config reset requires exiting the shell. Use 'httpcat config' from command line."));
|
|
248
305
|
}
|
|
249
306
|
else {
|
|
250
|
-
|
|
307
|
+
log(chalk.red("Usage: config [--show|--set key=value|--reset]"));
|
|
251
308
|
}
|
|
252
309
|
break;
|
|
253
310
|
}
|
|
254
311
|
case "network": {
|
|
255
|
-
|
|
256
|
-
|
|
312
|
+
log(chalk.yellow("Current network: ") + chalk.cyan(config.get("network")));
|
|
313
|
+
log(chalk.dim("Note: Only base-sepolia (testnet) is currently supported"));
|
|
257
314
|
break;
|
|
258
315
|
}
|
|
259
316
|
case "chat": {
|
|
317
|
+
// For chat, we need to exit the blessed shell and start chat stream
|
|
318
|
+
log(chalk.yellow("Starting chat mode..."));
|
|
319
|
+
screen.destroy();
|
|
260
320
|
const tokenIdentifier = args.length > 0 ? args[0] : undefined;
|
|
261
321
|
await startChatStream(client, false, tokenIdentifier);
|
|
322
|
+
process.exit(0);
|
|
262
323
|
break;
|
|
263
324
|
}
|
|
264
325
|
case "exit":
|
|
265
326
|
case "quit":
|
|
327
|
+
screen.destroy();
|
|
328
|
+
printCat("sleeping");
|
|
329
|
+
console.log(chalk.cyan("Goodbye! 👋"));
|
|
266
330
|
process.exit(0);
|
|
267
331
|
break;
|
|
332
|
+
case "clear":
|
|
333
|
+
// Clear the output box
|
|
334
|
+
screen.children[1].setContent("");
|
|
335
|
+
screen.render();
|
|
336
|
+
break;
|
|
268
337
|
default:
|
|
269
|
-
|
|
270
|
-
|
|
338
|
+
log(chalk.red(`Unknown command: ${command}`));
|
|
339
|
+
log(chalk.dim('Type "help" for available commands'));
|
|
271
340
|
}
|
|
272
341
|
}
|
|
273
|
-
function displayHelp() {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
342
|
+
function displayHelp(log, logLines) {
|
|
343
|
+
log("");
|
|
344
|
+
log(chalk.cyan.bold("Available Commands:"));
|
|
345
|
+
log("");
|
|
277
346
|
const commands = [
|
|
278
347
|
["create <name> <symbol>", "Create a new token"],
|
|
279
|
-
["buy <
|
|
280
|
-
["sell <
|
|
281
|
-
["info <
|
|
348
|
+
["buy <address|name|symbol> <amount>", "Buy tokens ($0.05, $0.10, or $0.20)"],
|
|
349
|
+
["sell <address|name|symbol> <amount|all>", "Sell tokens"],
|
|
350
|
+
["info <address|name|symbol>", "Get token information"],
|
|
282
351
|
["list [--sort mcap|created]", "List all tokens"],
|
|
283
352
|
["positions", "Get all your positions with comprehensive info"],
|
|
284
|
-
["
|
|
353
|
+
["balances", "Check wallet balances (ETH and USDC)"],
|
|
285
354
|
[
|
|
286
355
|
"chat [token]",
|
|
287
356
|
"Start streaming chat (optional: token symbol/name/address)",
|
|
@@ -289,38 +358,118 @@ function displayHelp() {
|
|
|
289
358
|
["health", "Check agent health"],
|
|
290
359
|
["config [--show|--set|--reset]", "Manage configuration"],
|
|
291
360
|
["network", "Show current network"],
|
|
361
|
+
["clear", "Clear the output"],
|
|
292
362
|
["help", "Show this help message"],
|
|
293
363
|
["exit", "Exit the shell"],
|
|
294
364
|
];
|
|
295
365
|
for (const [cmd, desc] of commands) {
|
|
296
|
-
|
|
366
|
+
log(` ${chalk.cyan(cmd.padEnd(30))} ${chalk.dim(desc)}`);
|
|
297
367
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
console.log();
|
|
368
|
+
log("");
|
|
369
|
+
log(chalk.dim("Examples:"));
|
|
370
|
+
log(chalk.dim(' create "My Token" "MTK"'));
|
|
371
|
+
log(chalk.dim(" buy 0x1234... 5"));
|
|
372
|
+
log(chalk.dim(' buy "My Token" 2'));
|
|
373
|
+
log(chalk.dim(" buy MTK 1"));
|
|
374
|
+
log(chalk.dim(" sell 0x1234... 50%"));
|
|
375
|
+
log(chalk.dim(' info "My Token"'));
|
|
376
|
+
log(chalk.dim(" list --sort mcap --limit 10"));
|
|
377
|
+
log(chalk.dim(" positions"));
|
|
309
378
|
}
|
|
310
|
-
function
|
|
379
|
+
function displayConfigToLog(log, logLines) {
|
|
311
380
|
const cfg = config.getAll();
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
381
|
+
log("");
|
|
382
|
+
log(chalk.cyan.bold("Current Configuration:"));
|
|
383
|
+
log("");
|
|
384
|
+
log(chalk.dim("Network: ") + chalk.cyan(cfg.network));
|
|
385
|
+
log(chalk.dim("Agent URL: ") + chalk.cyan(cfg.agentUrl));
|
|
386
|
+
log(chalk.dim("Facilitator: ") + chalk.cyan(cfg.facilitatorUrl));
|
|
387
|
+
log(chalk.dim("Max Payment: ") + chalk.cyan("$" + cfg.defaultMaxPayment));
|
|
388
|
+
log(chalk.dim("ASCII Art: ") +
|
|
389
|
+
chalk.cyan(cfg.preferences.enableAsciiArt ? "enabled" : "disabled"));
|
|
390
|
+
log(chalk.dim("Private Key: ") +
|
|
391
|
+
chalk.dim(cfg.privateKey ? "configured" : "not configured"));
|
|
392
|
+
log("");
|
|
393
|
+
log(chalk.dim(`Config file: ${config.getConfigPath()}`));
|
|
394
|
+
}
|
|
395
|
+
// Simplified display functions that log to blessed output
|
|
396
|
+
function displayCreateResultToLog(result, log, logLines) {
|
|
397
|
+
log(chalk.green("Token created successfully!"));
|
|
398
|
+
log(chalk.dim("Name: ") + result.name);
|
|
399
|
+
log(chalk.dim("Symbol: ") + result.symbol);
|
|
400
|
+
if (result.tokenAddress) {
|
|
401
|
+
log(chalk.dim("Address: ") + chalk.cyan(result.tokenAddress));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
function displayBuyResultToLog(result, log, logLines) {
|
|
405
|
+
log(chalk.green("Purchase successful!"));
|
|
406
|
+
log(chalk.dim("Tokens received: ") + chalk.cyan(result.tokensReceived));
|
|
407
|
+
log(chalk.dim("Amount spent: ") + chalk.yellow(result.amountSpent));
|
|
408
|
+
log(chalk.dim("New price: ") + chalk.cyan(result.newPrice));
|
|
409
|
+
log(chalk.dim("Graduation: ") +
|
|
410
|
+
chalk.magenta(result.graduationProgress.toFixed(2) + "%"));
|
|
411
|
+
}
|
|
412
|
+
function displaySellResultToLog(result, log, logLines) {
|
|
413
|
+
log(chalk.green("Sale successful!"));
|
|
414
|
+
log(chalk.dim("Tokens sold: ") + chalk.cyan(result.tokensSold));
|
|
415
|
+
log(chalk.dim("USDC received: ") + chalk.yellow(result.usdcReceived));
|
|
416
|
+
log(chalk.dim("New price: ") + chalk.cyan(result.newPrice));
|
|
417
|
+
log(chalk.dim("Graduation: ") +
|
|
418
|
+
chalk.magenta(result.graduationProgress.toFixed(2) + "%"));
|
|
419
|
+
}
|
|
420
|
+
function displayTokenInfoToLog(info, log, logLines) {
|
|
421
|
+
log(chalk.cyan.bold(info.name) + ` (${info.symbol})`);
|
|
422
|
+
if (info.tokenAddress) {
|
|
423
|
+
log(chalk.dim("Address: ") + info.tokenAddress);
|
|
424
|
+
}
|
|
425
|
+
log(chalk.dim("Price: ") + chalk.cyan(info.currentPrice));
|
|
426
|
+
log(chalk.dim("Market Cap: ") + chalk.yellow(info.marketCap));
|
|
427
|
+
log(chalk.dim("Supply: ") + info.totalSupply);
|
|
428
|
+
if (info.graduationProgress !== undefined) {
|
|
429
|
+
log(chalk.dim("Graduation: ") +
|
|
430
|
+
chalk.magenta(info.graduationProgress.toFixed(2) + "%"));
|
|
431
|
+
}
|
|
432
|
+
if (info.userPosition && info.userPosition.tokensOwned !== "0") {
|
|
433
|
+
log(chalk.dim("Your position: ") +
|
|
434
|
+
chalk.green(info.userPosition.tokensOwned + " tokens"));
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function displayTokenListToLog(result, log, logLines) {
|
|
438
|
+
log(chalk.cyan.bold(`Tokens (${result.tokens.length} total):`));
|
|
439
|
+
log("");
|
|
440
|
+
for (const token of result.tokens.slice(0, 10)) {
|
|
441
|
+
log(` ${chalk.cyan(token.symbol.padEnd(8))} ${token.name.padEnd(20)} ${chalk.yellow(token.marketCap || "N/A")}`);
|
|
442
|
+
}
|
|
443
|
+
if (result.tokens.length > 10) {
|
|
444
|
+
log(chalk.dim(` ... and ${result.tokens.length - 10} more`));
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function displayPositionsToLog(result, log, logLines) {
|
|
448
|
+
if (!result.positions || result.positions.length === 0) {
|
|
449
|
+
log(chalk.yellow("No positions found."));
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
log(chalk.cyan.bold(`Your Positions (${result.positions.length}):`));
|
|
453
|
+
log("");
|
|
454
|
+
for (const pos of result.positions) {
|
|
455
|
+
log(` ${chalk.cyan(pos.symbol || "???")} - ${chalk.green(pos.tokensOwned + " tokens")} @ ${chalk.yellow(pos.currentValue || "N/A")}`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
function displayHealthStatusToLog(health, log, logLines) {
|
|
459
|
+
const statusColor = health.status === "healthy" ? chalk.green : chalk.red;
|
|
460
|
+
log(statusColor(`Agent Status: ${health.status}`));
|
|
461
|
+
if (health.version) {
|
|
462
|
+
log(chalk.dim("Version: ") + health.version);
|
|
463
|
+
}
|
|
464
|
+
if (health.uptime) {
|
|
465
|
+
log(chalk.dim("Uptime: ") + health.uptime);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
function displayBalanceToLog(balance, log, logLines) {
|
|
469
|
+
log(chalk.cyan.bold("Wallet Balance:"));
|
|
470
|
+
log(chalk.dim("Address: ") + chalk.cyan(balance.address));
|
|
471
|
+
log(chalk.dim("ETH: ") + chalk.yellow(balance.ethBalance));
|
|
472
|
+
log(chalk.dim("USDC: ") + chalk.green(balance.usdcBalance));
|
|
324
473
|
}
|
|
325
474
|
function extractFlag(args, flag) {
|
|
326
475
|
const index = args.findIndex((arg) => arg === flag);
|