Skip to content

Commit

Permalink
refactor: input calc helper methods
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie committed May 13, 2024
1 parent e522113 commit 16a9e6e
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/app/features/psbt-signer/hooks/use-parsed-inputs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function useParsedInputs({ inputs, indexesToSign }: UseParsedInputsArgs)
() =>
inputs.map((input, i) => {
const inputAddress = isDefined(input.index)
? getBitcoinInputAddress(input.index, input, bitcoinNetwork)
? getBitcoinInputAddress(input, bitcoinNetwork)
: '';
const isCurrentAddress =
inputAddress === bitcoinAddressNativeSegwit || inputAddress === bitcoinAddressTaproot;
Expand All @@ -60,7 +60,7 @@ export function useParsedInputs({ inputs, indexesToSign }: UseParsedInputsArgs)
isMutable: canChange,
toSign: toSignAll || toSignIndex,
txid: input.txid ? bytesToHex(input.txid) : '',
value: isDefined(input.index) ? getBitcoinInputValue(input.index, input) : 0,
value: isDefined(input.index) ? getBitcoinInputValue(input) : 0,
};
}),
[
Expand Down
1 change: 0 additions & 1 deletion src/app/store/accounts/blockchain/bitcoin/bitcoin.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ export function useSignLedgerBitcoinTx() {
return [
config,
getInputPaymentType(
inputIndex,
btcSignerPsbtClone.getInput(config.index),
network.chain.bitcoin.bitcoinNetwork
),
Expand Down
39 changes: 21 additions & 18 deletions src/shared/crypto/bitcoin/bitcoin.utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PaymentTypes } from '@btckit/types';
import { PaymentTypes as PaymentType } from '@btckit/types';
import { hexToBytes } from '@noble/hashes/utils';
import { HDKey, Versions } from '@scure/bip32';
import * as btc from '@scure/btc-signer';
Expand All @@ -12,7 +12,7 @@ import { BtcSignerNetwork, getBtcSignerLibNetworkConfigByMode } from './bitcoin.
import { getTaprootPayment } from './p2tr-address-gen';

export interface BitcoinAccount {
type: PaymentTypes;
type: PaymentType;
derivationPath: string;
keychain: HDKey;
accountIndex: number;
Expand Down Expand Up @@ -96,54 +96,58 @@ export function getAddressFromOutScript(script: Uint8Array, bitcoinNetwork: BtcS
}

export function getBitcoinInputAddress(
index: number,
input: btc.TransactionInput,
bitcoinNetwork: BtcSignerNetwork
) {
if (isDefined(input.witnessUtxo))
return getAddressFromOutScript(input.witnessUtxo.script, bitcoinNetwork);
if (isDefined(input.nonWitnessUtxo))
return getAddressFromOutScript(input.nonWitnessUtxo.outputs[index]?.script, bitcoinNetwork);
if (isDefined(input.nonWitnessUtxo) && isDefined(input.index))
return getAddressFromOutScript(
input.nonWitnessUtxo.outputs[input.index]?.script,
bitcoinNetwork
);
return '';
}

export function getBitcoinInputValue(index: number, input: btc.TransactionInput) {
export function getBitcoinInputValue(input: btc.TransactionInput) {
if (isDefined(input.witnessUtxo)) return Number(input.witnessUtxo.amount);
if (isDefined(input.nonWitnessUtxo)) return Number(input.nonWitnessUtxo.outputs[index]?.amount);
if (isDefined(input.nonWitnessUtxo) && isDefined(input.index))
return Number(input.nonWitnessUtxo.outputs[input.index]?.amount);
logger.warn('Unable to find either `witnessUtxo` or `nonWitnessUtxo` in input. Defaulting to 0');
return 0;
}

type BtcSignerLibPaymentTypeIdentifers = 'wpkh' | 'wsh' | 'tr' | 'pkh' | 'sh';
type BtcSignerLibPaymentTypeIdentifer = 'wpkh' | 'wsh' | 'tr' | 'pkh' | 'sh';

const paymentTypeMap: Record<BtcSignerLibPaymentTypeIdentifers, PaymentTypes> = {
const paymentTypeMap: Record<BtcSignerLibPaymentTypeIdentifer, PaymentType> = {
wpkh: 'p2wpkh',
wsh: 'p2wpkh-p2sh',
tr: 'p2tr',
pkh: 'p2pkh',
sh: 'p2sh',
};

function btcSignerLibPaymentTypeToPaymentTypeMap(payment: BtcSignerLibPaymentTypeIdentifers) {
function btcSignerLibPaymentTypeToPaymentTypeMap(payment: BtcSignerLibPaymentTypeIdentifer) {
return paymentTypeMap[payment];
}

function isBtcSignerLibPaymentType(payment: string): payment is BtcSignerLibPaymentTypeIdentifers {
function isBtcSignerLibPaymentType(payment: string): payment is BtcSignerLibPaymentTypeIdentifer {
return payment in paymentTypeMap;
}

function parseKnownPaymentType(payment: BtcSignerLibPaymentTypeIdentifers | PaymentTypes) {
function parseKnownPaymentType(payment: BtcSignerLibPaymentTypeIdentifer | PaymentType) {
return isBtcSignerLibPaymentType(payment)
? btcSignerLibPaymentTypeToPaymentTypeMap(payment)
: payment;
}

type PaymentTypeMap<T> = Record<PaymentTypes, T>;
export function whenPaymentType(mode: PaymentTypes | BtcSignerLibPaymentTypeIdentifers) {
type PaymentTypeMap<T> = Record<PaymentType, T>;
export function whenPaymentType(mode: PaymentType | BtcSignerLibPaymentTypeIdentifer) {
return <T extends unknown>(paymentMap: PaymentTypeMap<T>): T =>
paymentMap[parseKnownPaymentType(mode)];
}

function inferPaymentTypeFromPath(path: string): PaymentTypes {
function inferPaymentTypeFromPath(path: string): PaymentType {
if (path.startsWith('m/84')) return 'p2wpkh';
if (path.startsWith('m/86')) return 'p2tr';
if (path.startsWith('m/44')) return 'p2pkh';
Expand Down Expand Up @@ -260,11 +264,10 @@ export function getPsbtTxOutputs(psbtTx: btc.Transaction) {
}

export function getInputPaymentType(
index: number,
input: btc.TransactionInput,
network: BitcoinNetworkModes
): PaymentTypes {
const address = getBitcoinInputAddress(index, input, getBtcSignerLibNetworkConfigByMode(network));
): PaymentType {
const address = getBitcoinInputAddress(input, getBtcSignerLibNetworkConfigByMode(network));
if (address === '') throw new Error('Input address cannot be empty');
if (address.startsWith('bc1p') || address.startsWith('tb1p') || address.startsWith('bcrt1p'))
return 'p2tr';
Expand Down
2 changes: 1 addition & 1 deletion src/shared/crypto/bitcoin/signer-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function getAssumedZeroIndexSigningConfig({
const input = tx.getInput(inputIndex);

if (isUndefined(input.index)) throw new Error('Input must have an index for payment type');
const paymentType = getInputPaymentType(input.index, input, network);
const paymentType = getInputPaymentType(input, network);

switch (paymentType) {
case 'p2wpkh':
Expand Down

0 comments on commit 16a9e6e

Please sign in to comment.