All files / src/TxSubmitProvider TxSubmitApiProvider.ts

16.66% Statements 5/30
0% Branches 0/10
0% Functions 0/3
17.24% Lines 5/29

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 8417x                 17x 17x 17x                       17x                                                                                                                        
import {
  Cardano,
  ProviderError,
  ProviderFailure,
  Serialization,
  SubmitTxArgs,
  TxSubmitProvider
} from '@cardano-sdk/core';
import { Logger } from 'ts-log';
import { hexStringToBuffer } from '@cardano-sdk/util';
import { mapCardanoTxSubmitError } from './cardanoTxSubmitErrorMapper';
import axios, { AxiosAdapter, AxiosInstance } from 'axios';
 
export type TxSubmitApiProviderProperties = {
  baseUrl: URL;
  path?: string;
};
 
export type TxSubmitApiProviderDependencies = {
  logger: Logger;
  adapter?: AxiosAdapter;
};
 
export class TxSubmitApiProvider implements TxSubmitProvider {
  #axios: AxiosInstance;
  #healthStatus = true;
  #logger: Logger;
  #path: string;
  #adapter?: AxiosAdapter;
 
  constructor(
    { baseUrl, path = '/api/submit/tx' }: TxSubmitApiProviderProperties,
    { logger, adapter }: TxSubmitApiProviderDependencies
  ) {
    this.#axios = axios.create({ baseURL: baseUrl.origin });
    this.#logger = logger;
    this.#path = path;
    this.#adapter = adapter;
  }
 
  async submitTx({ signedTransaction }: SubmitTxArgs) {
    let txId: Cardano.TransactionId | undefined;
 
    try {
      txId = Serialization.Transaction.fromCbor(signedTransaction).getId();
 
      this.#logger.debug(`Submitting tx ${txId} ...`);
 
      await this.#axios({
        adapter: this.#adapter,
        data: hexStringToBuffer(signedTransaction),
        headers: { 'Content-Type': 'application/cbor' },
        method: 'post',
        url: this.#path
      });
 
      this.#healthStatus = true;
      this.#logger.debug(`Tx ${txId} submitted`);
    } catch (error) {
      this.#healthStatus = false;
      this.#logger.error(`Tx ${txId} submission error`);
      this.#logger.error(error);
 
      Iif (axios.isAxiosError(error) && error.response) {
        const { data, status } = error.response;
 
        Iif (typeof status === 'number' && status >= 400 && status < 500) this.#healthStatus = true;
 
        throw new ProviderError(
          ProviderFailure.BadRequest,
          mapCardanoTxSubmitError(data),
          typeof data === 'string' ? data : JSON.stringify(data)
        );
      }
 
      throw new ProviderError(ProviderFailure.Unknown, error, 'submitting tx');
    }
  }
 
  healthCheck() {
    return Promise.resolve({ ok: this.#healthStatus });
  }
}