hodl-wallet 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -3
- package/dist/agent-cli.d.ts +11 -0
- package/dist/agent-cli.js +310 -0
- package/dist/agent-cli.js.map +1 -0
- package/dist/agent-errors.d.ts +7 -0
- package/dist/agent-errors.js +13 -0
- package/dist/agent-errors.js.map +1 -0
- package/dist/amounts.d.ts +3 -0
- package/dist/amounts.js +51 -0
- package/dist/amounts.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +95 -37
- package/dist/index.js.map +1 -1
- package/dist/network/arb.d.ts +3 -0
- package/dist/network/arb.js +4 -1
- package/dist/network/arb.js.map +1 -1
- package/dist/network/avax.d.ts +3 -0
- package/dist/network/avax.js +3 -0
- package/dist/network/avax.js.map +1 -1
- package/dist/network/bsc.d.ts +3 -0
- package/dist/network/bsc.js +3 -0
- package/dist/network/bsc.js.map +1 -1
- package/dist/network/btc.d.ts +3 -0
- package/dist/network/btc.js +3 -0
- package/dist/network/btc.js.map +1 -1
- package/dist/network/eth.d.ts +3 -0
- package/dist/network/eth.js +3 -0
- package/dist/network/eth.js.map +1 -1
- package/dist/network/ftm.d.ts +3 -0
- package/dist/network/ftm.js +3 -0
- package/dist/network/ftm.js.map +1 -1
- package/dist/network/hyperliquid.d.ts +2 -0
- package/dist/network/hyperliquid.js +2 -0
- package/dist/network/hyperliquid.js.map +1 -1
- package/dist/network/lib/BaseNetwork.d.ts +8 -4
- package/dist/network/lib/BaseNetwork.js +1 -1
- package/dist/network/lib/BaseNetwork.js.map +1 -1
- package/dist/network/lib/BitcoinNetwork.d.ts +9 -4
- package/dist/network/lib/BitcoinNetwork.js +92 -8
- package/dist/network/lib/BitcoinNetwork.js.map +1 -1
- package/dist/network/lib/Web3Network.d.ts +6 -2
- package/dist/network/lib/Web3Network.js +156 -58
- package/dist/network/lib/Web3Network.js.map +1 -1
- package/dist/network/op.d.ts +3 -0
- package/dist/network/op.js +4 -1
- package/dist/network/op.js.map +1 -1
- package/dist/network/pol.d.ts +3 -0
- package/dist/network/pol.js +3 -0
- package/dist/network/pol.js.map +1 -1
- package/dist/network/types.d.ts +33 -3
- package/dist/network-registry.d.ts +9 -0
- package/dist/network-registry.js +50 -0
- package/dist/network-registry.js.map +1 -0
- package/dist/persist.js +1 -1
- package/dist/persist.js.map +1 -1
- package/dist/profile-lock.d.ts +14 -0
- package/dist/profile-lock.js +84 -0
- package/dist/profile-lock.js.map +1 -0
- package/dist/wallet-service.d.ts +73 -0
- package/dist/wallet-service.js +633 -0
- package/dist/wallet-service.js.map +1 -0
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#### 📦 Install and try!
|
|
4
4
|
```bash
|
|
5
|
-
npm
|
|
6
|
-
hodl
|
|
5
|
+
npm i -g hodl-wallet && hodl
|
|
7
6
|
```
|
|
8
7
|
|
|
9
8
|

