Skip to content

Commit

Permalink
feat(utxo-lib): parse basic info from the psbt
Browse files Browse the repository at this point in the history
TICKET: BTC-637
  • Loading branch information
davidkaplanbitgo committed Nov 29, 2023
1 parent 7be0817 commit 385e594
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
37 changes: 36 additions & 1 deletion modules/utxo-lib/src/bitgo/wallet/Psbt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { UtxoTransaction } from '../UtxoTransaction';
import { createOutputScript2of3, getLeafHash, scriptTypeForChain, toXOnlyPublicKey } from '../outputScripts';
import { DerivedWalletKeys, RootWalletKeys } from './WalletKeys';
import { toPrevOutputWithPrevTx } from '../Unspent';
import { createPsbtFromHex, createPsbtFromTransaction } from '../transaction';
import { createPsbtFromHex, createPsbtFromTransaction, createTransactionFromBuffer } from '../transaction';
import { isWalletUnspent, WalletUnspent } from './Unspent';

import {
Expand Down Expand Up @@ -584,3 +584,38 @@ export function deleteWitnessUtxoForNonSegwitInputs(psbt: UtxoPsbt): void {
}
});
}

export function getTransactionInfoFromPsbt(psbt: UtxoPsbt): {
inputCount: number;
outputCount: number;
inputAmount: bigint;
outputAmount: bigint;
fee: bigint;
} {
const inputCount = psbt.data.inputs.length;
const outputCount = psbt.data.outputs.length;
const txInputs = psbt.txInputs;
const txOutputs = psbt.txOutputs;
const inputAmount = psbt.data.inputs.reduce((acc, input, inputIndex) => {
if (input.witnessUtxo) {
return acc + BigInt(input.witnessUtxo.value);
} else if (input.nonWitnessUtxo) {
const tx = createTransactionFromBuffer(input.nonWitnessUtxo, psbt.network, { amountType: 'bigint' });
return acc + tx.outs[txInputs[inputIndex].index].value;
} else {
throw new Error('missing witnessUtxo and nonWitnessUtxo');
}
}, BigInt(0));
const outputAmount = psbt.data.outputs.reduce(
(acc, output, outputIndex) => acc + txOutputs[outputIndex].value,
BigInt(0)
);
const fee = inputAmount - outputAmount;
return {
inputCount,
outputCount,
inputAmount,
outputAmount,
fee,
};
}
14 changes: 13 additions & 1 deletion modules/utxo-lib/test/bitgo/psbt/Psbt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import {
deleteWitnessUtxoForNonSegwitInputs,
getPsbtInputScriptType,
withUnsafeNonSegwit,
getTransactionInfoFromPsbt,
WalletUnspent,
} from '../../../src/bitgo';
import {
createOutputScript2of3,
Expand Down Expand Up @@ -876,8 +878,9 @@ function testUtxoPsbt(coinNetwork: Network) {
describe(`Testing UtxoPsbt (de)serialization for ${getNetworkName(coinNetwork)} network`, function () {
let psbt: UtxoPsbt;
let psbtHex: string;
let unspents: (WalletUnspent<bigint> | Unspent<bigint>)[];
before(async function () {
const unspents = mockUnspents(rootWalletKeys, ['p2sh'], BigInt('10000000000000'), coinNetwork);
unspents = mockUnspents(rootWalletKeys, ['p2sh'], BigInt('10000000000000'), coinNetwork);
const txBuilderParams = {
signer: 'user',
cosigner: 'bitgo',
Expand Down Expand Up @@ -905,6 +908,15 @@ function testUtxoPsbt(coinNetwork: Network) {
assert.deepStrictEqual(createPsbtFromHex(psbtHex, coinNetwork, false).toBuffer(), psbt.toBuffer());
});

it('should be able to get transaction info from psbt', function () {
const txInfo = getTransactionInfoFromPsbt(psbt);
assert.strictEqual(txInfo.fee, FEE);
assert.strictEqual(txInfo.inputCount, unspents.length);
assert.strictEqual(txInfo.inputAmount, BigInt('10000000000000') * BigInt(unspents.length));
assert.strictEqual(txInfo.outputAmount, BigInt('10000000000000') * BigInt(unspents.length) - FEE);
assert.strictEqual(txInfo.outputCount, psbt.data.outputs.length);
});

function deserializeBip32PathsCorrectly(bip32PathsAbsolute: boolean): void {
function checkDerivationPrefix(bip32Derivation: { path: string }): void {
const path = bip32Derivation.path.split('/');
Expand Down

0 comments on commit 385e594

Please sign in to comment.