Skip to content

Commit

Permalink
feat: add user input finalization function
Browse files Browse the repository at this point in the history
  • Loading branch information
Polybius93 committed Jun 28, 2024
1 parent ccdfded commit e8f044d
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 29 deletions.
6 changes: 4 additions & 2 deletions src/dlc-handlers/private-key-dlc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
createTaprootMultisigPayment,
deriveUnhardenedKeyPairFromRootPrivateKey,
deriveUnhardenedPublicKey,
finalizeUserInputs,
getBalance,
getFeeRate,
getUnspendableKeyCommittedToUUID,
Expand Down Expand Up @@ -263,7 +264,7 @@ export class PrivateKeyDLCHandler {
}
}

signPSBT(psbt: Transaction, transactionType: 'funding' | 'deposit' | 'closing'): Transaction {
signPSBT(psbt: Transaction, transactionType: 'funding' | 'deposit' | 'withdraw'): Transaction {
switch (transactionType) {
case 'funding':
psbt.sign(this.getPrivateKey('p2wpkh'));
Expand All @@ -272,8 +273,9 @@ export class PrivateKeyDLCHandler {
case 'deposit':
psbt.sign(this.getPrivateKey('p2tr'));
psbt.sign(this.getPrivateKey('p2wpkh'));
finalizeUserInputs(psbt, this.getPayment().nativeSegwitPayment);
break;
case 'closing':
case 'withdraw':
psbt.sign(this.getPrivateKey('p2tr'));
break;
default:
Expand Down
2 changes: 0 additions & 2 deletions src/dlc-handlers/software-wallet-dlc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@ export class SoftwareWalletDLCHandler {
customFeeRate ??
BigInt(await getFeeRate(this.bitcoinBlockchainFeeRecommendationAPI, feeRateMultiplier));

console.log('vault', vault);

const withdrawalTransaction = await createWithdrawalTransaction(
this.bitcoinBlockchainAPI,
withdrawAmount,
Expand Down
23 changes: 23 additions & 0 deletions src/functions/bitcoin/bitcoin-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,29 @@ export function validateScript(script: Uint8Array, outputScript: Uint8Array): bo
);
}

export function finalizeUserInputs(
transaction: Transaction,
userPayment: P2TROut | P2Ret
): Transaction {
const userPaymentScript = userPayment.script;
createRangeFromLength(transaction.inputsLength).forEach(index => {
const inputScript = transaction.getInput(index).witnessUtxo?.script;

if (!inputScript) {
throw new Error('Could not get Input Script');
}

if (
inputScript.length === userPaymentScript.length &&
inputScript.every((value, index) => value === userPaymentScript[index])
) {
transaction.finalizeIdx(index);
}
});

return transaction;
}

/**
* Converts an ECDSA Public Key to a Schnorr Public Key.
* @param publicKey - The ECDSA Public Key.
Expand Down
3 changes: 2 additions & 1 deletion src/functions/bitcoin/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getFeeAmount } from '../bitcoin/bitcoin-functions.js';
import { finalizeUserInputs, getFeeAmount } from '../bitcoin/bitcoin-functions.js';
import {
broadcastTransaction,
fetchBitcoinBlockchainBlockHeight,
Expand All @@ -16,6 +16,7 @@ export {
broadcastTransaction,
fetchBitcoinBlockchainBlockHeight,
fetchBitcoinTransaction,
finalizeUserInputs,
getFeeAmount,
getBalance,
};
45 changes: 23 additions & 22 deletions src/functions/bitcoin/psbt-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,13 @@ export async function createFundingTransaction(
network: bitcoinNetwork,
});

const fundingTX = selected?.tx;
if (!selected) {
throw new Error(
'Failed to select Inputs for the Funding Transaction. Ensure sufficient funds are available.'
);
}

const fundingTX = selected.tx;

if (!fundingTX) throw new Error('Could not create Funding Transaction');

Expand Down Expand Up @@ -127,8 +133,6 @@ export async function createDepositTransaction(

const userUTXOs = await getUTXOs(depositPayment, bitcoinBlockchainURL);

console.log('userUTXOs', userUTXOs);

const additionalDepositOutputs = [
{
address: feeAddress,
Expand All @@ -140,8 +144,6 @@ export async function createDepositTransaction(
},
];

console.log('additionalDepositOutputs', additionalDepositOutputs);

const additionalDepositSelected = selectUTXO(userUTXOs, additionalDepositOutputs, 'default', {
changeAddress: depositPaymentAddress,
feePerByte: feeRate,
Expand All @@ -150,8 +152,6 @@ export async function createDepositTransaction(
network: bitcoinNetwork,
});

console.log('additionalDepositSelected', additionalDepositSelected);

if (!additionalDepositSelected) {
throw new Error(
'Failed to select Inputs for the Additional Deposit Transaction. Ensure sufficient funds are available.'
Expand All @@ -168,20 +168,17 @@ export async function createDepositTransaction(
...multisigPayment,
};

const depositInputPromises = additionalDepositSelected.inputs.map(async input => {
const txID = input.txid;
if (!txID) {
throw new Error('Could not get Transaction ID from Input');
}
const utxo = userUTXOs.find((utxo: any) => utxo.txid === txID && utxo.index === input.index);
console.log('utxo', utxo);
if (utxo) {
return utxo;
}
});
const depositInputPromises = additionalDepositSelected.inputs
.map(async input => {
const txID = input.txid;
if (!txID) {
throw new Error('Could not get Transaction ID from Input');
}
return userUTXOs.find((utxo: any) => utxo.txid === txID && utxo.index === input.index);
})
.filter(utxo => utxo !== undefined);

const depositInputs = await Promise.all(depositInputPromises);
console.log('depositInputs', depositInputs);
depositInputs.push(vaultInput);

const depositOutputs = [
Expand All @@ -203,8 +200,6 @@ export async function createDepositTransaction(
network: bitcoinNetwork,
});

console.log('depositSelected', depositSelected);

if (!depositSelected) {
throw new Error(
'Failed to select Inputs for the Deposit Transaction. Ensure sufficient funds are available.'
Expand Down Expand Up @@ -316,7 +311,13 @@ export async function createWithdrawalTransaction(
network: bitcoinNetwork,
});

const withdrawTX = selected?.tx;
if (!selected) {
throw new Error(
'Failed to select Inputs for the Withdrawal Transaction. Ensure sufficient funds are available.'
);
}

const withdrawTX = selected.tx;

if (!withdrawTX) throw new Error('Could not create Withdrawal Transaction');

Expand Down
2 changes: 2 additions & 0 deletions tests/mocks/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ export const TEST_VAULT: RawVault = {
protocolContract: '0x6e692DB944162f8b4250aA25eCEe80608457D7a7',
timestamp: BigNumber.from('0x665da025'),
valueLocked: BigNumber.from('0x0f4240'),
valueMinted: BigNumber.from('0x0f4240'),
creator: '0x0DD4f29E21F10cb2E485cf9bDAb9F2dD1f240Bfa',
status: 0,
fundingTxId: '',
closingTxId: '',
withdrawTxId: '',
btcFeeRecipient: '031131cd88bcea8c1d84da8e034bb24c2f6e748c571922dc363e7e088f5df0436c',
btcMintFeeBasisPoints: BigNumber.from('0x64'),
btcRedeemFeeBasisPoints: BigNumber.from('0x64'),
Expand Down
2 changes: 0 additions & 2 deletions tests/unit/sign-transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ describe('Create and Sign Vault related Transactions', () => {
let dlcHandler: PrivateKeyDLCHandler;
let fundingTransaction: Transaction;
let signedFundingTransaction: Transaction;
let closingTransaction: Transaction;
let partiallySignedClosingTransaction: Transaction;

it('should initialize a Private Key DLC Handler', async () => {
dlcHandler = new PrivateKeyDLCHandler(
Expand Down

0 comments on commit e8f044d

Please sign in to comment.