|
|
@@ -13,7 +12,8 @@ hodl
|
|
|
13
12
|
Let's face it, Trust Wallet's sluggishness and annoying ads are so last season. HODL Wallet is here to agilize your crypto experience.
|
|
14
13
|
|
|
15
14
|
- 🏎️ Lightning-fast operations
|
|
16
|
-
-
|
|
15
|
+
- 🖥️ Interactive TUI and direct CLI commands
|
|
16
|
+
- 🤖 Agent-ready, non-interactive JSON interface
|
|
17
17
|
- 🚫 Zero ads, zero BS
|
|
18
18
|
- 🔒 Create wallets offline (because paranoia is just good sense in crypto)
|
|
19
19
|
- 🔍 Fully transparent, open-source code
|
|
@@ -67,6 +67,45 @@ These files are encrypted using your wallet password, providing an additional la
|
|
|
67
67
|
|
|
68
68
|
The main advantage of exporting a HODL file is that to access the private key, you need BOTH the file AND the password. This two-factor approach significantly enhances security. However, keep in mind that this solution is only compatible with HODL Wallet.
|
|
69
69
|
|
|
70
|
+
## Agent-friendly JSON CLI
|
|
71
|
+
|
|
72
|
+
Running `hodl` without arguments keeps the interactive wallet. Subcommands are
|
|
73
|
+
non-interactive: they emit one JSON object, use stable network IDs, and never
|
|
74
|
+
accept passwords, mnemonics, or private keys as command-line arguments.
|
|
75
|
+
Protected commands receive the password as JSON through stdin:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
hodl networks
|
|
79
|
+
hodl wallet list
|
|
80
|
+
|
|
81
|
+
echo '{"password":"vault-password"}' |
|
|
82
|
+
hodl wallet create --wallet treasury --words 24
|
|
83
|
+
|
|
84
|
+
echo '{"password":"vault-password"}' |
|
|
85
|
+
hodl balance --wallet treasury --network eth
|
|
86
|
+
|
|
87
|
+
echo '{"password":"vault-password"}' |
|
|
88
|
+
hodl send --wallet treasury --network eth \
|
|
89
|
+
--to "$RECIPIENT_ADDRESS" \
|
|
90
|
+
--asset ETH --amount 0.01 --dry-run
|
|
91
|
+
|
|
92
|
+
echo '{"password":"vault-password"}' |
|
|
93
|
+
hodl send --wallet treasury --network eth \
|
|
94
|
+
--to "$RECIPIENT_ADDRESS" \
|
|
95
|
+
--asset ETH --amount 0.01 --yes --request-id payment-001
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Successful commands write an envelope such as
|
|
99
|
+
`{"version":1,"ok":true,"command":"balance","data":{...}}` to stdout.
|
|
100
|
+
Failures write the equivalent `ok:false` envelope to stderr and return a
|
|
101
|
+
non-zero exit code. Amounts, balances, fees, and base units are JSON strings so
|
|
102
|
+
large values and token decimals remain exact.
|
|
103
|
+
|
|
104
|
+
Named profiles live under `~/.HODL/profiles/`. The special profile `default`
|
|
105
|
+
continues to use the existing `~/.HODL/persist.json` vault. A real transfer
|
|
106
|
+
requires both `--yes` and a unique `--request-id`; retries reuse the previously
|
|
107
|
+
prepared signed transaction instead of creating a second payment.
|
|
108
|
+
|
|
70
109
|
## 🔒 Security
|
|
71
110
|
|
|
72
111
|
### 🔍 Security Audit
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { WalletService } from './wallet-service.js';
|
|
2
|
+
export type AgentCliIO = {
|
|
3
|
+
readStdin(): Promise<string>;
|
|
4
|
+
writeStdout(value: string): void;
|
|
5
|
+
writeStderr(value: string): void;
|
|
6
|
+
};
|
|
7
|
+
export type AgentCliOptions = {
|
|
8
|
+
service?: WalletService;
|
|
9
|
+
io?: AgentCliIO;
|
|
10
|
+
};
|
|
11
|
+
export declare function runAgentCli(argv: string[], options?: AgentCliOptions): Promise<number>;
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { parseArgs } from 'node:util';
|
|
2
|
+
import { AgentError } from './agent-errors.js';
|
|
3
|
+
import { WalletService } from './wallet-service.js';
|
|
4
|
+
const defaultIO = {
|
|
5
|
+
async readStdin() {
|
|
6
|
+
if (process.stdin.isTTY) {
|
|
7
|
+
throw new AgentError('STDIN_REQUIRED', 'A JSON object is required on stdin.', 2);
|
|
8
|
+
}
|
|
9
|
+
const chunks = [];
|
|
10
|
+
for await (const chunk of process.stdin) {
|
|
11
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
12
|
+
}
|
|
13
|
+
const input = Buffer.concat(chunks);
|
|
14
|
+
try {
|
|
15
|
+
return input.toString('utf8');
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
input.fill(0);
|
|
19
|
+
chunks.forEach(chunk => chunk.fill(0));
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
writeStdout(value) {
|
|
23
|
+
process.stdout.write(value);
|
|
24
|
+
},
|
|
25
|
+
writeStderr(value) {
|
|
26
|
+
process.stderr.write(value);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export async function runAgentCli(argv, options = {}) {
|
|
30
|
+
const service = options.service || new WalletService();
|
|
31
|
+
const io = options.io || defaultIO;
|
|
32
|
+
let command = argv.slice(0, 2).join('.');
|
|
33
|
+
try {
|
|
34
|
+
const result = await execute(argv, service, io, value => {
|
|
35
|
+
command = value;
|
|
36
|
+
});
|
|
37
|
+
io.writeStdout(`${JSON.stringify({
|
|
38
|
+
version: 1,
|
|
39
|
+
ok: true,
|
|
40
|
+
command,
|
|
41
|
+
data: result
|
|
42
|
+
})}\n`);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const agentError = error instanceof AgentError
|
|
47
|
+
? error
|
|
48
|
+
: new AgentError('INTERNAL_ERROR', 'Unexpected internal error.', 5);
|
|
49
|
+
io.writeStderr(`${JSON.stringify({
|
|
50
|
+
version: 1,
|
|
51
|
+
ok: false,
|
|
52
|
+
error: {
|
|
53
|
+
code: agentError.code,
|
|
54
|
+
message: agentError.message,
|
|
55
|
+
...(agentError.details ? { details: agentError.details } : {})
|
|
56
|
+
}
|
|
57
|
+
})}\n`);
|
|
58
|
+
return agentError.exitCode;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function execute(argv, service, io, setCommand) {
|
|
62
|
+
if (argv[0] === 'networks') {
|
|
63
|
+
setCommand('networks');
|
|
64
|
+
requireNoArguments(argv.slice(1));
|
|
65
|
+
return { networks: service.listNetworks() };
|
|
66
|
+
}
|
|
67
|
+
if (argv[0] === 'wallet') {
|
|
68
|
+
return executeWallet(argv.slice(1), service, io, setCommand);
|
|
69
|
+
}
|
|
70
|
+
if (argv[0] === 'balance') {
|
|
71
|
+
setCommand('balance');
|
|
72
|
+
const values = parseOptions(argv.slice(1), {
|
|
73
|
+
network: { type: 'string' },
|
|
74
|
+
wallet: { type: 'string' },
|
|
75
|
+
address: { type: 'string' },
|
|
76
|
+
asset: { type: 'string' }
|
|
77
|
+
});
|
|
78
|
+
const network = requiredString(values, 'network');
|
|
79
|
+
const wallet = optionalString(values, 'wallet');
|
|
80
|
+
const address = optionalString(values, 'address');
|
|
81
|
+
if ((wallet ? 1 : 0) + (address ? 1 : 0) !== 1) {
|
|
82
|
+
throw new AgentError('INVALID_ARGUMENT', 'Balance requires exactly one of --wallet or --address.', 2);
|
|
83
|
+
}
|
|
84
|
+
let input;
|
|
85
|
+
try {
|
|
86
|
+
input = wallet ? await readSecretInput(io, ['password'], ['password']) : undefined;
|
|
87
|
+
return await service.getBalances({
|
|
88
|
+
network,
|
|
89
|
+
wallet,
|
|
90
|
+
password: input?.password,
|
|
91
|
+
address,
|
|
92
|
+
asset: optionalString(values, 'asset')
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
clearSecrets(input);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (argv[0] === 'send') {
|
|
100
|
+
setCommand('send');
|
|
101
|
+
const values = parseOptions(argv.slice(1), {
|
|
102
|
+
wallet: { type: 'string' },
|
|
103
|
+
network: { type: 'string' },
|
|
104
|
+
to: { type: 'string' },
|
|
105
|
+
asset: { type: 'string' },
|
|
106
|
+
amount: { type: 'string' },
|
|
107
|
+
'dry-run': { type: 'boolean' },
|
|
108
|
+
yes: { type: 'boolean' },
|
|
109
|
+
'request-id': { type: 'string' }
|
|
110
|
+
});
|
|
111
|
+
const dryRun = values['dry-run'] === true;
|
|
112
|
+
const yes = values.yes === true;
|
|
113
|
+
const requestId = optionalString(values, 'request-id');
|
|
114
|
+
if (dryRun === yes) {
|
|
115
|
+
throw new AgentError('INVALID_ARGUMENT', 'Send requires either --dry-run or --yes, but not both.', 2);
|
|
116
|
+
}
|
|
117
|
+
if ((dryRun && requestId) || (yes && !requestId)) {
|
|
118
|
+
throw new AgentError('INVALID_ARGUMENT', '--request-id is required with --yes and forbidden with --dry-run.', 2);
|
|
119
|
+
}
|
|
120
|
+
let input;
|
|
121
|
+
try {
|
|
122
|
+
input = await readSecretInput(io, ['password'], ['password']);
|
|
123
|
+
return await service.send({
|
|
124
|
+
wallet: requiredString(values, 'wallet'),
|
|
125
|
+
password: input.password,
|
|
126
|
+
network: requiredString(values, 'network'),
|
|
127
|
+
to: requiredString(values, 'to'),
|
|
128
|
+
asset: requiredString(values, 'asset'),
|
|
129
|
+
amount: requiredString(values, 'amount'),
|
|
130
|
+
dryRun,
|
|
131
|
+
requestId
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
clearSecrets(input);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
throw new AgentError('INVALID_ARGUMENT', `Unknown command: ${argv[0] || ''}.`, 2);
|
|
139
|
+
}
|
|
140
|
+
async function executeWallet(argv, service, io, setCommand) {
|
|
141
|
+
const action = argv[0];
|
|
142
|
+
setCommand(`wallet.${action || ''}`);
|
|
143
|
+
if (action === 'list') {
|
|
144
|
+
requireNoArguments(argv.slice(1));
|
|
145
|
+
return { wallets: service.listProfiles() };
|
|
146
|
+
}
|
|
147
|
+
if (action === 'create') {
|
|
148
|
+
const values = parseOptions(argv.slice(1), {
|
|
149
|
+
wallet: { type: 'string' },
|
|
150
|
+
words: { type: 'string' },
|
|
151
|
+
'reveal-secrets': { type: 'boolean' }
|
|
152
|
+
});
|
|
153
|
+
const wordsValue = requiredString(values, 'words');
|
|
154
|
+
if (wordsValue !== '12' && wordsValue !== '24') {
|
|
155
|
+
throw new AgentError('INVALID_ARGUMENT', '--words must be 12 or 24.', 2);
|
|
156
|
+
}
|
|
157
|
+
let input;
|
|
158
|
+
try {
|
|
159
|
+
input = await readSecretInput(io, ['password'], ['password']);
|
|
160
|
+
return await service.createProfile(requiredString(values, 'wallet'), input.password, Number(wordsValue), values['reveal-secrets'] === true);
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
clearSecrets(input);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (action === 'import') {
|
|
167
|
+
const values = parseOptions(argv.slice(1), {
|
|
168
|
+
wallet: { type: 'string' },
|
|
169
|
+
type: { type: 'string' },
|
|
170
|
+
network: { type: 'string' }
|
|
171
|
+
});
|
|
172
|
+
const wallet = requiredString(values, 'wallet');
|
|
173
|
+
const type = requiredString(values, 'type');
|
|
174
|
+
const network = optionalString(values, 'network');
|
|
175
|
+
if (type === 'mnemonic') {
|
|
176
|
+
if (network) {
|
|
177
|
+
throw new AgentError('INVALID_ARGUMENT', '--network is forbidden for mnemonic import.', 2);
|
|
178
|
+
}
|
|
179
|
+
let input;
|
|
180
|
+
try {
|
|
181
|
+
input = await readSecretInput(io, ['password', 'mnemonic'], ['password', 'mnemonic']);
|
|
182
|
+
return await service.importMnemonic(wallet, input.password, input.mnemonic);
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
clearSecrets(input);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (type === 'private-key') {
|
|
189
|
+
if (!network) {
|
|
190
|
+
throw new AgentError('INVALID_ARGUMENT', '--network is required for private-key import.', 2);
|
|
191
|
+
}
|
|
192
|
+
let input;
|
|
193
|
+
try {
|
|
194
|
+
input = await readSecretInput(io, ['password', 'privateKey'], ['password', 'privateKey']);
|
|
195
|
+
return await service.importPrivateKey(wallet, input.password, network, input.privateKey);
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
clearSecrets(input);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
throw new AgentError('INVALID_ARGUMENT', '--type must be mnemonic or private-key.', 2);
|
|
202
|
+
}
|
|
203
|
+
if (action === 'address') {
|
|
204
|
+
const values = parseOptions(argv.slice(1), {
|
|
205
|
+
wallet: { type: 'string' },
|
|
206
|
+
network: { type: 'string' }
|
|
207
|
+
});
|
|
208
|
+
let input;
|
|
209
|
+
try {
|
|
210
|
+
input = await readSecretInput(io, ['password'], ['password']);
|
|
211
|
+
return await service.getAddress(requiredString(values, 'wallet'), input.password, requiredString(values, 'network'));
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
clearSecrets(input);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
throw new AgentError('INVALID_ARGUMENT', `Unknown wallet command: ${action || ''}.`, 2);
|
|
218
|
+
}
|
|
219
|
+
function parseOptions(args, options) {
|
|
220
|
+
ensureNoDuplicateOptions(args);
|
|
221
|
+
try {
|
|
222
|
+
const parsed = parseArgs({
|
|
223
|
+
args,
|
|
224
|
+
options,
|
|
225
|
+
strict: true,
|
|
226
|
+
allowPositionals: false
|
|
227
|
+
});
|
|
228
|
+
return parsed.values;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
throw new AgentError('INVALID_ARGUMENT', error.message, 2);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function ensureNoDuplicateOptions(args) {
|
|
235
|
+
const seen = new Set();
|
|
236
|
+
for (const argument of args) {
|
|
237
|
+
if (!argument.startsWith('--')) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const name = argument.slice(2).split('=', 1)[0];
|
|
241
|
+
if (seen.has(name)) {
|
|
242
|
+
throw new AgentError('INVALID_ARGUMENT', `Option --${name} was provided more than once.`, 2);
|
|
243
|
+
}
|
|
244
|
+
seen.add(name);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function requireNoArguments(args) {
|
|
248
|
+
if (args.length > 0) {
|
|
249
|
+
throw new AgentError('INVALID_ARGUMENT', 'Command does not accept arguments.', 2);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function requiredString(values, name) {
|
|
253
|
+
const value = optionalString(values, name);
|
|
254
|
+
if (!value) {
|
|
255
|
+
throw new AgentError('INVALID_ARGUMENT', `--${name} is required.`, 2);
|
|
256
|
+
}
|
|
257
|
+
return value;
|
|
258
|
+
}
|
|
259
|
+
function optionalString(values, name) {
|
|
260
|
+
const value = values[name];
|
|
261
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
262
|
+
}
|
|
263
|
+
async function readSecretInput(io, allowedKeys, requiredKeys) {
|
|
264
|
+
const raw = await io.readStdin();
|
|
265
|
+
if (!raw.trim()) {
|
|
266
|
+
throw new AgentError('STDIN_REQUIRED', 'A JSON object is required on stdin.', 2);
|
|
267
|
+
}
|
|
268
|
+
let value;
|
|
269
|
+
try {
|
|
270
|
+
value = JSON.parse(raw);
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
throw new AgentError('INVALID_STDIN', 'stdin must contain one valid JSON object.', 2);
|
|
274
|
+
}
|
|
275
|
+
if (!isRecord(value)) {
|
|
276
|
+
throw new AgentError('INVALID_STDIN', 'stdin must contain a JSON object.', 2);
|
|
277
|
+
}
|
|
278
|
+
const unknownKeys = Object.keys(value).filter(key => !allowedKeys.includes(key));
|
|
279
|
+
if (unknownKeys.length > 0) {
|
|
280
|
+
throw new AgentError('INVALID_STDIN', `Unknown stdin fields: ${unknownKeys.join(', ')}.`, 2);
|
|
281
|
+
}
|
|
282
|
+
const result = {};
|
|
283
|
+
for (const key of allowedKeys) {
|
|
284
|
+
const field = value[key];
|
|
285
|
+
if (field !== undefined && (typeof field !== 'string' || field.length === 0)) {
|
|
286
|
+
throw new AgentError('INVALID_STDIN', `${key} must be a non-empty string.`, 2);
|
|
287
|
+
}
|
|
288
|
+
if (typeof field === 'string') {
|
|
289
|
+
result[key] = field;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
for (const key of requiredKeys) {
|
|
293
|
+
if (!result[key]) {
|
|
294
|
+
throw new AgentError('INVALID_STDIN', `${key} is required on stdin.`, 2);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return result;
|
|
298
|
+
}
|
|
299
|
+
function clearSecrets(input) {
|
|
300
|
+
if (!input) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
for (const key of Object.keys(input)) {
|
|
304
|
+
input[key] = '';
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function isRecord(value) {
|
|
308
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=agent-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-cli.js","sourceRoot":"","sources":["../agent-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type AgentErrorCode = 'INVALID_ARGUMENT' | 'INVALID_STDIN' | 'STDIN_REQUIRED' | 'PROFILE_EXISTS' | 'PROFILE_NOT_FOUND' | 'WRONG_PASSWORD' | 'ACCOUNT_NOT_FOUND' | 'PROFILE_LOCKED' | 'IDEMPOTENCY_CONFLICT' | 'NETWORK_ERROR' | 'TRANSFER_FAILED' | 'BROADCAST_UNKNOWN' | 'INTERNAL_ERROR';
|
|
2
|
+
export declare class AgentError extends Error {
|
|
3
|
+
readonly code: AgentErrorCode;
|
|
4
|
+
readonly exitCode: 2 | 3 | 4 | 5;
|
|
5
|
+
readonly details?: Record<string, unknown>;
|
|
6
|
+
constructor(code: AgentErrorCode, message: string, exitCode: 2 | 3 | 4 | 5, details?: Record<string, unknown>);
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class AgentError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
exitCode;
|
|
4
|
+
details;
|
|
5
|
+
constructor(code, message, exitCode, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'AgentError';
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.exitCode = exitCode;
|
|
10
|
+
this.details = details;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=agent-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-errors.js","sourceRoot":"","sources":["../agent-errors.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACxB,IAAI,CAAiB;IACrB,QAAQ,CAAgB;IACxB,OAAO,CAA2B;IAE3C,YACI,IAAoB,EACpB,OAAe,EACf,QAAuB,EACvB,OAAiC;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;CACJ"}
|
package/dist/amounts.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const DECIMAL_PATTERN = /^(0|[1-9]\d*)(?:\.(\d+))?$/;
|
|
2
|
+
export function parseDecimalToUnits(amount, decimals) {
|
|
3
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
4
|
+
throw new TypeError('Decimals must be a non-negative integer.');
|
|
5
|
+
}
|
|
6
|
+
const match = DECIMAL_PATTERN.exec(amount);
|
|
7
|
+
if (!match) {
|
|
8
|
+
throw new TypeError('Amount must be a plain positive decimal string.');
|
|
9
|
+
}
|
|
10
|
+
const fraction = match[2] || '';
|
|
11
|
+
if (fraction.length > decimals) {
|
|
12
|
+
throw new TypeError(`Amount supports at most ${decimals} decimal places.`);
|
|
13
|
+
}
|
|
14
|
+
const wholeUnits = BigInt(match[1]) * (10n ** BigInt(decimals));
|
|
15
|
+
const fractionalUnits = fraction
|
|
16
|
+
? BigInt(fraction.padEnd(decimals, '0'))
|
|
17
|
+
: 0n;
|
|
18
|
+
const units = wholeUnits + fractionalUnits;
|
|
19
|
+
if (units <= 0n) {
|
|
20
|
+
throw new TypeError('Amount must be greater than zero.');
|
|
21
|
+
}
|
|
22
|
+
return units;
|
|
23
|
+
}
|
|
24
|
+
export function formatUnits(units, decimals) {
|
|
25
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
26
|
+
throw new TypeError('Decimals must be a non-negative integer.');
|
|
27
|
+
}
|
|
28
|
+
const value = typeof units === 'bigint' ? units : BigInt(units);
|
|
29
|
+
const negative = value < 0n;
|
|
30
|
+
const absolute = negative ? -value : value;
|
|
31
|
+
if (decimals === 0) {
|
|
32
|
+
return `${negative ? '-' : ''}${absolute}`;
|
|
33
|
+
}
|
|
34
|
+
const padded = absolute.toString().padStart(decimals + 1, '0');
|
|
35
|
+
const whole = padded.slice(0, -decimals);
|
|
36
|
+
const fraction = padded.slice(-decimals).replace(/0+$/, '');
|
|
37
|
+
return `${negative ? '-' : ''}${whole}${fraction ? `.${fraction}` : ''}`;
|
|
38
|
+
}
|
|
39
|
+
export function normalizeDecimal(amount) {
|
|
40
|
+
const match = DECIMAL_PATTERN.exec(amount);
|
|
41
|
+
if (!match) {
|
|
42
|
+
throw new TypeError('Amount must be a plain positive decimal string.');
|
|
43
|
+
}
|
|
44
|
+
const fraction = (match[2] || '').replace(/0+$/, '');
|
|
45
|
+
const normalized = fraction ? `${match[1]}.${fraction}` : match[1];
|
|
46
|
+
if (BigInt(match[1]) === 0n && !/[1-9]/.test(fraction)) {
|
|
47
|
+
throw new TypeError('Amount must be greater than zero.');
|
|
48
|
+
}
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=amounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amounts.js","sourceRoot":"","sources":["../amounts.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
export declare function selectCliMode(argv: string[]): 'interactive' | 'agent';
|
|
3
|
+
interface CliDependencies {
|
|
4
|
+
runInteractive?: () => Promise<void>;
|
|
5
|
+
runAgent?: (argv: string[]) => Promise<number>;
|
|
6
|
+
}
|
|
7
|
+
export declare function runCli(argv: string[], dependencies?: CliDependencies): Promise<number>;
|
|
2
8
|
export {};
|