hodl-wallet 2.1.0 → 2.3.0

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 (117) hide show
  1. package/README.md +11 -11
  2. package/dist/app/account.d.ts +7 -0
  3. package/dist/app/account.js +248 -0
  4. package/dist/app/account.js.map +1 -0
  5. package/dist/app/format.d.ts +5 -0
  6. package/dist/app/format.js +33 -0
  7. package/dist/app/format.js.map +1 -0
  8. package/dist/app/history.d.ts +48 -0
  9. package/dist/app/history.js +115 -0
  10. package/dist/app/history.js.map +1 -0
  11. package/dist/app/index.d.ts +12 -0
  12. package/dist/app/index.js +9 -0
  13. package/dist/app/index.js.map +1 -0
  14. package/dist/app/menu.d.ts +13 -0
  15. package/dist/app/menu.js +93 -0
  16. package/dist/app/menu.js.map +1 -0
  17. package/dist/app/output.d.ts +17 -0
  18. package/dist/app/output.js +107 -0
  19. package/dist/app/output.js.map +1 -0
  20. package/dist/app/session.d.ts +125 -0
  21. package/dist/app/session.js +2 -0
  22. package/dist/app/session.js.map +1 -0
  23. package/dist/app/swap.d.ts +5 -0
  24. package/dist/app/swap.js +274 -0
  25. package/dist/app/swap.js.map +1 -0
  26. package/dist/app/transfer.d.ts +3 -0
  27. package/dist/app/transfer.js +144 -0
  28. package/dist/app/transfer.js.map +1 -0
  29. package/dist/app/ui.d.ts +73 -0
  30. package/dist/app/ui.js +15 -0
  31. package/dist/app/ui.js.map +1 -0
  32. package/dist/browser-core.d.ts +7 -1
  33. package/dist/browser-core.js +6 -1
  34. package/dist/browser-core.js.map +1 -1
  35. package/dist/config.d.ts +11 -0
  36. package/dist/config.js +12 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/hodl-file.d.ts +31 -0
  39. package/dist/hodl-file.js +78 -0
  40. package/dist/hodl-file.js.map +1 -0
  41. package/dist/index.js +24 -1096
  42. package/dist/index.js.map +1 -1
  43. package/dist/network/abis/erc20.d.ts +35 -13
  44. package/dist/network/abis/erc20.js +6 -26
  45. package/dist/network/abis/erc20.js.map +1 -1
  46. package/dist/network/arb.d.ts +5 -0
  47. package/dist/network/arb.js +5 -0
  48. package/dist/network/arb.js.map +1 -1
  49. package/dist/network/avax.d.ts +6 -0
  50. package/dist/network/avax.js +6 -0
  51. package/dist/network/avax.js.map +1 -1
  52. package/dist/network/bsc.d.ts +6 -0
  53. package/dist/network/bsc.js +6 -0
  54. package/dist/network/bsc.js.map +1 -1
  55. package/dist/network/eth.d.ts +6 -0
  56. package/dist/network/eth.js +6 -0
  57. package/dist/network/eth.js.map +1 -1
  58. package/dist/network/ftm.d.ts +6 -0
  59. package/dist/network/ftm.js +6 -0
  60. package/dist/network/ftm.js.map +1 -1
  61. package/dist/network/lib/BitcoinNetwork.d.ts +3 -1
  62. package/dist/network/lib/BitcoinNetwork.js +58 -13
  63. package/dist/network/lib/BitcoinNetwork.js.map +1 -1
  64. package/dist/network/lib/Web3Network.d.ts +10 -4
  65. package/dist/network/lib/Web3Network.js +141 -73
  66. package/dist/network/lib/Web3Network.js.map +1 -1
  67. package/dist/network/op.d.ts +5 -0
  68. package/dist/network/op.js +5 -0
  69. package/dist/network/op.js.map +1 -1
  70. package/dist/network/pol.d.ts +6 -0
  71. package/dist/network/pol.js +6 -0
  72. package/dist/network/pol.js.map +1 -1
  73. package/dist/network/types.d.ts +35 -0
  74. package/dist/network-registry.d.ts +6 -1
  75. package/dist/network-registry.js +28 -0
  76. package/dist/network-registry.js.map +1 -1
  77. package/dist/node-session.d.ts +53 -0
  78. package/dist/node-session.js +359 -0
  79. package/dist/node-session.js.map +1 -0
  80. package/dist/persist.d.ts +14 -7
  81. package/dist/persist.js +83 -108
  82. package/dist/persist.js.map +1 -1
  83. package/dist/request.d.ts +7 -0
  84. package/dist/request.js +26 -0
  85. package/dist/request.js.map +1 -0
  86. package/dist/swap/bitcoin.d.ts +1 -1
  87. package/dist/swap/bitcoin.js +7 -6
  88. package/dist/swap/bitcoin.js.map +1 -1
  89. package/dist/swap/chain.js +25 -40
  90. package/dist/swap/chain.js.map +1 -1
  91. package/dist/swap/config.d.ts +12 -0
  92. package/dist/swap/config.js +6 -0
  93. package/dist/swap/config.js.map +1 -1
  94. package/dist/swap/http.d.ts +2 -1
  95. package/dist/swap/http.js +8 -4
  96. package/dist/swap/http.js.map +1 -1
  97. package/dist/swap/providers.d.ts +15 -0
  98. package/dist/swap/providers.js +187 -1
  99. package/dist/swap/providers.js.map +1 -1
  100. package/dist/swap/routes.d.ts +28 -0
  101. package/dist/swap/routes.js +5 -3
  102. package/dist/swap/routes.js.map +1 -1
  103. package/dist/swap/service.d.ts +2 -1
  104. package/dist/swap/service.js +16 -5
  105. package/dist/swap/service.js.map +1 -1
  106. package/dist/swap/types.d.ts +3 -1
  107. package/dist/swap/types.js.map +1 -1
  108. package/dist/transfer-service.js +1 -2
  109. package/dist/transfer-service.js.map +1 -1
  110. package/dist/ui-inquirer.d.ts +37 -0
  111. package/dist/ui-inquirer.js +97 -0
  112. package/dist/ui-inquirer.js.map +1 -0
  113. package/dist/wallet-store.d.ts +2 -1
  114. package/package.json +17 -14
  115. package/dist/swap/ui.d.ts +0 -3
  116. package/dist/swap/ui.js +0 -257
  117. package/dist/swap/ui.js.map +0 -1
