UNPKG

raiden-ts

Version:

Raiden Light Client Typescript/Javascript SDK

205 lines 7.96 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ErrorCodec = exports.assert = exports.RaidenError = exports.commonAndFailTxErrors = exports.commonTxErrors = exports.networkErrors = exports.shouldRetryError = exports.matchError = exports.ErrorCodes = void 0; /* eslint-disable @typescript-eslint/no-explicit-any */ const Either_1 = require("fp-ts/lib/Either"); const function_1 = require("fp-ts/lib/function"); const t = __importStar(require("io-ts")); const findKey_1 = __importDefault(require("lodash/findKey")); const errors_json_1 = __importDefault(require("../errors.json")); exports.ErrorCodes = errors_json_1.default; /** * Matches an error, or creates a matcher for the error * The matcher is curried on the left side, meaning that it'll return a function to check errors * against the provided match or matches if error isn't provided as 2nd parameter. * Matches can be strings (to be checked as substrings of error.message), numbers (to be checked * for equality with error.httpStatus), or an arbitrary mapping of { key: values }, to check * for strict property equality on the error object. * * @param match - Match or array of Matches to check * @param error - Error to check * @returns boolean if 'error' matches 'match' or some 'match', or a matcher function for 'error', * if 2nd param is undefined */ function matchError(match, error) { const _errorMatcher = (match, error) => { let res; if (typeof match === 'string') res = error?.name === match || error?.message?.includes(match); else if (typeof match === 'number') res = error?.httpStatus === match; else res = Object.entries(match).every(([k, v]) => error?.[k] === v); // some errors include a sub-error; match it here as well, if needed if (!res && error && 'error' in error) res = _errorMatcher(match, error.error); return res; }; const errorMatcher = Array.isArray(match) ? (error) => match.some((m) => _errorMatcher(m, error)) : (error) => _errorMatcher(match, error); if (arguments.length < 2) return errorMatcher; else return errorMatcher(error); } exports.matchError = matchError; /** * Creates a function to decide if a given error should be retried or not * * @param opts - Options object * @param opts.maxRetries - maximum number of retries before rejecting * @param opts.onErrors - retry only on these errors * @param opts.neverOnErrors - Never retry on these errors * @param opts.predicate - Retry if this predicate matches * @param opts.stopPredicate - Don't retry if this predicate match * @param opts.log - Log using this function * @returns Function to test if errors should be retried or not */ function shouldRetryError(opts) { let count = -1; const maxRetries = opts.maxRetries ?? 10; return (error) => { count++; let retry = true; if (maxRetries >= 0) retry && (retry = count < maxRetries); if (opts.onErrors) retry && (retry = matchError(opts.onErrors, error)); if (opts.neverOnErrors) retry && (retry = !matchError(opts.neverOnErrors, error)); if (opts.predicate) retry && (retry = !!opts.predicate(error, count)); if (opts.stopPredicate) retry && (retry = !opts.stopPredicate(error, count)); opts.log?.(retry ? `retrying` : 'giving up', { count, maxRetries }, error); return retry; }; } exports.shouldRetryError = shouldRetryError; exports.networkErrors = [ 'invalid response', 'missing response', { code: 'TIMEOUT' }, { code: 'SERVER_ERROR' }, { code: 'NETWORK_ERROR' }, { code: 'ENOTFOUND' }, 429, 500, 502, 503, ]; const txEstimateErrors = [ 'always failing transaction', 'cannot estimate gas', { code: 'UNPREDICTABLE_GAS_LIMIT' }, ]; const txNonceErrors = [ 'replacement fee too low', 'gas price supplied is too low', 'nonce is too low', 'nonce has already been used', 'already known', 'Transaction with the same hash was already imported', ]; const txFailErrors = [ 'execution failed due to an exception', 'transaction failed', 'execution reverted', ]; exports.commonTxErrors = [ ...txEstimateErrors, ...txNonceErrors, ...exports.networkErrors, ]; exports.commonAndFailTxErrors = [...exports.commonTxErrors, ...txFailErrors]; class RaidenError extends Error { constructor(message, details) { super(message); this.details = details; this.name = 'RaidenError'; Object.setPrototypeOf(this, RaidenError.prototype); } get code() { return ((0, findKey_1.default)(exports.ErrorCodes, (message) => message === this.message) ?? 'RDN_GENERAL_ERROR'); } } exports.RaidenError = RaidenError; /** * Type-safe assertion function (TS3.7) * * @param condition - Condition to validate as truthy * @param error - Message, Error, error factory or tuple of RaidenError constructor parameters * to throw if condition is falsy * @param log - Logger to log error to */ function assert(condition, error, log) { if (!condition) { log?.('__assertion failed:', condition, error); throw error instanceof Error ? error : typeof error === 'function' ? error(condition) : Array.isArray(error) ? new RaidenError(...error) : new RaidenError(error ?? exports.ErrorCodes.RDN_ASSERT_ERROR, { condition }); } } exports.assert = assert; const serializedErr = t.intersection([ t.type({ name: t.string }), t.partial({ message: t.string, stack: t.string, details: t.unknown }), ]); /** * Simple Error codec * * This codec doesn't decode to an instance of the exact same error class object, but instead to * a generic Error, but assigning 'name', 'stack' & 'message' properties, more as an informative * object. */ exports.ErrorCodec = new t.Type('Error', // if it quacks like a duck... without relying on instanceof (u) => typeof u === 'object' && !!u && 'message' in u, (u) => (0, function_1.pipe)(serializedErr.decode(u), (0, Either_1.map)((error) => { if ('details' in error) { return Object.assign(new RaidenError(error.message, error.details), { name: error.name, stack: error.stack, }); } else { return Object.assign(new Error(error.message), { name: error.name, stack: error.stack }); } })), (error) => ({ name: error.name, message: error.message, stack: error.stack, ...('details' in error ? { details: error.details } : {}), })); //# sourceMappingURL=error.js.map