From ff865aa965cfe784f53bb485b228888915add659 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 13:39:31 -0300 Subject: [PATCH 01/26] chore: add new RailgunContractError class to separate different kind of errors --- src/utils/error.ts | 48 ++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/utils/error.ts b/src/utils/error.ts index 957a88c..a818d4c 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -2,6 +2,16 @@ import { isDefined } from './util'; const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; +class RailgunContractError extends Error { + originalError: Error; + + constructor(message: string, originalError: Error) { + super(message); + this.name = 'RailgunContractError'; + this.originalError = originalError; + } +} + const validAscii = (str: string) => { return str.replace( // eslint-disable-next-line no-useless-escape @@ -10,6 +20,8 @@ const validAscii = (str: string) => { ); }; + + export const sanitizeError = (cause: Error): Error => { if (isDefined(cause) && cause.message) { const lowercaseMsg = cause.message.toLowerCase(); @@ -84,56 +96,54 @@ export const sanitizeError = (cause: Error): Error => { // Custom RAILGUN contract error messages if (lowercaseMsg.includes('railgunsmartwallet')) { if (lowercaseMsg.includes('invalid nft note value')) { - return new Error('RailgunSmartWallet: Invalid NFT Note Value.', { - cause, - }); + return new RailgunContractError('RailgunSmartWallet: Invalid NFT Note Value.', cause); } if (lowercaseMsg.includes('unsupported token')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Unsupported Token. This token cannot interact with the RAILGUN contract.', - { cause }, + cause, ); } if (lowercaseMsg.includes('invalid note value')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Invalid Note Value. Please submit transaction with a corrected amount.', - { cause }, + cause, ); } if (lowercaseMsg.includes('invalid adapt contract as sender')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Invalid Adapt Contract as Sender. Please update your frontend to current Adapt module versions.', - { cause }, + cause, ); } if (lowercaseMsg.includes('invalid merkle root')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Invalid Merkle Root. Please sync your balances and try again.', - { cause }, + cause, ); } if (lowercaseMsg.includes('note already spent')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Note Already Spent. Please sync your balances and try again.', - { cause }, + cause, ); } if (lowercaseMsg.includes('invalid note ciphertext array length')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Invalid Note Ciphertext Array Length. Please sync balances and re-prove your transaction.', - { cause }, + cause, ); } if (lowercaseMsg.includes('invalid withdraw note')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Invalid Unshield Note. Please sync balances and re-prove your transaction.', - { cause }, + cause, ); } if (lowercaseMsg.includes('invalid snark proof')) { - return new Error( + return new RailgunContractError( 'RailgunSmartWallet: Invalid Snark Proof. Please re-prove your transaction.', - { cause }, + cause, ); } } From 553e4eabe8abd54b54a15a8fb51fc9d75da1d4ad Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 13:44:59 -0300 Subject: [PATCH 02/26] chore: add customError class --- src/utils/errors/constants.ts | 0 src/utils/{ => errors}/error.ts | 15 ++++++++++++--- src/utils/errors/types.ts | 0 src/utils/index.ts | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 src/utils/errors/constants.ts rename src/utils/{ => errors}/error.ts (95%) create mode 100644 src/utils/errors/types.ts diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/error.ts b/src/utils/errors/error.ts similarity index 95% rename from src/utils/error.ts rename to src/utils/errors/error.ts index a818d4c..0d2c865 100644 --- a/src/utils/error.ts +++ b/src/utils/errors/error.ts @@ -1,7 +1,18 @@ -import { isDefined } from './util'; +import { isDefined } from '../util'; const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; + +class CustomError extends Error { + originalError: Error; + + constructor(message: string, originalError: Error) { + super(message); + this.name = 'CustomError'; + this.originalError = originalError; + } +} + class RailgunContractError extends Error { originalError: Error; @@ -20,8 +31,6 @@ const validAscii = (str: string) => { ); }; - - export const sanitizeError = (cause: Error): Error => { if (isDefined(cause) && cause.message) { const lowercaseMsg = cause.message.toLowerCase(); diff --git a/src/utils/errors/types.ts b/src/utils/errors/types.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/index.ts b/src/utils/index.ts index 8a9c0c5..3aa4c67 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,7 +2,7 @@ export * from './artifact-v2'; export * from './available-rpc'; export * from './compare'; export * from './fallback-provider'; -export * from './error'; +export * from './errors/error'; export * from './format'; export * from './gas'; export * from './network'; From 04faafc0368c8c44479a36bbbf8c7c4a0534a6fe Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 14:07:07 -0300 Subject: [PATCH 03/26] chore: add constants.ts to segregate errors acording to categories, match them 1:1 to existing errros --- src/utils/errors/constants.ts | 88 +++++++++++++++++++++++++++++++++++ src/utils/errors/error.ts | 57 +++++++++++++---------- 2 files changed, 120 insertions(+), 25 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index e69de29..e7426c6 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -0,0 +1,88 @@ +import { isDefined } from '../util'; + +type ErrorDefinition = { + matches: string[]; + message: string; +}; + +type CustomErrorMapping = { + [key: string]: ErrorDefinition; +}; + +const CUSTOM_ERRORS: CustomErrorMapping = { + CONNECTION_ERROR: { + matches: ['quorum', 'could not connect to'], + message: 'Could not connect.' + }, + RPC_ERROR: { + matches: ['call revert exception', 'missing revert data', 'error while dialing dial tcp'], + message: 'Failed to connect to RPC.' + }, + KNOWN_TRANSACTION: { + matches: ['already known'], + message: 'Transaction successful but ethers request for TXID failed.' + }, + LOW_REPLACEMENT_FEE: { + matches: ['replacement fee too low'], + message: 'Nonce is used in a pending transaction, and replacement fee is too low. Please increase your network fee to replace the pending transaction.' + }, + LOW_GAS: { + matches: ['intrinsic gas too low'], + message: 'Gas price rejected. Please select a higher gas price or resubmit.' + }, + LOW_GAS_RESUBMIT: { + matches: ['intrinsic gas too low'], + message: 'Gas price rejected. Please select a higher gas price and resubmit.' + }, // @@TODO: Find a better suited message for this + INSUFFICIENT_GAS: { + matches: ['insufficient funds for intrinsic'], + message: 'Insufficient gas to process transaction.' + }, + NONCE_USED: { + matches: ['nonce has already been used'], + message: 'Nonce already used: the transaction was already completed.' + }, + LOW_PRIVATE_BALANCE: { + matches: ['spendable private balance too low', 'broadcaster fee'], + message: 'Private balance too low to pay broadcaster fee.' + } +}; + +const RAILGUN_ERRORS: CustomErrorMapping = { + INVALID_NFT_NOTE: { + matches: ['invalid nft note value'], + message: 'RailgunSmartWallet: Invalid NFT Note Value.' + }, + UNSUPPORTED_TOKEN: { + matches: ['unsupported token'], + message: 'RailgunSmartWallet: Unsupported Token. This token cannot interact with the RAILGUN contract.' + }, + INVALID_NOTE_VALUE: { + matches: ['invalid note value'], + message: 'RailgunSmartWallet: Invalid Note Value. Please submit transaction with a corrected amount.' + }, + INVALID_ADAPT_CONTRACT_SENDER: { + matches: ['invalid adapt contract as sender'], + message: 'RailgunSmartWallet: Invalid Adapt Contract as Sender. Please update your frontend to current Adapt module versions.' + }, + INVALID_MERKLE_ROOT: { + matches: ['invalid merkle root'], + message: 'RailgunSmartWallet: Invalid Merkle Root. Please sync your balances and try again.' + }, + NOTE_SPENT: { + matches: ['note already spent'], + message: 'RailgunSmartWallet: Note Already Spent. Please sync your balances and try again.' + }, + INVALID_NOTE_CIPHERTEXT_ARRAY_LENGTH: { + matches: ['invalid note ciphertext array length'], + message: 'RailgunSmartWallet: Invalid Note Ciphertext Array Length. Please sync balances and re-prove your transaction.' + }, + INVALID_WITHDRAW_NOTE: { + matches: ['invalid withdraw note'], + message: 'RailgunSmartWallet: Invalid Unshield Note. Please sync balances and re-prove your transaction.' + }, + INVALID_SNARK_PROOF: { + matches: ['invalid snark proof'], + message: 'RailgunSmartWallet: Invalid Snark Proof. Please re-prove your transaction.' + } +}; \ No newline at end of file diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 0d2c865..9130c2c 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -31,66 +31,73 @@ const validAscii = (str: string) => { ); }; +const isRailgunError = (cause: Error): boolean => cause.message.toLowerCase().includes('railgunsmartwallet') + export const sanitizeError = (cause: Error): Error => { if (isDefined(cause) && cause.message) { const lowercaseMsg = cause.message.toLowerCase(); + + if (isRailgunError(cause)) { + return cause; + } + if ( - lowercaseMsg.includes('quorum') || - lowercaseMsg.includes('could not connect to') + lowercaseMsg.includes('quorum') || // Connection error + lowercaseMsg.includes('could not connect to') // Connection error ) { return new Error('Could not connect.', { cause }); } - if (lowercaseMsg.includes('call revert exception')) { - return new Error('Failed to connect to RPC.', { cause }); + if (lowercaseMsg.includes('call revert exception')) { + return new Error('Failed to connect to RPC.', { cause }); // RPC_ERROR } if (lowercaseMsg.includes('already known')) { return new Error( 'Transaction successful but ethers request for TXID failed.', - { cause }, + { cause }, // KNOWN_TRANSACTION ); } if (lowercaseMsg.includes('missing revert data')) { - return new Error('RPC connection error.', { cause }); + return new Error('RPC connection error.', { cause }); // RPC_ERROR } if ( lowercaseMsg.includes( 'transaction may fail or may require manual gas limit', ) ) { - return new Error('Unknown error. Transaction failed.', { cause }); + return new Error('Unknown error. Transaction failed.', { cause }); // @@TODO: Replace or categorize better } if (lowercaseMsg.includes('replacement fee too low')) { return new Error( 'Nonce is used in a pending transaction, and replacement fee is too low. Please increase your network fee to replace the pending transaction.', - { cause }, + { cause }, // LOW_REPLACEMENT_FEE ); } if (lowercaseMsg.includes('intrinsic gas too low')) { return new Error( 'Gas price rejected. Please select a higher gas price or resubmit.', - { cause }, + { cause }, // LOW_GAS ); } if (lowercaseMsg.includes('transaction underpriced')) { return new Error( 'Gas fee too low. Please select a higher gas price and resubmit.', - { cause }, + { cause }, // LOW_GAS_RESUBMIT ); } if (lowercaseMsg.includes('insufficient funds for intrinsic')) { - return new Error('Insufficient gas to process transaction.', { cause }); + return new Error('Insufficient gas to process transaction.', { cause }); // INSUFFICIENT_GAS } if (lowercaseMsg.includes('nonce has already been used')) { return new Error( // Do not change 'Nonce already used' string of Error message. 'Nonce already used: the transaction was already completed.', - { cause }, + { cause }, // NONCE_USED ); } if (lowercaseMsg.includes('error while dialing dial tcp')) { return new Error( 'Error while connecting to RPC provider. Please try again.', - { cause }, + { cause }, // RPC_ERROR ); } if ( @@ -98,58 +105,58 @@ export const sanitizeError = (cause: Error): Error => { lowercaseMsg.includes('broadcaster fee') ) { return new Error('Private balance too low to pay broadcaster fee.', { - cause, + cause, // LOW_PRIVATE_BALANCE }); } // Custom RAILGUN contract error messages if (lowercaseMsg.includes('railgunsmartwallet')) { - if (lowercaseMsg.includes('invalid nft note value')) { - return new RailgunContractError('RailgunSmartWallet: Invalid NFT Note Value.', cause); + if (lowercaseMsg.includes('invalid nft note value')) { // INVALID_NFT_NOTE + return new RailgunContractError('RailgunSmartWallet: Invalid NFT Note Value.', cause); // INVALID_NFT_NOTE } if (lowercaseMsg.includes('unsupported token')) { return new RailgunContractError( - 'RailgunSmartWallet: Unsupported Token. This token cannot interact with the RAILGUN contract.', + 'RailgunSmartWallet: Unsupported Token. This token cannot interact with the RAILGUN contract.',// UNSUPPORTED_TOKEN cause, ); } - if (lowercaseMsg.includes('invalid note value')) { + if (lowercaseMsg.includes('invalid note value')) { // INVALID_NOTE_VALUE return new RailgunContractError( 'RailgunSmartWallet: Invalid Note Value. Please submit transaction with a corrected amount.', cause, ); } - if (lowercaseMsg.includes('invalid adapt contract as sender')) { + if (lowercaseMsg.includes('invalid adapt contract as sender')) { // INVALID_ADAPT_CONTRACT_SENDER return new RailgunContractError( 'RailgunSmartWallet: Invalid Adapt Contract as Sender. Please update your frontend to current Adapt module versions.', cause, ); } - if (lowercaseMsg.includes('invalid merkle root')) { + if (lowercaseMsg.includes('invalid merkle root')) { // INVALID_MERKLE_ROOT return new RailgunContractError( 'RailgunSmartWallet: Invalid Merkle Root. Please sync your balances and try again.', cause, ); } - if (lowercaseMsg.includes('note already spent')) { + if (lowercaseMsg.includes('note already spent')) { // NOTE_SPENT return new RailgunContractError( 'RailgunSmartWallet: Note Already Spent. Please sync your balances and try again.', cause, ); } - if (lowercaseMsg.includes('invalid note ciphertext array length')) { + if (lowercaseMsg.includes('invalid note ciphertext array length')) { // INVALID_NOTE_CIPHERTEXT_ARRAY_LENGTH return new RailgunContractError( 'RailgunSmartWallet: Invalid Note Ciphertext Array Length. Please sync balances and re-prove your transaction.', cause, ); } - if (lowercaseMsg.includes('invalid withdraw note')) { + if (lowercaseMsg.includes('invalid withdraw note')) { // INVALID_WITHDRAW_NOTE return new RailgunContractError( 'RailgunSmartWallet: Invalid Unshield Note. Please sync balances and re-prove your transaction.', cause, ); } - if (lowercaseMsg.includes('invalid snark proof')) { + if (lowercaseMsg.includes('invalid snark proof')) { // INVALID_SNARK_PROOF return new RailgunContractError( 'RailgunSmartWallet: Invalid Snark Proof. Please re-prove your transaction.', cause, @@ -165,5 +172,5 @@ export const sanitizeError = (cause: Error): Error => { ); } - return new Error('Unknown error. Please try again.', { cause }); + return new CustomError('Unknown error. Please try again', cause); }; From 3df2ce85384e922f2873e67d1290c37700cd69bd Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 14:08:50 -0300 Subject: [PATCH 04/26] fix: export constants for shared usage --- src/utils/errors/constants.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index e7426c6..ce53935 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -1,5 +1,3 @@ -import { isDefined } from '../util'; - type ErrorDefinition = { matches: string[]; message: string; @@ -9,7 +7,7 @@ type CustomErrorMapping = { [key: string]: ErrorDefinition; }; -const CUSTOM_ERRORS: CustomErrorMapping = { +export const CUSTOM_ERRORS: CustomErrorMapping = { CONNECTION_ERROR: { matches: ['quorum', 'could not connect to'], message: 'Could not connect.' @@ -48,7 +46,7 @@ const CUSTOM_ERRORS: CustomErrorMapping = { } }; -const RAILGUN_ERRORS: CustomErrorMapping = { +export const RAILGUN_ERRORS: CustomErrorMapping = { INVALID_NFT_NOTE: { matches: ['invalid nft note value'], message: 'RailgunSmartWallet: Invalid NFT Note Value.' From 5052dc8bef1325a14f893c2b873c92581de489ec Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 14:28:23 -0300 Subject: [PATCH 05/26] chore: refactor errors.ts sanitizeError with a more legible approach, move constants to dedicated file, and separate types onto another dedicated file --- src/utils/errors/constants.ts | 11 +-- src/utils/errors/error.ts | 162 +++++++--------------------------- src/utils/errors/types.ts | 8 ++ 3 files changed, 41 insertions(+), 140 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index ce53935..cc7ceeb 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -1,12 +1,5 @@ -type ErrorDefinition = { - matches: string[]; - message: string; -}; - -type CustomErrorMapping = { - [key: string]: ErrorDefinition; -}; - +import { CustomErrorMapping } from "./types"; +export const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; export const CUSTOM_ERRORS: CustomErrorMapping = { CONNECTION_ERROR: { matches: ['quorum', 'could not connect to'], diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 9130c2c..1d1619d 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -1,8 +1,7 @@ +import { CustomErrorMapping, ErrorDefinition } from './types'; +import { STRING_PREFIX_AFTER_UNICODE_REPLACEMENT, RAILGUN_ERRORS, CUSTOM_ERRORS } from './constants'; import { isDefined } from '../util'; -const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; - - class CustomError extends Error { originalError: Error; @@ -31,144 +30,45 @@ const validAscii = (str: string) => { ); }; +const findMatchingError = (errorMessage: string, errorMapping: CustomErrorMapping): ErrorDefinition | null => { + const lowercaseMsg = errorMessage.toLowerCase(); + + for (const [, errorDef] of Object.entries(errorMapping)) { + if (errorDef.matches.some(match => lowercaseMsg.includes(match))) { + return errorDef; + } + } + return null; +} + const isRailgunError = (cause: Error): boolean => cause.message.toLowerCase().includes('railgunsmartwallet') export const sanitizeError = (cause: Error): Error => { if (isDefined(cause) && cause.message) { - const lowercaseMsg = cause.message.toLowerCase(); - if (isRailgunError(cause)) { - return cause; + const matchedRailgunError = findMatchingError(cause.message, RAILGUN_ERRORS); + if (matchedRailgunError) { + return new RailgunContractError(matchedRailgunError.message, cause); + } + return new RailgunContractError('Uknown Railgun Smart Wallet Error.', cause); // @@ TODO: Check if this is a possibility } - if ( - lowercaseMsg.includes('quorum') || // Connection error - lowercaseMsg.includes('could not connect to') // Connection error - ) { - return new Error('Could not connect.', { cause }); - } - if (lowercaseMsg.includes('call revert exception')) { - return new Error('Failed to connect to RPC.', { cause }); // RPC_ERROR - } - if (lowercaseMsg.includes('already known')) { - return new Error( - 'Transaction successful but ethers request for TXID failed.', - { cause }, // KNOWN_TRANSACTION - ); - } - if (lowercaseMsg.includes('missing revert data')) { - return new Error('RPC connection error.', { cause }); // RPC_ERROR - } - if ( - lowercaseMsg.includes( - 'transaction may fail or may require manual gas limit', - ) - ) { - return new Error('Unknown error. Transaction failed.', { cause }); // @@TODO: Replace or categorize better - } - if (lowercaseMsg.includes('replacement fee too low')) { - return new Error( - 'Nonce is used in a pending transaction, and replacement fee is too low. Please increase your network fee to replace the pending transaction.', - { cause }, // LOW_REPLACEMENT_FEE - ); - } - if (lowercaseMsg.includes('intrinsic gas too low')) { - return new Error( - 'Gas price rejected. Please select a higher gas price or resubmit.', - { cause }, // LOW_GAS - ); - } - if (lowercaseMsg.includes('transaction underpriced')) { - return new Error( - 'Gas fee too low. Please select a higher gas price and resubmit.', - { cause }, // LOW_GAS_RESUBMIT - ); - } - if (lowercaseMsg.includes('insufficient funds for intrinsic')) { - return new Error('Insufficient gas to process transaction.', { cause }); // INSUFFICIENT_GAS - } - if (lowercaseMsg.includes('nonce has already been used')) { - return new Error( - // Do not change 'Nonce already used' string of Error message. - 'Nonce already used: the transaction was already completed.', - { cause }, // NONCE_USED - ); - } - if (lowercaseMsg.includes('error while dialing dial tcp')) { - return new Error( - 'Error while connecting to RPC provider. Please try again.', - { cause }, // RPC_ERROR - ); - } - if ( - lowercaseMsg.includes('spendable private balance too low') && - lowercaseMsg.includes('broadcaster fee') - ) { - return new Error('Private balance too low to pay broadcaster fee.', { - cause, // LOW_PRIVATE_BALANCE - }); - } + const matchedCustomError = findMatchingError(cause.message, CUSTOM_ERRORS); - // Custom RAILGUN contract error messages - if (lowercaseMsg.includes('railgunsmartwallet')) { - if (lowercaseMsg.includes('invalid nft note value')) { // INVALID_NFT_NOTE - return new RailgunContractError('RailgunSmartWallet: Invalid NFT Note Value.', cause); // INVALID_NFT_NOTE - } - if (lowercaseMsg.includes('unsupported token')) { - return new RailgunContractError( - 'RailgunSmartWallet: Unsupported Token. This token cannot interact with the RAILGUN contract.',// UNSUPPORTED_TOKEN - cause, - ); - } - if (lowercaseMsg.includes('invalid note value')) { // INVALID_NOTE_VALUE - return new RailgunContractError( - 'RailgunSmartWallet: Invalid Note Value. Please submit transaction with a corrected amount.', - cause, - ); - } - if (lowercaseMsg.includes('invalid adapt contract as sender')) { // INVALID_ADAPT_CONTRACT_SENDER - return new RailgunContractError( - 'RailgunSmartWallet: Invalid Adapt Contract as Sender. Please update your frontend to current Adapt module versions.', - cause, - ); - } - if (lowercaseMsg.includes('invalid merkle root')) { // INVALID_MERKLE_ROOT - return new RailgunContractError( - 'RailgunSmartWallet: Invalid Merkle Root. Please sync your balances and try again.', - cause, - ); - } - if (lowercaseMsg.includes('note already spent')) { // NOTE_SPENT - return new RailgunContractError( - 'RailgunSmartWallet: Note Already Spent. Please sync your balances and try again.', - cause, - ); - } - if (lowercaseMsg.includes('invalid note ciphertext array length')) { // INVALID_NOTE_CIPHERTEXT_ARRAY_LENGTH - return new RailgunContractError( - 'RailgunSmartWallet: Invalid Note Ciphertext Array Length. Please sync balances and re-prove your transaction.', - cause, - ); - } - if (lowercaseMsg.includes('invalid withdraw note')) { // INVALID_WITHDRAW_NOTE - return new RailgunContractError( - 'RailgunSmartWallet: Invalid Unshield Note. Please sync balances and re-prove your transaction.', - cause, - ); - } - if (lowercaseMsg.includes('invalid snark proof')) { // INVALID_SNARK_PROOF - return new RailgunContractError( - 'RailgunSmartWallet: Invalid Snark Proof. Please re-prove your transaction.', - cause, - ); - } + if (matchedCustomError) { + return new Error(matchedCustomError.message, cause); } - return new Error( - validAscii(cause.message).replace( - `:${STRING_PREFIX_AFTER_UNICODE_REPLACEMENT}`, - ': ', - ), + + // If no error is matched we return the original sanitized error + const errorMessage = validAscii(cause.message).replace( + `:${STRING_PREFIX_AFTER_UNICODE_REPLACEMENT}`, + ': ', + ); + + return new CustomError( + errorMessage, + cause ); } diff --git a/src/utils/errors/types.ts b/src/utils/errors/types.ts index e69de29..fca3229 100644 --- a/src/utils/errors/types.ts +++ b/src/utils/errors/types.ts @@ -0,0 +1,8 @@ +export type ErrorDefinition = { + matches: string[]; + message: string; +}; + +export type CustomErrorMapping = { + [key: string]: ErrorDefinition; +}; From 41c9377d9d801afa8470980e72e91aea2b1eab1f Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 14:29:56 -0300 Subject: [PATCH 06/26] fix: test suite correct path --- src/utils/__tests__/error.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/__tests__/error.test.ts b/src/utils/__tests__/error.test.ts index 9167de1..3e77113 100644 --- a/src/utils/__tests__/error.test.ts +++ b/src/utils/__tests__/error.test.ts @@ -1,6 +1,6 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import { sanitizeError } from '../error'; +import { sanitizeError } from '../errors/error'; chai.use(chaiAsPromised); const { expect } = chai; From 729c2e8b030a4f0ead44c9c2ddd135263d43fc92 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 14:42:30 -0300 Subject: [PATCH 07/26] chore: EOF --- src/utils/errors/constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index cc7ceeb..e3cfef6 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -1,5 +1,6 @@ import { CustomErrorMapping } from "./types"; export const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; + export const CUSTOM_ERRORS: CustomErrorMapping = { CONNECTION_ERROR: { matches: ['quorum', 'could not connect to'], @@ -76,4 +77,4 @@ export const RAILGUN_ERRORS: CustomErrorMapping = { matches: ['invalid snark proof'], message: 'RailgunSmartWallet: Invalid Snark Proof. Please re-prove your transaction.' } -}; \ No newline at end of file +}; From a64b53eb6c6936bacac64dd721d1f278e8e678d6 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 18:27:34 -0300 Subject: [PATCH 08/26] chore: move ascii to constants.ts file --- src/utils/errors/constants.ts | 4 ++++ src/utils/errors/error.ts | 6 ++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index e3cfef6..d6630aa 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -1,6 +1,10 @@ import { CustomErrorMapping } from "./types"; + export const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; +// eslint-disable-next-line no-useless-escape +export const VALID_ASCII_REGEX = /[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g; + export const CUSTOM_ERRORS: CustomErrorMapping = { CONNECTION_ERROR: { matches: ['quorum', 'could not connect to'], diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 1d1619d..3f51a12 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -1,5 +1,5 @@ import { CustomErrorMapping, ErrorDefinition } from './types'; -import { STRING_PREFIX_AFTER_UNICODE_REPLACEMENT, RAILGUN_ERRORS, CUSTOM_ERRORS } from './constants'; +import { STRING_PREFIX_AFTER_UNICODE_REPLACEMENT, RAILGUN_ERRORS, CUSTOM_ERRORS, INVALID_ASCII_REGEX } from './constants'; import { isDefined } from '../util'; class CustomError extends Error { @@ -24,8 +24,7 @@ class RailgunContractError extends Error { const validAscii = (str: string) => { return str.replace( - // eslint-disable-next-line no-useless-escape - /[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g, + INVALID_ASCII_REGEX, '', ); }; @@ -59,7 +58,6 @@ export const sanitizeError = (cause: Error): Error => { return new Error(matchedCustomError.message, cause); } - // If no error is matched we return the original sanitized error const errorMessage = validAscii(cause.message).replace( `:${STRING_PREFIX_AFTER_UNICODE_REPLACEMENT}`, From bb05caf02efb61d571230350d8bcbdc6d27abb94 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 18:29:54 -0300 Subject: [PATCH 09/26] chore: rename ascii regex to be self documenting --- src/utils/errors/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index d6630aa..d3e7012 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -3,7 +3,7 @@ import { CustomErrorMapping } from "./types"; export const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; // eslint-disable-next-line no-useless-escape -export const VALID_ASCII_REGEX = /[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g; +export const INVALID_ASCII_REGEX = /[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g; export const CUSTOM_ERRORS: CustomErrorMapping = { CONNECTION_ERROR: { From b8e3601c8ee859fb36a43be6cc2762b8f4cccec0 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 18:33:10 -0300 Subject: [PATCH 10/26] fix: correct message and rename for transaction underpriced --- src/utils/errors/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index d3e7012..cbc89d0 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -26,8 +26,8 @@ export const CUSTOM_ERRORS: CustomErrorMapping = { matches: ['intrinsic gas too low'], message: 'Gas price rejected. Please select a higher gas price or resubmit.' }, - LOW_GAS_RESUBMIT: { - matches: ['intrinsic gas too low'], + UNDERPRICED_TRANSACTION: { + matches: ['transaction underpriced'], message: 'Gas price rejected. Please select a higher gas price and resubmit.' }, // @@TODO: Find a better suited message for this INSUFFICIENT_GAS: { From 39a2ba4908f5e45d244d289f3086e792ed85e027 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 18:35:32 -0300 Subject: [PATCH 11/26] chore: remove comments --- src/utils/errors/constants.ts | 2 +- src/utils/errors/error.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index cbc89d0..f7c4b85 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -29,7 +29,7 @@ export const CUSTOM_ERRORS: CustomErrorMapping = { UNDERPRICED_TRANSACTION: { matches: ['transaction underpriced'], message: 'Gas price rejected. Please select a higher gas price and resubmit.' - }, // @@TODO: Find a better suited message for this + }, INSUFFICIENT_GAS: { matches: ['insufficient funds for intrinsic'], message: 'Insufficient gas to process transaction.' diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 3f51a12..117272a 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -49,7 +49,7 @@ export const sanitizeError = (cause: Error): Error => { if (matchedRailgunError) { return new RailgunContractError(matchedRailgunError.message, cause); } - return new RailgunContractError('Uknown Railgun Smart Wallet Error.', cause); // @@ TODO: Check if this is a possibility + return new RailgunContractError('Uknown Railgun Smart Wallet Error.', cause); } const matchedCustomError = findMatchingError(cause.message, CUSTOM_ERRORS); From 01c140382bc793e8bee506bbe3bb6aaa6daff695 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 18:42:43 -0300 Subject: [PATCH 12/26] chore: match refactor with old tests --- src/utils/errors/constants.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index f7c4b85..e5367e5 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -11,9 +11,13 @@ export const CUSTOM_ERRORS: CustomErrorMapping = { message: 'Could not connect.' }, RPC_ERROR: { - matches: ['call revert exception', 'missing revert data', 'error while dialing dial tcp'], + matches: ['call revert exception', 'error while dialing dial tcp'], message: 'Failed to connect to RPC.' }, + RPC_CONNECTION_ERROR: { + matches: ['missing revert data'], + message: 'RPC connection error.' + }, KNOWN_TRANSACTION: { matches: ['already known'], message: 'Transaction successful but ethers request for TXID failed.' @@ -41,6 +45,10 @@ export const CUSTOM_ERRORS: CustomErrorMapping = { LOW_PRIVATE_BALANCE: { matches: ['spendable private balance too low', 'broadcaster fee'], message: 'Private balance too low to pay broadcaster fee.' + }, + TRANSACTION_SIMULATION_FAILED: { + matches: ['transaction may fail or may require manual gas limit'], + message: 'Unknown error. Transaction failed.' } }; From 0c4fe1e9286d14e02fd4925dafc751f57a1f7438 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 18:50:32 -0300 Subject: [PATCH 13/26] chore: add more tests with edge cases for undefined, and ascii chars --- src/utils/__tests__/error.test.ts | 34 ++++++++++++++++++++++++++++++- src/utils/errors/error.ts | 2 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/utils/__tests__/error.test.ts b/src/utils/__tests__/error.test.ts index 3e77113..cda6d95 100644 --- a/src/utils/__tests__/error.test.ts +++ b/src/utils/__tests__/error.test.ts @@ -51,4 +51,36 @@ describe('error', () => { sanitizeError(new Error('replacement fee too low')).message, ).to.equal(expectedErrorMessage); }); -}); + + it('Should sanitize insufficient gas errors', () => { + const expectedErrorMessage = 'Insufficient gas to process transaction.'; + expect( + sanitizeError(new Error('insufficient funds for intrinsic')).message, + ).to.equal(expectedErrorMessage); + }); + + it('Should sanitize low gas price errors', () => { + const expectedErrorMessage = 'Gas price rejected. Please select a higher gas price or resubmit.'; + + expect( + sanitizeError(new Error('intrinsic gas too low')).message, + ).to.equal(expectedErrorMessage); + }); + + it('Should handle undefined error', () => { + const error = sanitizeError(undefined as unknown as Error); + expect(error.message).to.equal('Unknown error. Please try again.'); + }); + + it('Should handle error without message', () => { + const error = sanitizeError(new Error()); + expect(error.message).to.equal('Unknown error. Please try again.'); + }); + + it('Should sanitize non-ASCII characters in unknown errors', () => { + const error = sanitizeError(new Error('Unknown error 🚫')); + expect(error.message).to.equal('Unknown error '); + }); + + +}); \ No newline at end of file diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 117272a..7aee25e 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -70,5 +70,5 @@ export const sanitizeError = (cause: Error): Error => { ); } - return new CustomError('Unknown error. Please try again', cause); + return new CustomError('Unknown error. Please try again.', cause); }; From 2a624f96c21461113550d45971079125e20c3849 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 20:37:28 -0300 Subject: [PATCH 14/26] fix: remove unnecesary classes, but keep Error class --- src/utils/errors/constants.ts | 2 +- src/utils/errors/error.ts | 28 ++++------------------------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index e5367e5..63bc7db 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -43,7 +43,7 @@ export const CUSTOM_ERRORS: CustomErrorMapping = { message: 'Nonce already used: the transaction was already completed.' }, LOW_PRIVATE_BALANCE: { - matches: ['spendable private balance too low', 'broadcaster fee'], + matches: ['private balance too low', 'broadcaster fee'], message: 'Private balance too low to pay broadcaster fee.' }, TRANSACTION_SIMULATION_FAILED: { diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 7aee25e..5b83247 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -2,26 +2,6 @@ import { CustomErrorMapping, ErrorDefinition } from './types'; import { STRING_PREFIX_AFTER_UNICODE_REPLACEMENT, RAILGUN_ERRORS, CUSTOM_ERRORS, INVALID_ASCII_REGEX } from './constants'; import { isDefined } from '../util'; -class CustomError extends Error { - originalError: Error; - - constructor(message: string, originalError: Error) { - super(message); - this.name = 'CustomError'; - this.originalError = originalError; - } -} - -class RailgunContractError extends Error { - originalError: Error; - - constructor(message: string, originalError: Error) { - super(message); - this.name = 'RailgunContractError'; - this.originalError = originalError; - } -} - const validAscii = (str: string) => { return str.replace( INVALID_ASCII_REGEX, @@ -47,9 +27,9 @@ export const sanitizeError = (cause: Error): Error => { if (isRailgunError(cause)) { const matchedRailgunError = findMatchingError(cause.message, RAILGUN_ERRORS); if (matchedRailgunError) { - return new RailgunContractError(matchedRailgunError.message, cause); + return new Error(matchedRailgunError.message, cause); } - return new RailgunContractError('Uknown Railgun Smart Wallet Error.', cause); + return new Error('Uknown Railgun Smart Wallet Error.', cause); } const matchedCustomError = findMatchingError(cause.message, CUSTOM_ERRORS); @@ -64,11 +44,11 @@ export const sanitizeError = (cause: Error): Error => { ': ', ); - return new CustomError( + return new Error( errorMessage, cause ); } - return new CustomError('Unknown error. Please try again.', cause); + return new Error('Unknown error. Please try again.', cause); }; From 5741d5af98fad6960b15dda4434325359cb81e71 Mon Sep 17 00:00:00 2001 From: bhflm Date: Mon, 13 Jan 2025 21:55:11 -0300 Subject: [PATCH 15/26] misc: remove unnecesary spaces --- src/utils/__tests__/error.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/utils/__tests__/error.test.ts b/src/utils/__tests__/error.test.ts index cda6d95..87c93f0 100644 --- a/src/utils/__tests__/error.test.ts +++ b/src/utils/__tests__/error.test.ts @@ -81,6 +81,4 @@ describe('error', () => { const error = sanitizeError(new Error('Unknown error 🚫')); expect(error.message).to.equal('Unknown error '); }); - - }); \ No newline at end of file From 0e4c319bf186ec56676a64d0f1a86ef176712687 Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 11:34:44 -0300 Subject: [PATCH 16/26] chore: early return for undefined message case, check just for message inside cause since its type Error --- src/utils/__tests__/error.test.ts | 2 ++ src/utils/errors/error.ts | 45 +++++++++++++++---------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/utils/__tests__/error.test.ts b/src/utils/__tests__/error.test.ts index 87c93f0..559db35 100644 --- a/src/utils/__tests__/error.test.ts +++ b/src/utils/__tests__/error.test.ts @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { sanitizeError } from '../errors/error'; diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 5b83247..8855c86 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -1,6 +1,5 @@ import { CustomErrorMapping, ErrorDefinition } from './types'; import { STRING_PREFIX_AFTER_UNICODE_REPLACEMENT, RAILGUN_ERRORS, CUSTOM_ERRORS, INVALID_ASCII_REGEX } from './constants'; -import { isDefined } from '../util'; const validAscii = (str: string) => { return str.replace( @@ -23,32 +22,32 @@ const findMatchingError = (errorMessage: string, errorMapping: CustomErrorMappin const isRailgunError = (cause: Error): boolean => cause.message.toLowerCase().includes('railgunsmartwallet') export const sanitizeError = (cause: Error): Error => { - if (isDefined(cause) && cause.message) { - if (isRailgunError(cause)) { - const matchedRailgunError = findMatchingError(cause.message, RAILGUN_ERRORS); - if (matchedRailgunError) { - return new Error(matchedRailgunError.message, cause); - } - return new Error('Uknown Railgun Smart Wallet Error.', cause); - } - - const matchedCustomError = findMatchingError(cause.message, CUSTOM_ERRORS); + if (!cause.message) { + return new Error('Unknown error. Please try again.', { cause }); + } - if (matchedCustomError) { - return new Error(matchedCustomError.message, cause); + if (isRailgunError(cause)) { + const matchedRailgunError = findMatchingError(cause.message, RAILGUN_ERRORS); + if (matchedRailgunError) { + return new Error(matchedRailgunError.message, cause); } + return new Error('Uknown Railgun Smart Wallet Error.', cause); + } - // If no error is matched we return the original sanitized error - const errorMessage = validAscii(cause.message).replace( - `:${STRING_PREFIX_AFTER_UNICODE_REPLACEMENT}`, - ': ', - ); + const matchedCustomError = findMatchingError(cause.message, CUSTOM_ERRORS); - return new Error( - errorMessage, - cause - ); + if (matchedCustomError) { + return new Error(matchedCustomError.message, cause); } - return new Error('Unknown error. Please try again.', cause); + // If no error is matched we return the original sanitized error + const errorMessage = validAscii(cause.message).replace( + `:${STRING_PREFIX_AFTER_UNICODE_REPLACEMENT}`, + ': ', + ); + + return new Error( + errorMessage, + cause + ); }; From 21b9a122e90e06122cd2a7fb97a8d94972f7bd16 Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 11:37:04 -0300 Subject: [PATCH 17/26] chore: rename to sanitizeAscii, compress ascii regex --- src/utils/errors/constants.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index 63bc7db..1a30f3b 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -2,8 +2,9 @@ import { CustomErrorMapping } from "./types"; export const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; -// eslint-disable-next-line no-useless-escape -export const INVALID_ASCII_REGEX = /[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g; +// Matches any characters that are NOT in the printable ASCII range (space to tilde) +// Printable ASCII characters are in the range of 32 (space) to 126 (tilde) +export const INVALID_ASCII_REGEX = /[^ -~]+/g; export const CUSTOM_ERRORS: CustomErrorMapping = { CONNECTION_ERROR: { From 494542506ed88d6c211ce3bfd19a880c628b4013 Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 11:47:28 -0300 Subject: [PATCH 18/26] fix: encapsulate catch inside objectwhen throwing Error --- src/utils/errors/error.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/errors/error.ts b/src/utils/errors/error.ts index 8855c86..b0280b3 100644 --- a/src/utils/errors/error.ts +++ b/src/utils/errors/error.ts @@ -29,15 +29,15 @@ export const sanitizeError = (cause: Error): Error => { if (isRailgunError(cause)) { const matchedRailgunError = findMatchingError(cause.message, RAILGUN_ERRORS); if (matchedRailgunError) { - return new Error(matchedRailgunError.message, cause); + return new Error(matchedRailgunError.message, { cause }); } - return new Error('Uknown Railgun Smart Wallet Error.', cause); + return new Error('Uknown Railgun Smart Wallet Error.', { cause }); } const matchedCustomError = findMatchingError(cause.message, CUSTOM_ERRORS); if (matchedCustomError) { - return new Error(matchedCustomError.message, cause); + return new Error(matchedCustomError.message, { cause }); } // If no error is matched we return the original sanitized error @@ -48,6 +48,6 @@ export const sanitizeError = (cause: Error): Error => { return new Error( errorMessage, - cause + { cause } ); }; From c9c4a03ea3d973a5cad0d3939e62f79a81e620fa Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 11:50:49 -0300 Subject: [PATCH 19/26] fix: rename errors/error.ts to errors/index.ts --- src/utils/errors/{error.ts => index.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/utils/errors/{error.ts => index.ts} (100%) diff --git a/src/utils/errors/error.ts b/src/utils/errors/index.ts similarity index 100% rename from src/utils/errors/error.ts rename to src/utils/errors/index.ts From 95af50206d40924216d148f721921b8a0842881a Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 11:51:20 -0300 Subject: [PATCH 20/26] fix: errors path for test suite --- src/utils/__tests__/error.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/__tests__/error.test.ts b/src/utils/__tests__/error.test.ts index 559db35..debc262 100644 --- a/src/utils/__tests__/error.test.ts +++ b/src/utils/__tests__/error.test.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import { sanitizeError } from '../errors/error'; +import { sanitizeError } from '../errors'; chai.use(chaiAsPromised); const { expect } = chai; From 0b206e2023db3e3ae383da26e4f2151734ed0366 Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 11:51:56 -0300 Subject: [PATCH 21/26] chore: remove unnecesary eslint rules --- src/utils/__tests__/error.test.ts | 2 -- src/utils/index.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/utils/__tests__/error.test.ts b/src/utils/__tests__/error.test.ts index debc262..e287f49 100644 --- a/src/utils/__tests__/error.test.ts +++ b/src/utils/__tests__/error.test.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unsafe-call */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { sanitizeError } from '../errors'; diff --git a/src/utils/index.ts b/src/utils/index.ts index 3aa4c67..18df818 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,7 +2,7 @@ export * from './artifact-v2'; export * from './available-rpc'; export * from './compare'; export * from './fallback-provider'; -export * from './errors/error'; +export * from './errors'; export * from './format'; export * from './gas'; export * from './network'; From 082de73548573990927e84c37e0a511b354cba1e Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 13:38:19 -0300 Subject: [PATCH 22/26] chore: check for cause message and handle --- src/utils/errors/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/errors/index.ts b/src/utils/errors/index.ts index b0280b3..9db605f 100644 --- a/src/utils/errors/index.ts +++ b/src/utils/errors/index.ts @@ -22,7 +22,7 @@ const findMatchingError = (errorMessage: string, errorMapping: CustomErrorMappin const isRailgunError = (cause: Error): boolean => cause.message.toLowerCase().includes('railgunsmartwallet') export const sanitizeError = (cause: Error): Error => { - if (!cause.message) { + if (!cause?.message) { return new Error('Unknown error. Please try again.', { cause }); } From d79855b03125567be8cbd5688bebdb8ae1ccafe4 Mon Sep 17 00:00:00 2001 From: bhflm Date: Tue, 14 Jan 2025 19:39:51 -0300 Subject: [PATCH 23/26] chore: rename to sanitizeAscii --- src/utils/errors/index.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/utils/errors/index.ts b/src/utils/errors/index.ts index 9db605f..e0f52a2 100644 --- a/src/utils/errors/index.ts +++ b/src/utils/errors/index.ts @@ -1,12 +1,7 @@ import { CustomErrorMapping, ErrorDefinition } from './types'; import { STRING_PREFIX_AFTER_UNICODE_REPLACEMENT, RAILGUN_ERRORS, CUSTOM_ERRORS, INVALID_ASCII_REGEX } from './constants'; -const validAscii = (str: string) => { - return str.replace( - INVALID_ASCII_REGEX, - '', - ); -}; +const sanitizeAscii = (str: string) => str.replace(INVALID_ASCII_REGEX, ''); const findMatchingError = (errorMessage: string, errorMapping: CustomErrorMapping): ErrorDefinition | null => { const lowercaseMsg = errorMessage.toLowerCase(); @@ -41,7 +36,7 @@ export const sanitizeError = (cause: Error): Error => { } // If no error is matched we return the original sanitized error - const errorMessage = validAscii(cause.message).replace( + const errorMessage = sanitizeAscii(cause.message).replace( `:${STRING_PREFIX_AFTER_UNICODE_REPLACEMENT}`, ': ', ); From 08db45538dfe7158b1dc6acafe5bc381f6c178d1 Mon Sep 17 00:00:00 2001 From: bhflm Date: Thu, 16 Jan 2025 20:32:41 -0300 Subject: [PATCH 24/26] fix: do not remove newlines within ascii regex --- src/utils/errors/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/errors/constants.ts b/src/utils/errors/constants.ts index 1a30f3b..6392094 100644 --- a/src/utils/errors/constants.ts +++ b/src/utils/errors/constants.ts @@ -4,7 +4,7 @@ export const STRING_PREFIX_AFTER_UNICODE_REPLACEMENT = 'y %'; // Matches any characters that are NOT in the printable ASCII range (space to tilde) // Printable ASCII characters are in the range of 32 (space) to 126 (tilde) -export const INVALID_ASCII_REGEX = /[^ -~]+/g; +export const INVALID_ASCII_REGEX = /[^ -~\n]+/g; export const CUSTOM_ERRORS: CustomErrorMapping = { CONNECTION_ERROR: { From e88a4f4781b385e7424a228bef5f66aa5a6c30fc Mon Sep 17 00:00:00 2001 From: bhflm Date: Thu, 16 Jan 2025 20:34:05 -0300 Subject: [PATCH 25/26] fix: error directory rename --- src/utils/{errors => error}/constants.ts | 0 src/utils/{errors => error}/index.ts | 0 src/utils/{errors => error}/types.ts | 0 src/utils/index.ts | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename src/utils/{errors => error}/constants.ts (100%) rename src/utils/{errors => error}/index.ts (100%) rename src/utils/{errors => error}/types.ts (100%) diff --git a/src/utils/errors/constants.ts b/src/utils/error/constants.ts similarity index 100% rename from src/utils/errors/constants.ts rename to src/utils/error/constants.ts diff --git a/src/utils/errors/index.ts b/src/utils/error/index.ts similarity index 100% rename from src/utils/errors/index.ts rename to src/utils/error/index.ts diff --git a/src/utils/errors/types.ts b/src/utils/error/types.ts similarity index 100% rename from src/utils/errors/types.ts rename to src/utils/error/types.ts diff --git a/src/utils/index.ts b/src/utils/index.ts index 18df818..8a9c0c5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,7 +2,7 @@ export * from './artifact-v2'; export * from './available-rpc'; export * from './compare'; export * from './fallback-provider'; -export * from './errors'; +export * from './error'; export * from './format'; export * from './gas'; export * from './network'; From 142ef1fe4652d7558581673cc7daac76b422488a Mon Sep 17 00:00:00 2001 From: bhflm Date: Thu, 16 Jan 2025 20:34:26 -0300 Subject: [PATCH 26/26] fix: correct error dir test path --- src/utils/__tests__/error.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/__tests__/error.test.ts b/src/utils/__tests__/error.test.ts index e287f49..e07622e 100644 --- a/src/utils/__tests__/error.test.ts +++ b/src/utils/__tests__/error.test.ts @@ -1,6 +1,6 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import { sanitizeError } from '../errors'; +import { sanitizeError } from '../error'; chai.use(chaiAsPromised); const { expect } = chai;