All files / src/util/BlockfrostProvider BlockfrostClientFactory.ts

59.45% Statements 22/37
64.28% Branches 9/14
50% Functions 2/4
57.14% Lines 16/28

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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94  50x 50x           50x                   50x 6x     4x 1x         1x       3x 1x   2x     1x           1x               50x                                                                           50x 3x    
import { AvailableNetworks } from '../../Program';
import { BlockFrostAPI } from '@blockfrost/blockfrost-js';
import {
  BlockfrostClient,
  DEFAULT_BLOCKFROST_API_VERSION,
  DEFAULT_BLOCKFROST_RATE_LIMIT_CONFIG,
  DEFAULT_BLOCKFROST_URLS
} from '@cardano-sdk/cardano-services-client';
import Bottleneck from 'bottleneck';
 
let blockfrostApi: BlockFrostAPI | undefined;
let blockfrostClient: BlockfrostClient | undefined;
 
/**
 * Gets the singleton blockfrost API instance.
 *
 * @returns The blockfrost API instance, this function always returns the same instance.
 */
export const getBlockfrostApi = () => {
  if (blockfrostApi !== undefined) return blockfrostApi;
 
  // custom hosted instance
  if (process.env.BLOCKFROST_CUSTOM_BACKEND_URL && process.env.BLOCKFROST_CUSTOM_BACKEND_URL !== '') {
    blockfrostApi = new BlockFrostAPI({
      customBackend: process.env.BLOCKFROST_CUSTOM_BACKEND_URL,
      rateLimiter: false
    });
 
    return blockfrostApi;
  }
 
  // instance hosted by Blockfrost
  if (process.env.BLOCKFROST_API_KEY === undefined || process.env.BLOCKFROST_API_KEY === '')
    throw new Error('BLOCKFROST_API_KEY or BLOCKFROST_CUSTOM_BACKEND_URL environment variable is required');
 
  if (process.env.NETWORK === undefined) throw new Error('NETWORK environment variable is required');
 
  // network is not mandatory, we keep it for safety.
  blockfrostApi = new BlockFrostAPI({
    network: process.env.NETWORK as AvailableNetworks,
    projectId: process.env.BLOCKFROST_API_KEY,
    rateLimiter: false
  });
 
  return blockfrostApi;
};
 
/**
 * Gets the singleton blockfrost API instance.
 *
 * @returns The blockfrost API instance, this function always returns the same instance.
 */
export const getBlockfrostClient = (): BlockfrostClient => {
  Iif (blockfrostClient !== undefined) return blockfrostClient;
 
  // custom hosted instance
  Iif (process.env.BLOCKFROST_CUSTOM_BACKEND_URL) {
    blockfrostClient = new BlockfrostClient(
      { apiVersion: DEFAULT_BLOCKFROST_API_VERSION, baseUrl: process.env.BLOCKFROST_CUSTOM_BACKEND_URL },
      { rateLimiter: { schedule: (task) => task() } }
    );
 
    return blockfrostClient;
  }
 
  // instance hosted by Blockfrost
  Iif (!process.env.BLOCKFROST_API_KEY)
    throw new Error('BLOCKFROST_API_KEY or BLOCKFROST_CUSTOM_BACKEND_URL environment variable is required');
 
  Iif (!process.env.NETWORK) throw new Error('NETWORK environment variable is required');
  const baseUrl = DEFAULT_BLOCKFROST_URLS[process.env.NETWORK as keyof typeof DEFAULT_BLOCKFROST_URLS];
  Iif (!baseUrl) throw new Error(`Unsupported NETWORK for blockfrost: ${process.env.NETWORK}`);
 
  // network is not mandatory, we keep it for safety.
  blockfrostClient = new BlockfrostClient(
    { apiVersion: DEFAULT_BLOCKFROST_API_VERSION, baseUrl, projectId: process.env.BLOCKFROST_API_KEY },
    {
      rateLimiter: new Bottleneck({
        reservoir: DEFAULT_BLOCKFROST_RATE_LIMIT_CONFIG.size,
        reservoirIncreaseAmount: DEFAULT_BLOCKFROST_RATE_LIMIT_CONFIG.increaseAmount,
        reservoirIncreaseInterval: DEFAULT_BLOCKFROST_RATE_LIMIT_CONFIG.increaseInterval,
        reservoirIncreaseMaximum: DEFAULT_BLOCKFROST_RATE_LIMIT_CONFIG.size
      })
    }
  );
 
  return blockfrostClient;
};
 
// for testing purpose
export const clearBlockfrostApi = () => {
  if (blockfrostApi !== undefined) blockfrostApi = undefined;
};