FIX: better support parsing taproot addresses from Electrum (rel #4749)

This commit is contained in:
Overtorment 2022-06-21 13:43:28 +01:00
parent 34e0d39913
commit a34605224a
6 changed files with 53 additions and 1 deletions

View file

@ -85,3 +85,5 @@ export function estimateFees(): Promise<{ fast: number; medium: number; slow: nu
export function broadcastV2(txhex: string): Promise<string>; export function broadcastV2(txhex: string): Promise<string>;
export function getTransactionsFullByAddress(address: string): Promise<Transaction[]>; export function getTransactionsFullByAddress(address: string): Promise<Transaction[]>;
export function txhexToElectrumTransaction(txhes: string): Transaction;

View file

@ -1,6 +1,6 @@
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
import { Alert } from 'react-native'; import { Alert } from 'react-native';
import { LegacyWallet, SegwitBech32Wallet, SegwitP2SHWallet } from '../class'; import { LegacyWallet, SegwitBech32Wallet, SegwitP2SHWallet, TaprootWallet } from '../class';
import DefaultPreference from 'react-native-default-preference'; import DefaultPreference from 'react-native-default-preference';
import loc from '../loc'; import loc from '../loc';
import WidgetCommunication from './WidgetCommunication'; import WidgetCommunication from './WidgetCommunication';
@ -1030,6 +1030,9 @@ function txhexToElectrumTransaction(txhex) {
} else if (LegacyWallet.scriptPubKeyToAddress(out.script.toString('hex'))) { } else if (LegacyWallet.scriptPubKeyToAddress(out.script.toString('hex'))) {
address = LegacyWallet.scriptPubKeyToAddress(out.script.toString('hex')); address = LegacyWallet.scriptPubKeyToAddress(out.script.toString('hex'));
type = '???'; // TODO type = '???'; // TODO
} else {
address = TaprootWallet.scriptPubKeyToAddress(out.script.toString('hex'));
type = 'witness_v1_taproot';
} }
ret.vout.push({ ret.vout.push({
@ -1047,3 +1050,6 @@ function txhexToElectrumTransaction(txhex) {
} }
return ret; return ret;
} }
// exported only to be used in unit tests
module.exports.txhexToElectrumTransaction = txhexToElectrumTransaction;

View file

@ -2,6 +2,7 @@ export * from './app-storage';
export * from './wallets/abstract-wallet'; export * from './wallets/abstract-wallet';
export * from './wallets/legacy-wallet'; export * from './wallets/legacy-wallet';
export * from './wallets/segwit-bech32-wallet'; export * from './wallets/segwit-bech32-wallet';
export * from './wallets/taproot-wallet';
export * from './wallets/segwit-p2sh-wallet'; export * from './wallets/segwit-p2sh-wallet';
export * from './wallets/hd-segwit-p2sh-wallet'; export * from './wallets/hd-segwit-p2sh-wallet';
export * from './wallets/hd-legacy-breadwallet-wallet'; export * from './wallets/hd-legacy-breadwallet-wallet';

View file

@ -0,0 +1,23 @@
import { SegwitBech32Wallet } from './segwit-bech32-wallet';
const bitcoin = require('bitcoinjs-lib');
export class TaprootWallet extends SegwitBech32Wallet {
static type = 'taproot';
static typeReadable = 'P2 TR';
static segwitType = 'p2wpkh';
/**
* Converts script pub key to a Taproot address if it can. Returns FALSE if it cant.
*
* @param scriptPubKey
* @returns {boolean|string} Either bech32 address or false
*/
static scriptPubKeyToAddress(scriptPubKey) {
try {
const publicKey = Buffer.from(scriptPubKey, 'hex');
return bitcoin.address.fromOutputScript(publicKey, bitcoin.networks.bitcoin);
} catch (_) {
return false;
}
}
}

View file

@ -168,6 +168,13 @@ describe('BlueElectrum', () => {
} }
}); });
it('BlueElectrum can do txhexToElectrumTransaction()', () => {
const tx =
'0200000000010137d07edbc9db9a072a79c6f03e7274e52642d64d760143adc64832501087f37b00000000000000008002102700000000000022512040ef293a8a0ebaf8b351a27d89ff4b5b3822a635e4afdca77a30170c363bafa3e4ad0b00000000001600147dfe2249fa56a2f2b4b7ed3b16ee55e7c565198002483045022100e5b9f1c12e133ef659a0e5cc417b1f8625ba9e951bc7083408de2a33d6fb1a84022035ebb1e2d4ab620ee178dc6cd0b58c54123d1526d9a1b3efba612ea80e48edd101210295b56fc62cdd09c200ce19f873d5ddb3074f7141b2533448829385f48f093a1600000000';
const decoded = BlueElectrum.txhexToElectrumTransaction(tx);
assert.strictEqual(decoded.vout[0].scriptPubKey.addresses[0], 'bc1pgrhjjw52p6a03v635f7cnl6ttvuz9f34ujhaefm6xqtscd3m473szkl92g');
});
it.each([false, true])('BlueElectrum can do multiGetBalanceByAddress(), disableBatching=%p', async function (diableBatching) { it.each([false, true])('BlueElectrum can do multiGetBalanceByAddress(), disableBatching=%p', async function (diableBatching) {
if (diableBatching) BlueElectrum.setBatchingDisabled(); if (diableBatching) BlueElectrum.setBatchingDisabled();
const balances = await BlueElectrum.multiGetBalanceByAddress([ const balances = await BlueElectrum.multiGetBalanceByAddress([

View file

@ -0,0 +1,13 @@
import { TaprootWallet } from '../../class';
const assert = require('assert');
describe('Taproot wallet', () => {
it('can convert scriptPubKey to address', () => {
let address = TaprootWallet.scriptPubKeyToAddress('512040ef293a8a0ebaf8b351a27d89ff4b5b3822a635e4afdca77a30170c363bafa3');
assert.strictEqual(address, 'bc1pgrhjjw52p6a03v635f7cnl6ttvuz9f34ujhaefm6xqtscd3m473szkl92g');
address = TaprootWallet.scriptPubKeyToAddress();
assert.strictEqual(address, false);
address = TaprootWallet.scriptPubKeyToAddress('trololo');
assert.strictEqual(address, false);
});
});