diff --git a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts index 2a3872becb..bbb23f57cb 100644 --- a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts +++ b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts @@ -11,6 +11,7 @@ import { krsProviders, } from '@bitgo/sdk-core'; import { getMainnet, networks } from '@bitgo/utxo-lib'; +import { CoinName } from '@bitgo/wasm-utxo'; import { AbstractUtxoCoin } from '../abstractUtxoCoin'; import { signAndVerifyPsbt } from '../transaction/fixedScript/signPsbt'; @@ -377,6 +378,7 @@ export async function backupKeyRecovery( recoveryDestination: params.recoveryDestination, keyRecoveryServiceFee: krsFee, keyRecoveryServiceFeeAddress: krsFeeAddress, + coinName: coin.getChain() as CoinName, }, backend ); diff --git a/modules/abstract-utxo/src/recovery/crossChainRecovery.ts b/modules/abstract-utxo/src/recovery/crossChainRecovery.ts index 4b65d98792..c4bd264d1f 100644 --- a/modules/abstract-utxo/src/recovery/crossChainRecovery.ts +++ b/modules/abstract-utxo/src/recovery/crossChainRecovery.ts @@ -1,7 +1,7 @@ import * as utxolib from '@bitgo/utxo-lib'; import { BIP32Interface, bip32 } from '@bitgo/secp256k1'; import { Dimensions } from '@bitgo/unspents'; -import { fixedScriptWallet } from '@bitgo/wasm-utxo'; +import { fixedScriptWallet, CoinName } from '@bitgo/wasm-utxo'; import { BitGoBase, IWallet, Keychain, Triple, Wallet } from '@bitgo/sdk-core'; import { decrypt } from '@bitgo/sdk-api'; @@ -388,6 +388,7 @@ function createSweepTransactionUtxolib * @param unspents * @param targetAddress * @param feeRateSatVB + * @param coinName - BitGo coin name (e.g. 'btc', 'tbtc', 'ltc') * @return unsigned PSBT */ function createSweepTransactionWasm( @@ -395,7 +396,8 @@ function createSweepTransactionWasm( walletKeys: RootWalletKeys, unspents: WalletUnspent[], targetAddress: string, - feeRateSatVB: number + feeRateSatVB: number, + coinName: CoinName ): utxolib.bitgo.UtxoPsbt { const inputValue = unspentSum( unspents.map((u) => ({ ...u, value: BigInt(u.value) })), @@ -408,9 +410,8 @@ function createSweepTransactionWasm( addWalletInputsToWasmPsbt(wasmPsbt, unspentsBigint, walletKeys); // Calculate dimensions using wasm-utxo Dimensions - const targetOutputScript = utxolib.address.toOutputScript(targetAddress, network); const vsize = fixedScriptWallet.Dimensions.fromPsbt(wasmPsbt) - .plus(fixedScriptWallet.Dimensions.fromOutput(new Uint8Array(targetOutputScript))) + .plus(fixedScriptWallet.Dimensions.fromOutput(targetAddress, coinName)) .getVSize(); const fee = BigInt(Math.round(vsize * feeRateSatVB)); @@ -429,6 +430,7 @@ function createSweepTransactionWasm( * @param targetAddress * @param feeRateSatVB * @param backend - Which backend to use for PSBT creation (default: 'wasm-utxo') + * @param coinName - BitGo coin name (required for wasm-utxo backend) * @return unsigned PSBT */ function createSweepTransaction( @@ -437,10 +439,14 @@ function createSweepTransaction( unspents: WalletUnspent[], targetAddress: string, feeRateSatVB: number, - backend: PsbtBackend = 'wasm-utxo' + backend: PsbtBackend = 'wasm-utxo', + coinName?: CoinName ): utxolib.bitgo.UtxoPsbt { if (backend === 'wasm-utxo') { - return createSweepTransactionWasm(network, walletKeys, unspents, targetAddress, feeRateSatVB); + if (!coinName) { + throw new Error('coinName is required for wasm-utxo backend'); + } + return createSweepTransactionWasm(network, walletKeys, unspents, targetAddress, feeRateSatVB, coinName); } else { return createSweepTransactionUtxolib(network, walletKeys, unspents, targetAddress, feeRateSatVB); } @@ -502,7 +508,8 @@ export async function recoverCrossChain = utxolib.bitgo.WalletUnspent; @@ -60,6 +60,8 @@ interface CreateBackupKeyRecoveryPsbtOptions { keyRecoveryServiceFeeAddress: string | undefined; /** Block height for Zcash networks (required to determine consensus branch ID) */ blockHeight?: number; + /** Coin name for wasm-utxo (e.g. 'btc', 'tbtc', 'ltc') */ + coinName?: CoinName; } /** @@ -243,21 +245,23 @@ function createBackupKeyRecoveryPsbtWasm( unspents: WalletUnspent[], options: CreateBackupKeyRecoveryPsbtOptions ): utxolib.bitgo.UtxoPsbt { - const { feeRateSatVB, recoveryDestination, keyRecoveryServiceFee, keyRecoveryServiceFeeAddress } = options; + const { feeRateSatVB, recoveryDestination, keyRecoveryServiceFee, keyRecoveryServiceFeeAddress, coinName } = options; + + if (!coinName) { + throw new Error('coinName is required for wasm-utxo backend'); + } // Create PSBT with wasm-utxo and add wallet inputs using shared utilities const wasmPsbt = createEmptyWasmPsbt(network, rootWalletKeys, { blockHeight: options.blockHeight }); addWalletInputsToWasmPsbt(wasmPsbt, unspents, rootWalletKeys); // Calculate dimensions using wasm-utxo Dimensions - const recoveryOutputScript = utxolib.address.toOutputScript(recoveryDestination, network); let dimensions = fixedScriptWallet.Dimensions.fromPsbt(wasmPsbt).plus( - fixedScriptWallet.Dimensions.fromOutput(new Uint8Array(recoveryOutputScript)) + fixedScriptWallet.Dimensions.fromOutput(recoveryDestination, coinName) ); if (keyRecoveryServiceFeeAddress) { - const krsOutputScript = utxolib.address.toOutputScript(keyRecoveryServiceFeeAddress, network); - dimensions = dimensions.plus(fixedScriptWallet.Dimensions.fromOutput(new Uint8Array(krsOutputScript))); + dimensions = dimensions.plus(fixedScriptWallet.Dimensions.fromOutput(keyRecoveryServiceFeeAddress, coinName)); } const approximateFee = BigInt(dimensions.getVSize() * feeRateSatVB);