package/README.md CHANGED
@@ -72,7 +72,7 @@ HODL Wallet now supports exporting and importing encrypted .HODL files, which se
72
72
  - **Export HODL File**: Save your wallet data (including private keys and addresses) to an encrypted .HODL file.
73
73
  - **Import HODL File**: Restore your wallet from a previously exported .HODL file.
74
74
 
75
- These files are encrypted using your wallet password, providing an additional layer of security for storing and transferring your wallet information.
75
+ These files are encrypted using your wallet password, providing an additional layer of security for storing and transferring your wallet information. Files saved in the legacy format by older releases can no longer be imported.
76
76
 
77
77
  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.
78
78
 
@@ -125,10 +125,11 @@ transaction. The destination account is offered by default; you can also type
125
125
  an external address for the destination network. Importing only an EVM private
126
126
  key does not create a Bitcoin account.
127
127
 
128
- HODL compares single-execution Chainflip with automatic THORChain streaming,
129
- which divides the exchange into smaller swaps to reduce price impact. Unavailable,
128
+ HODL compares single-execution Chainflip and NEAR Intents with automatic THORChain
129
+ streaming, which divides the exchange into smaller swaps to reduce price impact. Unavailable,
130
130
  paused, or unsupported routes are shown separately. DCA, boosts and HODL affiliate
131
- commissions are not enabled. Streaming and its estimated duration are shown
131
+ commissions are not enabled. NEAR Intents charges its own 0.2% platform fee, shown
132
+ with the quote and included in the comparison; quotes with any higher fee are rejected. Streaming and its estimated duration are shown
132
133
  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.
133
134
  Total cost includes fees and price impact against a recent CoinGecko reference;
134
135
  it is an estimate, not a guaranteed execution price. There is no fixed cost cap:
@@ -155,7 +156,7 @@ budget. `--watch` emits JSONL progress envelopes followed by the final result.
155
156
  Without `--watch`, execution returns after publishing the next funding step;
156
157
  use `resume --yes` to continue after an approval confirms. `status` only observes
157
158
  and never submits a transaction. Only one unfinished swap per profile is
158
- allowed, and it blocks other HODL BSC and Bitcoin transfers until resolved.
159
+ allowed, and it blocks other HODL transfers on the network it spends from until resolved.
159
160
 
160
161
  The minimum destination amount for a full swap limits deterioration from the accepted quote to 0.5%.
161
162
  This is separate from total fees. Source approvals grant only the required
@@ -213,21 +214,20 @@ We're as transparent as your ex's excuses. Our code is open-source, and we encou
213
214
  We've carefully selected trusted and well-maintained dependencies for this project. Our goal is to balance functionality with security. Here's a brief overview of our main dependencies:
214
215
 
215
216
  - Common
216
- - **inquirer** and **inquirer-autocomplete-prompt**: For interactive command-line interfaces.
217
- - **inquirer-fuzzy-path**: For fuzzy searching and selecting file paths during HODL file import.
217
+ - **inquirer**: For interactive command-line interfaces.
218
218
  - **cli-table3**: For creating formatted CLI tables.
219
219
  - **ora**: For displaying progress bars.
220
220
  - **deepbase**: For persistent storage.
221
221
  - **node:crypto**: Native encryption for JSON storage.
222
- - **bip39**: For generating and handling mnemonic phrases.
222
+ - **@scure/bip39**: For generating and handling mnemonic phrases.
223
223
  - Web3
224
- - **web3**: The Ethereum JavaScript API for blockchain interactions.
225
- - **hdkey**: For handling hierarchical deterministic (HD) keys.
224
+ - **viem**: For EVM RPC, contract encoding and transaction signing.
225
+ - **@scure/bip32**: For handling hierarchical deterministic (HD) keys.
226
226
  - Bitcoin
