Skip to content

Commit 6911f87

Browse files
committed
feat: use wasm-utxo for address generation on testnets
Use wasm-utxo's fixedScriptWallet.address for testnets instead of utxo-lib's address derivation. This improves compatibility with the native implementation. Co-authored-by: llm-git <[email protected]> Ticket: BTC-2720 TICKET: BTC-2720
1 parent 61daef3 commit 6911f87

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

modules/abstract-utxo/src/address/fixedScript.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import * as utxolib from '@bitgo/utxo-lib';
1515
import { bitgo } from '@bitgo/utxo-lib';
1616
import { bip32 } from '@bitgo/secp256k1';
17+
import * as wasmUtxo from '@bitgo/wasm-utxo';
1718

1819
type ScriptType2Of3 = bitgo.outputScripts.ScriptType2Of3;
1920

@@ -56,6 +57,15 @@ export function generateAddressWithChainAndIndex(
5657
index: number,
5758
format: CreateAddressFormat | undefined
5859
): string {
60+
if (utxolib.isTestnet(network)) {
61+
return wasmUtxo.fixedScriptWallet.address(
62+
keychains.map((k) => k.pub) as [string, string, string],
63+
chain,
64+
index,
65+
network
66+
);
67+
}
68+
5969
const path = '0/0/' + chain + '/' + index;
6070
const hdNodes = keychains.map(({ pub }) => bip32.fromBase58(pub));
6171
const derivedKeys = hdNodes.map((hdNode) => hdNode.derivePath(sanitizeLegacyPath(path)).publicKey);

modules/abstract-utxo/test/unit/util/unspents.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as utxolib from '@bitgo/utxo-lib';
22
import { getSeed } from '@bitgo/sdk-test';
3+
import * as wasmUtxo from '@bitgo/wasm-utxo';
34

45
import { getReplayProtectionAddresses } from '../../../src';
56

@@ -31,6 +32,9 @@ export function getWalletAddress(
3132
chain = defaultChain,
3233
index = 0
3334
): string {
35+
if (utxolib.isTestnet(network)) {
36+
return wasmUtxo.fixedScriptWallet.address(walletKeys, chain, index, network);
37+
}
3438
return utxolib.address.fromOutputScript(getOutputScript(walletKeys, chain, index).scriptPubKey, network);
3539
}
3640

@@ -49,8 +53,7 @@ export function mockWalletUnspent<TNumber extends number | bigint = number>(
4953
if (chain === undefined) {
5054
throw new Error(`unspent chain must be set`);
5155
}
52-
const derived = getOutputScript(walletKeys, chain, index);
53-
const deriveAddress = utxolib.address.fromOutputScript(derived.scriptPubKey, network);
56+
const deriveAddress = getWalletAddress(network, walletKeys, chain, index);
5457
if (address) {
5558
if (address !== deriveAddress) {
5659
throw new Error(`derivedAddress mismatch: ${address} derived=${deriveAddress}`);

modules/utxo-lib/src/bitgo/wallet/WalletScripts.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { Network, address } from '../..';
1+
import { Network, address, isTestnet } from '../..';
22
import { ChainCode, outputScripts } from '..';
33
import { RootWalletKeys } from './WalletKeys';
44
import { scriptTypeForChain, SpendableScript } from '../outputScripts';
5+
import * as wasmUtxo from '@bitgo/wasm-utxo';
56

67
export function getWalletOutputScripts(keys: RootWalletKeys, chain: ChainCode, index: number): SpendableScript {
78
return outputScripts.createOutputScript2of3(
@@ -11,5 +12,8 @@ export function getWalletOutputScripts(keys: RootWalletKeys, chain: ChainCode, i
1112
}
1213

1314
export function getWalletAddress(keys: RootWalletKeys, chain: ChainCode, index: number, network: Network): string {
15+
if (isTestnet(network)) {
16+
return wasmUtxo.fixedScriptWallet.address(keys, chain, index, network);
17+
}
1418
return address.fromOutputScript(getWalletOutputScripts(keys, chain, index).scriptPubKey, network);
1519
}

modules/utxo-lib/src/testutil/mock.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ok as assert } from 'assert';
22
import { BIP32Interface } from '@bitgo/secp256k1';
33
import { payments } from '..';
4-
import { getMainnet, Network, networks } from '../networks';
4+
import { getMainnet, Network, networks, isTestnet } from '../networks';
55

66
import {
77
ChainCode,
@@ -22,6 +22,7 @@ import {
2222
} from '../bitgo';
2323
import { fromOutputScript } from '../address';
2424
import { createOutputScript2of3, createOutputScriptP2shP2pk } from '../bitgo/outputScripts';
25+
import * as wasmUtxo from '@bitgo/wasm-utxo';
2526

2627
import { getDefaultWalletKeys, getKey } from './keys';
2728

@@ -94,14 +95,17 @@ export function mockWalletUnspent<TNumber extends number | bigint>(
9495
id,
9596
}: { chain?: ChainCode; index?: number; keys?: RootWalletKeys; vout?: number; id?: string } = {}
9697
): WalletUnspent<TNumber> | NonWitnessWalletUnspent<TNumber> {
97-
const derivedKeys = keys.deriveForChainAndIndex(chain, index);
98-
const address = fromOutputScript(
99-
createOutputScript2of3(derivedKeys.publicKeys, scriptTypeForChain(chain)).scriptPubKey,
100-
network
101-
);
98+
const address = isTestnet(network)
99+
? wasmUtxo.fixedScriptWallet.address(keys, chain, index, network)
100+
: fromOutputScript(
101+
createOutputScript2of3(keys.deriveForChainAndIndex(chain, index).publicKeys, scriptTypeForChain(chain))
102+
.scriptPubKey,
103+
network
104+
);
102105
if (id && typeof id === 'string') {
103106
return { id, address, chain, index, value };
104107
} else {
108+
const derivedKeys = keys.deriveForChainAndIndex(chain, index);
105109
const prevTransaction = mockPrevTx(
106110
vout,
107111
createOutputScript2of3(derivedKeys.publicKeys, scriptTypeForChain(chain), network).scriptPubKey,

0 commit comments

Comments
 (0)