From d7ca5301ea5dc92415dc8f0d178ca8ad29f950a5 Mon Sep 17 00:00:00 2001 From: victorkirov Date: Wed, 22 Nov 2023 11:43:16 +0200 Subject: [PATCH] fix: Get UTXO ordinal data in batches --- api/ordinals.ts | 42 ++++++++++++++++++++++------------------ api/ordinals/provider.ts | 13 +++++++++++++ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/api/ordinals.ts b/api/ordinals.ts index 0aaa88bc..f228fa1d 100644 --- a/api/ordinals.ts +++ b/api/ordinals.ts @@ -1,5 +1,6 @@ import axios from 'axios'; import BitcoinEsploraApiProvider from '../api/esplora/esploraAPiProvider'; +import XordApiProvider from '../api/ordinals/provider'; import { INSCRIPTION_REQUESTS_SERVICE_URL, ORDINALS_URL, XVERSE_API_BASE_URL, XVERSE_INSCRIBE_URL } from '../constant'; import { Account, @@ -47,28 +48,31 @@ export async function fetchBtcOrdinalsData(btcAddress: string, network: NetworkT const btcClient = new BitcoinEsploraApiProvider({ network, }); - const addressUTXOs = await btcClient.getUnspentUtxos(btcAddress); - const ordinals: BtcOrdinal[] = []; + const xordClient = new XordApiProvider({ + network, + }); - await Promise.all( - addressUTXOs - .filter((utxo) => utxo.status.confirmed) // we can only detect ordinals from confirmed utxos - .map(async (utxo: UTXO) => { - const ordinalContentUrl = `${XVERSE_INSCRIBE_URL(network)}/v1/inscriptions/utxo/${utxo.txid}/${utxo.vout}`; + const [addressUTXOs, inscriptions] = await Promise.all([ + btcClient.getUnspentUtxos(btcAddress), + xordClient.getAllInscriptions(btcAddress), + ]); + const ordinals: BtcOrdinal[] = []; - const ordinalIds = await axios.get(ordinalContentUrl); + const utxoMap = addressUTXOs.reduce((acc, utxo) => { + acc[`${utxo.txid}:${utxo.vout}`] = utxo; + return acc; + }, {} as Record); - if (ordinalIds.data.length > 0) { - ordinalIds.data.forEach((ordinalId) => { - ordinals.push({ - id: ordinalId, - confirmationTime: utxo.status.block_time || 0, - utxo, - }); - }); - } - }), - ); + inscriptions.forEach((inscription) => { + const utxo = utxoMap[inscription.output]; + if (utxo) { + ordinals.push({ + id: inscription.id, + confirmationTime: utxo.status.block_time || 0, + utxo, + }); + } + }); return ordinals.sort(sortOrdinalsByConfirmationTime); } diff --git a/api/ordinals/provider.ts b/api/ordinals/provider.ts index 3b2a346c..e6e3fd93 100644 --- a/api/ordinals/provider.ts +++ b/api/ordinals/provider.ts @@ -111,6 +111,19 @@ export default class OrdinalsApi implements OrdinalsApiProvider { } } + async getAllInscriptions(address: string): Promise { + const firstPage = await this.getInscriptions(address, 0, 100); + const results = [...firstPage.results]; + + // we do this sequentially to avoid rate limiting + while (results.length < firstPage.total) { + const nextPage = await this.getInscriptions(address, results.length, firstPage.limit); + results.push(...nextPage.results); + } + + return results; + } + async getInscriptions(address: string, offset: number, limit: number): Promise { const url = 'inscriptions'; const params = {