UNPKG

rosetta-sdk-typescript

Version:

Typescript SDK to create and interact with Rosetta API implementations.

136 lines (124 loc) 4.07 kB
import fetch from 'node-fetch'; import { AccountApi, AccountApiInterface, BlockApi, BlockApiInterface, CallApi, CallApiInterface, Configuration, ConstructionApi, ConstructionApiInterface, EventsApi, EventsApiInterface, MempoolApi, MempoolApiInterface, Middleware, ModelErrorFromJSON, NetworkApi, NetworkApiInterface, ResponseContext, SearchApi, SearchApiInterface, } from 'rosetta-sdk-typescript'; /** * Params used to create a client factory. */ interface RestClientFactoryParams { /** * The rest url of the Rosetta service. E.g: http://localhost:8080/ */ url: string; /** * Optional fetch api. */ fetchApi?: unknown; /** * Middleware for pre/post request customizations. */ middleware?: Middleware[]; } /** * When the rest client raises an error, the error will be wrapped in this exception. */ export class RestClientCallError extends Error { /** * * @param message - the message resolved from the error response * @param statusCode - the response status code * @param statusMessage - the response status message * @param body - the body as string */ constructor(message: string, public readonly statusCode: number, public readonly statusMessage: string, public readonly body: string) { super(message); } } /** * Basic implementation of the exception handling middleware. */ export const exceptionHandlingMiddleware: Middleware = { async post(context: ResponseContext): Promise<Response | void> { const response = context.response; if (response.status >= 200 && response.status < 300) { return response; } throw await RosettaRestClientFactory.getErrorFromFetchResponse(response); }, }; /** * Main class used to create Rosetta rest clients. * * These rest client would most likely be used for Rosetta e2e testing as this sdk brings server side dependencies (e.g. express) you may not want in a Rosetta client. * */ export class RosettaRestClientFactory { private readonly configuration: Configuration; constructor(configs: RestClientFactoryParams) { const fetchApi = configs.fetchApi || (typeof window !== 'undefined' && window.fetch.bind(window)) || fetch; this.configuration = new Configuration({ basePath: configs.url, fetchApi: fetchApi, middleware: configs.middleware || [exceptionHandlingMiddleware], }); } public static async getErrorFromFetchResponse(error: Response): Promise<RestClientCallError> { const statusCode = error?.status || 0; const statusMessage = (error?.statusText || 'Unknown Error').toString(); const body = await error.text(); const getMessage = () => { const defaultMessage = `${statusCode} - ${statusMessage}`; try { const modelError = ModelErrorFromJSON(JSON.parse(body)); return [modelError.code, modelError.message, modelError.description].join(' - '); } catch (e) { return defaultMessage; } }; const message = getMessage(); return new RestClientCallError(message, statusCode, statusMessage, body); } account(): AccountApiInterface { return new AccountApi(this.configuration); } block(): BlockApiInterface { return new BlockApi(this.configuration); } events(): EventsApiInterface { return new EventsApi(this.configuration); } construction(): ConstructionApiInterface { return new ConstructionApi(this.configuration); } call(): CallApiInterface { return new CallApi(this.configuration); } mempool(): MempoolApiInterface { return new MempoolApi(this.configuration); } network(): NetworkApiInterface { return new NetworkApi(this.configuration); } search(): SearchApiInterface { return new SearchApi(this.configuration); } }