hodl-wallet 1.8.0 → 1.8.4

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/index.js CHANGED
@@ -464,17 +464,23 @@ class Wallet {
464
464
 
465
465
  const transactionHash = receipt?.transactionHash || receipt?.hash || 'UNKNOWN_HASH';
466
466
 
467
- // Get current balance after transfer
467
+ // Calculate the post-transaction balance
468
468
  let currentBalance = 0;
469
469
  try {
470
470
  const walletAddress = await this.getAddress();
471
+
472
+ // Get the balance AFTER transaction (not before)
471
473
  if (token === this.selectedNetwork.nativeToken) {
472
474
  currentBalance = await this.network.getBalance(walletAddress);
473
475
  } else {
474
476
  currentBalance = await this.network.getTokenBalance(walletAddress, token);
475
477
  }
478
+
479
+ // Round to avoid floating point precision issues
480
+ currentBalance = Math.round(currentBalance * 100000000) / 100000000;
481
+
476
482
  } catch (error) {
477
- console.error('Error getting current balance:', error.message);
483
+ console.error('Error getting post-transaction balance:', error.message);
478
484
  }
479
485
 
480
486
  await this.displayTransactionResult(address, token, numericAmount, transactionHash, currentBalance);
@@ -47,7 +47,26 @@ export default class BaseNetwork {
47
47
  throw new Error("Method 'validateMnemonic' must be implemented.");
48
48
  }
49
49
 
50
- // Add after line 51
50
+ async getTokenBalance(address, tokenSymbol) {
51
+ throw new Error("Method 'getTokenBalance' must be implemented.");
52
+ }
53
+
54
+ async getTokenBalances(address) {
55
+ const balances = [];
56
+
57
+ // Get native token balance
58
+ const nativeBalance = await this.getBalance(address);
59
+ balances.push([this.config.nativeToken, parseFloat(nativeBalance)]);
60
+
61
+ // Get balances for all configured tokens
62
+ for (const symbol of Object.keys(this.config.tokens)) {
63
+ const tokenBalance = await this.getTokenBalance(address, symbol);
64
+ balances.push([symbol, tokenBalance]);
65
+ }
66
+
67
+ return balances;
68
+ }
69
+
51
70
  async sendSignedTransaction(signedTx) {
52
71
  throw new Error("Method 'sendSignedTransaction' must be implemented.");
53
72
  }
@@ -30,20 +30,17 @@ export default class BitcoinNetwork extends BaseNetwork {
30
30
  }
31
31
  }
32
32
 
