|
5 | 5 | BlockfrostToCore, |
6 | 6 | BlockfrostTransactionContent, |
7 | 7 | blockfrostMetadataToTxMetadata, |
| 8 | + blockfrostToProviderError, |
8 | 9 | fetchByAddressSequentially, |
9 | 10 | isBlockfrostNotFoundError |
10 | 11 | } from '../../util'; |
@@ -185,111 +186,128 @@ export class BlockfrostChainHistoryProvider extends BlockfrostProvider implement |
185 | 186 | protected parseValidityInterval = (num: string | null) => Cardano.Slot(Number.parseInt(num || '')) || undefined; |
186 | 187 |
|
187 | 188 | protected async fetchTransaction(hash: Cardano.TransactionId): Promise<Cardano.HydratedTx> { |
188 | | - const utxos: Responses['tx_content_utxo'] = await this.blockfrost.txsUtxos(hash.toString()); |
189 | | - const { inputs, outputs, collaterals } = BlockfrostToCore.transactionUtxos(utxos); |
| 189 | + try { |
| 190 | + const utxos: Responses['tx_content_utxo'] = await this.blockfrost.txsUtxos(hash.toString()); |
| 191 | + const { inputs, outputs, collaterals } = BlockfrostToCore.transactionUtxos(utxos); |
190 | 192 |
|
191 | | - const response = await this.blockfrost.txs(hash.toString()); |
192 | | - const metadata = await this.fetchJsonMetadata(hash); |
193 | | - const certificates = await this.fetchCertificates(response); |
194 | | - const withdrawals = await this.fetchWithdrawals(response); |
195 | | - return { |
196 | | - auxiliaryData: metadata |
197 | | - ? { |
198 | | - blob: metadata |
199 | | - } |
200 | | - : undefined, |
| 193 | + const response = await this.blockfrost.txs(hash.toString()); |
| 194 | + const metadata = await this.fetchJsonMetadata(hash); |
| 195 | + const certificates = await this.fetchCertificates(response); |
| 196 | + const withdrawals = await this.fetchWithdrawals(response); |
| 197 | + return { |
| 198 | + auxiliaryData: metadata |
| 199 | + ? { |
| 200 | + blob: metadata |
| 201 | + } |
| 202 | + : undefined, |
201 | 203 |
|
202 | | - blockHeader: { |
203 | | - blockNo: Cardano.BlockNo(response.block_height), |
204 | | - hash: Cardano.BlockId(response.block), |
205 | | - slot: Cardano.Slot(response.slot) |
206 | | - }, |
207 | | - body: { |
208 | | - certificates, |
209 | | - collaterals, |
210 | | - fee: BigInt(response.fees), |
211 | | - inputs, |
212 | | - mint: this.gatherMintsFromUtxos(response, utxos), |
213 | | - outputs, |
214 | | - validityInterval: { |
215 | | - invalidBefore: this.parseValidityInterval(response.invalid_before), |
216 | | - invalidHereafter: this.parseValidityInterval(response.invalid_hereafter) |
| 204 | + blockHeader: { |
| 205 | + blockNo: Cardano.BlockNo(response.block_height), |
| 206 | + hash: Cardano.BlockId(response.block), |
| 207 | + slot: Cardano.Slot(response.slot) |
217 | 208 | }, |
218 | | - withdrawals |
219 | | - }, |
220 | | - id: hash, |
221 | | - index: response.index, |
222 | | - inputSource: inputs && inputs.length > 0 ? Cardano.InputSource.inputs : Cardano.InputSource.collaterals, |
223 | | - txSize: response.size, |
224 | | - witness: { |
225 | | - redeemers: await this.fetchRedeemers(response), |
226 | | - signatures: new Map() // not available in blockfrost @todo check again |
227 | | - } |
228 | | - }; |
| 209 | + body: { |
| 210 | + certificates, |
| 211 | + collaterals, |
| 212 | + fee: BigInt(response.fees), |
| 213 | + inputs, |
| 214 | + mint: this.gatherMintsFromUtxos(response, utxos), |
| 215 | + outputs, |
| 216 | + validityInterval: { |
| 217 | + invalidBefore: this.parseValidityInterval(response.invalid_before), |
| 218 | + invalidHereafter: this.parseValidityInterval(response.invalid_hereafter) |
| 219 | + }, |
| 220 | + withdrawals |
| 221 | + }, |
| 222 | + id: hash, |
| 223 | + index: response.index, |
| 224 | + inputSource: inputs && inputs.length > 0 ? Cardano.InputSource.inputs : Cardano.InputSource.collaterals, |
| 225 | + txSize: response.size, |
| 226 | + witness: { |
| 227 | + redeemers: await this.fetchRedeemers(response), |
| 228 | + signatures: new Map() // not available in blockfrost @todo check again |
| 229 | + } |
| 230 | + }; |
| 231 | + } catch (error) { |
| 232 | + throw blockfrostToProviderError(error); |
| 233 | + } |
229 | 234 | } |
230 | 235 |
|
231 | 236 | public async blocksByHashes({ ids }: BlocksByIdsArgs): Promise<Cardano.ExtendedBlockInfo[]> { |
232 | | - const responses = await Promise.all(ids.map((id) => this.blockfrost.blocks(id.toString()))); |
233 | | - return responses.map((response) => { |
234 | | - if (!response.epoch || !response.epoch_slot || !response.height || !response.slot || !response.block_vrf) { |
235 | | - throw new ProviderError(ProviderFailure.Unknown, null, 'Queried unsupported block'); |
236 | | - } |
237 | | - return { |
238 | | - confirmations: response.confirmations, |
239 | | - date: new Date(response.time * 1000), |
240 | | - epoch: Cardano.EpochNo(response.epoch), |
241 | | - epochSlot: response.epoch_slot, |
242 | | - fees: BigInt(response.fees || '0'), |
243 | | - header: { |
244 | | - blockNo: Cardano.BlockNo(response.height), |
245 | | - hash: Cardano.BlockId(response.hash), |
246 | | - slot: Cardano.Slot(response.slot) |
247 | | - }, |
248 | | - nextBlock: response.next_block ? Cardano.BlockId(response.next_block) : undefined, |
249 | | - previousBlock: response.previous_block ? Cardano.BlockId(response.previous_block) : undefined, |
250 | | - size: Cardano.BlockSize(response.size), |
251 | | - slotLeader: Cardano.SlotLeader(response.slot_leader), |
252 | | - totalOutput: BigInt(response.output || '0'), |
253 | | - txCount: response.tx_count, |
254 | | - vrf: Cardano.VrfVkBech32(response.block_vrf) |
255 | | - }; |
256 | | - }); |
| 237 | + try { |
| 238 | + const responses = await Promise.all(ids.map((id) => this.blockfrost.blocks(id.toString()))); |
| 239 | + return responses.map((response) => { |
| 240 | + if (!response.epoch || !response.epoch_slot || !response.height || !response.slot || !response.block_vrf) { |
| 241 | + throw new ProviderError(ProviderFailure.Unknown, null, 'Queried unsupported block'); |
| 242 | + } |
| 243 | + return { |
| 244 | + confirmations: response.confirmations, |
| 245 | + date: new Date(response.time * 1000), |
| 246 | + epoch: Cardano.EpochNo(response.epoch), |
| 247 | + epochSlot: response.epoch_slot, |
| 248 | + fees: BigInt(response.fees || '0'), |
| 249 | + header: { |
| 250 | + blockNo: Cardano.BlockNo(response.height), |
| 251 | + hash: Cardano.BlockId(response.hash), |
| 252 | + slot: Cardano.Slot(response.slot) |
| 253 | + }, |
| 254 | + nextBlock: response.next_block ? Cardano.BlockId(response.next_block) : undefined, |
| 255 | + previousBlock: response.previous_block ? Cardano.BlockId(response.previous_block) : undefined, |
| 256 | + size: Cardano.BlockSize(response.size), |
| 257 | + slotLeader: Cardano.SlotLeader(response.slot_leader), |
| 258 | + totalOutput: BigInt(response.output || '0'), |
| 259 | + txCount: response.tx_count, |
| 260 | + vrf: Cardano.VrfVkBech32(response.block_vrf) |
| 261 | + }; |
| 262 | + }); |
| 263 | + } catch (error) { |
| 264 | + throw blockfrostToProviderError(error); |
| 265 | + } |
257 | 266 | } |
258 | 267 |
|
259 | 268 | public async transactionsByHashes({ ids }: TransactionsByIdsArgs): Promise<Cardano.HydratedTx[]> { |
260 | | - return Promise.all(ids.map((id) => this.fetchTransaction(id))); |
| 269 | + try { |
| 270 | + return Promise.all(ids.map((id) => this.fetchTransaction(id))); |
| 271 | + } catch (error) { |
| 272 | + throw blockfrostToProviderError(error); |
| 273 | + } |
261 | 274 | } |
262 | 275 |
|
263 | 276 | public async transactionsByAddresses({ |
264 | 277 | addresses, |
265 | 278 | blockRange |
266 | 279 | }: TransactionsByAddressesArgs): Promise<Paginated<Cardano.HydratedTx>> { |
267 | | - const addressTransactions = await Promise.all( |
268 | | - addresses.map(async (address) => |
269 | | - fetchByAddressSequentially< |
270 | | - { tx_hash: string; tx_index: number; block_height: number }, |
271 | | - BlockfrostTransactionContent |
272 | | - >({ |
273 | | - address, |
274 | | - haveEnoughItems: blockRange?.lowerBound |
275 | | - ? (transactions) => |
276 | | - transactions.length > 0 && transactions[transactions.length - 1].block_height < blockRange!.lowerBound! |
277 | | - : undefined, |
278 | | - request: (addr: Cardano.PaymentAddress, paginationOptions) => |
279 | | - this.blockfrost.addressesTransactions(addr.toString(), paginationOptions) |
280 | | - }) |
281 | | - ) |
282 | | - ); |
| 280 | + try { |
| 281 | + const addressTransactions = await Promise.all( |
| 282 | + addresses.map(async (address) => |
| 283 | + fetchByAddressSequentially< |
| 284 | + { tx_hash: string; tx_index: number; block_height: number }, |
| 285 | + BlockfrostTransactionContent |
| 286 | + >({ |
| 287 | + address, |
| 288 | + haveEnoughItems: blockRange?.lowerBound |
| 289 | + ? (transactions) => |
| 290 | + transactions.length > 0 && |
| 291 | + transactions[transactions.length - 1].block_height < blockRange!.lowerBound! |
| 292 | + : undefined, |
| 293 | + request: (addr: Cardano.PaymentAddress, paginationOptions) => |
| 294 | + this.blockfrost.addressesTransactions(addr.toString(), paginationOptions) |
| 295 | + }) |
| 296 | + ) |
| 297 | + ); |
283 | 298 |
|
284 | | - const allTransactions = addressTransactions |
285 | | - .flat(1) |
286 | | - .sort((a, b) => b.block_height - a.block_height || b.tx_index - a.tx_index); |
287 | | - const addressTransactionsSinceBlock = blockRange?.lowerBound |
288 | | - ? allTransactions.filter(({ block_height }) => block_height >= blockRange!.lowerBound!) |
289 | | - : allTransactions; |
290 | | - const ids = addressTransactionsSinceBlock.map(({ tx_hash }) => Cardano.TransactionId(tx_hash)); |
291 | | - const pageResults = await this.transactionsByHashes({ ids }); |
| 299 | + const allTransactions = addressTransactions |
| 300 | + .flat(1) |
| 301 | + .sort((a, b) => b.block_height - a.block_height || b.tx_index - a.tx_index); |
| 302 | + const addressTransactionsSinceBlock = blockRange?.lowerBound |
| 303 | + ? allTransactions.filter(({ block_height }) => block_height >= blockRange!.lowerBound!) |
| 304 | + : allTransactions; |
| 305 | + const ids = addressTransactionsSinceBlock.map(({ tx_hash }) => Cardano.TransactionId(tx_hash)); |
| 306 | + const pageResults = await this.transactionsByHashes({ ids }); |
292 | 307 |
|
293 | | - return { pageResults, totalResultCount: allTransactions.length }; |
| 308 | + return { pageResults, totalResultCount: allTransactions.length }; |
| 309 | + } catch (error) { |
| 310 | + throw blockfrostToProviderError(error); |
| 311 | + } |
294 | 312 | } |
295 | 313 | } |
0 commit comments