import type { WalletError } from '@meshconnect/uwc-types' import { WalletConnectorError } from '@meshconnect/uwc-types' /** * Extract a clean error message from SDK errors that use multiline format. * TON Connect SDK wraps errors as "[TON_CONNECT_SDK_ERROR] Type\nActual message", * so we return the last line when present. */ export function extractTonSdkErrorMessage(error: unknown): string { const msg = error instanceof Error ? error.message : error && typeof error === 'object' && 'message' in error && typeof (error as { message: unknown }).message === 'string' ? (error as { message: string }).message : '' if (!msg) return '' const lastLine = msg.split('\n').pop() if (lastLine && lastLine !== msg) { return lastLine.trim() } return msg } /** * Parse an error and throw a WalletConnectorError * Detects if the error is a user rejection or an unknown error */ export function parseError(error: unknown): never { // Already-typed connector errors (e.g. the `expired` timeout) must pass // through — re-deriving the type here would downgrade them to 'unknown'. if (error instanceof WalletConnectorError) { throw error } let message: string let isRejected = false // Preserve the numeric provider code so the classifier can place it (e.g. // -32002 "already pending" → provider_error); it is lost at wrap time otherwise. let numericCode: number | undefined // Handle different error formats if (error && typeof error === 'object') { // eslint-disable-next-line @typescript-eslint/no-explicit-any const errorObj = error as any // Read once — a wallet-controlled getter/proxy could yield inconsistent // values or throw on repeated access. const code = errorObj.code if (typeof code === 'number' && Number.isInteger(code)) { numericCode = code } // Check for EIP-1193 error code if (code === 4001 || code === 'ACTION_REJECTED') { isRejected = true } // Extract message if (errorObj.message) { message = errorObj.message } else if (errorObj.error?.message) { message = errorObj.error.message } else { message = String(error) } } else { message = String(error) } // If not already marked as rejected, check message patterns if (!isRejected) { const rejectionPatterns = [ 'user rejected', 'user denied', 'user cancelled', 'user canceled', 'rejected by user', 'denied by user', 'cancelled by user', 'canceled by user', 'user disapproved', 'user declined', 'action_rejected', 'reject request', 'user rejects' ] const lowerMessage = message.toLowerCase() isRejected = rejectionPatterns.some(pattern => lowerMessage.includes(pattern.toLowerCase()) ) } const walletError: WalletError = { type: isRejected ? 'rejected' : 'unknown', message, ...(numericCode !== undefined ? { code: numericCode } : {}) } throw new WalletConnectorError(walletError) }