httpcat-cli 0.0.22 → 0.0.23
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/dist/commands/account.d.ts.map +1 -0
- package/dist/commands/account.js +229 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/info.d.ts.map +1 -1
- package/dist/commands/info.js +15 -3
- package/dist/commands/info.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +295 -7
- package/dist/config.js.map +1 -1
- package/dist/index.js +224 -13
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +22 -5
- package/dist/mcp/tools.js.map +1 -1
- package/dist/utils/privateKeyPrompt.d.ts.map +1 -1
- package/dist/utils/privateKeyPrompt.js +238 -32
- package/dist/utils/privateKeyPrompt.js.map +1 -1
- package/dist/utils/token-resolver.d.ts.map +1 -1
- package/dist/utils/token-resolver.js +15 -4
- package/dist/utils/token-resolver.js.map +1 -1
- package/dist/utils/wallet.d.ts.map +1 -0
- package/dist/utils/wallet.js +134 -0
- package/dist/utils/wallet.js.map +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"AAQA,OAAO,EAAgB,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAkC,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA0DpF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA8C9D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CA+BnC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAejD;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgGhD"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { config } from "../config.js";
|
|
3
|
+
import { HttpcatClient } from "../client.js";
|
|
4
|
+
import { formatAddress, createTable } from "../utils/formatting.js";
|
|
5
|
+
import { checkBalance } from "./balance.js";
|
|
6
|
+
import { getPositions, displayPositions } from "./positions.js";
|
|
7
|
+
import { decryptData } from "../utils/wallet.js";
|
|
8
|
+
/**
|
|
9
|
+
* Get account information including address, balances, and positions
|
|
10
|
+
*/
|
|
11
|
+
export async function getAccountInfo(accountIndex) {
|
|
12
|
+
const index = accountIndex !== undefined ? accountIndex : config.getActiveAccountIndex();
|
|
13
|
+
const accounts = config.getAllAccounts();
|
|
14
|
+
const account = accounts.find((acc) => acc.index === index);
|
|
15
|
+
if (!account) {
|
|
16
|
+
throw new Error(`Account at index ${index} not found. Use "httpcat account list" to see available accounts.`);
|
|
17
|
+
}
|
|
18
|
+
// Get private key for this account
|
|
19
|
+
const privateKey = config.getAccountPrivateKey(index);
|
|
20
|
+
// Derive address from private key to ensure we're using the correct one
|
|
21
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
22
|
+
const derivedAccount = privateKeyToAccount(privateKey);
|
|
23
|
+
const derivedAddress = derivedAccount.address;
|
|
24
|
+
// Verify the address matches the stored account address
|
|
25
|
+
if (account.address.toLowerCase() !== derivedAddress.toLowerCase()) {
|
|
26
|
+
console.warn(`⚠️ Address mismatch: stored ${account.address} but derived ${derivedAddress}`);
|
|
27
|
+
}
|
|
28
|
+
// Get balance
|
|
29
|
+
const balance = await checkBalance(privateKey);
|
|
30
|
+
// Get positions if we have a client - use derived address to ensure correctness
|
|
31
|
+
let positions;
|
|
32
|
+
try {
|
|
33
|
+
const client = await HttpcatClient.create(privateKey);
|
|
34
|
+
// Log which address we're querying (for debugging)
|
|
35
|
+
console.log(chalk.dim(` Querying positions for address: ${formatAddress(derivedAddress, 12)}`));
|
|
36
|
+
positions = await getPositions(client, derivedAddress);
|
|
37
|
+
// The API should filter by userAddress, so positions returned should be for this address
|
|
38
|
+
// If positions exist but balances are 0, that's suspicious - log a warning
|
|
39
|
+
if (positions && positions.positions.length > 0) {
|
|
40
|
+
const ethBalance = parseFloat(balance.ethFormatted);
|
|
41
|
+
const usdcBalance = parseFloat(balance.usdcFormatted.replace('$', ''));
|
|
42
|
+
if (ethBalance === 0 && usdcBalance === 0) {
|
|
43
|
+
console.log(chalk.yellow(` ⚠️ Warning: Found ${positions.positions.length} position(s) but account has 0 ETH and 0 USDC.`));
|
|
44
|
+
console.log(chalk.yellow(` This might indicate positions are for a different address.`));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
// If positions fail, just continue without them
|
|
50
|
+
console.warn("Could not fetch positions:", error);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
account,
|
|
54
|
+
balance,
|
|
55
|
+
positions,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Display account information
|
|
60
|
+
*/
|
|
61
|
+
export function displayAccountInfo(data) {
|
|
62
|
+
const { account, balance, positions } = data;
|
|
63
|
+
console.log();
|
|
64
|
+
console.log(chalk.cyan("=".repeat(80)));
|
|
65
|
+
console.log(chalk.cyan.bold("👤 Account Information"));
|
|
66
|
+
console.log(chalk.cyan("=".repeat(80)));
|
|
67
|
+
console.log();
|
|
68
|
+
// Account details
|
|
69
|
+
const accountTable = createTable(["Property", "Value"]);
|
|
70
|
+
accountTable.push(["Account Index", account.index.toString()], ["Type", account.type === "custom" ? "Custom (Private Key)" : "Seed-Derived"], ["Address", formatAddress(account.address, 12)], ["Full Address", account.address]);
|
|
71
|
+
if (account.label) {
|
|
72
|
+
accountTable.push(["Label", account.label]);
|
|
73
|
+
}
|
|
74
|
+
console.log(accountTable.toString());
|
|
75
|
+
console.log();
|
|
76
|
+
// Balance information
|
|
77
|
+
console.log(chalk.cyan.bold("💰 Balances"));
|
|
78
|
+
console.log();
|
|
79
|
+
const balanceTable = createTable(["Asset", "Balance"]);
|
|
80
|
+
balanceTable.push(["ETH", chalk.yellow(balance.ethFormatted)], ["USDC", chalk.green(`$${balance.usdcFormatted}`)]);
|
|
81
|
+
console.log(balanceTable.toString());
|
|
82
|
+
console.log();
|
|
83
|
+
// Positions if available
|
|
84
|
+
if (positions && positions.positions.length > 0) {
|
|
85
|
+
console.log(chalk.cyan.bold("💼 Positions"));
|
|
86
|
+
console.log();
|
|
87
|
+
displayPositions(positions);
|
|
88
|
+
}
|
|
89
|
+
else if (positions) {
|
|
90
|
+
console.log(chalk.cyan.bold("💼 Positions"));
|
|
91
|
+
console.log();
|
|
92
|
+
console.log(chalk.dim("No positions found."));
|
|
93
|
+
console.log();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* List all accounts
|
|
98
|
+
*/
|
|
99
|
+
export function listAccounts() {
|
|
100
|
+
const accounts = config.getAllAccounts();
|
|
101
|
+
const activeIndex = config.getActiveAccountIndex();
|
|
102
|
+
console.log();
|
|
103
|
+
console.log(chalk.cyan.bold("📋 All Accounts"));
|
|
104
|
+
console.log();
|
|
105
|
+
if (accounts.length === 0) {
|
|
106
|
+
console.log(chalk.yellow("No accounts configured."));
|
|
107
|
+
console.log();
|
|
108
|
+
console.log(chalk.dim('Run "httpcat config" to set up your wallet.'));
|
|
109
|
+
console.log();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const table = createTable(["Index", "Type", "Address", "Status"]);
|
|
113
|
+
for (const account of accounts) {
|
|
114
|
+
const isActive = account.index === activeIndex;
|
|
115
|
+
const status = isActive ? chalk.green("● Active") : chalk.dim("○ Inactive");
|
|
116
|
+
const type = account.type === "custom" ? "Custom" : "Seed-Derived";
|
|
117
|
+
const address = formatAddress(account.address, 12);
|
|
118
|
+
table.push([account.index.toString(), type, address, status]);
|
|
119
|
+
}
|
|
120
|
+
console.log(table.toString());
|
|
121
|
+
console.log();
|
|
122
|
+
console.log(chalk.dim(`Active account: ${chalk.green(activeIndex.toString())}`));
|
|
123
|
+
console.log();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Switch active account
|
|
127
|
+
*/
|
|
128
|
+
export function switchAccount(index) {
|
|
129
|
+
const accounts = config.getAllAccounts();
|
|
130
|
+
const account = accounts.find((acc) => acc.index === index);
|
|
131
|
+
if (!account) {
|
|
132
|
+
throw new Error(`Account at index ${index} not found. Use "httpcat account list" to see available accounts.`);
|
|
133
|
+
}
|
|
134
|
+
config.setActiveAccount(index);
|
|
135
|
+
console.log();
|
|
136
|
+
console.log(chalk.green(`✅ Switched to account ${index}`));
|
|
137
|
+
console.log(chalk.dim(` Address: ${formatAddress(account.address, 12)}`));
|
|
138
|
+
console.log();
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Add a new seed-derived account
|
|
142
|
+
*/
|
|
143
|
+
export async function addAccount() {
|
|
144
|
+
const accounts = config.getAllAccounts();
|
|
145
|
+
const hasSeedPhrase = !!config.get("encryptedSeedPhrase");
|
|
146
|
+
const password = config.getPassword() || "";
|
|
147
|
+
// Check if we already have a seed phrase
|
|
148
|
+
if (hasSeedPhrase) {
|
|
149
|
+
// Find the highest seed-derived account index
|
|
150
|
+
const seedAccounts = accounts.filter((acc) => acc.type === "seed");
|
|
151
|
+
const maxIndex = seedAccounts.length > 0
|
|
152
|
+
? Math.max(...seedAccounts.map((acc) => acc.index))
|
|
153
|
+
: 0;
|
|
154
|
+
// Next account index
|
|
155
|
+
const nextIndex = maxIndex + 1;
|
|
156
|
+
const seedIndex = nextIndex - 1; // Seed index is account index - 1
|
|
157
|
+
// Get seed phrase
|
|
158
|
+
config.ensureSessionValid();
|
|
159
|
+
const encrypted = config.get("encryptedSeedPhrase");
|
|
160
|
+
let seedPhrase;
|
|
161
|
+
if (password) {
|
|
162
|
+
if (!config.isSessionValid()) {
|
|
163
|
+
throw new Error("Session expired. Please unlock your wallet.");
|
|
164
|
+
}
|
|
165
|
+
seedPhrase = decryptData(encrypted, password);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
seedPhrase = encrypted;
|
|
169
|
+
}
|
|
170
|
+
// Derive new account
|
|
171
|
+
const { seedPhraseToPrivateKey, getAddressFromPrivateKey } = await import("../utils/wallet.js");
|
|
172
|
+
const privateKey = seedPhraseToPrivateKey(seedPhrase, seedIndex);
|
|
173
|
+
const address = getAddressFromPrivateKey(privateKey);
|
|
174
|
+
// Add account
|
|
175
|
+
config.addAccount({
|
|
176
|
+
type: "seed",
|
|
177
|
+
index: nextIndex,
|
|
178
|
+
address,
|
|
179
|
+
});
|
|
180
|
+
console.log();
|
|
181
|
+
console.log(chalk.green(`✅ Added account ${nextIndex}`));
|
|
182
|
+
console.log(chalk.dim(` Address: ${formatAddress(address, 12)}`));
|
|
183
|
+
console.log();
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
// No seed phrase - need to generate or import one
|
|
187
|
+
console.log();
|
|
188
|
+
console.log(chalk.yellow("⚠️ No seed phrase found."));
|
|
189
|
+
console.log(chalk.dim(" To add more accounts, you need to set up a seed phrase."));
|
|
190
|
+
console.log();
|
|
191
|
+
const inquirer = (await import("inquirer")).default;
|
|
192
|
+
const { handleGenerateSeedPhrase, handleImportSeedPhrase } = await import("../utils/privateKeyPrompt.js");
|
|
193
|
+
const choice = await inquirer.prompt([
|
|
194
|
+
{
|
|
195
|
+
type: "list",
|
|
196
|
+
name: "option",
|
|
197
|
+
message: "How would you like to add accounts?",
|
|
198
|
+
choices: [
|
|
199
|
+
{ name: "Generate new seed phrase", value: "generate" },
|
|
200
|
+
{ name: "Import existing seed phrase", value: "import" },
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
]);
|
|
204
|
+
let seedPhrase;
|
|
205
|
+
if (choice.option === "generate") {
|
|
206
|
+
seedPhrase = await handleGenerateSeedPhrase();
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
seedPhrase = await handleImportSeedPhrase();
|
|
210
|
+
}
|
|
211
|
+
// Save seed phrase
|
|
212
|
+
config.setEncryptedSeedPhrase(seedPhrase, password);
|
|
213
|
+
// Create Account 1 (first seed-derived account)
|
|
214
|
+
const { seedPhraseToPrivateKey, getAddressFromPrivateKey } = await import("../utils/wallet.js");
|
|
215
|
+
const account1PrivateKey = seedPhraseToPrivateKey(seedPhrase, 0);
|
|
216
|
+
const account1Address = getAddressFromPrivateKey(account1PrivateKey);
|
|
217
|
+
config.addAccount({
|
|
218
|
+
type: "seed",
|
|
219
|
+
index: 1,
|
|
220
|
+
address: account1Address,
|
|
221
|
+
});
|
|
222
|
+
console.log();
|
|
223
|
+
console.log(chalk.green("✅ Seed phrase saved"));
|
|
224
|
+
console.log(chalk.green(`✅ Added account 1`));
|
|
225
|
+
console.log(chalk.dim(` Address: ${formatAddress(account1Address, 12)}`));
|
|
226
|
+
console.log();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAM7C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,EAAE,mCAAmC;AACvD,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,UAAQ,GACb,OAAO,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAM7C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,EAAE,mCAAmC;AACvD,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,UAAQ,GACb,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA6B5D"}
|
package/dist/commands/info.js
CHANGED
|
@@ -6,10 +6,22 @@ export async function getTokenInfo(client, identifier, // Can be token ID, name,
|
|
|
6
6
|
userAddress, silent = false // Suppress resolver output for quiet/JSON mode
|
|
7
7
|
) {
|
|
8
8
|
// Resolve identifier to token ID
|
|
9
|
-
const
|
|
9
|
+
const resolvedTokenId = await resolveTokenId(identifier, client, silent);
|
|
10
|
+
// Validate that we got a tokenId
|
|
11
|
+
if (!resolvedTokenId || typeof resolvedTokenId !== 'string') {
|
|
12
|
+
throw new Error(`Failed to resolve token identifier: ${identifier}`);
|
|
13
|
+
}
|
|
10
14
|
// Validate input
|
|
11
|
-
validateTokenId(
|
|
12
|
-
|
|
15
|
+
validateTokenId(resolvedTokenId);
|
|
16
|
+
// Ensure tokenId is set in input
|
|
17
|
+
const input = {
|
|
18
|
+
tokenId: resolvedTokenId,
|
|
19
|
+
...(userAddress && { userAddress })
|
|
20
|
+
};
|
|
21
|
+
// Double-check tokenId is set
|
|
22
|
+
if (!input.tokenId) {
|
|
23
|
+
throw new Error(`Token ID is missing in input object. Resolved ID was: ${resolvedTokenId}`);
|
|
24
|
+
}
|
|
13
25
|
// Make request
|
|
14
26
|
const { data } = await client.invoke('token_info', input);
|
|
15
27
|
return data;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACpG,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AA4B5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAqB,EACrB,UAAkB,EAAE,mCAAmC;AACvD,WAAoB,EACpB,MAAM,GAAG,KAAK,CAAC,+CAA+C;;IAE9D,iCAAiC;IACjC,MAAM,
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Conf from "conf";
|
|
2
2
|
import { createInterface } from "readline";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
import { decryptData, encryptData, seedPhraseToPrivateKey, getAddressFromPrivateKey } from "./utils/wallet.js";
|
|
4
5
|
const DEFAULT_ENVIRONMENTS = {
|
|
5
6
|
local: {
|
|
6
7
|
name: "local",
|
|
@@ -28,11 +29,14 @@ const DEFAULT_CONFIG = {
|
|
|
28
29
|
};
|
|
29
30
|
export class ConfigManager {
|
|
30
31
|
store;
|
|
32
|
+
session = null;
|
|
31
33
|
constructor() {
|
|
32
34
|
this.store = new Conf({
|
|
33
35
|
projectName: "httpcat",
|
|
34
36
|
defaults: DEFAULT_CONFIG,
|
|
35
37
|
});
|
|
38
|
+
// Migrate old privateKey format on first access
|
|
39
|
+
this.migrateLegacyPrivateKey();
|
|
36
40
|
}
|
|
37
41
|
get(key) {
|
|
38
42
|
return this.store.get(key);
|
|
@@ -56,8 +60,52 @@ export class ConfigManager {
|
|
|
56
60
|
return this.store.path;
|
|
57
61
|
}
|
|
58
62
|
isConfigured() {
|
|
63
|
+
// Check new format first
|
|
64
|
+
const accounts = this.get("accounts");
|
|
65
|
+
if (accounts && accounts.length > 0) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
// Check legacy format
|
|
59
69
|
return this.has("privateKey") && !!this.get("privateKey");
|
|
60
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Migrate legacy privateKey to new account format
|
|
73
|
+
*/
|
|
74
|
+
migrateLegacyPrivateKey() {
|
|
75
|
+
const legacyKey = this.get("privateKey");
|
|
76
|
+
if (legacyKey && !this.get("accounts")) {
|
|
77
|
+
// Migrate to Account 0
|
|
78
|
+
const address = getAddressFromPrivateKey(legacyKey);
|
|
79
|
+
const accounts = [
|
|
80
|
+
{
|
|
81
|
+
type: "custom",
|
|
82
|
+
index: 0,
|
|
83
|
+
address,
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
this.set("accounts", accounts);
|
|
87
|
+
this.set("activeAccountIndex", 0);
|
|
88
|
+
// Encrypt and store if password is set
|
|
89
|
+
const password = this.get("password");
|
|
90
|
+
if (password) {
|
|
91
|
+
try {
|
|
92
|
+
const encrypted = encryptData(legacyKey, password);
|
|
93
|
+
this.set("encryptedPrivateKey", encrypted);
|
|
94
|
+
// Remove plain private key
|
|
95
|
+
this.delete("privateKey");
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
// If encryption fails, keep plain key (password might be invalid)
|
|
99
|
+
console.warn("Failed to encrypt legacy private key during migration");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// Store as encrypted with empty password (no encryption)
|
|
104
|
+
this.set("encryptedPrivateKey", legacyKey);
|
|
105
|
+
this.delete("privateKey");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
61
109
|
async runSetupWizard(options = {}) {
|
|
62
110
|
console.log(chalk.cyan("=".repeat(80)));
|
|
63
111
|
console.log(chalk.cyan.bold("🐱 httpcat Configuration Setup"));
|
|
@@ -120,8 +168,11 @@ export class ConfigManager {
|
|
|
120
168
|
});
|
|
121
169
|
});
|
|
122
170
|
}
|
|
123
|
-
|
|
124
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Get private key for a specific account index (or active account)
|
|
173
|
+
*/
|
|
174
|
+
getPrivateKey(accountIndex) {
|
|
175
|
+
// Check environment variable first (highest priority)
|
|
125
176
|
const envKey = process.env.HTTPCAT_PRIVATE_KEY;
|
|
126
177
|
if (envKey) {
|
|
127
178
|
if (!envKey.startsWith("0x") || envKey.length !== 66) {
|
|
@@ -129,12 +180,249 @@ export class ConfigManager {
|
|
|
129
180
|
}
|
|
130
181
|
return envKey;
|
|
131
182
|
}
|
|
132
|
-
//
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
183
|
+
// Use new account system
|
|
184
|
+
const index = accountIndex !== undefined ? accountIndex : this.getActiveAccountIndex();
|
|
185
|
+
return this.getAccountPrivateKey(index);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get private key for a specific account index
|
|
189
|
+
*/
|
|
190
|
+
getAccountPrivateKey(accountIndex) {
|
|
191
|
+
const accounts = this.get("accounts") || [];
|
|
192
|
+
const account = accounts.find((acc) => acc.index === accountIndex);
|
|
193
|
+
if (!account) {
|
|
194
|
+
throw new Error(`Account at index ${accountIndex} not found. Use "httpcat account list" to see available accounts.`);
|
|
195
|
+
}
|
|
196
|
+
// Ensure session is valid
|
|
197
|
+
this.ensureSessionValid();
|
|
198
|
+
if (account.type === "custom") {
|
|
199
|
+
// Account 0 - use encrypted private key
|
|
200
|
+
const encrypted = this.get("encryptedPrivateKey");
|
|
201
|
+
if (!encrypted) {
|
|
202
|
+
throw new Error("Account 0 private key not found");
|
|
203
|
+
}
|
|
204
|
+
const password = this.get("password") || "";
|
|
205
|
+
if (password) {
|
|
206
|
+
// Decrypt using session
|
|
207
|
+
if (!this.session?.decryptedPrivateKey) {
|
|
208
|
+
throw new Error("Session expired. Please unlock your wallet.");
|
|
209
|
+
}
|
|
210
|
+
return this.session.decryptedPrivateKey;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// No password - stored as plain (but in encryptedPrivateKey field)
|
|
214
|
+
return encrypted;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
// Seed-derived account
|
|
219
|
+
const encrypted = this.get("encryptedSeedPhrase");
|
|
220
|
+
if (!encrypted) {
|
|
221
|
+
throw new Error("Seed phrase not found");
|
|
222
|
+
}
|
|
223
|
+
const password = this.get("password") || "";
|
|
224
|
+
let seedPhrase;
|
|
225
|
+
if (password) {
|
|
226
|
+
// Decrypt using session
|
|
227
|
+
if (!this.session?.decryptedSeedPhrase) {
|
|
228
|
+
throw new Error("Session expired. Please unlock your wallet.");
|
|
229
|
+
}
|
|
230
|
+
seedPhrase = this.session.decryptedSeedPhrase;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
// No password - stored as plain
|
|
234
|
+
seedPhrase = encrypted;
|
|
235
|
+
}
|
|
236
|
+
// Derive private key from seed phrase
|
|
237
|
+
// Account index 1 = seed index 0, Account index 2 = seed index 1, etc.
|
|
238
|
+
const seedIndex = accountIndex - 1;
|
|
239
|
+
return seedPhraseToPrivateKey(seedPhrase, seedIndex);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get active account index
|
|
244
|
+
*/
|
|
245
|
+
getActiveAccountIndex() {
|
|
246
|
+
const active = this.get("activeAccountIndex");
|
|
247
|
+
if (active !== undefined) {
|
|
248
|
+
return active;
|
|
249
|
+
}
|
|
250
|
+
// Default to 0 if accounts exist, otherwise throw
|
|
251
|
+
const accounts = this.get("accounts") || [];
|
|
252
|
+
if (accounts.length > 0) {
|
|
253
|
+
return 0;
|
|
254
|
+
}
|
|
255
|
+
throw new Error("No accounts configured");
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Set active account index
|
|
259
|
+
*/
|
|
260
|
+
setActiveAccount(index) {
|
|
261
|
+
const accounts = this.get("accounts") || [];
|
|
262
|
+
const account = accounts.find((acc) => acc.index === index);
|
|
263
|
+
if (!account) {
|
|
264
|
+
throw new Error(`Account at index ${index} not found`);
|
|
265
|
+
}
|
|
266
|
+
this.set("activeAccountIndex", index);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get active account info
|
|
270
|
+
*/
|
|
271
|
+
getActiveAccount() {
|
|
272
|
+
const index = this.getActiveAccountIndex();
|
|
273
|
+
const accounts = this.get("accounts") || [];
|
|
274
|
+
return accounts.find((acc) => acc.index === index) || null;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Get all accounts
|
|
278
|
+
*/
|
|
279
|
+
getAllAccounts() {
|
|
280
|
+
return this.get("accounts") || [];
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Add an account
|
|
284
|
+
*/
|
|
285
|
+
addAccount(account) {
|
|
286
|
+
const accounts = this.get("accounts") || [];
|
|
287
|
+
if (accounts.find((acc) => acc.index === account.index)) {
|
|
288
|
+
throw new Error(`Account at index ${account.index} already exists`);
|
|
289
|
+
}
|
|
290
|
+
accounts.push(account);
|
|
291
|
+
// Sort by index
|
|
292
|
+
accounts.sort((a, b) => a.index - b.index);
|
|
293
|
+
this.set("accounts", accounts);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Password management
|
|
297
|
+
*/
|
|
298
|
+
setPassword(password) {
|
|
299
|
+
this.set("password", password);
|
|
300
|
+
// Clear session when password changes
|
|
301
|
+
this.clearSession();
|
|
302
|
+
}
|
|
303
|
+
getPassword() {
|
|
304
|
+
return this.get("password") || "";
|
|
305
|
+
}
|
|
306
|
+
setPasswordTimeout(minutes) {
|
|
307
|
+
this.set("passwordTimeoutMinutes", minutes);
|
|
308
|
+
}
|
|
309
|
+
getPasswordTimeout() {
|
|
310
|
+
return this.get("passwordTimeoutMinutes") || 15;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Session management
|
|
314
|
+
*/
|
|
315
|
+
async unlockSession(password) {
|
|
316
|
+
const storedPassword = this.getPassword();
|
|
317
|
+
// If no password is set, session is always valid
|
|
318
|
+
if (!storedPassword) {
|
|
319
|
+
this.session = {
|
|
320
|
+
expiresAt: Date.now() + 365 * 24 * 60 * 60 * 1000, // 1 year (effectively never expires)
|
|
321
|
+
};
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
// If password provided, validate it
|
|
325
|
+
if (password !== undefined) {
|
|
326
|
+
// Try to decrypt to validate password
|
|
327
|
+
const encryptedSeed = this.get("encryptedSeedPhrase");
|
|
328
|
+
const encryptedKey = this.get("encryptedPrivateKey");
|
|
329
|
+
try {
|
|
330
|
+
if (encryptedSeed) {
|
|
331
|
+
decryptData(encryptedSeed, password);
|
|
332
|
+
}
|
|
333
|
+
if (encryptedKey) {
|
|
334
|
+
decryptData(encryptedKey, password);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
throw new Error("Invalid password");
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
// No password provided, check if we need to prompt
|
|
343
|
+
if (!this.isSessionValid()) {
|
|
344
|
+
throw new Error("Session expired. Password required.");
|
|
345
|
+
}
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
// Decrypt and cache
|
|
349
|
+
const timeout = this.getPasswordTimeout();
|
|
350
|
+
const expiresAt = Date.now() + timeout * 60 * 1000;
|
|
351
|
+
const decryptedSeed = this.get("encryptedSeedPhrase")
|
|
352
|
+
? decryptData(this.get("encryptedSeedPhrase"), password)
|
|
353
|
+
: undefined;
|
|
354
|
+
const decryptedKey = this.get("encryptedPrivateKey")
|
|
355
|
+
? decryptData(this.get("encryptedPrivateKey"), password)
|
|
356
|
+
: undefined;
|
|
357
|
+
this.session = {
|
|
358
|
+
decryptedSeedPhrase: decryptedSeed,
|
|
359
|
+
decryptedPrivateKey: decryptedKey,
|
|
360
|
+
expiresAt,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
isSessionValid() {
|
|
364
|
+
if (!this.session) {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
if (Date.now() >= this.session.expiresAt) {
|
|
368
|
+
this.clearSession();
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
373
|
+
ensureSessionValid() {
|
|
374
|
+
const password = this.getPassword();
|
|
375
|
+
if (!password) {
|
|
376
|
+
// No password required
|
|
377
|
+
if (!this.session) {
|
|
378
|
+
this.session = {
|
|
379
|
+
expiresAt: Date.now() + 365 * 24 * 60 * 60 * 1000,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
if (!this.isSessionValid()) {
|
|
385
|
+
throw new Error("Session expired. Please unlock your wallet.");
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
clearSession() {
|
|
389
|
+
// Clear sensitive data from memory
|
|
390
|
+
if (this.session) {
|
|
391
|
+
if (this.session.decryptedSeedPhrase) {
|
|
392
|
+
// Overwrite with zeros (best effort)
|
|
393
|
+
this.session.decryptedSeedPhrase = "";
|
|
394
|
+
}
|
|
395
|
+
if (this.session.decryptedPrivateKey) {
|
|
396
|
+
this.session.decryptedPrivateKey = undefined;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
this.session = null;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Store encrypted seed phrase
|
|
403
|
+
*/
|
|
404
|
+
setEncryptedSeedPhrase(seedPhrase, password) {
|
|
405
|
+
if (password) {
|
|
406
|
+
const encrypted = encryptData(seedPhrase, password);
|
|
407
|
+
this.set("encryptedSeedPhrase", encrypted);
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
// No password - store as plain (but in encryptedSeedPhrase field)
|
|
411
|
+
this.set("encryptedSeedPhrase", seedPhrase);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Store encrypted private key
|
|
416
|
+
*/
|
|
417
|
+
setEncryptedPrivateKey(privateKey, password) {
|
|
418
|
+
if (password) {
|
|
419
|
+
const encrypted = encryptData(privateKey, password);
|
|
420
|
+
this.set("encryptedPrivateKey", encrypted);
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// No password - store as plain (but in encryptedPrivateKey field)
|
|
424
|
+
this.set("encryptedPrivateKey", privateKey);
|
|
136
425
|
}
|
|
137
|
-
return configKey;
|
|
138
426
|
}
|
|
139
427
|
// Environment management methods
|
|
140
428
|
getEnvironments() {
|