From e7053c07b0f9bb93578e8c90e9cd0818c5dc7e42 Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Fri, 4 Aug 2023 10:13:43 +0500 Subject: [PATCH 1/4] added functions for sign ordinal tx and get fee --- transactions/btc.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/transactions/btc.ts b/transactions/btc.ts index 282ae42e..dd7eaa46 100644 --- a/transactions/btc.ts +++ b/transactions/btc.ts @@ -6,7 +6,7 @@ import * as btc from '@scure/btc-signer'; import BigNumber from 'bignumber.js'; import BitcoinEsploraApiProvider from '../api/esplora/esploraAPiProvider'; import { fetchBtcFeeRate } from '../api/xverse'; -import { BtcFeeResponse, ErrorCodes, NetworkType, ResponseError, UTXO } from '../types'; +import { BtcFeeResponse, ErrorCodes, Inscription, NetworkType, ResponseError, UTXO } from '../types'; import { getBtcPrivateKey, getBtcTaprootPrivateKey } from '../wallet'; import { BitcoinNetwork, getBtcNetwork } from './btcNetwork'; @@ -404,6 +404,27 @@ export function filterUtxos(allUtxos: UTXO[], filterUtxoSet: UTXO[]) { (utxo) => !filterUtxoSet.some((filterUtxo) => utxo.txid === filterUtxo.txid && utxo.vout === filterUtxo.vout), ); } +export async function getBtcFeesForOrdinalTransaction( + recipientAddress: string, + btcAddress: string, + ordinalsAddress: string, + network: NetworkType, + ordinal: Inscription, + isRecover?: boolean, + feeMode?: string, + feeRateInput?: string, +) { + const btcClient = new BitcoinEsploraApiProvider({ + network, + }); + const address = isRecover ? btcAddress : ordinalsAddress; + const addressUtxos = await btcClient.getUnspentUtxos(address); + const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); + if (!ordUtxo) { + throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; + } + return getBtcFeesForOrdinalSend(recipientAddress, ordUtxo!, btcAddress, network, addressUtxos, feeMode, feeRateInput); +} // Used to calculate fees for setting low/high fee settings // Should replace this function @@ -662,6 +683,38 @@ export async function signBtcTransaction( } } +export async function signOrdinalTransaction( + recipientAddress: string, + btcAddress: string, + ordinalsAddress: string, + accountIndex: number, + seedPhrase: string, + network: NetworkType, + ordinal: Inscription, + fee?: BigNumber, + isRecover?: boolean, +): Promise { + const btcClient = new BitcoinEsploraApiProvider({ + network, + }); + const address = isRecover ? btcAddress : ordinalsAddress; + const addressUtxos = await btcClient.getUnspentUtxos(address); + const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); + if (!ordUtxo) { + throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; + } + return signOrdinalSendTransaction( + recipientAddress, + ordUtxo, + btcAddress, + accountIndex, + seedPhrase, + network, + addressUtxos, + fee, + ); +} + export async function signOrdinalSendTransaction( recipientAddress: string, ordinalUtxo: UTXO, From 9b32ed0ade7f114b0ecb94af3f61af423f8d491c Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Fri, 4 Aug 2023 10:28:42 +0500 Subject: [PATCH 2/4] fix test --- transactions/btc.ts | 107 ++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/transactions/btc.ts b/transactions/btc.ts index dd7eaa46..edc7b567 100644 --- a/transactions/btc.ts +++ b/transactions/btc.ts @@ -404,27 +404,6 @@ export function filterUtxos(allUtxos: UTXO[], filterUtxoSet: UTXO[]) { (utxo) => !filterUtxoSet.some((filterUtxo) => utxo.txid === filterUtxo.txid && utxo.vout === filterUtxo.vout), ); } -export async function getBtcFeesForOrdinalTransaction( - recipientAddress: string, - btcAddress: string, - ordinalsAddress: string, - network: NetworkType, - ordinal: Inscription, - isRecover?: boolean, - feeMode?: string, - feeRateInput?: string, -) { - const btcClient = new BitcoinEsploraApiProvider({ - network, - }); - const address = isRecover ? btcAddress : ordinalsAddress; - const addressUtxos = await btcClient.getUnspentUtxos(address); - const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); - if (!ordUtxo) { - throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; - } - return getBtcFeesForOrdinalSend(recipientAddress, ordUtxo!, btcAddress, network, addressUtxos, feeMode, feeRateInput); -} // Used to calculate fees for setting low/high fee settings // Should replace this function @@ -490,6 +469,28 @@ export async function getBtcFeesForOrdinalSend( } } +export async function getBtcFeesForOrdinalTransaction( + recipientAddress: string, + btcAddress: string, + ordinalsAddress: string, + network: NetworkType, + ordinal: Inscription, + isRecover?: boolean, + feeMode?: string, + feeRateInput?: string, +) { + const btcClient = new BitcoinEsploraApiProvider({ + network, + }); + const address = isRecover ? btcAddress : ordinalsAddress; + const addressUtxos = await btcClient.getUnspentUtxos(address); + const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); + if (!ordUtxo) { + throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; + } + return getBtcFeesForOrdinalSend(recipientAddress, ordUtxo!, btcAddress, network, addressUtxos, feeMode, feeRateInput); +} + // Used to calculate fees for setting low/high fee settings // Should replace this function export async function getBtcFeesForNonOrdinalBtcSend( @@ -683,38 +684,6 @@ export async function signBtcTransaction( } } -export async function signOrdinalTransaction( - recipientAddress: string, - btcAddress: string, - ordinalsAddress: string, - accountIndex: number, - seedPhrase: string, - network: NetworkType, - ordinal: Inscription, - fee?: BigNumber, - isRecover?: boolean, -): Promise { - const btcClient = new BitcoinEsploraApiProvider({ - network, - }); - const address = isRecover ? btcAddress : ordinalsAddress; - const addressUtxos = await btcClient.getUnspentUtxos(address); - const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); - if (!ordUtxo) { - throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; - } - return signOrdinalSendTransaction( - recipientAddress, - ordUtxo, - btcAddress, - accountIndex, - seedPhrase, - network, - addressUtxos, - fee, - ); -} - export async function signOrdinalSendTransaction( recipientAddress: string, ordinalUtxo: UTXO, @@ -842,6 +811,38 @@ export async function signOrdinalSendTransaction( return signedBtcTx; } +export async function signOrdinalTransaction( + recipientAddress: string, + btcAddress: string, + ordinalsAddress: string, + accountIndex: number, + seedPhrase: string, + network: NetworkType, + ordinal: Inscription, + fee?: BigNumber, + isRecover?: boolean, +): Promise { + const btcClient = new BitcoinEsploraApiProvider({ + network, + }); + const address = isRecover ? btcAddress : ordinalsAddress; + const addressUtxos = await btcClient.getUnspentUtxos(address); + const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); + if (!ordUtxo) { + throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; + } + return signOrdinalSendTransaction( + recipientAddress, + ordUtxo, + btcAddress, + accountIndex, + seedPhrase, + network, + addressUtxos, + fee, + ); +} + export async function signNonOrdinalBtcSendTransaction( recipientAddress: string, nonOrdinalUtxos: Array, From 920fda7a7f5d249f5aa18038a0f6492583e3e5de Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Fri, 4 Aug 2023 10:37:13 +0500 Subject: [PATCH 3/4] eslist disable for throwing error --- transactions/btc.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/transactions/btc.ts b/transactions/btc.ts index edc7b567..e422b2db 100644 --- a/transactions/btc.ts +++ b/transactions/btc.ts @@ -486,6 +486,8 @@ export async function getBtcFeesForOrdinalTransaction( const addressUtxos = await btcClient.getUnspentUtxos(address); const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); if (!ordUtxo) { + // TODO: Throw error and not just the code + // eslint-disable-next-line @typescript-eslint/no-throw-literal throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; } return getBtcFeesForOrdinalSend(recipientAddress, ordUtxo!, btcAddress, network, addressUtxos, feeMode, feeRateInput); @@ -829,6 +831,8 @@ export async function signOrdinalTransaction( const addressUtxos = await btcClient.getUnspentUtxos(address); const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); if (!ordUtxo) { + // TODO: Throw error and not just the code + // eslint-disable-next-line @typescript-eslint/no-throw-literal throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; } return signOrdinalSendTransaction( From 1768cf32827aefdce4925afc890d5b3649a9fbff Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Mon, 7 Aug 2023 11:32:19 +0500 Subject: [PATCH 4/4] named params, added function to get correct utxo --- transactions/btc.ts | 57 ++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/transactions/btc.ts b/transactions/btc.ts index e422b2db..f65e52b0 100644 --- a/transactions/btc.ts +++ b/transactions/btc.ts @@ -405,6 +405,11 @@ export function filterUtxos(allUtxos: UTXO[], filterUtxoSet: UTXO[]) { ); } +// get correct ordinal utxo to send from address utxos +export function getOrdinalUtxo(addressUtxos: UTXO[], ordinal: Inscription): UTXO | undefined { + return addressUtxos.find((utxo) => `${utxo.txid}:${utxo.vout}` === ordinal.output); +} + // Used to calculate fees for setting low/high fee settings // Should replace this function export async function getBtcFeesForOrdinalSend( @@ -469,28 +474,30 @@ export async function getBtcFeesForOrdinalSend( } } -export async function getBtcFeesForOrdinalTransaction( - recipientAddress: string, - btcAddress: string, - ordinalsAddress: string, - network: NetworkType, - ordinal: Inscription, - isRecover?: boolean, - feeMode?: string, - feeRateInput?: string, -) { +export async function getBtcFeesForOrdinalTransaction(feeParams: { + recipientAddress: string; + btcAddress: string; + ordinalsAddress: string; + network: NetworkType; + ordinal: Inscription; + isRecover?: boolean; + feeMode?: string; + feeRateInput?: string; +}): Promise<{ fee: BigNumber; selectedFeeRate?: BigNumber }> { + const { recipientAddress, btcAddress, ordinalsAddress, network, ordinal, isRecover, feeMode, feeRateInput } = + feeParams; const btcClient = new BitcoinEsploraApiProvider({ network, }); const address = isRecover ? btcAddress : ordinalsAddress; const addressUtxos = await btcClient.getUnspentUtxos(address); - const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); + const ordUtxo = getOrdinalUtxo(addressUtxos, ordinal); if (!ordUtxo) { // TODO: Throw error and not just the code // eslint-disable-next-line @typescript-eslint/no-throw-literal throw new ResponseError(ErrorCodes.OrdinalUtxoNotfound).statusCode; } - return getBtcFeesForOrdinalSend(recipientAddress, ordUtxo!, btcAddress, network, addressUtxos, feeMode, feeRateInput); + return getBtcFeesForOrdinalSend(recipientAddress, ordUtxo, btcAddress, network, addressUtxos, feeMode, feeRateInput); } // Used to calculate fees for setting low/high fee settings @@ -813,23 +820,25 @@ export async function signOrdinalSendTransaction( return signedBtcTx; } -export async function signOrdinalTransaction( - recipientAddress: string, - btcAddress: string, - ordinalsAddress: string, - accountIndex: number, - seedPhrase: string, - network: NetworkType, - ordinal: Inscription, - fee?: BigNumber, - isRecover?: boolean, -): Promise { +export async function signOrdinalTransaction(ordinalTxParams: { + recipientAddress: string; + btcAddress: string; + ordinalsAddress: string; + accountIndex: number; + seedPhrase: string; + network: NetworkType; + ordinal: Inscription; + fee?: BigNumber; + isRecover?: boolean; +}): Promise { + const { recipientAddress, btcAddress, ordinalsAddress, accountIndex, seedPhrase, network, ordinal, fee, isRecover } = + ordinalTxParams; const btcClient = new BitcoinEsploraApiProvider({ network, }); const address = isRecover ? btcAddress : ordinalsAddress; const addressUtxos = await btcClient.getUnspentUtxos(address); - const ordUtxo = addressUtxos.find((utx) => `${utx.txid}:${utx.vout}` === ordinal.output); + const ordUtxo = getOrdinalUtxo(addressUtxos, ordinal); if (!ordUtxo) { // TODO: Throw error and not just the code // eslint-disable-next-line @typescript-eslint/no-throw-literal