Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: parse jupiter errors to human readable translations #8433

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/swapper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './thorchain-utils'
export * from './cowswap-utils'
export * from './safe-utils'
export * from './swappers/CowSwapper'
export * from './swappers/JupiterSwapper'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused

Suggested change
export * from './swappers/JupiterSwapper'

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used again in 2de18a2

26 changes: 25 additions & 1 deletion packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,34 @@ import type { Asset } from '@shapeshiftoss/types'

import { executeSolanaTransaction } from '../..'
import type { BuyAssetBySellIdInput, Swapper } from '../../types'
import { JUPITER_ERRORS, SolanaLogsError } from './errorPatterns'
import { jupiterSupportedChainIds } from './utils/constants'

export const jupiterSwapper: Swapper = {
executeSolanaTransaction,
executeSolanaTransaction: async (...args) => {
try {
const txid = await executeSolanaTransaction(...args)
return txid
} catch (e) {
if (e instanceof Error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove me, all errors are instanceof Error

const errorMessage = e.message
const swapperErrorType = Object.keys(JUPITER_ERRORS).reduce(
(acc, errorPattern) => {
if (errorMessage.includes(errorPattern)) {
acc = JUPITER_ERRORS[errorPattern]
}

return acc
},
undefined as undefined | string,
)

if (swapperErrorType) throw new SolanaLogsError(swapperErrorType)
}

throw e
}
},

filterAssetIdsBySellable: (assets: Asset[]): Promise<AssetId[]> => {
return Promise.resolve(
Expand Down
25 changes: 25 additions & 0 deletions packages/swapper/src/swappers/JupiterSwapper/errorPatterns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export class SolanaLogsError extends Error {
constructor(name: string) {
super(name)
this.name = name
}
}

export enum JUPITER_ERROR_PATTERNS {
SLIPPAGE_TOLERANCE_EXCEEDED = 'SlippageToleranceExceeded',
UNDER_MINIMUM_AMOUNT = 'RequireGteViolated',
CONSUMED_MORE_FEES = 'exceeded CUs meter',
}

export enum JUPITER_ERROR_NAMES {
SLIPPAGE_TOLERANCE_EXCEEDED = 'SlippageToleranceExceeded',
UNDER_MINIMUM_AMOUNT = 'UnderMinimumAmount',
CONSUMED_MORE_FEES = 'ConsumedMoreFees',
}
Comment on lines +8 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: don't pluralize enums


export const JUPITER_ERRORS: Record<JUPITER_ERROR_PATTERNS | string, string> = {
[JUPITER_ERROR_PATTERNS.SLIPPAGE_TOLERANCE_EXCEEDED]:
JUPITER_ERROR_NAMES.SLIPPAGE_TOLERANCE_EXCEEDED,
[JUPITER_ERROR_PATTERNS.UNDER_MINIMUM_AMOUNT]: JUPITER_ERROR_NAMES.UNDER_MINIMUM_AMOUNT,
[JUPITER_ERROR_PATTERNS.CONSUMED_MORE_FEES]: JUPITER_ERROR_NAMES.CONSUMED_MORE_FEES,
}
2 changes: 2 additions & 0 deletions packages/swapper/src/swappers/JupiterSwapper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './utils/constants'
export * from './errorPatterns'
5 changes: 4 additions & 1 deletion src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,10 @@
"unsafeQuote": "This amount is below the recommended minimum for this pair (%{recommendedMin} %{symbol}). This could cause your trade to fail or loss of funds.",
"rateLimitExceeded": "Rate limit exceeded, try again later",
"maxSlippageExceededWithExpectedSlippage": "The maximum allowed slippage tolerance for this trade has been exceeded during simulation. Expected slippage: %{expectedSlippage}%. Try again with a higher slipppage tolerance.",
"executionRevertedWithExpectedSlippage": "Execution reverted during execution. This may be due to insufficient slippage tolerance. Expected slippage: %{expectedSlippage}%. Try again with a higher slipppage tolerance."
"executionRevertedWithExpectedSlippage": "Execution reverted during execution. This may be due to insufficient slippage tolerance. Expected slippage: %{expectedSlippage}%. Try again with a higher slipppage tolerance.",
"slippageExceeded": "Slippage tolerance exceeded.",
Copy link
Contributor

@gomesalexandre gomesalexandre Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"slippageExceeded": "Slippage tolerance exceeded.",
"slippageToleranceExceeded": "Slippage tolerance exceeded.",

"underMinimumAmount": "One or more of the assets in this trade are below the minimum amount required for this trade.",
"consumedMoreFees": "The transaction did revert because the fees consumed by this trade were higher than expected."
},
"swappingComingSoonForWallet": "Swapping for %{walletName} is coming soon",
"recentTrades": "Recent Trades",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import type {
import {
getHopByIndex,
isExecutableTradeQuote,
SolanaLogsError,
SwapperName,
TradeExecutionEvent,
} from '@shapeshiftoss/swapper'
import { LIFI_TRADE_POLL_INTERVAL_MILLISECONDS } from '@shapeshiftoss/swapper/dist/swappers/LifiSwapper/LifiSwapper'
import type { CosmosSdkChainId } from '@shapeshiftoss/types'
import { jupiterErrorNamesToTranslationKeys } from 'constants/errorMapping'
import type { TypedData } from 'eip-712'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslate } from 'react-polyglot'
Expand Down Expand Up @@ -133,6 +135,10 @@ export const useTradeExecution = (

const onFail = (e: unknown) => {
const message = (() => {
if (e instanceof SolanaLogsError) {
return translate(jupiterErrorNamesToTranslationKeys[e.name])
}

if (e instanceof ChainAdapterError) {
return translate(e.metadata.translation, e.metadata.options)
}
Expand Down
7 changes: 7 additions & 0 deletions src/constants/errorMapping.ts
Copy link
Contributor

@gomesalexandre gomesalexandre Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: <error> in values of JUPITER_ERROR_NAMES are the same as trade.errors.<error> (except for SlippageToleranceExceeded, see https://github.com/shapeshift/web/pull/8433/files#r1895898762) with a different casing only, we could use lodash/camelCase to avoid another mapping

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { JUPITER_ERROR_NAMES } from '@shapeshiftoss/swapper'

export const jupiterErrorNamesToTranslationKeys: Record<string, string> = {
[JUPITER_ERROR_NAMES.SLIPPAGE_TOLERANCE_EXCEEDED]: 'trade.errors.slippageExceeded',
[JUPITER_ERROR_NAMES.UNDER_MINIMUM_AMOUNT]: 'trade.errors.underMinimumAmount',
[JUPITER_ERROR_NAMES.CONSUMED_MORE_FEES]: 'trade.errors.consumedMoreFees',
}
6 changes: 6 additions & 0 deletions src/hooks/useErrorToast/useErrorToast.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useToast } from '@chakra-ui/react'
import { ChainAdapterError } from '@shapeshiftoss/chain-adapters'
import { SolanaLogsError } from '@shapeshiftoss/swapper'
import { jupiterErrorNamesToTranslationKeys } from 'constants/errorMapping'
import type { InterpolationOptions } from 'node-polyglot'
import { useCallback } from 'react'
import { useTranslate } from 'react-polyglot'
Expand All @@ -19,6 +21,10 @@ export const useErrorToast = () => {
errorMsgTranslationOptions?: InterpolationOptions,
) => {
const translationArgs = (() => {
if (error instanceof SolanaLogsError) {
return [jupiterErrorNamesToTranslationKeys[error.name]]
}

// Chain adapter errors take priority
if (error instanceof ChainAdapterError) {
return [error.metadata.translation, error.metadata.options]
Expand Down