33
-
34
- async getTokenBalances(address) {
35
- const balances = [];
36
-
37
- const nativeBalance = await this.getBalance(address);
38
- balances.push([this.config.nativeToken, nativeBalance]);
39
-
40
- return balances;
33
+ async getTokenBalance(address, tokenSymbol) {
34
+ if (tokenSymbol === this.config.nativeToken) {
35
+ return await this.getBalance(address);
36
+ }
37
+ throw new Error(`Token ${tokenSymbol} not supported on Bitcoin network`);
41
38
  }
42
39
 
43
40
  async transfer(from, to, amount, options = {}) {
44
41
  try {
45
42
  const utxos = await this.getUTXOs(from.address);
46
- const satoshis = BigInt(this.BTCToSatoshis(amount));
43
+ const satoshis = this.BTCToSatoshis(amount); // Regular number, not BigInt
47
44
  const feeRate = options.feeRate || 10; // sats/byte
48
45
 
49
46
  // Create PSBT instance with network
@@ -51,7 +48,7 @@ export default class BitcoinNetwork extends BaseNetwork {
51
48
  psbt.setVersion(2);
52
49
  psbt.setLocktime(0);
53
50
 
54
- let totalInputValue = 0n;
51
+ let totalInputValue = 0;
55
52
 
56
53
  // Add inputs
57
54
  for (const utxo of utxos) {
@@ -65,16 +62,16 @@ export default class BitcoinNetwork extends BaseNetwork {
65
62
  sequence: 0xffffffff
66
63
  });
67
64
 
68
- totalInputValue += BigInt(utxo.value);
65
+ totalInputValue += utxo.value;
69
66
 
70
67
  // Break if we have enough funds (considering estimated fee)
71
- const estimatedFee = BigInt(this.estimateTxSize(psbt.inputCount, 2) * feeRate);
68
+ const estimatedFee = this.estimateTxSize(psbt.inputCount, 2) * feeRate;
72
69
  if (totalInputValue >= satoshis + estimatedFee) {
73
70
  break;
74
71
  }
75
72
  }
76
73
 
77
- if (totalInputValue < satoshis + BigInt(feeRate)) {
74
+ if (totalInputValue < satoshis + feeRate) {
78
75
  throw new Error('Insufficient balance for the transaction including fees.');
79
76
  }
80
77
 
@@ -85,9 +82,9 @@ export default class BitcoinNetwork extends BaseNetwork {
85
82
  });
86
83
 
87
84
  // Add change output if needed
88
- const estimatedFee = BigInt(this.estimateTxSize(psbt.inputCount, 2) * feeRate);
85
+ const estimatedFee = this.estimateTxSize(psbt.inputCount, 2) * feeRate;
89
86
  const changeValue = totalInputValue - satoshis - estimatedFee;
90
- if (changeValue > 546n) { // Dust threshold
87
+ if (changeValue > 546) { // Dust threshold
91
88
  psbt.addOutput({
92
89
  address: from.address,
93
90
  value: changeValue
@@ -167,15 +164,23 @@ export default class BitcoinNetwork extends BaseNetwork {
167
164
  const path = `m/84'/0'/0'/0/0`; // BIP84 para SegWit nativo
168
165
  const child = root.derivePath(path);
169
166
 
167
+ // Convert Uint8Array to Buffer if needed
168
+ const privateKeyBuffer = Buffer.isBuffer(child.privateKey)
169
+ ? child.privateKey
170
+ : Buffer.from(child.privateKey);
171
+
172
+ // Create ECPair from the private key buffer
173
+ const keyPair = ECPair.fromPrivateKey(privateKeyBuffer, { network: this.network });
174
+
170
175
  const { address } = bitcoin.payments.p2wpkh({
171
- pubkey: child.publicKey,
176
+ pubkey: keyPair.publicKey,
172
177
  network: this.network
173
178
  });
174
179
 
175
180
  return {
176
181
  address,
177
- privateKey: child.toWIF(),
178
- publicKey: child.publicKey.toString('hex'),
182
+ privateKey: keyPair.toWIF(),
183
+ publicKey: keyPair.publicKey.toString('hex'),
179
184
  mnemonic
180
185
  };
181
186
  }
@@ -137,32 +137,6 @@ export default class TONNetwork extends BaseNetwork {
137
137
  }));
138
138
  }
139
139
 
140
- async getTokenBalances(address) {
141
- const balances = [];
142
-
143
- // Add native TON balance
144
- try {
145
- const nativeBalance = await this.getBalance(address);
146
- balances.push([this.config.nativeToken, nativeBalance]);
147
- } catch (error) {
148
- console.error('Failed to get TON balance:', error);
149
- balances.push([this.config.nativeToken, 0]);
150
- }
151
-
152
- // Add token balances (not implemented yet)
153
- for (const tokenSymbol in this.config.tokens) {
154
- try {
155
- const tokenBalance = await this.getTokenBalance(address, tokenSymbol);
156
- balances.push([tokenSymbol, tokenBalance]);
157
- } catch (error) {
158
- console.error(`Failed to get ${tokenSymbol} balance:`, error);
159
- balances.push([tokenSymbol, 0]);
160
- }
161
- }
162
-
163
- return balances;
164
- }
165
-
166
140
  async sendSignedTransaction(signedTx) {
167
141
  // For TON, the transaction is already sent and signedTx contains the result
168
142
  let transactionHash;
@@ -98,30 +98,21 @@ export default class Web3Network extends BaseNetwork {
98
98
  return this.transfer(account, recipient, amount, { gasLimit, gasPrice });
99
99
  }
100
100
 
101
- async getTokenBalances(address) {
102
- const balances = [];
103
-
104
- // Get native token balance
105
- const nativeBalance = await this.getBalance(address);
106
- balances.push([this.config.nativeToken, parseFloat(nativeBalance)]);
107
-
108
- // Get balances for all configured tokens
109
- for (const [symbol, tokenConfig] of Object.entries(this.config.tokens)) {
110
- const contract = new this.web3.eth.Contract(
111
- ERC20_ABI,
112
- tokenConfig.address
113
- );
114
- const balance = await contract.methods.balanceOf(address).call();
115
- const decimals = await contract.methods.decimals().call();
116
-
117
- const formattedBalance = Number(
118
- (BigInt(balance) * 100n) / (10n ** BigInt(decimals))
119
- ) / 100;
120
-
121
- balances.push([symbol, formattedBalance]);
101
+ async getTokenBalance(address, tokenSymbol) {
102
+ if (tokenSymbol === this.config.nativeToken) {
103
+ return await this.getBalance(address);
122
104
  }
123
105
 
124
- return balances;
106
+ const tokenConfig = this.config.tokens[tokenSymbol];
107
+ if (!tokenConfig) throw new Error(`Token ${tokenSymbol} not supported`);
108
+
109
+ const contract = new this.web3.eth.Contract(ERC20_ABI, tokenConfig.address);
110
+ const balance = await contract.methods.balanceOf(address).call();
111
+ const decimals = await contract.methods.decimals().call();
112
+
113
+ return Number(
114
+ (BigInt(balance) * 100n) / (10n ** BigInt(decimals))
115
+ ) / 100;
125
116
  }
126
117
 
127
118
  async privateKeyToAccount(privateKey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hodl-wallet",
3
- "version": "1.8.0",
3
+ "version": "1.8.4",
4
4
  "description": "🧊 HODL Wallet - Fast CLI crypto wallet!",
5
5
  "author": "Martin Clasen",
6
6
  "repository": {
@@ -29,6 +29,7 @@
29
29
  "bep20",
30
30
  "bnb",
31
31
  "eth",
32
+ "ton",
32
33
  "binance",
33
34
  "trust",
34
35
  "blockchain",