hodl-wallet 2.0.4 → 2.0.5

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.
Files changed (81) hide show
  1. package/README.md +79 -2
  2. package/dist/agent-cli.js +75 -0
  3. package/dist/agent-cli.js.map +1 -1
  4. package/dist/agent-errors.d.ts +1 -1
  5. package/dist/agent-errors.js.map +1 -1
  6. package/dist/index.js +130 -77
  7. package/dist/index.js.map +1 -1
  8. package/dist/network/arb.d.ts +1 -0
  9. package/dist/network/arb.js +2 -1
  10. package/dist/network/arb.js.map +1 -1
  11. package/dist/network/avax.d.ts +1 -0
  12. package/dist/network/avax.js +2 -1
  13. package/dist/network/avax.js.map +1 -1
  14. package/dist/network/bsc.d.ts +1 -0
  15. package/dist/network/bsc.js +2 -1
  16. package/dist/network/bsc.js.map +1 -1
  17. package/dist/network/eth.d.ts +1 -0
  18. package/dist/network/eth.js +2 -1
  19. package/dist/network/eth.js.map +1 -1
  20. package/dist/network/ftm.d.ts +1 -0
  21. package/dist/network/ftm.js +2 -1
  22. package/dist/network/ftm.js.map +1 -1
  23. package/dist/network/hyperliquid.d.ts +1 -0
  24. package/dist/network/hyperliquid.js +2 -1
  25. package/dist/network/hyperliquid.js.map +1 -1
  26. package/dist/network/lib/BitcoinNetwork.d.ts +2 -0
  27. package/dist/network/lib/BitcoinNetwork.js +11 -11
  28. package/dist/network/lib/BitcoinNetwork.js.map +1 -1
  29. package/dist/network/op.d.ts +1 -0
  30. package/dist/network/op.js +2 -1
  31. package/dist/network/op.js.map +1 -1
  32. package/dist/network/pol.d.ts +1 -0
  33. package/dist/network/pol.js +2 -1
  34. package/dist/network/pol.js.map +1 -1
  35. package/dist/network/types.d.ts +1 -0
  36. package/dist/network-registry.d.ts +1 -0
  37. package/dist/network-registry.js +3 -0
  38. package/dist/network-registry.js.map +1 -1
  39. package/dist/persist.d.ts +2 -0
  40. package/dist/persist.js +21 -0
  41. package/dist/persist.js.map +1 -1
  42. package/dist/profile-lock.d.ts +4 -0
  43. package/dist/profile-lock.js +9 -1
  44. package/dist/profile-lock.js.map +1 -1
  45. package/dist/swap/bitcoin.d.ts +34 -0
  46. package/dist/swap/bitcoin.js +179 -0
  47. package/dist/swap/bitcoin.js.map +1 -0
  48. package/dist/swap/chain.d.ts +49 -0
  49. package/dist/swap/chain.js +255 -0
  50. package/dist/swap/chain.js.map +1 -0
  51. package/dist/swap/config.d.ts +68 -0
  52. package/dist/swap/config.js +46 -0
  53. package/dist/swap/config.js.map +1 -0
  54. package/dist/swap/http.d.ts +14 -0
  55. package/dist/swap/http.js +70 -0
  56. package/dist/swap/http.js.map +1 -0
  57. package/dist/swap/providers.d.ts +24 -0
  58. package/dist/swap/providers.js +424 -0
  59. package/dist/swap/providers.js.map +1 -0
  60. package/dist/swap/routes.d.ts +145 -0
  61. package/dist/swap/routes.js +48 -0
  62. package/dist/swap/routes.js.map +1 -0
  63. package/dist/swap/service.d.ts +104 -0
  64. package/dist/swap/service.js +512 -0
  65. package/dist/swap/service.js.map +1 -0
  66. package/dist/swap/storage.d.ts +3 -0
  67. package/dist/swap/storage.js +28 -0
  68. package/dist/swap/storage.js.map +1 -0
  69. package/dist/swap/types.d.ts +140 -0
  70. package/dist/swap/types.js +2 -0
  71. package/dist/swap/types.js.map +1 -0
  72. package/dist/swap/ui.d.ts +3 -0
  73. package/dist/swap/ui.js +257 -0
  74. package/dist/swap/ui.js.map +1 -0
  75. package/dist/transfer-service.d.ts +38 -0
  76. package/dist/transfer-service.js +177 -0
  77. package/dist/transfer-service.js.map +1 -0
  78. package/dist/wallet-service.d.ts +22 -6
  79. package/dist/wallet-service.js +36 -171
  80. package/dist/wallet-service.js.map +1 -1
  81. package/package.json +99 -92