227
227
  - **bitcoinjs-lib**: For Bitcoin-specific operations.
228
228
  - **bip32**: For handling hierarchical deterministic (HD) keys.
229
229
  - **ecpair**: For elliptic curve pairings.
230
- - **tiny-secp256k1**: For elliptic curve secp256k1 operations.
230
+ - **@bitcoinerlab/secp256k1**: For elliptic curve secp256k1 operations.
231
231
 
232
232
  ⚠️ **Important Notice**: HODL Wallet is a personal project created with the best intentions. While we strive for security, it may contain security flaws or vulnerabilities. Use at your own risk and always exercise caution with your crypto assets.
233
233
 
@@ -0,0 +1,7 @@
1
+ import type { WalletSession } from './session.js';
2
+ import type { Ui } from './ui.js';
3
+ export declare function showAccountDetails(ui: Ui, session: WalletSession): Promise<void>;
4
+ export declare function switchNetwork(ui: Ui, session: WalletSession, loggedIn?: boolean): Promise<void>;
5
+ /** Offers to name a recipient the address book does not know yet. */
6
+ export declare function saveContact(ui: Ui, session: WalletSession, address: string): Promise<void>;
7
+ export declare function loadAccount(ui: Ui, session: WalletSession, loggedIn?: boolean): Promise<void>;
@@ -0,0 +1,248 @@
1
+ import { clearSensitiveData } from '../sensitive-data.js';
2
+ import { notice, showAddress, showError } from './output.js';
3
+ async function confirmOverwrite(ui, session) {
4
+ if (!await session.hasAccount())
5
+ return true;
6
+ return ui.confirm({
7
+ message: 'This action will overwrite the existing account; without a backup it cannot be recovered. Are you sure you want to continue?',
8
+ default: false
9
+ });
10
+ }
11
+ async function importFromMnemonic(ui, session) {
12
+ const mnemonic = await ui.password({
13
+ message: 'Enter your mnemonic phrase (12 or 24 words):',
14
+ validate: input => {
15
+ if (input.trim() === '')
16
+ return true;
17
+ return session.network.validateMnemonic(input) || 'Please enter a valid mnemonic phrase or leave empty to cancel.';
18
+ }
19
+ });
20
+ if (!mnemonic.trim())
21
+ return;
22
+ await session.importMnemonic(mnemonic);
23
+ await showAddress(ui, session);
24
+ }
25
+ async function importPrivateKey(ui, session) {
26
+ const privateKey = await ui.password({
27
+ message: 'Private-key (leave empty to cancel):',
28
+ validate: input => {
29
+ if (input.trim() === '')
30
+ return true;
31
+ return session.network.validatePrivateKey(input) ||
32
+ 'Please enter a valid private-key for the selected network or leave empty to cancel.';
33
+ }
34
+ });
35
+ if (!privateKey.trim())
36
+ return;
37
+ try {
38
+ await session.importPrivateKey(privateKey);
39
+ await showAddress(ui, session);
40
+ }
41
+ catch {
42
+ showError(ui, 'Invalid private-key.');
43
+ }
44
+ }
45
+ export async function showAccountDetails(ui, session) {
46
+ const account = await session.accountDetails();
47
+ if (!account) {
48
+ showError(ui, 'Account not initialized.');
49
+ return;
50
+ }
51
+ const rows = [['Address', account.address], ['Private-key', account.privateKey]];
52
+ if (account.mnemonic) {
53
+ rows.push(['Mnemonic Phrase', account.mnemonic]);
54
+ rows.push(['WARNING', 'Please keep your private-key and mnemonic phrase secure. Never share it.']);
55
+ }
56
+ else {
57
+ rows.push(['WARNING', 'Please keep your private-key secure. Never share it.']);
58
+ }
59
+ ui.table({ head: [{ colSpan: 2, content: 'Account Details' }], tone: 'green', wordWrap: true, secret: true, rows });
60
+ clearSensitiveData(account);
61
+ }
62
+ async function createNewAccount(ui, session) {
63
+ let created = false;
64
+ if (await session.hasMnemonic()) {
65
+ const useExisting = await ui.confirm({ message: 'Use existing mnemonic to create account?', default: true });
66
+ if (useExisting) {
67
+ await session.createAccount('existing-mnemonic');
68
+ created = true;
69
+ }
70
+ }
71
+ if (!created) {
72
+ const withMnemonic = await ui.confirm({ message: 'Create account with mnemonic?', default: true });
73
+ if (withMnemonic) {
74
+ const words = await ui.select({
75
+ message: 'Choose mnemonic phrase length:',
76
+ choices: [
77
+ { name: '12 words (standard)', value: 12 },
78
+ { name: '24 words (more secure)', value: 24 }
79
+ ],
80
+ default: 12
81
+ });
82
+ await session.createAccount(words);
83
+ }
84
+ else {
85
+ await session.createAccount('random');
86
+ }
87
+ }
88
+ const contacts = await session.contacts?.list() ?? [];
89
+ if (session.contacts && contacts.length > 0) {
90
+ const clear = await ui.confirm({
91
+ message: `Do you want to delete all ${contacts.length} addresses from the previous account?`,
92
+ default: false
93
+ });
94
+ if (clear) {
95
+ await session.contacts.clear();
96
+ notice(ui, 'green', 'Address Book', 'All addresses deleted successfully.');
97
+ }
98
+ }
99
+ let message = 'Do you want to display sensitive information (private key';
100
+ if (await session.hasMnemonic())
101
+ message += ' and mnemonic';
102
+ message += ')?';
103
+ if (await ui.confirm({ message, default: false })) {
104
+ await showAccountDetails(ui, session);
105
+ }
106
+ else {
107
+ await showAddress(ui, session);
108
+ }
109
+ }
110
+ export async function switchNetwork(ui, session, loggedIn = true) {
111
+ const plugin = await ui.select({
112
+ message: 'Select the network:',
113
+ choices: session.networks().map(network => ({ name: network.name, value: network }))
114
+ });
115
+ await session.selectNetwork(plugin);
116
+ if (await session.hasAccount()) {
117
+ await showAddress(ui, session);
118
+ }
119
+ else {
120
+ ui.print(`\nNo account found for ${session.plugin.name}. Please create or import an account.`);
121
+ await loadAccount(ui, session, loggedIn);
122
+ }
123
+ }
124
+ async function deleteFromAddressBook(ui, session) {
125
+ const contacts = await session.contacts.list();
126
+ if (contacts.length === 0) {
127
+ notice(ui, 'yellow', 'Address Book', 'No addresses in the address book.');
128
+ return;
129
+ }
130
+ const address = await ui.select({
131
+ message: 'Select an address to delete:',
132
+ choices: [
133
+ ...contacts.map(contact => ({ name: `${contact.address} (${contact.name})`, value: contact.address })),
134
+ { name: 'Go Back', value: '' }
135
+ ]
136
+ });
137
+ if (!address)
138
+ return;
139
+ if (await ui.confirm({ message: 'Are you sure you want to delete this address?', default: false })) {
140
+ await session.contacts.delete(address);
141
+ notice(ui, 'green', 'Address Book', 'Address deleted successfully.');
142
+ }
143
+ }
144
+ /** Offers to name a recipient the address book does not know yet. */
145
+ export async function saveContact(ui, session, address) {
146
+ if (!session.contacts || await session.contacts.get(address))
147
+ return;
148
+ const name = await ui.input({ message: 'Name for the address book (leave empty to skip):' });
149
+ if (name.trim() === '')
150
+ return;
151
+ await session.contacts.set(address, name);
152
+ ui.table({
153
+ head: [{ colSpan: 2, content: 'Recipient saved to the address book.' }],
154
+ tone: 'green',
155
+ rows: [[name, address]]
156
+ });
157
+ }
158
+ async function runImport(ui, session, action) {
159
+ if (action === 'importMnemonic') {
160
+ await importFromMnemonic(ui, session);
161
+ }
162
+ else if (action === 'importPrivateKey') {
163
+ await importPrivateKey(ui, session);
164
+ }
165
+ else if (typeof action === 'object' && await action.run(ui)) {
166
+ await showAddress(ui, session);
167
+ }
168
+ }
169
+ function importChoices(session) {
170
+ return [
171
+ ...session.importActions().map(action => ({ name: action.name, value: action })),
172
+ { name: 'Import Mnemonic (12 or 24 words)', value: 'importMnemonic' },
173
+ { name: 'Import Private-key', value: 'importPrivateKey' }
174
+ ];
175
+ }
176
+ export async function loadAccount(ui, session, loggedIn = false) {
177
+ if (!loggedIn && await session.hasAccount())
178
+ return;
179
+ const choices = [];
180
+ if (!loggedIn) {
181
+ choices.push({ name: 'Create New Account', value: 'create' }, ...importChoices(session));
182
+ if (session.capabilities.switchNetworkFirst)
183
+ choices.push({ name: 'Switch Network', value: 'switch' });
184
+ }
185
+ else {
186
+ if (session.capabilities.replaceAccount)
187
+ choices.push({ name: 'Create New Account', value: 'create' });
188
+ choices.push({ name: 'Import Options', value: 'import' });
189
+ choices.push({ name: 'Export Options', value: 'export' }, { name: 'Switch Network', value: 'switch' });
190
+ if (session.contacts)
191
+ choices.push({ name: 'Manage Address Book', value: 'addressBook' });
192
+ choices.push({ name: 'Go Back', value: 'back', back: true });
193
+ }
194
+ const action = await ui.select({ message: 'Select an account option:', choices });
195
+ if (action === 'back')
196
+ return;
197
+ if (action === 'addressBook') {
198
+ const next = await ui.select({
199
+ message: 'Select an address book option:',
200
+ choices: [{ name: 'Delete Address', value: 'delete' }, { name: 'Go Back', value: 'back', back: true }]
201
+ });
202
+ if (next === 'back')
203
+ return loadAccount(ui, session, loggedIn);
204
+ await deleteFromAddressBook(ui, session);
205
+ return;
206
+ }
207
+ if (action === 'import') {
208
+ const next = await ui.select({
209
+ message: 'Select an import option:',
210
+ choices: [...importChoices(session), { name: 'Go Back', value: 'back', back: true }]
211
+ });
212
+ if (next === 'back')
213
+ return loadAccount(ui, session, loggedIn);
214
+ if (!await confirmOverwrite(ui, session))
215
+ return;
216
+ await runImport(ui, session, next);
217
+ return;
218
+ }
219
+ if (action === 'export') {
220
+ const next = await ui.select({
221
+ message: 'Select an export option:',
222
+ choices: [
223
+ ...session.exportActions().map(item => ({ name: item.name, value: item })),
224
+ { name: 'Export Private-key', value: 'privateKey' },
225
+ { name: 'Go Back', value: 'back', back: true }
226
+ ]
227
+ });
228
+ if (next === 'back')
229
+ return loadAccount(ui, session, loggedIn);
230
+ if (next === 'privateKey')
231
+ await showAccountDetails(ui, session);
232
+ else if (typeof next === 'object')
233
+ await next.run(ui);
234
+ return;
235
+ }
236
+ if (action === 'create') {
237
+ if (!await confirmOverwrite(ui, session))
238
+ return;
239
+ await createNewAccount(ui, session);
240
+ return;
241
+ }
242
+ if (action === 'switch') {
243
+ await switchNetwork(ui, session, loggedIn);
244
+ return;
245
+ }
246
+ await runImport(ui, session, action);
247
+ }
248
+ //# sourceMappingURL=account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.js","sourceRoot":"","sources":["../../app/account.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { errorMessage } from '../request.js';
2
+ export declare function formatAmount(num: number | string): string;
3
+ /** USDT shows cents; other tokens use the shared amount format. */
4
+ export declare function formatTokenAmount(token: string, amount: number | string): string;
5
+ export declare function formatDate(date: string | number | Date): string;
@@ -0,0 +1,33 @@
1
+ export { errorMessage } from '../request.js';
2
+ export function formatAmount(num) {
3
+ return amountWithDecimals(num, 3);
4
+ }
5
+ /** USDT shows cents; other tokens use the shared amount format. */
6
+ export function formatTokenAmount(token, amount) {
7
+ return amountWithDecimals(amount, token === 'USDT' ? 2 : 3);
8
+ }
9
+ function amountWithDecimals(num, maxDecimals) {
10
+ num = parseFloat(num.toString());
11
+ // Integers get .00
12
+ if (num === Math.floor(num)) {
13
+ return num.toString() + '.00';
14
+ }
15
+ // Decimals: at most `maxDecimals` places, or as many as the first two significant digits need,
16
+ // so a nonzero amount never shows as zero; trailing zeros removed, at least 2 kept
17
+ let formatted = num.toFixed(Math.max(maxDecimals, 1 - Math.floor(Math.log10(Math.abs(num)))));
18
+ while (formatted.endsWith('0') && formatted.split('.')[1].length > 2) {
19
+ formatted = formatted.slice(0, -1);
20
+ }
21
+ return formatted;
22
+ }
23
+ export function formatDate(date) {
24
+ return new Date(date).toLocaleString('en-GB', {
25
+ year: 'numeric',
26
+ month: '2-digit',
27
+ day: '2-digit',
28
+ hour: '2-digit',
29
+ minute: '2-digit',
30
+ hour12: false
31
+ }).replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1').replace(",", "");
32
+ }
33
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../app/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,UAAU,YAAY,CAAC,GAAoB;IAC7C,OAAO,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,MAAuB;IACpE,OAAO,kBAAkB,CAAC,MAAM,EAAE,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAoB,EAAE,WAAmB;IACjE,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEjC,mBAAmB;IACnB,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC;IAClC,CAAC;IAED,+FAA+F;IAC/F,mFAAmF;IACnF,IAAI,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9F,OAAO,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnE,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAA4B;IACnD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE;QAC1C,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,KAAK;KAChB,CAAC,CAAC,OAAO,CAAC,2BAA2B,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC"}
@@ -0,0 +1,48 @@
1
+ import type { ChainTransfer, NetworkPlugin, TransferScan } from '../network/types.js';
2
+ import type { TransferResult } from '../transfer-service.js';
3
+ import type { TransferRow, SentTransfer } from './session.js';
4
+ /** A sent transfer recorded under `transactions`, then the sender's address, a history key and an id. */
5
+ export type RecordedTransfer = {
6
+ timestamp: string;
7
+ recipient: string;
8
+ token: string;
9
+ amount: string | number;
10
+ hash: string;
11
+ balance?: string | number;
12
+ status?: string;
13
+ };
14
+ /** A transfer from the durable journal (`sendRequest`). */
15
+ export type JournalTransfer = TransferResult & {
16
+ createdAt: string;
17
+ };
18
+ export declare function isRecordedTransfer(value: unknown): value is RecordedTransfer;
19
+ /** The history keys holding a network's recorded transfers: its native token, plus the symbol older versions used for Optimism and Arbitrum. */
20
+ export declare function recordedTransferKeys(plugin: NetworkPlugin): string[];
21
+ /** Transfers sent from `address`, oldest first: the recorded ones and the journal's, whose status wins for the same hash. */
22
+ export declare function sentTransfers(plugin: NetworkPlugin, address: string, recorded: RecordedTransfer[], journal: JournalTransfer[], contactName: (address: string) => Promise<string | undefined>): Promise<SentTransfer[]>;
23
+ /** What a host saves of one address's transfers on a network: what scans found, and where the next scan starts. */
24
+ export type TransferSnapshot = {
25
+ cursor?: string;
26
+ transfers: ChainTransfer[];
27
+ };
28
+ export declare function isTransferSnapshot(value: unknown): value is TransferSnapshot;
29
+ /** The snapshot with a scan added. Unconfirmed transfers stay only while scans still report them; the newest are kept. */
30
+ export declare function mergeTransferScan(saved: TransferSnapshot | undefined, scan: TransferScan): TransferSnapshot;
31
+ /** Scans from where the saved snapshot left off. A failed scan leaves the snapshot as saved and says why. */
32
+ export declare function rescanTransfers(saved: TransferSnapshot | undefined, scan: (cursor: string | undefined) => Promise<TransferScan>): Promise<{
33
+ snapshot: TransferSnapshot | undefined;
34
+ error?: string;
35
+ }>;
36
+ /** Recent transfers as listed by the network, newest first, with the other party's contact name. */
37
+ export declare function recentTransferRows(plugin: NetworkPlugin, transfers: ChainTransfer[], contactName: (address: string) => Promise<string | undefined>): Promise<TransferRow[]>;
38
+ /**
39
+ * Sent transfers and the network's recent ones as one list, oldest first and unconfirmed last.
40
+ * A sent transfer stands for the network's outgoing rows of the same transaction. The network's
41
+ * transfers worth nothing (anyone can move zero on another's behalf) and incoming ones from an
42
+ * address imitating one paid or known (`known`: the wallet's own and its contacts) are left out as
43
+ * likely address poisoning and only counted.
44
+ */
45
+ export declare function transferRows(sent: SentTransfer[], recent: TransferRow[], known: string[]): {
46
+ rows: TransferRow[];
47
+ hidden: number;
48
+ };
@@ -0,0 +1,115 @@
1
+ import { walletConfig } from '../config.js';
2
+ import { errorMessage } from './format.js';
3
+ import { isPromptAborted } from './ui.js';
4
+ function isRecord(value) {
5
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
6
+ }
7
+ export function isRecordedTransfer(value) {
8
+ return isRecord(value) && ['timestamp', 'recipient', 'token', 'hash'].every(field => typeof value[field] === 'string') &&
9
+ ['string', 'number'].includes(typeof value.amount) &&
10
+ (value.balance === undefined || ['string', 'number'].includes(typeof value.balance)) &&
11
+ (value.status === undefined || typeof value.status === 'string');
12
+ }
13
+ /** The history keys holding a network's recorded transfers: its native token, plus the symbol older versions used for Optimism and Arbitrum. */
14
+ export function recordedTransferKeys(plugin) {
15
+ const legacy = { op: 'OP', arb: 'ARB' }[plugin.id];
16
+ return legacy ? [plugin.nativeToken, legacy] : [plugin.nativeToken];
17
+ }
18
+ /** Transfers sent from `address`, oldest first: the recorded ones and the journal's, whose status wins for the same hash. */
19
+ export async function sentTransfers(plugin, address, recorded, journal, contactName) {
20
+ const history = recorded.map(transfer => ({ ...transfer }));
21
+ for (const transfer of journal.filter(item => item.from === address)) {
22
+ const existing = history.find(item => item.hash === transfer.transactionHash);
23
+ if (existing)
24
+ existing.status = transfer.status;
25
+ else
26
+ history.push({
27
+ timestamp: transfer.createdAt, recipient: transfer.to, token: transfer.asset,
28
+ amount: transfer.amount, hash: transfer.transactionHash, status: transfer.status
29
+ });
30
+ }
31
+ history.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
32
+ return Promise.all(history.map(async (tx) => ({
33
+ timestamp: tx.timestamp, recipient: tx.recipient, contact: await contactName(tx.recipient),
34
+ token: tx.token, amount: tx.amount, balance: tx.balance, status: tx.status,
35
+ url: plugin.explorer + tx.hash
36
+ })));
37
+ }
38
+ function isChainTransfer(value) {
39
+ return isRecord(value) && ['id', 'hash', 'counterparty', 'asset', 'amount'].every(field => typeof value[field] === 'string') &&
40
+ ['in', 'out'].includes(value.direction) && ['pending', 'confirmed'].includes(value.state) &&
41
+ (value.timestamp === undefined || typeof value.timestamp === 'string');
42
+ }
43
+ export function isTransferSnapshot(value) {
44
+ return isRecord(value) && (value.cursor === undefined || typeof value.cursor === 'string') &&
45
+ Array.isArray(value.transfers) && value.transfers.every(isChainTransfer);
46
+ }
47
+ const newestFirst = (a, b) => (b.timestamp ?? '\uffff').localeCompare(a.timestamp ?? '\uffff');
48
+ /** The snapshot with a scan added. Unconfirmed transfers stay only while scans still report them; the newest are kept. */
49
+ export function mergeTransferScan(saved, scan) {
50
+ const transfers = new Map((saved?.transfers ?? []).filter(tx => tx.state === 'confirmed').map(tx => [tx.id, tx]));
51
+ for (const tx of scan.transfers)
52
+ transfers.set(tx.id, tx);
53
+ const cursor = scan.cursor ?? saved?.cursor;
54
+ return {
55
+ ...(cursor !== undefined ? { cursor } : {}),
56
+ transfers: [...transfers.values()].sort(newestFirst).slice(0, walletConfig.history.keptTransfers)
57
+ };
58
+ }
59
+ /** Scans from where the saved snapshot left off. A failed scan leaves the snapshot as saved and says why. */
60
+ export async function rescanTransfers(saved, scan) {
61
+ try {
62
+ return { snapshot: mergeTransferScan(saved, await scan(saved?.cursor)) };
63
+ }
64
+ catch (error) {
65
+ if (isPromptAborted(error))
66
+ throw error;
67
+ return { snapshot: saved, error: errorMessage(error) };
68
+ }
69
+ }
70
+ /** Recent transfers as listed by the network, newest first, with the other party's contact name. */
71
+ export function recentTransferRows(plugin, transfers, contactName) {
72
+ return Promise.all(transfers.map(async (tx) => ({
73
+ ...(tx.timestamp ? { timestamp: tx.timestamp } : {}),
74
+ direction: tx.direction === 'in' ? 'In' : 'Out',
75
+ counterparty: tx.counterparty, contact: await contactName(tx.counterparty),
76
+ token: tx.asset, amount: tx.amount, status: tx.state,
77
+ url: plugin.explorer + tx.hash
78
+ })));
79
+ }
80
+ /** The part of an address after its format prefix, which an imitation copies. */
81
+ function addressBody(address) {
82
+ return address.toLowerCase().replace(/^(0x|bc1.|tb1.|[123mn])/, '');
83
+ }
84
+ /** Whether the address starts or ends like a known one without being it, as address poisoning does. */
85
+ function imitates(address, known) {
86
+ const chars = walletConfig.history.lookAlikeChars;
87
+ const body = addressBody(address);
88
+ return known.map(addressBody).some(other => other !== body &&
89
+ (other.slice(0, chars) === body.slice(0, chars) || other.slice(-chars) === body.slice(-chars)));
90
+ }
91
+ /**
92
+ * Sent transfers and the network's recent ones as one list, oldest first and unconfirmed last.
93
+ * A sent transfer stands for the network's outgoing rows of the same transaction. The network's
94
+ * transfers worth nothing (anyone can move zero on another's behalf) and incoming ones from an
95
+ * address imitating one paid or known (`known`: the wallet's own and its contacts) are left out as
96
+ * likely address poisoning and only counted.
97
+ */
98
+ export function transferRows(sent, recent, known) {
99
+ const sentUrls = new Set(sent.map(tx => tx.url));
100
+ const valued = recent.filter(tx => Number(tx.amount) > 0);
101
+ const outgoing = valued.filter(tx => tx.direction === 'Out');
102
+ const paid = [...known, ...sent.map(tx => tx.recipient), ...outgoing.map(tx => tx.counterparty)];
103
+ const incoming = valued.filter(tx => tx.direction === 'In' && !imitates(tx.counterparty, paid));
104
+ const rows = [
105
+ ...sent.map(({ recipient, ...tx }) => ({ ...tx, direction: 'Out', counterparty: recipient })),
106
+ ...outgoing.filter(tx => !sentUrls.has(tx.url)),
107
+ ...incoming
108
+ ];
109
+ const time = (row) => row.timestamp === undefined ? Infinity : new Date(row.timestamp).getTime();
110
+ return {
111
+ rows: rows.sort((a, b) => time(a) === time(b) ? 0 : time(a) < time(b) ? -1 : 1),
112
+ hidden: recent.length - outgoing.length - incoming.length
113
+ };
114
+ }
115
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../app/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAgB1C,SAAS,QAAQ,CAAC,KAAc;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC7C,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC;QAClH,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,MAAM,CAAC;QAClD,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC;QACpF,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;AACzE,CAAC;AAED,gJAAgJ;AAChJ,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACtD,MAAM,MAAM,GAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAyC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3F,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACxE,CAAC;AAED,6HAA6H;AAC7H,MAAM,CAAC,KAAK,UAAU,aAAa,CAC/B,MAAqB,EACrB,OAAe,EACf,QAA4B,EAC5B,OAA0B,EAC1B,WAA6D;IAE7D,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC5D,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC;QACnE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,eAAe,CAAC,CAAC;QAC9E,IAAI,QAAQ;YAAE,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;;YAC3C,OAAO,CAAC,IAAI,CAAC;gBACd,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK;gBAC5E,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM;aACnF,CAAC,CAAC;IACP,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/D,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CAAC,CAAC;QACxC,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC,EAAE,CAAC,SAAS,CAAC;QAC1F,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM;QAC1E,GAAG,EAAE,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC,IAAI;KACjC,CAAC,CAAC,CAAC,CAAC;AACT,CAAC;AAQD,SAAS,eAAe,CAAC,KAAc;IACnC,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC;QACxH,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAmB,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAe,CAAC;QAC7G,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC7C,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC;QACtF,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,CAAgB,EAAE,CAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC;AAE7H,0HAA0H;AAC1H,MAAM,UAAU,iBAAiB,CAAC,KAAmC,EAAE,IAAkB;IACrF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAClH,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS;QAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,MAAM,CAAC;IAC5C,OAAO;QACH,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,aAAa,CAAC;KACpG,CAAC;AACN,CAAC;AAED,6GAA6G;AAC7G,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,KAAmC,EACnC,IAA2D;IAE3D,IAAI,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAC7E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,eAAe,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;IAC3D,CAAC;AACL,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,kBAAkB,CAC9B,MAAqB,EACrB,SAA0B,EAC1B,WAA6D;IAE7D,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CAAC,CAAC;QAC1C,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,IAAa,CAAC,CAAC,CAAC,KAAc;QACjE,YAAY,EAAE,EAAE,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC,EAAE,CAAC,YAAY,CAAC;QAC1E,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK;QACpD,GAAG,EAAE,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC,IAAI;KACjC,CAAC,CAAC,CAAC,CAAC;AACT,CAAC;AAED,iFAAiF;AACjF,SAAS,WAAW,CAAC,OAAe;IAChC,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,uGAAuG;AACvG,SAAS,QAAQ,CAAC,OAAe,EAAE,KAAe;IAC9C,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,cAAc,CAAC;IAClD,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,IAAI;QACtD,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACxG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,IAAoB,EAAE,MAAqB,EAAE,KAAe;IACrF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,KAAK,KAAK,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IACjG,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;IAChG,MAAM,IAAI,GAAkB;QACxB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,KAAc,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC;QACtG,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAC/C,GAAG,QAAQ;KACd,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,GAAgB,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAC9G,OAAO;QACH,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM;KAC5D,CAAC;AACN,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { PromptAborted, isPromptAborted } from './ui.js';
2
+ export type { Cell, Choice, Spinner, TableSpec, Tone, Ui, Validation, Watch } from './ui.js';
3
+ export type { AccountDetails, Contact, ContactsPort, HostAction, NewAccount, PendingTransfer, RecentTransfers, TransferRow, SentTransfer, SessionCapabilities, TransferDraft, TransferPort, WalletSession } from './session.js';
4
+ export { WELCOME_ART, farewell, showAddress, showError, welcome } from './output.js';
5
+ export { errorMessage, formatAmount, formatDate, formatTokenAmount } from './format.js';
6
+ export { AccountNotInitialized, initialize, mainMenu, runWallet, showBalance, showTransactions } from './menu.js';
7
+ export { loadAccount, showAccountDetails, switchNetwork } from './account.js';
8
+ export { transferFunds } from './transfer.js';
9
+ export { swapMenu } from './swap.js';
10
+ export type { SwapPort } from './swap.js';
11
+ export { isRecordedTransfer, isTransferSnapshot, mergeTransferScan, recentTransferRows, recordedTransferKeys, rescanTransfers, sentTransfers, transferRows } from './history.js';
12
+ export type { JournalTransfer, RecordedTransfer, TransferSnapshot } from './history.js';
@@ -0,0 +1,9 @@
1
+ export { PromptAborted, isPromptAborted } from './ui.js';
2
+ export { WELCOME_ART, farewell, showAddress, showError, welcome } from './output.js';
3
+ export { errorMessage, formatAmount, formatDate, formatTokenAmount } from './format.js';
4
+ export { AccountNotInitialized, initialize, mainMenu, runWallet, showBalance, showTransactions } from './menu.js';
5
+ export { loadAccount, showAccountDetails, switchNetwork } from './account.js';
6
+ export { transferFunds } from './transfer.js';
7
+ export { swapMenu } from './swap.js';
8
+ export { isRecordedTransfer, isTransferSnapshot, mergeTransferScan, recentTransferRows, recordedTransferKeys, rescanTransfers, sentTransfers, transferRows } from './history.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAMzD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAClH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { WalletSession } from './session.js';
2
+ import type { Ui } from './ui.js';
3
+ /** No account exists after the account menu closed. Hosts that can show the menu again may do so quietly. */
4
+ export declare class AccountNotInitialized extends Error {
5
+ constructor();
6
+ }
7
+ export declare function showBalance(ui: Ui, session: WalletSession): Promise<void>;
8
+ /** Sent transfers together with the network's ones in and out. Saved ones still show when the network cannot be read. */
9
+ export declare function showTransactions(ui: Ui, session: WalletSession): Promise<void>;
10
+ export declare function mainMenu(ui: Ui, session: WalletSession): Promise<void>;
11
+ export declare function initialize(ui: Ui, session: WalletSession): Promise<void>;
12
+ /** The signed-in experience: pick or create an account, show its address, then the main menu. */
13
+ export declare function runWallet(ui: Ui, session: WalletSession): Promise<void>;