@shogun-sdk/money-legos
Version:
Shogun Money Legos: clients and types for quotes, memes, prices, balances, fees, validations, etc.
179 lines (145 loc) • 7.84 kB
text/typescript
import { BaseError } from 'viem';
import { CHAIN_MAP } from '../config/chains.js';
import type { QuoteTypes } from '../types/index.js';
import { formatEthDecimal } from './format-eth-decimals.js';
import { lowercase } from './formatter.js';
import { getSuggestedSlippage } from './slippage.js';
const UNPOSSIBLE_SLIPPAGE = 100;
export const DEFAULT_ERROR_MESSAGE = 'Action Failed: Please try again or contact support';
export const ERROR_FETCHING_DEST_TX = 'Transaction is still processing.';
export const INSUFFICIENT_BALANCE_MSG = 'Insufficient balance';
const LOW_AMOUNT_ERROR_MSG = 'error_low_give_amount error message:';
export const SLIPPAGE_CODE = '0xff5f293c';
export const SLIPPAGE_ERROR_MSG = 'Slippage tolerance exceeded';
const SLIPPAGE_ERROR_OUTPUT_MSG = 'Slippage error. Please retry, or increase slippage if the issue persists.';
export const ERROR_MISSING_REQUIRED_DATA = 'Missing required data, aborting swap';
const MINIMUM_TX_FEE_PART = 'Minimum transaction fee for cross-chain swap';
export const makeNotEnoughFundsUsdCrosschainErrorMsg = (
amountInUsd: number | string,
inTokenSymbol: string,
network: number,
): string => {
return `${MINIMUM_TX_FEE_PART} is $${formatEthDecimal(amountInUsd, 2, 0)} worth of ${inTokenSymbol} on ${CHAIN_MAP[network]?.name ?? ''}`;
};
export const makeEstimatedSlippageError = (suggestedSlippage: number): string => {
if (suggestedSlippage === UNPOSSIBLE_SLIPPAGE) {
return `Transaction can't be executed with the slippage ${suggestedSlippage}%`;
}
return `Slippage error. Please increase slippage up to ${suggestedSlippage}%`;
};
export const ERROR_INSUFFICIENT_FUNDS_DETAILED =
'Please ensure your account has sufficient funds to cover the transaction cost.';
const UNAUTHORIZED_ERROR_MSG = 'Please log out and log back in.';
const DELEGATED_TRANSACTION_APPROVALS_EXPIRED_ERROR_MSG =
'Delegated transaction approvals have expired or been disabled. Please log in to the dashboard to re-enable access for delegated transactions.';
const ERROR_MISSING_ASSET = 'Please select an asset';
export const ERROR_INVALID_RECIPIENT = 'Please enter a valid recipient address';
const ERROR_INVALID_TRANSFER_DATA = 'The specified amount is invalid or the recipient address is incorrect.';
const ERROR_INVALID_SWAP_PAYLOAD = 'Invalid swap payload';
const ERROR_INVALID_AMOUNT = 'Please enter a valid amount';
export const INSUFFICIENT_FUNDS_ERROR_MSG = 'Insufficient balance';
export const INSUFFICIENT_FUNDS_FOR_GAS_ERROR_MSG = 'Insufficient funds for gas';
export const getInsufficientFundsWebAppError = (estimatedFees: bigint, network: number) => {
if (!estimatedFees && !network) {
return buildInsufficientFundsWebAppError();
}
return INSUFFICIENT_FUNDS_ERROR_MSG;
};
export const getInsufficientGasWebAppError = () => {
return INSUFFICIENT_FUNDS_FOR_GAS_ERROR_MSG;
};
export const BELOW_MIN_TRADE = 'Below minimum trade';
export const buildInsufficientFundsWebAppError = () => {
return INSUFFICIENT_FUNDS_ERROR_MSG;
};
const renderFundsWebAppError = () => {
return INSUFFICIENT_FUNDS_ERROR_MSG;
};
const sameErrorReturn = ({ errorMessage }: { errorMessage: string }) => {
return errorMessage || DEFAULT_ERROR_MESSAGE;
};
const ERROR_MESSAGES = {
InsufficientFundsForRent: renderFundsWebAppError,
'Simulation failed': renderFundsWebAppError,
gasRefuel: renderFundsWebAppError,
['TransactionExecutionError'.toLowerCase()]: renderFundsWebAppError,
['execution reverted']: renderFundsWebAppError,
[LOW_AMOUNT_ERROR_MSG]: renderFundsWebAppError,
'insufficient funds for transfer': renderFundsWebAppError,
'Insufficient balance to cover gas cost': renderFundsWebAppError,
'Insufficient balance to cover transaction fees': renderFundsWebAppError,
'intrinsic gas too low': renderFundsWebAppError,
'insufficient funds for gas * price + value': renderFundsWebAppError,
'intrinsic gas too low: gas 0, minimum needed': renderFundsWebAppError,
duplicateinstruction: 'Unable to process transaction',
'is too small to cover operational costs':
'The input amount is too small. Please increase the amount to execute the order',
'Request failed with status code 400': DEFAULT_ERROR_MESSAGE,
'gas required exceeds allowance': 'Swap Failed: Insufficient gas fee',
'turnkey error 16': DELEGATED_TRANSACTION_APPROVALS_EXPIRED_ERROR_MSG,
'transaction failed:{"instructionerror":[5,{"custom":6001}]}': SLIPPAGE_ERROR_OUTPUT_MSG,
'non-base58 character': 'The provided address is not a valid Solana address',
[UNAUTHORIZED_ERROR_MSG.toLowerCase()]: UNAUTHORIZED_ERROR_MSG,
SLIPPAGE_CODE: SLIPPAGE_ERROR_OUTPUT_MSG,
'0x5c0dee5d': DEFAULT_ERROR_MESSAGE,
[ERROR_INVALID_TRANSFER_DATA.toLowerCase()]: ERROR_INVALID_TRANSFER_DATA,
'self-transfers within the same chain are not allowed': 'Self-transfers within the same chain are not allowed.',
[ERROR_INVALID_SWAP_PAYLOAD]: ERROR_INVALID_SWAP_PAYLOAD,
[ERROR_INVALID_AMOUNT]: ERROR_INVALID_AMOUNT,
[ERROR_MISSING_ASSET]: ERROR_MISSING_ASSET,
[ERROR_INVALID_RECIPIENT]: ERROR_INVALID_RECIPIENT,
[ERROR_INVALID_TRANSFER_DATA]: ERROR_INVALID_TRANSFER_DATA,
'Internal server error': DEFAULT_ERROR_MESSAGE,
'Invalid value affiliateFee': INSUFFICIENT_FUNDS_ERROR_MSG,
'insufficient balance to cover gas cost': 'Insufficient funds',
'the total cost (gas * gas fee + value) of executing this transaction exceeds': ERROR_INSUFFICIENT_FUNDS_DETAILED,
'please increase the amount in to execute the order':
'Amount too low! Please increase the input to execute the swap.',
[ERROR_MISSING_REQUIRED_DATA]: ERROR_MISSING_REQUIRED_DATA,
'No account found': "No account found. Let's create one and get started!",
'Token IN and Token OUT are the same': 'Please select different tokens',
'denied permission': 'Please enable passkey permissions in your device settings',
[BELOW_MIN_TRADE]: sameErrorReturn,
slippage: sameErrorReturn,
"couldn't find a valid swap route": 'No valid swap route found. Please try again with different tokens.',
'relay error: amount is higher than the available liquidity.':
'The amount you are trying to swap is higher than the available liquidity. Please try again with a smaller amount.',
'transaction confirmation timeout after': 'Swap failed: try again or increase slippage',
'bundle transaction failed to confirm': 'Swap failed: try again or increase slippage',
[INSUFFICIENT_FUNDS_ERROR_MSG]: sameErrorReturn,
[INSUFFICIENT_FUNDS_FOR_GAS_ERROR_MSG]: sameErrorReturn,
};
export function decodeErrorMessage(errorMessage: string): string {
if (!errorMessage) {
return '';
}
const lowerCaseError = errorMessage?.toLowerCase();
for (const [key, value] of Object.entries(ERROR_MESSAGES)) {
const lowercaseKey = key.toLowerCase();
if (lowerCaseError.includes(lowercaseKey)) {
return typeof value === 'function' ? value({ errorMessage } as any) : value;
}
}
return DEFAULT_ERROR_MESSAGE;
}
export const returnErrorDuringEstimationGas = (quote: QuoteTypes, error: unknown) => {
const err = (error as BaseError).walk?.() || error;
const errorData = (err as any)?.['data'];
if (errorData) {
// Convert error data to lowercase for case-insensitive matching
const lowercasedData = lowercase(errorData);
if (lowercasedData.includes(lowercase(SLIPPAGE_CODE))) {
const suggestedSlippageValue = getSuggestedSlippage(quote, errorData);
throw Object.assign(new Error(makeEstimatedSlippageError(suggestedSlippageValue)), {
suggestedSlippageValue,
});
} else {
// Iterate over the ERROR_MESSAGES object
for (const [key, value] of Object.entries(ERROR_MESSAGES)) {
if (lowercasedData.includes(lowercase(key)) && typeof value !== 'function') {
throw new Error(value);
}
}
}
}
};