package/README.md CHANGED
@@ -17,7 +17,7 @@ Let's face it, Trust Wallet's sluggishness and annoying ads are so last season.
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
20
- - 🌐 Support for Bitcoin and Ethereum. Binance Smart Chain, Polygon, Avalanche, Optimism, Arbitrum, Fantom, and Hyperliquid.
20
+ - 🌐 Support for Bitcoin and Ethereum. BNB Smart Chain (BSC), Polygon, Avalanche, Optimism, Arbitrum, Fantom, and Hyperliquid.
21
21
 
22
22
  That's it! Follow the prompts and you're in crypto heaven.
23
23
 
@@ -46,7 +46,7 @@ Seamlessly manage your assets on multiple networks. HODL Wallet supports the fol
46
46
  - Bitcoin
47
47
  - EVM
48
48
  - Ethereum
49
- - Binance Smart Chain
49
+ - BNB Smart Chain (BSC)
50
50
  - Polygon
51
51
  - Optimism
52
52
  - Arbitrum One
@@ -106,6 +106,83 @@ continues to use the existing `~/.HODL/persist.json` vault. A real transfer
106
106
  requires both `--yes` and a unique `--request-id`; retries reuse the previously
107
107
  prepared signed transaction instead of creating a second payment.
108
108
 
109
+ ### Swap between USDT on BSC and native Bitcoin
110
+
111
+ The Swap menu appears on BSC and Bitcoin and shows the direction explicitly:
112
+ **USDT (BSC) → BTC (Bitcoin)** or **BTC (Bitcoin) → USDT (BSC)**.
113
+ **Track Swaps** is inside that menu and follows both directions regardless of the
114
+ selected network. Tracking only reads status and never signs or submits a
115
+ transaction. The destination account is offered by default; you can also type
116
+ an external address for the destination network. Importing only an EVM private
117
+ key does not create a Bitcoin account.
118
+
119
+ HODL compares single-execution Chainflip with automatic THORChain streaming,
120
+ which divides the exchange into smaller swaps to reduce price impact. Unavailable,
121
+ paused, or unsupported routes are shown separately. DCA, boosts and HODL affiliate
122
+ commissions are not enabled. Streaming and its estimated duration are shown
123
+ before confirmation. The best available quote is ranked by estimated destination value after accounting for the separate source-network fee: BNB for BSC, or BTC for Bitcoin.
124
+ Total cost includes fees and price impact against a recent CoinGecko reference;
125
+ it is an estimate, not a guaranteed execution price. There is no fixed cost cap:
126
+ review and accept the displayed cost before executing.
127
+
128
+ ```bash
129
+ hodl swap destination --wallet treasury < "$WALLET_SECRET_INPUT"
130
+ hodl swap quote --wallet treasury --amount 100 < "$WALLET_SECRET_INPUT"
131
+ hodl swap quote --wallet treasury --amount 100 --to "$BTC_ADDRESS" < "$WALLET_SECRET_INPUT"
132
+ hodl swap destination --wallet treasury --network btc < "$WALLET_SECRET_INPUT"
133
+ hodl swap quote --wallet treasury --network btc --amount 0.01 --to "$BSC_ADDRESS" < "$WALLET_SECRET_INPUT"
134
+ hodl swap execute --wallet treasury --quote-id "$QUOTE_ID" \
135
+ --request-id swap-001 --yes --watch < "$WALLET_SECRET_INPUT"
136
+ hodl swap status --wallet treasury --request-id swap-001 --watch < "$WALLET_SECRET_INPUT"
137
+ hodl swap list --wallet treasury < "$WALLET_SECRET_INPUT"
138
+ hodl swap resume --wallet treasury --request-id swap-001 --yes --watch < "$WALLET_SECRET_INPUT"
139
+ ```
140
+
141
+ `WALLET_SECRET_INPUT` identifies your existing protected JSON stdin source;
142
+ passwords remain off command-line arguments. `quote` saves a short-lived quote
143
+ but does not sign, open a deposit channel or send funds. `execute --yes` accepts
144
+ that exact quote, including its destination, minimum output and maximum source-network fee
145
+ budget. `--watch` emits JSONL progress envelopes followed by the final result.
146
+ Without `--watch`, execution returns after publishing the next funding step;
147
+ use `resume --yes` to continue after an approval confirms. `status` only observes
148
+ and never submits a transaction. Only one unfinished swap per profile is
149
+ allowed, and it blocks other HODL BSC and Bitcoin transfers until resolved.
150
+
151
+ The minimum destination amount for a full swap limits deterioration from the accepted quote to 0.5%.
152
+ This is separate from total fees. Source approvals grant only the required
153
+ amount to the configured THORChain router. Signed transactions and provider
154
+ identifiers are saved in the encrypted wallet before broadcasting; a retry uses
155
+ the same signed transaction and request ID. Expired quotes or channels cannot
156
+ start a new deposit. Closing HODL stops local monitoring and any remaining
157
+ funding steps; it does not cancel a deposit already sent to the protocol.
158
+
159
+ Bitcoin funding spends confirmed inputs selected when quoting and reserves the
160
+ accepted fee budget plus change to the original Bitcoin address. Changed inputs
161
+ or a higher fee rate require a new quote. THORChain deposits include its extended
162
+ memo outputs; their cost is included in the displayed source-network fee.
163
+
164
+ Progress distinguishes source funding, provider processing, payout and
165
+ confirmations. Completion requires the exact destination payment with **3 Bitcoin
166
+ confirmations** or **15 BSC confirmations**, according to the route. Read failures
167
+ retain the last known state and report an update error.
168
+
169
+ Refunds return the source asset to the original sender: USDT on BSC for the
170
+ forward route, BTC for the reverse route. Refund and network fees may be deducted.
171
+ Streaming can finish partially, with a destination payment and a source refund.
172
+ The payment can be below the full-swap minimum in that case. HODL reports
173
+ `partial_completed` only after the provider reports every outbound and both
174
+ payments are verified; `partial_pending` means verification is still in progress.
175
+ A completed exchange with a delayed payout cannot automatically reverse into the
176
+ source asset. Protocol failures can require provider support.
177
+
178
+ The JSON CLI defaults to BSC when `--network` is omitted. Execute, resume and
179
+ status use the route stored with the quote or operation; they do not take a new
180
+ network selection. Existing BSC-to-Bitcoin operations remain readable.
181
+
182
+ Swap endpoints, timeouts, gas budgets and confirmation policy are centralized
183
+ in `swap/config.ts`. Tests use temporary wallets and simulated networks:
184
+ `pnpm run test:swap`. These tests do not transfer real funds.
185
+
109
186
  ## 🔒 Security
