All files / src/Utxo/BlockfrostUtxoProvider BlockfrostUtxoProvider.ts

71.42% Statements 20/28
33.33% Branches 1/3
69.23% Functions 9/13
76.92% Lines 20/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 6341x 41x 41x         41x   5x         3x 200x 200x 200x     3x       200x                     200x             200x 200x       3x 3x   3x   5x       2x   1x        
import { BlockfrostProvider } from '../../util/BlockfrostProvider/BlockfrostProvider';
import { BlockfrostToCore, blockfrostToProviderError, fetchByAddressSequentially } from '../../util';
import { Cardano, Serialization, UtxoByAddressesArgs, UtxoProvider } from '@cardano-sdk/core';
import { PaginationOptions } from '@blockfrost/blockfrost-js/lib/types';
import { Responses } from '@blockfrost/blockfrost-js';
import { Schemas } from '@blockfrost/blockfrost-js/lib/types/open-api';
 
export class BlockfrostUtxoProvider extends BlockfrostProvider implements UtxoProvider {
  protected async fetchUtxos(addr: Cardano.PaymentAddress, pagination: PaginationOptions): Promise<Cardano.Utxo[]> {
    const utxos: Responses['address_utxo_content'] = (await this.blockfrost.addressesUtxos(
      addr.toString(),
      pagination
    )) as Responses['address_utxo_content'];
 
    const utxoPromises = utxos.map((utxo) =>
      this.fetchDetailsFromCBOR(utxo.tx_hash).then((tx) => {
        const txOut = tx ? tx.body.outputs.find((output) => output.address === utxo.address) : undefined;
        return BlockfrostToCore.addressUtxoContent(addr.toString(), utxo, txOut);
      })
    );
    return Promise.all(utxoPromises);
  }
 
  async fetchCBOR(hash: string): Promise<string> {
    return this.blockfrost
      .instance<Schemas['script_cbor']>(`txs/${hash}/cbor`)
      .then((response) => {
        Iif (response.body.cbor) return response.body.cbor;
        throw new Error('CBOR is null');
      })
      .catch((_error) => {
        throw new Error('CBOR fetch failed');
      });
  }
  protected async fetchDetailsFromCBOR(hash: string) {
    return this.fetchCBOR(hash)
      .then((cbor) => {
        const tx = Serialization.Transaction.fromCbor(Serialization.TxCBOR(cbor)).toCore();
        this.logger.info('Fetched details from CBOR for tx', hash);
        return tx;
      })
      .catch((error) => {
        this.logger.warn('Failed to fetch details from CBOR for tx', hash, error);
        return null;
      });
  }
  public async utxoByAddresses({ addresses }: UtxoByAddressesArgs): Promise<Cardano.Utxo[]> {
    try {
      const utxoResults = await Promise.all(
        addresses.map(async (address) =>
          fetchByAddressSequentially<Cardano.Utxo, Cardano.Utxo>({
            address,
            request: async (addr: Cardano.PaymentAddress, pagination) => await this.fetchUtxos(addr, pagination)
          })
        )
      );
      return utxoResults.flat(1);
    } catch (error) {
      throw blockfrostToProviderError(error);
    }
  }
}