From 4e2a24a326614235a516949f911fe7a047ff2c7a Mon Sep 17 00:00:00 2001 From: xieqiancaosissi Date: Fri, 1 Nov 2024 20:49:35 +0800 Subject: [PATCH] Add path for near usdt (#632) * feat: add near--->usdt estimate logic * feat: add triggle logic * feat: add exception log * fix: pool fee issue * feat: add testnet data * fix: update tx clear logic * fix: mint-base wallet issue * fix: error * fix: mintbase wallet issue * feat: remote test log * feat: remove test log * Feat new meme xref token * Fix meme bugs * feat: add swap double check logic * fix: ui issue --------- Co-authored-by: naturexie <786281870@qq.com> Co-authored-by: lq0-github <1441665200@qq.com> --- package.json | 1 + src/components/forms/SelectToken.tsx | 2 +- src/components/forms/SwapFormWrap.tsx | 19 +- src/components/layout/SwapDoubleCheck.tsx | 11 +- src/components/layout/transactionTipPopUp.tsx | 20 +- src/components/meme/StakingChart.tsx | 22 +- src/components/meme/memeConfig.tsx | 23 +- src/components/swap/SwapCard.tsx | 65 ++- src/components/swap/SwapMixModal.tsx | 174 ++++++ src/pages/SwapPage.tsx | 3 +- src/services/swap.ts | 90 +++- src/services/swapV3.ts | 2 +- src/state/swap.tsx | 494 ++++++------------ src/state/swap_near_usdt.tsx | 260 +++++++++ src/stores/swapStore.ts | 58 ++ src/utils/swapConfig.ts | 12 + yarn.lock | 156 +++++- 17 files changed, 1046 insertions(+), 366 deletions(-) create mode 100644 src/components/swap/SwapMixModal.tsx create mode 100644 src/state/swap_near_usdt.tsx create mode 100644 src/stores/swapStore.ts create mode 100644 src/utils/swapConfig.ts diff --git a/package.json b/package.json index 87cc2e713..2db5958ab 100644 --- a/package.json +++ b/package.json @@ -198,6 +198,7 @@ "react-spinners": "^0.11.0", "react-toastify": "^9.1.1", "react-tooltip": "^5.23.0", + "react-use": "17.4.0", "react-use-websocket": "^4.3.1", "recharts": "^2.1.6", "reconnecting-websocket": "^4.4.0", diff --git a/src/components/forms/SelectToken.tsx b/src/components/forms/SelectToken.tsx index 23c1159d3..28cf86b67 100644 --- a/src/components/forms/SelectToken.tsx +++ b/src/components/forms/SelectToken.tsx @@ -1499,4 +1499,4 @@ export const SelectTokenForList = ({ ); -}; \ No newline at end of file +}; diff --git a/src/components/forms/SwapFormWrap.tsx b/src/components/forms/SwapFormWrap.tsx index e3a637705..ea20da03b 100644 --- a/src/components/forms/SwapFormWrap.tsx +++ b/src/components/forms/SwapFormWrap.tsx @@ -17,6 +17,7 @@ import { get_pool_name, openUrl } from '../../services/commonV3'; import { PoolInfo } from 'src/services/swapV3'; import { OutLinkIcon } from '../../components/icon/Common'; import { REF_FI_POOL_ACTIVE_TAB } from '../../pages/pools/utils'; +import { INEAR_USDT_SWAP_TODOS } from '../../stores/swapStore'; interface SwapFormWrapProps { title?: string; @@ -54,6 +55,7 @@ interface SwapFormWrapProps { wrapOperation?: boolean; isInsufficient?: boolean; mostPoolDetail?: PoolInfo; + near_usdt_swapTodos?: INEAR_USDT_SWAP_TODOS; } export default function SwapFormWrap({ @@ -76,6 +78,7 @@ export default function SwapFormWrap({ quoteDoneLimit, isInsufficient, mostPoolDetail, + near_usdt_swapTodos, }: React.PropsWithChildren) { const [error, setError] = useState(); @@ -132,13 +135,17 @@ export default function SwapFormWrap({ if (isSignedIn || selectMarket === 'orderly') { try { - selectMarket !== 'orderly' && - setShowSwapLoading && - setShowSwapLoading(true); - - selectMarket !== 'orderly' && - setShowSwapLoading && + if (near_usdt_swapTodos) { setLoadingPause(true); + } else { + selectMarket !== 'orderly' && + setShowSwapLoading && + setShowSwapLoading(true); + + selectMarket !== 'orderly' && + setLoadingPause && + setLoadingPause(true); + } onSubmit(event); } catch (err) { setError(err); diff --git a/src/components/layout/SwapDoubleCheck.tsx b/src/components/layout/SwapDoubleCheck.tsx index 07f3a2bcd..5870fb838 100644 --- a/src/components/layout/SwapDoubleCheck.tsx +++ b/src/components/layout/SwapDoubleCheck.tsx @@ -56,9 +56,11 @@ export function DoubleCheckModal( from: string; onSwap: (e?: any) => void; priceImpactValue: string; + isMixBest?: boolean; } ) { - const { tokenIn, tokenOut, from, onSwap, priceImpactValue } = props; + const { tokenIn, tokenOut, from, onSwap, priceImpactValue, isMixBest } = + props; const [buttonLoading, setButtonLoading] = useState(false); @@ -145,8 +147,13 @@ export function DoubleCheckModal( { - setButtonLoading(true); + if (!isMixBest) { + setButtonLoading(true); + } onSwap(); + if (isMixBest) { + props.onRequestClose(e); + } }} className="text-sm w-auto text-center" padding="px-4 py-1.5" diff --git a/src/components/layout/transactionTipPopUp.tsx b/src/components/layout/transactionTipPopUp.tsx index 7eebd207a..26562db99 100644 --- a/src/components/layout/transactionTipPopUp.tsx +++ b/src/components/layout/transactionTipPopUp.tsx @@ -54,13 +54,23 @@ export const getURLInfo = () => { const errorCode = new URLSearchParams(search).get('errorCode'); const signInErrorType = new URLSearchParams(search).get('signInErrorType'); - - const txHashes = ( + const selectedWalletId = + window.selector?.store?.getState()?.selectedWalletId ?? ''; + let txHashes = []; + const txHashesStr = new URLSearchParams(search).get(TRANSACTION_WALLET_TYPE.NEAR_WALLET) || new URLSearchParams(search).get(TRANSACTION_WALLET_TYPE.SENDER_WALLET) || - new URLSearchParams(search).get(TRANSACTION_WALLET_TYPE.WalletSelector) - )?.split(','); - + new URLSearchParams(search).get(TRANSACTION_WALLET_TYPE.WalletSelector); + if ( + selectedWalletId == 'bitte-wallet' || + selectedWalletId == 'mintbase-wallet' + ) { + txHashes = decodeURIComponent(decodeURIComponent(txHashesStr || '')).split( + ',' + ); + } else { + txHashes = (txHashesStr || '').split(','); + } return { txHash: txHashes && txHashes.length > 0 ? txHashes[txHashes.length - 1] : '', diff --git a/src/components/meme/StakingChart.tsx b/src/components/meme/StakingChart.tsx index bdaa2d51c..41aabbff5 100644 --- a/src/components/meme/StakingChart.tsx +++ b/src/components/meme/StakingChart.tsx @@ -157,10 +157,30 @@ const StakingChart = ({ chartType }) => { if (activeIndex < 0 || activeIndex >= data.length) return null; const activeEntry = data[activeIndex]; + const centerX = 275 / 2; + const imageSize = 44; + const imageX = centerX - imageSize / 2; + const imageY = 66; return ( <> - + + + + + + (false); - const [supportLedger, setSupportLedger] = useState( localStorage.getItem(SUPPORT_LEDGER_KEY) ? true : false ); @@ -729,6 +734,7 @@ export default function SwapCard(props: { const [balanceOutDone, setBalanceOutDone] = useState(false); const [tokenDeflationRateData, setTokenDeflationRateData] = useState>(); + const [showMixSwapModal, setShowMixSwapModal] = useState(false); const intl = useIntl(); const location = useLocation(); @@ -922,6 +928,22 @@ export default function SwapCard(props: { setTokenDeflationRateData(undefined); } }, [tokenIn?.id]); + useEffect(() => { + if ( + accountId && + near_usdt_swapTodos_transaction?.accountId == accountId && + near_usdt_swapTodos_transaction?.process == '1' + ) { + setShowMixSwapModal(true); + } + if ( + accountId && + near_usdt_swapTodos_transaction && + near_usdt_swapTodos_transaction.accountId !== accountId + ) { + set_near_usdt_swapTodos_transaction(null); + } + }, [near_usdt_swapTodos_transaction?.process, accountId]); async function getTokenDeflationRate() { setTokenDeflationRateData(undefined); const tokenMeta = await tokenFtMetadata(tokenIn.id); @@ -1102,14 +1124,24 @@ export default function SwapCard(props: { const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); - const ifDoubleCheck = new BigNumber(tokenInAmount || 0).isLessThanOrEqualTo( new BigNumber(tokenInMax || 0) ) && Number(selectTrade?.priceImpact || 0) > 2; - - if (ifDoubleCheck) setDoubleCheckOpen(true); - else selectTrade && selectTrade.makeSwap(); + if (selectTrade.estimatesMix) { + if (near_usdt_swapTodos_transaction?.process == '2') { + set_near_usdt_swapTodos_transaction(null); + } + if (ifDoubleCheck) { + // TODO4 + setDoubleCheckOpen(true); + } else { + setShowMixSwapModal(true); + } + } else { + if (ifDoubleCheck) setDoubleCheckOpen(true); + else selectTrade && selectTrade.makeSwap(); + } }; const handleSubmit_wrap = (e: any) => { e.preventDefault(); @@ -1176,7 +1208,10 @@ export default function SwapCard(props: { tokenInAmount, tokenInAmountInput, ]); - + function closeMixSwapModal() { + setShowMixSwapModal(false); + set_near_usdt_swapTodos_transaction(null); + } return ( <> selectTrade && selectTrade.makeSwap()} + isMixBest={!!selectTrade?.estimatesMix} + onSwap={() => { + if (selectTrade) { + if (selectTrade.estimatesMix) { + setShowMixSwapModal(true); + } else { + selectTrade && selectTrade.makeSwap(); + } + } + }} priceImpactValue={selectTrade?.priceImpact || '0'} /> @@ -1445,6 +1490,10 @@ export default function SwapCard(props: { }} isOpen={showSkywardTip} /> + ); } diff --git a/src/components/swap/SwapMixModal.tsx b/src/components/swap/SwapMixModal.tsx new file mode 100644 index 000000000..39f99ca40 --- /dev/null +++ b/src/components/swap/SwapMixModal.tsx @@ -0,0 +1,174 @@ +import React, { useEffect, useState, useMemo } from 'react'; +import Modal from 'react-modal'; +import { usePersistSwapStore } from '../../stores/swapStore'; +import { isMobile } from '../../utils/device'; +import { ModalCloseIcon } from '../meme/icons'; +import { + ButtonTextWrapper, + OprationButton, +} from 'src/components/button/Button'; +import { + makeDclSwap_nearUsdt, + makeV1Swap_nearUsdt, +} from '../../state/swap_near_usdt'; +export default function SwapMixModal(props: any) { + const { isOpen, onRequestClose } = props; + const [step1Loading, setStep1Loading] = useState(false); + const [step2Loading, setStep2Loading] = useState(false); + const { + near_usdt_swapTodos, + set_near_usdt_swapTodos_transaction, + near_usdt_swapTodos_transaction, + } = usePersistSwapStore(); + const cardWidth = isMobile() ? '95vw' : '400px'; + const step1Disabled = + near_usdt_swapTodos_transaction && + near_usdt_swapTodos_transaction.process !== '0'; + const step2Disabled = !step1Disabled; + function makeDclSwap(e) { + e.preventDefault(); + e.stopPropagation(); + if (step1Disabled) return; + setStep1Loading(true); + set_near_usdt_swapTodos_transaction({ + ...near_usdt_swapTodos, + accountId: window.selectorAccountId, + }); + const { pools, slippageTolerance, dcl_quote_amout, tokens, tokenInAmount } = + near_usdt_swapTodos; + makeDclSwap_nearUsdt({ + dcl_pool_id: pools[0].pool_id, + slippageTolerance, + dcl_quote_amout, + nearMetadata: tokens[0], + usdcMetadata: tokens[1], + tokenInAmount, + }); + } + function makeV1Swap() { + if (step2Disabled) return; + setStep2Loading(true); + const { + dcl_quote_amout_real, + tokens, + nonEstimateOutAmountWithSlippageTolerance, + } = near_usdt_swapTodos_transaction; + set_near_usdt_swapTodos_transaction({ + ...near_usdt_swapTodos_transaction, + process: '2', + }); + makeV1Swap_nearUsdt({ + usdcMetadata: tokens[1], + usdtMetadata: tokens[2], + amountIn: dcl_quote_amout_real, + nonEstimateOutAmountWithSlippageTolerance, + }); + } + return ( + +
+
+ Swap + +
+
+
+ + 1 + + Swap from NEAR to USDC +
+ {step1Disabled ? ( + + + + + + + + + + + ) : ( + + ( +
+ Submit +
+ )} + /> +
+ )} +
+
+
+ + 2 + + Swap from USDC to USDt +
+ + ( +
Submit
+ )} + /> +
+
+
+
+ ); +} diff --git a/src/pages/SwapPage.tsx b/src/pages/SwapPage.tsx index e51c4629b..99ced6bc9 100644 --- a/src/pages/SwapPage.tsx +++ b/src/pages/SwapPage.tsx @@ -35,8 +35,8 @@ import BLACKTip from '../components/pool/BLACKTip'; import OrderlyAirDropPop from '../components/orderlyAirdrop/index'; import OrderlyAirDropPopMobile from '../components/orderlyAirdropMobile/index'; import { useOrderlyGuidePopStore } from '../stores/orderlyGuidePop'; -import { isMobile } from 'src/utils/device'; import { IEstimateSwapServerView } from '~src/services/smartRouterFromServer'; +import { INEAR_USDT_SWAP_TODOS } from '../stores/swapStore'; export const SWAP_MODE_KEY = 'SWAP_MODE_VALUE'; @@ -73,6 +73,7 @@ export type SwapContractType = export interface ExchangeEstimate { estimates?: EstimateSwapView[]; estimatesServer?: IEstimateSwapServerView; + estimatesMix?: INEAR_USDT_SWAP_TODOS; fee?: number; priceImpact?: string; minAmountOut?: string; diff --git a/src/services/swap.ts b/src/services/swap.ts index f1a1fe40f..6ffa11a6c 100644 --- a/src/services/swap.ts +++ b/src/services/swap.ts @@ -26,6 +26,7 @@ import { ftGetTokensMetadata, native_usdc_has_upgrated, TokenMetadata, + ftViewFunction, } from './ft-contract'; import { getTokenFlow } from './indexer'; import { @@ -37,6 +38,7 @@ import { REF_FI_CONTRACT_ID, RefFiFunctionCallOptions, Transaction, + refFiViewFunction, } from './near'; import { getAllStablePoolsFromCache, @@ -66,7 +68,7 @@ import { getUsedPools, getUsedTokens, } from './smartRouterFromServer'; -import { REF_DCL_POOL_CACHE_KEY } from '../state/swap'; +import { getSelectedWalletId } from '../pages/Orderly/orderly/utils'; import { getTokenPriceListFromCacheForServer } from '../services/smartRouterFromServer'; export const REF_FI_SWAP_SIGNAL = 'REF_FI_SWAP_SIGNAL_KEY'; @@ -1259,6 +1261,69 @@ export const swapFromServer = async ({ return executeMultipleTransactions(transactions); }; +export const swapFromFourPool = async ({ + tokenIn, + tokenOut, + amountIn, // NonDivisibleNumber + pool_id, + min_amount_out, +}) => { + const transactions: Transaction[] = []; + const tokenOutActions: RefFiFunctionCallOptions[] = []; + const walletId = getSelectedWalletId(); + const gas = walletId == 'neth' ? '250000000000000' : '300000000000000'; + const registerToken = async (token: TokenMetadata) => { + const tokenRegistered = await ftGetStorageBalance(token.id).catch(() => { + throw new Error(`${token.id} doesn't exist.`); + }); + if (tokenRegistered === null) { + tokenOutActions.push({ + methodName: 'storage_deposit', + args: { + registration_only: true, + account_id: getCurrentWallet()?.wallet?.getAccountId(), + }, + gas, + amount: STORAGE_TO_REGISTER_WITH_MFT, + }); + transactions.push({ + receiverId: token.id, + functionCalls: tokenOutActions, + }); + } + }; + await registerToken(tokenOut); + const actionsList = [ + { + pool_id: +pool_id, + token_in: tokenIn.id, + token_out: tokenOut.id, + amount_in: amountIn, + min_amount_out, + }, + ]; + transactions.push({ + receiverId: tokenIn.id, + functionCalls: [ + { + methodName: 'ft_transfer_call', + args: { + receiver_id: REF_FI_CONTRACT_ID, + amount: amountIn, + msg: JSON.stringify({ + force: 0, + actions: actionsList, + }), + }, + gas, + amount: ONE_YOCTO_NEAR, + }, + ], + }); + + return executeMultipleTransactions(transactions); +}; + export const nearInstantSwap = async ({ tokenIn, tokenOut, @@ -1373,7 +1438,8 @@ export const nearInstantSwap = async ({ }); } } - + const gas = + getSelectedWalletId() == 'neth' ? '2500000000000000' : '300000000000000'; transactions.push({ receiverId: tokenIn.id, functionCalls: [ @@ -1388,7 +1454,7 @@ export const nearInstantSwap = async ({ ...(tokenOut.symbol == 'NEAR' ? { skip_unwrap_near: false } : {}), }), }, - gas: '300000000000000', + gas, amount: ONE_YOCTO_NEAR, }, ], @@ -1896,3 +1962,21 @@ export const smartRouteSwapCase = async ({ return curTransactions; }; + +// v1 pool estimate +export const getReturn = async ({ + pool_id, + token_in, + amount_in, + token_out, +}: { + pool_id: number; + token_in: string; + amount_in: string; + token_out: string; +}) => { + return refFiViewFunction({ + methodName: 'get_return', + args: { pool_id, token_in, amount_in, token_out }, + }); +}; diff --git a/src/services/swapV3.ts b/src/services/swapV3.ts index c336f7dfd..b5c445e73 100644 --- a/src/services/swapV3.ts +++ b/src/services/swapV3.ts @@ -584,7 +584,7 @@ export const get_pool_old_version = async ( }) as Promise; }; -export const get_pool_from_cache = async (pool_id: string, token0?: string) => { +export const get_pool_from_cache = async (pool_id: string) => { const [token_x, token_y, fee] = pool_id.split('|'); const token_seq = [token_x, token_y].sort().join('|'); diff --git a/src/state/swap.tsx b/src/state/swap.tsx index 7470141aa..337166d2e 100644 --- a/src/state/swap.tsx +++ b/src/state/swap.tsx @@ -4,7 +4,7 @@ import _ from 'lodash'; import React, { useContext, useEffect, useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; import { useHistory } from 'react-router'; - +import { useDebounce } from 'react-use'; import { failToast, getURLInfo, @@ -21,11 +21,6 @@ import { } from '../components/layout/transactionTipPopUp'; import { parsedTransactionSuccessValue } from '../components/layout/transactionTipPopUp'; import { SUPPORT_LEDGER_KEY } from '../components/swap/SwapCard'; -import { useWalletSelector } from '../context/WalletSelectorContext'; -import { parseSymbol } from '../pages/Orderly/components/RecentTrade'; -import { getAccountInformation } from '../pages/Orderly/orderly/off-chain-api'; -import { useOrderlyContext } from '../pages/Orderly/orderly/OrderlyContext'; -import { ClientInfo, Orders } from '../pages/Orderly/orderly/type'; import { ExchangeEstimate, SWAP_MODE, @@ -34,7 +29,6 @@ import { SwapProContext, } from '../pages/SwapPage'; import { hasTriPools } from '../services/aurora/aurora'; -import { openUrl } from '../services/commonV3'; import getConfig from '../services/config'; import { ftGetTokenMetadata, TokenMetadata } from '../services/ft-contract'; import { isStablePool, POOL_TOKEN_REFRESH_INTERVAL } from '../services/near'; @@ -73,17 +67,28 @@ import { toRealSymbol } from '../utils/token'; import { getCurrentWallet, WalletContext } from '../utils/wallets-integration'; import { useIndexerStatus } from './pool'; import { useTokenPriceList } from './token'; +import { useSwapMix } from './swap_near_usdt'; +import { usePersistSwapStore } from '../stores/swapStore'; import { IEstimateSwapServerView, getAvgFeeFromServer, getPriceImpactFromServer, getAllPoolsFromCache, } from '../services/smartRouterFromServer'; +import { + token_near_id, + token_usdc_id, + token_usdt_id, + near_udsc_pool_id, + four_stable_pool_id, +} from '../utils/swapConfig'; +import { useWalletSelector } from '../context/WalletSelectorContext'; +import { safeJSONParse } from '../pages/Bridge/utils/common'; const ONLY_ZEROS = /^0*\.?0*$/; export const REF_DCL_POOL_CACHE_KEY = 'REF_DCL_POOL_CACHE_VALUE'; -interface SwapOptions { +export interface SwapOptions { tokenIn: TokenMetadata; tokenInAmount: string; tokenOut: TokenMetadata; @@ -132,6 +137,12 @@ const getTokenPriceListFromCache = async () => { export const useSwapPopUp = () => { const { txHash, pathname, errorType } = getURLInfo(); const history = useHistory(); + const { accountId } = useWalletSelector(); + const { + near_usdt_swapTodos, + near_usdt_swapTodos_transaction, + set_near_usdt_swapTodos_transaction, + } = usePersistSwapStore(); const parseLimitOrderPopUp = async (res: any) => { const byNeth = @@ -305,10 +316,18 @@ export const useSwapPopUp = () => { useEffect(() => { if (swapSig === 'tri') return; if (txHash && getCurrentWallet().wallet.isSignedIn()) { + if ( + near_usdt_swapTodos_transaction && + near_usdt_swapTodos_transaction?.process !== '0' + ) { + set_near_usdt_swapTodos_transaction(null); + } checkTransaction(txHash) .then(async (res: any) => { - const isLimitOrder = await parseLimitOrderPopUp(res); - + let isLimitOrder; + try { + isLimitOrder = await parseLimitOrderPopUp(res); + } catch (error) {} const transactionErrorType = getErrorMessage(res); const byNeth = res?.transaction?.actions?.[0]?.FunctionCall?.method_name === @@ -318,11 +337,18 @@ export const useSwapPopUp = () => { 'rlp_execute'; const isPackage = byNeth || byEvm; const transaction = res.transaction; - const isSwapReceipt = - res?.receipts?.[0]?.receipt?.Action?.actions?.[0]?.FunctionCall - ?.method_name === 'ft_transfer_call' || - res?.receipts?.[0]?.receipt?.Action?.actions?.[0]?.FunctionCall - ?.method_name === 'near_withdraw'; + const isSwapReceipt = !!res?.receipts?.find((receipt) => { + return ( + receipt?.receipt?.Action?.actions?.[0]?.FunctionCall + ?.method_name === 'ft_transfer_call' || + receipt?.receipt?.Action?.actions?.[0]?.FunctionCall + ?.method_name === 'near_withdraw' || + receipt?.receipt?.Action?.actions?.[0]?.FunctionCall + ?.method_name === 'near_deposit' || + receipt?.receipt?.Action?.actions?.[0]?.FunctionCall + ?.method_name === 'swap' + ); + }); return { isSwap: (transaction?.actions[1]?.FunctionCall?.method_name === @@ -334,20 +360,56 @@ export const useSwapPopUp = () => { 'near_deposit' || transaction?.actions[0]?.FunctionCall?.method_name === 'near_withdraw' || - (isSwapReceipt && isPackage)) && + isSwapReceipt) && !isLimitOrder, transactionErrorType, + res, }; }) - .then(({ isSwap, transactionErrorType }) => { + .then(({ isSwap, transactionErrorType, res }) => { if (isSwap) { - !transactionErrorType && !errorType && swapToast(txHash); - transactionErrorType && failToast(txHash, transactionErrorType); + if (!transactionErrorType && !errorType) { + if (near_usdt_swapTodos_transaction?.process == '0') { + handle_near_usdt_swap(res); + } else { + if (near_usdt_swapTodos_transaction) { + set_near_usdt_swapTodos_transaction(null); + } + swapToast(txHash); + } + } else if (transactionErrorType) { + failToast(txHash, transactionErrorType); + } } history.replace(pathname); }); } }, [txHash]); + function handle_near_usdt_swap(res: any) { + const targetReceipt = res.receipts.find((receipt) => { + return ( + receipt.receiver_id == token_usdc_id && + receipt.receipt?.Action?.actions?.[0]?.FunctionCall?.method_name == + 'ft_transfer' + ); + }); + const args = parsedArgs( + targetReceipt.receipt?.Action?.actions?.[0]?.FunctionCall?.args + ); + const argsObj: { + receiver_id: string; + amount: string; + } = safeJSONParse(args); + if (argsObj?.amount && argsObj?.receiver_id == accountId) { + set_near_usdt_swapTodos_transaction({ + ...near_usdt_swapTodos_transaction, + process: '1', + dcl_quote_amout_real: argsObj?.amount, + }); + } else { + set_near_usdt_swapTodos_transaction(null); + } + } }; export const useCrossSwapPopUp = () => { @@ -412,7 +474,6 @@ export const estimateValidator = ( return true; }; -// TODO 1 export const useSwap = ({ tokenIn, tokenInAmount, @@ -464,7 +525,6 @@ export const useSwap = ({ const setAverageFee = (estimates: EstimateSwapView[]) => { let avgFee: number = 0; - try { const routes = separateRoutes(estimates, tokenOut.id); @@ -823,10 +883,7 @@ export const useSwapV3 = ({ useEffect(() => { if (!bestFee || wrapOperation) return; - get_pool_from_cache( - getV3PoolId(tokenIn.id, tokenOut.id, bestFee), - tokenIn.id - ) + get_pool_from_cache(getV3PoolId(tokenIn.id, tokenOut.id, bestFee)) .then((bestPool) => { setBestPool(bestPool); }) @@ -1581,23 +1638,63 @@ export const useRefSwap = ({ setLoadingTrigger, reEstimateTrigger, }); + const mixEstimateResult = useSwapMix({ + tokenIn, + tokenInAmount, + tokenOut, + slippageTolerance, + setLoadingData, + loadingTrigger, + setLoadingTrigger, + setShowSwapLoading, + loadingData, + loadingPause, + swapMode, + reEstimateTrigger, + supportLedger, + tokenDeflationRateData, + }); + const { + estimateOutAmount: tokenOutAmountMix, + mixTag, + quoteDone: quoteDoneMix, + canSwap: canSwapMix, + fee: feeMix, + priceImpact: priceImpactFix, + estimateOutAmountWithSlippageTolerance: minAmountOutMix, + } = mixEstimateResult; + let bestSwap; + const { set_near_usdt_swapTodos, set_near_usdt_swapTodos_transaction } = + usePersistSwapStore(); + useDebounce( + () => { + if (bestSwap == 'mix') { + set_near_usdt_swapTodos(mixEstimateResult); + } + }, + 500, + [bestSwap, JSON.stringify(mixEstimateResult || {})] + ); function validator() { - if (tag && tagV3) { + if (tag && tagV3 && mixTag) { const [inId, outId, inAmount] = tag.split('|'); const [dclInId, dclOutId, dclInAmount] = tagV3.split('|'); + const [mixInId, mixOutId, mixInAmount] = mixTag.split('|'); return ( inId == tokenIn?.id && outId == tokenOut.id && inAmount == tokenInAmount && dclInId == tokenIn?.id && dclOutId == tokenOut.id && - dclInAmount == tokenInAmount + dclInAmount == tokenInAmount && + mixInId == tokenIn?.id && + mixOutId == tokenOut.id && + mixInAmount == tokenInAmount ); } return false; } - // TODO 2 - const quoteDoneRef = quoteDoneV2 && quoteDone && validator(); + const quoteDoneRef = quoteDoneV2 && quoteDone && quoteDoneMix && validator(); if (!quoteDoneRef) return { quoteDone: false, @@ -1608,12 +1705,27 @@ export const useRefSwap = ({ market: 'ref', tokenOutAmount: '0', }; - const bestSwap = + // console.table([ + // `tag---${tag}---${tokenOutAmount}`, + // `tagV3---${tagV3}---${tokenOutAmountV2}`, + // `mixTag---${mixTag}---${tokenOutAmountMix}`, + // ]); + const betterSwap = new Big(tokenOutAmountV2 || '0').gte(tokenOutAmount || '0') && canSwapV2 && !swapErrorV2 ? 'v2' : 'v1'; + const betterOutAmount = new Big(tokenOutAmountV2 || '0').gte( + tokenOutAmount || '0' + ) + ? tokenOutAmountV2 + : tokenOutAmount; + bestSwap = + canSwapMix && Big(tokenOutAmountMix || '0').gt(betterOutAmount) + ? 'mix' + : betterSwap; + // bestSwap = 'mix'; // TODO4 Test code if (bestSwap === 'v1') { if (swapsToDoServer) { swapsToDoServer.contract = 'Ref_Classic'; @@ -1672,289 +1784,23 @@ export const useRefSwap = ({ exchange_name:
Ref
, }; } -}; - -export const useOrderlySwap = ({ - tokenIn, - tokenOut, - tokenInAmount, - loadingTrigger, - reEstimateTrigger, -}: SwapOptions): ExchangeEstimate => { - const [estimate, setEstimate] = useState(); - - const { swapType } = useContext(SwapProContext); - - const [orderlyQuoteDone, setOrderlyQuoteDone] = useState(false); - - const { accountId } = useWalletSelector(); - - const [side, setCurSide] = useState<'Sell' | 'Buy'>(); - - const { - tokenInfo, - availableSymbols, - systemAvailable, - symbol, - orders, - setSymbol, - } = useOrderlyContext(); - - const [userInfo, setUserInfo] = useState(); - - const calculatePrice = ( - side: 'Sell' | 'Buy', - orders: Orders, - tokenInAmount: string | number - ) => { - const asks = (side === 'Buy' ? orders?.asks : orders?.bids) || []; - - if (asks.length == 0) { - setCanSwap(false); - setEstimate(''); - setOrderlyQuoteDone(true); - return 0; - } - - let totalPrice = 0; - let totalAmount = 0; - - if (side === 'Sell') { - for (let i = 0; i < asks.length; i++) { - const [price, quantity] = asks[i]; - if (totalAmount + quantity <= Number(tokenInAmount)) { - totalPrice += price * quantity; - totalAmount += quantity; - } else { - const remainingQuantity = Number(tokenInAmount) - totalAmount; - totalPrice += price * remainingQuantity; - totalAmount += remainingQuantity; - break; - } - } - } - - if (side === 'Buy') { - for (let i = 0; i < asks.length; i++) { - const [price, quantity] = asks[i]; - if (totalAmount + price * quantity <= Number(tokenInAmount)) { - totalPrice += quantity; - totalAmount += price * quantity; - } else { - const remainingQuantity = Number(tokenInAmount) - totalAmount; - totalPrice += remainingQuantity / price; - totalAmount += remainingQuantity; - break; - } - } - } - - return totalPrice; - }; - - const getAmountByAsksAndBids = async ( - amount: number, - tokenInProp: TokenMetadata, - tokenOutProp: TokenMetadata, - loadingTrigger?: boolean - ) => { - const tokenIn = - tokenInProp.symbol === 'NEAR' - ? { - ...tokenInProp, - id: 'near', - } - : tokenInProp; - - const tokenOut = - tokenOutProp.symbol === 'NEAR' - ? { - ...tokenOutProp, - id: 'near', - } - : tokenOutProp; - - const availableSymbolsWithTokens = availableSymbols?.map((symbol) => { - const { symbolFrom, symbolTo } = parseSymbol(symbol.symbol); - - return { - ...symbol, - token_ids: [ - tokenInfo?.find((token) => token.token === symbolFrom) - ?.token_account_id, - tokenInfo?.find((token) => token.token === symbolTo) - ?.token_account_id, - ], - }; - }); - - const canSwapSymbol = availableSymbolsWithTokens?.find((symbol) => { - return ( - symbol.token_ids.includes(tokenIn.id) && - symbol.token_ids.includes(tokenOut.id) && - symbol.symbol.indexOf('SPOT') > -1 - ); - }); - - const side = ( - canSwapSymbol?.token_ids[0] === tokenIn.id ? 'Sell' : 'Buy' - ) as 'Sell' | 'Buy'; - - if (!availableSymbols || !canSwapSymbol || !canSwapSymbol?.token_ids) { - setCanSwap(false); - setEstimate('0'); - - setOrderlyQuoteDone(true); - setCurSide(side); - - return; - } - - if (canSwapSymbol.symbol !== symbol || !orders) { - // setReEstimate(!reEstimate); - setCurSide(side); - - setSymbol(canSwapSymbol.symbol); - - return; - } - - if (canSwapSymbol.symbol === symbol) { - const calcRes = calculatePrice(side, orders, tokenInAmount); - - if (calcRes > 0) { - setEstimate( - scientificNotationToString( - percentLess( - (userInfo?.taker_fee_rate || 10) / 100, - - calcRes - ).toString() - ) - ); - - setOrderlyQuoteDone(true); - setCurSide(side); - setCanSwap(true); - } - } - }; - - useEffect(() => { - if (!accountId) return; - - getAccountInformation({ accountId }).then((res) => { - setUserInfo(res); - }); - }, [accountId]); - - const history = useHistory(); - - const [canSwap, setCanSwap] = useState(false); - - const availableSymbolsWithTokens = - symbol && - availableSymbols?.map((symbol) => { - const { symbolFrom, symbolTo } = parseSymbol(symbol.symbol); - - return { - ...symbol, - token_ids: [ - tokenInfo?.find((token) => token.token === symbolFrom) - ?.token_account_id, - tokenInfo?.find((token) => token.token === symbolTo) - ?.token_account_id, - ], - }; - }); - - const canSwapSymbol = availableSymbolsWithTokens?.find((symbol) => { - return ( - symbol.token_ids.includes( - tokenIn?.symbol === 'NEAR' ? 'near' : tokenIn?.id - ) && - symbol.token_ids.includes( - tokenOut?.symbol === 'NEAR' ? 'near' : tokenOut?.id - ) - ); - }); - - const pairExist = - tokenIn && - tokenOut && - tokenIn.id !== tokenOut.id && - symbol && - !!tokenInfo?.find( - (token) => - token.token_account_id === - (tokenIn.symbol === 'NEAR' ? 'near' : tokenIn?.id) - ) && - !!tokenInfo?.find( - (token) => - token.token_account_id === - (tokenOut.symbol === 'NEAR' ? 'near' : tokenOut?.id) - ) && - canSwapSymbol; - - useEffect(() => { - if (!tokenIn || !tokenOut || !pairExist) return; - - setOrderlyQuoteDone(false); - setCanSwap(false); - - getAmountByAsksAndBids(Number(tokenInAmount), tokenIn, tokenOut); - }, [ - loadingTrigger, - JSON.stringify(tokenInfo || ''), - JSON.stringify(availableSymbols || ''), - tokenIn?.id, - tokenOut?.id, - tokenInAmount, - pairExist, - reEstimateTrigger, - ]); - - const makeSwap = () => { - openUrl(`/orderbook/spot?side=${side}&orderType=Market`); - }; - - return { - maker_fee: userInfo?.maker_fee_rate || 10, - taker_fee: userInfo?.taker_fee_rate || 10, - estimates: !estimate - ? null - : [ - { - contract: 'Orderly', - estimate, - tokens: [tokenIn, tokenOut], - outputToken: tokenOut?.id, - inputToken: tokenIn?.id, - pool: null, - totalInputAmount: toNonDivisibleNumber( - tokenIn?.decimals === null || tokenIn?.decimals === undefined - ? 24 - : tokenIn.decimals, - tokenInAmount - ), - }, - ], - makeSwap, - quoteDone: !pairExist || orderlyQuoteDone, - canSwap, - tokenInAmount, - tokenIn, - tokenOut, - market: 'orderly', - availableRoute: - swapType === SWAP_TYPE.Pro && - !!systemAvailable && - !!pairExist && - !!canSwap, - swapError: null, - tokenOutAmount: toPrecision(estimate, Math.min(8, tokenOut?.decimals ?? 8)), - exchange_name:
Orderly
, - }; + if (bestSwap == 'mix') { + return { + estimatesMix: mixEstimateResult, + quoteDone: true, + canSwap: true, + tokenOutAmount: mixEstimateResult.estimateOutAmount, + minAmountOut: minAmountOutMix, + tokenInAmount, + availableRoute: !mixEstimateResult.mixError, + tokenIn, + tokenOut, + market: 'ref', + fee: feeMix, + priceImpact: priceImpactFix, + exchange_name:
Ref
, + }; + } }; export const REF_FI_BEST_MARKET_ROUTE = 'REF_FI_BEST_MARKET_ROUTE'; @@ -1990,7 +1836,6 @@ export const useRefSwapPro = ({ selectMarket, swapType, } = useContext(SwapProContext); - // TODO 3 const resRef = useRefSwap({ tokenIn, tokenInAmount, @@ -2027,15 +1872,6 @@ export const useRefSwapPro = ({ reEstimateTrigger, }); - const resOrderly = useOrderlySwap({ - tokenIn, - tokenInAmount, - tokenOut, - loadingTrigger, - slippageTolerance, - reEstimateTrigger, - }); - useEffect(() => { if (tokenIn && tokenOut && tokenIn.id === tokenOut.id) { setSelectMarket('ref'); @@ -2043,15 +1879,10 @@ export const useRefSwapPro = ({ }, [tokenIn, tokenOut]); useEffect(() => { - if ( - resRef.quoteDone && - (!enableTri || resAurora.quoteDone) && - resOrderly.quoteDone - ) { + if (resRef.quoteDone && (!enableTri || resAurora.quoteDone)) { const trades = { ['ref']: resRef, ['tri']: resAurora, - ['orderly']: resOrderly, }; const tradeList = [resRef, resAurora]; @@ -2085,7 +1916,8 @@ export const useRefSwapPro = ({ resRef.estimates?.[0]?.tokens?.[ resRef.estimates?.[0]?.tokens.length - 1 ]?.id === localStorage.getItem('REF_FI_SWAP_OUT'))) || - (resRef.estimatesServer && !resRef.estimates); + (resRef.estimatesServer && !resRef.estimates) || + (resRef.estimatesMix && !resRef.estimatesServer && !resRef.estimates); if (!resValid) { setReEstimateTrigger(!reEstimateTrigger); @@ -2130,7 +1962,6 @@ export const useRefSwapPro = ({ resRef.quoteDone, enableTri, resAurora.quoteDone, - resOrderly.quoteDone, slippageTolerance, swapType, @@ -2139,7 +1970,6 @@ export const useRefSwapPro = ({ quoting, JSON.stringify(resRef?.tokenOutAmount || {}), JSON.stringify(resAurora?.tokenOutAmount || {}), - JSON.stringify(resOrderly?.tokenOutAmount || {}), JSON.stringify(resRef?.estimates || {}), JSON.stringify(resAurora?.estimates || {}), diff --git a/src/state/swap_near_usdt.tsx b/src/state/swap_near_usdt.tsx new file mode 100644 index 000000000..db6efbfc9 --- /dev/null +++ b/src/state/swap_near_usdt.tsx @@ -0,0 +1,260 @@ +import { useEffect, useState } from 'react'; +import { useDebounce } from 'react-use'; +import Big from 'big.js'; +import { SwapOptions } from './swap'; +import { getReturn, swapFromFourPool } from '../services/swap'; +import { + PoolInfo, + quote, + v3Swap, + get_pool_from_cache, +} from '../services/swapV3'; +import { percentLess, toReadableNumber } from '../utils/numbers'; +import { ftGetTokenMetadata, TokenMetadata } from '../services/ft-contract'; +import { getStablePoolFromCacheForServer, StablePool } from '../services/pool'; +import { INEAR_USDT_SWAP_TODOS } from '../stores/swapStore'; +import { + token_near_id, + token_usdc_id, + token_usdt_id, + near_udsc_pool_id, + four_stable_pool_id, +} from '../utils/swapConfig'; +import { getBoostTokenPrices } from '../services/farm'; +import { toPrecision } from '../utils/numbers'; +import { usePersistSwapStore } from '../stores/swapStore'; +const token_in_id = token_near_id; +const token_out_id = token_usdt_id; +const dcl_pool_id = near_udsc_pool_id; +const four_pool_id = four_stable_pool_id; +export const useSwapMix = ({ + tokenIn, + tokenInAmount, + tokenOut, + slippageTolerance, + loadingTrigger, + setLoadingTrigger, + reEstimateTrigger, + supportLedger, +}: SwapOptions): INEAR_USDT_SWAP_TODOS => { + const [estimateOutAmount, setEstimateOutAmount] = useState('0'); + const [quoteDone, setQuoteDone] = useState(false); + const [canSwap, setCanSwap] = useState(false); + const [mixTag, setMixTag] = useState(); + const [mixError, setMixError] = useState(); + const [dcl_quote_amout, set_dcl_quote_amout] = useState('0'); + const [dclPool, setDclPool] = useState(); + const [stablePool, setStablePool] = useState(); + const [usdcMetadata, setUsdcMetadata] = useState(); + const [tokenPriceList, setTokenPriceList] = useState>(); + const [avgFee, setAvgFee] = useState(0); + const [priceImpact, setPriceImpact] = useState('0'); + const { set_near_usdt_swapTodos, set_near_usdt_swapTodos_transaction } = + usePersistSwapStore(); + useEffect(() => { + getAssets(); + }, []); + useDebounce( + () => { + if ( + tokenIn?.id == token_in_id && + tokenOut?.id == token_out_id && + usdcMetadata?.id && + Big(tokenInAmount || 0).gt(0) && + !supportLedger + ) { + getEstimate(); + } else { + initState(); + } + }, + 500, + [ + tokenIn?.id, + tokenIn?.symbol, + tokenOut?.id, + tokenOut?.symbol, + tokenInAmount, + usdcMetadata?.id, + supportLedger, + reEstimateTrigger, + ] + ); + useEffect(() => { + if ( + (tokenIn && tokenIn.id !== token_in_id) || + (tokenOut && tokenOut.id !== token_out_id) + ) { + set_near_usdt_swapTodos(null); + set_near_usdt_swapTodos_transaction(null); + } + }, [tokenIn?.id, tokenOut?.id]); + useEffect(() => { + if ( + tokenIn?.id == token_in_id && + tokenOut?.id == token_out_id && + usdcMetadata?.id && + Big(tokenInAmount || 0).gt(0) && + !supportLedger && + loadingTrigger + ) { + getEstimate(); + } + }, [loadingTrigger]); + async function getEstimate() { + setQuoteDone(false); + try { + const dcl_quote = await quote({ + pool_ids: [dcl_pool_id], + input_token: tokenIn, + output_token: usdcMetadata, + input_amount: tokenInAmount, + tag: `${tokenIn.id}|2000|${tokenInAmount}`, + }); + const { amount: dcl_quote_amount } = dcl_quote; + const v1_quote_amount = await getReturn({ + pool_id: four_pool_id, + token_in: token_usdc_id, + token_out: token_out_id, + amount_in: dcl_quote_amount, + }); + set_dcl_quote_amout(dcl_quote_amount); + setEstimateOutAmount(v1_quote_amount); + setQuoteDone(true); + setCanSwap(true); + setMixTag(`${token_in_id}|${token_out_id}|${tokenInAmount}`); + getPriceImpact(tokenInAmount, v1_quote_amount); + setLoadingTrigger(false); + } catch (error) { + initState(); + setMixError(error); + setLoadingTrigger(false); + } + } + function initState() { + setEstimateOutAmount('0'); + set_dcl_quote_amout('0'); + setQuoteDone(true); + setCanSwap(false); + setMixTag(`${tokenIn?.id}|${tokenOut?.id}|${tokenInAmount}`); + } + async function getAssets() { + const dclPool = await get_pool_from_cache(dcl_pool_id); + const [stablePool, stablePoolInfo] = await getStablePoolFromCacheForServer( + four_pool_id.toString() + ); + const tokenUsdcMetadata = await ftGetTokenMetadata(token_usdc_id); + const tokenPrices = await getBoostTokenPrices(); + setDclPool(dclPool); + setStablePool(stablePoolInfo); + setUsdcMetadata(tokenUsdcMetadata); + setTokenPriceList(tokenPrices); + getAverageFee(stablePool); + } + function getAverageFee(stablePool) { + const dclPoolFee = 2000 / 100; + const stablePoolFee = stablePool.fee; + setAvgFee(dclPoolFee + +stablePoolFee); + } + const getPriceImpact = (tokenInAmount, estimateOutAmount) => { + try { + const readablEStimateOutAmount = toReadableNumber( + tokenOut?.decimals || 0, + estimateOutAmount + ); + const newPrice = new Big(tokenInAmount || '0').div( + new Big(readablEStimateOutAmount || '1') + ); + const priceIn = tokenPriceList[tokenIn.id]?.price; + const priceOut = tokenPriceList[tokenOut.id]?.price; + const oldPrice = new Big(priceOut).div(priceIn || '1'); + const priceImpact = newPrice.lt(oldPrice) + ? '0' + : newPrice.minus(oldPrice).div(newPrice).times(100).abs().toFixed(); + setPriceImpact( + new Big(priceImpact).minus(new Big((avgFee || 0) / 100)).toFixed() + ); + } catch (error) { + setPriceImpact('0'); + } + }; + const readblEstimateOutAmount = toReadableNumber( + tokenOut?.decimals || 0, + estimateOutAmount + ); + const readblEstimateOutAmountMin = readblEstimateOutAmount + ? toPrecision( + percentLess(slippageTolerance, toPrecision(readblEstimateOutAmount, 6)), + tokenOut?.decimals ?? 6 + ) + : null; + const estimateOutAmountMin = estimateOutAmount + ? Big(percentLess(slippageTolerance, estimateOutAmount)).toFixed(0) + : null; + return { + estimateOutAmount: readblEstimateOutAmount, + estimateOutAmountWithSlippageTolerance: readblEstimateOutAmountMin, + dcl_quote_amout, + nonEstimateOutAmount: estimateOutAmount, + nonEstimateOutAmountWithSlippageTolerance: estimateOutAmountMin, + mixTag, + quoteDone, + canSwap, + pools: [dclPool, stablePool], + tokens: [tokenIn, usdcMetadata, tokenOut], + slippageTolerance, + mixError, + process: '0', + tokenInAmount, + fee: avgFee, + priceImpact, + }; +}; + +export async function makeDclSwap_nearUsdt({ + dcl_pool_id, + slippageTolerance, + dcl_quote_amout, + nearMetadata, + usdcMetadata, + tokenInAmount, +}: { + dcl_pool_id: string; + slippageTolerance: number; + dcl_quote_amout: string; + nearMetadata: TokenMetadata; + usdcMetadata: TokenMetadata; + tokenInAmount: string; +}) { + v3Swap({ + Swap: { + pool_ids: [dcl_pool_id], + min_output_amount: percentLess(slippageTolerance, dcl_quote_amout), + }, + swapInfo: { + tokenA: nearMetadata, + tokenB: usdcMetadata, + amountA: tokenInAmount, + amountB: toReadableNumber(usdcMetadata.decimals, dcl_quote_amout), + }, + }); +} +export async function makeV1Swap_nearUsdt({ + usdcMetadata, + usdtMetadata, + amountIn, + nonEstimateOutAmountWithSlippageTolerance, +}: { + usdcMetadata: TokenMetadata; + usdtMetadata: TokenMetadata; + amountIn: string; + nonEstimateOutAmountWithSlippageTolerance: string; +}) { + swapFromFourPool({ + tokenIn: usdcMetadata, + tokenOut: usdtMetadata, + amountIn, // NonDivisibleNumber + pool_id: four_pool_id, + min_amount_out: nonEstimateOutAmountWithSlippageTolerance, + }); +} diff --git a/src/stores/swapStore.ts b/src/stores/swapStore.ts new file mode 100644 index 000000000..f2b6f1ea1 --- /dev/null +++ b/src/stores/swapStore.ts @@ -0,0 +1,58 @@ +import { create, StateCreator } from 'zustand'; +import { createJSONStorage, persist } from 'zustand/middleware'; +import { PoolInfo } from '../services/swapV3'; +import { StablePool } from '../services/pool'; +import { TokenMetadata } from '../services/ft-contract'; +export interface INEAR_USDT_SWAP_TODOS { + tokenInAmount: string; + estimateOutAmount: string; + estimateOutAmountWithSlippageTolerance: string; + dcl_quote_amout: string; + dcl_quote_amout_real?: string; + nonEstimateOutAmount: string; + nonEstimateOutAmountWithSlippageTolerance: string; + mixTag: string; + quoteDone: boolean; + canSwap: boolean; + pools: [PoolInfo, StablePool]; + tokens: [TokenMetadata, TokenMetadata, TokenMetadata]; + slippageTolerance: number; + mixError: Error; + fee: number; + priceImpact: string; + accountId?: string; + process: '0' | '1' | '2' | '3'; // "0": dcl transaction has been processing, "1": "The dcl transaction has been completed", "2": "The v1 transaction has been processing", "3": "The v1 transaction has been completed" +} +export interface IPersistSwap { + near_usdt_swapTodos: INEAR_USDT_SWAP_TODOS; + near_usdt_swapTodos_transaction: INEAR_USDT_SWAP_TODOS; + set_near_usdt_swapTodos: (near_usdt_swapTodos: INEAR_USDT_SWAP_TODOS) => void; + set_near_usdt_swapTodos_transaction: ( + near_usdt_swapTodos_transaction: INEAR_USDT_SWAP_TODOS + ) => void; +} +type IPersistSwapState = IPersistSwap; +type IPersistSwapStore = StateCreator< + IPersistSwapState, + [], + [], + IPersistSwapState +>; +export const usePersistSwapStore = create()( + persist( + (set) => ({ + near_usdt_swapTodos: null, + near_usdt_swapTodos_transaction: null, + set_near_usdt_swapTodos: (near_usdt_swapTodos: INEAR_USDT_SWAP_TODOS) => + set({ near_usdt_swapTodos }), + set_near_usdt_swapTodos_transaction: ( + near_usdt_swapTodos_transaction: INEAR_USDT_SWAP_TODOS + ) => set({ near_usdt_swapTodos_transaction }), + }), + { + name: '_cached_swap', + version: 0.1, + storage: createJSONStorage(() => localStorage), + } + ) +); diff --git a/src/utils/swapConfig.ts b/src/utils/swapConfig.ts new file mode 100644 index 000000000..5dd659f87 --- /dev/null +++ b/src/utils/swapConfig.ts @@ -0,0 +1,12 @@ +const isTest = process.env.REACT_APP_NEAR_ENV == 'pub-testnet'; +export const token_near_id = isTest ? 'wrap.testnet' : 'wrap.near'; +export const token_usdt_id = isTest + ? 'usdt.fakes.testnet' + : 'usdt.tether-token.near'; +export const token_usdc_id = isTest + ? 'usdc.fakes.testnet' + : '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1'; +export const near_udsc_pool_id = isTest + ? 'usdc.fakes.testnet|wrap.testnet|2000' + : '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1|wrap.near|2000'; +export const four_stable_pool_id = isTest ? 218 : 4179; diff --git a/yarn.lock b/yarn.lock index 0e409fb57..b86f5caa3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2580,7 +2580,7 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== @@ -5782,6 +5782,11 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" +"@types/js-cookie@^2.2.6": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" + integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== + "@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.14" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" @@ -7543,6 +7548,11 @@ "@webassemblyjs/ast" "1.11.6" "@xtuc/long" "4.2.2" +"@xobotyi/scrollbar-width@^1.9.5": + version "1.9.5" + resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d" + integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -9705,6 +9715,13 @@ css-has-pseudo@^3.0.4: dependencies: postcss-selector-parser "^6.0.9" +css-in-js-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz#640ae6a33646d401fc720c54fc61c42cd76ae2bb" + integrity sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A== + dependencies: + hyphenate-style-name "^1.0.3" + css-loader@^6.5.1: version "6.8.1" resolved "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88" @@ -9915,6 +9932,11 @@ csstype@^3.0.2: resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== +csstype@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + customize-cra@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz#73286563631aa08127ad4d30a2e3c89cf4e93c8d" @@ -12009,6 +12031,16 @@ fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.0.8: resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== +fast-shallow-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b" + integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw== + +fastest-stable-stringify@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz#3757a6774f6ec8de40c4e86ec28ea02417214c76" + integrity sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q== + fastq@^1.6.0: version "1.15.0" resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -13109,6 +13141,11 @@ human-signals@^2.1.0: resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +hyphenate-style-name@^1.0.3: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz#1797bf50369588b47b72ca6d5e65374607cf4436" + integrity sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw== + i18next-browser-languagedetector@7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.1.0.tgz#01876fac51f86b78975e79b48ccb62e2313a2d7d" @@ -13240,6 +13277,13 @@ inline-style-parser@0.1.1: resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +inline-style-prefixer@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz#9310f3cfa2c6f3901d1480f373981c02691781e8" + integrity sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw== + dependencies: + css-in-js-utils "^3.1.0" + internal-slot@^1.0.5: version "1.0.6" resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" @@ -14677,6 +14721,11 @@ joi@17.9.1: "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" +js-cookie@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" + integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== + js-sha256@0.9.0, js-sha256@^0.9.0: version "0.9.0" resolved "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" @@ -15868,6 +15917,20 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" +nano-css@^5.3.1: + version "5.6.2" + resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.6.2.tgz#584884ddd7547278f6d6915b6805069742679a32" + integrity sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + css-tree "^1.1.2" + csstype "^3.1.2" + fastest-stable-stringify "^2.0.2" + inline-style-prefixer "^7.0.1" + rtl-css-js "^1.16.1" + stacktrace-js "^2.0.2" + stylis "^4.3.0" + nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.npmmirror.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -18361,11 +18424,36 @@ react-transition-group@2.9.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" +react-universal-interface@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" + integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== + react-use-websocket@^4.3.1: version "4.5.0" resolved "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.5.0.tgz#8e3a18c51328522876bfea28661521292d6f210a" integrity sha512-oxYVLWM3Lv0InCfjW7hG/Hk0hkE0P1SiLd5/I3d5x0W4riAnDUkD4VEu7qNVAqxNjBF3nU7k0jLMOetLXpwfsA== +react-use@17.4.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.4.0.tgz#cefef258b0a6c534a5c8021c2528ac6e1a4cdc6d" + integrity sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q== + dependencies: + "@types/js-cookie" "^2.2.6" + "@xobotyi/scrollbar-width" "^1.9.5" + copy-to-clipboard "^3.3.1" + fast-deep-equal "^3.1.3" + fast-shallow-equal "^1.0.0" + js-cookie "^2.2.1" + nano-css "^5.3.1" + react-universal-interface "^0.6.2" + resize-observer-polyfill "^1.5.1" + screenfull "^5.1.0" + set-harmonic-interval "^1.0.1" + throttle-debounce "^3.0.1" + ts-easing "^0.2.0" + tslib "^2.1.0" + react-useinterval@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/react-useinterval/-/react-useinterval-1.0.2.tgz#d9537b7e1a823422c70cb3dc226d07835ff15569" @@ -18690,6 +18778,11 @@ requires-port@^1.0.0: resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +resize-observer-polyfill@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.npmmirror.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -18879,6 +18972,13 @@ rsvp@^4.8.4: resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +rtl-css-js@^1.16.1: + version "1.16.1" + resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.16.1.tgz#4b48b4354b0ff917a30488d95100fbf7219a3e80" + integrity sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg== + dependencies: + "@babel/runtime" "^7.1.2" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -19054,6 +19154,11 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.1.0" +screenfull@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" + integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== + scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" @@ -19215,6 +19320,11 @@ set-function-name@^2.0.0, set-function-name@^2.0.1: functions-have-names "^1.2.3" has-property-descriptors "^1.0.0" +set-harmonic-interval@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" + integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g== + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -19531,6 +19641,11 @@ source-map-url@^0.4.0: resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA== + source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -19673,6 +19788,13 @@ stable@^0.1.8: resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-generator@^2.0.5: + version "2.0.10" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.10.tgz#8ae171e985ed62287d4f1ed55a1633b3fb53bb4d" + integrity sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ== + dependencies: + stackframe "^1.3.4" + stack-utils@^2.0.2, stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" @@ -19685,6 +19807,23 @@ stackframe@^1.3.4: resolved "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== +stacktrace-gps@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz#0c40b24a9b119b20da4525c398795338966a2fb0" + integrity sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ== + dependencies: + source-map "0.5.6" + stackframe "^1.3.4" + +stacktrace-js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + standard-as-callback@^2.1.0: version "2.1.0" resolved "https://registry.npmmirror.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" @@ -19951,6 +20090,11 @@ stylis@4.2.0: resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== +stylis@^4.3.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.4.tgz#ca5c6c4a35c4784e4e93a2a24dc4e9fa075250a4" + integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now== + sucrase@^3.32.0: version "3.34.0" resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f" @@ -20289,6 +20433,11 @@ throttle-debounce@^2.1.0: resolved "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz#fd31865e66502071e411817e241465b3e9c372e2" integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ== +throttle-debounce@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz#32f94d84dfa894f786c9a1f290e7a645b6a19abb" + integrity sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg== + through2@^2.0.0: version "2.0.5" resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -20469,6 +20618,11 @@ ts-api-utils@^1.0.1: resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-easing@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" + integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== + ts-essentials@7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38"