mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-03 12:06:21 +01:00
feat: working balance
This commit is contained in:
parent
ffed650961
commit
fd61583db5
6 changed files with 76 additions and 83 deletions
|
@ -682,6 +682,7 @@ export class AppStorage {
|
|||
}
|
||||
} else {
|
||||
for (const wallet of this.wallets) {
|
||||
console.log('fetching balance for', wallet.getLabel());
|
||||
await wallet.fetchBalance();
|
||||
}
|
||||
}
|
||||
|
@ -728,10 +729,18 @@ export class AppStorage {
|
|||
fetchSenderPaymentCodes = async index => {
|
||||
console.log('fetchSenderPaymentCodes for wallet#', typeof index === 'undefined' ? '(all)' : index);
|
||||
if (index || index === 0) {
|
||||
this.wallets[index].fetchBIP47SenderPaymentCodes();
|
||||
try {
|
||||
await this.wallets[index].fetchBIP47SenderPaymentCodes();
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch sender payment codes for wallet', index, error);
|
||||
}
|
||||
} else {
|
||||
for (const wallet of this.wallets) {
|
||||
wallet.fetchBIP47SenderPaymentCodes();
|
||||
try {
|
||||
await wallet.fetchBIP47SenderPaymentCodes();
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch sender payment codes for wallet', wallet.label, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -297,7 +297,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
|
||||
// next, bip47 addresses
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + 2; c++) {
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + this.gap_limit; c++) {
|
||||
let hasUnconfirmed = false;
|
||||
this._txs_by_payment_code_index[pc] = this._txs_by_payment_code_index[pc] || {};
|
||||
this._txs_by_payment_code_index[pc][c] = this._txs_by_payment_code_index[pc][c] || [];
|
||||
|
@ -357,7 +357,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
this._txs_by_internal_index[c] = this._txs_by_internal_index[c].filter(tx => !!tx.confirmations);
|
||||
}
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + 2; c++) {
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + this.gap_limit; c++) {
|
||||
this._txs_by_payment_code_index[pc][c] = this._txs_by_payment_code_index[pc][c].filter(tx => !!tx.confirmations);
|
||||
}
|
||||
}
|
||||
|
@ -447,7 +447,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
}
|
||||
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + 2; c++) {
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + this.gap_limit; c++) {
|
||||
for (const tx of Object.values(txdatas)) {
|
||||
for (const vin of tx.vin) {
|
||||
if (vin.addresses && vin.addresses.indexOf(this._getBIP47Address(pc, c)) !== -1) {
|
||||
|
@ -607,7 +607,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
) {
|
||||
const address = this._getInternalAddressByIndex(c);
|
||||
if (lastHistoriesWithUsedAddresses[address] && lastHistoriesWithUsedAddresses[address].length > 0) {
|
||||
lastUsedIndex = Math.max(c, lastUsedIndex) + 1; // point to next, which is supposed to be unsued
|
||||
lastUsedIndex = Math.max(c, lastUsedIndex) + 1; // point to next, which is supposed to be unused
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -650,7 +650,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
) {
|
||||
const address = this._getExternalAddressByIndex(c);
|
||||
if (lastHistoriesWithUsedAddresses[address] && lastHistoriesWithUsedAddresses[address].length > 0) {
|
||||
lastUsedIndex = Math.max(c, lastUsedIndex) + 1; // point to next, which is supposed to be unsued
|
||||
lastUsedIndex = Math.max(c, lastUsedIndex) + 1; // point to next, which is supposed to be unused
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -693,7 +693,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
) {
|
||||
const address = this._getBIP47Address(paymentCode, c);
|
||||
if (lastHistoriesWithUsedAddresses[address] && lastHistoriesWithUsedAddresses[address].length > 0) {
|
||||
lastUsedIndex = Math.max(c, lastUsedIndex) + 1; // point to next, which is supposed to be unsued
|
||||
lastUsedIndex = Math.max(c, lastUsedIndex) + 1; // point to next, which is supposed to be unused
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -710,6 +710,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
if (this._sender_payment_codes) {
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
this.next_free_payment_code_address_index[pc] = await this._binarySearchIterationForBIP47Address(pc, 10);
|
||||
// console.log('new index after binary search', this.next_free_payment_code_address_index[pc]);
|
||||
}
|
||||
}
|
||||
} // end rescanning fresh wallet
|
||||
|
@ -733,14 +734,22 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
for (let c = this.next_free_change_address_index; c < this.next_free_change_address_index + this.gap_limit; c++) {
|
||||
lagAddressesToFetch.push(this._getInternalAddressByIndex(c));
|
||||
}
|
||||
for (const pc in this._sender_payment_codes) {
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
for (let c = this.next_free_payment_code_address_index[pc]; c < this.next_free_payment_code_address_index[pc] + this.gap_limit; c++) {
|
||||
// console.log(pc, c);
|
||||
lagAddressesToFetch.push(this._getBIP47Address(pc, c));
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('lagAddressesToFetch', lagAddressesToFetch.length);
|
||||
|
||||
const txs = await BlueElectrum.multiGetHistoryByAddress(lagAddressesToFetch); // <------ electrum call
|
||||
|
||||
console.log(
|
||||
'txs',
|
||||
Object.values(txs).filter(item => item.length > 0),
|
||||
);
|
||||
|
||||
for (let c = this.next_free_address_index; c < this.next_free_address_index + this.gap_limit; c++) {
|
||||
const address = this._getExternalAddressByIndex(c);
|
||||
if (txs[address] && Array.isArray(txs[address]) && txs[address].length > 0) {
|
||||
|
@ -757,12 +766,14 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
}
|
||||
}
|
||||
|
||||
for (const pc in this._sender_payment_codes) {
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
for (let c = this.next_free_payment_code_address_index[pc]; c < this.next_free_payment_code_address_index[pc] + this.gap_limit; c++) {
|
||||
const address = this._getBIP47Address(pc, c);
|
||||
if (txs[address] && Array.isArray(txs[address]) && txs[address].length > 0) {
|
||||
// whoa, someone uses our wallet outside! better catch up
|
||||
// console.log('catching up with bip47 address', address, c);
|
||||
this.next_free_payment_code_address_index[pc] = c + 1;
|
||||
// console.log('new index', this.next_free_payment_code_address_index[pc]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -785,14 +796,21 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
addresses2fetch.push(this._getInternalAddressByIndex(c));
|
||||
}
|
||||
|
||||
for (const pc in this._sender_payment_codes) {
|
||||
for (let c = this.next_free_payment_code_address_index[pc]; c < this.next_free_payment_code_address_index[pc] + this.gap_limit; c++) {
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
for (let c = 0; c < this.next_free_payment_code_address_index[pc] + this.gap_limit; c++) {
|
||||
addresses2fetch.push(this._getBIP47Address(pc, c));
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('fetching balance for', addresses2fetch.length, 'addresses');
|
||||
|
||||
const balances = await BlueElectrum.multiGetBalanceByAddress(addresses2fetch);
|
||||
|
||||
console.log(
|
||||
'balances',
|
||||
Object.values(balances.addresses).filter(item => item.confirmed > 0 || item.unconfirmed > 0),
|
||||
);
|
||||
|
||||
// converting to a more compact internal format
|
||||
for (let c = 0; c < this.next_free_address_index + this.gap_limit; c++) {
|
||||
const addr = this._getExternalAddressByIndex(c);
|
||||
|
@ -836,26 +854,20 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
}
|
||||
|
||||
for (const pc of this._sender_payment_codes) {
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + 2; c++) {
|
||||
let confirmed = 0;
|
||||
let unconfirmed = 0;
|
||||
for (let c = 0; c < this._getNextFreePaymentCodeAddress(pc) + this.gap_limit; c++) {
|
||||
const addr = this._getBIP47Address(pc, c);
|
||||
if (balances.addresses[addr]) {
|
||||
// first, if balances differ from what we store - we delete transactions for that
|
||||
// address so next fetchTransactions() will refetch everything
|
||||
if (this._getBalancesByPaymentCodeIndex(pc).c) {
|
||||
if (
|
||||
this._getBalancesByPaymentCodeIndex(pc).c !== balances.addresses[addr].confirmed ||
|
||||
this._getBalancesByPaymentCodeIndex(pc).u !== balances.addresses[addr].unconfirmed
|
||||
) {
|
||||
delete this._txs_by_payment_code_index[pc];
|
||||
}
|
||||
}
|
||||
// update local representation of balances on that address:
|
||||
this._balances_by_payment_code_index[pc] = {
|
||||
c: balances.addresses[addr].confirmed,
|
||||
u: balances.addresses[addr].unconfirmed,
|
||||
};
|
||||
if (balances.addresses[addr].confirmed || balances.addresses[addr].unconfirmed) {
|
||||
confirmed = confirmed + balances.addresses[addr].confirmed;
|
||||
unconfirmed = unconfirmed + balances.addresses[addr].unconfirmed;
|
||||
// console.log(this._balances_by_payment_code_index);
|
||||
}
|
||||
}
|
||||
this._balances_by_payment_code_index[pc] = {
|
||||
c: confirmed,
|
||||
u: unconfirmed,
|
||||
};
|
||||
}
|
||||
|
||||
this._lastBalanceFetch = +new Date();
|
||||
|
@ -1450,20 +1462,24 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
return this._payment_code;
|
||||
}
|
||||
|
||||
getBIP47NotificationAddress(): string {
|
||||
return this.getBIP47FromSeed().getNotificationAddress();
|
||||
}
|
||||
async fetchBIP47SenderPaymentCodes(): Promise<void> {
|
||||
const bip47_instance = BIP47Factory(ecc).fromBip39Seed(this.secret, undefined, this.passphrase);
|
||||
|
||||
async fetchBIP47SenderPaymentCodes() {
|
||||
const bip47 = this.getBIP47FromSeed();
|
||||
const address = bip47.getNotificationAddress();
|
||||
if (!bip47_instance.getNotificationAddress) {
|
||||
console.error('bip47.getNotificationAddress is not a function');
|
||||
return;
|
||||
}
|
||||
|
||||
const address = bip47_instance.getNotificationAddress();
|
||||
|
||||
const histories = await BlueElectrum.multiGetHistoryByAddress([address]);
|
||||
const txHashes = histories[address].map(({ tx_hash }) => tx_hash);
|
||||
|
||||
const txHexs = await BlueElectrum.multiGetTransactionHexByTxid(txHashes);
|
||||
this._sender_payment_codes = Object.values(txHexs).map(str => {
|
||||
return bip47.getPaymentCodeFromRawNotificationTransaction(str);
|
||||
this.next_free_payment_code_address_index[str] = 0; // initialize
|
||||
this._balances_by_payment_code_index[str] = { c: 0, u: 0 };
|
||||
return bip47_instance.getPaymentCodeFromRawNotificationTransaction(str);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1471,19 +1487,21 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
|||
return this._sender_payment_codes;
|
||||
}
|
||||
|
||||
_getBIP47Address(paymentCode: string, index: number) {
|
||||
_getBIP47Address(paymentCode: string, index: number): string {
|
||||
if (!this.addresses_by_payment_code[paymentCode]) this.addresses_by_payment_code[paymentCode] = [];
|
||||
|
||||
if (this.addresses_by_payment_code[paymentCode][index]) {
|
||||
return this.addresses_by_payment_code[paymentCode][index];
|
||||
}
|
||||
|
||||
const bip47_instance = this.getBIP47FromSeed();
|
||||
const bip47 = BIP47Factory(ecc);
|
||||
const bip47_instance = bip47.fromBip39Seed(this.secret, undefined, this.passphrase);
|
||||
const senderBIP47_instance = bip47.fromPaymentCode(paymentCode);
|
||||
const remotePaymentNode = senderBIP47_instance.getPaymentCodeNode();
|
||||
const hdNode = bip47_instance.getPaymentWallet(remotePaymentNode, index);
|
||||
const address = bip47_instance.getAddressFromNode(hdNode, bip47_instance.network);
|
||||
this.addresses_by_payment_code[paymentCode][index] = address;
|
||||
console.log('generated address', address);
|
||||
return address;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ export class AbstractHDWallet extends LegacyWallet {
|
|||
this._xpub = ''; // cache
|
||||
this.usedAddresses = [];
|
||||
this._address_to_wif_cache = {};
|
||||
this.gap_limit = 20;
|
||||
this.gap_limit = 5;
|
||||
this._derivationPath = Constructor.derivationPath;
|
||||
}
|
||||
|
||||
|
|
50
package-lock.json
generated
50
package-lock.json
generated
|
@ -21,7 +21,7 @@
|
|||
"@react-navigation/drawer": "5.12.9",
|
||||
"@react-navigation/native": "5.9.8",
|
||||
"@remobile/react-native-qrcode-local-image": "https://github.com/BlueWallet/react-native-qrcode-local-image",
|
||||
"@spsina/bip47": "^1.0.1",
|
||||
"@spsina/bip47": "file:../bip47/spsina-bip47-1.0.1.tgz",
|
||||
"aez": "1.0.1",
|
||||
"assert": "2.0.0",
|
||||
"base-x": "3.0.9",
|
||||
|
@ -5778,8 +5778,9 @@
|
|||
},
|
||||
"node_modules/@spsina/bip47": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@spsina/bip47/-/bip47-1.0.1.tgz",
|
||||
"integrity": "sha512-ZCjDXm9WcVLz1wgBBRPxg0NTg3RvgxmWcAQhsZSYFgp7PLpa7pK/dHfxNUhnBNbaCwRFiyfHnNYHLV0OFTizkw==",
|
||||
"resolved": "file:../bip47/spsina-bip47-1.0.1.tgz",
|
||||
"integrity": "sha512-lsgEpiEMDgpiYOA2kizOwiSS3vjTeLe2VnkOTIGnJ7Eu7Mkgl9dLES7oSLAjY64aQXr0VolqCRciRDc2nAC++w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bip32": "^3.0.1",
|
||||
"bip39": "^3.0.4",
|
||||
|
@ -5787,23 +5788,12 @@
|
|||
"bs58check": "^2.1.1",
|
||||
"create-hmac": "^1.1.7",
|
||||
"ecpair": "^2.0.1",
|
||||
"tiny-secp256k1": "^2.2.1"
|
||||
"tiny-secp256k1": "^1.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@spsina/bip47/node_modules/tiny-secp256k1": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz",
|
||||
"integrity": "sha512-/U4xfVqnVxJXN4YVsru0E6t5wVncu2uunB8+RVR40fYUxkKYUPS10f+ePQZgFBoE/Jbf9H1NBveupF2VmB58Ng==",
|
||||
"dependencies": {
|
||||
"uint8array-tools": "0.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||
|
@ -26312,14 +26302,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uint8array-tools": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz",
|
||||
"integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ultron": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
|
||||
|
@ -31344,9 +31326,8 @@
|
|||
}
|
||||
},
|
||||
"@spsina/bip47": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@spsina/bip47/-/bip47-1.0.1.tgz",
|
||||
"integrity": "sha512-ZCjDXm9WcVLz1wgBBRPxg0NTg3RvgxmWcAQhsZSYFgp7PLpa7pK/dHfxNUhnBNbaCwRFiyfHnNYHLV0OFTizkw==",
|
||||
"version": "file:../bip47/spsina-bip47-1.0.1.tgz",
|
||||
"integrity": "sha512-lsgEpiEMDgpiYOA2kizOwiSS3vjTeLe2VnkOTIGnJ7Eu7Mkgl9dLES7oSLAjY64aQXr0VolqCRciRDc2nAC++w==",
|
||||
"requires": {
|
||||
"bip32": "^3.0.1",
|
||||
"bip39": "^3.0.4",
|
||||
|
@ -31354,17 +31335,7 @@
|
|||
"bs58check": "^2.1.1",
|
||||
"create-hmac": "^1.1.7",
|
||||
"ecpair": "^2.0.1",
|
||||
"tiny-secp256k1": "^2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"tiny-secp256k1": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz",
|
||||
"integrity": "sha512-/U4xfVqnVxJXN4YVsru0E6t5wVncu2uunB8+RVR40fYUxkKYUPS10f+ePQZgFBoE/Jbf9H1NBveupF2VmB58Ng==",
|
||||
"requires": {
|
||||
"uint8array-tools": "0.0.7"
|
||||
}
|
||||
}
|
||||
"tiny-secp256k1": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"@tootallnate/once": {
|
||||
|
@ -47383,11 +47354,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"uint8array-tools": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz",
|
||||
"integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ=="
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
"@react-navigation/drawer": "5.12.9",
|
||||
"@react-navigation/native": "5.9.8",
|
||||
"@remobile/react-native-qrcode-local-image": "https://github.com/BlueWallet/react-native-qrcode-local-image",
|
||||
"@spsina/bip47": "^1.0.1",
|
||||
"@spsina/bip47": "file:../bip47/spsina-bip47-1.0.1.tgz",
|
||||
"aez": "1.0.1",
|
||||
"assert": "2.0.0",
|
||||
"base-x": "3.0.9",
|
||||
|
|
|
@ -179,7 +179,7 @@ const WalletTransactions = ({ navigation }) => {
|
|||
// await BlueElectrum.ping();
|
||||
await BlueElectrum.waitTillConnected();
|
||||
/** @type {LegacyWallet} */
|
||||
await wallet.fetchBIP47SenderPaymentCodes();
|
||||
await wallet.fetchBIP47SenderPaymentCodes(); // FIXME:
|
||||
const balanceStart = +new Date();
|
||||
const oldBalance = wallet.getBalance();
|
||||
await wallet.fetchBalance();
|
||||
|
|
Loading…
Add table
Reference in a new issue