From ea608861cfd577dea2681ac8c48f44f734be6ca4 Mon Sep 17 00:00:00 2001 From: tony Date: Wed, 15 Dec 2021 19:03:49 +0800 Subject: [PATCH 01/10] feat: add openocean --- .../Labs/components/SwapSettingDialog.tsx | 13 +++- .../SNSAdaptor/trader/TradeProviderIcon.tsx | 3 + .../mask/src/plugins/Trader/apis/index.ts | 1 + .../plugins/Trader/apis/openocean/index.ts | 43 ++++++++++ .../src/plugins/Trader/apis/trader/index.ts | 21 ++++- .../src/plugins/Trader/constants/openocean.ts | 11 +++ packages/mask/src/plugins/Trader/pipes.ts | 6 ++ packages/mask/src/plugins/Trader/settings.ts | 3 + .../trader/openocean/useSlippageTolerance.ts | 9 +++ .../Trader/trader/openocean/useTrade.ts | 65 ++++++++++++++++ .../trader/openocean/useTradeCallback.ts | 78 +++++++++++++++++++ .../trader/openocean/useTradeComputed.ts | 38 +++++++++ .../trader/openocean/useTradeGasLimit.ts | 27 +++++++ .../Trader/trader/useAllTradeComputed.ts | 12 +++ .../Trader/trader/useGetTradeContext.ts | 5 ++ .../plugins/Trader/trader/useTradeCallback.ts | 9 ++- .../plugins/Trader/trader/useTradeContext.ts | 5 ++ .../mask/src/plugins/Trader/types/index.ts | 1 + .../src/plugins/Trader/types/openocean.ts | 45 +++++++++++ packages/mask/src/resources/OpenOceanIcon.tsx | 32 ++++++++ packages/public-api/src/web.ts | 1 + packages/web3-constants/evm/trader.json | 28 +++++++ 22 files changed, 449 insertions(+), 7 deletions(-) create mode 100644 packages/mask/src/plugins/Trader/apis/openocean/index.ts create mode 100644 packages/mask/src/plugins/Trader/constants/openocean.ts create mode 100644 packages/mask/src/plugins/Trader/trader/openocean/useSlippageTolerance.ts create mode 100644 packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts create mode 100644 packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts create mode 100644 packages/mask/src/plugins/Trader/trader/openocean/useTradeComputed.ts create mode 100644 packages/mask/src/plugins/Trader/trader/openocean/useTradeGasLimit.ts create mode 100644 packages/mask/src/plugins/Trader/types/openocean.ts create mode 100644 packages/mask/src/resources/OpenOceanIcon.tsx diff --git a/packages/dashboard/src/pages/Labs/components/SwapSettingDialog.tsx b/packages/dashboard/src/pages/Labs/components/SwapSettingDialog.tsx index 62099f1d293a..458471fb451a 100644 --- a/packages/dashboard/src/pages/Labs/components/SwapSettingDialog.tsx +++ b/packages/dashboard/src/pages/Labs/components/SwapSettingDialog.tsx @@ -27,6 +27,7 @@ export default function SwapSettingDialog({ open, onClose }: SettingDialogProps) { label: 'Balancer', value: TradeProvider.BALANCER }, { label: 'DODO', value: TradeProvider.DODO }, { label: 'Bancor', value: TradeProvider.BANCOR }, + { label: 'OpenOcean', value: TradeProvider.OPENOCEAN }, ] const polygonOptions = [ @@ -34,6 +35,7 @@ export default function SwapSettingDialog({ open, onClose }: SettingDialogProps) { label: 'SushiSwap', value: TradeProvider.SUSHISWAP }, { label: '0x', value: TradeProvider.ZRX }, { label: 'DODO', value: TradeProvider.DODO }, + { label: 'OpenOcean', value: TradeProvider.OPENOCEAN }, ] const bscOptions = [ @@ -41,11 +43,18 @@ export default function SwapSettingDialog({ open, onClose }: SettingDialogProps) { label: 'SushiSwap', value: TradeProvider.SUSHISWAP }, { label: '0x', value: TradeProvider.ZRX }, { label: 'DODO', value: TradeProvider.DODO }, + { label: 'OpenOcean', value: TradeProvider.OPENOCEAN }, ] - const arbitrumOptions = [{ label: 'UniSwap V3', value: TradeProvider.UNISWAP_V3 }] + const arbitrumOptions = [ + { label: 'UniSwap V3', value: TradeProvider.UNISWAP_V3 }, + { label: 'OpenOcean', value: TradeProvider.OPENOCEAN }, + ] - const xDaiOptions = [{ label: 'SushiSwap', value: TradeProvider.SUSHISWAP }] + const xDaiOptions = [ + { label: 'SushiSwap', value: TradeProvider.SUSHISWAP }, + { label: 'OpenOcean', value: TradeProvider.OPENOCEAN }, + ] const t = useDashboardI18N() diff --git a/packages/mask/src/plugins/Trader/SNSAdaptor/trader/TradeProviderIcon.tsx b/packages/mask/src/plugins/Trader/SNSAdaptor/trader/TradeProviderIcon.tsx index 1edffc16c22f..422b3e44e89d 100644 --- a/packages/mask/src/plugins/Trader/SNSAdaptor/trader/TradeProviderIcon.tsx +++ b/packages/mask/src/plugins/Trader/SNSAdaptor/trader/TradeProviderIcon.tsx @@ -8,6 +8,7 @@ import { SushiSwapIcon } from '../../../../resources/SushiSwapIcon' import { UniswapIcon } from '../../../../resources/UniswapIcon' import { ZRXIcon } from '../../../../resources/ZRXIcon' import { DODOIcon } from '../../../../resources/DODOIcon' +import { OpenOceanIcon } from '../../../../resources/OpenOceanIcon' import { resolveTradeProviderName } from '../../pipes' const quickswapIcon = new URL('../../../../resources/quickswap.png', import.meta.url).toString() @@ -59,6 +60,8 @@ export function TradeProviderIcon(props: TradeProviderIconProps) { return case TradeProvider.BANCOR: return + case TradeProvider.OPENOCEAN: + return default: unreachable(props.provider) } diff --git a/packages/mask/src/plugins/Trader/apis/index.ts b/packages/mask/src/plugins/Trader/apis/index.ts index 686bb84b62f4..ed4fa7e0fd63 100644 --- a/packages/mask/src/plugins/Trader/apis/index.ts +++ b/packages/mask/src/plugins/Trader/apis/index.ts @@ -6,3 +6,4 @@ export * from './blocks' export * from './LBP' export * from './dodo' export * from './bancor' +export * from './openocean' diff --git a/packages/mask/src/plugins/Trader/apis/openocean/index.ts b/packages/mask/src/plugins/Trader/apis/openocean/index.ts new file mode 100644 index 000000000000..7bea4c175ca9 --- /dev/null +++ b/packages/mask/src/plugins/Trader/apis/openocean/index.ts @@ -0,0 +1,43 @@ +import type { SwapOOData, SwapOORequest } from '../../types/openocean' +import { OPENOCEAN_BASE_URL } from '../../constants/openocean' +import BigNumber from 'bignumber.js' +import { pow10 } from '@masknet/web3-shared-base' +import urlcat from 'urlcat' + +export async function swapOO(request: SwapOORequest) { + const response = await fetch( + urlcat(OPENOCEAN_BASE_URL, `/${request.chainId}/swap`, { + inTokenSymbol: request.toToken?.symbol, + inTokenAddress: request.fromToken?.address, + outTokenSymbol: request.toToken?.symbol, + outTokenAddress: request.toToken?.address, + amount: request.fromAmount, + gasPrice: 5000000000, + slippage: request.slippage, + disabledDexIds: '', + account: request.userAddr, + }), + ) + const payload = await response.json() + // if (payload.status !== 200) { + // throw new Error((payload as SwapOOErrorResponse).data ?? 'Unknown Error') + // } + const { data, outAmount, minOutAmount, to, value } = payload + const _resAmount = new BigNumber(outAmount).dividedBy(pow10(request.toToken.decimals ?? 0)).toNumber() + const _fromAmount = new BigNumber(request.fromAmount).dividedBy(pow10(request.fromToken.decimals ?? 0)).toNumber() + return { + data, + targetApproveAddr: request.fromToken.address, + targetDecimals: request.fromToken.decimals, + resAmount: _resAmount, + fromAmount: _fromAmount, + resPricePerFromToken: +(_fromAmount / _resAmount).toFixed(8), + resPricePerToToken: +(_resAmount / _fromAmount).toFixed(8), + to, + value, + slippage: request.slippage, + fromTokenSymbol: request.fromToken.symbol, + toTokenSymbol: request.toToken.symbol, + minOutAmount, + } as SwapOOData +} diff --git a/packages/mask/src/plugins/Trader/apis/trader/index.ts b/packages/mask/src/plugins/Trader/apis/trader/index.ts index b9ba608d5120..7e76a5a39655 100644 --- a/packages/mask/src/plugins/Trader/apis/trader/index.ts +++ b/packages/mask/src/plugins/Trader/apis/trader/index.ts @@ -16,15 +16,28 @@ export async function getAvailableTraderProviders(chainId: ChainId) { TradeProvider.BALANCER, TradeProvider.DODO, TradeProvider.BANCOR, + TradeProvider.OPENOCEAN, ] case NetworkType.Polygon: - return [TradeProvider.QUICKSWAP, TradeProvider.SUSHISWAP, TradeProvider.DODO, TradeProvider.ZRX] + return [ + TradeProvider.QUICKSWAP, + TradeProvider.SUSHISWAP, + TradeProvider.DODO, + TradeProvider.ZRX, + TradeProvider.OPENOCEAN, + ] case NetworkType.Binance: - return [TradeProvider.PANCAKESWAP, TradeProvider.SUSHISWAP, TradeProvider.DODO, TradeProvider.ZRX] + return [ + TradeProvider.PANCAKESWAP, + TradeProvider.SUSHISWAP, + TradeProvider.DODO, + TradeProvider.ZRX, + TradeProvider.OPENOCEAN, + ] case NetworkType.Arbitrum: - return [TradeProvider.UNISWAP_V3] + return [TradeProvider.UNISWAP_V3, TradeProvider.OPENOCEAN] case NetworkType.xDai: - return [TradeProvider.SUSHISWAP] + return [TradeProvider.SUSHISWAP, TradeProvider.OPENOCEAN] default: safeUnreachable(networkType) return [] diff --git a/packages/mask/src/plugins/Trader/constants/openocean.ts b/packages/mask/src/plugins/Trader/constants/openocean.ts new file mode 100644 index 000000000000..8c8b1f27790f --- /dev/null +++ b/packages/mask/src/plugins/Trader/constants/openocean.ts @@ -0,0 +1,11 @@ +import { NetworkType } from '@masknet/web3-shared-evm' + +export const OPENOCEAN_BASE_URL = 'https://ethapi.openocean.finance/v2/' + +export const networkNames: Record = { + [NetworkType.Ethereum]: 'eth', + [NetworkType.Binance]: 'bsc', + [NetworkType.Polygon]: 'polygon', + [NetworkType.Arbitrum]: 'arbitrum', + [NetworkType.xDai]: 'xdai', +} diff --git a/packages/mask/src/plugins/Trader/pipes.ts b/packages/mask/src/plugins/Trader/pipes.ts index 432b56a9b5b8..96703d73f8a4 100644 --- a/packages/mask/src/plugins/Trader/pipes.ts +++ b/packages/mask/src/plugins/Trader/pipes.ts @@ -56,6 +56,7 @@ export const resolveTradeProviderName = createLookupTableResolver { throw new Error(`Unknown provider type: ${tradeProvider}`) @@ -98,6 +99,8 @@ export function resolveTradeProviderLink(tradeProvider: TradeProvider, networkTy return 'https://app.dodoex.io' case TradeProvider.BANCOR: return 'https://app.bancor.network/eth/swap' + case TradeProvider.OPENOCEAN: + return 'https://openocean.finance/classic' default: unreachable(tradeProvider) } @@ -149,6 +152,9 @@ export function resolveTradePairLink(tradeProvider: TradeProvider, address: stri case TradeProvider.BANCOR: // TODO - Bancor analytics should be available with V3 return `` + case TradeProvider.OPENOCEAN: + // TODO - OpenOcean + return `` default: unreachable(tradeProvider) } diff --git a/packages/mask/src/plugins/Trader/settings.ts b/packages/mask/src/plugins/Trader/settings.ts index 1373bd750078..fc9804c62a7b 100644 --- a/packages/mask/src/plugins/Trader/settings.ts +++ b/packages/mask/src/plugins/Trader/settings.ts @@ -92,6 +92,7 @@ const pancakeswapSettings = createInternalSettings(`${PLUGIN_IDENTIFIER} const balancerSettings = createInternalSettings(`${PLUGIN_IDENTIFIER}+tradeProvider+balancer`, '') const dodoSettings = createInternalSettings(`${PLUGIN_IDENTIFIER}+tradeProvider+dodo`, '') const bancorSettings = createInternalSettings(`${PLUGIN_IDENTIFIER}+tradeProvider+bancor`, '') +const openoceanSettings = createInternalSettings(`${PLUGIN_IDENTIFIER}+tradeProvider+openocean`, '') /** * The general settings of specific tarde provider @@ -118,6 +119,8 @@ export function getCurrentTradeProviderGeneralSettings(tradeProvider: TradeProvi return dodoSettings case TradeProvider.BANCOR: return bancorSettings + case TradeProvider.OPENOCEAN: + return openoceanSettings default: unreachable(tradeProvider) } diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useSlippageTolerance.ts b/packages/mask/src/plugins/Trader/trader/openocean/useSlippageTolerance.ts new file mode 100644 index 000000000000..f54692e3703f --- /dev/null +++ b/packages/mask/src/plugins/Trader/trader/openocean/useSlippageTolerance.ts @@ -0,0 +1,9 @@ +import { clamp } from 'lodash-unified' +import { useValueRef } from '@masknet/shared' +import { SLIPPAGE_MAX, SLIPPAGE_MIN } from '../../constants' +import { currentSlippageSettings } from '../../settings' + +export function useSlippageTolerance() { + const slippage_ = useValueRef(currentSlippageSettings) + return clamp(slippage_, SLIPPAGE_MIN, SLIPPAGE_MAX) +} diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts b/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts new file mode 100644 index 000000000000..1b8037b9832e --- /dev/null +++ b/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts @@ -0,0 +1,65 @@ +import { + FungibleTokenDetailed, + isNative, + useAccount, + useBlockNumber, + useChainId, + useRPCConstants, + useTokenConstants, + useTraderConstants, +} from '@masknet/web3-shared-evm' +import { useAsyncRetry } from 'react-use' +import { PluginTraderRPC } from '../../messages' +import type { TradeStrategy } from '../../types' +import { useSlippageTolerance } from './useSlippageTolerance' +import { first } from 'lodash-unified' + +export function useTrade( + strategy: TradeStrategy, + inputAmount: string, + outputAmount: string, + inputToken?: FungibleTokenDetailed, + outputToken?: FungibleTokenDetailed, +) { + const { NATIVE_TOKEN_ADDRESS } = useTokenConstants() + const blockNumber = useBlockNumber() + const slippage = useSlippageTolerance() + const chainId = useChainId() + const { RPC } = useRPCConstants(chainId) + const providerURL = first(RPC) + const { OPENOCEAN_ETH_ADDRESS } = useTraderConstants(chainId) + const account = useAccount() + + return useAsyncRetry(async () => { + if (!inputToken || !outputToken) return null + if (inputAmount === '0') return null + const sellToken = isNative(inputToken.address) + ? { ...inputToken, address: OPENOCEAN_ETH_ADDRESS ?? '' } + : inputToken + const buyToken = isNative(outputToken.address) + ? { ...outputToken, address: OPENOCEAN_ETH_ADDRESS ?? '' } + : outputToken + return PluginTraderRPC.swapOO({ + isNativeSellToken: isNative(inputToken.address), + fromToken: sellToken, + toToken: buyToken, + fromAmount: inputAmount, + slippage, + userAddr: account, + rpc: providerURL, + chainId, + }) + }, [ + NATIVE_TOKEN_ADDRESS, + strategy, + inputAmount, + outputAmount, + inputToken?.address, + outputToken?.address, + slippage, + blockNumber, // refresh api each block + account, + providerURL, + chainId, + ]) +} diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts b/packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts new file mode 100644 index 000000000000..cb6de4b6f5b7 --- /dev/null +++ b/packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts @@ -0,0 +1,78 @@ +import { useCallback, useMemo, useState } from 'react' +import stringify from 'json-stable-stringify' +import { pick } from 'lodash-unified' +import type { TransactionConfig } from 'web3-core' +import { TransactionState, TransactionStateType, useAccount, useChainId, useWeb3 } from '@masknet/web3-shared-evm' +import type { SwapOOSuccessResponse, TradeComputed } from '../../types' + +export function useTradeCallback(tradeComputed: TradeComputed | null) { + const web3 = useWeb3() + const account = useAccount() + const chainId = useChainId() + const [tradeState, setTradeState] = useState({ + type: TransactionStateType.UNKNOWN, + }) + + // compose transaction config + const config = useMemo(() => { + if (!account || !tradeComputed?.trade_) return null + return { + from: account, + ...pick(tradeComputed.trade_, ['to', 'data', 'value']), + } as TransactionConfig + }, [account, tradeComputed]) + + const tradeCallback = useCallback(async () => { + // validate config + if (!account || !config) { + setTradeState({ + type: TransactionStateType.UNKNOWN, + }) + return + } + + // start waiting for provider to confirm tx + setTradeState({ + type: TransactionStateType.WAIT_FOR_CONFIRMING, + }) + + // compose transaction config + const config_ = { + ...config, + gas: await web3.eth.estimateGas(config).catch((error) => { + setTradeState({ + type: TransactionStateType.FAILED, + error, + }) + throw error + }), + } + + // send transaction and wait for hash + return new Promise((resolve, reject) => { + web3.eth.sendTransaction(config_, (error, hash) => { + if (error) { + setTradeState({ + type: TransactionStateType.FAILED, + error, + }) + reject(error) + } else { + setTradeState({ + type: TransactionStateType.HASH, + hash, + }) + resolve(hash) + } + }) + }) + }, [web3, account, chainId, stringify(config)]) + + const resetCallback = useCallback(() => { + setTradeState({ + type: TransactionStateType.UNKNOWN, + }) + }, []) + + return [tradeState, tradeCallback, resetCallback] as const +} diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useTradeComputed.ts b/packages/mask/src/plugins/Trader/trader/openocean/useTradeComputed.ts new file mode 100644 index 000000000000..f91027c64583 --- /dev/null +++ b/packages/mask/src/plugins/Trader/trader/openocean/useTradeComputed.ts @@ -0,0 +1,38 @@ +import BigNumber from 'bignumber.js' +import { useMemo } from 'react' +import type { FungibleTokenDetailed } from '@masknet/web3-shared-evm' +import { ZERO, pow10 } from '@masknet/web3-shared-base' +import { SwapOOData, TradeComputed, TradeStrategy } from '../../types' + +export function useTradeComputed( + trade: SwapOOData | null, + strategy: TradeStrategy, + inputToken?: FungibleTokenDetailed, + outputToken?: FungibleTokenDetailed, +) { + return useMemo(() => { + if (!trade) return null + if (!inputToken || !outputToken) return null + const isExactIn = strategy === TradeStrategy.ExactIn + if (!isExactIn) return null + const inputAmount = new BigNumber(trade.fromAmount).multipliedBy(pow10(inputToken.decimals)).integerValue() + const executionPrice = new BigNumber(trade.resPricePerToToken) + const outputAmount = new BigNumber(trade.resAmount).multipliedBy(pow10(outputToken.decimals)).integerValue() + const priceImpact = new BigNumber(trade.priceImpact) + return { + strategy, + inputToken, + outputToken, + inputAmount, + outputAmount, + executionPrice, + fee: ZERO, + maximumSold: inputAmount, + minimumReceived: new BigNumber(trade.minOutAmount), + // minimumProtocolFee + priceImpact, + + trade_: { ...trade }, + } as TradeComputed + }, [trade, strategy, inputToken, outputToken]) +} diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useTradeGasLimit.ts b/packages/mask/src/plugins/Trader/trader/openocean/useTradeGasLimit.ts new file mode 100644 index 000000000000..6173ce860c80 --- /dev/null +++ b/packages/mask/src/plugins/Trader/trader/openocean/useTradeGasLimit.ts @@ -0,0 +1,27 @@ +import type { SwapRouteData, TradeComputed } from '../../types' +import { useMemo } from 'react' +import { useAccount, useWeb3 } from '@masknet/web3-shared-evm' +import { TargetChainIdContext } from '../useTargetChainIdContext' +import { pick } from 'lodash-unified' +import type { TransactionConfig } from 'web3-core' +import { useAsync } from 'react-use' +import type { AsyncState } from 'react-use/lib/useAsyncFn' + +export function useTradeGasLimit(tradeComputed: TradeComputed | null): AsyncState { + const { targetChainId } = TargetChainIdContext.useContainer() + + const web3 = useWeb3(false, targetChainId) + const account = useAccount() + const config = useMemo(() => { + if (!account || !tradeComputed?.trade_) return null + return { + from: account, + ...pick(tradeComputed.trade_, ['to', 'data', 'value']), + } as TransactionConfig + }, [account, tradeComputed]) + + return useAsync(async () => { + if (!config) return 0 + return web3.eth.estimateGas(config) + }, [config, web3]) +} diff --git a/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts b/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts index bb42bb019a60..482a209b7c42 100644 --- a/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts +++ b/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts @@ -18,6 +18,8 @@ import { useTradeGasLimit as useDODOTradeGasLimit } from './dodo/useTradeGasLimi import { useTrade as useBancorTrade } from './bancor/useTrade' import { useTradeComputed as useBancorTradeComputed } from './bancor/useTradeComputed' import { useTradeGasLimit as useBancorTradeGasLimit } from './bancor/useTradeGasLimit' +import { useTradeComputed as useOpenOceanTradeComputed } from './openocean/useTradeComputed' +import { useTrade as useOpenOceanTrade } from './openocean/useTrade' import { TradeProvider } from '@masknet/public-api' import { useAvailableTraderProviders } from '../trending/useAvailableTraderProviders' import { useNativeTradeGasLimit } from './useNativeTradeGasLimit' @@ -176,6 +178,15 @@ export function useAllTradeComputed( const bancorSwapEstimateGas = useBancorTradeGasLimit(bancor) + // openocean + const openocean_ = useOpenOceanTrade(TradeStrategy.ExactIn, inputAmount_, '0', inputToken, outputToken) + const openocean = useOpenOceanTradeComputed( + openocean_.value ?? null, + TradeStrategy.ExactIn, + inputToken, + outputToken, + ) + const allTradeResult = [ { provider: TradeProvider.UNISWAP_V2, ...uniswapV2_, value: uniswapV2, gas: uniswapEstimateGas }, { provider: TradeProvider.SUSHISWAP, ...sushiSwap_, value: sushiSwap, gas: sushiSwapEstimateGas }, @@ -187,6 +198,7 @@ export function useAllTradeComputed( { provider: TradeProvider.BALANCER, ...balancer_, value: balancer, gas: balancerSwapEstimateGas }, { provider: TradeProvider.DODO, ...dodo_, value: dodo, gas: dodoSwapEstimateGas }, { provider: TradeProvider.BANCOR, ...bancor_, value: bancor, gas: bancorSwapEstimateGas }, + { provider: TradeProvider.OPENOCEAN, ...openocean_, value: openocean, gas: bancorSwapEstimateGas }, ] return nativeToken_.value diff --git a/packages/mask/src/plugins/Trader/trader/useGetTradeContext.ts b/packages/mask/src/plugins/Trader/trader/useGetTradeContext.ts index c0eb7e4df671..b9eea9226d02 100644 --- a/packages/mask/src/plugins/Trader/trader/useGetTradeContext.ts +++ b/packages/mask/src/plugins/Trader/trader/useGetTradeContext.ts @@ -113,6 +113,11 @@ export function useGetTradeContext(tradeProvider?: TradeProvider) { TYPE: tradeProvider, ROUTER_CONTRACT_ADDRESS: getTraderConstants(chainId).BANCOR_EXCHANGE_PROXY_ADDRESS, } + case TradeProvider.OPENOCEAN: + return { + TYPE: tradeProvider, + ROUTER_CONTRACT_ADDRESS: getTraderConstants(chainId).BANCOR_EXCHANGE_PROXY_ADDRESS, + } default: if (tradeProvider) unreachable(tradeProvider) return null diff --git a/packages/mask/src/plugins/Trader/trader/useTradeCallback.ts b/packages/mask/src/plugins/Trader/trader/useTradeCallback.ts index 5994a0906bcd..9ebd4c42cb4a 100644 --- a/packages/mask/src/plugins/Trader/trader/useTradeCallback.ts +++ b/packages/mask/src/plugins/Trader/trader/useTradeCallback.ts @@ -9,6 +9,7 @@ import type { SwapBancorRequest, SwapRouteSuccessResponse, TradeComputed, + SwapOOSuccessResponse, } from '../types' import { useTradeCallback as useNativeTokenWrapperCallback } from './native/useTradeCallback' import { useTradeCallback as useZrxCallback } from './0x/useTradeCallback' @@ -16,6 +17,7 @@ import { useTradeCallback as useUniswapCallback } from './uniswap/useTradeCallba import { useTradeCallback as useBalancerCallback } from './balancer/useTradeCallback' import { useTradeCallback as useDODOCallback } from './dodo/useTradeCallback' import { useTradeCallback as useBancorCallback } from './bancor/useTradeCallback' +import { useTradeCallback as useOpenOceanCallback } from './openocean/useTradeCallback' import { useExchangeProxyContract } from '../contracts/balancer/useExchangeProxyContract' import type { NativeTokenWrapper } from './native/useTradeComputed' import { isNativeTokenWrapper } from '../helpers' @@ -48,7 +50,9 @@ export function useTradeCallback( ? (tradeComputed as TradeComputed) : null const tradeComputedForBancor = !isNativeTokenWrapper_ ? (tradeComputed as TradeComputed) : null - + const tradeComputedForOpenOcean = !isNativeTokenWrapper_ + ? (tradeComputed as TradeComputed) + : null // uniswap like providers const uniswapV2Like = useUniswapCallback(tradeComputedForUniswapV2Like, provider, gasConfig) const uniswapV3Like = useUniswapCallback(tradeComputedForUniswapV3Like, provider, gasConfig) @@ -66,6 +70,7 @@ export function useTradeCallback( const zrx = useZrxCallback(provider === TradeProvider.ZRX ? tradeComputedForZRX : null, gasConfig) const dodo = useDODOCallback(provider === TradeProvider.DODO ? tradeComputedForDODO : null, gasConfig) const bancor = useBancorCallback(provider === TradeProvider.BANCOR ? tradeComputedForBancor : null, gasConfig) + const openocean = useOpenOceanCallback(provider === TradeProvider.OPENOCEAN ? tradeComputedForOpenOcean : null) // the trade is an ETH-WETH pair const nativeTokenWrapper = useNativeTokenWrapperCallback( @@ -96,6 +101,8 @@ export function useTradeCallback( return dodo case TradeProvider.BANCOR: return bancor + case TradeProvider.OPENOCEAN: + return openocean default: if (provider) unreachable(provider) return [] diff --git a/packages/mask/src/plugins/Trader/trader/useTradeContext.ts b/packages/mask/src/plugins/Trader/trader/useTradeContext.ts index b5b6dfc7f350..6aa3cdfb1df1 100644 --- a/packages/mask/src/plugins/Trader/trader/useTradeContext.ts +++ b/packages/mask/src/plugins/Trader/trader/useTradeContext.ts @@ -114,6 +114,11 @@ export function useTradeContext(tradeProvider: TradeProvider) { TYPE: tradeProvider, ROUTER_CONTRACT_ADDRESS: getTraderConstants(chainId).BANCOR_EXCHANGE_PROXY_ADDRESS, } + case TradeProvider.OPENOCEAN: + return { + TYPE: tradeProvider, + ROUTER_CONTRACT_ADDRESS: getTraderConstants(chainId).OPENOCEAN_EXCHANGE_PROXY_ADDRESS, + } default: unreachable(tradeProvider) } diff --git a/packages/mask/src/plugins/Trader/types/index.ts b/packages/mask/src/plugins/Trader/types/index.ts index 776dc3316315..bcb516e55046 100644 --- a/packages/mask/src/plugins/Trader/types/index.ts +++ b/packages/mask/src/plugins/Trader/types/index.ts @@ -5,3 +5,4 @@ export * from './dodo' export * from './trader' export * from './trending' export * from './bancor' +export * from './openocean' diff --git a/packages/mask/src/plugins/Trader/types/openocean.ts b/packages/mask/src/plugins/Trader/types/openocean.ts new file mode 100644 index 000000000000..5875abdf78f8 --- /dev/null +++ b/packages/mask/src/plugins/Trader/types/openocean.ts @@ -0,0 +1,45 @@ +import type { FungibleTokenDetailed } from '@masknet/web3-shared-evm' + +export interface SwapOORequest { + isNativeSellToken: boolean + fromToken: FungibleTokenDetailed + toToken: FungibleTokenDetailed + fromAmount: string + slippage: number + userAddr?: string + rpc?: string + chainId: number +} + +export type SwapOOResponse = SwapOOSuccessResponse | SwapOOErrorResponse + +export interface SwapOOSuccessResponse { + code: number + status: 200 + data: SwapOOData +} + +export interface SwapOOErrorResponse { + code: number + status: number + data: string | undefined +} + +export interface SwapOOData { + data: string + priceImpact: number + resAmount: number + resCostGas: number + resPricePerFromToken: number + resPricePerToToken: number + targetApproveAddr: string + targetDecimals: number + to: string + useSource: string + fromAmount: number + value: string + slippage: number + fromTokenSymbol: string + toTokenSymbol: string + minOutAmount: number +} diff --git a/packages/mask/src/resources/OpenOceanIcon.tsx b/packages/mask/src/resources/OpenOceanIcon.tsx new file mode 100644 index 000000000000..74e470ab9d23 --- /dev/null +++ b/packages/mask/src/resources/OpenOceanIcon.tsx @@ -0,0 +1,32 @@ +import { SvgIconProps, SvgIcon } from '@mui/material' + +const svg = ( + + Fill-1 Clipped + Created with Sketch. + + + + + + + + + + + + + + + +) + +export function OpenOceanIcon(props: SvgIconProps) { + return {svg} +} diff --git a/packages/public-api/src/web.ts b/packages/public-api/src/web.ts index fb9aaeb03303..1cd77bcc010b 100644 --- a/packages/public-api/src/web.ts +++ b/packages/public-api/src/web.ts @@ -210,6 +210,7 @@ export enum TradeProvider { DODO = 7, UNISWAP_V3 = 8, BANCOR = 9, + OPENOCEAN = 10, } /** Supported language settings */ export enum LanguageOptions { diff --git a/packages/web3-constants/evm/trader.json b/packages/web3-constants/evm/trader.json index f9b466a0d1dc..35d64c975900 100644 --- a/packages/web3-constants/evm/trader.json +++ b/packages/web3-constants/evm/trader.json @@ -446,5 +446,33 @@ "Arbitrum": "", "Arbitrum_Rinkeby": "", "xDai": "" + }, + "OPENOCEAN_ETH_ADDRESS": { + "Mainnet": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + "Ropsten": "", + "Rinkeby": "", + "Kovan": "", + "Gorli": "", + "BSC": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + "BSCT": "", + "Matic": "0x0000000000000000000000000000000000001010", + "Mumbai": "", + "Arbitrum": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + "Arbitrum_Rinkeby": "", + "xDai": "0x0000000000000000000000000000000000000000" + }, + "OPENOCEAN_EXCHANGE_PROXY_ADDRESS": { + "Mainnet": "0x6352a56caadC4F1E25CD6c75970Fa768A3304e64", + "Ropsten": "", + "Rinkeby": "", + "Kovan": "", + "Gorli": "", + "BSC": "0x6352a56caadC4F1E25CD6c75970Fa768A3304e64", + "BSCT": "", + "Matic": "0x6352a56caadc4f1e25cd6c75970fa768a3304e64", + "Mumbai": "", + "Arbitrum": "0x6352a56caadc4f1e25cd6c75970fa768a3304e64", + "Arbitrum_Rinkeby": "", + "xDai": "0x6352a56caadC4F1E25CD6c75970Fa768A3304e64" } } From 7118c806da2c30dd22238cfd9b7477554c35c8eb Mon Sep 17 00:00:00 2001 From: tony Date: Thu, 16 Dec 2021 10:00:09 +0800 Subject: [PATCH 02/10] fix: use leftShift --- .../mask/src/plugins/Trader/apis/openocean/index.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/mask/src/plugins/Trader/apis/openocean/index.ts b/packages/mask/src/plugins/Trader/apis/openocean/index.ts index 7bea4c175ca9..2482947ec9e1 100644 --- a/packages/mask/src/plugins/Trader/apis/openocean/index.ts +++ b/packages/mask/src/plugins/Trader/apis/openocean/index.ts @@ -1,10 +1,9 @@ import type { SwapOOData, SwapOORequest } from '../../types/openocean' import { OPENOCEAN_BASE_URL } from '../../constants/openocean' -import BigNumber from 'bignumber.js' -import { pow10 } from '@masknet/web3-shared-base' +import { leftShift } from '@masknet/web3-shared-base' import urlcat from 'urlcat' -export async function swapOO(request: SwapOORequest) { +export async function swapOO(request: SwapOORequest): Promise { const response = await fetch( urlcat(OPENOCEAN_BASE_URL, `/${request.chainId}/swap`, { inTokenSymbol: request.toToken?.symbol, @@ -23,8 +22,10 @@ export async function swapOO(request: SwapOORequest) { // throw new Error((payload as SwapOOErrorResponse).data ?? 'Unknown Error') // } const { data, outAmount, minOutAmount, to, value } = payload - const _resAmount = new BigNumber(outAmount).dividedBy(pow10(request.toToken.decimals ?? 0)).toNumber() - const _fromAmount = new BigNumber(request.fromAmount).dividedBy(pow10(request.fromToken.decimals ?? 0)).toNumber() + // const _resAmount = new BigNumber(outAmount).dividedBy(pow10(request.toToken.decimals ?? 0)).toNumber() + // const _fromAmount = new BigNumber(request.fromAmount).dividedBy(pow10(request.fromToken.decimals ?? 0)).toNumber() + const _resAmount = leftShift(outAmount, request.toToken.decimals).toNumber() + const _fromAmount = leftShift(request.fromAmount, request.fromToken.decimals).toNumber() return { data, targetApproveAddr: request.fromToken.address, From 4c471d5e316f05e70f0891ddc56305c906c8b8f8 Mon Sep 17 00:00:00 2001 From: tony Date: Thu, 16 Dec 2021 10:10:07 +0800 Subject: [PATCH 03/10] fix: add openocean to ignoreWords --- cspell.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cspell.json b/cspell.json index 3b35105fa48d..8133121288ba 100644 --- a/cspell.json +++ b/cspell.json @@ -281,6 +281,8 @@ "crwdns", "dodoapi", "getdodoroute", + "openocean", + "OPENOCEAN", "getx", "hookform", "idiv", From 9cfc849abfc93c4f49d06192f02c7603433696d8 Mon Sep 17 00:00:00 2001 From: tony Date: Thu, 16 Dec 2021 11:48:01 +0800 Subject: [PATCH 04/10] fix: remove annotation --- packages/mask/src/plugins/Trader/apis/openocean/index.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/mask/src/plugins/Trader/apis/openocean/index.ts b/packages/mask/src/plugins/Trader/apis/openocean/index.ts index 2482947ec9e1..92b8443b25eb 100644 --- a/packages/mask/src/plugins/Trader/apis/openocean/index.ts +++ b/packages/mask/src/plugins/Trader/apis/openocean/index.ts @@ -18,12 +18,7 @@ export async function swapOO(request: SwapOORequest): Promise { }), ) const payload = await response.json() - // if (payload.status !== 200) { - // throw new Error((payload as SwapOOErrorResponse).data ?? 'Unknown Error') - // } const { data, outAmount, minOutAmount, to, value } = payload - // const _resAmount = new BigNumber(outAmount).dividedBy(pow10(request.toToken.decimals ?? 0)).toNumber() - // const _fromAmount = new BigNumber(request.fromAmount).dividedBy(pow10(request.fromToken.decimals ?? 0)).toNumber() const _resAmount = leftShift(outAmount, request.toToken.decimals).toNumber() const _fromAmount = leftShift(request.fromAmount, request.fromToken.decimals).toNumber() return { From 9d63fdd550bea497fd3bd7dcdfbd0490aedaccea Mon Sep 17 00:00:00 2001 From: tony Date: Tue, 21 Dec 2021 14:53:19 +0800 Subject: [PATCH 05/10] fix: clear openoceanIcon properties --- packages/mask/src/resources/OpenOceanIcon.tsx | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/packages/mask/src/resources/OpenOceanIcon.tsx b/packages/mask/src/resources/OpenOceanIcon.tsx index 74e470ab9d23..8af955de587e 100644 --- a/packages/mask/src/resources/OpenOceanIcon.tsx +++ b/packages/mask/src/resources/OpenOceanIcon.tsx @@ -1,28 +1,12 @@ import { SvgIconProps, SvgIcon } from '@mui/material' const svg = ( - - Fill-1 Clipped - Created with Sketch. - - - - - - - - - - - - - + + + ) From d888cbd3b52751016e7d3c792dbfdb1b7e707622 Mon Sep 17 00:00:00 2001 From: zhouhanseng Date: Thu, 30 Dec 2021 12:38:35 +0800 Subject: [PATCH 06/10] fix: conflict --- .../mask/src/plugins/Trader/trader/openocean/useTrade.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts b/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts index 1b8037b9832e..89ced2ea37ee 100644 --- a/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts +++ b/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts @@ -1,6 +1,6 @@ import { FungibleTokenDetailed, - isNative, + isNativeTokenAddress, useAccount, useBlockNumber, useChainId, @@ -33,14 +33,14 @@ export function useTrade( return useAsyncRetry(async () => { if (!inputToken || !outputToken) return null if (inputAmount === '0') return null - const sellToken = isNative(inputToken.address) + const sellToken = isNativeTokenAddress(inputToken.address) ? { ...inputToken, address: OPENOCEAN_ETH_ADDRESS ?? '' } : inputToken - const buyToken = isNative(outputToken.address) + const buyToken = isNativeTokenAddress(outputToken.address) ? { ...outputToken, address: OPENOCEAN_ETH_ADDRESS ?? '' } : outputToken return PluginTraderRPC.swapOO({ - isNativeSellToken: isNative(inputToken.address), + isNativeSellToken: isNativeTokenAddress(inputToken.address), fromToken: sellToken, toToken: buyToken, fromAmount: inputAmount, From ad2eee58777222a87d97f12cb314be6e32529cfe Mon Sep 17 00:00:00 2001 From: zhouhanseng Date: Thu, 30 Dec 2021 12:40:48 +0800 Subject: [PATCH 07/10] fix: conflict --- packages/mask/src/plugins/Trader/constants/openocean.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/mask/src/plugins/Trader/constants/openocean.ts b/packages/mask/src/plugins/Trader/constants/openocean.ts index 8c8b1f27790f..e3412435e2bc 100644 --- a/packages/mask/src/plugins/Trader/constants/openocean.ts +++ b/packages/mask/src/plugins/Trader/constants/openocean.ts @@ -8,4 +8,6 @@ export const networkNames: Record = { [NetworkType.Polygon]: 'polygon', [NetworkType.Arbitrum]: 'arbitrum', [NetworkType.xDai]: 'xdai', + [NetworkType.Celo]: 'celo', + [NetworkType.Fantom]: 'fantom', } From 07eaf2897dc4cb906d5769dc7656c66f3f449d8b Mon Sep 17 00:00:00 2001 From: zhouhanseng Date: Thu, 30 Dec 2021 14:01:26 +0800 Subject: [PATCH 08/10] chore: qa --- .../plugins/Trader/trader/dodo/useTradeGasLimit.ts | 3 +-- .../src/plugins/Trader/trader/openocean/useTrade.ts | 12 ++++++------ .../src/plugins/Trader/trader/useAllTradeComputed.ts | 4 +++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/mask/src/plugins/Trader/trader/dodo/useTradeGasLimit.ts b/packages/mask/src/plugins/Trader/trader/dodo/useTradeGasLimit.ts index 6173ce860c80..fbd80ff11a33 100644 --- a/packages/mask/src/plugins/Trader/trader/dodo/useTradeGasLimit.ts +++ b/packages/mask/src/plugins/Trader/trader/dodo/useTradeGasLimit.ts @@ -9,8 +9,7 @@ import type { AsyncState } from 'react-use/lib/useAsyncFn' export function useTradeGasLimit(tradeComputed: TradeComputed | null): AsyncState { const { targetChainId } = TargetChainIdContext.useContainer() - - const web3 = useWeb3(false, targetChainId) + const web3 = useWeb3(true, targetChainId) const account = useAccount() const config = useMemo(() => { if (!account || !tradeComputed?.trade_) return null diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts b/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts index 89ced2ea37ee..960a788ce0eb 100644 --- a/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts +++ b/packages/mask/src/plugins/Trader/trader/openocean/useTrade.ts @@ -3,7 +3,6 @@ import { isNativeTokenAddress, useAccount, useBlockNumber, - useChainId, useRPCConstants, useTokenConstants, useTraderConstants, @@ -11,6 +10,7 @@ import { import { useAsyncRetry } from 'react-use' import { PluginTraderRPC } from '../../messages' import type { TradeStrategy } from '../../types' +import { TargetChainIdContext } from '../useTargetChainIdContext' import { useSlippageTolerance } from './useSlippageTolerance' import { first } from 'lodash-unified' @@ -24,10 +24,10 @@ export function useTrade( const { NATIVE_TOKEN_ADDRESS } = useTokenConstants() const blockNumber = useBlockNumber() const slippage = useSlippageTolerance() - const chainId = useChainId() - const { RPC } = useRPCConstants(chainId) + const { targetChainId } = TargetChainIdContext.useContainer() + const { RPC } = useRPCConstants(targetChainId) const providerURL = first(RPC) - const { OPENOCEAN_ETH_ADDRESS } = useTraderConstants(chainId) + const { OPENOCEAN_ETH_ADDRESS } = useTraderConstants(targetChainId) const account = useAccount() return useAsyncRetry(async () => { @@ -47,7 +47,7 @@ export function useTrade( slippage, userAddr: account, rpc: providerURL, - chainId, + chainId: targetChainId, }) }, [ NATIVE_TOKEN_ADDRESS, @@ -60,6 +60,6 @@ export function useTrade( blockNumber, // refresh api each block account, providerURL, - chainId, + targetChainId, ]) } diff --git a/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts b/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts index 1901f4d63565..5e4400bde41e 100644 --- a/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts +++ b/packages/mask/src/plugins/Trader/trader/useAllTradeComputed.ts @@ -24,6 +24,7 @@ import { TradeProvider } from '@masknet/public-api' import { useAvailableTraderProviders } from '../trending/useAvailableTraderProviders' import { useNativeTradeGasLimit } from './useNativeTradeGasLimit' import { TargetChainIdContext } from './useTargetChainIdContext' +import type { TradeComputed, SwapRouteData } from '../types' export function useAllTradeComputed( inputAmount: string, @@ -184,6 +185,7 @@ export function useAllTradeComputed( inputToken, outputToken, ) + const openoceanSwapEstimateGas = useDODOTradeGasLimit(openocean as TradeComputed | null) const allTradeResult = [ { provider: TradeProvider.UNISWAP_V2, ...uniswapV2_, value: uniswapV2, gas: uniswapV2EstimateGas }, @@ -196,7 +198,7 @@ export function useAllTradeComputed( { provider: TradeProvider.BALANCER, ...balancer_, value: balancer, gas: balancerSwapEstimateGas }, { provider: TradeProvider.DODO, ...dodo_, value: dodo, gas: dodoSwapEstimateGas }, { provider: TradeProvider.BANCOR, ...bancor_, value: bancor, gas: bancorSwapEstimateGas }, - { provider: TradeProvider.OPENOCEAN, ...openocean_, value: openocean, gas: bancorSwapEstimateGas }, + { provider: TradeProvider.OPENOCEAN, ...openocean_, value: openocean, gas: openoceanSwapEstimateGas }, ] return nativeToken_.value From dd2ce1023e6330360a15492a143a1ad256101060 Mon Sep 17 00:00:00 2001 From: zhouhanseng Date: Thu, 30 Dec 2021 14:23:32 +0800 Subject: [PATCH 09/10] chore: qa --- .../Trader/trader/openocean/useTradeCallback.ts | 15 +++++++++++++-- .../src/plugins/Trader/trader/useTradeCallback.ts | 5 ++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts b/packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts index cb6de4b6f5b7..38d729d0a6bd 100644 --- a/packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts +++ b/packages/mask/src/plugins/Trader/trader/openocean/useTradeCallback.ts @@ -2,10 +2,20 @@ import { useCallback, useMemo, useState } from 'react' import stringify from 'json-stable-stringify' import { pick } from 'lodash-unified' import type { TransactionConfig } from 'web3-core' -import { TransactionState, TransactionStateType, useAccount, useChainId, useWeb3 } from '@masknet/web3-shared-evm' +import { + TransactionState, + TransactionStateType, + useAccount, + useChainId, + useWeb3, + GasOptionConfig, +} from '@masknet/web3-shared-evm' import type { SwapOOSuccessResponse, TradeComputed } from '../../types' -export function useTradeCallback(tradeComputed: TradeComputed | null) { +export function useTradeCallback( + tradeComputed: TradeComputed | null, + gasConfig?: GasOptionConfig, +) { const web3 = useWeb3() const account = useAccount() const chainId = useChainId() @@ -46,6 +56,7 @@ export function useTradeCallback(tradeComputed: TradeComputed Date: Fri, 31 Dec 2021 11:07:21 +0800 Subject: [PATCH 10/10] chore: qa --- .../mask/src/plugins/Trader/trader/useTradeApproveComputed.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/mask/src/plugins/Trader/trader/useTradeApproveComputed.ts b/packages/mask/src/plugins/Trader/trader/useTradeApproveComputed.ts index 3a64c6fb201f..8130abcb3e97 100644 --- a/packages/mask/src/plugins/Trader/trader/useTradeApproveComputed.ts +++ b/packages/mask/src/plugins/Trader/trader/useTradeApproveComputed.ts @@ -24,6 +24,8 @@ export function useTradeApproveComputed( approveAddress: (() => { if (context?.TYPE === TradeProvider.ZRX) return trade?.trade_ ? (trade.trade_ as SwapQuoteResponse).allowanceTarget : '' + if (context?.TYPE === TradeProvider.OPENOCEAN) + return trade?.trade_ ? (trade?.trade_ as SwapQuoteResponse).to : '' return context?.ROUTER_CONTRACT_ADDRESS ?? '' })(), }