UNPKG

@anuragchvn-blip/mandatekit

Version:

Production-ready Web3 autopay SDK for crypto-based recurring payments using EIP-712 mandates

191 lines 6.83 kB
/** * Custom error classes for MandateKit SDK * Provides descriptive, actionable error messages for common failure scenarios * @module errors */ /** * Base error class for all MandateKit errors */ export class MandateKitError extends Error { constructor(message, code, details) { super(message); this.name = 'MandateKitError'; this.code = code; this.details = details; // Maintains proper stack trace for where error was thrown if (typeof Error.captureStackTrace === 'function') { Error.captureStackTrace(this, this.constructor); } } } /** * Thrown when a signature is invalid or cannot be verified */ export class InvalidSignatureError extends MandateKitError { constructor(message = 'Invalid signature: signature verification failed', details) { super(message, 'INVALID_SIGNATURE', details); this.name = 'InvalidSignatureError'; } } /** * Thrown when a mandate has expired based on validBefore timestamp */ export class ExpiredMandateError extends MandateKitError { constructor(validBefore, currentTime = Math.floor(Date.now() / 1000), details) { const message = `Mandate expired: valid until ${new Date(validBefore * 1000).toISOString()}, current time is ${new Date(currentTime * 1000).toISOString()}`; super(message, 'MANDATE_EXPIRED', { validBefore, currentTime, ...details }); this.name = 'ExpiredMandateError'; } } /** * Thrown when attempting to use a mandate before its validAfter timestamp */ export class MandateNotYetValidError extends MandateKitError { constructor(validAfter, currentTime = Math.floor(Date.now() / 1000), details) { const message = `Mandate not yet valid: valid after ${new Date(validAfter * 1000).toISOString()}, current time is ${new Date(currentTime * 1000).toISOString()}`; super(message, 'MANDATE_NOT_YET_VALID', { validAfter, currentTime, ...details }); this.name = 'MandateNotYetValidError'; } } /** * Thrown when cadence rules are violated (e.g., executing too frequently) */ export class CadenceViolationError extends MandateKitError { constructor(message, nextAllowedExecution, details) { super(message, 'CADENCE_VIOLATION', { nextAllowedExecution, ...details }); this.name = 'CadenceViolationError'; } } /** * Thrown when a nonce has already been used (replay protection) */ export class NonceAlreadyUsedError extends MandateKitError { constructor(nonce, address, details) { const message = `Nonce ${nonce.toString()} has already been used by address ${address}. Use a fresh nonce to prevent replay attacks.`; super(message, 'NONCE_ALREADY_USED', { nonce: nonce.toString(), address, ...details }); this.name = 'NonceAlreadyUsedError'; } } /** * Thrown when maximum payment count has been reached */ export class MaxPaymentsReachedError extends MandateKitError { constructor(maxPayments, currentCount, details) { const message = `Maximum payment count reached: ${currentCount} of ${maxPayments} payments have been executed`; super(message, 'MAX_PAYMENTS_REACHED', { maxPayments, currentCount, ...details }); this.name = 'MaxPaymentsReachedError'; } } /** * Thrown when mandate validation fails */ export class ValidationError extends MandateKitError { constructor(message, field, details) { super(`Validation error${field ? ` for field '${field}'` : ''}: ${message}`, 'VALIDATION_ERROR', { field, ...details }); this.name = 'ValidationError'; } } /** * Thrown when a contract interaction fails */ export class ContractError extends MandateKitError { constructor(message, contractAddress, details) { super(`Contract error${contractAddress ? ` at ${contractAddress}` : ''}: ${message}`, 'CONTRACT_ERROR', { contractAddress, ...details }); this.name = 'ContractError'; } } /** * Thrown when insufficient token balance or allowance */ export class InsufficientBalanceError extends MandateKitError { constructor(required, available, tokenAddress, details) { const message = `Insufficient balance: required ${required.toString()}, available ${available.toString()} for token ${tokenAddress}`; super(message, 'INSUFFICIENT_BALANCE', { required: required.toString(), available: available.toString(), tokenAddress, ...details, }); this.name = 'InsufficientBalanceError'; } } /** * Thrown when there's an issue with the relayer */ export class RelayerError extends MandateKitError { constructor(message, details) { super(`Relayer error: ${message}`, 'RELAYER_ERROR', details); this.name = 'RelayerError'; } } /** * Thrown when network or RPC issues occur */ export class NetworkError extends MandateKitError { constructor(message, chainId, details) { super(`Network error${chainId ? ` on chain ${chainId}` : ''}: ${message}`, 'NETWORK_ERROR', { chainId, ...details, }); this.name = 'NetworkError'; } } /** * Thrown when trying to execute a payment too early */ export class ExecutionTooEarlyError extends MandateKitError { constructor(nextExecutionTime, currentTime = Math.floor(Date.now() / 1000), details) { const waitSeconds = nextExecutionTime - currentTime; const message = `Execution too early: next payment scheduled for ${new Date(nextExecutionTime * 1000).toISOString()} (in ${waitSeconds} seconds)`; super(message, 'EXECUTION_TOO_EARLY', { nextExecutionTime, currentTime, waitSeconds, ...details, }); this.name = 'ExecutionTooEarlyError'; } } /** * Helper function to check if an error is a MandateKit error */ export function isMandateKitError(error) { return error instanceof MandateKitError; } /** * Helper function to get error code from any error */ export function getErrorCode(error) { if (isMandateKitError(error)) { return error.code; } if (error instanceof Error) { return 'UNKNOWN_ERROR'; } return 'UNEXPECTED_ERROR'; } /** * Helper function to format error for API responses */ export function formatErrorResponse(error) { if (isMandateKitError(error)) { return { code: error.code, message: error.message, details: error.details, }; } if (error instanceof Error) { return { code: 'UNKNOWN_ERROR', message: error.message, details: { stack: error.stack }, }; } return { code: 'UNEXPECTED_ERROR', message: 'An unexpected error occurred', details: error, }; } //# sourceMappingURL=index.js.map