diff --git a/src/app/query/bitcoin/bitcoin-client.ts b/src/app/query/bitcoin/bitcoin-client.ts index 6ba5937d9b4..44796947f62 100644 --- a/src/app/query/bitcoin/bitcoin-client.ts +++ b/src/app/query/bitcoin/bitcoin-client.ts @@ -54,12 +54,12 @@ interface BestinslotInscription { byte_size: number; } -export interface BestinslotInscriptionByIdResponse { +interface BestinslotInscriptionByIdResponse { data: BestinslotInscription; block_height: number; } -export interface BestinslotInscriptionsByTxIdResponse { +interface BestinslotInscriptionsByTxIdResponse { data: { inscription_id: string }[]; blockHeight: number; } diff --git a/src/app/query/bitcoin/transaction/use-check-utxos.ts b/src/app/query/bitcoin/transaction/use-check-utxos.ts index 1d83fe71346..71fe959a921 100644 --- a/src/app/query/bitcoin/transaction/use-check-utxos.ts +++ b/src/app/query/bitcoin/transaction/use-check-utxos.ts @@ -10,10 +10,7 @@ import { useAnalytics } from '@app/common/hooks/analytics/use-analytics'; import { useBitcoinClient } from '@app/store/common/api-clients.hooks'; import { useCurrentNetworkState } from '@app/store/networks/networks.hooks'; -import type { - BestinslotInscriptionByIdResponse, - BestinslotInscriptionsByTxIdResponse, -} from '../bitcoin-client'; +import type { BitcoinClient } from '../bitcoin-client'; import { getNumberOfInscriptionOnUtxoUsingOrdinalsCom } from '../ordinals/inscriptions.query'; class PreventTransactionError extends Error { @@ -45,27 +42,29 @@ export function filterOutIntentionalUtxoSpend({ interface CheckInscribedUtxosByBestinslotArgs { inputs: btc.TransactionInput[]; txids: string[]; - getInscriptionsByTransactionId(id: string): Promise; - getInscriptionById(id: string): Promise; + client: BitcoinClient; } async function checkInscribedUtxosByBestinslot({ inputs, txids, - getInscriptionsByTransactionId, - getInscriptionById, + client, }: CheckInscribedUtxosByBestinslotArgs): Promise { /** * @description Get the list of inscriptions moving on a transaction * @see https://docs.bestinslot.xyz/reference/api-reference/ordinals-and-brc-20-and-bitmap-v3-api-mainnet+testnet/inscriptions */ - const inscriptionIdsList = await Promise.all(txids.map(id => getInscriptionsByTransactionId(id))); + const inscriptionIdsList = await Promise.all( + txids.map(id => client.BestinslotApi.getInscriptionsByTransactionId(id)) + ); const inscriptionIds = inscriptionIdsList.flatMap(inscription => inscription.data.map(data => data.inscription_id) ); - const inscriptionsList = await Promise.all(inscriptionIds.map(id => getInscriptionById(id))); + const inscriptionsList = await Promise.all( + inscriptionIds.map(id => client.BestinslotApi.getInscriptionById(id)) + ); const hasInscribedUtxos = inscriptionsList.some(resp => { return inputs.some(input => { @@ -147,8 +146,7 @@ export function useCheckUnspendableUtxos(blockTxAction?: () => void) { const hasInscribedUtxo = await checkInscribedUtxosByBestinslot({ inputs, txids, - getInscriptionsByTransactionId: client.BestinslotApi.getInscriptionsByTransactionId, - getInscriptionById: client.BestinslotApi.getInscriptionById, + client, }); if (hasInscribedUtxo) { diff --git a/tests/specs/send/send-btc.spec.ts b/tests/specs/send/send-btc.spec.ts index 4ef10d57b09..4e40a7371b4 100644 --- a/tests/specs/send/send-btc.spec.ts +++ b/tests/specs/send/send-btc.spec.ts @@ -100,9 +100,65 @@ test.describe('send btc', () => { await sendPage.clickInfoCardButton(); - const isErrorPageVisible = await sendPage.broadcastErrorTitle.isVisible(); + await test.expect(sendPage.broadcastErrorTitle).toBeVisible(); + }); + + test('that fallbacks to other api provider if main fails', async ({ sendPage }) => { + let output = ''; + let id = ''; + let index = ''; + + await sendPage.page.route('**/ordinals-explorer.generative.xyz/**', async route => { + return route.fulfill({ + status: 500, + contentType: 'text/html', + body: mockOrdinalsComApiHtmlResponse, + }); + }); + + sendPage.page.on('request', async request => { + if (request.url().includes('ordinals-explorer.generative.xyz')) { + const url = request.url(); + output = url.split('/').pop() || ''; + id = output.split(':')[0]; + index = output.split(':')[1]; + } + }); + + await sendPage.page.route( + '**/leatherapi.bestinslot.xyz/v3/inscription/in_transaction**', + async route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + data: [{ txid: id, output, index, satpoint: output }], + }), + }); + } + ); + + await sendPage.page.route( + '**/leatherapi.bestinslot.xyz/v3/inscription/single_info_id**', + async route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + data: { txid: id, output, index, satpoint: output }, + }), + }); + } + ); + await sendPage.amountInput.fill('0.00006'); + await sendPage.recipientInput.fill(TEST_TESTNET_ACCOUNT_2_BTC_ADDRESS); + + await sendPage.previewSendTxButton.click(); + await sendPage.feesListItem.filter({ hasText: BtcFeeType.High }).click(); + + await sendPage.clickInfoCardButton(); - test.expect(isErrorPageVisible).toBeTruthy(); + await test.expect(sendPage.broadcastErrorTitle).toBeVisible(); }); }); });