UNPKG

@bsv/wallet-toolbox

Version:

BRC100 conforming wallet, wallet storage and wallet signer components

120 lines (110 loc) 3.79 kB
import { ErrorCodeString10To40Bytes, ErrorDescriptionString20To200Bytes, WalletErrorObject } from '@bsv/sdk' /** * Derived class constructors should use the derived class name as the value for `name`, * and an internationalizable constant string for `message`. * * If a derived class intends to wrap another WalletError, the public property should * be named `walletError` and will be recovered by `fromUnknown`. * * Optionaly, the derived class `message` can include template parameters passed in * to the constructor. See WERR_MISSING_PARAMETER for an example. * * To avoid derived class name colisions, packages should include a package specific * identifier after the 'WERR_' prefix. e.g. 'WERR_FOO_' as the prefix for Foo package error * classes. */ export class WalletError extends Error implements WalletErrorObject { // Facilitates detection of Error objects from non-error return values. isError: true = true constructor( name: string, message: string, stack?: string, public details?: Record<string, string> ) { super(message) this.name = name if (stack) this.stack = stack } /** * Error class compatible accessor for `code`. */ get code(): ErrorCodeString10To40Bytes { return this.name } set code(v: ErrorCodeString10To40Bytes) { this.name = v } /** * Error class compatible accessor for `description`. */ get description(): ErrorDescriptionString20To200Bytes { return this.message } set description(v: ErrorDescriptionString20To200Bytes) { this.message = v } /** * Recovers all public fields from WalletError derived error classes and relevant Error derived errors. * */ static fromUnknown(err: unknown): WalletError { if (err instanceof WalletError) return err let name = 'WERR_UNKNOWN' let message = '' let stack: string | undefined const details: Record<string, string> = {} if (err !== null && typeof err === 'object') { if (err['name'] === 'Error' || err['name'] === 'FetchError') name = err['code'] || err['status'] || 'WERR_UNKNOWN' else name = err['name'] || err['code'] || err['status'] || 'WERR_UNKNOWN' if (typeof name !== 'string') name = 'WERR_UNKNOWN' message = err['message'] || err['description'] || '' if (typeof message !== 'string') message = 'WERR_UNKNOWN' if (typeof err['stack'] === 'string') stack = err['stack'] if (typeof err['sql'] === 'string') details.sql = err['sql'] if (typeof err['sqlMessage'] === 'string') details.sqlMessage = err['sqlMessage'] } const e = new WalletError(name, message, stack, Object.keys(details).length > 0 ? details : undefined) if (err !== null && typeof err === 'object') { for (const [key, value] of Object.entries(err)) { if (key !== 'walletError' && typeof value !== 'string' && typeof value !== 'number' && !Array.isArray(value)) continue switch (key) { case 'walletError': e[key] = WalletError.fromUnknown(value) break case 'status': break case 'name': break case 'code': break case 'message': break case 'description': break case 'stack': break case 'sql': break case 'sqlMessage': break default: e[key] = value break } } } return e } /** * @returns standard HTTP error status object with status property set to 'error'. */ asStatus(): { status: string; code: string; description: string } { return { status: 'error', code: this.name, description: this.message } } }