110
187
 
111
188
  ### 🔍 Security Audit
package/dist/agent-cli.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { parseArgs } from 'node:util';
2
2
  import { AgentError } from './agent-errors.js';
3
3
  import { WalletService } from './wallet-service.js';
4
+ import { swapConfig } from './swap/config.js';
5
+ import { terminalSwapStates } from './swap/types.js';
6
+ import { setTimeout as delay } from 'node:timers/promises';
4
7
  const defaultIO = {
5
8
  async readStdin() {
6
9
  if (process.stdin.isTTY) {
@@ -67,6 +70,9 @@ async function execute(argv, service, io, setCommand) {
67
70
  if (argv[0] === 'wallet') {
68
71
  return executeWallet(argv.slice(1), service, io, setCommand);
69
72
  }
73
+ if (argv[0] === 'swap') {
74
+ return executeSwap(argv.slice(1), service, io, setCommand);
75
+ }
70
76
  if (argv[0] === 'balance') {
71
77
  setCommand('balance');
72
78
  const values = parseOptions(argv.slice(1), {
@@ -137,6 +143,75 @@ async function execute(argv, service, io, setCommand) {
137
143
  }
138
144
  throw new AgentError('INVALID_ARGUMENT', `Unknown command: ${argv[0] || ''}.`, 2);
139
145
  }
146
+ async function executeSwap(argv, service, io, setCommand) {
147
+ const action = argv[0];
148
+ setCommand(`swap.${action || ''}`);
149
+ const options = { wallet: { type: 'string' } };
150
+ switch (action) {
151
+ case 'quote':
152
+ Object.assign(options, { amount: { type: 'string' }, to: { type: 'string' }, network: { type: 'string' } });
153
+ break;
154
+ case 'execute':
155
+ Object.assign(options, { 'quote-id': { type: 'string' }, 'request-id': { type: 'string' }, yes: { type: 'boolean' }, watch: { type: 'boolean' } });
156
+ break;
157
+ case 'resume':
158
+ Object.assign(options, { 'request-id': { type: 'string' }, yes: { type: 'boolean' }, watch: { type: 'boolean' } });
159
+ break;
160
+ case 'status':
161
+ Object.assign(options, { 'request-id': { type: 'string' }, watch: { type: 'boolean' } });
162
+ break;
163
+ case 'destination':
164
+ Object.assign(options, { network: { type: 'string' } });
165
+ break;
166
+ case 'list': break;
167
+ default: throw new AgentError('INVALID_ARGUMENT', 'Use swap quote, execute, resume, status, list or destination.', 2);
168
+ }
169
+ const values = parseOptions(argv.slice(1), options);
170
+ const wallet = requiredString(values, 'wallet');
171
+ let command;
172
+ switch (action) {
173
+ case 'quote':
174
+ command = { action, amount: requiredString(values, 'amount'), to: optionalString(values, 'to'), network: optionalString(values, 'network') };
175
+ break;
176
+ case 'execute':
177
+ if (values.yes !== true)
178
+ throw new AgentError('INVALID_ARGUMENT', 'Executing a swap requires --yes and an accepted --quote-id.', 2);
179
+ command = { action, quoteId: requiredString(values, 'quote-id'), requestId: requiredString(values, 'request-id') };
180
+ break;
181
+ case 'resume':
182
+ if (values.yes !== true)
183
+ throw new AgentError('INVALID_ARGUMENT', 'Resuming swap funding requires --yes.', 2);
184
+ command = { action, requestId: requiredString(values, 'request-id') };
185
+ break;
186
+ case 'status':
187
+ command = { action, requestId: requiredString(values, 'request-id') };
188
+ break;
189
+ case 'destination':
190
+ command = { action, network: optionalString(values, 'network') };
191
+ break;
192
+ default: command = { action };
193
+ }
194
+ let input;
195
+ try {
196
+ input = await readSecretInput(io, ['password'], ['password']);
197
+ let result = await service.swap(wallet, input.password, command);
198
+ if (values.watch !== true)
199
+ return result;
200
+ const requestId = requiredString(values, 'request-id');
201
+ const watchAction = action === 'status' ? 'status' : 'resume';
202
+ while (true) {
203
+ const state = result.state;
204
+ if (terminalSwapStates.includes(state) || state === 'needs_attention')
205
+ return result;
206
+ io.writeStdout(`${JSON.stringify({ version: 1, ok: true, command: 'swap.progress', data: result })}\n`);
207
+ await delay(swapConfig.pollIntervalMs);
208
+ result = await service.swap(wallet, input.password, { action: watchAction, requestId });
209
+ }
210
+ }
211
+ finally {
212
+ clearSecrets(input);
213
+ }
214
+ }
140
215
  async function executeWallet(argv, service, io, setCommand) {
141
216
  const action = argv[0];
142
217
  setCommand(`wallet.${action || ''}`);
@@ -1 +1 @@
1
- {"version":3,"file":"agent-cli.js","sourceRoot":"","sources":["../agent-cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-cli.js","sourceRoot":"","sources":["../agent-cli.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
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';
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' | 'SWAP_IN_PROGRESS' | 'SWAP_QUOTE_EXPIRED' | 'INTERNAL_ERROR';
2
2
  export declare class AgentError extends Error {
3
3
  readonly code: AgentErrorCode;
4
4
  readonly exitCode: 2 | 3 | 4 | 5;
@@ -1 +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"}
1
+ {"version":3,"file":"agent-errors.js","sourceRoot":"","sources":["../agent-errors.ts"],"names":[],"mappings":"AAiBA,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/index.js CHANGED
@@ -1,11 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'fs';
3
+ import crypto from 'node:crypto';
4
+ import { AgentError } from './agent-errors.js';
5
+ import { TransferService } from './transfer-service.js';
3
6
  import path from 'path';
4
7
  import inquirer from 'inquirer';
5
8
  import Persist from './persist.js';
6
9
  import { normalizeDecimal } from './amounts.js';
7
- import { NetworkRegistry } from './network-registry.js';
8
- import { ProfileLock } from './profile-lock.js';
10
+ import { NetworkRegistry, networkStorageName } from './network-registry.js';
11
+ import { ProfileLock, ProfileLockedError } from './profile-lock.js';
12
+ import { SwapService } from './swap/service.js';
13
+ import { routeForNetwork } from './swap/routes.js';
14
+ import { startSwapMenu } from './swap/ui.js';
9
15
  import { fileURLToPath } from 'url';
10
16
  import Table from 'cli-table3';
11
17
  import os from 'os';
@@ -42,7 +48,7 @@ class Wallet {
42
48
  databaseExisted;
43
49
  profileLock;
44
50
  hodlDir;
45
- constructor(encryptionKey) {
51
+ constructor(encryptionKey, profileLock) {
46
52
  const hodlDir = path.join(os.homedir(), '.HODL');
47
53
  this.hodlDir = hodlDir;
48
54
  if (!fs.existsSync(hodlDir)) {
@@ -50,8 +56,7 @@ class Wallet {
50
56
  }
51
57
  fs.chmodSync(hodlDir, 0o700);
52
58
  this.databaseExisted = fs.existsSync(path.join(hodlDir, 'persist.json'));
53
- this.profileLock = new ProfileLock(path.join(hodlDir, '.default.lock'));
54
- this.profileLock.acquire();
59
+ this.profileLock = profileLock;
55
60
  try {
56
61
  this.db = new Persist({ path: hodlDir, encryptionKey });
57
62
  }
@@ -176,8 +181,8 @@ class Wallet {
176
181
  async selectNetwork(networkPlugins, { autoSelect = false } = {}) {
177
182
  // Sort networks by last used timestamp (most recent first)
178
183
  const sortedNetworks = networkPlugins.sort((a, b) => {
179
- const aUsage = this.networkUsage[a.name];
180
- const bUsage = this.networkUsage[b.name];
184
+ const aUsage = this.networkUsage[networkStorageName(a)];
185
+ const bUsage = this.networkUsage[networkStorageName(b)];
181
186
  // Handle old format (number) vs new format (object)
182
187
  const aLastUsed = typeof aUsage === 'object' ? aUsage.lastUsed || 0 : 0;
183
188
  const bLastUsed = typeof bUsage === 'object' ? bUsage.lastUsed || 0 : 0;
@@ -209,10 +214,10 @@ class Wallet {
209
214
  }
210
215
  // Update usage info for the selected network
211
216
  // Handle migration from old format (number) to new format (object)
212
- const currentUsage = this.networkUsage[selectedNetwork.name];
217
+ const currentUsage = this.networkUsage[networkStorageName(selectedNetwork)];
213
218
  if (!currentUsage || typeof currentUsage === 'number' || typeof currentUsage !== 'object' || currentUsage === null || Array.isArray(currentUsage)) {
214
219
  // Old format (number), doesn't exist, or corrupted data - create new object
215
- this.networkUsage[selectedNetwork.name] = {
220
+ this.networkUsage[networkStorageName(selectedNetwork)] = {
216
221
  count: typeof currentUsage === 'number' ? currentUsage + 1 : 1,
217
222
  lastUsed: Date.now()
218
223
  };
@@ -223,7 +228,7 @@ class Wallet {
223
228
  currentUsage.lastUsed = Date.now();
224
229
  }
225
230
  else {
226
- this.networkUsage[selectedNetwork.name] = {
231
+ this.networkUsage[networkStorageName(selectedNetwork)] = {
227
232
  count: 1,
228
233
  lastUsed: Date.now()
229
234
  };
@@ -400,12 +405,34 @@ class Wallet {
400
405
  colWidths: [21, 22]
401
406
  });
402
407
  balances.forEach(([token, balance]) => {
403
- table.push([token, this.formatAmount(balance)]);
408
+ table.push([token, token === 'USDT' ? Number(balance).toFixed(2) : this.formatAmount(balance)]);
404
409
  });
405
410
  console.log(table.toString());
406
411
  }
407
412
  async transferFunds() {
408
- const contacts = await this.db.entries('contact', this.network.name ?? '') || [];
413
+ const service = new TransferService(this.db, this.selectedNetwork, this.network);
414
+ const pending = (await service.list()).filter(transfer => !['confirmed', 'failed'].includes(transfer.status));
415
+ if (pending.length) {
416
+ const { requestId } = await inquirer.prompt({
417
+ type: 'list', name: 'requestId', message: 'A previous transfer is still pending:',
418
+ choices: [
419
+ ...pending.map(transfer => ({
420
+ name: `Check / resume ${transfer.amount} ${transfer.asset} to ${transfer.to} (${transfer.status})`,
421
+ value: transfer.requestId
422
+ })),
423
+ { name: 'New transfer', value: 'new' },
424
+ { name: 'Go back', value: 'back' }
425
+ ]
426
+ });
427
+ if (requestId === 'back')
428
+ return;
429
+ if (requestId !== 'new') {
430
+ const transfer = pending.find(item => item.requestId === requestId);
431
+ await this.submitTransfer(service, transfer.to, transfer.asset, transfer.amount, requestId);
432
+ return;
433
+ }
434
+ }
435
+ const contacts = await this.db.entries('contact', this.storageNetworkName) || [];
409
436
  const addressBook = contacts.map(([address, data]) => ({
410
437
  address,
411
438
  name: data.name
@@ -471,63 +498,40 @@ class Wallet {
471
498
  if (!confirmTransaction) {
472
499
  return;
473
500
  }
474
- const spinner = ora({
475
- text: 'Sending transaction...',
476
- spinner: 'dots'
477
- }).start();
501
+ await this.submitTransfer(service, address, token, transferAmount, crypto.randomUUID());
502
+ }
503
+ async submitTransfer(service, address, token, amount, requestId) {
504
+ const spinner = ora({ text: 'Checking / sending transaction...', spinner: 'dots' }).start();
505
+ let result;
478
506
  try {
479
- let signedTx;
480
- const account = await this.getAccount();
481
- if (!account) {
482
- throw new Error('Account not initialized.');
483
- }
484
- try {
485
- if (token === this.selectedNetwork.nativeToken) {
486
- if (!this.network.handleNativeTransfer) {
487
- throw new Error('Selected network does not support native transfers.');
488
- }
489
- signedTx = await this.network.handleNativeTransfer(account, address, transferAmount);
490
- }
491
- else {
492
- if (!this.network.handleERC20Transfer) {
493
- throw new Error('Selected network does not support token transfers.');
494
- }
495
- signedTx = await this.network.handleERC20Transfer(account, token, address, transferAmount);
496
- }
497
- }
498
- finally {
499
- Persist.clearSensitiveData(account);
500
- }
501
- const receipt = await this.network.sendSignedTransaction(signedTx);
502
- spinner.succeed('Transaction confirmed!');
503
- const transactionHash = receipt?.transactionHash || receipt?.hash || 'UNKNOWN_HASH';
504
- // Calculate the post-transaction balance
505
- let currentBalance = '0';
506
- try {
507
- const walletAddress = await this.getAddress();
508
- // Get the balance AFTER transaction (not before)
509
- if (token === this.selectedNetwork.nativeToken) {
510
- currentBalance = await this.network.getBalance(walletAddress);
511
- }
512
- else {
513
- currentBalance = await this.network.getTokenBalance(walletAddress, token);
514
- }
507
+ result = await service.send({ wallet: 'default', to: address, asset: token, amount, requestId, dryRun: false });
508
+ }
509
+ catch (error) {
510
+ spinner.fail('Could not complete the transfer request.');
511
+ this.displayTransactionError(error);
512
+ if (error instanceof AgentError && error.details?.transactionHash) {
513
+ console.log(`Saved transfer: ${error.details.requestId}`);
514
+ console.log(this.selectedNetwork.explorer + error.details.transactionHash);
515
515
  }
516
- catch (error) {
517
- console.error('Error getting post-transaction balance:', errorMessage(error));
516
+ else {
517
+ console.log(`Request ID: ${requestId}`);
518
518
  }
519
- await this.displayTransactionResult(address, token, transferAmount, transactionHash, currentBalance);
520
- // Add transaction to history
521
- await this.addToTransactions(address, token, transferAmount, transactionHash, currentBalance);
522
- // Check if the address is already in contacts before asking to add it
523
- const existingContact = await this.db.get('contact', this.network.name ?? '', address);
524
- if (!existingContact) {
519
+ console.log('Open Transfer Funds to check or resume any saved request before creating another payment.');
520
+ return;
521
+ }
522
+ spinner.succeed(result.status === 'confirmed' ? 'Transaction confirmed!' : 'Transaction submitted; awaiting confirmation.');
523
+ console.log(`Request ID: ${requestId}`);
524
+ console.log(this.selectedNetwork.explorer + result.transactionHash);
525
+ try {
526
+ const currentBalance = (await this.network.getAssetBalance(result.from, token)).amount;
527
+ await this.addToTransactions(address, token, amount, result.transactionHash, currentBalance);
528
+ await this.displayTransactionResult(address, token, amount, result.transactionHash, currentBalance);
529
+ const existingContact = await this.db.get('contact', this.storageNetworkName, address);
530
+ if (!existingContact)
525
531
  await this.addToAddressBook(address);
526
- }
527
532
  }
528
533
  catch (error) {
529
- spinner.fail('Transaction failed');
530
- this.displayTransactionError(error);
534
+ Wallet.displayError('Transfer recorded; could not update balance, history or contact.', errorMessage(error));
531
535
  }
532
536
  }
533
537
  /**
@@ -590,7 +594,10 @@ class Wallet {
590
594
  balance
591
595
  };
592
596
  const address = await this.getAddress();
593
- await this.db.add('transactions', address, this.selectedNetwork.nativeToken, transaction);
597
+ const history = await this.db.values('transactions', address, this.selectedNetwork.nativeToken) || [];
598
+ if (!history.some(entry => entry.hash === hash)) {
599
+ await this.db.add('transactions', address, this.selectedNetwork.nativeToken, transaction);
600
+ }
594
601
  }
595
602
  async showTransactions() {
596
603
  const address = await this.getAddress();
@@ -605,21 +612,33 @@ class Wallet {
605
612
  history.push(...legacyHistory);
606
613
  history.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
607
614
  }
615
+ const transfers = await new TransferService(this.db, this.selectedNetwork, this.network).list();
616
+ for (const transfer of transfers.filter(item => item.from === address)) {
617
+ const existing = history.find(item => item.hash === transfer.transactionHash);
618
+ if (existing)
619
+ existing.status = transfer.status;
620
+ else
621
+ history.push({
622
+ timestamp: transfer.createdAt, recipient: transfer.to, token: transfer.asset,
623
+ amount: transfer.amount, hash: transfer.transactionHash, status: transfer.status
624
+ });
625
+ }
626
+ history.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
608
627
  const table = new AnyTable({
609
- head: ['Date', 'Recipient', 'Contact', 'Token', 'Amount', 'Balance'],
628
+ head: ['Date', 'Recipient', 'Contact', 'Token', 'Amount', 'Balance', 'Status'],
610
629
  style: { head: ['blue'] },
611
630
  });
612
631
  if (history.length === 0) {
613
- table.push([{ colSpan: 6, content: 'No transaction history available.' }]);
632
+ table.push([{ colSpan: 7, content: 'No transaction history available.' }]);
614
633
  }
615
634
  for (const tx of history) {
616
635
  const date = this.formatDate(tx.timestamp);
617
- const contact = await this.db.get('contact', this.network.name, tx.recipient);
636
+ const contact = await this.db.get('contact', this.storageNetworkName, tx.recipient);
618
637
  const contactName = contact ? contact.name : '-';
619
638
  const amount = this.formatAmount(tx.amount);
620
639
  const balance = tx.balance !== undefined ? this.formatAmount(tx.balance) : '-';
621
- table.push([date, tx.recipient, contactName, tx.token, amount, balance]);
622
- table.push([{ colSpan: 6, content: this.selectedNetwork.explorer + tx.hash }]);
640
+ table.push([date, tx.recipient, contactName, tx.token, amount, balance, tx.status || '-']);
641
+ table.push([{ colSpan: 7, content: this.selectedNetwork.explorer + tx.hash }]);
623
642
  }
624
643
  console.log(table.toString());
625
644
  }
@@ -634,7 +653,7 @@ class Wallet {
634
653
  message: 'Name for the address book (leave empty to skip):',
635
654
  });
636
655
  if (name.trim() !== '') {
637
- await this.db.set('contact', this.network.name, address, 'name', name);
656
+ await this.db.set('contact', this.storageNetworkName, address, 'name', name);
638
657
  const table = new AnyTable({
639
658
  head: [{ colSpan: 2, content: "Recipient saved to the address book." }],
640
659
  style: { head: ['green'] },
@@ -644,7 +663,7 @@ class Wallet {
644
663
  }
645
664
  }
646
665
  async deleteFromAddressBook() {
647
- const contacts = await this.db.get('contact', this.network.name) || {};
666
+ const contacts = await this.db.get('contact', this.storageNetworkName) || {};
648
667
  const addressBook = Object.entries(contacts).map(([address, data]) => ({
649
668
  address,
650
669
  name: data.name
@@ -677,7 +696,7 @@ class Wallet {
677
696
  default: false
678
697
  });
679
698
  if (confirmDelete) {
680
- await this.db.del('contact', this.network.name, addressToDelete);
699
+ await this.db.del('contact', this.storageNetworkName, addressToDelete);
681
700
  const table = new AnyTable({
682
701
  head: ['Address Book'],
683
702
  style: { head: ['green'] },
@@ -700,7 +719,7 @@ class Wallet {
700
719
  style: { head: ['green'] },
701
720
  });
702
721
  const date = this.formatDate(new Date());
703
- const contact = await this.db.get('contact', this.network.name, address);
722
+ const contact = await this.db.get('contact', this.storageNetworkName, address);
704
723
  const contactName = contact ? contact.name : '-';
705
724
  table.push([date, address, contactName, token, this.formatAmount(amount), this.formatAmount(balance)]);
706
725
  table.push([{ colSpan: 6, content: this.selectedNetwork.explorer + hash }]);
@@ -715,6 +734,14 @@ class Wallet {
715
734
  this.profileLock.release();
716
735
  }
717
736
  }
737
+ get storageNetworkName() { return networkStorageName(this.selectedNetwork); }
738
+ getSwapRoute() { return routeForNetwork(this.selectedNetwork.id); }
739
+ async swapFunds() {
740
+ const route = this.getSwapRoute();
741
+ if (!route)
742
+ throw new Error('No swap route for the selected network.');
743
+ await startSwapMenu(new SwapService(this.db, { routeId: route.id }));
744
+ }
718
745
  securePersistFile() {
719
746
  const persistPath = path.join(this.hodlDir, 'persist.json');
720
747
  if (fs.existsSync(persistPath)) {
@@ -911,7 +938,7 @@ class Wallet {
911
938
  }
912
939
  }
913
940
  // Check if there are addresses in the address book
914
- const addressBook = await this.db.entries('contact', this.network.name) || [];
941
+ const addressBook = await this.db.entries('contact', this.storageNetworkName) || [];
915
942
  if (addressBook.length > 0) {
916
943
  const { deleteAddresses } = await inquirer.prompt({
917
944
  type: 'confirm',
@@ -1013,6 +1040,7 @@ class UIManager {
1013
1040
  }
1014
1041
  }
1015
1042
  async function mainMenu(wallet) {
1043
+ const route = wallet.getSwapRoute();
1016
1044
  const { action } = await inquirer.prompt({
1017
1045
  type: 'list',
1018
1046
  name: 'action',
@@ -1022,10 +1050,14 @@ async function mainMenu(wallet) {
1022
1050
  { name: 'Show Balance', value: 'balance' },
1023
1051
  { name: 'Show Sent Transfers', value: 'showTransactions' },
1024
1052
  { name: 'Account Settings', value: 'account' },
1053
+ ...(route ? [{ name: 'Swap', value: 'swapFunds' }] : []),
1025
1054
  { name: 'Exit', value: 'exit' }
1026
1055
  ],
1027
1056
  });
1028
1057
  switch (action) {
1058
+ case 'swapFunds':
1059
+ await wallet.swapFunds();
1060
+ return mainMenu(wallet);
1029
1061
  case 'transferFunds':
1030
1062
  await wallet.transferFunds();
1031
1063
  return mainMenu(wallet);
@@ -1058,9 +1090,25 @@ async function shutdown() {
1058
1090
  }
1059
1091
  async function run() {
1060
1092
  UIManager.displayWelcome();
1061
- let encryptionKey = await UIManager.getEncryptionKey();
1093
+ const hodlDir = path.join(os.homedir(), '.HODL');
1094
+ fs.mkdirSync(hodlDir, { recursive: true, mode: 0o700 });
1095
+ const profileLock = new ProfileLock(path.join(hodlDir, '.default.lock'));
1062
1096
  try {
1063
- const wallet = new Wallet(encryptionKey);
1097
+ profileLock.acquire();
1098
+ }
1099
+ catch (error) {
1100
+ if (!(error instanceof ProfileLockedError)) {
1101
+ throw error;
1102
+ }
1103
+ Wallet.displayError(error.owner === null
1104
+ ? 'The HODL profile is locked. Close the other instance and try again.'
1105
+ : `HODL is already open in another terminal (PID ${error.owner}). Close that instance and try again.`);
1106
+ return;
1107
+ }
1108
+ let encryptionKey = null;
1109
+ try {
1110
+ encryptionKey = await UIManager.getEncryptionKey();
1111
+ const wallet = new Wallet(encryptionKey, profileLock);
1064
1112
  activeWallet = wallet;
1065
1113
  const databaseExisted = wallet.hasStoredDatabase();
1066
1114
  try {
@@ -1093,7 +1141,12 @@ async function run() {
1093
1141
  }
1094
1142
  finally {
1095
1143
  encryptionKey = null;
1096
- await shutdown();
1144
+ try {
1145
+ await shutdown();
1146
+ }
1147
+ finally {
1148
+ profileLock.release();
1149
+ }
1097
1150
  }
1098
1151
  }
1099
1152
  export function selectCliMode(argv) {