From 189591336348338067bf99c44d31f6820246da9a Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Thu, 13 Jun 2024 17:06:03 +0200 Subject: [PATCH] feat: add comments, modify withdrawal transaction recipients --- src/dlc-handlers/ledger-dlc-handler.ts | 67 +++++++++++++++++++ .../software-wallet-dlc-handler.ts | 9 ++- src/functions/bitcoin/psbt-functions.ts | 22 ++++-- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/dlc-handlers/ledger-dlc-handler.ts b/src/dlc-handlers/ledger-dlc-handler.ts index 3afb97b..c8ae6c5 100644 --- a/src/dlc-handlers/ledger-dlc-handler.ts +++ b/src/dlc-handlers/ledger-dlc-handler.ts @@ -18,6 +18,7 @@ import { addTaprootInputSignaturesToPSBT, createClosingTransaction, createFundingTransaction, + createWithdrawalTransaction, getNativeSegwitInputsToSign, getTaprootInputsToSign, updateNativeSegwitInputs, @@ -396,6 +397,72 @@ export class LedgerDLCHandler { } } + async createWithdrawalPSBT( + vault: RawVault, + withdrawAmount: bigint, + attestorGroupPublicKey: string, + fundingTransactionID: string, + feeRateMultiplier?: number, + customFeeRate?: bigint + ): Promise { + try { + const { nativeSegwitPayment, taprootDerivedPublicKey, taprootMultisigPayment } = + await this.createPayment(vault.uuid, attestorGroupPublicKey); + + if ( + taprootMultisigPayment.address === undefined || + nativeSegwitPayment.address === undefined + ) { + throw new Error('Payment Address is undefined'); + } + + const feeRate = + customFeeRate ?? + BigInt(await getFeeRate(this.bitcoinBlockchainFeeRecommendationAPI, feeRateMultiplier)); + + const withdrawalPSBT = await createWithdrawalTransaction( + this.bitcoinBlockchainAPI, + withdrawAmount, + this.bitcoinNetwork, + fundingTransactionID, + taprootMultisigPayment, + nativeSegwitPayment.address, + feeRate, + vault.btcFeeRecipient, + vault.btcRedeemFeeBasisPoints.toBigInt() + ); + + const withdrawalTransactionSigningConfiguration = createBitcoinInputSigningConfiguration( + withdrawalPSBT, + this.walletAccountIndex, + this.bitcoinNetwork + ); + + const formattedWithdrawalPSBT = Psbt.fromBuffer(Buffer.from(withdrawalPSBT), { + network: this.bitcoinNetwork, + }); + + const withdrawalInputByPaymentTypeArray = getInputByPaymentTypeArray( + withdrawalTransactionSigningConfiguration, + formattedWithdrawalPSBT.toBuffer(), + this.bitcoinNetwork + ); + + const taprootInputsToSign = getTaprootInputsToSign(withdrawalInputByPaymentTypeArray); + + await updateTaprootInputs( + taprootInputsToSign, + taprootDerivedPublicKey, + this.masterFingerprint, + formattedWithdrawalPSBT + ); + + return formattedWithdrawalPSBT; + } catch (error: any) { + throw new Error(`Error creating Withdrawal PSBT: ${error}`); + } + } + async signPSBT(psbt: Psbt, transactionType: 'funding' | 'closing'): Promise { try { const { diff --git a/src/dlc-handlers/software-wallet-dlc-handler.ts b/src/dlc-handlers/software-wallet-dlc-handler.ts index af807e8..62a24b8 100644 --- a/src/dlc-handlers/software-wallet-dlc-handler.ts +++ b/src/dlc-handlers/software-wallet-dlc-handler.ts @@ -230,12 +230,17 @@ export class SoftwareWalletDLCHandler { async createWithdrawalPSBT( vault: RawVault, + withdrawAmount: bigint, + attestorGroupPublicKey: string, fundingTransactionID: string, feeRateMultiplier?: number, customFeeRate?: bigint ): Promise { try { - const { nativeSegwitPayment, taprootMultisigPayment } = this.getPayment(); + const { nativeSegwitPayment, taprootMultisigPayment } = await this.createPayments( + vault.uuid, + attestorGroupPublicKey + ); if ( taprootMultisigPayment.address === undefined || @@ -250,7 +255,7 @@ export class SoftwareWalletDLCHandler { const withdrawalTransaction = await createWithdrawalTransaction( this.bitcoinBlockchainAPI, - vault.valueLocked.toBigInt(), + withdrawAmount, this.bitcoinNetwork, fundingTransactionID, taprootMultisigPayment, diff --git a/src/functions/bitcoin/psbt-functions.ts b/src/functions/bitcoin/psbt-functions.ts index 8f3defd..a114e85 100644 --- a/src/functions/bitcoin/psbt-functions.ts +++ b/src/functions/bitcoin/psbt-functions.ts @@ -173,10 +173,15 @@ export async function createWithdrawalTransaction( fundingTransactionID, bitcoinBlockchainURL ); + + console.log('fundingTransaction', fundingTransaction); + const fundingTransactionOutputIndex = fundingTransaction.vout.findIndex( output => output.scriptpubkey_address === multisigTransactionAddress ); + console.log('fundingTransactionOutputIndex', fundingTransactionOutputIndex); + if (fundingTransactionOutputIndex === -1) { throw new Error('Could not find Funding Transaction Output Index'); } @@ -184,37 +189,46 @@ export async function createWithdrawalTransaction( const feeAddress = getFeeRecipientAddressFromPublicKey(feePublicKey, bitcoinNetwork); const feeAmount = getFeeAmount(Number(bitcoinAmount), Number(feeBasisPoints)); + console.log('bitcoinAmount', bitcoinAmount); const inputs = [ { txid: hexToBytes(fundingTransactionID), index: fundingTransactionOutputIndex, witnessUtxo: { - amount: bitcoinAmount, + amount: BigInt(fundingTransaction.vout[fundingTransactionOutputIndex].value), script: multisigTransaction.script, }, ...multisigTransaction, }, ]; + console.log('inputs', inputs); + const outputs = [ { address: feeAddress, amount: BigInt(feeAmount), }, { - address: userNativeSegwitAddress, - amount: BigInt(bitcoinAmount), + address: multisigTransactionAddress, + amount: + BigInt(fundingTransaction.vout[fundingTransactionOutputIndex].value) - + BigInt(bitcoinAmount), }, ]; + console.log('outputs', outputs); + const selected = selectUTXO(inputs, outputs, 'default', { - changeAddress: multisigTransactionAddress, + changeAddress: userNativeSegwitAddress, feePerByte: feeRate, bip69: false, createTx: true, network: bitcoinNetwork, }); + console.log('selected', selected); + const closingTX = selected?.tx; if (!closingTX) throw new Error('Could not create Closing Transaction');