From c9f6599e6750bdd91de8c4593981925ce19902aa Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sun, 17 Apr 2022 10:14:32 +0900 Subject: [PATCH 01/60] feat: stop-loss view --- src/components/Header/useMenu.tsx | 12 ++ src/config/features.ts | 12 +- src/enums/Feature.ts | 1 + src/features/trade/HeaderNew.tsx | 11 ++ src/pages/stop-loss/[[...tokens]].tsx | 174 ++++++++++++++++++++++++++ src/pages/stop-loss/history.tsx | 46 +++++++ src/pages/stop-loss/open.tsx | 46 +++++++ 7 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 src/pages/stop-loss/[[...tokens]].tsx create mode 100644 src/pages/stop-loss/history.tsx create mode 100644 src/pages/stop-loss/open.tsx diff --git a/src/components/Header/useMenu.tsx b/src/components/Header/useMenu.tsx index f34d87a415..ccd504b721 100644 --- a/src/components/Header/useMenu.tsx +++ b/src/components/Header/useMenu.tsx @@ -47,6 +47,12 @@ const useMenu: UseMenu = () => { link: '/limit-order', disabled: !featureEnabled(Feature.LIMIT_ORDERS, chainId), }, + { + key: 'stop', + title: i18n._(t`Stop loss`), + link: '/stop-loss', + disabled: !featureEnabled(Feature.STOP_LOSSES, chainId), + }, ] const liquidity = [ @@ -97,6 +103,12 @@ const useMenu: UseMenu = () => { link: '/limit-order', disabled: !featureEnabled(Feature.LIMIT_ORDERS, chainId), }, + { + key: 'stop', + title: i18n._(t`Stop loss`), + link: '/stop-loss', + disabled: !featureEnabled(Feature.STOP_LOSSES, chainId), + }, ].filter((item) => !item.disabled), }) menu.push({ diff --git a/src/config/features.ts b/src/config/features.ts index 8f535f1ab9..60e679ecc0 100644 --- a/src/config/features.ts +++ b/src/config/features.ts @@ -17,6 +17,7 @@ const features: FeatureMap = { Feature.INARI, Feature.VESTING, Feature.LIMIT_ORDERS, + Feature.STOP_LOSSES, Feature.SUSHIGUARD, ], [ChainId.ROPSTEN]: [Feature.AMM, Feature.LIQUIDITY_MINING, Feature.BENTOBOX, Feature.KASHI, Feature.MISO], @@ -36,6 +37,7 @@ const features: FeatureMap = { Feature.AMM, Feature.ANALYTICS, Feature.LIMIT_ORDERS, + Feature.STOP_LOSSES, Feature.LIQUIDITY_MINING, Feature.ANALYTICS, Feature.BENTOBOX, @@ -49,13 +51,21 @@ const features: FeatureMap = { Feature.MIGRATE, Feature.ANALYTICS, Feature.LIMIT_ORDERS, + Feature.STOP_LOSSES, Feature.TRIDENT, Feature.MISO, ], [ChainId.MATIC_TESTNET]: [Feature.AMM], [ChainId.HARMONY]: [Feature.AMM, Feature.LIQUIDITY_MINING, Feature.ANALYTICS, Feature.MISO], [ChainId.HARMONY_TESTNET]: [Feature.AMM], - [ChainId.AVALANCHE]: [Feature.AMM, Feature.BENTOBOX, Feature.KASHI, Feature.LIMIT_ORDERS, Feature.ANALYTICS], + [ChainId.AVALANCHE]: [ + Feature.AMM, + Feature.BENTOBOX, + Feature.KASHI, + Feature.LIMIT_ORDERS, + Feature.STOP_LOSSES, + Feature.ANALYTICS, + ], [ChainId.AVALANCHE_TESTNET]: [Feature.AMM], [ChainId.OKEX]: [Feature.AMM], [ChainId.OKEX_TESTNET]: [Feature.AMM], diff --git a/src/enums/Feature.ts b/src/enums/Feature.ts index 4cf60fdba4..bba7efe12f 100644 --- a/src/enums/Feature.ts +++ b/src/enums/Feature.ts @@ -10,6 +10,7 @@ export enum Feature { STAKING = 'Staking', TRIDENT = 'Trident', LIMIT_ORDERS = 'LimitOrders', + STOP_LOSSES = 'StopLosses', INARI = 'Inari', MEOWSHI = 'MEOWSHI', VESTING = 'Vesting', diff --git a/src/features/trade/HeaderNew.tsx b/src/features/trade/HeaderNew.tsx index 0b54f91aa8..d512ff9035 100644 --- a/src/features/trade/HeaderNew.tsx +++ b/src/features/trade/HeaderNew.tsx @@ -56,6 +56,17 @@ const HeaderNew: FC = ({ inputCurrency, outputCurrency, trident {i18n._(t`Limit`)} + + + {i18n._(t`Stop`)} + +
{isLimitOrder && } diff --git a/src/pages/stop-loss/[[...tokens]].tsx b/src/pages/stop-loss/[[...tokens]].tsx new file mode 100644 index 0000000000..602780421f --- /dev/null +++ b/src/pages/stop-loss/[[...tokens]].tsx @@ -0,0 +1,174 @@ +import { SwitchVerticalIcon } from '@heroicons/react/outline' +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { Percent } from '@sushiswap/core-sdk' +import limitOrderPairList from '@sushiswap/limit-order-pair-list/dist/limit-order.pairlist.json' +import RecipientField from 'app/components/RecipientField' +import Typography from 'app/components/Typography' +import { ZERO_PERCENT } from 'app/constants' +import { Feature } from 'app/enums' +import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' +import LimitOrderButton from 'app/features/legacy/limit-order/LimitOrderButton' +import LimitOrderReviewModal from 'app/features/legacy/limit-order/LimitOrderReviewModal' +import LimitPriceInputPanel from 'app/features/legacy/limit-order/LimitPriceInputPanel' +import OrderExpirationDropdown from 'app/features/legacy/limit-order/OrderExpirationDropdown' +import HeaderNew from 'app/features/trade/HeaderNew' +import SwapAssetPanel from 'app/features/trident/swap/SwapAssetPanel' +import { featureEnabled } from 'app/functions' +import NetworkGuard from 'app/guards/Network' +import { SwapLayout, SwapLayoutCard } from 'app/layouts/SwapLayout' +import { useActiveWeb3React } from 'app/services/web3' +import { useAppDispatch } from 'app/state/hooks' +import { Field, setFromBentoBalance, setRecipient } from 'app/state/limit-order/actions' +import useLimitOrderDerivedCurrencies, { + useLimitOrderActionHandlers, + useLimitOrderDerivedLimitPrice, + useLimitOrderDerivedParsedAmounts, + useLimitOrderDerivedTrade, + useLimitOrderState, +} from 'app/state/limit-order/hooks' +import { useExpertModeManager } from 'app/state/user/hooks' +import { NextSeo } from 'next-seo' +import React, { useMemo } from 'react' + +const LimitOrder = () => { + const { i18n } = useLingui() + const dispatch = useAppDispatch() + const { chainId } = useActiveWeb3React() + const [isExpertMode] = useExpertModeManager() + const { typedField, typedValue, fromBentoBalance, recipient } = useLimitOrderState() + const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() + const trade = useLimitOrderDerivedTrade() + const rate = useLimitOrderDerivedLimitPrice() + const parsedAmounts = useLimitOrderDerivedParsedAmounts({ rate, trade }) + const { onSwitchTokens, onCurrencySelection, onUserInput } = useLimitOrderActionHandlers() + + const pairs = useMemo( + // @ts-ignore TYPE NEEDS FIXING + () => (limitOrderPairList.pairs[chainId || 1] || []).map(([token0, token1]) => [token0.address, token1.address]), + [chainId] + ) + + const inputPanelHelperText = useMemo(() => { + if (rate && trade) { + const { numerator, denominator } = rate.subtract(trade.executionPrice).divide(trade.executionPrice) + return new Percent(numerator, denominator) + } + }, [rate, trade]) + + const inputTokenList = useMemo(() => { + if (pairs.length === 0) return [] + // @ts-ignore TYPE NEEDS FIXING + return pairs.reduce((acc, [token0, token1]) => { + acc.push(token0) + acc.push(token1) + return acc + }, []) + }, [pairs]) + + const outputTokenList = useMemo(() => { + if (pairs.length === 0) return [] + if (inputCurrency) { + // @ts-ignore TYPE NEEDS FIXING + return pairs.reduce((acc, [token0, token1]) => { + if (inputCurrency.wrapped.address === token0) acc.push(token1) + if (inputCurrency.wrapped.address === token1) acc.push(token0) + return acc + }, []) + } + // @ts-ignore TYPE NEEDS FIXING + return pairs.reduce((acc, [token0, token1]) => { + acc.push(token0) + acc.push(token1) + return acc + }, []) + }, [inputCurrency, pairs]) + + return ( + <> + + + +
+ {chainId && ( + + )} +
+
+ ( + dispatch(setFromBentoBalance(!fromBentoBalance))} + /> + )} + selected={true} + spendFromWallet={!fromBentoBalance} + currency={inputCurrency} + value={(typedField === Field.INPUT ? typedValue : parsedAmounts?.inputAmount?.toSignificant(6)) || ''} + onChange={(value) => onUserInput(Field.INPUT, value || '')} + onSelect={(inputCurrency) => onCurrencySelection(Field.INPUT, inputCurrency)} + currencies={inputTokenList} + /> +
+
+ +
+ +
+ +
+
+ onUserInput(Field.OUTPUT, value || '')} + onSelect={(outputCurrency) => onCurrencySelection(Field.OUTPUT, outputCurrency)} + currencies={outputTokenList} + priceImpact={inputPanelHelperText} + priceImpactCss={inputPanelHelperText?.greaterThan(ZERO_PERCENT) ? 'text-green' : 'text-red'} + /> +
+ + {isExpertMode && } + + +
+ + {i18n._(t`Stop orders use funds from BentoBox, to create a stop order depositing into BentoBox is required.`)} + + + + Tip + + :{' '} + {i18n._(t`When expert mode is enabled, balance isn't checked when creating orders. You can use this to chain stop + orders.`)} + + + ) +} + +LimitOrder.Guard = NetworkGuard(Feature.LIMIT_ORDERS) +LimitOrder.Layout = SwapLayout('limit-order-page') + +export default LimitOrder diff --git a/src/pages/stop-loss/history.tsx b/src/pages/stop-loss/history.tsx new file mode 100644 index 0000000000..e28381710e --- /dev/null +++ b/src/pages/stop-loss/history.tsx @@ -0,0 +1,46 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' +import Typography from 'app/components/Typography' +import { Feature } from 'app/enums' +import CompletedOrders from 'app/features/legacy/limit-order/CompletedOrders' +import DiscoverHeader from 'app/features/legacy/limit-order/DiscoverHeader' +import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' +import OrdersTableToggle from 'app/features/legacy/limit-order/OrderTableToggle' +import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import NetworkGuard from 'app/guards/Network' +import { TridentBody } from 'app/layouts/Trident' +import { useActiveWeb3React } from 'app/services/web3' +import { useBentoMasterContractAllowed } from 'app/state/bentobox/hooks' +import React from 'react' + +function OpenOrdersPage() { + const { chainId, account } = useActiveWeb3React() + const { i18n } = useLingui() + const { pending } = useLimitOrders() + const masterContract = chainId ? STOP_LIMIT_ORDER_ADDRESS[chainId] : undefined + const allowed = useBentoMasterContractAllowed(masterContract, account ?? undefined) + + return ( + <> + + + + {pending.totalOrders > 0 && typeof allowed !== 'undefined' && !allowed && ( +
+ + {i18n._(t`It seems like you have open orders while the limit order master contract is not yet approved. Please make + sure you have approved the limit order master contract or the order will not execute`)} + +
+ )} + + +
+ + ) +} + +OpenOrdersPage.Guard = NetworkGuard(Feature.LIMIT_ORDERS) + +export default OpenOrdersPage diff --git a/src/pages/stop-loss/open.tsx b/src/pages/stop-loss/open.tsx new file mode 100644 index 0000000000..5553dd4915 --- /dev/null +++ b/src/pages/stop-loss/open.tsx @@ -0,0 +1,46 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' +import Typography from 'app/components/Typography' +import { Feature } from 'app/enums' +import DiscoverHeader from 'app/features/legacy/limit-order/DiscoverHeader' +import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' +import OpenOrders from 'app/features/legacy/limit-order/OpenOrders' +import OrdersTableToggle from 'app/features/legacy/limit-order/OrderTableToggle' +import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import NetworkGuard from 'app/guards/Network' +import { TridentBody } from 'app/layouts/Trident' +import { useActiveWeb3React } from 'app/services/web3' +import { useBentoMasterContractAllowed } from 'app/state/bentobox/hooks' +import React from 'react' + +function OpenOrdersPage() { + const { chainId, account } = useActiveWeb3React() + const { i18n } = useLingui() + const { pending } = useLimitOrders() + const masterContract = chainId ? STOP_LIMIT_ORDER_ADDRESS[chainId] : undefined + const allowed = useBentoMasterContractAllowed(masterContract, account ?? undefined) + + return ( + <> + + + + {pending.totalOrders > 0 && typeof allowed !== 'undefined' && !allowed && ( +
+ + {i18n._(t`It seems like you have open orders while the limit order master contract is not yet approved. Please make + sure you have approved the limit order master contract or the order will not execute`)} + +
+ )} + + +
+ + ) +} + +OpenOrdersPage.Guard = NetworkGuard(Feature.LIMIT_ORDERS) + +export default OpenOrdersPage From fe345271cf04e1203fffac7c0815751c423f4725 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 19 Apr 2022 01:37:57 +0900 Subject: [PATCH 02/60] feat: integrate autonomy for stop-loss --- src/constants/abis/autonomy-registry.json | 1 + src/constants/index.ts | 5 + src/pages/stop-loss/StopLossReviewModal.tsx | 131 +++++++++++++++++ src/pages/stop-loss/[[...tokens]].tsx | 15 +- src/pages/stop-loss/useStopLossExecute.ts | 150 ++++++++++++++++++++ 5 files changed, 295 insertions(+), 7 deletions(-) create mode 100644 src/constants/abis/autonomy-registry.json create mode 100644 src/pages/stop-loss/StopLossReviewModal.tsx create mode 100644 src/pages/stop-loss/useStopLossExecute.ts diff --git a/src/constants/abis/autonomy-registry.json b/src/constants/abis/autonomy-registry.json new file mode 100644 index 0000000000..4a602cfa5f --- /dev/null +++ b/src/constants/abis/autonomy-registry.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IStakeManager","name":"stakeMan","type":"address"},{"internalType":"contract IOracle","name":"oracle","type":"address"},{"internalType":"contract IForwarder","name":"userForwarder","type":"address"},{"internalType":"contract IForwarder","name":"gasForwarder","type":"address"},{"internalType":"contract IForwarder","name":"userGasForwarder","type":"address"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"},{"internalType":"uint256","name":"totalAUTOSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"address payable","name":"referer","type":"address"},{"indexed":false,"internalType":"bytes","name":"callData","type":"bytes"},{"indexed":false,"internalType":"uint112","name":"initEthSent","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"ethForCall","type":"uint112"},{"indexed":false,"internalType":"bool","name":"verifyUser","type":"bool"},{"indexed":false,"internalType":"bool","name":"insertFeeAmount","type":"bool"},{"indexed":false,"internalType":"bool","name":"payWithAUTO","type":"bool"},{"indexed":false,"internalType":"bool","name":"isAlive","type":"bool"}],"name":"HashedReqAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"HashedReqCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bool","name":"wasRemoved","type":"bool"}],"name":"HashedReqExecuted","type":"event"},{"inputs":[],"name":"BASE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GAS_OVERHEAD_AUTO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GAS_OVERHEAD_ETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAY_AUTO_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAY_ETH_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"address payable","name":"user","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"address payable","name":"referer","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint112","name":"initEthSent","type":"uint112"},{"internalType":"uint112","name":"ethForCall","type":"uint112"},{"internalType":"bool","name":"verifyUser","type":"bool"},{"internalType":"bool","name":"insertFeeAmount","type":"bool"},{"internalType":"bool","name":"payWithAUTO","type":"bool"},{"internalType":"bool","name":"isAlive","type":"bool"}],"internalType":"struct IRegistry.Request","name":"r","type":"tuple"}],"name":"cancelHashedReq","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"address payable","name":"user","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"address payable","name":"referer","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint112","name":"initEthSent","type":"uint112"},{"internalType":"uint112","name":"ethForCall","type":"uint112"},{"internalType":"bool","name":"verifyUser","type":"bool"},{"internalType":"bool","name":"insertFeeAmount","type":"bool"},{"internalType":"bool","name":"payWithAUTO","type":"bool"},{"internalType":"bool","name":"isAlive","type":"bool"}],"internalType":"struct IRegistry.Request","name":"r","type":"tuple"},{"internalType":"uint256","name":"expectedGas","type":"uint256"}],"name":"executeHashedReq","outputs":[{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAUTOAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getExecCountOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGasForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getHashedReq","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHashedReqs","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHashedReqsLen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIdx","type":"uint256"},{"internalType":"uint256","name":"endIdx","type":"uint256"}],"name":"getHashedReqsSlice","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getReferalCountOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"user","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"address payable","name":"referer","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint112","name":"initEthSent","type":"uint112"},{"internalType":"uint112","name":"ethForCall","type":"uint112"},{"internalType":"bool","name":"verifyUser","type":"bool"},{"internalType":"bool","name":"insertFeeAmount","type":"bool"},{"internalType":"bool","name":"payWithAUTO","type":"bool"},{"internalType":"bool","name":"isAlive","type":"bool"}],"internalType":"struct IRegistry.Request","name":"r","type":"tuple"}],"name":"getReqBytes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getReqCountOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakeManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserGasForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"expectedGas","type":"uint256"},{"internalType":"uint256","name":"startIdx","type":"uint256"}],"name":"insertToCallData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address payable","name":"referer","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint112","name":"ethForCall","type":"uint112"},{"internalType":"bool","name":"verifyUser","type":"bool"},{"internalType":"bool","name":"insertFeeAmount","type":"bool"},{"internalType":"bool","name":"isAlive","type":"bool"}],"name":"newReq","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address payable","name":"referer","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint112","name":"ethForCall","type":"uint112"},{"internalType":"bool","name":"verifyUser","type":"bool"},{"internalType":"bool","name":"insertFeeAmount","type":"bool"},{"internalType":"bool","name":"payWithAUTO","type":"bool"},{"internalType":"bool","name":"isAlive","type":"bool"}],"name":"newReqPaySpecific","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/src/constants/index.ts b/src/constants/index.ts index 0ec1eed3aa..9216aee0b4 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -84,3 +84,8 @@ export const EIP_1559_ACTIVATION_BLOCK: { [chainId in ChainId]?: number } = { export const DEFAULT_TXN_DISMISS_MS = 25000 export const IS_IN_IFRAME = typeof window !== 'undefined' && window.parent !== window + +export const AUTONOMY_REGISTRY_ADDRESSES: { [chainId in ChainId]?: string } = { + [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', + [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', +} diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx new file mode 100644 index 0000000000..f8b5e4b1b7 --- /dev/null +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -0,0 +1,131 @@ +import { ArrowDownIcon } from '@heroicons/react/outline' +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { Currency, CurrencyAmount, Percent, Price, Trade, TradeType, ZERO } from '@sushiswap/core-sdk' +import Button from 'app/components/Button' +import ListPanel from 'app/components/ListPanel' +import { HeadlessUiModal } from 'app/components/Modal' +import Typography from 'app/components/Typography' +import TradePrice from 'app/features/legacy/swap/TradePrice' +import { isAddress, shortenAddress } from 'app/functions' +import { useAppDispatch } from 'app/state/hooks' +import { setLimitOrderShowReview } from 'app/state/limit-order/actions' +import { useLimitOrderState } from 'app/state/limit-order/hooks' +import React, { FC, useCallback, useMemo, useState } from 'react' + +import useStopLossExecute from './useStopLossExecute' + +interface StopLossReviewModal { + trade?: Trade + limitPrice?: Price + parsedAmounts: { + inputAmount?: CurrencyAmount + outputAmount?: CurrencyAmount + } +} + +const StopLossReviewModal: FC = ({ parsedAmounts, trade, limitPrice }) => { + const [inverted, setInverted] = useState(false) + const { showReview, orderExpiration, recipient, attemptingTxn } = useLimitOrderState() + const dispatch = useAppDispatch() + const { i18n } = useLingui() + const { execute } = useStopLossExecute() + + const _execute = useCallback(() => { + if (parsedAmounts?.inputAmount && parsedAmounts?.outputAmount) { + execute({ + orderExpiration: orderExpiration.value, + recipient, + outputAmount: parsedAmounts.outputAmount, + inputAmount: parsedAmounts.inputAmount, + }) + } + }, [execute, orderExpiration.value, parsedAmounts.inputAmount, parsedAmounts.outputAmount, recipient]) + + const deviation = useMemo(() => { + if (limitPrice && trade) { + const { numerator, denominator } = limitPrice.subtract(trade.executionPrice).divide(trade.executionPrice) + return new Percent(numerator, denominator) + } + }, [limitPrice, trade]) + + return ( + dispatch(setLimitOrderShowReview(false))} + maxWidth="sm" + > +
+ dispatch(setLimitOrderShowReview(false))} + /> + + + {i18n._(t`You'll pay`)} + + ]} /> +
+ +
+ + {i18n._(t`You'll receive`)} + + ]} /> +
+ + {recipient && ( +
+ + {i18n._(t`Recipient`)} + + + {isAddress(recipient) && shortenAddress(recipient)} + +
+ )} +
+ + {i18n._(t`Expiration`)} + + + {orderExpiration.label} + +
+
+
+ + {i18n._(t`Rate`)} + + +
+ {deviation && ( +
+ + {deviation.toSignificant(2)}% {deviation?.greaterThan(ZERO) ? 'above' : 'below'} market rate + +
+ )} +
+
+ + {i18n._(t`Please note that after order execution, your tokens will be received in your BentoBox`)} + + +
+
+ ) +} + +export default StopLossReviewModal diff --git a/src/pages/stop-loss/[[...tokens]].tsx b/src/pages/stop-loss/[[...tokens]].tsx index 602780421f..11986bd080 100644 --- a/src/pages/stop-loss/[[...tokens]].tsx +++ b/src/pages/stop-loss/[[...tokens]].tsx @@ -9,7 +9,6 @@ import { ZERO_PERCENT } from 'app/constants' import { Feature } from 'app/enums' import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' import LimitOrderButton from 'app/features/legacy/limit-order/LimitOrderButton' -import LimitOrderReviewModal from 'app/features/legacy/limit-order/LimitOrderReviewModal' import LimitPriceInputPanel from 'app/features/legacy/limit-order/LimitPriceInputPanel' import OrderExpirationDropdown from 'app/features/legacy/limit-order/OrderExpirationDropdown' import HeaderNew from 'app/features/trade/HeaderNew' @@ -31,7 +30,9 @@ import { useExpertModeManager } from 'app/state/user/hooks' import { NextSeo } from 'next-seo' import React, { useMemo } from 'react' -const LimitOrder = () => { +import StopLossReviewModal from './StopLossReviewModal' + +const StopLoss = () => { const { i18n } = useLingui() const dispatch = useAppDispatch() const { chainId } = useActiveWeb3React() @@ -86,7 +87,7 @@ const LimitOrder = () => { return ( <> - +
@@ -147,7 +148,7 @@ const LimitOrder = () => { {isExpertMode && } - { ) } -LimitOrder.Guard = NetworkGuard(Feature.LIMIT_ORDERS) -LimitOrder.Layout = SwapLayout('limit-order-page') +StopLoss.Guard = NetworkGuard(Feature.LIMIT_ORDERS) +StopLoss.Layout = SwapLayout('limit-order-page') -export default LimitOrder +export default StopLoss diff --git a/src/pages/stop-loss/useStopLossExecute.ts b/src/pages/stop-loss/useStopLossExecute.ts new file mode 100644 index 0000000000..c388055f05 --- /dev/null +++ b/src/pages/stop-loss/useStopLossExecute.ts @@ -0,0 +1,150 @@ +import { Signature } from '@ethersproject/bytes' +import { AddressZero } from '@ethersproject/constants' +import { TransactionResponse } from '@ethersproject/providers' +import { Currency, CurrencyAmount } from '@sushiswap/core-sdk' +import { ADVANCED_RECEIVER_ADDRESS, LimitOrder } from '@sushiswap/limit-order-sdk' +import { AUTONOMY_REGISTRY_ADDRESSES } from 'app/constants' +import AUTONOMY_REGISTRY_ABI from 'app/constants/abis/autonomy-registry.json' +import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import { ZERO } from 'app/functions' +import { useContract, useLimitOrderContract } from 'app/hooks' +import { useActiveWeb3React } from 'app/services/web3' +import { useAddPopup } from 'app/state/application/hooks' +import { useAppDispatch } from 'app/state/hooks' +import { setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions' +import { OrderExpiration } from 'app/state/limit-order/reducer' +import { useCallback } from 'react' + +const getEndTime = (orderExpiration: OrderExpiration | string): number => { + switch (orderExpiration) { + case OrderExpiration.hour: + return Math.floor(new Date().getTime() / 1000) + 3600 + case OrderExpiration.day: + return Math.floor(new Date().getTime() / 1000) + 86400 + case OrderExpiration.week: + return Math.floor(new Date().getTime() / 1000) + 604800 + case OrderExpiration.never: + default: + return Number.MAX_SAFE_INTEGER + } +} + +export type DepositAndApprovePayload = { inputAmount: CurrencyAmount; bentoPermit: Signature } +export type DepositPayload = { + inputAmount?: CurrencyAmount + bentoPermit?: Signature + fromBentoBalance: boolean +} +export type ExecutePayload = { + orderExpiration: OrderExpiration | string + inputAmount?: CurrencyAmount + outputAmount?: CurrencyAmount + recipient?: string +} + +export type UseLimitOrderExecuteDeposit = (x: DepositPayload) => Promise +export type UseLimitOrderExecuteExecute = (x: ExecutePayload) => void +export type UseLimitOrderExecute = () => { + execute: UseLimitOrderExecuteExecute +} + +const useStopLossExecute: UseLimitOrderExecute = () => { + const { account, chainId, library } = useActiveWeb3React() + + const autonomyRegistryContract = useContract( + chainId ? AUTONOMY_REGISTRY_ADDRESSES[chainId] : undefined, + AUTONOMY_REGISTRY_ABI, + true + ) + const limitOrderContract = useLimitOrderContract() + + const dispatch = useAppDispatch() + const addPopup = useAddPopup() + const { mutate } = useLimitOrders() + + const execute = useCallback( + async ({ orderExpiration, inputAmount, outputAmount, recipient }) => { + if (!inputAmount || !outputAmount || !account || !library) throw new Error('Dependencies unavailable') + + const endTime = getEndTime(orderExpiration) + const order = new LimitOrder( + account, + inputAmount.wrapped, + outputAmount.wrapped, + recipient ? recipient : account, + Math.floor(new Date().getTime() / 1000).toString(), + endTime.toString() + ) + + try { + dispatch(setLimitOrderAttemptingTxn(true)) + await order?.signOrderWithProvider(chainId || 1, library) + + if (limitOrderContract) { + const encodedFillOrderData = limitOrderContract.interface.encodeFunctionData('fillOrder', [ + [ + order.maker, + order.amountInRaw, + order.amountOutRaw, + order.recipient, + order.startTime, + order.endTime, + order.stopPrice, + order.oracleAddress, + order.oracleData, + order.amountInRaw, + order.v, + order.r, + order.s, + ], + order.tokenInAddress, + order.tokenOutAddress, + chainId && ADVANCED_RECEIVER_ADDRESS[chainId], + [], + ]) + console.log('encoded fillOrder() data: ', JSON.stringify(encodedFillOrderData)) + + await autonomyRegistryContract.newReq( + limitOrderContract.address, + AddressZero, + encodedFillOrderData, + ZERO, + false, + false, + false + ) + } + + // const resp = await order?.send() + // if (resp.success) { + // addPopup({ + // txn: { hash: '', summary: 'Limit order created', success: true }, + // }) + + // await mutate() + // dispatch(clear()) + // } + + dispatch(setLimitOrderAttemptingTxn(false)) + } catch (e) { + console.log('Error: ', e) + dispatch(setLimitOrderAttemptingTxn(false)) + addPopup({ + txn: { + hash: '', + // @ts-ignore TYPE NEEDS FIXING + summary: `Error: ${e?.response?.data?.data}`, + success: false, + }, + }) + } + }, + [account, addPopup, chainId, dispatch, library, autonomyRegistryContract, limitOrderContract] + ) + + return { + execute, + } +} + +export default useStopLossExecute From 383efbb8229ee93796486080b9304928f314a846 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 19 Apr 2022 02:06:14 +0900 Subject: [PATCH 03/60] fix: autonomy addresses --- src/constants/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constants/index.ts b/src/constants/index.ts index 9216aee0b4..c86a440360 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,4 +1,4 @@ -import { ChainId, JSBI, Percent } from '@sushiswap/core-sdk' +import { AddressMap, ChainId, JSBI, Percent } from '@sushiswap/core-sdk' // TODO: Move some of this to config level... @@ -85,7 +85,7 @@ export const DEFAULT_TXN_DISMISS_MS = 25000 export const IS_IN_IFRAME = typeof window !== 'undefined' && window.parent !== window -export const AUTONOMY_REGISTRY_ADDRESSES: { [chainId in ChainId]?: string } = { +export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', } From dd4644256e839e596e12f020b540a72ae2303dc4 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 19 Apr 2022 02:16:30 +0900 Subject: [PATCH 04/60] fix: autonomy validation --- src/pages/stop-loss/useStopLossExecute.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/stop-loss/useStopLossExecute.ts b/src/pages/stop-loss/useStopLossExecute.ts index c388055f05..0276c3d14e 100644 --- a/src/pages/stop-loss/useStopLossExecute.ts +++ b/src/pages/stop-loss/useStopLossExecute.ts @@ -80,7 +80,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { dispatch(setLimitOrderAttemptingTxn(true)) await order?.signOrderWithProvider(chainId || 1, library) - if (limitOrderContract) { + if (limitOrderContract && autonomyRegistryContract) { const encodedFillOrderData = limitOrderContract.interface.encodeFunctionData('fillOrder', [ [ order.maker, From a5aa1a0c99294fd3e5d5f712f621bc90142eabbc Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 19 Apr 2022 21:37:18 +0900 Subject: [PATCH 05/60] feat: add autonomy reg of avax --- src/constants/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/constants/index.ts b/src/constants/index.ts index c86a440360..ccccd45ae8 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -88,4 +88,5 @@ export const IS_IN_IFRAME = typeof window !== 'undefined' && window.parent !== w export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', + [ChainId.AVALANCHE]: '0x68FCbECa74A7E5D386f74E14682c94DE0e1bC56b', } From 301aec72f16a768005b92bb066243ff90c8b8a34 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 26 Apr 2022 22:57:29 +0900 Subject: [PATCH 06/60] fix: stop-loss by autonomy bot --- .../registry.json} | 0 .../autonomy/stop-limit-order-wrapper.json | 1 + src/constants/autonomy.ts | 12 ++++ src/constants/index.ts | 8 +-- src/pages/stop-loss/useStopLossExecute.ts | 56 ++++++++++++++----- src/pages/stop-loss/utils.ts | 44 +++++++++++++++ 6 files changed, 100 insertions(+), 21 deletions(-) rename src/constants/abis/{autonomy-registry.json => autonomy/registry.json} (100%) create mode 100644 src/constants/abis/autonomy/stop-limit-order-wrapper.json create mode 100644 src/constants/autonomy.ts create mode 100644 src/pages/stop-loss/utils.ts diff --git a/src/constants/abis/autonomy-registry.json b/src/constants/abis/autonomy/registry.json similarity index 100% rename from src/constants/abis/autonomy-registry.json rename to src/constants/abis/autonomy/registry.json diff --git a/src/constants/abis/autonomy/stop-limit-order-wrapper.json b/src/constants/abis/autonomy/stop-limit-order-wrapper.json new file mode 100644 index 0000000000..b4a98f999c --- /dev/null +++ b/src/constants/abis/autonomy/stop-limit-order-wrapper.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address payable","name":"registry_","type":"address"},{"internalType":"address","name":"gasFeeForwarder_","type":"address"},{"internalType":"address","name":"bentoBox_","type":"address"},{"internalType":"address","name":"stopLimitOrderContract_","type":"address"},{"internalType":"address","name":"WETH_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bentoBox","outputs":[{"internalType":"contract IBentoBoxV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"components":[{"internalType":"address","name":"maker","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"stopPrice","type":"uint256"},{"internalType":"contract IOracle","name":"oracleAddress","type":"address"},{"internalType":"bytes","name":"oracleData","type":"bytes"},{"internalType":"uint256","name":"amountToFill","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct OrderArgs","name":"order","type":"tuple"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"fillOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gasFeeForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stopLimitOrderContract","outputs":[{"internalType":"contract IStopLimitOrder","name":"","type":"address"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts new file mode 100644 index 0000000000..abc7c5193b --- /dev/null +++ b/src/constants/autonomy.ts @@ -0,0 +1,12 @@ +import { AddressMap, ChainId } from '@sushiswap/core-sdk' + +export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { + [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', + [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', + [ChainId.AVALANCHE]: '0x68FCbECa74A7E5D386f74E14682c94DE0e1bC56b', +} + +export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { + [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', + [ChainId.AVALANCHE]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', +} diff --git a/src/constants/index.ts b/src/constants/index.ts index ccccd45ae8..0ec1eed3aa 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,4 +1,4 @@ -import { AddressMap, ChainId, JSBI, Percent } from '@sushiswap/core-sdk' +import { ChainId, JSBI, Percent } from '@sushiswap/core-sdk' // TODO: Move some of this to config level... @@ -84,9 +84,3 @@ export const EIP_1559_ACTIVATION_BLOCK: { [chainId in ChainId]?: number } = { export const DEFAULT_TXN_DISMISS_MS = 25000 export const IS_IN_IFRAME = typeof window !== 'undefined' && window.parent !== window - -export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { - [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', - [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', - [ChainId.AVALANCHE]: '0x68FCbECa74A7E5D386f74E14682c94DE0e1bC56b', -} diff --git a/src/pages/stop-loss/useStopLossExecute.ts b/src/pages/stop-loss/useStopLossExecute.ts index 0276c3d14e..7d7f6c7544 100644 --- a/src/pages/stop-loss/useStopLossExecute.ts +++ b/src/pages/stop-loss/useStopLossExecute.ts @@ -1,10 +1,12 @@ +import { defaultAbiCoder } from '@ethersproject/abi' import { Signature } from '@ethersproject/bytes' import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount } from '@sushiswap/core-sdk' -import { ADVANCED_RECEIVER_ADDRESS, LimitOrder } from '@sushiswap/limit-order-sdk' -import { AUTONOMY_REGISTRY_ADDRESSES } from 'app/constants' -import AUTONOMY_REGISTRY_ABI from 'app/constants/abis/autonomy-registry.json' +import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sdk' +import AUTONOMY_REGISTRY_ABI from 'app/constants/abis/autonomy/registry.json' +import STOP_LIMIT_ORDER_WRAPPER_ABI from 'app/constants/abis/autonomy/stop-limit-order-wrapper.json' +import { AUTONOMY_REGISTRY_ADDRESSES, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' import { useContract, useLimitOrderContract } from 'app/hooks' @@ -15,6 +17,8 @@ import { setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions' import { OrderExpiration } from 'app/state/limit-order/reducer' import { useCallback } from 'react' +import { calculateAmountExternal, IStopLimitOrderReceiverParam } from './utils' + const getEndTime = (orderExpiration: OrderExpiration | string): number => { switch (orderExpiration) { case OrderExpiration.hour: @@ -56,6 +60,11 @@ const useStopLossExecute: UseLimitOrderExecute = () => { AUTONOMY_REGISTRY_ABI, true ) + const limitOrderWrapperContract = useContract( + chainId ? STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId] : undefined, + STOP_LIMIT_ORDER_WRAPPER_ABI, + true + ) const limitOrderContract = useLimitOrderContract() const dispatch = useAppDispatch() @@ -80,8 +89,27 @@ const useStopLossExecute: UseLimitOrderExecute = () => { dispatch(setLimitOrderAttemptingTxn(true)) await order?.signOrderWithProvider(chainId || 1, library) - if (limitOrderContract && autonomyRegistryContract) { - const encodedFillOrderData = limitOrderContract.interface.encodeFunctionData('fillOrder', [ + if (limitOrderContract && autonomyRegistryContract && limitOrderWrapperContract && chainId) { + const limitOrderReceiverParam: IStopLimitOrderReceiverParam = calculateAmountExternal( + inputAmount.wrapped, + outputAmount.wrapped, + chainId + ) + if (!limitOrderReceiverParam.isValidPair) { + throw 'Unsupported pair' + } + const data = defaultAbiCoder.encode( + ['address[]', 'uint256', 'address', 'bool'], + [ + [order.tokenInAddress, order.tokenOutAddress], // path + limitOrderReceiverParam.amountExternal, // amountExternal + chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId], // profit receiver + limitOrderReceiverParam.keepTokenIn, // keepTokenIn + ] + ) + + const encodedFillOrderData = limitOrderWrapperContract.interface.encodeFunctionData('fillOrder', [ + 0, // fee amount, that will be filled later [ order.maker, order.amountInRaw, @@ -99,19 +127,19 @@ const useStopLossExecute: UseLimitOrderExecute = () => { ], order.tokenInAddress, order.tokenOutAddress, - chainId && ADVANCED_RECEIVER_ADDRESS[chainId], - [], + chainId && ROUND_UP_RECEIVER_ADDRESS[chainId], + data, ]) console.log('encoded fillOrder() data: ', JSON.stringify(encodedFillOrderData)) await autonomyRegistryContract.newReq( - limitOrderContract.address, - AddressZero, - encodedFillOrderData, - ZERO, - false, - false, - false + chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId], // target + AddressZero, // referer + encodedFillOrderData, // callData + ZERO, // ethForCall + false, // verifyUser + true, // insertFeeAmount + false // isAlive ) } diff --git a/src/pages/stop-loss/utils.ts b/src/pages/stop-loss/utils.ts new file mode 100644 index 0000000000..557f3e0b91 --- /dev/null +++ b/src/pages/stop-loss/utils.ts @@ -0,0 +1,44 @@ +import { CurrencyAmount, Token, WNATIVE_ADDRESS } from '@sushiswap/core-sdk' +import { BigNumber } from 'ethers' + +export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 2 // percent unit + +export function keepTokenIn(tokenIn: string, tokenOut: string, chainId: number): boolean { + return tokenIn === WNATIVE_ADDRESS[chainId] ? true : false +} + +export interface IStopLimitOrderReceiverParam { + isValidPair: boolean + keepTokenIn?: boolean + amountExternal: BigNumber +} + +/// @dev now it provides stopLimitOrder for pairs only, coupled with WETH +export function calculateAmountExternal( + tokenIn: CurrencyAmount, + tokenOut: CurrencyAmount, + chainId: number +): IStopLimitOrderReceiverParam { + const WNATIVE_ADDR = WNATIVE_ADDRESS[chainId] + if (WNATIVE_ADDR !== tokenIn.currency.address && WNATIVE_ADDR !== tokenOut.currency.address) { + return { + isValidPair: false, + amountExternal: BigNumber.from(0), + } + } + + const keepTokenIn = tokenIn.currency.address === WNATIVE_ADDR ? true : false + const amountExternal = keepTokenIn + ? BigNumber.from(tokenIn.quotient.toString()) + .mul(100 - STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) + .div(100) + : BigNumber.from(tokenOut.quotient.toString()) + .mul(100 + STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) + .div(100) + + return { + isValidPair: true, + keepTokenIn, + amountExternal, + } +} From bb18012c078075c95306d72988b07e3f3de1384f Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 27 Apr 2022 00:33:36 +0900 Subject: [PATCH 07/60] feat: update stopLimitOrder ui --- .../stop-limit-order/StopPriceInputPanel.tsx | 63 +++++++++++++++++++ .../stop-limit-order}/useStopLossExecute.ts | 7 +-- .../stop-limit-order}/utils.ts | 0 src/pages/stop-loss/StopLossReviewModal.tsx | 3 +- src/pages/stop-loss/[[...tokens]].tsx | 12 +++- src/state/limit-order/actions.ts | 7 +++ src/state/limit-order/hooks.ts | 18 +++++- src/state/limit-order/reducer.ts | 20 ++++++ 8 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 src/features/stop-limit-order/StopPriceInputPanel.tsx rename src/{pages/stop-loss => features/stop-limit-order}/useStopLossExecute.ts (96%) rename src/{pages/stop-loss => features/stop-limit-order}/utils.ts (100%) diff --git a/src/features/stop-limit-order/StopPriceInputPanel.tsx b/src/features/stop-limit-order/StopPriceInputPanel.tsx new file mode 100644 index 0000000000..65b07d0677 --- /dev/null +++ b/src/features/stop-limit-order/StopPriceInputPanel.tsx @@ -0,0 +1,63 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { Currency, Price, Trade, TradeType } from '@sushiswap/core-sdk' +import Input from 'app/components/Input' +import Typography from 'app/components/Typography' +import { useAppDispatch } from 'app/state/hooks' +import { LimitPrice, setStopLossInvertState, setStopPrice } from 'app/state/limit-order/actions' +import useLimitOrderDerivedCurrencies, { useLimitOrderState } from 'app/state/limit-order/hooks' +import React, { FC } from 'react' + +interface StopPriceInputPanel { + trade?: Trade + stopPrice?: Price +} + +const StopPriceInputPanel: FC = ({ trade, stopPrice }) => { + const { i18n } = useLingui() + const dispatch = useAppDispatch() + const { stopPrice: stopPriceString, invertStopRate } = useLimitOrderState() + const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() + const disabled = !inputCurrency || !outputCurrency + + return ( +
+ + {i18n._(t`Stop`)} + +
+ + dispatch(setStopPrice(value))} + /> + + + dispatch( + setStopLossInvertState({ + invertStopRate: !invertStopRate, + stopPrice: stopPrice + ? !invertStopRate + ? stopPrice?.invert().toSignificant(6) + : stopPrice?.toSignificant(6) + : '', + }) + ) + } + > + {invertStopRate ? inputCurrency?.symbol : outputCurrency?.symbol} + +
+
+ ) +} + +export default StopPriceInputPanel diff --git a/src/pages/stop-loss/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts similarity index 96% rename from src/pages/stop-loss/useStopLossExecute.ts rename to src/features/stop-limit-order/useStopLossExecute.ts index 7d7f6c7544..0f888bb951 100644 --- a/src/pages/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -9,7 +9,7 @@ import STOP_LIMIT_ORDER_WRAPPER_ABI from 'app/constants/abis/autonomy/stop-limit import { AUTONOMY_REGISTRY_ADDRESSES, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' -import { useContract, useLimitOrderContract } from 'app/hooks' +import { useContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' @@ -65,7 +65,6 @@ const useStopLossExecute: UseLimitOrderExecute = () => { STOP_LIMIT_ORDER_WRAPPER_ABI, true ) - const limitOrderContract = useLimitOrderContract() const dispatch = useAppDispatch() const addPopup = useAddPopup() @@ -89,7 +88,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { dispatch(setLimitOrderAttemptingTxn(true)) await order?.signOrderWithProvider(chainId || 1, library) - if (limitOrderContract && autonomyRegistryContract && limitOrderWrapperContract && chainId) { + if (autonomyRegistryContract && limitOrderWrapperContract && chainId) { const limitOrderReceiverParam: IStopLimitOrderReceiverParam = calculateAmountExternal( inputAmount.wrapped, outputAmount.wrapped, @@ -167,7 +166,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { }) } }, - [account, addPopup, chainId, dispatch, library, autonomyRegistryContract, limitOrderContract] + [account, addPopup, chainId, dispatch, library, autonomyRegistryContract, limitOrderWrapperContract] ) return { diff --git a/src/pages/stop-loss/utils.ts b/src/features/stop-limit-order/utils.ts similarity index 100% rename from src/pages/stop-loss/utils.ts rename to src/features/stop-limit-order/utils.ts diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index f8b5e4b1b7..4247db5907 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -7,14 +7,13 @@ import ListPanel from 'app/components/ListPanel' import { HeadlessUiModal } from 'app/components/Modal' import Typography from 'app/components/Typography' import TradePrice from 'app/features/legacy/swap/TradePrice' +import useStopLossExecute from 'app/features/stop-limit-order/useStopLossExecute' import { isAddress, shortenAddress } from 'app/functions' import { useAppDispatch } from 'app/state/hooks' import { setLimitOrderShowReview } from 'app/state/limit-order/actions' import { useLimitOrderState } from 'app/state/limit-order/hooks' import React, { FC, useCallback, useMemo, useState } from 'react' -import useStopLossExecute from './useStopLossExecute' - interface StopLossReviewModal { trade?: Trade limitPrice?: Price diff --git a/src/pages/stop-loss/[[...tokens]].tsx b/src/pages/stop-loss/[[...tokens]].tsx index 11986bd080..bb2064014f 100644 --- a/src/pages/stop-loss/[[...tokens]].tsx +++ b/src/pages/stop-loss/[[...tokens]].tsx @@ -10,7 +10,8 @@ import { Feature } from 'app/enums' import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' import LimitOrderButton from 'app/features/legacy/limit-order/LimitOrderButton' import LimitPriceInputPanel from 'app/features/legacy/limit-order/LimitPriceInputPanel' -import OrderExpirationDropdown from 'app/features/legacy/limit-order/OrderExpirationDropdown' +import StopPriceInputPanel from 'app/features/stop-limit-order/StopPriceInputPanel' +// import OrderExpirationDropdown from 'app/features/legacy/limit-order/OrderExpirationDropdown' import HeaderNew from 'app/features/trade/HeaderNew' import SwapAssetPanel from 'app/features/trident/swap/SwapAssetPanel' import { featureEnabled } from 'app/functions' @@ -25,6 +26,7 @@ import useLimitOrderDerivedCurrencies, { useLimitOrderDerivedParsedAmounts, useLimitOrderDerivedTrade, useLimitOrderState, + useStopLossDerivedLimitPrice, } from 'app/state/limit-order/hooks' import { useExpertModeManager } from 'app/state/user/hooks' import { NextSeo } from 'next-seo' @@ -41,6 +43,7 @@ const StopLoss = () => { const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() const trade = useLimitOrderDerivedTrade() const rate = useLimitOrderDerivedLimitPrice() + const stopRate = useStopLossDerivedLimitPrice() const parsedAmounts = useLimitOrderDerivedParsedAmounts({ rate, trade }) const { onSwitchTokens, onCurrencySelection, onUserInput } = useLimitOrderActionHandlers() @@ -121,7 +124,7 @@ const StopLoss = () => { />
- +
{ onClick={onSwitchTokens} />
- +
+ {/*
+ +
*/}
('limit-order/setLimitPrice') +export const setStopPrice = createAction('limit-order/setStopPrice') export const setLimitOrderBentoPermit = createAction('limit-order/setLimitBentoPermit') export const setLimitOrderAttemptingTxn = createAction('limit-order/setLimitAttemptingTxn') export const setLimitOrderInvertRate = createAction('limit-order/setLimitOrderInvertRate') export const setLimitOrderInvertState = createAction<{ invertRate: boolean; limitPrice: string }>( 'limit-order/setLimitOrderInvertState' ) +export const setStopLossInvertRate = createAction('limit-order/setStopLossInvertRate') +export const setStopLossInvertState = createAction<{ invertStopRate: boolean; stopPrice: string }>( + 'limit-order/setStopLossInvertState' +) + export const setOrderExpiration = createAction< | { value: string @@ -35,6 +41,7 @@ export const replaceLimitOrderState = createAction<{ recipient?: string fromBentoBalance?: boolean limitPrice?: string + stopPrice?: string orderExpiration?: { value: string; label: string } }>('limit-order/replaceLimitOrderState') export const selectCurrency = createAction<{ diff --git a/src/state/limit-order/hooks.ts b/src/state/limit-order/hooks.ts index be14e21c9e..171f47ef87 100644 --- a/src/state/limit-order/hooks.ts +++ b/src/state/limit-order/hooks.ts @@ -214,6 +214,19 @@ export const useLimitOrderDerivedLimitPrice: UseLimitOrderDerivedLimitPrice = () : undefined }, [inputCurrency, invertRate, limitPrice, outputCurrency]) } +export const useStopLossDerivedLimitPrice: UseLimitOrderDerivedLimitPrice = () => { + const { stopPrice, invertStopRate } = useLimitOrderState() + const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() + + return useMemo(() => { + const baseAmount = tryParseAmount(invertStopRate ? stopPrice : '1', inputCurrency) + const quoteAmount = tryParseAmount(invertStopRate ? '1' : stopPrice, outputCurrency) + + return baseAmount && quoteAmount && inputCurrency && outputCurrency + ? new Price({ baseAmount, quoteAmount }) + : undefined + }, [inputCurrency, invertStopRate, stopPrice, outputCurrency]) +} type UseLimitOrderDerivedParsedAmounts = ({ rate, @@ -263,7 +276,7 @@ export const useLimitOrderDerivedTypedInputAmount: UseLimitOrderDerivedTypedInpu type UseLimitOrderDerivedInputError = ({ trade }: { trade?: Trade }) => string export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ trade }) => { - const { recipient, orderExpiration, fromBentoBalance, limitPrice, typedValue } = useLimitOrderState() + const { recipient, orderExpiration, fromBentoBalance, limitPrice, stopPrice, typedValue } = useLimitOrderState() const { account } = useActiveWeb3React() const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() const recipientLookup = useENS(recipient) @@ -283,6 +296,8 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ ? i18n._(t`Enter a valid recipient address`) : limitPrice !== LimitPrice.CURRENT && parsedRate?.equalTo(ZERO) ? i18n._(t`Select a rate`) + : stopPrice !== LimitPrice.CURRENT && parsedRate?.equalTo(ZERO) + ? i18n._(t`Select a rate`) : !orderExpiration ? i18n._(t`Select an order expiration`) : !balance @@ -296,6 +311,7 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ expertMode, inputCurrency, limitPrice, + stopPrice, orderExpiration, outputCurrency, parsedRate, diff --git a/src/state/limit-order/reducer.ts b/src/state/limit-order/reducer.ts index 52f156ccf6..1a582f1456 100644 --- a/src/state/limit-order/reducer.ts +++ b/src/state/limit-order/reducer.ts @@ -17,6 +17,9 @@ import { setLimitPrice, setOrderExpiration, setRecipient, + setStopLossInvertRate, + setStopLossInvertState, + setStopPrice, switchCurrencies, typeInput, } from './actions' @@ -33,6 +36,7 @@ export interface LimitOrderState { readonly typedField: Field readonly typedValue: string readonly limitPrice: string + readonly stopPrice: string readonly inputCurrencyId: string readonly outputCurrencyId: string readonly recipient?: string @@ -46,12 +50,14 @@ export interface LimitOrderState { readonly attemptingTxn: boolean readonly showReview: boolean readonly invertRate: boolean + readonly invertStopRate: boolean } const initialState: LimitOrderState = { typedField: Field.INPUT, typedValue: '', limitPrice: '', + stopPrice: '', inputCurrencyId: 'ETH', outputCurrencyId: 'SUSHI', recipient: undefined, @@ -65,6 +71,7 @@ const initialState: LimitOrderState = { attemptingTxn: false, showReview: false, invertRate: false, + invertStopRate: false, } export default createReducer(initialState, (builder) => @@ -83,6 +90,7 @@ export default createReducer(initialState, (builder) => outputCurrencyId, fromBentoBalance, limitPrice, + stopPrice, orderExpiration, }, } @@ -94,6 +102,7 @@ export default createReducer(initialState, (builder) => recipient, fromBentoBalance, limitPrice, + stopPrice, orderExpiration, limitOrderApprovalPending: state.limitOrderApprovalPending, }) @@ -102,6 +111,10 @@ export default createReducer(initialState, (builder) => // @ts-ignore TYPE NEEDS FIXING state.limitPrice = limitPrice }) + .addCase(setStopPrice, (state, { payload: stopPrice }) => { + // @ts-ignore TYPE NEEDS FIXING + state.stopPrice = stopPrice + }) .addCase(setLimitOrderApprovalPending, (state, { payload: limitOrderApprovalPending }) => { state.limitOrderApprovalPending = limitOrderApprovalPending }) @@ -157,6 +170,13 @@ export default createReducer(initialState, (builder) => state.invertRate = invertRate state.limitPrice = limitPrice }) + .addCase(setStopLossInvertRate, (state, { payload: invertStopRate }) => { + state.invertStopRate = invertStopRate + }) + .addCase(setStopLossInvertState, (state, { payload: { invertStopRate, stopPrice } }) => { + state.invertStopRate = invertStopRate + state.stopPrice = stopPrice + }) ) type SelectLimitOrder = (state: AppState) => LimitOrderState From bfa56b70e81b681046d50c6f268efdde8d95f2dc Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 27 Apr 2022 03:37:46 +0900 Subject: [PATCH 08/60] feat: prepareOracleData for stopPrice --- src/constants/autonomy.ts | 5 ++++ .../stop-limit-order/useStopLossExecute.ts | 30 +++++++++++++++---- src/features/stop-limit-order/utils.ts | 29 +++++++++++++++++- src/pages/stop-loss/StopLossReviewModal.tsx | 4 ++- 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index abc7c5193b..ede7fb8396 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -10,3 +10,8 @@ export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', [ChainId.AVALANCHE]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', } + +export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { + [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF11111', + [ChainId.AVALANCHE]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF22222', +} diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index 0f888bb951..869a4316e6 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -2,11 +2,15 @@ import { defaultAbiCoder } from '@ethersproject/abi' import { Signature } from '@ethersproject/bytes' import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' -import { Currency, CurrencyAmount } from '@sushiswap/core-sdk' +import { Currency, CurrencyAmount, Price } from '@sushiswap/core-sdk' import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sdk' import AUTONOMY_REGISTRY_ABI from 'app/constants/abis/autonomy/registry.json' import STOP_LIMIT_ORDER_WRAPPER_ABI from 'app/constants/abis/autonomy/stop-limit-order-wrapper.json' -import { AUTONOMY_REGISTRY_ADDRESSES, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { + AUTONOMY_REGISTRY_ADDRESSES, + CHAINLINK_ORACLE_ADDRESS, + STOP_LIMIT_ORDER_WRAPPER_ADDRESSES, +} from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' import { useContract } from 'app/hooks' @@ -17,7 +21,12 @@ import { setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions' import { OrderExpiration } from 'app/state/limit-order/reducer' import { useCallback } from 'react' -import { calculateAmountExternal, IStopLimitOrderReceiverParam } from './utils' +import { + calculateAmountExternal, + IStopLimitOrderReceiverParam, + prepareStopPriceOracleData, + ZERO_ORACLE_ADDRESS, +} from './utils' const getEndTime = (orderExpiration: OrderExpiration | string): number => { switch (orderExpiration) { @@ -44,6 +53,7 @@ export type ExecutePayload = { inputAmount?: CurrencyAmount outputAmount?: CurrencyAmount recipient?: string + stopPrice?: Price | undefined } export type UseLimitOrderExecuteDeposit = (x: DepositPayload) => Promise @@ -71,8 +81,13 @@ const useStopLossExecute: UseLimitOrderExecute = () => { const { mutate } = useLimitOrders() const execute = useCallback( - async ({ orderExpiration, inputAmount, outputAmount, recipient }) => { - if (!inputAmount || !outputAmount || !account || !library) throw new Error('Dependencies unavailable') + async ({ orderExpiration, inputAmount, outputAmount, recipient, stopPrice }) => { + if (!inputAmount || !outputAmount || !account || !library || !chainId) throw new Error('Dependencies unavailable') + + let oracleData + if (stopPrice) { + oracleData = prepareStopPriceOracleData(inputAmount.wrapped, outputAmount.wrapped, stopPrice) + } const endTime = getEndTime(orderExpiration) const order = new LimitOrder( @@ -81,7 +96,10 @@ const useStopLossExecute: UseLimitOrderExecute = () => { outputAmount.wrapped, recipient ? recipient : account, Math.floor(new Date().getTime() / 1000).toString(), - endTime.toString() + endTime.toString(), + oracleData && oracleData.stopPrice, + oracleData && CHAINLINK_ORACLE_ADDRESS[chainId] && ZERO_ORACLE_ADDRESS, + oracleData && oracleData.oracleData ) try { diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-limit-order/utils.ts index 557f3e0b91..916ee7afa1 100644 --- a/src/features/stop-limit-order/utils.ts +++ b/src/features/stop-limit-order/utils.ts @@ -1,4 +1,4 @@ -import { CurrencyAmount, Token, WNATIVE_ADDRESS } from '@sushiswap/core-sdk' +import { Currency, CurrencyAmount, Price, Token, WNATIVE_ADDRESS } from '@sushiswap/core-sdk' import { BigNumber } from 'ethers' export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 2 // percent unit @@ -42,3 +42,30 @@ export function calculateAmountExternal( amountExternal, } } + +export interface IStopPriceOracleData { + stopPrice: string + oracleData: string +} + +export const ZERO_ORACLE_ADDRESS = '0x0000000000000000000000000000000000000000' +export const ZERO_ORACLE_DATA = '0x00000000000000000000000000000000000000000000000000000000000000' + +/** + * @dev stopPrice should be inverse value, due to smart contract requirements. + * + * @param tokenIn + * @param tokenOut + * @param stopPrice + * @returns + */ +export function prepareStopPriceOracleData( + tokenIn: CurrencyAmount, + tokenOut: CurrencyAmount, + stopPrice: Price +): IStopPriceOracleData { + return { + stopPrice: '0', + oracleData: ZERO_ORACLE_ADDRESS, + } +} diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index 4247db5907..a7a9c9bf36 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -11,7 +11,7 @@ import useStopLossExecute from 'app/features/stop-limit-order/useStopLossExecute import { isAddress, shortenAddress } from 'app/functions' import { useAppDispatch } from 'app/state/hooks' import { setLimitOrderShowReview } from 'app/state/limit-order/actions' -import { useLimitOrderState } from 'app/state/limit-order/hooks' +import { useLimitOrderState, useStopLossDerivedLimitPrice } from 'app/state/limit-order/hooks' import React, { FC, useCallback, useMemo, useState } from 'react' interface StopLossReviewModal { @@ -26,6 +26,7 @@ interface StopLossReviewModal { const StopLossReviewModal: FC = ({ parsedAmounts, trade, limitPrice }) => { const [inverted, setInverted] = useState(false) const { showReview, orderExpiration, recipient, attemptingTxn } = useLimitOrderState() + const stopRate = useStopLossDerivedLimitPrice() const dispatch = useAppDispatch() const { i18n } = useLingui() const { execute } = useStopLossExecute() @@ -37,6 +38,7 @@ const StopLossReviewModal: FC = ({ parsedAmounts, trade, li recipient, outputAmount: parsedAmounts.outputAmount, inputAmount: parsedAmounts.inputAmount, + stopPrice: stopRate, }) } }, [execute, orderExpiration.value, parsedAmounts.inputAmount, parsedAmounts.outputAmount, recipient]) From c30c16017cdc7a74efbe98e6747b3715895d50d1 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 27 Apr 2022 21:16:44 +0900 Subject: [PATCH 09/60] feat: implement stopLimitOrder --- src/constants/autonomy.ts | 11 ++-- .../stop-limit-order/useStopLossExecute.ts | 5 +- src/features/stop-limit-order/utils.ts | 50 +++++++++++++++++-- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index ede7fb8396..e0e75885c7 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -2,16 +2,17 @@ import { AddressMap, ChainId } from '@sushiswap/core-sdk' export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', - [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', + [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // no deployed yet [ChainId.AVALANCHE]: '0x68FCbECa74A7E5D386f74E14682c94DE0e1bC56b', } export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { - [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', - [ChainId.AVALANCHE]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', + [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // not deployed yet + [ChainId.AVALANCHE]: '0x0000000000000000000000000000000000000000', // not deployed yet } export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { - [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF11111', - [ChainId.AVALANCHE]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF22222', + [ChainId.BSC]: '0x00632CFe43d8F9f8E6cD0d39Ffa3D4fa7ec73CFB', + [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF11111', // not confirmed yet + [ChainId.AVALANCHE]: '0x8f2CC3376078568a04eBC600ae5F0a036DBfd812', // not confirmed yet } diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index 869a4316e6..047eb4565c 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -86,7 +86,8 @@ const useStopLossExecute: UseLimitOrderExecute = () => { let oracleData if (stopPrice) { - oracleData = prepareStopPriceOracleData(inputAmount.wrapped, outputAmount.wrapped, stopPrice) + oracleData = prepareStopPriceOracleData(inputAmount.wrapped, outputAmount.wrapped, stopPrice, chainId) + console.log('oracleData: ', JSON.stringify(oracleData)) } const endTime = getEndTime(orderExpiration) @@ -98,7 +99,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { Math.floor(new Date().getTime() / 1000).toString(), endTime.toString(), oracleData && oracleData.stopPrice, - oracleData && CHAINLINK_ORACLE_ADDRESS[chainId] && ZERO_ORACLE_ADDRESS, + oracleData && oracleData.stopPrice ? CHAINLINK_ORACLE_ADDRESS[chainId] : ZERO_ORACLE_ADDRESS, oracleData && oracleData.oracleData ) diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-limit-order/utils.ts index 916ee7afa1..e46d6dd994 100644 --- a/src/features/stop-limit-order/utils.ts +++ b/src/features/stop-limit-order/utils.ts @@ -1,4 +1,6 @@ +import { defaultAbiCoder } from '@ethersproject/abi' import { Currency, CurrencyAmount, Price, Token, WNATIVE_ADDRESS } from '@sushiswap/core-sdk' +import { CHAINLINK_PRICE_FEED_MAP, ChainlinkPriceFeedEntry } from 'app/config/oracles/chainlink' import { BigNumber } from 'ethers' export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 2 // percent unit @@ -51,8 +53,28 @@ export interface IStopPriceOracleData { export const ZERO_ORACLE_ADDRESS = '0x0000000000000000000000000000000000000000' export const ZERO_ORACLE_DATA = '0x00000000000000000000000000000000000000000000000000000000000000' +interface IChainlinkAggregator { + address: string + entry: ChainlinkPriceFeedEntry +} + +export function getOracleFeedEntry(currencyAddr: string, chainId: number): IChainlinkAggregator | undefined { + const NETWORK_FEED_MAPPING = CHAINLINK_PRICE_FEED_MAP[chainId] // {currency} / USD mapping + + for (const aggregatorAddr of Object.keys(NETWORK_FEED_MAPPING)) { + if (NETWORK_FEED_MAPPING[aggregatorAddr].from === currencyAddr) { + return { + address: aggregatorAddr, + entry: NETWORK_FEED_MAPPING[aggregatorAddr], + } + } + } + + return undefined +} + /** - * @dev stopPrice should be inverse value, due to smart contract requirements. + * @dev stopPrice should be inverse value, due to smart contract issue. * * @param tokenIn * @param tokenOut @@ -62,10 +84,30 @@ export const ZERO_ORACLE_DATA = '0x000000000000000000000000000000000000000000000 export function prepareStopPriceOracleData( tokenIn: CurrencyAmount, tokenOut: CurrencyAmount, - stopPrice: Price + stopPrice: Price, + chainId: number ): IStopPriceOracleData { + const inAggregator = getOracleFeedEntry(tokenIn.currency.address, chainId) + const outAggregator = getOracleFeedEntry(tokenOut.currency.address, chainId) + + // if priceFeed does not exists + if (!inAggregator || !outAggregator) { + return { + stopPrice: '', + oracleData: ZERO_ORACLE_ADDRESS, + } + } + + // make stopPrice decimals as 18 + const decimals = 36 + outAggregator.entry.decimals - inAggregator.entry.decimals - 18 + const oracleData = defaultAbiCoder.encode( + ['address', 'address', 'uint256'], // multiply, divide, decimals + [outAggregator.address, inAggregator.address, BigNumber.from(10).pow(decimals)] + ) + + const inverseStopPrice = parseFloat(stopPrice.invert().toSignificant(18)) * 1e18 return { - stopPrice: '0', - oracleData: ZERO_ORACLE_ADDRESS, + stopPrice: inverseStopPrice.toString(), + oracleData, } } From be92943e54e13a5f2fe5b829255c0cb73872ac33 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 27 Apr 2022 21:30:41 +0900 Subject: [PATCH 10/60] refactor: stopLimitOrder --- src/pages/stop-loss/StopLossReviewModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index a7a9c9bf36..624360a867 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -26,11 +26,11 @@ interface StopLossReviewModal { const StopLossReviewModal: FC = ({ parsedAmounts, trade, limitPrice }) => { const [inverted, setInverted] = useState(false) const { showReview, orderExpiration, recipient, attemptingTxn } = useLimitOrderState() - const stopRate = useStopLossDerivedLimitPrice() const dispatch = useAppDispatch() const { i18n } = useLingui() const { execute } = useStopLossExecute() + const stopRate = useStopLossDerivedLimitPrice() const _execute = useCallback(() => { if (parsedAmounts?.inputAmount && parsedAmounts?.outputAmount) { execute({ From 63652ada6579dadb76e48cc7fef44bcce73f284b Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 27 Apr 2022 22:47:16 +0900 Subject: [PATCH 11/60] feat: update stopLimitOrderWrapper address --- src/constants/autonomy.ts | 2 +- src/features/stop-limit-order/useStopLossExecute.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index e0e75885c7..07a33ebfa4 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -8,7 +8,7 @@ export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // not deployed yet - [ChainId.AVALANCHE]: '0x0000000000000000000000000000000000000000', // not deployed yet + [ChainId.AVALANCHE]: '0x849F9303AC8fb345e3D07c78A6795d1989d9CE16', } export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index 047eb4565c..313ff02480 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -2,7 +2,7 @@ import { defaultAbiCoder } from '@ethersproject/abi' import { Signature } from '@ethersproject/bytes' import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' -import { Currency, CurrencyAmount, Price } from '@sushiswap/core-sdk' +import { ChainId, Currency, CurrencyAmount, Price } from '@sushiswap/core-sdk' import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sdk' import AUTONOMY_REGISTRY_ABI from 'app/constants/abis/autonomy/registry.json' import STOP_LIMIT_ORDER_WRAPPER_ABI from 'app/constants/abis/autonomy/stop-limit-order-wrapper.json' @@ -145,7 +145,10 @@ const useStopLossExecute: UseLimitOrderExecute = () => { ], order.tokenInAddress, order.tokenOutAddress, - chainId && ROUND_UP_RECEIVER_ADDRESS[chainId], + chainId && + (chainId == ChainId.AVALANCHE + ? '0x802290173908ed30A9642D6872e252Ef4f6e59A2' + : ROUND_UP_RECEIVER_ADDRESS[chainId]), data, ]) console.log('encoded fillOrder() data: ', JSON.stringify(encodedFillOrderData)) From 2b421f35be80fd836b37903598784fd7d75af108 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 28 Apr 2022 01:47:11 +0900 Subject: [PATCH 12/60] fix: avax chainlinkV2 addr --- src/constants/autonomy.ts | 4 ++-- src/features/stop-limit-order/utils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index 07a33ebfa4..03a4d11ecb 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -13,6 +13,6 @@ export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { [ChainId.BSC]: '0x00632CFe43d8F9f8E6cD0d39Ffa3D4fa7ec73CFB', - [ChainId.MATIC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF11111', // not confirmed yet - [ChainId.AVALANCHE]: '0x8f2CC3376078568a04eBC600ae5F0a036DBfd812', // not confirmed yet + [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // not confirmed yet + [ChainId.AVALANCHE]: '0x232d595594585613F48aaE9c85861E4aB06CE3E5', } diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-limit-order/utils.ts index e46d6dd994..2a01fe7d93 100644 --- a/src/features/stop-limit-order/utils.ts +++ b/src/features/stop-limit-order/utils.ts @@ -3,7 +3,7 @@ import { Currency, CurrencyAmount, Price, Token, WNATIVE_ADDRESS } from '@sushis import { CHAINLINK_PRICE_FEED_MAP, ChainlinkPriceFeedEntry } from 'app/config/oracles/chainlink' import { BigNumber } from 'ethers' -export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 2 // percent unit +export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 20 // percent unit export function keepTokenIn(tokenIn: string, tokenOut: string, chainId: number): boolean { return tokenIn === WNATIVE_ADDRESS[chainId] ? true : false From b21d5cfe0c350e739c6e31f250d3ce7a57445c63 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 28 Apr 2022 17:34:36 +0900 Subject: [PATCH 13/60] fix: oracleData in stopLimitOrder --- src/features/stop-limit-order/useStopLossExecute.ts | 5 +++-- src/features/stop-limit-order/utils.ts | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index 313ff02480..e4a5fe8414 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -26,6 +26,7 @@ import { IStopLimitOrderReceiverParam, prepareStopPriceOracleData, ZERO_ORACLE_ADDRESS, + ZERO_ORACLE_DATA, } from './utils' const getEndTime = (orderExpiration: OrderExpiration | string): number => { @@ -98,9 +99,9 @@ const useStopLossExecute: UseLimitOrderExecute = () => { recipient ? recipient : account, Math.floor(new Date().getTime() / 1000).toString(), endTime.toString(), - oracleData && oracleData.stopPrice, + oracleData && oracleData.stopPrice ? oracleData.stopPrice : '0', oracleData && oracleData.stopPrice ? CHAINLINK_ORACLE_ADDRESS[chainId] : ZERO_ORACLE_ADDRESS, - oracleData && oracleData.oracleData + oracleData && oracleData.stopPrice ? oracleData.oracleData : ZERO_ORACLE_DATA ) try { diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-limit-order/utils.ts index 2a01fe7d93..e02d291016 100644 --- a/src/features/stop-limit-order/utils.ts +++ b/src/features/stop-limit-order/utils.ts @@ -46,7 +46,7 @@ export function calculateAmountExternal( } export interface IStopPriceOracleData { - stopPrice: string + stopPrice?: string oracleData: string } @@ -93,8 +93,7 @@ export function prepareStopPriceOracleData( // if priceFeed does not exists if (!inAggregator || !outAggregator) { return { - stopPrice: '', - oracleData: ZERO_ORACLE_ADDRESS, + oracleData: ZERO_ORACLE_DATA, } } From 8afebfa2c40af56b65a9f2dfb8f5e7aa24a44e09 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 28 Apr 2022 21:38:58 +0900 Subject: [PATCH 14/60] fix: stopLimitOrder slippage as 10% --- src/features/stop-limit-order/utils.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-limit-order/utils.ts index e02d291016..7ac9dffc27 100644 --- a/src/features/stop-limit-order/utils.ts +++ b/src/features/stop-limit-order/utils.ts @@ -3,7 +3,7 @@ import { Currency, CurrencyAmount, Price, Token, WNATIVE_ADDRESS } from '@sushis import { CHAINLINK_PRICE_FEED_MAP, ChainlinkPriceFeedEntry } from 'app/config/oracles/chainlink' import { BigNumber } from 'ethers' -export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 20 // percent unit +export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 10 // percent unit export function keepTokenIn(tokenIn: string, tokenOut: string, chainId: number): boolean { return tokenIn === WNATIVE_ADDRESS[chainId] ? true : false @@ -15,7 +15,17 @@ export interface IStopLimitOrderReceiverParam { amountExternal: BigNumber } -/// @dev now it provides stopLimitOrder for pairs only, coupled with WETH +/** + * @dev It calculates input or output amount, after deducting the fee amount. + * stopLimitOrder charges service fee as WETH. + * If input token is WETH, then it cuts 10% of input token as service fee, and uses left 90% for swapping. + * If output token is WETH, then it use all input token to swap 110% of output token, and uses addition 10% as fee. + * + * @param tokenIn + * @param tokenOut + * @param chainId + * @returns + */ export function calculateAmountExternal( tokenIn: CurrencyAmount, tokenOut: CurrencyAmount, @@ -58,6 +68,13 @@ interface IChainlinkAggregator { entry: ChainlinkPriceFeedEntry } +/** + * @dev It returns Chainlink Aggregator address for input currency. + * + * @param currencyAddr + * @param chainId + * @returns Chainlink aggregator address, for [currencyAddr] / USD price feed + */ export function getOracleFeedEntry(currencyAddr: string, chainId: number): IChainlinkAggregator | undefined { const NETWORK_FEED_MAPPING = CHAINLINK_PRICE_FEED_MAP[chainId] // {currency} / USD mapping From c6699c3148fc87e0775be7794105af976dd6f1ac Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 28 Apr 2022 22:12:04 +0900 Subject: [PATCH 15/60] fix: stopLimitOrder ui --- .../stop-limit-order/useStopLossExecute.ts | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index e4a5fe8414..d066b8c930 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -17,7 +17,7 @@ import { useContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' -import { setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions' +import { clear, setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions' import { OrderExpiration } from 'app/state/limit-order/reducer' import { useCallback } from 'react' @@ -115,7 +115,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { chainId ) if (!limitOrderReceiverParam.isValidPair) { - throw 'Unsupported pair' + throw new Error('Unsupported pair') } const data = defaultAbiCoder.encode( ['address[]', 'uint256', 'address', 'bool'], @@ -165,25 +165,21 @@ const useStopLossExecute: UseLimitOrderExecute = () => { ) } - // const resp = await order?.send() - // if (resp.success) { - // addPopup({ - // txn: { hash: '', summary: 'Limit order created', success: true }, - // }) + addPopup({ + txn: { hash: '', summary: 'Stop limit order created', success: true }, + }) - // await mutate() - // dispatch(clear()) - // } + await mutate() + dispatch(clear()) dispatch(setLimitOrderAttemptingTxn(false)) - } catch (e) { - console.log('Error: ', e) + } catch (e: any) { dispatch(setLimitOrderAttemptingTxn(false)) addPopup({ txn: { hash: '', // @ts-ignore TYPE NEEDS FIXING - summary: `Error: ${e?.response?.data?.data}`, + summary: `Error: ${e?.message}`, success: false, }, }) From dacd9e73b25a087050a470252e6ef9c5734378c5 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 28 Apr 2022 22:19:28 +0900 Subject: [PATCH 16/60] fix: stopLimitOrder ui/ux --- src/features/stop-limit-order/useStopLossExecute.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index d066b8c930..21aca363d9 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -114,7 +114,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { outputAmount.wrapped, chainId ) - if (!limitOrderReceiverParam.isValidPair) { + if (!limitOrderReceiverParam.isValidPair || (stopPrice && !oracleData?.stopPrice)) { throw new Error('Unsupported pair') } const data = defaultAbiCoder.encode( From 58fc6035f25877aac825b5bdb8f68d0f4591d478 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Mon, 2 May 2022 22:42:28 +0900 Subject: [PATCH 17/60] refactor: stopLimitOrder ui --- .../stop-limit-order/LimitPriceInputPanel.tsx | 64 +++++++++++ .../stop-limit-order/StopLimitOrderButton.tsx | 103 ++++++++++++++++++ .../stop-limit-order/StopPriceInputPanel.tsx | 2 +- src/pages/stop-loss/StopLossReviewModal.tsx | 2 +- src/pages/stop-loss/[[...tokens]].tsx | 6 +- 5 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 src/features/stop-limit-order/LimitPriceInputPanel.tsx create mode 100644 src/features/stop-limit-order/StopLimitOrderButton.tsx diff --git a/src/features/stop-limit-order/LimitPriceInputPanel.tsx b/src/features/stop-limit-order/LimitPriceInputPanel.tsx new file mode 100644 index 0000000000..53000301fc --- /dev/null +++ b/src/features/stop-limit-order/LimitPriceInputPanel.tsx @@ -0,0 +1,64 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { Currency, Price, Trade, TradeType } from '@sushiswap/core-sdk' +import Input from 'app/components/Input' +import Typography from 'app/components/Typography' +import { useAppDispatch } from 'app/state/hooks' +import { LimitPrice, setLimitOrderInvertState, setLimitPrice } from 'app/state/limit-order/actions' +import useLimitOrderDerivedCurrencies, { useLimitOrderState } from 'app/state/limit-order/hooks' +import React, { FC } from 'react' + +interface LimitPriceInputPanel { + trade?: Trade + limitPrice?: Price +} + +const LimitPriceInputPanel: FC = ({ trade, limitPrice }) => { + const { i18n } = useLingui() + const dispatch = useAppDispatch() + const { limitPrice: limitPriceString, invertRate } = useLimitOrderState() + const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() + const disabled = !inputCurrency || !outputCurrency + + return ( +
+ + {i18n._(t`Limit Rate`)} + +
+ + dispatch(setLimitPrice(value))} + /> + + + dispatch( + setLimitOrderInvertState({ + invertRate: !invertRate, + limitPrice: limitPrice + ? !invertRate + ? limitPrice?.invert().toSignificant(6) + : limitPrice?.toSignificant(6) + : '', + }) + ) + } + > + {invertRate ? inputCurrency?.symbol : outputCurrency?.symbol} + +
+
+ ) +} + +export default LimitPriceInputPanel diff --git a/src/features/stop-limit-order/StopLimitOrderButton.tsx b/src/features/stop-limit-order/StopLimitOrderButton.tsx new file mode 100644 index 0000000000..508cdf55e9 --- /dev/null +++ b/src/features/stop-limit-order/StopLimitOrderButton.tsx @@ -0,0 +1,103 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { Currency, CurrencyAmount, Trade, TradeType } from '@sushiswap/core-sdk' +import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' +import Button from 'app/components/Button' +import Typography from 'app/components/Typography' +import useLimitOrderExecute, { DepositPayload } from 'app/features/legacy/limit-order/useLimitOrderExecute' +import TridentApproveGate from 'app/features/trident/TridentApproveGate' +import { useBentoBoxContract } from 'app/hooks' +import useENS from 'app/hooks/useENS' +import { useActiveWeb3React } from 'app/services/web3' +import { useAppDispatch } from 'app/state/hooks' +import { setFromBentoBalance, setLimitOrderBentoPermit, setLimitOrderShowReview } from 'app/state/limit-order/actions' +import { useLimitOrderDerivedInputError, useLimitOrderState } from 'app/state/limit-order/hooks' +import React, { FC, useCallback, useState } from 'react' + +interface StopLimitOrderButton { + trade?: Trade + parsedAmounts: { + inputAmount?: CurrencyAmount + outputAmount?: CurrencyAmount + } +} + +const StopLimitOrderButton: FC = ({ trade, parsedAmounts }) => { + const { i18n } = useLingui() + const { chainId } = useActiveWeb3React() + const dispatch = useAppDispatch() + const { fromBentoBalance, bentoPermit, attemptingTxn, recipient } = useLimitOrderState() + const { address } = useENS(recipient) + + const error = useLimitOrderDerivedInputError({ trade }) + const { deposit } = useLimitOrderExecute() + const bentoboxContract = useBentoBoxContract() + const masterContractAddress = chainId ? STOP_LIMIT_ORDER_ADDRESS[chainId] : undefined + const [permitError, setPermitError] = useState(false) + + const _deposit = useCallback( + async (payload: DepositPayload) => { + const tx = await deposit(payload) + if (tx?.hash) { + dispatch(setFromBentoBalance(true)) + } + }, + [deposit, dispatch] + ) + + const handler = useCallback(async () => { + if (!parsedAmounts?.inputAmount) return + + if (fromBentoBalance) { + dispatch(setLimitOrderShowReview(true)) + } else { + await _deposit({ + inputAmount: parsedAmounts?.inputAmount, + bentoPermit, + fromBentoBalance, + }) + } + }, [_deposit, bentoPermit, dispatch, fromBentoBalance, parsedAmounts?.inputAmount]) + + return ( + <> + {permitError && ( + + {i18n._( + t`Something went wrong during signing of the approval. This is expected for hardware wallets, such as Trezor and Ledger. Click 'Approve BentoBox' again for approving using the fallback method` + )} + + )} + dispatch(setLimitOrderBentoPermit(permit)), + onPermitError: () => setPermitError(true), + })} + > + {({ approved, loading }) => { + const disabled = !!error || !approved || loading || attemptingTxn || Boolean(recipient && !address && error) + return ( + + ) + }} + + + ) +} + +export default StopLimitOrderButton diff --git a/src/features/stop-limit-order/StopPriceInputPanel.tsx b/src/features/stop-limit-order/StopPriceInputPanel.tsx index 65b07d0677..c5ef2f5238 100644 --- a/src/features/stop-limit-order/StopPriceInputPanel.tsx +++ b/src/features/stop-limit-order/StopPriceInputPanel.tsx @@ -23,7 +23,7 @@ const StopPriceInputPanel: FC = ({ trade, stopPrice }) => { return (
- {i18n._(t`Stop`)} + {i18n._(t`Stop Rate`)}
diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index 624360a867..5de9bfd471 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -122,7 +122,7 @@ const StopLossReviewModal: FC = ({ parsedAmounts, trade, li {i18n._(t`Please note that after order execution, your tokens will be received in your BentoBox`)}
diff --git a/src/pages/stop-loss/[[...tokens]].tsx b/src/pages/stop-loss/[[...tokens]].tsx index bb2064014f..a45a6b9289 100644 --- a/src/pages/stop-loss/[[...tokens]].tsx +++ b/src/pages/stop-loss/[[...tokens]].tsx @@ -8,8 +8,8 @@ import Typography from 'app/components/Typography' import { ZERO_PERCENT } from 'app/constants' import { Feature } from 'app/enums' import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' -import LimitOrderButton from 'app/features/legacy/limit-order/LimitOrderButton' -import LimitPriceInputPanel from 'app/features/legacy/limit-order/LimitPriceInputPanel' +import LimitPriceInputPanel from 'app/features/stop-limit-order/LimitPriceInputPanel' +import StopLimitOrderButton from 'app/features/stop-limit-order/StopLimitOrderButton' import StopPriceInputPanel from 'app/features/stop-limit-order/StopPriceInputPanel' // import OrderExpirationDropdown from 'app/features/legacy/limit-order/OrderExpirationDropdown' import HeaderNew from 'app/features/trade/HeaderNew' @@ -153,7 +153,7 @@ const StopLoss = () => {
{isExpertMode && } - + Date: Tue, 3 May 2022 21:33:48 +0900 Subject: [PATCH 18/60] refactor: stop-limit-order --- .../stop-limit-order/useStopLossExecute.ts | 20 +++------- src/features/stop-limit-order/utils.ts | 38 +++---------------- 2 files changed, 10 insertions(+), 48 deletions(-) diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index 21aca363d9..73f6b14c09 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -21,13 +21,7 @@ import { clear, setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions import { OrderExpiration } from 'app/state/limit-order/reducer' import { useCallback } from 'react' -import { - calculateAmountExternal, - IStopLimitOrderReceiverParam, - prepareStopPriceOracleData, - ZERO_ORACLE_ADDRESS, - ZERO_ORACLE_DATA, -} from './utils' +import { calculateAmountExternal, prepareStopPriceOracleData, ZERO_ORACLE_ADDRESS, ZERO_ORACLE_DATA } from './utils' const getEndTime = (orderExpiration: OrderExpiration | string): number => { switch (orderExpiration) { @@ -109,21 +103,17 @@ const useStopLossExecute: UseLimitOrderExecute = () => { await order?.signOrderWithProvider(chainId || 1, library) if (autonomyRegistryContract && limitOrderWrapperContract && chainId) { - const limitOrderReceiverParam: IStopLimitOrderReceiverParam = calculateAmountExternal( - inputAmount.wrapped, - outputAmount.wrapped, - chainId - ) - if (!limitOrderReceiverParam.isValidPair || (stopPrice && !oracleData?.stopPrice)) { + const amountExternal = calculateAmountExternal(inputAmount.wrapped, outputAmount.wrapped, chainId) + if (stopPrice && oracleData?.stopPrice == ZERO_ORACLE_DATA) { throw new Error('Unsupported pair') } const data = defaultAbiCoder.encode( ['address[]', 'uint256', 'address', 'bool'], [ [order.tokenInAddress, order.tokenOutAddress], // path - limitOrderReceiverParam.amountExternal, // amountExternal + amountExternal, // amountExternal chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId], // profit receiver - limitOrderReceiverParam.keepTokenIn, // keepTokenIn + true, // keepTokenIn, charge fee, by inputToken always ] ) diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-limit-order/utils.ts index 7ac9dffc27..dfc7936849 100644 --- a/src/features/stop-limit-order/utils.ts +++ b/src/features/stop-limit-order/utils.ts @@ -9,17 +9,8 @@ export function keepTokenIn(tokenIn: string, tokenOut: string, chainId: number): return tokenIn === WNATIVE_ADDRESS[chainId] ? true : false } -export interface IStopLimitOrderReceiverParam { - isValidPair: boolean - keepTokenIn?: boolean - amountExternal: BigNumber -} - /** - * @dev It calculates input or output amount, after deducting the fee amount. - * stopLimitOrder charges service fee as WETH. - * If input token is WETH, then it cuts 10% of input token as service fee, and uses left 90% for swapping. - * If output token is WETH, then it use all input token to swap 110% of output token, and uses addition 10% as fee. + * @dev StopLimitOrder charges fee from the input token always, and deduct 10% for the fee. * * @param tokenIn * @param tokenOut @@ -30,29 +21,10 @@ export function calculateAmountExternal( tokenIn: CurrencyAmount, tokenOut: CurrencyAmount, chainId: number -): IStopLimitOrderReceiverParam { - const WNATIVE_ADDR = WNATIVE_ADDRESS[chainId] - if (WNATIVE_ADDR !== tokenIn.currency.address && WNATIVE_ADDR !== tokenOut.currency.address) { - return { - isValidPair: false, - amountExternal: BigNumber.from(0), - } - } - - const keepTokenIn = tokenIn.currency.address === WNATIVE_ADDR ? true : false - const amountExternal = keepTokenIn - ? BigNumber.from(tokenIn.quotient.toString()) - .mul(100 - STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) - .div(100) - : BigNumber.from(tokenOut.quotient.toString()) - .mul(100 + STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) - .div(100) - - return { - isValidPair: true, - keepTokenIn, - amountExternal, - } +): BigNumber { + return BigNumber.from(tokenIn.quotient.toString()) + .mul(100 - STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) + .div(100) } export interface IStopPriceOracleData { From b29d0fb4b99567bf72914f4517387465a32216cc Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 3 May 2022 22:09:21 +0900 Subject: [PATCH 19/60] refactor: stop-limit-order --- src/features/stop-limit-order/useStopLossExecute.ts | 2 +- src/features/stop-limit-order/utils.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-limit-order/useStopLossExecute.ts index 73f6b14c09..2c45aaa94c 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-limit-order/useStopLossExecute.ts @@ -113,7 +113,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { [order.tokenInAddress, order.tokenOutAddress], // path amountExternal, // amountExternal chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId], // profit receiver - true, // keepTokenIn, charge fee, by inputToken always + false, // keepTokenIn, charge fee, by outputToken always ] ) diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-limit-order/utils.ts index dfc7936849..cf8aac359b 100644 --- a/src/features/stop-limit-order/utils.ts +++ b/src/features/stop-limit-order/utils.ts @@ -10,7 +10,7 @@ export function keepTokenIn(tokenIn: string, tokenOut: string, chainId: number): } /** - * @dev StopLimitOrder charges fee from the input token always, and deduct 10% for the fee. + * @dev StopLimitOrder charges fee from the output token always, and so swap 110% of output token, and deduct fee. * * @param tokenIn * @param tokenOut @@ -22,8 +22,8 @@ export function calculateAmountExternal( tokenOut: CurrencyAmount, chainId: number ): BigNumber { - return BigNumber.from(tokenIn.quotient.toString()) - .mul(100 - STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) + return BigNumber.from(tokenOut.quotient.toString()) + .mul(100 + STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) .div(100) } From 45547b37a62863734617145292c94ad6fbb3a1ac Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 4 May 2022 01:33:32 +0900 Subject: [PATCH 20/60] fix: stopLimitOrderWrapper address --- src/constants/autonomy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index 03a4d11ecb..bce90f568b 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -8,7 +8,7 @@ export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // not deployed yet - [ChainId.AVALANCHE]: '0x849F9303AC8fb345e3D07c78A6795d1989d9CE16', + [ChainId.AVALANCHE]: '0x2f57dabe3dd1ecAed3F79a0D6d2530fCa5A11912', } export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { From 7aac3492fe94a447f752525dcae3c0e697ca8b28 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 6 May 2022 22:16:57 +0900 Subject: [PATCH 21/60] refactor: stop loss order hooks --- .../LimitPriceInputPanel.tsx | 0 .../StopLimitOrderButton.tsx | 0 .../StopPriceInputPanel.tsx | 0 .../useStopLossExecute.ts | 28 +++++-------------- .../{stop-limit-order => stop-loss}/utils.ts | 0 src/hooks/useContract.ts | 17 +++++++++++ src/pages/stop-loss/StopLossReviewModal.tsx | 2 +- src/pages/stop-loss/[[...tokens]].tsx | 6 ++-- 8 files changed, 28 insertions(+), 25 deletions(-) rename src/features/{stop-limit-order => stop-loss}/LimitPriceInputPanel.tsx (100%) rename src/features/{stop-limit-order => stop-loss}/StopLimitOrderButton.tsx (100%) rename src/features/{stop-limit-order => stop-loss}/StopPriceInputPanel.tsx (100%) rename src/features/{stop-limit-order => stop-loss}/useStopLossExecute.ts (86%) rename src/features/{stop-limit-order => stop-loss}/utils.ts (100%) diff --git a/src/features/stop-limit-order/LimitPriceInputPanel.tsx b/src/features/stop-loss/LimitPriceInputPanel.tsx similarity index 100% rename from src/features/stop-limit-order/LimitPriceInputPanel.tsx rename to src/features/stop-loss/LimitPriceInputPanel.tsx diff --git a/src/features/stop-limit-order/StopLimitOrderButton.tsx b/src/features/stop-loss/StopLimitOrderButton.tsx similarity index 100% rename from src/features/stop-limit-order/StopLimitOrderButton.tsx rename to src/features/stop-loss/StopLimitOrderButton.tsx diff --git a/src/features/stop-limit-order/StopPriceInputPanel.tsx b/src/features/stop-loss/StopPriceInputPanel.tsx similarity index 100% rename from src/features/stop-limit-order/StopPriceInputPanel.tsx rename to src/features/stop-loss/StopPriceInputPanel.tsx diff --git a/src/features/stop-limit-order/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts similarity index 86% rename from src/features/stop-limit-order/useStopLossExecute.ts rename to src/features/stop-loss/useStopLossExecute.ts index 2c45aaa94c..ae991935ea 100644 --- a/src/features/stop-limit-order/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -4,16 +4,10 @@ import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' import { ChainId, Currency, CurrencyAmount, Price } from '@sushiswap/core-sdk' import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sdk' -import AUTONOMY_REGISTRY_ABI from 'app/constants/abis/autonomy/registry.json' -import STOP_LIMIT_ORDER_WRAPPER_ABI from 'app/constants/abis/autonomy/stop-limit-order-wrapper.json' -import { - AUTONOMY_REGISTRY_ADDRESSES, - CHAINLINK_ORACLE_ADDRESS, - STOP_LIMIT_ORDER_WRAPPER_ADDRESSES, -} from 'app/constants/autonomy' +import { CHAINLINK_ORACLE_ADDRESS, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' -import { useContract } from 'app/hooks' +import { useAutonomyLimitOrderWrapperContract, useAutonomyRegistryContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' @@ -60,16 +54,8 @@ export type UseLimitOrderExecute = () => { const useStopLossExecute: UseLimitOrderExecute = () => { const { account, chainId, library } = useActiveWeb3React() - const autonomyRegistryContract = useContract( - chainId ? AUTONOMY_REGISTRY_ADDRESSES[chainId] : undefined, - AUTONOMY_REGISTRY_ABI, - true - ) - const limitOrderWrapperContract = useContract( - chainId ? STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId] : undefined, - STOP_LIMIT_ORDER_WRAPPER_ABI, - true - ) + const autonomyRegistryContract = useAutonomyRegistryContract() + const limitOrderWrapperContract = useAutonomyLimitOrderWrapperContract() const dispatch = useAppDispatch() const addPopup = useAddPopup() @@ -82,7 +68,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { let oracleData if (stopPrice) { oracleData = prepareStopPriceOracleData(inputAmount.wrapped, outputAmount.wrapped, stopPrice, chainId) - console.log('oracleData: ', JSON.stringify(oracleData)) + // console.log('oracleData: ', JSON.stringify(oracleData)) } const endTime = getEndTime(orderExpiration) @@ -142,7 +128,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { : ROUND_UP_RECEIVER_ADDRESS[chainId]), data, ]) - console.log('encoded fillOrder() data: ', JSON.stringify(encodedFillOrderData)) + // console.log('encoded fillOrder() data: ', JSON.stringify(encodedFillOrderData)) await autonomyRegistryContract.newReq( chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId], // target @@ -156,7 +142,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { } addPopup({ - txn: { hash: '', summary: 'Stop limit order created', success: true }, + txn: { hash: '', summary: 'Stop loss order created', success: true }, }) await mutate() diff --git a/src/features/stop-limit-order/utils.ts b/src/features/stop-loss/utils.ts similarity index 100% rename from src/features/stop-limit-order/utils.ts rename to src/features/stop-loss/utils.ts diff --git a/src/hooks/useContract.ts b/src/hooks/useContract.ts index 442a727cdf..06489312bf 100644 --- a/src/hooks/useContract.ts +++ b/src/hooks/useContract.ts @@ -29,6 +29,8 @@ import { ARGENT_WALLET_DETECTOR_ABI, ARGENT_WALLET_DETECTOR_MAINNET_ADDRESS, } from 'app/constants/abis/argent-wallet-detector' +import AUTONOMY_REGISTRY_ABI from 'app/constants/abis/autonomy/registry.json' +import STOP_LIMIT_ORDER_WRAPPER_ABI from 'app/constants/abis/autonomy/stop-limit-order-wrapper.json' import BAR_ABI from 'app/constants/abis/bar.json' import BENTOBOX_ABI from 'app/constants/abis/bentobox.json' import BORING_HELPER_ABI from 'app/constants/abis/boring-helper.json' @@ -63,6 +65,7 @@ import UNI_FACTORY_ABI from 'app/constants/abis/uniswap-v2-factory.json' import IUniswapV2PairABI from 'app/constants/abis/uniswap-v2-pair.json' import WETH9_ABI from 'app/constants/abis/weth.json' import ZENKO_ABI from 'app/constants/abis/zenko.json' +import { AUTONOMY_REGISTRY_ADDRESSES, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import { poolEntityMapper } from 'app/features/trident/poolEntityMapper' import { getContract } from 'app/functions' import { useActiveWeb3React } from 'app/services/web3' @@ -395,3 +398,17 @@ export function useOldFarmsContract(withSignerIfPossibe?: boolean): Contract | n const { chainId } = useActiveWeb3React() return useContract(chainId ? OLD_FARMS[chainId] : undefined, MINICHEF_ABI, withSignerIfPossibe) } + +export function useAutonomyRegistryContract(): Contract | null { + const { chainId } = useActiveWeb3React() + return useContract(chainId ? AUTONOMY_REGISTRY_ADDRESSES[chainId] : undefined, AUTONOMY_REGISTRY_ABI, true) +} + +export function useAutonomyLimitOrderWrapperContract(): Contract | null { + const { chainId } = useActiveWeb3React() + return useContract( + chainId ? STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId] : undefined, + STOP_LIMIT_ORDER_WRAPPER_ABI, + true + ) +} diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index 5de9bfd471..b3b104d00d 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -7,7 +7,7 @@ import ListPanel from 'app/components/ListPanel' import { HeadlessUiModal } from 'app/components/Modal' import Typography from 'app/components/Typography' import TradePrice from 'app/features/legacy/swap/TradePrice' -import useStopLossExecute from 'app/features/stop-limit-order/useStopLossExecute' +import useStopLossExecute from 'app/features/stop-loss/useStopLossExecute' import { isAddress, shortenAddress } from 'app/functions' import { useAppDispatch } from 'app/state/hooks' import { setLimitOrderShowReview } from 'app/state/limit-order/actions' diff --git a/src/pages/stop-loss/[[...tokens]].tsx b/src/pages/stop-loss/[[...tokens]].tsx index a45a6b9289..2dce285e84 100644 --- a/src/pages/stop-loss/[[...tokens]].tsx +++ b/src/pages/stop-loss/[[...tokens]].tsx @@ -8,9 +8,9 @@ import Typography from 'app/components/Typography' import { ZERO_PERCENT } from 'app/constants' import { Feature } from 'app/enums' import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' -import LimitPriceInputPanel from 'app/features/stop-limit-order/LimitPriceInputPanel' -import StopLimitOrderButton from 'app/features/stop-limit-order/StopLimitOrderButton' -import StopPriceInputPanel from 'app/features/stop-limit-order/StopPriceInputPanel' +import LimitPriceInputPanel from 'app/features/stop-loss/LimitPriceInputPanel' +import StopLimitOrderButton from 'app/features/stop-loss/StopLimitOrderButton' +import StopPriceInputPanel from 'app/features/stop-loss/StopPriceInputPanel' // import OrderExpirationDropdown from 'app/features/legacy/limit-order/OrderExpirationDropdown' import HeaderNew from 'app/features/trade/HeaderNew' import SwapAssetPanel from 'app/features/trident/swap/SwapAssetPanel' From 0111d9945383932406cff0d605185f1a0283087e Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 19 May 2022 01:07:08 +0900 Subject: [PATCH 22/60] feat: stop limit order ui popup --- src/constants/autonomy.ts | 3 --- src/features/stop-loss/StopLimitOrderButton.tsx | 10 ++++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index bce90f568b..acdd083555 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -2,17 +2,14 @@ import { AddressMap, ChainId } from '@sushiswap/core-sdk' export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', - [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // no deployed yet [ChainId.AVALANCHE]: '0x68FCbECa74A7E5D386f74E14682c94DE0e1bC56b', } export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { - [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // not deployed yet [ChainId.AVALANCHE]: '0x2f57dabe3dd1ecAed3F79a0D6d2530fCa5A11912', } export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { [ChainId.BSC]: '0x00632CFe43d8F9f8E6cD0d39Ffa3D4fa7ec73CFB', - [ChainId.MATIC]: '0x0000000000000000000000000000000000000000', // not confirmed yet [ChainId.AVALANCHE]: '0x232d595594585613F48aaE9c85861E4aB06CE3E5', } diff --git a/src/features/stop-loss/StopLimitOrderButton.tsx b/src/features/stop-loss/StopLimitOrderButton.tsx index 508cdf55e9..0fd0dd08b5 100644 --- a/src/features/stop-loss/StopLimitOrderButton.tsx +++ b/src/features/stop-loss/StopLimitOrderButton.tsx @@ -4,11 +4,13 @@ import { Currency, CurrencyAmount, Trade, TradeType } from '@sushiswap/core-sdk' import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' import Button from 'app/components/Button' import Typography from 'app/components/Typography' +import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrderExecute, { DepositPayload } from 'app/features/legacy/limit-order/useLimitOrderExecute' import TridentApproveGate from 'app/features/trident/TridentApproveGate' import { useBentoBoxContract } from 'app/hooks' import useENS from 'app/hooks/useENS' import { useActiveWeb3React } from 'app/services/web3' +import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' import { setFromBentoBalance, setLimitOrderBentoPermit, setLimitOrderShowReview } from 'app/state/limit-order/actions' import { useLimitOrderDerivedInputError, useLimitOrderState } from 'app/state/limit-order/hooks' @@ -28,6 +30,7 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const dispatch = useAppDispatch() const { fromBentoBalance, bentoPermit, attemptingTxn, recipient } = useLimitOrderState() const { address } = useENS(recipient) + const addPopup = useAddPopup() const error = useLimitOrderDerivedInputError({ trade }) const { deposit } = useLimitOrderExecute() @@ -48,6 +51,13 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const handler = useCallback(async () => { if (!parsedAmounts?.inputAmount) return + if (chainId && !STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId]) { + addPopup({ + txn: { hash: '', summary: 'Autonomy unsupported!', success: false }, + }) + return + } + if (fromBentoBalance) { dispatch(setLimitOrderShowReview(true)) } else { From dd9df026b5b091ed786be711012b389124c0b441 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 19 May 2022 23:28:32 +0900 Subject: [PATCH 23/60] feat: customize stop-loss ui --- src/features/stop-loss/DiscoverHeader.tsx | 33 ++++ src/features/stop-loss/MyStopOrders.tsx | 36 ++++ src/features/stop-loss/OpenOrders.tsx | 151 ++++++++++++++++ .../stop-loss/useOpenOrdersTableConfig.tsx | 168 ++++++++++++++++++ src/features/trade/HeaderNew.tsx | 3 + src/pages/stop-loss/open.tsx | 4 +- 6 files changed, 393 insertions(+), 2 deletions(-) create mode 100644 src/features/stop-loss/DiscoverHeader.tsx create mode 100644 src/features/stop-loss/MyStopOrders.tsx create mode 100644 src/features/stop-loss/OpenOrders.tsx create mode 100644 src/features/stop-loss/useOpenOrdersTableConfig.tsx diff --git a/src/features/stop-loss/DiscoverHeader.tsx b/src/features/stop-loss/DiscoverHeader.tsx new file mode 100644 index 0000000000..2af38e7ca1 --- /dev/null +++ b/src/features/stop-loss/DiscoverHeader.tsx @@ -0,0 +1,33 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import Button from 'app/components/Button' +import Typography from 'app/components/Typography' +import { TridentHeader } from 'app/layouts/Trident' +import Link from 'next/link' +import React from 'react' + +const DiscoverHeader = () => { + const { i18n } = useLingui() + + return ( + +
+ + {i18n._(t`Stop Loss Orders`)} + + + {i18n._(t`Place a stop loss order or check the status of your past orders`)} + +
+
+ + + +
+
+ ) +} + +export default DiscoverHeader diff --git a/src/features/stop-loss/MyStopOrders.tsx b/src/features/stop-loss/MyStopOrders.tsx new file mode 100644 index 0000000000..a6dc2270ee --- /dev/null +++ b/src/features/stop-loss/MyStopOrders.tsx @@ -0,0 +1,36 @@ +import { BookOpenIcon } from '@heroicons/react/outline' +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import Badge from 'app/components/Badge' +import QuestionHelper from 'app/components/QuestionHelper' +import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import Link from 'next/link' +import React, { FC } from 'react' + +const MyStopOrders: FC = () => { + const { i18n } = useLingui() + const { pending } = useLimitOrders() + + const content = ( + } + /> + ) + + return ( + + + {pending.totalOrders > 0 ? ( + + {content} + + ) : ( + content + )} + + + ) +} + +export default MyStopOrders diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx new file mode 100644 index 0000000000..04b22cd0e3 --- /dev/null +++ b/src/features/stop-loss/OpenOrders.tsx @@ -0,0 +1,151 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { LimitOrder } from '@sushiswap/limit-order-sdk' +import Pagination from 'app/components/Pagination' +import Typography from 'app/components/Typography' +import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import { + TABLE_TABLE_CLASSNAME, + TABLE_TBODY_TD_CLASSNAME, + TABLE_TBODY_TR_CLASSNAME, + TABLE_TR_TH_CLASSNAME, + TABLE_WRAPPER_DIV_CLASSNAME, +} from 'app/features/trident/constants' +import { classNames } from 'app/functions' +import { useLimitOrderContract } from 'app/hooks' +import { useActiveWeb3React } from 'app/services/web3' +import { useTransactionAdder } from 'app/state/transactions/hooks' +import Link from 'next/link' +import React, { FC, useCallback } from 'react' +import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' + +import { useOpenOrdersTableConfig } from './useOpenOrdersTableConfig' + +const OpenOrders: FC = () => { + const { i18n } = useLingui() + const { account } = useActiveWeb3React() + const { pending, mutate } = useLimitOrders() + const addTransaction = useTransactionAdder() + const limitOrderContract = useLimitOrderContract(true) + + const cancelOrder = useCallback( + async (limitOrder: LimitOrder, summary: string) => { + if (!limitOrderContract) return + + const tx = await limitOrderContract.cancelOrder(limitOrder.getTypeHash()) + if (tx) { + addTransaction(tx, { + summary, + }) + + await tx.wait() + // @ts-ignore TYPE NEEDS FIXING + await mutate((data) => ({ ...data })) + } + }, + [addTransaction, limitOrderContract, mutate] + ) + + const { config } = useOpenOrdersTableConfig({ orders: pending.data, cancelOrder }) + + // @ts-ignore TYPE NEEDS FIXING + const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( + // @ts-ignore TYPE NEEDS FIXING + config, + useSortBy, + usePagination, + useFlexLayout + ) + + return ( +
+
1 ? 'min-h-[537px]' : '')}> + + + {headerGroups.map((headerGroup, i) => ( + + {headerGroup.headers.map((column, i) => ( + + ))} + + ))} + + + {page.length > 0 ? ( + // @ts-ignore TYPE NEEDS FIXING + page.map((row, i) => { + prepareRow(row) + return ( + + {/*@ts-ignore TYPE NEEDS FIXING*/} + {row.cells.map((cell, i) => { + return ( + + ) + })} + + ) + }) + ) : ( + + + + )} + + + + + + +
+ {column.render('Header')} +
+ {cell.render('Cell')} +
+ + {i18n._(t`No open orders`)} + +
+ + Funds will be received in your{' '} + + + BentoBox + + {' '} + after order execution + +
+
+ 1} + canNextPage={pending.page < pending.maxPages} + onChange={(page) => pending.setPage(page + 1)} + totalPages={pending.maxPages} + currentPage={pending.page - 1} + pageNeighbours={1} + /> +
+ ) +} + +export default OpenOrders diff --git a/src/features/stop-loss/useOpenOrdersTableConfig.tsx b/src/features/stop-loss/useOpenOrdersTableConfig.tsx new file mode 100644 index 0000000000..03a0844894 --- /dev/null +++ b/src/features/stop-loss/useOpenOrdersTableConfig.tsx @@ -0,0 +1,168 @@ +import { ChevronRightIcon } from '@heroicons/react/outline' +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import { LimitOrder } from '@sushiswap/limit-order-sdk' +import Button from 'app/components/Button' +import { CurrencyLogo } from 'app/components/CurrencyLogo' +import Typography from 'app/components/Typography' +import { DerivedOrder } from 'app/features/legacy/limit-order/types' +import React, { useMemo, useState } from 'react' +import { CellProps } from 'react-table' + +export const useOpenOrdersTableConfig = ({ + orders, + cancelOrder, +}: { + orders?: DerivedOrder[] + cancelOrder: (limitOrder: LimitOrder, type: string) => void +}) => { + const { i18n } = useLingui() + + const data = useMemo( + () => [ + { + accessor: 'tokenOut', + Header: 'Market', + minWidth: 300, + Cell: (props: CellProps) => { + return ( +
+
+ +
+ + + {props.cell.row.original.limitOrder.amountIn.toSignificant(6)} + {' '} + {props.cell.row.original.tokenIn.symbol} + + +
+ +
+ + + {props.cell.row.original.limitOrder.amountOut.toSignificant(6)} + {' '} + {props.cell.row.original.tokenOut.symbol} + +
+ ) + }, + }, + { + accessor: 'rate', + Header: 'Rate', + width: 100, + minWidth: 100, + Cell: (props: CellProps) => { + const [invert, setInvert] = useState(false) + + return ( + setInvert(!invert)} + > + + {invert ? props.cell.value.invert().toSignificant(6) : props.cell.value.toSignificant(6)} + {' '} + {invert ? props.cell.row.original.tokenIn.symbol : props.cell.row.original.tokenOut.symbol} + + ) + }, + }, + { + accessor: 'filledPercent', + Header: 'Filled', + width: 80, + minWidth: 80, + Cell: (props: CellProps) => { + return ( + + {props.cell.value}% + + ) + }, + }, + { + accessor: 'timestamp', + Header: 'Expires', + width: 150, + minWidth: 150, + Cell: (props: CellProps) => { + return ( + + {Number(props.cell.row.original.limitOrder.endTime) === Number.MAX_SAFE_INTEGER + ? 'Never' + : new Date(Number(props.cell.row.original.limitOrder.endTime) * 1000).toLocaleString('en-uS', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + timeZone: 'UTC', + })} + + ) + }, + }, + { + accessor: 'Updated', + Header: 'Created at', + width: 150, + minWidth: 150, + Cell: (props: CellProps) => { + return ( + + {new Date(Number(props.cell.row.original.limitOrder.startTime) * 1000).toLocaleString('en-uS', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + timeZone: 'UTC', + })} + + ) + }, + }, + { + accessor: 'id', + Header: 'Cancel', + width: 100, + minWidth: 100, + Cell: (props: CellProps) => { + return ( + + ) + }, + }, + ], + [cancelOrder, i18n] + ) + + const defaultColumn = React.useMemo(() => ({ minWidth: 0 }), []) + + return useMemo( + () => ({ + config: { + columns: data, + data: orders?.filter((order) => Number(order.limitOrder.endTime) * 1000 > Date.now()), + defaultColumn, + // initialState: { + // sortBy: [{ id: 'receive', desc: true }], + // }, + }, + }), + [orders, data, defaultColumn] + ) +} diff --git a/src/features/trade/HeaderNew.tsx b/src/features/trade/HeaderNew.tsx index d512ff9035..f508845ada 100644 --- a/src/features/trade/HeaderNew.tsx +++ b/src/features/trade/HeaderNew.tsx @@ -5,6 +5,7 @@ import NavLink from 'app/components/NavLink' import Settings from 'app/components/Settings' import Typography from 'app/components/Typography' import MyOrders from 'app/features/legacy/limit-order/MyOrders' +import MyStopOrders from 'app/features/stop-loss/MyStopOrders' import { useRouter } from 'next/router' import React, { FC } from 'react' @@ -30,6 +31,7 @@ const HeaderNew: FC = ({ inputCurrency, outputCurrency, trident const { i18n } = useLingui() const { asPath } = useRouter() const isLimitOrder = asPath.startsWith('/limit-order') + const isStopLoss = asPath.startsWith('/stop-loss') return (
@@ -70,6 +72,7 @@ const HeaderNew: FC = ({ inputCurrency, outputCurrency, trident
{isLimitOrder && } + {isStopLoss && }
diff --git a/src/pages/stop-loss/open.tsx b/src/pages/stop-loss/open.tsx index 5553dd4915..78c1e4c379 100644 --- a/src/pages/stop-loss/open.tsx +++ b/src/pages/stop-loss/open.tsx @@ -3,11 +3,11 @@ import { useLingui } from '@lingui/react' import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' import Typography from 'app/components/Typography' import { Feature } from 'app/enums' -import DiscoverHeader from 'app/features/legacy/limit-order/DiscoverHeader' import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' -import OpenOrders from 'app/features/legacy/limit-order/OpenOrders' import OrdersTableToggle from 'app/features/legacy/limit-order/OrderTableToggle' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import DiscoverHeader from 'app/features/stop-loss/DiscoverHeader' +import OpenOrders from 'app/features/stop-loss/OpenOrders' import NetworkGuard from 'app/guards/Network' import { TridentBody } from 'app/layouts/Trident' import { useActiveWeb3React } from 'app/services/web3' From baf0ee9bb8696475aa6d6d20a31d8cd85b584744 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sat, 21 May 2022 00:13:29 +0900 Subject: [PATCH 24/60] feat: fetch stop-loss-order history --- package.json | 3 + src/features/stop-loss/OpenOrders.tsx | 7 + src/features/stop-loss/useStopLossOrders.tsx | 84 ++++++++++ yarn.lock | 159 +++++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 src/features/stop-loss/useStopLossOrders.tsx diff --git a/package.json b/package.json index 2bf380a9cc..e560bc23dc 100644 --- a/package.json +++ b/package.json @@ -242,5 +242,8 @@ "entrypoints": [ "src/pages" ] + }, + "dependencies": { + "moralis": "^1.7.0" } } diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index 04b22cd0e3..2c54aac2bf 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -20,6 +20,7 @@ import React, { FC, useCallback } from 'react' import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' import { useOpenOrdersTableConfig } from './useOpenOrdersTableConfig' +import useStopLossOrders from './useStopLossOrders' const OpenOrders: FC = () => { const { i18n } = useLingui() @@ -28,6 +29,12 @@ const OpenOrders: FC = () => { const addTransaction = useTransactionAdder() const limitOrderContract = useLimitOrderContract(true) + const { totalOrders, loading, data } = useStopLossOrders() + + console.log('total orders: ', totalOrders) + console.log('loading: ', loading) + console.log('data: ', data) + const cancelOrder = useCallback( async (limitOrder: LimitOrder, summary: string) => { if (!limitOrderContract) return diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx new file mode 100644 index 0000000000..bc9875c401 --- /dev/null +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -0,0 +1,84 @@ +import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { useAutonomyLimitOrderWrapperContract } from 'app/hooks' +import { useActiveWeb3React } from 'app/services/web3' +import Moralis from 'moralis' +import { useCallback, useEffect, useState } from 'react' + +interface StopLossOrder { + id: string | number + tokenIn: string + tokenOut: string + stopRate: string + limitRate: string +} + +interface State { + totalOrders: number + loading: boolean + data: StopLossOrder[] +} + +const useStopLossOrders = () => { + const { account, chainId } = useActiveWeb3React() + const limitOrderWrapperContract = useAutonomyLimitOrderWrapperContract() + + const [state, setState] = useState({ + totalOrders: 0, + loading: true, + data: [], + }) + + const fetchRegistryHistory = useCallback(async () => { + console.log('Fetching registry history ...') + + Moralis.initialize(process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY || '') + Moralis.serverURL = process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_SERVER_URL || '' + + const bscRequests = new Moralis.Query('RegistryRequests') + bscRequests.equalTo('user', account?.toLowerCase()) + bscRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) + let registryRequests = await bscRequests.find() + + console.log('Requests: ', registryRequests) + + return await Promise.all( + registryRequests.map(async (request) => { + return request.get('callData') + }) + ) + }, [account, chainId]) + + const transform = (callData: string, id: number) => { + const fillOrderArgs = limitOrderWrapperContract?.interface.decodeFunctionData('fillOrder', callData) + + const stopLossOrder: StopLossOrder = { + id, + tokenIn: fillOrderArgs && fillOrderArgs[2], + tokenOut: fillOrderArgs && fillOrderArgs[3], + stopRate: '', + limitRate: '', + } + + return stopLossOrder + } + + useEffect(() => { + const initializeOrdersData = async () => { + const callDataHistory: string[] = await fetchRegistryHistory() + + const fillOrderData = callDataHistory.map((callData, index) => transform(callData, index)) + + setState({ + totalOrders: fillOrderData.length, + loading: false, + data: fillOrderData, + }) + } + + initializeOrdersData() + }, [account, chainId]) + + return state +} + +export default useStopLossOrders diff --git a/yarn.lock b/yarn.lock index 0766636c36..6a2276dcc7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -948,6 +948,14 @@ "@babel/plugin-transform-react-jsx-development" "^7.16.7" "@babel/plugin-transform-react-pure-annotations" "^7.16.7" +"@babel/runtime-corejs3@7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz#ea533d96eda6fdc76b1812248e9fbd0c11d4a1a7" + integrity sha512-3fKhuICS1lMz0plI5ktOE/yEtBRMVxplzRkdn6mJQ197XiY0JnrzYV0+Mxozq3JZ8SBV9Ecurmw1XsGbwOf+Sg== + dependencies: + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" + "@babel/runtime-corejs3@^7.10.2": version "7.17.9" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz#3d02d0161f0fbf3ada8e88159375af97690f4055" @@ -956,6 +964,13 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" +"@babel/runtime@7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" + integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/runtime@7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" @@ -1335,6 +1350,21 @@ "@ethereumjs/common" "^2.6.3" ethereumjs-util "^7.1.4" +"@ethersproject/abi@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.0.tgz#ea07cbc1eec2374d32485679c12408005895e9f3" + integrity sha512-AhVByTwdXCc2YQ20v300w6KVHle9g2OFc28ZAFCPnJyEpkv1xKXjZcSTgWOlv1i+0dqlgF8RCF2Rn2KC1t+1Vg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/abi@5.6.1", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.6.0": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.1.tgz#f7de888edeb56b0a657b672bdd1b3a1135cd14f7" @@ -1409,6 +1439,13 @@ "@ethersproject/logger" "^5.6.0" bn.js "^4.11.9" +"@ethersproject/bytes@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.0.tgz#81652f2a0e04533575befadce555213c11d8aa20" + integrity sha512-3hJPlYemb9V4VLfJF5BfN0+55vltPZSHU3QKUyP9M3Y2TcajbiRrz65UG+xVHOzBereB1b9mn7r12o177xgN7w== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.6.0": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" @@ -1512,6 +1549,13 @@ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== +"@ethersproject/networks@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.0.tgz#486d03fff29b4b6b5414d47a232ded09fe10de5e" + integrity sha512-DaVzgyThzHgSDLuURhvkp4oviGoGe9iTZW4jMEORHDRCgSZ9K9THGFKqL+qGXqPAYLEgZTf5z2w56mRrPR1MjQ== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks@5.6.2", "@ethersproject/networks@^5.6.0": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.2.tgz#2bacda62102c0b1fcee408315f2bed4f6fbdf336" @@ -1534,6 +1578,31 @@ dependencies: "@ethersproject/logger" "^5.6.0" +"@ethersproject/providers@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.0.tgz#08ec8e2666771e3a347e66c8f664a2af97366534" + integrity sha512-6+5PKXTWAttJWFWF8+xCDTCa2/dtq9BNrdKQHGl0IyIOwj99vM6OeThmIRcsIAzIOb8m0XS6w+1KFZwrf3j9nw== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + bech32 "1.1.4" + ws "7.4.6" + "@ethersproject/providers@5.6.4", "@ethersproject/providers@^5", "@ethersproject/providers@^5.4.0", "@ethersproject/providers@^5.4.5": version "5.6.4" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.4.tgz#1a49c211b57b0b2703c320819abbbfa35c83dff7" @@ -2214,6 +2283,11 @@ messageformat-parser "^4.1.3" ramda "^0.27.1" +"@metamask/detect-provider@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@metamask/detect-provider/-/detect-provider-1.2.0.tgz#3667a7531f2a682e3c3a43eaf3a1958bdb42a696" + integrity sha512-ocA76vt+8D0thgXZ7LxFPyqw3H7988qblgzddTDA6B8a/yU0uKV42QR/DhA+Jh11rJjxW0jKvwb5htA6krNZDQ== + "@metamask/safe-event-emitter@2.0.0", "@metamask/safe-event-emitter@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" @@ -4203,6 +4277,13 @@ axe-core@^4.3.5: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413" integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw== +axios@0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + axios@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" @@ -5297,6 +5378,11 @@ cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypto-js@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" @@ -6570,6 +6656,42 @@ ethereumjs-vm@^2.3.4: rustbn.js "~0.2.0" safe-buffer "^5.1.1" +ethers@5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.0.tgz#924eb965dc03963fad0a09ce687efdf49aca3b45" + integrity sha512-00FP71jt6bW3ndO5DhgH9mLIZhoCGnAKFLu8qig5KmV03ubEChKf2ilB3g6fX512tTYo+tSMDJ5WpCJWdBHkBQ== + dependencies: + "@ethersproject/abi" "5.6.0" + "@ethersproject/abstract-provider" "5.6.0" + "@ethersproject/abstract-signer" "5.6.0" + "@ethersproject/address" "5.6.0" + "@ethersproject/base64" "5.6.0" + "@ethersproject/basex" "5.6.0" + "@ethersproject/bignumber" "5.6.0" + "@ethersproject/bytes" "5.6.0" + "@ethersproject/constants" "5.6.0" + "@ethersproject/contracts" "5.6.0" + "@ethersproject/hash" "5.6.0" + "@ethersproject/hdnode" "5.6.0" + "@ethersproject/json-wallets" "5.6.0" + "@ethersproject/keccak256" "5.6.0" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.0" + "@ethersproject/pbkdf2" "5.6.0" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.0" + "@ethersproject/random" "5.6.0" + "@ethersproject/rlp" "5.6.0" + "@ethersproject/sha2" "5.6.0" + "@ethersproject/signing-key" "5.6.0" + "@ethersproject/solidity" "5.6.0" + "@ethersproject/strings" "5.6.0" + "@ethersproject/transactions" "5.6.0" + "@ethersproject/units" "5.6.0" + "@ethersproject/wallet" "5.6.0" + "@ethersproject/web" "5.6.0" + "@ethersproject/wordlists" "5.6.0" + ethers@^5.1.4, ethers@^5.4.7, ethers@^5.6.0: version "5.6.4" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.4.tgz#23629e9a7d4bc5802dfb53d4da420d738744b53c" @@ -6957,6 +7079,11 @@ follow-redirects@^1.14.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== +follow-redirects@^1.14.8: + version "1.15.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4" + integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -9430,6 +9557,23 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" +moralis@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/moralis/-/moralis-1.7.0.tgz#2d39fd54e56982402c0b5177c4c5b1457e2a81ec" + integrity sha512-hgVdUQvm6a1zZGxODemLgMDMlMXPRQS1685NhZ6uz4Q94KeiMRxvYFN/N2yzhi4dAT5Qb0RMjzZh16ylgalwaA== + dependencies: + "@babel/runtime" "7.16.7" + "@babel/runtime-corejs3" "7.16.8" + "@metamask/detect-provider" "^1.2.0" + axios "0.26.1" + ethers "5.6.0" + react-native-crypto-js "1.0.0" + uuid "^8.3.2" + ws "^8.3.0" + xmlhttprequest "1.8.0" + optionalDependencies: + crypto-js "4.1.1" + mrmime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" @@ -10913,6 +11057,11 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-native-crypto-js@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/react-native-crypto-js/-/react-native-crypto-js-1.0.0.tgz#e677e022e147f41b35614416c92d655f87e2450a" + integrity sha512-FNbLuG/HAdapQoybeZSoes1PWdOj0w242gb+e1R0hicf3Gyj/Mf8M9NaED2AnXVOX01b2FXomwUiw1xP1K+8sA== + react-popper@^2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.2.5.tgz#1214ef3cec86330a171671a4fbcbeeb65ee58e96" @@ -13323,6 +13472,11 @@ ws@^7.3.1, ws@^7.4.0, ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== +ws@^8.3.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.6.0.tgz#e5e9f1d9e7ff88083d0c0dd8281ea662a42c9c23" + integrity sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw== + xhr@^2.0.1, xhr@^2.2.0: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" @@ -13361,6 +13515,11 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From 854e95fdaac51fac22761c4c1925b7bc7cf6061c Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sat, 21 May 2022 00:47:44 +0900 Subject: [PATCH 25/60] fix: useStopLossOrders --- src/features/stop-loss/useStopLossOrders.tsx | 35 +++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index bc9875c401..d01bd229cd 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -30,22 +30,25 @@ const useStopLossOrders = () => { const fetchRegistryHistory = useCallback(async () => { console.log('Fetching registry history ...') - - Moralis.initialize(process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY || '') - Moralis.serverURL = process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_SERVER_URL || '' - - const bscRequests = new Moralis.Query('RegistryRequests') - bscRequests.equalTo('user', account?.toLowerCase()) - bscRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) - let registryRequests = await bscRequests.find() - - console.log('Requests: ', registryRequests) - - return await Promise.all( - registryRequests.map(async (request) => { - return request.get('callData') - }) - ) + try { + Moralis.initialize(process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY || '') + Moralis.serverURL = process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_SERVER_URL || '' + + const bscRequests = new Moralis.Query('RegistryRequests') + bscRequests.equalTo('user', account?.toLowerCase()) + bscRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) + let registryRequests = await bscRequests.find() + + console.log('Requests: ', registryRequests) + + return await Promise.all( + registryRequests.map(async (request) => { + return request.get('callData') + }) + ) + } catch (e) { + return [] + } }, [account, chainId]) const transform = (callData: string, id: number) => { From df78e9a5a3e218876946a2b115243b3365871bb4 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sat, 21 May 2022 01:16:41 +0900 Subject: [PATCH 26/60] feat: parse stopLossOrder --- src/features/stop-loss/useStopLossOrders.tsx | 49 ++++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index d01bd229cd..db258a6bfb 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -1,13 +1,33 @@ +import { Token } from '@sushiswap/core-sdk' +import DEFAULT_TOKEN_LIST from '@sushiswap/default-token-list' import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import { useAutonomyLimitOrderWrapperContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import Moralis from 'moralis' -import { useCallback, useEffect, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' + +interface IToken { + chainId: number + address: string + name: string + symbol: string + decimals: number + logoUrl?: string +} + +interface ITokenList { + name: string + logoURL?: string + keywords: any + timestamp: any + tokens: IToken[] + version: any +} interface StopLossOrder { id: string | number - tokenIn: string - tokenOut: string + tokenIn: Token | undefined + tokenOut: Token | undefined stopRate: string limitRate: string } @@ -15,7 +35,7 @@ interface StopLossOrder { interface State { totalOrders: number loading: boolean - data: StopLossOrder[] + data: Array } const useStopLossOrders = () => { @@ -28,6 +48,11 @@ const useStopLossOrders = () => { data: [], }) + const tokens = useMemo( + () => (DEFAULT_TOKEN_LIST as ITokenList).tokens.filter((token) => token.chainId === chainId), + [chainId] + ) + const fetchRegistryHistory = useCallback(async () => { console.log('Fetching registry history ...') try { @@ -51,13 +76,16 @@ const useStopLossOrders = () => { } }, [account, chainId]) - const transform = (callData: string, id: number) => { - const fillOrderArgs = limitOrderWrapperContract?.interface.decodeFunctionData('fillOrder', callData) + const transform = (callData: string, id: number): StopLossOrder | undefined => { + if (!chainId) return + const fillOrderArgs = limitOrderWrapperContract?.interface.decodeFunctionData('fillOrder', callData) + const token0 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[2]) + const token1 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[3]) const stopLossOrder: StopLossOrder = { id, - tokenIn: fillOrderArgs && fillOrderArgs[2], - tokenOut: fillOrderArgs && fillOrderArgs[3], + tokenIn: token0 && new Token(chainId, token0.address, token0.decimals, token0.symbol, token0.name), + tokenOut: token1 && new Token(chainId, token1.address, token1.decimals, token1.symbol, token1.name), stopRate: '', limitRate: '', } @@ -77,8 +105,9 @@ const useStopLossOrders = () => { data: fillOrderData, }) } - - initializeOrdersData() + if (chainId) { + initializeOrdersData() + } }, [account, chainId]) return state From 40f950081d856fc054bff993b8b2b6cada1fb8d0 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Mon, 23 May 2022 22:12:54 +0900 Subject: [PATCH 27/60] fix: fetch history from moralis --- src/constants/autonomy.ts | 16 ++++++++++++++++ src/features/stop-loss/useStopLossOrders.tsx | 12 +++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index acdd083555..f124e45970 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -13,3 +13,19 @@ export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { [ChainId.BSC]: '0x00632CFe43d8F9f8E6cD0d39Ffa3D4fa7ec73CFB', [ChainId.AVALANCHE]: '0x232d595594585613F48aaE9c85861E4aB06CE3E5', } + +interface MoralisInfo { + serverURL: string + key: string +} + +export const MORALIS_INFO: { [chainId: number]: MoralisInfo } = { + [ChainId.AVALANCHE]: { + serverURL: 'https://ietd1r5r9bs1.usemoralis.com:2053/server', + key: '94CRrkmYxPCfdDQQd4L9gGiem3PKpZsv25fTSwDO', + }, + [ChainId.BSC]: { + serverURL: 'https://mz4k8ltjvwtm.usemoralis.com:2053/server', + key: '0InOR7cWvu3rRwDZRHTDdDZ26Vj7Jc7HOBiYiGWa', + }, +} diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index db258a6bfb..12e01e78df 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -1,6 +1,6 @@ import { Token } from '@sushiswap/core-sdk' import DEFAULT_TOKEN_LIST from '@sushiswap/default-token-list' -import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import { useAutonomyLimitOrderWrapperContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import Moralis from 'moralis' @@ -56,8 +56,8 @@ const useStopLossOrders = () => { const fetchRegistryHistory = useCallback(async () => { console.log('Fetching registry history ...') try { - Moralis.initialize(process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY || '') - Moralis.serverURL = process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_SERVER_URL || '' + Moralis.initialize((chainId && MORALIS_INFO[chainId].key) || '') + Moralis.serverURL = (chainId && MORALIS_INFO[chainId].serverURL) || '' const bscRequests = new Moralis.Query('RegistryRequests') bscRequests.equalTo('user', account?.toLowerCase()) @@ -72,6 +72,7 @@ const useStopLossOrders = () => { }) ) } catch (e) { + console.log('Error while fetching history from Moralis') return [] } }, [account, chainId]) @@ -99,6 +100,11 @@ const useStopLossOrders = () => { const fillOrderData = callDataHistory.map((callData, index) => transform(callData, index)) + console.log( + 'fillOrderData: ', + fillOrderData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) + ) + setState({ totalOrders: fillOrderData.length, loading: false, From e4d7933fa4b980d307c80311b1bd1a474897be71 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 24 May 2022 02:14:41 +0900 Subject: [PATCH 28/60] fix: fetch stop-loss-orders --- src/features/stop-loss/OpenOrders.tsx | 46 ++++++++++-- src/features/stop-loss/useStopLossOrders.tsx | 76 +++++++------------- 2 files changed, 63 insertions(+), 59 deletions(-) diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index 2c54aac2bf..ad43ca2e13 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -16,11 +16,17 @@ import { useLimitOrderContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useTransactionAdder } from 'app/state/transactions/hooks' import Link from 'next/link' -import React, { FC, useCallback } from 'react' +import React, { FC, useCallback, useEffect, useState } from 'react' import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' import { useOpenOrdersTableConfig } from './useOpenOrdersTableConfig' -import useStopLossOrders from './useStopLossOrders' +import useStopLossOrders, { StopLossOrder } from './useStopLossOrders' + +interface OrdersData { + loading: boolean + totalOrders: number + data: Array +} const OpenOrders: FC = () => { const { i18n } = useLingui() @@ -29,11 +35,12 @@ const OpenOrders: FC = () => { const addTransaction = useTransactionAdder() const limitOrderContract = useLimitOrderContract(true) - const { totalOrders, loading, data } = useStopLossOrders() - - console.log('total orders: ', totalOrders) - console.log('loading: ', loading) - console.log('data: ', data) + const { fetchRegistryHistory, transform } = useStopLossOrders() + const [ordersData, setOrdersData] = useState({ + loading: false, + totalOrders: 0, + data: [], + }) const cancelOrder = useCallback( async (limitOrder: LimitOrder, summary: string) => { @@ -64,6 +71,31 @@ const OpenOrders: FC = () => { useFlexLayout ) + useEffect(() => { + const initOrdersData = async () => { + setOrdersData({ + ...ordersData, + loading: true, + }) + console.log('init orders data ...') + const callDataHistory: string[] = await fetchRegistryHistory() + const fillOrdersData = callDataHistory.map((callData, index) => transform(callData, index)) + + setOrdersData({ + loading: false, + totalOrders: fillOrdersData.length, + data: fillOrdersData, + }) + + console.log( + 'fillOrderData: ', + fillOrdersData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) + ) + } + + initOrdersData() + }, [fetchRegistryHistory, transform]) + return (
1 ? 'min-h-[537px]' : '')}> diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index 12e01e78df..74ef53ec00 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -4,7 +4,7 @@ import { MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/ import { useAutonomyLimitOrderWrapperContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import Moralis from 'moralis' -import { useCallback, useEffect, useMemo, useState } from 'react' +import { useCallback, useMemo } from 'react' interface IToken { chainId: number @@ -24,7 +24,7 @@ interface ITokenList { version: any } -interface StopLossOrder { +export interface StopLossOrder { id: string | number tokenIn: Token | undefined tokenOut: Token | undefined @@ -32,22 +32,10 @@ interface StopLossOrder { limitRate: string } -interface State { - totalOrders: number - loading: boolean - data: Array -} - const useStopLossOrders = () => { const { account, chainId } = useActiveWeb3React() const limitOrderWrapperContract = useAutonomyLimitOrderWrapperContract() - const [state, setState] = useState({ - totalOrders: 0, - loading: true, - data: [], - }) - const tokens = useMemo( () => (DEFAULT_TOKEN_LIST as ITokenList).tokens.filter((token) => token.chainId === chainId), [chainId] @@ -77,46 +65,30 @@ const useStopLossOrders = () => { } }, [account, chainId]) - const transform = (callData: string, id: number): StopLossOrder | undefined => { - if (!chainId) return - - const fillOrderArgs = limitOrderWrapperContract?.interface.decodeFunctionData('fillOrder', callData) - const token0 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[2]) - const token1 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[3]) - const stopLossOrder: StopLossOrder = { - id, - tokenIn: token0 && new Token(chainId, token0.address, token0.decimals, token0.symbol, token0.name), - tokenOut: token1 && new Token(chainId, token1.address, token1.decimals, token1.symbol, token1.name), - stopRate: '', - limitRate: '', - } + const transform = useCallback( + (callData: string, id: number): StopLossOrder | undefined => { + if (!chainId) return + + const fillOrderArgs = limitOrderWrapperContract?.interface.decodeFunctionData('fillOrder', callData) + const token0 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[2]) + const token1 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[3]) + const stopLossOrder: StopLossOrder = { + id, + tokenIn: token0 && new Token(chainId, token0.address, token0.decimals, token0.symbol, token0.name), + tokenOut: token1 && new Token(chainId, token1.address, token1.decimals, token1.symbol, token1.name), + stopRate: '', + limitRate: '', + } + + return stopLossOrder + }, + [limitOrderWrapperContract, tokens] + ) - return stopLossOrder + return { + fetchRegistryHistory, + transform, } - - useEffect(() => { - const initializeOrdersData = async () => { - const callDataHistory: string[] = await fetchRegistryHistory() - - const fillOrderData = callDataHistory.map((callData, index) => transform(callData, index)) - - console.log( - 'fillOrderData: ', - fillOrderData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) - ) - - setState({ - totalOrders: fillOrderData.length, - loading: false, - data: fillOrderData, - }) - } - if (chainId) { - initializeOrdersData() - } - }, [account, chainId]) - - return state } export default useStopLossOrders From 5c16bd1fee18fbeaac05354e8483ad92a0454f49 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 24 May 2022 23:52:50 +0900 Subject: [PATCH 29/60] feat: fetch exec stop-loss-orders --- src/features/stop-loss/OpenOrders.tsx | 33 ++++++++++++++------ src/features/stop-loss/useStopLossOrders.tsx | 23 ++++++++++++-- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index ad43ca2e13..f5a9962c18 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -25,7 +25,9 @@ import useStopLossOrders, { StopLossOrder } from './useStopLossOrders' interface OrdersData { loading: boolean totalOrders: number - data: Array + all: Array + executedOrders: number + executed: Array } const OpenOrders: FC = () => { @@ -35,11 +37,13 @@ const OpenOrders: FC = () => { const addTransaction = useTransactionAdder() const limitOrderContract = useLimitOrderContract(true) - const { fetchRegistryHistory, transform } = useStopLossOrders() + const { fetchRegistryHistory, fetchExecutedRegistryHistory, transform } = useStopLossOrders() const [ordersData, setOrdersData] = useState({ loading: false, totalOrders: 0, - data: [], + all: [], + executedOrders: 0, + executed: [], }) const cancelOrder = useCallback( @@ -77,19 +81,28 @@ const OpenOrders: FC = () => { ...ordersData, loading: true, }) - console.log('init orders data ...') - const callDataHistory: string[] = await fetchRegistryHistory() - const fillOrdersData = callDataHistory.map((callData, index) => transform(callData, index)) + const allOrdersCallData: string[] = await fetchRegistryHistory() + const allOrdersData = allOrdersCallData.map((callData, index) => transform(callData, index)) + + const executedOrdersCallData: string[] = await fetchExecutedRegistryHistory() + const executedOrdersData = executedOrdersCallData.map((callData, index) => transform(callData, index)) setOrdersData({ loading: false, - totalOrders: fillOrdersData.length, - data: fillOrdersData, + totalOrders: allOrdersData.length, + all: allOrdersData, + executedOrders: executedOrdersData.length, + executed: executedOrdersData, }) console.log( - 'fillOrderData: ', - fillOrdersData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) + 'allOrdersData: ', + allOrdersData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) + ) + + console.log( + 'executedOrdersData: ', + executedOrdersData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) ) } diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index 74ef53ec00..f18c30bc8b 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -42,7 +42,6 @@ const useStopLossOrders = () => { ) const fetchRegistryHistory = useCallback(async () => { - console.log('Fetching registry history ...') try { Moralis.initialize((chainId && MORALIS_INFO[chainId].key) || '') Moralis.serverURL = (chainId && MORALIS_INFO[chainId].serverURL) || '' @@ -52,7 +51,26 @@ const useStopLossOrders = () => { bscRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) let registryRequests = await bscRequests.find() - console.log('Requests: ', registryRequests) + return await Promise.all( + registryRequests.map(async (request) => { + return request.get('callData') + }) + ) + } catch (e) { + console.log('Error while fetching history from Moralis') + return [] + } + }, [account, chainId]) + + const fetchExecutedRegistryHistory = useCallback(async () => { + try { + Moralis.initialize((chainId && MORALIS_INFO[chainId].key) || '') + Moralis.serverURL = (chainId && MORALIS_INFO[chainId].serverURL) || '' + + const bscRequests = new Moralis.Query('RegistryExecutedRequests') + bscRequests.equalTo('user', account?.toLowerCase()) + bscRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) + let registryRequests = await bscRequests.find() return await Promise.all( registryRequests.map(async (request) => { @@ -87,6 +105,7 @@ const useStopLossOrders = () => { return { fetchRegistryHistory, + fetchExecutedRegistryHistory, transform, } } From df066e8b0de76582b51d894b06280adc3a509006 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 25 May 2022 02:41:09 +0900 Subject: [PATCH 30/60] fix: fetching stop-loss-orders --- src/features/stop-loss/CompletedOrders.tsx | 126 ++++++++++++++++ src/features/stop-loss/OpenOrders.tsx | 28 ++-- src/features/stop-loss/OrderTableToggle.tsx | 57 +++++++ .../useCompletedOrdersTableConfig.tsx | 140 ++++++++++++++++++ src/features/stop-loss/useStopLossOrders.tsx | 52 +++++-- src/pages/stop-loss/history.tsx | 6 +- src/pages/stop-loss/open.tsx | 2 +- 7 files changed, 382 insertions(+), 29 deletions(-) create mode 100644 src/features/stop-loss/CompletedOrders.tsx create mode 100644 src/features/stop-loss/OrderTableToggle.tsx create mode 100644 src/features/stop-loss/useCompletedOrdersTableConfig.tsx diff --git a/src/features/stop-loss/CompletedOrders.tsx b/src/features/stop-loss/CompletedOrders.tsx new file mode 100644 index 0000000000..4d861e0c70 --- /dev/null +++ b/src/features/stop-loss/CompletedOrders.tsx @@ -0,0 +1,126 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import Pagination from 'app/components/Pagination' +import Typography from 'app/components/Typography' +import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import { useCompletedOrdersTableConfig } from 'app/features/stop-loss/useCompletedOrdersTableConfig' +import { + TABLE_TABLE_CLASSNAME, + TABLE_TBODY_TD_CLASSNAME, + TABLE_TBODY_TR_CLASSNAME, + TABLE_TR_TH_CLASSNAME, + TABLE_WRAPPER_DIV_CLASSNAME, +} from 'app/features/trident/constants' +import { classNames } from 'app/functions' +import { useActiveWeb3React } from 'app/services/web3' +import Link from 'next/link' +import React, { FC } from 'react' +import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' + +const CompletedOrders: FC = () => { + const { i18n } = useLingui() + const { account } = useActiveWeb3React() + const { completed } = useLimitOrders() + const { config } = useCompletedOrdersTableConfig({ orders: completed.data }) + + // @ts-ignore TYPE NEEDS FIXING + const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( + // @ts-ignore TYPE NEEDS FIXING + config, + useSortBy, + usePagination, + useFlexLayout + ) + + return ( +
+
1 ? 'min-h-[537px]' : '')}> + + + {headerGroups.map((headerGroup, i) => ( + + {headerGroup.headers.map((column, i) => ( + + ))} + + ))} + + + {page.length > 0 ? ( + // @ts-ignore TYPE NEEDS FIXING + page.map((row, i) => { + prepareRow(row) + return ( + + {/*@ts-ignore TYPE NEEDS FIXING*/} + {row.cells.map((cell, i) => { + return ( + + ) + })} + + ) + }) + ) : ( + + + + )} + + + + + + +
+ {column.render('Header')} +
+ {cell.render('Cell')} +
+ + {i18n._(t`No order history`)} + +
+ + Funds will be received in your{' '} + + + BentoBox + + {' '} + after order execution + +
+
+ 1} + canNextPage={completed.page < completed.maxPages} + onChange={(page) => completed.setPage(page + 1)} + totalPages={completed.maxPages} + currentPage={completed.page - 1} + pageNeighbours={1} + /> +
+ ) +} + +export default CompletedOrders diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index f5a9962c18..6439b01a8d 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -1,8 +1,9 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' -import { LimitOrder } from '@sushiswap/limit-order-sdk' +import { OrderStatus } from '@sushiswap/limit-order-sdk' import Pagination from 'app/components/Pagination' import Typography from 'app/components/Typography' +import { DerivedOrder } from 'app/features/legacy/limit-order/types' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { TABLE_TABLE_CLASSNAME, @@ -16,18 +17,18 @@ import { useLimitOrderContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useTransactionAdder } from 'app/state/transactions/hooks' import Link from 'next/link' -import React, { FC, useCallback, useEffect, useState } from 'react' +import React, { FC, useEffect, useState } from 'react' import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' import { useOpenOrdersTableConfig } from './useOpenOrdersTableConfig' -import useStopLossOrders, { StopLossOrder } from './useStopLossOrders' +import useStopLossOrders from './useStopLossOrders' interface OrdersData { loading: boolean totalOrders: number - all: Array + all: Array executedOrders: number - executed: Array + executed: Array } const OpenOrders: FC = () => { @@ -45,7 +46,7 @@ const OpenOrders: FC = () => { executedOrders: 0, executed: [], }) - + /* const cancelOrder = useCallback( async (limitOrder: LimitOrder, summary: string) => { if (!limitOrderContract) return @@ -63,8 +64,13 @@ const OpenOrders: FC = () => { }, [addTransaction, limitOrderContract, mutate] ) + */ + + const cancelOrder = () => { + console.log('trying to cancel order') + } - const { config } = useOpenOrdersTableConfig({ orders: pending.data, cancelOrder }) + const { config } = useOpenOrdersTableConfig({ orders: ordersData.all, cancelOrder }) // @ts-ignore TYPE NEEDS FIXING const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( @@ -82,10 +88,14 @@ const OpenOrders: FC = () => { loading: true, }) const allOrdersCallData: string[] = await fetchRegistryHistory() - const allOrdersData = allOrdersCallData.map((callData, index) => transform(callData, index)) + const allOrdersData = allOrdersCallData + .map((callData, index) => transform(callData, index)) + .filter((order) => order) as DerivedOrder[] const executedOrdersCallData: string[] = await fetchExecutedRegistryHistory() - const executedOrdersData = executedOrdersCallData.map((callData, index) => transform(callData, index)) + const executedOrdersData = executedOrdersCallData + .map((callData, index) => transform(callData, index, OrderStatus.FILLED)) + .filter((order) => order) as DerivedOrder[] setOrdersData({ loading: false, diff --git a/src/features/stop-loss/OrderTableToggle.tsx b/src/features/stop-loss/OrderTableToggle.tsx new file mode 100644 index 0000000000..431b17c14d --- /dev/null +++ b/src/features/stop-loss/OrderTableToggle.tsx @@ -0,0 +1,57 @@ +import { t } from '@lingui/macro' +import { useLingui } from '@lingui/react' +import Typography from 'app/components/Typography' +import { classNames } from 'app/functions' +import Link from 'next/link' +import { useRouter } from 'next/router' +import React, { useMemo } from 'react' + +const OrdersTableToggle = () => { + const { i18n } = useLingui() + const { asPath } = useRouter() + + const items = useMemo( + () => [ + { + key: 'open', + label: i18n._(t`Orders`), + link: '/stop-loss/open', + }, + { + key: 'history', + label: i18n._(t`History`), + link: '/stop-loss/history', + }, + ], + [i18n] + ) + + return ( +
+ {items.map(({ label, link, key }, index) => ( + + + + {label} + +
+ + + ))} +
+ ) +} + +export default OrdersTableToggle diff --git a/src/features/stop-loss/useCompletedOrdersTableConfig.tsx b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx new file mode 100644 index 0000000000..8132ddfbe5 --- /dev/null +++ b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx @@ -0,0 +1,140 @@ +import { ChevronRightIcon } from '@heroicons/react/outline' +import { OrderStatus } from '@sushiswap/limit-order-sdk' +import Chip from 'app/components/Chip' +import { CurrencyLogo } from 'app/components/CurrencyLogo' +import Typography from 'app/components/Typography' +import React, { useMemo, useState } from 'react' +import { CellProps } from 'react-table' + +import { DerivedOrder } from './types' + +export const useCompletedOrdersTableConfig = ({ orders }: { orders?: DerivedOrder[] }) => { + const data = useMemo( + () => [ + { + accessor: 'tokenOut', + Header: 'Market', + minWidth: 300, + Cell: (props: CellProps) => { + return ( +
+
+ +
+ + + {props.cell.row.original.limitOrder.amountIn.toSignificant(6)} + {' '} + {props.cell.row.original.tokenIn.symbol} + + +
+ +
+ + + {props.cell.row.original.limitOrder.amountOut.toSignificant(6)} + {' '} + {props.cell.row.original.tokenOut.symbol} + +
+ ) + }, + }, + { + accessor: 'rate', + Header: 'Rate', + width: 100, + minWidth: 100, + Cell: (props: CellProps) => { + const [invert, setInvert] = useState(false) + + return ( + setInvert(!invert)} + > + + {invert ? props.cell.value.invert().toSignificant(6) : props.cell.value.toSignificant(6)} + {' '} + {invert ? props.cell.row.original.tokenIn.symbol : props.cell.row.original.tokenOut.symbol} + + ) + }, + }, + { + accessor: 'filledPercent', + Header: 'Filled', + width: 80, + minWidth: 80, + Cell: (props: CellProps) => { + return ( + + {props.cell.value}% + + ) + }, + }, + { + accessor: 'updated', + Header: 'Created at', + width: 150, + minWidth: 150, + Cell: (props: CellProps) => { + return ( + + {new Date(Number(props.cell.row.original.limitOrder.startTime) * 1000).toLocaleString('en-uS', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + timeZone: 'UTC', + })} + + ) + }, + }, + { + accessor: 'status', + Header: 'Status', + minWidth: 100, + Cell: (props: CellProps) => { + return ( + + ) + }, + }, + ], + [] + ) + + const defaultColumn = React.useMemo(() => ({ minWidth: 0 }), []) + + return useMemo( + () => ({ + config: { + columns: data, + data: orders, + defaultColumn, + // initialState: { + // sortBy: [{ id: 'receive', desc: true }], + // }, + }, + }), + [orders, data, defaultColumn] + ) +} diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index f18c30bc8b..3fcee66497 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -1,6 +1,8 @@ -import { Token } from '@sushiswap/core-sdk' +import { Price, Token } from '@sushiswap/core-sdk' import DEFAULT_TOKEN_LIST from '@sushiswap/default-token-list' +import { LimitOrder, OrderStatus } from '@sushiswap/limit-order-sdk' import { MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { DerivedOrder } from 'app/features/legacy/limit-order/types' import { useAutonomyLimitOrderWrapperContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import Moralis from 'moralis' @@ -24,14 +26,6 @@ interface ITokenList { version: any } -export interface StopLossOrder { - id: string | number - tokenIn: Token | undefined - tokenOut: Token | undefined - stopRate: string - limitRate: string -} - const useStopLossOrders = () => { const { account, chainId } = useActiveWeb3React() const limitOrderWrapperContract = useAutonomyLimitOrderWrapperContract() @@ -84,18 +78,44 @@ const useStopLossOrders = () => { }, [account, chainId]) const transform = useCallback( - (callData: string, id: number): StopLossOrder | undefined => { + (callData: string, id: number, status: OrderStatus = OrderStatus.PENDING): DerivedOrder | undefined => { if (!chainId) return const fillOrderArgs = limitOrderWrapperContract?.interface.decodeFunctionData('fillOrder', callData) const token0 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[2]) const token1 = fillOrderArgs && tokens.find((token) => token.address === fillOrderArgs[3]) - const stopLossOrder: StopLossOrder = { - id, - tokenIn: token0 && new Token(chainId, token0.address, token0.decimals, token0.symbol, token0.name), - tokenOut: token1 && new Token(chainId, token1.address, token1.decimals, token1.symbol, token1.name), - stopRate: '', - limitRate: '', + if (!token0 || !token1) return + + const limitOrder: LimitOrder = LimitOrder.getLimitOrder({ + maker: fillOrderArgs[1][0] as string, + tokenIn: fillOrderArgs[2] as string, + tokenOut: fillOrderArgs[3] as string, + tokenInDecimals: token0.decimals, + tokenOutDecimals: token1.decimals, + tokenInSymbol: token0.symbol, + tokenOutSymbol: token1.symbol, + amountIn: fillOrderArgs[1][1] as string, + amountOut: fillOrderArgs[1][2] as string, + recipient: fillOrderArgs[1][3] as string, + startTime: fillOrderArgs[1][4] as string, + endTime: fillOrderArgs[1][5] as string, + stopPrice: fillOrderArgs[1][6] as string, + oracleAddress: fillOrderArgs[1][7] as string, + oracleData: fillOrderArgs[1][8] as string, + v: Number(fillOrderArgs[1][10]), + r: fillOrderArgs[1][11] as string, + s: fillOrderArgs[1][12] as string, + chainId: chainId, + }) + + const stopLossOrder: DerivedOrder = { + id: `${id}`, // [TODO] + tokenIn: new Token(chainId, token0.address, token0.decimals, token0.symbol, token0.name), + tokenOut: new Token(chainId, token1.address, token1.decimals, token1.symbol, token1.name), + limitOrder, + filledPercent: '100', // [TODO] + status, + rate: new Price({ baseAmount: limitOrder.amountIn, quoteAmount: limitOrder.amountOut }), } return stopLossOrder diff --git a/src/pages/stop-loss/history.tsx b/src/pages/stop-loss/history.tsx index e28381710e..742854952c 100644 --- a/src/pages/stop-loss/history.tsx +++ b/src/pages/stop-loss/history.tsx @@ -3,11 +3,11 @@ import { useLingui } from '@lingui/react' import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' import Typography from 'app/components/Typography' import { Feature } from 'app/enums' -import CompletedOrders from 'app/features/legacy/limit-order/CompletedOrders' -import DiscoverHeader from 'app/features/legacy/limit-order/DiscoverHeader' import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' -import OrdersTableToggle from 'app/features/legacy/limit-order/OrderTableToggle' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import CompletedOrders from 'app/features/stop-loss/CompletedOrders' +import DiscoverHeader from 'app/features/stop-loss/DiscoverHeader' +import OrdersTableToggle from 'app/features/stop-loss/OrderTableToggle' import NetworkGuard from 'app/guards/Network' import { TridentBody } from 'app/layouts/Trident' import { useActiveWeb3React } from 'app/services/web3' diff --git a/src/pages/stop-loss/open.tsx b/src/pages/stop-loss/open.tsx index 78c1e4c379..800007c965 100644 --- a/src/pages/stop-loss/open.tsx +++ b/src/pages/stop-loss/open.tsx @@ -4,10 +4,10 @@ import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' import Typography from 'app/components/Typography' import { Feature } from 'app/enums' import LimitOrderApprovalCheck from 'app/features/legacy/limit-order/LimitOrderApprovalCheck' -import OrdersTableToggle from 'app/features/legacy/limit-order/OrderTableToggle' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import DiscoverHeader from 'app/features/stop-loss/DiscoverHeader' import OpenOrders from 'app/features/stop-loss/OpenOrders' +import OrdersTableToggle from 'app/features/stop-loss/OrderTableToggle' import NetworkGuard from 'app/guards/Network' import { TridentBody } from 'app/layouts/Trident' import { useActiveWeb3React } from 'app/services/web3' From 19b82b63aee2f4490c66ba865b6e84c0ecafe096 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 25 May 2022 21:16:47 +0900 Subject: [PATCH 31/60] fix: stop-loss-orders ui --- src/features/stop-loss/useCompletedOrdersTableConfig.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/features/stop-loss/useCompletedOrdersTableConfig.tsx b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx index 8132ddfbe5..5afe7a75b7 100644 --- a/src/features/stop-loss/useCompletedOrdersTableConfig.tsx +++ b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx @@ -3,11 +3,10 @@ import { OrderStatus } from '@sushiswap/limit-order-sdk' import Chip from 'app/components/Chip' import { CurrencyLogo } from 'app/components/CurrencyLogo' import Typography from 'app/components/Typography' +import { DerivedOrder } from 'app/features/legacy/limit-order/types' import React, { useMemo, useState } from 'react' import { CellProps } from 'react-table' -import { DerivedOrder } from './types' - export const useCompletedOrdersTableConfig = ({ orders }: { orders?: DerivedOrder[] }) => { const data = useMemo( () => [ From 91db9cf301d344a9dad75964021d92d8fdcc5a27 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 25 May 2022 21:59:26 +0900 Subject: [PATCH 32/60] fix: open orders list --- src/features/stop-loss/OpenOrders.tsx | 20 ++++++++++--------- .../stop-loss/useOpenOrdersTableConfig.tsx | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index 6439b01a8d..a22c0dba38 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -1,5 +1,6 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' +import { LimitOrder } from '@sushiswap/limit-order-sdk' import { OrderStatus } from '@sushiswap/limit-order-sdk' import Pagination from 'app/components/Pagination' import Typography from 'app/components/Typography' @@ -17,7 +18,7 @@ import { useLimitOrderContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useTransactionAdder } from 'app/state/transactions/hooks' import Link from 'next/link' -import React, { FC, useEffect, useState } from 'react' +import React, { FC, useCallback, useEffect, useState } from 'react' import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' import { useOpenOrdersTableConfig } from './useOpenOrdersTableConfig' @@ -46,11 +47,11 @@ const OpenOrders: FC = () => { executedOrders: 0, executed: [], }) - /* + const cancelOrder = useCallback( async (limitOrder: LimitOrder, summary: string) => { if (!limitOrderContract) return - + /* const tx = await limitOrderContract.cancelOrder(limitOrder.getTypeHash()) if (tx) { addTransaction(tx, { @@ -61,14 +62,13 @@ const OpenOrders: FC = () => { // @ts-ignore TYPE NEEDS FIXING await mutate((data) => ({ ...data })) } +*/ + console.log('canceling order: ', limitOrder.getTypeHash()) + console.log('start time: ', limitOrder.startTime) + console.log('end time: ', limitOrder.endTime) }, [addTransaction, limitOrderContract, mutate] ) - */ - - const cancelOrder = () => { - console.log('trying to cancel order') - } const { config } = useOpenOrdersTableConfig({ orders: ordersData.all, cancelOrder }) @@ -107,7 +107,9 @@ const OpenOrders: FC = () => { console.log( 'allOrdersData: ', - allOrdersData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) + allOrdersData.map( + (order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name + order.limitOrder.amountOut.toSignificant(6) + ) ) console.log( diff --git a/src/features/stop-loss/useOpenOrdersTableConfig.tsx b/src/features/stop-loss/useOpenOrdersTableConfig.tsx index 03a0844894..bdb1c16b70 100644 --- a/src/features/stop-loss/useOpenOrdersTableConfig.tsx +++ b/src/features/stop-loss/useOpenOrdersTableConfig.tsx @@ -156,7 +156,7 @@ export const useOpenOrdersTableConfig = ({ () => ({ config: { columns: data, - data: orders?.filter((order) => Number(order.limitOrder.endTime) * 1000 > Date.now()), + data: orders, // orders?.filter((order) => Number(order.limitOrder.endTime) * 1000 > Date.now()), defaultColumn, // initialState: { // sortBy: [{ id: 'receive', desc: true }], From 52011bc2163cb55940d02ac4ab2c1f28907ab064 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sat, 28 May 2022 00:48:36 +0900 Subject: [PATCH 33/60] feat: show open/history of stop-loss-orders --- package.json | 1 + src/constants/autonomy.ts | 2 + src/features/stop-loss/CompletedOrders.tsx | 20 +--- src/features/stop-loss/OpenOrders.tsx | 80 +------------ .../useCompletedOrdersTableConfig.tsx | 13 --- .../stop-loss/useOpenOrdersTableConfig.tsx | 13 --- src/features/stop-loss/useStopLossOrders.tsx | 109 +++++++++++++----- yarn.lock | 5 + 8 files changed, 103 insertions(+), 140 deletions(-) diff --git a/package.json b/package.json index f877d021de..15f6745181 100644 --- a/package.json +++ b/package.json @@ -242,6 +242,7 @@ ] }, "dependencies": { + "@sushiswap/default-token-list": "^28.0.0", "moralis": "^1.7.0" } } diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index f124e45970..af0db8c0db 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -1,5 +1,7 @@ import { AddressMap, ChainId } from '@sushiswap/core-sdk' +export const QUERY_REQUEST_LIMIT = 10000 + export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', [ChainId.AVALANCHE]: '0x68FCbECa74A7E5D386f74E14682c94DE0e1bC56b', diff --git a/src/features/stop-loss/CompletedOrders.tsx b/src/features/stop-loss/CompletedOrders.tsx index 4d861e0c70..2397a59466 100644 --- a/src/features/stop-loss/CompletedOrders.tsx +++ b/src/features/stop-loss/CompletedOrders.tsx @@ -1,8 +1,6 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' -import Pagination from 'app/components/Pagination' import Typography from 'app/components/Typography' -import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { useCompletedOrdersTableConfig } from 'app/features/stop-loss/useCompletedOrdersTableConfig' import { TABLE_TABLE_CLASSNAME, @@ -17,11 +15,13 @@ import Link from 'next/link' import React, { FC } from 'react' import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' +import useStopLossOrders from './useStopLossOrders' + const CompletedOrders: FC = () => { const { i18n } = useLingui() const { account } = useActiveWeb3React() - const { completed } = useLimitOrders() - const { config } = useCompletedOrdersTableConfig({ orders: completed.data }) + const { loading, executed } = useStopLossOrders() + const { config } = useCompletedOrdersTableConfig({ orders: executed }) // @ts-ignore TYPE NEEDS FIXING const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( @@ -34,7 +34,7 @@ const CompletedOrders: FC = () => { return (
-
1 ? 'min-h-[537px]' : '')}> +
{headerGroups.map((headerGroup, i) => ( @@ -85,7 +85,7 @@ const CompletedOrders: FC = () => { className="text-center text-low-emphesis h-[60px] flex items-center justify-center" component="span" > - {i18n._(t`No order history`)} + {loading ? i18n._(t`Loading executed orders...`) : i18n._(t`No order history`)} @@ -111,14 +111,6 @@ const CompletedOrders: FC = () => {
- 1} - canNextPage={completed.page < completed.maxPages} - onChange={(page) => completed.setPage(page + 1)} - totalPages={completed.maxPages} - currentPage={completed.page - 1} - pageNeighbours={1} - />
) } diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index a22c0dba38..c486184e01 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -1,11 +1,7 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' import { LimitOrder } from '@sushiswap/limit-order-sdk' -import { OrderStatus } from '@sushiswap/limit-order-sdk' -import Pagination from 'app/components/Pagination' import Typography from 'app/components/Typography' -import { DerivedOrder } from 'app/features/legacy/limit-order/types' -import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { TABLE_TABLE_CLASSNAME, TABLE_TBODY_TD_CLASSNAME, @@ -18,35 +14,19 @@ import { useLimitOrderContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useTransactionAdder } from 'app/state/transactions/hooks' import Link from 'next/link' -import React, { FC, useCallback, useEffect, useState } from 'react' +import React, { FC, useCallback } from 'react' import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' import { useOpenOrdersTableConfig } from './useOpenOrdersTableConfig' import useStopLossOrders from './useStopLossOrders' -interface OrdersData { - loading: boolean - totalOrders: number - all: Array - executedOrders: number - executed: Array -} - const OpenOrders: FC = () => { const { i18n } = useLingui() const { account } = useActiveWeb3React() - const { pending, mutate } = useLimitOrders() const addTransaction = useTransactionAdder() const limitOrderContract = useLimitOrderContract(true) - const { fetchRegistryHistory, fetchExecutedRegistryHistory, transform } = useStopLossOrders() - const [ordersData, setOrdersData] = useState({ - loading: false, - totalOrders: 0, - all: [], - executedOrders: 0, - executed: [], - }) + const { loading, unexecuted } = useStopLossOrders() const cancelOrder = useCallback( async (limitOrder: LimitOrder, summary: string) => { @@ -67,10 +47,10 @@ const OpenOrders: FC = () => { console.log('start time: ', limitOrder.startTime) console.log('end time: ', limitOrder.endTime) }, - [addTransaction, limitOrderContract, mutate] + [addTransaction, limitOrderContract] ) - const { config } = useOpenOrdersTableConfig({ orders: ordersData.all, cancelOrder }) + const { config } = useOpenOrdersTableConfig({ orders: unexecuted, cancelOrder }) // @ts-ignore TYPE NEEDS FIXING const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( @@ -81,49 +61,9 @@ const OpenOrders: FC = () => { useFlexLayout ) - useEffect(() => { - const initOrdersData = async () => { - setOrdersData({ - ...ordersData, - loading: true, - }) - const allOrdersCallData: string[] = await fetchRegistryHistory() - const allOrdersData = allOrdersCallData - .map((callData, index) => transform(callData, index)) - .filter((order) => order) as DerivedOrder[] - - const executedOrdersCallData: string[] = await fetchExecutedRegistryHistory() - const executedOrdersData = executedOrdersCallData - .map((callData, index) => transform(callData, index, OrderStatus.FILLED)) - .filter((order) => order) as DerivedOrder[] - - setOrdersData({ - loading: false, - totalOrders: allOrdersData.length, - all: allOrdersData, - executedOrders: executedOrdersData.length, - executed: executedOrdersData, - }) - - console.log( - 'allOrdersData: ', - allOrdersData.map( - (order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name + order.limitOrder.amountOut.toSignificant(6) - ) - ) - - console.log( - 'executedOrdersData: ', - executedOrdersData.map((order) => order?.tokenIn?.name + ' > ' + order?.tokenOut?.name) - ) - } - - initOrdersData() - }, [fetchRegistryHistory, transform]) - return (
-
1 ? 'min-h-[537px]' : '')}> +
{headerGroups.map((headerGroup, i) => ( @@ -174,7 +114,7 @@ const OpenOrders: FC = () => { className="text-center text-low-emphesis h-[60px] flex items-center justify-center" component="span" > - {i18n._(t`No open orders`)} + {loading ? i18n._(t`Loading open orders...`) : i18n._(t`No open orders`)} @@ -200,14 +140,6 @@ const OpenOrders: FC = () => {
- 1} - canNextPage={pending.page < pending.maxPages} - onChange={(page) => pending.setPage(page + 1)} - totalPages={pending.maxPages} - currentPage={pending.page - 1} - pageNeighbours={1} - />
) } diff --git a/src/features/stop-loss/useCompletedOrdersTableConfig.tsx b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx index 5afe7a75b7..9754948134 100644 --- a/src/features/stop-loss/useCompletedOrdersTableConfig.tsx +++ b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx @@ -62,19 +62,6 @@ export const useCompletedOrdersTableConfig = ({ orders }: { orders?: DerivedOrde ) }, }, - { - accessor: 'filledPercent', - Header: 'Filled', - width: 80, - minWidth: 80, - Cell: (props: CellProps) => { - return ( - - {props.cell.value}% - - ) - }, - }, { accessor: 'updated', Header: 'Created at', diff --git a/src/features/stop-loss/useOpenOrdersTableConfig.tsx b/src/features/stop-loss/useOpenOrdersTableConfig.tsx index bdb1c16b70..c13becba88 100644 --- a/src/features/stop-loss/useOpenOrdersTableConfig.tsx +++ b/src/features/stop-loss/useOpenOrdersTableConfig.tsx @@ -72,19 +72,6 @@ export const useOpenOrdersTableConfig = ({ ) }, }, - { - accessor: 'filledPercent', - Header: 'Filled', - width: 80, - minWidth: 80, - Cell: (props: CellProps) => { - return ( - - {props.cell.value}% - - ) - }, - }, { accessor: 'timestamp', Header: 'Expires', diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index 3fcee66497..273c8b7622 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -1,12 +1,12 @@ import { Price, Token } from '@sushiswap/core-sdk' import DEFAULT_TOKEN_LIST from '@sushiswap/default-token-list' import { LimitOrder, OrderStatus } from '@sushiswap/limit-order-sdk' -import { MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { MORALIS_INFO, QUERY_REQUEST_LIMIT, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import { DerivedOrder } from 'app/features/legacy/limit-order/types' import { useAutonomyLimitOrderWrapperContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import Moralis from 'moralis' -import { useCallback, useMemo } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' interface IToken { chainId: number @@ -26,6 +26,19 @@ interface ITokenList { version: any } +interface IRegistryRequest { + callData: string + uid: string +} + +interface OrdersData { + loading: boolean + totalOrders: number + all: Array + executed: Array + unexecuted: Array +} + const useStopLossOrders = () => { const { account, chainId } = useActiveWeb3React() const limitOrderWrapperContract = useAutonomyLimitOrderWrapperContract() @@ -35,19 +48,30 @@ const useStopLossOrders = () => { [chainId] ) + const [ordersData, setOrdersData] = useState({ + loading: false, + totalOrders: 0, + all: [], + executed: [], + unexecuted: [], + }) + const fetchRegistryHistory = useCallback(async () => { try { Moralis.initialize((chainId && MORALIS_INFO[chainId].key) || '') Moralis.serverURL = (chainId && MORALIS_INFO[chainId].serverURL) || '' - const bscRequests = new Moralis.Query('RegistryRequests') - bscRequests.equalTo('user', account?.toLowerCase()) - bscRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) - let registryRequests = await bscRequests.find() + const queryRequests = new Moralis.Query('RegistryRequests') + queryRequests.equalTo('user', account?.toLowerCase()) + queryRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) + let registryRequests = await queryRequests.find() return await Promise.all( registryRequests.map(async (request) => { - return request.get('callData') + return { + callData: request.get('callData'), + uid: request.get('uid'), + } }) ) } catch (e) { @@ -61,24 +85,18 @@ const useStopLossOrders = () => { Moralis.initialize((chainId && MORALIS_INFO[chainId].key) || '') Moralis.serverURL = (chainId && MORALIS_INFO[chainId].serverURL) || '' - const bscRequests = new Moralis.Query('RegistryExecutedRequests') - bscRequests.equalTo('user', account?.toLowerCase()) - bscRequests.equalTo('target', chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId].toLowerCase()) - let registryRequests = await bscRequests.find() - - return await Promise.all( - registryRequests.map(async (request) => { - return request.get('callData') - }) - ) + const queryExecutes = new Moralis.Query('RegistryExecutedRequests') + queryExecutes.limit(QUERY_REQUEST_LIMIT) + let execRequests = await queryExecutes.find() + return execRequests } catch (e) { - console.log('Error while fetching history from Moralis') + console.log('Error while fetching executed history from Moralis') return [] } }, [account, chainId]) const transform = useCallback( - (callData: string, id: number, status: OrderStatus = OrderStatus.PENDING): DerivedOrder | undefined => { + (callData: string, uid: string, status: OrderStatus = OrderStatus.PENDING): DerivedOrder | undefined => { if (!chainId) return const fillOrderArgs = limitOrderWrapperContract?.interface.decodeFunctionData('fillOrder', callData) @@ -109,11 +127,11 @@ const useStopLossOrders = () => { }) const stopLossOrder: DerivedOrder = { - id: `${id}`, // [TODO] + id: uid, tokenIn: new Token(chainId, token0.address, token0.decimals, token0.symbol, token0.name), tokenOut: new Token(chainId, token1.address, token1.decimals, token1.symbol, token1.name), limitOrder, - filledPercent: '100', // [TODO] + filledPercent: '100', status, rate: new Price({ baseAmount: limitOrder.amountIn, quoteAmount: limitOrder.amountOut }), } @@ -123,11 +141,50 @@ const useStopLossOrders = () => { [limitOrderWrapperContract, tokens] ) - return { - fetchRegistryHistory, - fetchExecutedRegistryHistory, - transform, - } + useEffect(() => { + const initOrdersData = async () => { + if (!account || !chainId) return + + setOrdersData({ + ...ordersData, + loading: true, + }) + + const executedOrdersCallData = await fetchExecutedRegistryHistory() + const executedUids = await Promise.all( + executedOrdersCallData.map(async (request) => { + return request.get('uid') + }) + ) + + const allRequests: IRegistryRequest[] = await fetchRegistryHistory() + const allOrdersData = allRequests + .map((request) => transform(request.callData, request.uid)) + .filter((order) => order) as DerivedOrder[] + + const pendingOrdersData = allRequests + .filter((request) => !executedUids.includes(request.uid)) + .map((request) => transform(request.callData, request.uid, OrderStatus.PENDING)) + .filter((order) => order) as DerivedOrder[] + + const executedOrdersData = allRequests + .filter((request) => executedUids.includes(request.uid)) + .map((request) => transform(request.callData, request.uid, OrderStatus.FILLED)) + .filter((order) => order) as DerivedOrder[] + + setOrdersData({ + loading: false, + totalOrders: allOrdersData.length, + all: allOrdersData, + executed: executedOrdersData, + unexecuted: pendingOrdersData, + }) + } + + initOrdersData() + }, [account, chainId]) + + return ordersData } export default useStopLossOrders diff --git a/yarn.lock b/yarn.lock index f1ab0ff20d..a9095c1443 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2695,6 +2695,11 @@ resolved "https://registry.yarnpkg.com/@sushiswap/core/-/core-2.0.0-canary.1.tgz#91c938668282d463e4fce6e0cf4d320ce5f3768f" integrity sha512-6YFT4EKgm0XgfwCBsKx5HrDtRI6EvhZHipjBKegdTV0b2zKuXnmdyZ+RwPCr0mCKq2pKB0qIiqCxfbgXYDlLCQ== +"@sushiswap/default-token-list@^28.0.0": + version "28.0.0" + resolved "https://registry.yarnpkg.com/@sushiswap/default-token-list/-/default-token-list-28.0.0.tgz#67067f6a5014f0e1725bb8d59e7d1a046f7bb7cf" + integrity sha512-Psa4oQhMzaRABuBcTzgII+UxdpqJuvqT5j1wPa2nvHedfKPEV664kKO+ypkgAB25eScbS/zgJQdBvO8ZhDZS8g== + "@sushiswap/kashi-sdk@1.0.0-canary.80": version "1.0.0-canary.80" resolved "https://registry.yarnpkg.com/@sushiswap/kashi-sdk/-/kashi-sdk-1.0.0-canary.80.tgz#1565f03c71ba1093b2d374dfa5782ba72121d209" From 75fd7c5ca7743fe7f9442cb0b8e267aace4d92bc Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 31 May 2022 00:01:01 +0900 Subject: [PATCH 34/60] feat: cancel stop-loss orders --- src/features/stop-loss/OpenOrders.tsx | 21 ++------- .../useCompletedOrdersTableConfig.tsx | 24 ++++++++++ .../stop-loss/useOpenOrdersTableConfig.tsx | 30 +++++++++++- src/features/stop-loss/useStopLossExecute.ts | 46 ++++++++++++++++++- 4 files changed, 102 insertions(+), 19 deletions(-) diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index c486184e01..c08c2fc0d8 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -18,6 +18,7 @@ import React, { FC, useCallback } from 'react' import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table' import { useOpenOrdersTableConfig } from './useOpenOrdersTableConfig' +import useStopLossExecute from './useStopLossExecute' import useStopLossOrders from './useStopLossOrders' const OpenOrders: FC = () => { @@ -26,26 +27,14 @@ const OpenOrders: FC = () => { const addTransaction = useTransactionAdder() const limitOrderContract = useLimitOrderContract(true) + const { cancelRequest } = useStopLossExecute() const { loading, unexecuted } = useStopLossOrders() const cancelOrder = useCallback( - async (limitOrder: LimitOrder, summary: string) => { + async (id: string, limitOrder: LimitOrder, summary: string) => { if (!limitOrderContract) return - /* - const tx = await limitOrderContract.cancelOrder(limitOrder.getTypeHash()) - if (tx) { - addTransaction(tx, { - summary, - }) - - await tx.wait() - // @ts-ignore TYPE NEEDS FIXING - await mutate((data) => ({ ...data })) - } -*/ - console.log('canceling order: ', limitOrder.getTypeHash()) - console.log('start time: ', limitOrder.startTime) - console.log('end time: ', limitOrder.endTime) + console.log('canceling stop-loss request #', id) + await cancelRequest(id) }, [addTransaction, limitOrderContract] ) diff --git a/src/features/stop-loss/useCompletedOrdersTableConfig.tsx b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx index 9754948134..119cb6c7bb 100644 --- a/src/features/stop-loss/useCompletedOrdersTableConfig.tsx +++ b/src/features/stop-loss/useCompletedOrdersTableConfig.tsx @@ -40,6 +40,30 @@ export const useCompletedOrdersTableConfig = ({ orders }: { orders?: DerivedOrde ) }, }, + { + accessor: 'stopPrice', + Header: 'Stop Price', + width: 100, + minWidth: 100, + Cell: (props: CellProps) => { + const [invert, setInvert] = useState(false) + + return ( + setInvert(!invert)} + > + + {!invert + ? 1e18 / parseFloat(props.cell.row.original.limitOrder.stopPrice) + : parseFloat(props.cell.row.original.limitOrder.stopPrice) / 1e18} + {' '} + {invert ? props.cell.row.original.tokenIn.symbol : props.cell.row.original.tokenOut.symbol} + + ) + }, + }, { accessor: 'rate', Header: 'Rate', diff --git a/src/features/stop-loss/useOpenOrdersTableConfig.tsx b/src/features/stop-loss/useOpenOrdersTableConfig.tsx index c13becba88..095f214288 100644 --- a/src/features/stop-loss/useOpenOrdersTableConfig.tsx +++ b/src/features/stop-loss/useOpenOrdersTableConfig.tsx @@ -14,7 +14,7 @@ export const useOpenOrdersTableConfig = ({ cancelOrder, }: { orders?: DerivedOrder[] - cancelOrder: (limitOrder: LimitOrder, type: string) => void + cancelOrder: (id: string, limitOrder: LimitOrder, type: string) => void }) => { const { i18n } = useLingui() @@ -50,6 +50,30 @@ export const useOpenOrdersTableConfig = ({ ) }, }, + { + accessor: 'stopPrice', + Header: 'Stop Price', + width: 100, + minWidth: 100, + Cell: (props: CellProps) => { + const [invert, setInvert] = useState(false) + + return ( + setInvert(!invert)} + > + + {!invert + ? 1e18 / parseFloat(props.cell.row.original.limitOrder.stopPrice) + : parseFloat(props.cell.row.original.limitOrder.stopPrice) / 1e18} + {' '} + {invert ? props.cell.row.original.tokenIn.symbol : props.cell.row.original.tokenOut.symbol} + + ) + }, + }, { accessor: 'rate', Header: 'Rate', @@ -125,7 +149,9 @@ export const useOpenOrdersTableConfig = ({ color="blue" variant="empty" size="xs" - onClick={() => cancelOrder(props.cell.row.original.limitOrder, `Cancel order`)} + onClick={() => + cancelOrder(props.cell.row.original.id, props.cell.row.original.limitOrder, `Cancel order`) + } className="whitespace-nowrap" > {i18n._(t`Cancel Order`)} diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index ae991935ea..4fd4b859fa 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -4,7 +4,7 @@ import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' import { ChainId, Currency, CurrencyAmount, Price } from '@sushiswap/core-sdk' import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sdk' -import { CHAINLINK_ORACLE_ADDRESS, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { CHAINLINK_ORACLE_ADDRESS, MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' import { useAutonomyLimitOrderWrapperContract, useAutonomyRegistryContract } from 'app/hooks' @@ -13,6 +13,8 @@ import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' import { clear, setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions' import { OrderExpiration } from 'app/state/limit-order/reducer' +import { useTransactionAdder } from 'app/state/transactions/hooks' +import Moralis from 'moralis' import { useCallback } from 'react' import { calculateAmountExternal, prepareStopPriceOracleData, ZERO_ORACLE_ADDRESS, ZERO_ORACLE_DATA } from './utils' @@ -49,6 +51,7 @@ export type UseLimitOrderExecuteDeposit = (x: DepositPayload) => Promise void export type UseLimitOrderExecute = () => { execute: UseLimitOrderExecuteExecute + cancelRequest: (id: string) => void } const useStopLossExecute: UseLimitOrderExecute = () => { @@ -56,6 +59,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { const autonomyRegistryContract = useAutonomyRegistryContract() const limitOrderWrapperContract = useAutonomyLimitOrderWrapperContract() + const addTransaction = useTransactionAdder() const dispatch = useAppDispatch() const addPopup = useAddPopup() @@ -164,7 +168,47 @@ const useStopLossExecute: UseLimitOrderExecute = () => { [account, addPopup, chainId, dispatch, library, autonomyRegistryContract, limitOrderWrapperContract] ) + const cancelRequest = useCallback( + async (requestId: string) => { + if (!account || !chainId || !library || !limitOrderWrapperContract || !autonomyRegistryContract) + throw new Error('Dependencies unavailable') + + try { + Moralis.initialize((chainId && MORALIS_INFO[chainId].key) || '') + Moralis.serverURL = (chainId && MORALIS_INFO[chainId].serverURL) || '' + const queryRequest = new Moralis.Query('RegistryRequests') + queryRequest.equalTo('uid', requestId) + let requests = await queryRequest.find() + + const callData = await requests[0].get('callData') + console.log('callData: ', callData) + + const tx = await autonomyRegistryContract.cancelHashedReq(requestId, [ + account, + chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId], // target + AddressZero, // referer + callData, // callData + ZERO, // initEthSent + ZERO, // ethForCall + false, // verifyUser + true, // insertFeeAmount + false, // payWithAuto + false, // isAlive + ]) + + addTransaction(tx, { + summary: 'Stop loss order canceled', + }) + await tx.wait() + } catch (e) { + console.log('Error while fetching history from Moralis') + } + }, + [account, chainId, dispatch, library, limitOrderWrapperContract, autonomyRegistryContract] + ) + return { + cancelRequest, execute, } } From cb5792f0c31acb4fb434cb5a1ebf60da5e5a88df Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 31 May 2022 00:42:40 +0900 Subject: [PATCH 35/60] feat: update stop-loss orders ui --- src/features/stop-loss/CompletedOrders.tsx | 4 +- src/features/stop-loss/MyStopOrders.tsx | 8 ++-- src/features/stop-loss/useStopLossExecute.ts | 1 - src/features/stop-loss/useStopLossOrders.tsx | 42 ++++++++++++++++---- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/features/stop-loss/CompletedOrders.tsx b/src/features/stop-loss/CompletedOrders.tsx index 2397a59466..64e81416f0 100644 --- a/src/features/stop-loss/CompletedOrders.tsx +++ b/src/features/stop-loss/CompletedOrders.tsx @@ -20,8 +20,8 @@ import useStopLossOrders from './useStopLossOrders' const CompletedOrders: FC = () => { const { i18n } = useLingui() const { account } = useActiveWeb3React() - const { loading, executed } = useStopLossOrders() - const { config } = useCompletedOrdersTableConfig({ orders: executed }) + const { loading, completed } = useStopLossOrders() + const { config } = useCompletedOrdersTableConfig({ orders: completed }) // @ts-ignore TYPE NEEDS FIXING const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( diff --git a/src/features/stop-loss/MyStopOrders.tsx b/src/features/stop-loss/MyStopOrders.tsx index a6dc2270ee..c00bd7a503 100644 --- a/src/features/stop-loss/MyStopOrders.tsx +++ b/src/features/stop-loss/MyStopOrders.tsx @@ -3,13 +3,13 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' import Badge from 'app/components/Badge' import QuestionHelper from 'app/components/QuestionHelper' -import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' +import useStopLossOrders from 'app/features/stop-loss/useStopLossOrders' import Link from 'next/link' import React, { FC } from 'react' const MyStopOrders: FC = () => { const { i18n } = useLingui() - const { pending } = useLimitOrders() + const { unexecuted } = useStopLossOrders() const content = ( { return ( - {pending.totalOrders > 0 ? ( - + {unexecuted.length > 0 ? ( + {content} ) : ( diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index 4fd4b859fa..58476f9d0f 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -181,7 +181,6 @@ const useStopLossExecute: UseLimitOrderExecute = () => { let requests = await queryRequest.find() const callData = await requests[0].get('callData') - console.log('callData: ', callData) const tx = await autonomyRegistryContract.cancelHashedReq(requestId, [ account, diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index 273c8b7622..da9746f42a 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -35,7 +35,7 @@ interface OrdersData { loading: boolean totalOrders: number all: Array - executed: Array + completed: Array unexecuted: Array } @@ -52,7 +52,7 @@ const useStopLossOrders = () => { loading: false, totalOrders: 0, all: [], - executed: [], + completed: [], unexecuted: [], }) @@ -95,6 +95,21 @@ const useStopLossOrders = () => { } }, [account, chainId]) + const fetchCanceledRegistryHistory = useCallback(async () => { + try { + Moralis.initialize((chainId && MORALIS_INFO[chainId].key) || '') + Moralis.serverURL = (chainId && MORALIS_INFO[chainId].serverURL) || '' + + const queryCanceled = new Moralis.Query('RegistryCancelRequests') + queryCanceled.limit(QUERY_REQUEST_LIMIT) + let canceledRequests = await queryCanceled.find() + return canceledRequests + } catch (e) { + console.log('Error while fetching canceled history from Moralis') + return [] + } + }, [account, chainId]) + const transform = useCallback( (callData: string, uid: string, status: OrderStatus = OrderStatus.PENDING): DerivedOrder | undefined => { if (!chainId) return @@ -157,26 +172,39 @@ const useStopLossOrders = () => { }) ) + const canceledOrdersCallData = await fetchCanceledRegistryHistory() + const canceledUids = await Promise.all( + canceledOrdersCallData.map(async (request) => { + return request.get('uid') + }) + ) + const allRequests: IRegistryRequest[] = await fetchRegistryHistory() const allOrdersData = allRequests .map((request) => transform(request.callData, request.uid)) .filter((order) => order) as DerivedOrder[] const pendingOrdersData = allRequests - .filter((request) => !executedUids.includes(request.uid)) + .filter((request) => !executedUids.includes(request.uid) && !canceledUids.includes(request.uid)) .map((request) => transform(request.callData, request.uid, OrderStatus.PENDING)) .filter((order) => order) as DerivedOrder[] - const executedOrdersData = allRequests - .filter((request) => executedUids.includes(request.uid)) - .map((request) => transform(request.callData, request.uid, OrderStatus.FILLED)) + const completedOrdersData = allRequests + .filter((request) => executedUids.includes(request.uid) || canceledUids.includes(request.uid)) + .map((request) => + transform( + request.callData, + request.uid, + executedUids.includes(request.uid) ? OrderStatus.FILLED : OrderStatus.CANCELLED + ) + ) .filter((order) => order) as DerivedOrder[] setOrdersData({ loading: false, totalOrders: allOrdersData.length, all: allOrdersData, - executed: executedOrdersData, + completed: completedOrdersData, unexecuted: pendingOrdersData, }) } From 2467f172fb4c75540d2c40b21548f64cbe72eba0 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 31 May 2022 02:06:29 +0900 Subject: [PATCH 36/60] fix: env var for stop-loss --- src/constants/autonomy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index af0db8c0db..e4c13769b7 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -23,11 +23,11 @@ interface MoralisInfo { export const MORALIS_INFO: { [chainId: number]: MoralisInfo } = { [ChainId.AVALANCHE]: { - serverURL: 'https://ietd1r5r9bs1.usemoralis.com:2053/server', - key: '94CRrkmYxPCfdDQQd4L9gGiem3PKpZsv25fTSwDO', + serverURL: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_URL_AVAX || '', + key: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY_AVAX || '', }, [ChainId.BSC]: { - serverURL: 'https://mz4k8ltjvwtm.usemoralis.com:2053/server', - key: '0InOR7cWvu3rRwDZRHTDdDZ26Vj7Jc7HOBiYiGWa', + serverURL: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_URL_BSC || '', + key: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY_BSC || '', }, } From e6016a37a881350761f21d1378a3321d05e0e35d Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Mon, 18 Jul 2022 14:31:23 +0900 Subject: [PATCH 37/60] fix: add explainer in stop-loss ui --- src/features/stop-loss/LimitPriceInputPanel.tsx | 4 +++- src/features/stop-loss/StopPriceInputPanel.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/features/stop-loss/LimitPriceInputPanel.tsx b/src/features/stop-loss/LimitPriceInputPanel.tsx index 53000301fc..d0af71b364 100644 --- a/src/features/stop-loss/LimitPriceInputPanel.tsx +++ b/src/features/stop-loss/LimitPriceInputPanel.tsx @@ -2,6 +2,7 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' import { Currency, Price, Trade, TradeType } from '@sushiswap/core-sdk' import Input from 'app/components/Input' +import QuestionHelper from 'app/components/QuestionHelper' import Typography from 'app/components/Typography' import { useAppDispatch } from 'app/state/hooks' import { LimitPrice, setLimitOrderInvertState, setLimitPrice } from 'app/state/limit-order/actions' @@ -22,8 +23,9 @@ const LimitPriceInputPanel: FC = ({ trade, limitPrice }) = return (
- + {i18n._(t`Limit Rate`)} +
diff --git a/src/features/stop-loss/StopPriceInputPanel.tsx b/src/features/stop-loss/StopPriceInputPanel.tsx index c5ef2f5238..977987501e 100644 --- a/src/features/stop-loss/StopPriceInputPanel.tsx +++ b/src/features/stop-loss/StopPriceInputPanel.tsx @@ -2,6 +2,7 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' import { Currency, Price, Trade, TradeType } from '@sushiswap/core-sdk' import Input from 'app/components/Input' +import QuestionHelper from 'app/components/QuestionHelper' import Typography from 'app/components/Typography' import { useAppDispatch } from 'app/state/hooks' import { LimitPrice, setStopLossInvertState, setStopPrice } from 'app/state/limit-order/actions' @@ -22,8 +23,9 @@ const StopPriceInputPanel: FC = ({ trade, stopPrice }) => { return (
- + {i18n._(t`Stop Rate`)} +
From f36a2d8cba2eecb08dfd5980126d18668bc65fd1 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 2 Aug 2022 23:32:59 +0900 Subject: [PATCH 38/60] feat: add input validation in stop-loss ui --- .../stop-loss/LimitPriceInputPanel.tsx | 2 +- .../stop-loss/StopLimitOrderButton.tsx | 2 +- src/state/limit-order/hooks.ts | 23 +++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/features/stop-loss/LimitPriceInputPanel.tsx b/src/features/stop-loss/LimitPriceInputPanel.tsx index d0af71b364..3672d1f96e 100644 --- a/src/features/stop-loss/LimitPriceInputPanel.tsx +++ b/src/features/stop-loss/LimitPriceInputPanel.tsx @@ -24,7 +24,7 @@ const LimitPriceInputPanel: FC = ({ trade, limitPrice }) = return (
- {i18n._(t`Limit Rate`)} + {i18n._(t`Minimum Rate`)}
diff --git a/src/features/stop-loss/StopLimitOrderButton.tsx b/src/features/stop-loss/StopLimitOrderButton.tsx index 0fd0dd08b5..b4ea7950ca 100644 --- a/src/features/stop-loss/StopLimitOrderButton.tsx +++ b/src/features/stop-loss/StopLimitOrderButton.tsx @@ -32,7 +32,7 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const { address } = useENS(recipient) const addPopup = useAddPopup() - const error = useLimitOrderDerivedInputError({ trade }) + const error = useLimitOrderDerivedInputError({ trade, isStopLossOrder: true }) const { deposit } = useLimitOrderExecute() const bentoboxContract = useBentoBoxContract() const masterContractAddress = chainId ? STOP_LIMIT_ORDER_ADDRESS[chainId] : undefined diff --git a/src/state/limit-order/hooks.ts b/src/state/limit-order/hooks.ts index 171f47ef87..84a823f31c 100644 --- a/src/state/limit-order/hooks.ts +++ b/src/state/limit-order/hooks.ts @@ -274,16 +274,33 @@ export const useLimitOrderDerivedTypedInputAmount: UseLimitOrderDerivedTypedInpu }, [inputCurrency, outputCurrency, typedField, typedValue]) } -type UseLimitOrderDerivedInputError = ({ trade }: { trade?: Trade }) => string -export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ trade }) => { +type UseLimitOrderDerivedInputError = ({ + trade, + isStopLossOrder, +}: { + trade?: Trade + isStopLossOrder?: boolean +}) => string +export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ trade, isStopLossOrder }) => { const { recipient, orderExpiration, fromBentoBalance, limitPrice, stopPrice, typedValue } = useLimitOrderState() const { account } = useActiveWeb3React() const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() + const rate = useLimitOrderDerivedLimitPrice() + const stopRate = useStopLossDerivedLimitPrice() const recipientLookup = useENS(recipient) const to = !recipient ? account : recipientLookup.address const parsedRate = useLimitOrderDerivedLimitPrice() const balance = useBentoOrWalletBalance(account ?? undefined, inputCurrency, !fromBentoBalance) const [expertMode] = useExpertModeManager() + const limitPriceOrDefaultPrice = useMemo(() => (limitPrice ? rate : trade?.executionPrice), [limitPrice, trade]) + const stopPriceOrDefaultPrice = useMemo(() => (stopPrice ? stopRate : trade?.executionPrice), [stopPrice, trade]) + const isLimitPriceBiggerThanStopPrice = useMemo( + () => + limitPriceOrDefaultPrice && + stopPriceOrDefaultPrice && + limitPriceOrDefaultPrice?.toSignificant(6) >= stopPriceOrDefaultPrice?.toSignificant(6), + [limitPrice, stopPrice] + ) return useMemo(() => { return !account @@ -298,6 +315,8 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ ? i18n._(t`Select a rate`) : stopPrice !== LimitPrice.CURRENT && parsedRate?.equalTo(ZERO) ? i18n._(t`Select a rate`) + : isStopLossOrder && isLimitPriceBiggerThanStopPrice + ? 'Big minimum rate' : !orderExpiration ? i18n._(t`Select an order expiration`) : !balance From 89d74abcd0a02be9b5fd42960ab08c50e73a5921 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 2 Aug 2022 23:46:40 +0900 Subject: [PATCH 39/60] fix: stop-loss orders ui --- src/state/limit-order/hooks.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state/limit-order/hooks.ts b/src/state/limit-order/hooks.ts index 84a823f31c..06ee0d2729 100644 --- a/src/state/limit-order/hooks.ts +++ b/src/state/limit-order/hooks.ts @@ -315,8 +315,8 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ ? i18n._(t`Select a rate`) : stopPrice !== LimitPrice.CURRENT && parsedRate?.equalTo(ZERO) ? i18n._(t`Select a rate`) - : isStopLossOrder && isLimitPriceBiggerThanStopPrice - ? 'Big minimum rate' + : isStopLossOrder && isLimitPriceBiggerThanStopPrice // for stop-loss orders only + ? 'Minimum larger than stop rate' : !orderExpiration ? i18n._(t`Select an order expiration`) : !balance From 38b4f812463f283bd2a439f5b81649774e1e48e2 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 4 Aug 2022 00:28:18 +0900 Subject: [PATCH 40/60] feat: add amount validation in stop-loss ui --- src/constants/autonomy.ts | 8 +++ .../stop-loss/StopLimitOrderButton.tsx | 34 ++++++++++- src/features/stop-loss/useStopLossExecute.ts | 61 ++++++++++++++++++- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index e4c13769b7..7262efb57c 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -16,6 +16,14 @@ export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { [ChainId.AVALANCHE]: '0x232d595594585613F48aaE9c85861E4aB06CE3E5', } +type FeeAmountOfEthMap = { + [chainId: number]: string +} +// it defines minimum amount of fee(ETH unit) that Autonomy wrapper contract charges when to execute orders. +export const STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM: FeeAmountOfEthMap = { + [ChainId.AVALANCHE]: '0.025', // 0.025 AVAX +} + interface MoralisInfo { serverURL: string key: string diff --git a/src/features/stop-loss/StopLimitOrderButton.tsx b/src/features/stop-loss/StopLimitOrderButton.tsx index b4ea7950ca..14926e341b 100644 --- a/src/features/stop-loss/StopLimitOrderButton.tsx +++ b/src/features/stop-loss/StopLimitOrderButton.tsx @@ -4,8 +4,9 @@ import { Currency, CurrencyAmount, Trade, TradeType } from '@sushiswap/core-sdk' import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' import Button from 'app/components/Button' import Typography from 'app/components/Typography' -import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES, STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM } from 'app/constants/autonomy' import useLimitOrderExecute, { DepositPayload } from 'app/features/legacy/limit-order/useLimitOrderExecute' +import { useEstimateEquivalentEthAmount } from 'app/features/stop-loss/useStopLossExecute' import TridentApproveGate from 'app/features/trident/TridentApproveGate' import { useBentoBoxContract } from 'app/hooks' import useENS from 'app/hooks/useENS' @@ -14,8 +15,11 @@ import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' import { setFromBentoBalance, setLimitOrderBentoPermit, setLimitOrderShowReview } from 'app/state/limit-order/actions' import { useLimitOrderDerivedInputError, useLimitOrderState } from 'app/state/limit-order/hooks' +import { useMemo } from 'react' import React, { FC, useCallback, useState } from 'react' +import { STOP_LIMIT_ORDER_PROFIT_SLIPPAGE } from './utils' + interface StopLimitOrderButton { trade?: Trade parsedAmounts: { @@ -38,6 +42,18 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const masterContractAddress = chainId ? STOP_LIMIT_ORDER_ADDRESS[chainId] : undefined const [permitError, setPermitError] = useState(false) + // check if input token amount is too small, not able to pay autonomy fee + // input token amount(ETH unit) should be greater than feeMinimum * 100 / 10 + // (roughly fee is taken from 10% of total amount) + const inputTokenValueOfEth = useEstimateEquivalentEthAmount(parsedAmounts?.inputAmount) + const tooSmallAmount = useMemo( + () => + chainId && + parseFloat(inputTokenValueOfEth) < + (parseFloat(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId]) * 100) / STOP_LIMIT_ORDER_PROFIT_SLIPPAGE, + [inputTokenValueOfEth] + ) + const _deposit = useCallback( async (payload: DepositPayload) => { const tx = await deposit(payload) @@ -92,7 +108,13 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } })} > {({ approved, loading }) => { - const disabled = !!error || !approved || loading || attemptingTxn || Boolean(recipient && !address && error) + const disabled = + !!error || + !!tooSmallAmount || + !approved || + loading || + attemptingTxn || + Boolean(recipient && !address && error) return ( ) }} diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index 58476f9d0f..b415096972 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -1,13 +1,20 @@ import { defaultAbiCoder } from '@ethersproject/abi' +import { BigNumber } from '@ethersproject/bignumber' import { Signature } from '@ethersproject/bytes' import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' -import { ChainId, Currency, CurrencyAmount, Price } from '@sushiswap/core-sdk' +import { formatUnits } from '@ethersproject/units' +import { ChainId, Currency, CurrencyAmount, Price, WNATIVE_ADDRESS } from '@sushiswap/core-sdk' import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sdk' import { CHAINLINK_ORACLE_ADDRESS, MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' -import { useAutonomyLimitOrderWrapperContract, useAutonomyRegistryContract } from 'app/hooks' +import { + useAutonomyLimitOrderWrapperContract, + useAutonomyRegistryContract, + useFactoryContract, + usePairContract, +} from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' @@ -15,6 +22,7 @@ import { clear, setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions import { OrderExpiration } from 'app/state/limit-order/reducer' import { useTransactionAdder } from 'app/state/transactions/hooks' import Moralis from 'moralis' +import { useEffect, useState } from 'react' import { useCallback } from 'react' import { calculateAmountExternal, prepareStopPriceOracleData, ZERO_ORACLE_ADDRESS, ZERO_ORACLE_DATA } from './utils' @@ -54,6 +62,55 @@ export type UseLimitOrderExecute = () => { cancelRequest: (id: string) => void } +export function useEstimateEquivalentEthAmount(token: CurrencyAmount | undefined): string { + const { chainId } = useActiveWeb3React() + + const [lpAddress, setLpAddress] = useState(AddressZero) // LP with ETH + const [equivalentEthAmount, setEquivalentEthAmount] = useState('0') + + const factory = useFactoryContract() + const pairContract = usePairContract(lpAddress) + + useEffect(() => { + const updateLiquidityPairAddress = async () => { + if (!factory || !chainId || !token) return + if (token.wrapped.currency.address === WNATIVE_ADDRESS[chainId]) return + + const pairAddress = await factory.getPair(WNATIVE_ADDRESS[chainId], token.wrapped.currency.address) + setLpAddress(pairAddress) + console.log('pair address: ', pairAddress) + } + + updateLiquidityPairAddress() + }, [token?.wrapped.currency.address]) + + useEffect(() => { + const updateEquivalentEthAmount = async () => { + if (!factory || !chainId || !token) return + if (token.wrapped.currency.address === WNATIVE_ADDRESS[chainId]) { + setEquivalentEthAmount(formatUnits(token.quotient.toString(), 18)) + return + } + + if (!pairContract || lpAddress === AddressZero) { + // lp does not exist + return + } + const token0 = await pairContract.token0() + const reserves = await pairContract.getReserves() + const ethAmount = BigNumber.from(token.quotient.toString()) + .mul(token0 !== WNATIVE_ADDRESS[chainId] ? reserves.reserve1 : reserves.reserve0) // eth reserve + .div(BigNumber.from(token0 === WNATIVE_ADDRESS[chainId] ? reserves.reserve1 : reserves.reserve0)) // token reserve + + setEquivalentEthAmount(formatUnits(ethAmount, 18)) + } + + updateEquivalentEthAmount() + }, [token, pairContract]) + + return equivalentEthAmount +} + const useStopLossExecute: UseLimitOrderExecute = () => { const { account, chainId, library } = useActiveWeb3React() From fb2b207c9d865cd7d54fc7d32b4ed90aa70afe79 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 4 Aug 2022 23:33:03 +0900 Subject: [PATCH 41/60] fix: margin rate validation in stop-loss order --- .../stop-loss/StopLimitOrderButton.tsx | 37 ++++++++------- src/features/stop-loss/useStopLossExecute.ts | 47 ++++--------------- 2 files changed, 30 insertions(+), 54 deletions(-) diff --git a/src/features/stop-loss/StopLimitOrderButton.tsx b/src/features/stop-loss/StopLimitOrderButton.tsx index 14926e341b..bc886303bc 100644 --- a/src/features/stop-loss/StopLimitOrderButton.tsx +++ b/src/features/stop-loss/StopLimitOrderButton.tsx @@ -14,12 +14,15 @@ import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' import { setFromBentoBalance, setLimitOrderBentoPermit, setLimitOrderShowReview } from 'app/state/limit-order/actions' -import { useLimitOrderDerivedInputError, useLimitOrderState } from 'app/state/limit-order/hooks' +import { + useLimitOrderDerivedInputError, + useLimitOrderDerivedLimitPrice, + useLimitOrderState, + useStopLossDerivedLimitPrice, +} from 'app/state/limit-order/hooks' import { useMemo } from 'react' import React, { FC, useCallback, useState } from 'react' -import { STOP_LIMIT_ORDER_PROFIT_SLIPPAGE } from './utils' - interface StopLimitOrderButton { trade?: Trade parsedAmounts: { @@ -35,6 +38,8 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const { fromBentoBalance, bentoPermit, attemptingTxn, recipient } = useLimitOrderState() const { address } = useENS(recipient) const addPopup = useAddPopup() + const rate = useLimitOrderDerivedLimitPrice() + const stopRate = useStopLossDerivedLimitPrice() const error = useLimitOrderDerivedInputError({ trade, isStopLossOrder: true }) const { deposit } = useLimitOrderExecute() @@ -42,16 +47,16 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const masterContractAddress = chainId ? STOP_LIMIT_ORDER_ADDRESS[chainId] : undefined const [permitError, setPermitError] = useState(false) - // check if input token amount is too small, not able to pay autonomy fee - // input token amount(ETH unit) should be greater than feeMinimum * 100 / 10 - // (roughly fee is taken from 10% of total amount) - const inputTokenValueOfEth = useEstimateEquivalentEthAmount(parsedAmounts?.inputAmount) - const tooSmallAmount = useMemo( - () => - chainId && - parseFloat(inputTokenValueOfEth) < - (parseFloat(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId]) * 100) / STOP_LIMIT_ORDER_PROFIT_SLIPPAGE, - [inputTokenValueOfEth] + // check if difference between stopRate and minimum rate is enough to cover autonomy fee + const diffOfStopAndMinRate = useMemo(() => { + if (!stopRate || !rate || !parsedAmounts.inputAmount || stopRate.equalTo(rate) || stopRate.lessThan(rate)) + return undefined + return stopRate?.quote(parsedAmounts.inputAmount).subtract(rate?.quote(parsedAmounts.inputAmount)) + }, [rate, stopRate, parsedAmounts]) + const diffValueOfEth = useEstimateEquivalentEthAmount(diffOfStopAndMinRate) + const tooNarrowMarginOfRates = useMemo( + () => chainId && parseFloat(diffValueOfEth) < parseFloat(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId]), + [diffValueOfEth] ) const _deposit = useCallback( @@ -110,7 +115,7 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } {({ approved, loading }) => { const disabled = !!error || - !!tooSmallAmount || + !!tooNarrowMarginOfRates || !approved || loading || attemptingTxn || @@ -125,8 +130,8 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } > {error ? error - : tooSmallAmount - ? 'Too small amount' + : tooNarrowMarginOfRates + ? 'Too narrow margin of rates' : fromBentoBalance ? i18n._(t`Review Stop Limit Order`) : i18n._(t`Confirm Deposit`)} diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index b415096972..b0eb2ba59c 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -1,5 +1,4 @@ import { defaultAbiCoder } from '@ethersproject/abi' -import { BigNumber } from '@ethersproject/bignumber' import { Signature } from '@ethersproject/bytes' import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' @@ -9,12 +8,7 @@ import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sd import { CHAINLINK_ORACLE_ADDRESS, MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' -import { - useAutonomyLimitOrderWrapperContract, - useAutonomyRegistryContract, - useFactoryContract, - usePairContract, -} from 'app/hooks' +import { useAutonomyLimitOrderWrapperContract, useAutonomyRegistryContract, useRouterContract } from 'app/hooks' import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' @@ -64,49 +58,26 @@ export type UseLimitOrderExecute = () => { export function useEstimateEquivalentEthAmount(token: CurrencyAmount | undefined): string { const { chainId } = useActiveWeb3React() - - const [lpAddress, setLpAddress] = useState(AddressZero) // LP with ETH + const router = useRouterContract() const [equivalentEthAmount, setEquivalentEthAmount] = useState('0') - const factory = useFactoryContract() - const pairContract = usePairContract(lpAddress) - - useEffect(() => { - const updateLiquidityPairAddress = async () => { - if (!factory || !chainId || !token) return - if (token.wrapped.currency.address === WNATIVE_ADDRESS[chainId]) return - - const pairAddress = await factory.getPair(WNATIVE_ADDRESS[chainId], token.wrapped.currency.address) - setLpAddress(pairAddress) - console.log('pair address: ', pairAddress) - } - - updateLiquidityPairAddress() - }, [token?.wrapped.currency.address]) - useEffect(() => { const updateEquivalentEthAmount = async () => { - if (!factory || !chainId || !token) return + if (!router || !chainId || !token) return if (token.wrapped.currency.address === WNATIVE_ADDRESS[chainId]) { setEquivalentEthAmount(formatUnits(token.quotient.toString(), 18)) return } - if (!pairContract || lpAddress === AddressZero) { - // lp does not exist - return - } - const token0 = await pairContract.token0() - const reserves = await pairContract.getReserves() - const ethAmount = BigNumber.from(token.quotient.toString()) - .mul(token0 !== WNATIVE_ADDRESS[chainId] ? reserves.reserve1 : reserves.reserve0) // eth reserve - .div(BigNumber.from(token0 === WNATIVE_ADDRESS[chainId] ? reserves.reserve1 : reserves.reserve0)) // token reserve - - setEquivalentEthAmount(formatUnits(ethAmount, 18)) + const amountsOut = await router.getAmountsOut(token.quotient.toString(), [ + token.wrapped.currency.address, + WNATIVE_ADDRESS[chainId], + ]) + setEquivalentEthAmount(formatUnits(amountsOut[amountsOut.length - 1], 18)) } updateEquivalentEthAmount() - }, [token, pairContract]) + }, [token]) return equivalentEthAmount } From d1e9956e81c95040f4d15347dc6d95b4d98eb741 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 5 Aug 2022 00:31:25 +0900 Subject: [PATCH 42/60] refactor: stop and minimum rate validation in stop-loss --- .../stop-loss/StopLimitOrderButton.tsx | 27 +++-------- src/features/stop-loss/useStopLossExecute.ts | 46 ++++++++++++++++++- src/features/stop-loss/utils.ts | 6 +-- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/features/stop-loss/StopLimitOrderButton.tsx b/src/features/stop-loss/StopLimitOrderButton.tsx index bc886303bc..e2ceebccab 100644 --- a/src/features/stop-loss/StopLimitOrderButton.tsx +++ b/src/features/stop-loss/StopLimitOrderButton.tsx @@ -4,9 +4,9 @@ import { Currency, CurrencyAmount, Trade, TradeType } from '@sushiswap/core-sdk' import { STOP_LIMIT_ORDER_ADDRESS } from '@sushiswap/limit-order-sdk' import Button from 'app/components/Button' import Typography from 'app/components/Typography' -import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES, STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM } from 'app/constants/autonomy' +import { STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' import useLimitOrderExecute, { DepositPayload } from 'app/features/legacy/limit-order/useLimitOrderExecute' -import { useEstimateEquivalentEthAmount } from 'app/features/stop-loss/useStopLossExecute' +import { useDiffOfStopAndMinimumRate } from 'app/features/stop-loss/useStopLossExecute' import TridentApproveGate from 'app/features/trident/TridentApproveGate' import { useBentoBoxContract } from 'app/hooks' import useENS from 'app/hooks/useENS' @@ -14,13 +14,7 @@ import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' import { setFromBentoBalance, setLimitOrderBentoPermit, setLimitOrderShowReview } from 'app/state/limit-order/actions' -import { - useLimitOrderDerivedInputError, - useLimitOrderDerivedLimitPrice, - useLimitOrderState, - useStopLossDerivedLimitPrice, -} from 'app/state/limit-order/hooks' -import { useMemo } from 'react' +import { useLimitOrderDerivedInputError, useLimitOrderState } from 'app/state/limit-order/hooks' import React, { FC, useCallback, useState } from 'react' interface StopLimitOrderButton { @@ -38,8 +32,6 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const { fromBentoBalance, bentoPermit, attemptingTxn, recipient } = useLimitOrderState() const { address } = useENS(recipient) const addPopup = useAddPopup() - const rate = useLimitOrderDerivedLimitPrice() - const stopRate = useStopLossDerivedLimitPrice() const error = useLimitOrderDerivedInputError({ trade, isStopLossOrder: true }) const { deposit } = useLimitOrderExecute() @@ -48,16 +40,9 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } const [permitError, setPermitError] = useState(false) // check if difference between stopRate and minimum rate is enough to cover autonomy fee - const diffOfStopAndMinRate = useMemo(() => { - if (!stopRate || !rate || !parsedAmounts.inputAmount || stopRate.equalTo(rate) || stopRate.lessThan(rate)) - return undefined - return stopRate?.quote(parsedAmounts.inputAmount).subtract(rate?.quote(parsedAmounts.inputAmount)) - }, [rate, stopRate, parsedAmounts]) - const diffValueOfEth = useEstimateEquivalentEthAmount(diffOfStopAndMinRate) - const tooNarrowMarginOfRates = useMemo( - () => chainId && parseFloat(diffValueOfEth) < parseFloat(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId]), - [diffValueOfEth] - ) + const { tooNarrowMarginOfRates } = useDiffOfStopAndMinimumRate({ + inputAmount: parsedAmounts.inputAmount, + }) const _deposit = useCallback( async (payload: DepositPayload) => { diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index b0eb2ba59c..66ce5b3704 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -5,7 +5,12 @@ import { TransactionResponse } from '@ethersproject/providers' import { formatUnits } from '@ethersproject/units' import { ChainId, Currency, CurrencyAmount, Price, WNATIVE_ADDRESS } from '@sushiswap/core-sdk' import { LimitOrder, ROUND_UP_RECEIVER_ADDRESS } from '@sushiswap/limit-order-sdk' -import { CHAINLINK_ORACLE_ADDRESS, MORALIS_INFO, STOP_LIMIT_ORDER_WRAPPER_ADDRESSES } from 'app/constants/autonomy' +import { + CHAINLINK_ORACLE_ADDRESS, + MORALIS_INFO, + STOP_LIMIT_ORDER_WRAPPER_ADDRESSES, + STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM, +} from 'app/constants/autonomy' import useLimitOrders from 'app/features/legacy/limit-order/useLimitOrders' import { ZERO } from 'app/functions' import { useAutonomyLimitOrderWrapperContract, useAutonomyRegistryContract, useRouterContract } from 'app/hooks' @@ -13,10 +18,11 @@ import { useActiveWeb3React } from 'app/services/web3' import { useAddPopup } from 'app/state/application/hooks' import { useAppDispatch } from 'app/state/hooks' import { clear, setLimitOrderAttemptingTxn } from 'app/state/limit-order/actions' +import { useLimitOrderDerivedLimitPrice, useStopLossDerivedLimitPrice } from 'app/state/limit-order/hooks' import { OrderExpiration } from 'app/state/limit-order/reducer' import { useTransactionAdder } from 'app/state/transactions/hooks' import Moralis from 'moralis' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useCallback } from 'react' import { calculateAmountExternal, prepareStopPriceOracleData, ZERO_ORACLE_ADDRESS, ZERO_ORACLE_DATA } from './utils' @@ -82,6 +88,42 @@ export function useEstimateEquivalentEthAmount(token: CurrencyAmount | return equivalentEthAmount } +interface DifferenceOfStopAndMinimumRateResult { + diffOfStopAndMinRate: CurrencyAmount | undefined + diffValueOfEth: string + tooNarrowMarginOfRates: boolean +} + +// check if difference between stopRate and minimum rate is enough to cover autonomy fee +export function useDiffOfStopAndMinimumRate({ + inputAmount, +}: { + inputAmount: CurrencyAmount | undefined +}): DifferenceOfStopAndMinimumRateResult { + const { chainId } = useActiveWeb3React() + const rate = useLimitOrderDerivedLimitPrice() + const stopRate = useStopLossDerivedLimitPrice() + + // get difference of output amounts between stop and minimum rate + const diffOfStopAndMinRate = useMemo(() => { + if (!stopRate || !rate || !inputAmount || stopRate.equalTo(rate) || stopRate.lessThan(rate)) return undefined + return stopRate?.quote(inputAmount).subtract(rate?.quote(inputAmount)) + }, [rate, stopRate, inputAmount]) + // get equivalent ETH amount of difference + const diffValueOfEth = useEstimateEquivalentEthAmount(diffOfStopAndMinRate) + // compare with minimum fee amount + const tooNarrowMarginOfRates = useMemo( + () => (!!chainId ? parseFloat(diffValueOfEth) < parseFloat(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId]) : false), + [diffValueOfEth] + ) + + return { + diffOfStopAndMinRate, + diffValueOfEth, + tooNarrowMarginOfRates, + } +} + const useStopLossExecute: UseLimitOrderExecute = () => { const { account, chainId, library } = useActiveWeb3React() diff --git a/src/features/stop-loss/utils.ts b/src/features/stop-loss/utils.ts index cf8aac359b..ded104f13e 100644 --- a/src/features/stop-loss/utils.ts +++ b/src/features/stop-loss/utils.ts @@ -1,14 +1,10 @@ import { defaultAbiCoder } from '@ethersproject/abi' -import { Currency, CurrencyAmount, Price, Token, WNATIVE_ADDRESS } from '@sushiswap/core-sdk' +import { Currency, CurrencyAmount, Price, Token } from '@sushiswap/core-sdk' import { CHAINLINK_PRICE_FEED_MAP, ChainlinkPriceFeedEntry } from 'app/config/oracles/chainlink' import { BigNumber } from 'ethers' export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 10 // percent unit -export function keepTokenIn(tokenIn: string, tokenOut: string, chainId: number): boolean { - return tokenIn === WNATIVE_ADDRESS[chainId] ? true : false -} - /** * @dev StopLimitOrder charges fee from the output token always, and so swap 110% of output token, and deduct fee. * From 690dfd0e7296a3a0099f7d3bda2def420aaa9b1a Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 5 Aug 2022 21:37:19 +0900 Subject: [PATCH 43/60] fix: amountExternal in stop-loss --- src/features/stop-loss/useStopLossExecute.ts | 24 ++++++++++++++++---- src/pages/stop-loss/StopLossReviewModal.tsx | 10 +++++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index 66ce5b3704..6e8adb749a 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -1,4 +1,5 @@ import { defaultAbiCoder } from '@ethersproject/abi' +import { BigNumber } from '@ethersproject/bignumber' import { Signature } from '@ethersproject/bytes' import { AddressZero } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' @@ -25,7 +26,7 @@ import Moralis from 'moralis' import { useEffect, useMemo, useState } from 'react' import { useCallback } from 'react' -import { calculateAmountExternal, prepareStopPriceOracleData, ZERO_ORACLE_ADDRESS, ZERO_ORACLE_DATA } from './utils' +import { prepareStopPriceOracleData, ZERO_ORACLE_ADDRESS, ZERO_ORACLE_DATA } from './utils' const getEndTime = (orderExpiration: OrderExpiration | string): number => { switch (orderExpiration) { @@ -51,6 +52,7 @@ export type ExecutePayload = { orderExpiration: OrderExpiration | string inputAmount?: CurrencyAmount outputAmount?: CurrencyAmount + amountExternal?: CurrencyAmount recipient?: string stopPrice?: Price | undefined } @@ -69,7 +71,10 @@ export function useEstimateEquivalentEthAmount(token: CurrencyAmount | useEffect(() => { const updateEquivalentEthAmount = async () => { - if (!router || !chainId || !token) return + if (!router || !chainId || !token) { + setEquivalentEthAmount('0') + return + } if (token.wrapped.currency.address === WNATIVE_ADDRESS[chainId]) { setEquivalentEthAmount(formatUnits(token.quotient.toString(), 18)) return @@ -92,6 +97,7 @@ interface DifferenceOfStopAndMinimumRateResult { diffOfStopAndMinRate: CurrencyAmount | undefined diffValueOfEth: string tooNarrowMarginOfRates: boolean + externalAmount: string } // check if difference between stopRate and minimum rate is enough to cover autonomy fee @@ -117,10 +123,20 @@ export function useDiffOfStopAndMinimumRate({ [diffValueOfEth] ) + const convertIntWithMultiply = (sValue: string) => `${Math.floor(parseFloat(sValue) * 1000000)}` + // calculate amount for autonomy fee: (stopRate - minimumRate) * MIN_FEE_ETH_AMOUNT / equivalentEthAmountOf[stopRate - minimumRate] + const externalAmountForFee = + !!chainId && !!diffOfStopAndMinRate && parseFloat(diffValueOfEth) > 0 + ? BigNumber.from(diffOfStopAndMinRate?.quotient.toString()) + .mul(BigNumber.from(convertIntWithMultiply(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId]))) + .div(BigNumber.from(convertIntWithMultiply(diffValueOfEth))) + : 0 + return { diffOfStopAndMinRate, diffValueOfEth, tooNarrowMarginOfRates, + externalAmount: externalAmountForFee.toString(), } } @@ -136,7 +152,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { const { mutate } = useLimitOrders() const execute = useCallback( - async ({ orderExpiration, inputAmount, outputAmount, recipient, stopPrice }) => { + async ({ orderExpiration, inputAmount, outputAmount, amountExternal, recipient, stopPrice }) => { if (!inputAmount || !outputAmount || !account || !library || !chainId) throw new Error('Dependencies unavailable') let oracleData @@ -163,7 +179,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { await order?.signOrderWithProvider(chainId || 1, library) if (autonomyRegistryContract && limitOrderWrapperContract && chainId) { - const amountExternal = calculateAmountExternal(inputAmount.wrapped, outputAmount.wrapped, chainId) + // const amountExternal = calculateAmountExternal(inputAmount.wrapped, outputAmount.wrapped, chainId) if (stopPrice && oracleData?.stopPrice == ZERO_ORACLE_DATA) { throw new Error('Unsupported pair') } diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index b3b104d00d..cde27f318c 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -7,7 +7,7 @@ import ListPanel from 'app/components/ListPanel' import { HeadlessUiModal } from 'app/components/Modal' import Typography from 'app/components/Typography' import TradePrice from 'app/features/legacy/swap/TradePrice' -import useStopLossExecute from 'app/features/stop-loss/useStopLossExecute' +import useStopLossExecute, { useDiffOfStopAndMinimumRate } from 'app/features/stop-loss/useStopLossExecute' import { isAddress, shortenAddress } from 'app/functions' import { useAppDispatch } from 'app/state/hooks' import { setLimitOrderShowReview } from 'app/state/limit-order/actions' @@ -30,6 +30,13 @@ const StopLossReviewModal: FC = ({ parsedAmounts, trade, li const { i18n } = useLingui() const { execute } = useStopLossExecute() + const { externalAmount } = useDiffOfStopAndMinimumRate({ + inputAmount: parsedAmounts.inputAmount, + }) + const amountExternal = parsedAmounts.outputAmount + if (parsedAmounts.outputAmount) { + amountExternal?.add(CurrencyAmount.fromRawAmount(parsedAmounts.outputAmount?.currency, externalAmount)) + } const stopRate = useStopLossDerivedLimitPrice() const _execute = useCallback(() => { if (parsedAmounts?.inputAmount && parsedAmounts?.outputAmount) { @@ -37,6 +44,7 @@ const StopLossReviewModal: FC = ({ parsedAmounts, trade, li orderExpiration: orderExpiration.value, recipient, outputAmount: parsedAmounts.outputAmount, + amountExternal, // outputAmount + feeRelatedAmount inputAmount: parsedAmounts.inputAmount, stopPrice: stopRate, }) From 2528a364e0ac3527b9071a9a01c5867d042449b8 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 5 Aug 2022 22:27:18 +0900 Subject: [PATCH 44/60] chore: moralis version --- package.json | 2 +- yarn.lock | 29 ++++++++++++----------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 9611175c27..14ca532e55 100644 --- a/package.json +++ b/package.json @@ -250,6 +250,6 @@ }, "dependencies": { "@sushiswap/default-token-list": "^28.0.0", - "moralis": "^1.7.0" + "moralis": "^1.11.0" } } diff --git a/yarn.lock b/yarn.lock index 8ddae9aa1a..20bb1773db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5613,9 +5613,9 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1: semver "7.0.0" core-js-pure@^3.20.2: - version "3.23.4" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.23.4.tgz#aba5c7fb297063444f6bf93afb0362151679a012" - integrity sha512-lizxkcgj3XDmi7TUBFe+bQ1vNpD5E4t76BrBWI3HdUxdw/Mq1VF4CkiHzIKyieECKtcODK2asJttoofEeUKICQ== + version "3.24.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.24.1.tgz#8839dde5da545521bf282feb7dc6d0b425f39fd3" + integrity sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg== core-util-is@1.0.2: version "1.0.2" @@ -7447,16 +7447,11 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" -follow-redirects@^1.14.0: +follow-redirects@^1.14.0, follow-redirects@^1.14.8: version "1.15.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== -follow-redirects@^1.14.8: - version "1.15.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4" - integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== - for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -10005,10 +10000,10 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" -moralis@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/moralis/-/moralis-1.7.0.tgz#2d39fd54e56982402c0b5177c4c5b1457e2a81ec" - integrity sha512-hgVdUQvm6a1zZGxODemLgMDMlMXPRQS1685NhZ6uz4Q94KeiMRxvYFN/N2yzhi4dAT5Qb0RMjzZh16ylgalwaA== +moralis@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/moralis/-/moralis-1.11.0.tgz#aa736cf5acbd3f65ac83d44f2e4e12e0e88566f8" + integrity sha512-oqoKqP47RuHq+SnztN48+YgWsKLt1YBy7IfeSBOixUW0Tzn9RQDjNKpkSBcKFttNZQ/KzCEes6TCqA9IxSoTPQ== dependencies: "@babel/runtime" "7.16.7" "@babel/runtime-corejs3" "7.16.8" @@ -13988,9 +13983,9 @@ ws@^7.3.1, ws@^7.4.0, ws@^7.4.6: integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw== ws@^8.3.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.6.0.tgz#e5e9f1d9e7ff88083d0c0dd8281ea662a42c9c23" - integrity sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw== + version "8.8.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" + integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== xhr@^2.0.1, xhr@^2.2.0: version "2.6.0" @@ -14033,7 +14028,7 @@ xmlchars@^2.2.0: xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0: version "4.0.2" From b1183ae04712afe0b63c71ae9dc48600d1d8cb90 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 5 Aug 2022 22:50:56 +0900 Subject: [PATCH 45/60] fix: moralis version --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 14ca532e55..9611175c27 100644 --- a/package.json +++ b/package.json @@ -250,6 +250,6 @@ }, "dependencies": { "@sushiswap/default-token-list": "^28.0.0", - "moralis": "^1.11.0" + "moralis": "^1.7.0" } } diff --git a/yarn.lock b/yarn.lock index 20bb1773db..4935b997e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10000,7 +10000,7 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" -moralis@^1.11.0: +moralis@^1.7.0: version "1.11.0" resolved "https://registry.yarnpkg.com/moralis/-/moralis-1.11.0.tgz#aa736cf5acbd3f65ac83d44f2e4e12e0e88566f8" integrity sha512-oqoKqP47RuHq+SnztN48+YgWsKLt1YBy7IfeSBOixUW0Tzn9RQDjNKpkSBcKFttNZQ/KzCEes6TCqA9IxSoTPQ== From 18830dbbf4a318825f208100d50dd88066a05759 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sat, 6 Aug 2022 00:04:03 +0900 Subject: [PATCH 46/60] fix: stop-loss order params --- src/features/stop-loss/useStopLossExecute.ts | 7 +++---- src/features/stop-loss/utils.ts | 18 ------------------ src/pages/stop-loss/StopLossReviewModal.tsx | 11 +++++------ 3 files changed, 8 insertions(+), 28 deletions(-) diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index 6e8adb749a..408db80292 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -97,7 +97,7 @@ interface DifferenceOfStopAndMinimumRateResult { diffOfStopAndMinRate: CurrencyAmount | undefined diffValueOfEth: string tooNarrowMarginOfRates: boolean - externalAmount: string + externalAmountForFee: string } // check if difference between stopRate and minimum rate is enough to cover autonomy fee @@ -136,7 +136,7 @@ export function useDiffOfStopAndMinimumRate({ diffOfStopAndMinRate, diffValueOfEth, tooNarrowMarginOfRates, - externalAmount: externalAmountForFee.toString(), + externalAmountForFee: externalAmountForFee.toString(), } } @@ -179,7 +179,6 @@ const useStopLossExecute: UseLimitOrderExecute = () => { await order?.signOrderWithProvider(chainId || 1, library) if (autonomyRegistryContract && limitOrderWrapperContract && chainId) { - // const amountExternal = calculateAmountExternal(inputAmount.wrapped, outputAmount.wrapped, chainId) if (stopPrice && oracleData?.stopPrice == ZERO_ORACLE_DATA) { throw new Error('Unsupported pair') } @@ -187,7 +186,7 @@ const useStopLossExecute: UseLimitOrderExecute = () => { ['address[]', 'uint256', 'address', 'bool'], [ [order.tokenInAddress, order.tokenOutAddress], // path - amountExternal, // amountExternal + amountExternal?.wrapped.quotient.toString(), chainId && STOP_LIMIT_ORDER_WRAPPER_ADDRESSES[chainId], // profit receiver false, // keepTokenIn, charge fee, by outputToken always ] diff --git a/src/features/stop-loss/utils.ts b/src/features/stop-loss/utils.ts index ded104f13e..f0005a0d93 100644 --- a/src/features/stop-loss/utils.ts +++ b/src/features/stop-loss/utils.ts @@ -5,24 +5,6 @@ import { BigNumber } from 'ethers' export const STOP_LIMIT_ORDER_PROFIT_SLIPPAGE = 10 // percent unit -/** - * @dev StopLimitOrder charges fee from the output token always, and so swap 110% of output token, and deduct fee. - * - * @param tokenIn - * @param tokenOut - * @param chainId - * @returns - */ -export function calculateAmountExternal( - tokenIn: CurrencyAmount, - tokenOut: CurrencyAmount, - chainId: number -): BigNumber { - return BigNumber.from(tokenOut.quotient.toString()) - .mul(100 + STOP_LIMIT_ORDER_PROFIT_SLIPPAGE) - .div(100) -} - export interface IStopPriceOracleData { stopPrice?: string oracleData: string diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index cde27f318c..ede31b7086 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -30,13 +30,10 @@ const StopLossReviewModal: FC = ({ parsedAmounts, trade, li const { i18n } = useLingui() const { execute } = useStopLossExecute() - const { externalAmount } = useDiffOfStopAndMinimumRate({ + const { externalAmountForFee } = useDiffOfStopAndMinimumRate({ inputAmount: parsedAmounts.inputAmount, }) - const amountExternal = parsedAmounts.outputAmount - if (parsedAmounts.outputAmount) { - amountExternal?.add(CurrencyAmount.fromRawAmount(parsedAmounts.outputAmount?.currency, externalAmount)) - } + const stopRate = useStopLossDerivedLimitPrice() const _execute = useCallback(() => { if (parsedAmounts?.inputAmount && parsedAmounts?.outputAmount) { @@ -44,7 +41,9 @@ const StopLossReviewModal: FC = ({ parsedAmounts, trade, li orderExpiration: orderExpiration.value, recipient, outputAmount: parsedAmounts.outputAmount, - amountExternal, // outputAmount + feeRelatedAmount + amountExternal: parsedAmounts.outputAmount?.add( + CurrencyAmount.fromRawAmount(parsedAmounts.outputAmount?.currency, externalAmountForFee) + ), // outputAmount + feeRelatedAmount inputAmount: parsedAmounts.inputAmount, stopPrice: stopRate, }) From 613ee23421422d0c45f1480a5dafa266fad4f737 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sat, 6 Aug 2022 00:49:24 +0900 Subject: [PATCH 47/60] fix: stop-loss validation --- src/state/limit-order/hooks.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/state/limit-order/hooks.ts b/src/state/limit-order/hooks.ts index 06ee0d2729..f77399deed 100644 --- a/src/state/limit-order/hooks.ts +++ b/src/state/limit-order/hooks.ts @@ -292,14 +292,14 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ const parsedRate = useLimitOrderDerivedLimitPrice() const balance = useBentoOrWalletBalance(account ?? undefined, inputCurrency, !fromBentoBalance) const [expertMode] = useExpertModeManager() - const limitPriceOrDefaultPrice = useMemo(() => (limitPrice ? rate : trade?.executionPrice), [limitPrice, trade]) + const limitPriceOrDefaultPrice = useMemo(() => (rate ? rate : trade?.executionPrice), [rate, trade]) const stopPriceOrDefaultPrice = useMemo(() => (stopPrice ? stopRate : trade?.executionPrice), [stopPrice, trade]) const isLimitPriceBiggerThanStopPrice = useMemo( () => limitPriceOrDefaultPrice && stopPriceOrDefaultPrice && - limitPriceOrDefaultPrice?.toSignificant(6) >= stopPriceOrDefaultPrice?.toSignificant(6), - [limitPrice, stopPrice] + parseFloat(limitPriceOrDefaultPrice?.toSignificant(6)) >= parseFloat(stopPriceOrDefaultPrice?.toSignificant(6)), + [limitPriceOrDefaultPrice, stopPriceOrDefaultPrice] ) return useMemo(() => { From 0c776b20707fd59df3b82c42f960e811f490f0ca Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Mon, 8 Aug 2022 18:23:01 +0900 Subject: [PATCH 48/60] fix: stop-loss validation --- src/pages/stop-loss/StopLossReviewModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/stop-loss/StopLossReviewModal.tsx b/src/pages/stop-loss/StopLossReviewModal.tsx index ede31b7086..a945f76184 100644 --- a/src/pages/stop-loss/StopLossReviewModal.tsx +++ b/src/pages/stop-loss/StopLossReviewModal.tsx @@ -36,7 +36,7 @@ const StopLossReviewModal: FC = ({ parsedAmounts, trade, li const stopRate = useStopLossDerivedLimitPrice() const _execute = useCallback(() => { - if (parsedAmounts?.inputAmount && parsedAmounts?.outputAmount) { + if (parsedAmounts?.inputAmount && parsedAmounts?.outputAmount && parseInt(externalAmountForFee) > 0) { execute({ orderExpiration: orderExpiration.value, recipient, From 57c3bacb10df4e78e439b71ad113fe3d92c7e1fc Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 9 Aug 2022 00:58:59 +0900 Subject: [PATCH 49/60] fix: pagination in stop-loss ui --- src/features/stop-loss/CompletedOrders.tsx | 14 +++- src/features/stop-loss/MyStopOrders.tsx | 6 +- src/features/stop-loss/OpenOrders.tsx | 14 +++- src/features/stop-loss/useStopLossOrders.tsx | 84 +++++++++++++++++--- 4 files changed, 99 insertions(+), 19 deletions(-) diff --git a/src/features/stop-loss/CompletedOrders.tsx b/src/features/stop-loss/CompletedOrders.tsx index 64e81416f0..dab4af8f52 100644 --- a/src/features/stop-loss/CompletedOrders.tsx +++ b/src/features/stop-loss/CompletedOrders.tsx @@ -1,5 +1,6 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' +import Pagination from 'app/components/Pagination' import Typography from 'app/components/Typography' import { useCompletedOrdersTableConfig } from 'app/features/stop-loss/useCompletedOrdersTableConfig' import { @@ -20,8 +21,8 @@ import useStopLossOrders from './useStopLossOrders' const CompletedOrders: FC = () => { const { i18n } = useLingui() const { account } = useActiveWeb3React() - const { loading, completed } = useStopLossOrders() - const { config } = useCompletedOrdersTableConfig({ orders: completed }) + const { loading, completed, setCompletedPage } = useStopLossOrders() + const { config } = useCompletedOrdersTableConfig({ orders: completed.data }) // @ts-ignore TYPE NEEDS FIXING const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( @@ -111,6 +112,15 @@ const CompletedOrders: FC = () => {
+ + 1} + canNextPage={completed.page < completed.maxPages} + onChange={(page) => setCompletedPage(page + 1)} + totalPages={completed.maxPages} + currentPage={completed.page - 1} + pageNeighbours={1} + />
) } diff --git a/src/features/stop-loss/MyStopOrders.tsx b/src/features/stop-loss/MyStopOrders.tsx index c00bd7a503..8c66db9634 100644 --- a/src/features/stop-loss/MyStopOrders.tsx +++ b/src/features/stop-loss/MyStopOrders.tsx @@ -9,7 +9,7 @@ import React, { FC } from 'react' const MyStopOrders: FC = () => { const { i18n } = useLingui() - const { unexecuted } = useStopLossOrders() + const { pending } = useStopLossOrders() const content = ( { return (
- {unexecuted.length > 0 ? ( - + {pending.allData.length > 0 ? ( + {content} ) : ( diff --git a/src/features/stop-loss/OpenOrders.tsx b/src/features/stop-loss/OpenOrders.tsx index c08c2fc0d8..d4f748d3b4 100644 --- a/src/features/stop-loss/OpenOrders.tsx +++ b/src/features/stop-loss/OpenOrders.tsx @@ -1,6 +1,7 @@ import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' import { LimitOrder } from '@sushiswap/limit-order-sdk' +import Pagination from 'app/components/Pagination' import Typography from 'app/components/Typography' import { TABLE_TABLE_CLASSNAME, @@ -28,7 +29,7 @@ const OpenOrders: FC = () => { const limitOrderContract = useLimitOrderContract(true) const { cancelRequest } = useStopLossExecute() - const { loading, unexecuted } = useStopLossOrders() + const { loading, pending, setPendingPage } = useStopLossOrders() const cancelOrder = useCallback( async (id: string, limitOrder: LimitOrder, summary: string) => { @@ -39,7 +40,7 @@ const OpenOrders: FC = () => { [addTransaction, limitOrderContract] ) - const { config } = useOpenOrdersTableConfig({ orders: unexecuted, cancelOrder }) + const { config } = useOpenOrdersTableConfig({ orders: pending.data, cancelOrder }) // @ts-ignore TYPE NEEDS FIXING const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page } = useTable( @@ -129,6 +130,15 @@ const OpenOrders: FC = () => {
+ + 1} + canNextPage={pending.page < pending.maxPages} + onChange={(page) => setPendingPage(page + 1)} + totalPages={pending.maxPages} + currentPage={pending.page - 1} + pageNeighbours={1} + />
) } diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index da9746f42a..2f2b464c92 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -32,11 +32,18 @@ interface IRegistryRequest { } interface OrdersData { + allData: Array + data: Array + page: number + maxPages: number +} + +interface StopLossOrdersData { loading: boolean totalOrders: number all: Array - completed: Array - unexecuted: Array + pending: OrdersData + completed: OrdersData } const useStopLossOrders = () => { @@ -48,12 +55,22 @@ const useStopLossOrders = () => { [chainId] ) - const [ordersData, setOrdersData] = useState({ + const [state, setState] = useState({ loading: false, totalOrders: 0, all: [], - completed: [], - unexecuted: [], + pending: { + allData: [], + data: [], + page: 1, + maxPages: 1, + }, + completed: { + allData: [], + data: [], + page: 1, + maxPages: 1, + }, }) const fetchRegistryHistory = useCallback(async () => { @@ -160,10 +177,10 @@ const useStopLossOrders = () => { const initOrdersData = async () => { if (!account || !chainId) return - setOrdersData({ - ...ordersData, + setState((prevState) => ({ + ...prevState, loading: true, - }) + })) const executedOrdersCallData = await fetchExecutedRegistryHistory() const executedUids = await Promise.all( @@ -200,19 +217,62 @@ const useStopLossOrders = () => { ) .filter((order) => order) as DerivedOrder[] - setOrdersData({ + setState({ loading: false, totalOrders: allOrdersData.length, all: allOrdersData, - completed: completedOrdersData, - unexecuted: pendingOrdersData, + completed: { + allData: completedOrdersData, + data: completedOrdersData.slice(0, 10), + page: 1, + maxPages: Math.ceil(completedOrdersData.length / 10), + }, + pending: { + allData: pendingOrdersData, + data: pendingOrdersData.slice(0, 10), + page: 1, + maxPages: Math.ceil(pendingOrdersData.length / 10), + }, }) } initOrdersData() }, [account, chainId]) - return ordersData + const setCompletedPage = useCallback((page: number) => { + if (page < 1 || page > state.completed.maxPages) return + + setState((prevState) => ({ + ...prevState, + completed: { + ...prevState.completed, + page, + data: prevState.completed.allData.slice(10 * (page - 1), 10 * page), + }, + })) + }, []) + + const setPendingPage = useCallback((page: number) => { + if (page < 1 || page > state.pending.maxPages) return + + setState((prevState) => ({ + ...prevState, + pending: { + ...prevState.pending, + page, + data: prevState.pending.allData.slice(10 * (page - 1), 10 * page), + }, + })) + }, []) + + return useMemo( + () => ({ + ...state, + setCompletedPage, + setPendingPage, + }), + [setCompletedPage, setPendingPage, state] + ) } export default useStopLossOrders From b66d78638a913543315a1b49213e81a945b7fd48 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 9 Aug 2022 01:17:39 +0900 Subject: [PATCH 50/60] fix: stop-loss orders pagination --- src/features/stop-loss/useStopLossOrders.tsx | 56 +++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index 2f2b464c92..9de453ee26 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -239,31 +239,37 @@ const useStopLossOrders = () => { initOrdersData() }, [account, chainId]) - const setCompletedPage = useCallback((page: number) => { - if (page < 1 || page > state.completed.maxPages) return - - setState((prevState) => ({ - ...prevState, - completed: { - ...prevState.completed, - page, - data: prevState.completed.allData.slice(10 * (page - 1), 10 * page), - }, - })) - }, []) - - const setPendingPage = useCallback((page: number) => { - if (page < 1 || page > state.pending.maxPages) return - - setState((prevState) => ({ - ...prevState, - pending: { - ...prevState.pending, - page, - data: prevState.pending.allData.slice(10 * (page - 1), 10 * page), - }, - })) - }, []) + const setCompletedPage = useCallback( + (page: number) => { + if (page < 1 || page > state.completed.maxPages) return + + setState((prevState) => ({ + ...prevState, + completed: { + ...prevState.completed, + page, + data: prevState.completed.allData.slice(10 * (page - 1), 10 * page), + }, + })) + }, + [state.completed] + ) + + const setPendingPage = useCallback( + (page: number) => { + if (page < 1 || page > state.pending.maxPages) return + + setState((prevState) => ({ + ...prevState, + pending: { + ...prevState.pending, + page, + data: prevState.pending.allData.slice(10 * (page - 1), 10 * page), + }, + })) + }, + [state.pending] + ) return useMemo( () => ({ From b763dd286ece6ecb0d3aad5d3d7f5789b69e6bcf Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Tue, 9 Aug 2022 23:26:13 +0900 Subject: [PATCH 51/60] feat: expert mode in stop-loss --- src/pages/stop-loss/[[...tokens]].tsx | 32 ++++++++++++++++++++++++--- src/state/limit-order/actions.ts | 3 +++ src/state/limit-order/hooks.ts | 16 +++++++++++++- src/state/limit-order/reducer.ts | 6 +++++ 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/pages/stop-loss/[[...tokens]].tsx b/src/pages/stop-loss/[[...tokens]].tsx index 2dce285e84..8a233db8db 100644 --- a/src/pages/stop-loss/[[...tokens]].tsx +++ b/src/pages/stop-loss/[[...tokens]].tsx @@ -1,9 +1,11 @@ -import { SwitchVerticalIcon } from '@heroicons/react/outline' +import { CheckIcon, SwitchVerticalIcon } from '@heroicons/react/outline' import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' import { Percent } from '@sushiswap/core-sdk' import limitOrderPairList from '@sushiswap/limit-order-pair-list/dist/limit-order.pairlist.json' +import CloseIcon from 'app/components/CloseIcon' import RecipientField from 'app/components/RecipientField' +import Switch from 'app/components/Switch' import Typography from 'app/components/Typography' import { ZERO_PERCENT } from 'app/constants' import { Feature } from 'app/enums' @@ -19,7 +21,12 @@ import NetworkGuard from 'app/guards/Network' import { SwapLayout, SwapLayoutCard } from 'app/layouts/SwapLayout' import { useActiveWeb3React } from 'app/services/web3' import { useAppDispatch } from 'app/state/hooks' -import { Field, setFromBentoBalance, setRecipient } from 'app/state/limit-order/actions' +import { + Field, + setFromBentoBalance, + setRecipient, + toggleEnableHigherStopRateThanMarketPrice, +} from 'app/state/limit-order/actions' import useLimitOrderDerivedCurrencies, { useLimitOrderActionHandlers, useLimitOrderDerivedLimitPrice, @@ -39,7 +46,8 @@ const StopLoss = () => { const dispatch = useAppDispatch() const { chainId } = useActiveWeb3React() const [isExpertMode] = useExpertModeManager() - const { typedField, typedValue, fromBentoBalance, recipient } = useLimitOrderState() + const { enableHigherStopRateThanMarketPrice, typedField, typedValue, fromBentoBalance, recipient } = + useLimitOrderState() const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() const trade = useLimitOrderDerivedTrade() const rate = useLimitOrderDerivedLimitPrice() @@ -122,6 +130,24 @@ const StopLoss = () => { onSelect={(inputCurrency) => onCurrencySelection(Field.INPUT, inputCurrency)} currencies={inputTokenList} /> + {isExpertMode && ( +
+
+ + {i18n._(t`Enable larger stop rate than market price`)} + +
+ dispatch(toggleEnableHigherStopRateThanMarketPrice())} + checkedIcon={} + uncheckedIcon={} + color="gradient" + /> +
+ )}
diff --git a/src/state/limit-order/actions.ts b/src/state/limit-order/actions.ts index 8e948878f9..c5d4b5dd66 100644 --- a/src/state/limit-order/actions.ts +++ b/src/state/limit-order/actions.ts @@ -22,6 +22,9 @@ export const setStopLossInvertRate = createAction('limit-order/setStopL export const setStopLossInvertState = createAction<{ invertStopRate: boolean; stopPrice: string }>( 'limit-order/setStopLossInvertState' ) +export const toggleEnableHigherStopRateThanMarketPrice = createAction( + 'limit-order/toggleEnableHigherStopRateThanMarketPrice' +) export const setOrderExpiration = createAction< | { diff --git a/src/state/limit-order/hooks.ts b/src/state/limit-order/hooks.ts index f77399deed..d7225a4bb6 100644 --- a/src/state/limit-order/hooks.ts +++ b/src/state/limit-order/hooks.ts @@ -282,7 +282,15 @@ type UseLimitOrderDerivedInputError = ({ isStopLossOrder?: boolean }) => string export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ trade, isStopLossOrder }) => { - const { recipient, orderExpiration, fromBentoBalance, limitPrice, stopPrice, typedValue } = useLimitOrderState() + const { + enableHigherStopRateThanMarketPrice, + recipient, + orderExpiration, + fromBentoBalance, + limitPrice, + stopPrice, + typedValue, + } = useLimitOrderState() const { account } = useActiveWeb3React() const { inputCurrency, outputCurrency } = useLimitOrderDerivedCurrencies() const rate = useLimitOrderDerivedLimitPrice() @@ -301,6 +309,10 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ parseFloat(limitPriceOrDefaultPrice?.toSignificant(6)) >= parseFloat(stopPriceOrDefaultPrice?.toSignificant(6)), [limitPriceOrDefaultPrice, stopPriceOrDefaultPrice] ) + const isStopPriceLargerThanMarketPrice = useMemo( + () => !enableHigherStopRateThanMarketPrice && trade && stopRate?.greaterThan(trade?.executionPrice), + [stopRate, trade, enableHigherStopRateThanMarketPrice] + ) return useMemo(() => { return !account @@ -317,6 +329,8 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ ? i18n._(t`Select a rate`) : isStopLossOrder && isLimitPriceBiggerThanStopPrice // for stop-loss orders only ? 'Minimum larger than stop rate' + : isStopLossOrder && isStopPriceLargerThanMarketPrice // for stop-loss orders only + ? 'Stop rate larger than market price' : !orderExpiration ? i18n._(t`Select an order expiration`) : !balance diff --git a/src/state/limit-order/reducer.ts b/src/state/limit-order/reducer.ts index 1a582f1456..07488a8708 100644 --- a/src/state/limit-order/reducer.ts +++ b/src/state/limit-order/reducer.ts @@ -21,6 +21,7 @@ import { setStopLossInvertState, setStopPrice, switchCurrencies, + toggleEnableHigherStopRateThanMarketPrice, typeInput, } from './actions' @@ -51,6 +52,7 @@ export interface LimitOrderState { readonly showReview: boolean readonly invertRate: boolean readonly invertStopRate: boolean + readonly enableHigherStopRateThanMarketPrice: boolean } const initialState: LimitOrderState = { @@ -72,6 +74,7 @@ const initialState: LimitOrderState = { showReview: false, invertRate: false, invertStopRate: false, + enableHigherStopRateThanMarketPrice: false, } export default createReducer(initialState, (builder) => @@ -177,6 +180,9 @@ export default createReducer(initialState, (builder) => state.invertStopRate = invertStopRate state.stopPrice = stopPrice }) + .addCase(toggleEnableHigherStopRateThanMarketPrice, (state) => { + state.enableHigherStopRateThanMarketPrice = !state.enableHigherStopRateThanMarketPrice + }) ) type SelectLimitOrder = (state: AppState) => LimitOrderState From 3dda0ca70f63724e1aa2937726c1a14752516beb Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Thu, 11 Aug 2022 22:10:32 +0900 Subject: [PATCH 52/60] fix: stop loss ui --- src/features/stop-loss/LimitPriceInputPanel.tsx | 6 +++++- src/features/stop-loss/StopLimitOrderButton.tsx | 4 ++-- src/features/stop-loss/StopPriceInputPanel.tsx | 6 +++++- src/pages/stop-loss/[[...tokens]].tsx | 8 ++++++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/features/stop-loss/LimitPriceInputPanel.tsx b/src/features/stop-loss/LimitPriceInputPanel.tsx index 3672d1f96e..9401ffc5c6 100644 --- a/src/features/stop-loss/LimitPriceInputPanel.tsx +++ b/src/features/stop-loss/LimitPriceInputPanel.tsx @@ -25,7 +25,11 @@ const LimitPriceInputPanel: FC = ({ trade, limitPrice }) =
{i18n._(t`Minimum Rate`)} - +
diff --git a/src/features/stop-loss/StopLimitOrderButton.tsx b/src/features/stop-loss/StopLimitOrderButton.tsx index e2ceebccab..ba6e43a40b 100644 --- a/src/features/stop-loss/StopLimitOrderButton.tsx +++ b/src/features/stop-loss/StopLimitOrderButton.tsx @@ -116,9 +116,9 @@ const StopLimitOrderButton: FC = ({ trade, parsedAmounts } {error ? error : tooNarrowMarginOfRates - ? 'Too narrow margin of rates' + ? 'Rate diff not enough for fee' : fromBentoBalance - ? i18n._(t`Review Stop Limit Order`) + ? i18n._(t`Create Stop Limit Order`) : i18n._(t`Confirm Deposit`)} ) diff --git a/src/features/stop-loss/StopPriceInputPanel.tsx b/src/features/stop-loss/StopPriceInputPanel.tsx index 977987501e..c6a953a241 100644 --- a/src/features/stop-loss/StopPriceInputPanel.tsx +++ b/src/features/stop-loss/StopPriceInputPanel.tsx @@ -25,7 +25,11 @@ const StopPriceInputPanel: FC = ({ trade, stopPrice }) => {
{i18n._(t`Stop Rate`)} - +
diff --git a/src/pages/stop-loss/[[...tokens]].tsx b/src/pages/stop-loss/[[...tokens]].tsx index 8a233db8db..791f166a05 100644 --- a/src/pages/stop-loss/[[...tokens]].tsx +++ b/src/pages/stop-loss/[[...tokens]].tsx @@ -179,6 +179,14 @@ const StopLoss = () => {
{isExpertMode && } + +
+ Date: Fri, 12 Aug 2022 00:55:54 +0900 Subject: [PATCH 53/60] fix: stop-loss zero-division issue --- src/features/stop-loss/useStopLossExecute.ts | 13 +++++++++---- src/features/stop-loss/useStopLossOrders.tsx | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/features/stop-loss/useStopLossExecute.ts b/src/features/stop-loss/useStopLossExecute.ts index 408db80292..6dd98a5b2f 100644 --- a/src/features/stop-loss/useStopLossExecute.ts +++ b/src/features/stop-loss/useStopLossExecute.ts @@ -64,6 +64,7 @@ export type UseLimitOrderExecute = () => { cancelRequest: (id: string) => void } +// estimate equivalent ETH amount from any input token amount export function useEstimateEquivalentEthAmount(token: CurrencyAmount | undefined): string { const { chainId } = useActiveWeb3React() const router = useRouterContract() @@ -80,6 +81,7 @@ export function useEstimateEquivalentEthAmount(token: CurrencyAmount | return } + // estimate output amount with uniV2 router const amountsOut = await router.getAmountsOut(token.quotient.toString(), [ token.wrapped.currency.address, WNATIVE_ADDRESS[chainId], @@ -123,13 +125,15 @@ export function useDiffOfStopAndMinimumRate({ [diffValueOfEth] ) - const convertIntWithMultiply = (sValue: string) => `${Math.floor(parseFloat(sValue) * 1000000)}` + const convertIntWithMultiply = (s: string) => Math.floor(parseFloat(s) * 1000000) // 1000,000 aims to mitigate loss while in math operation + const getBigNumberFromTinyFloat = (s: string) => BigNumber.from(`${convertIntWithMultiply(s)}`) // calculate amount for autonomy fee: (stopRate - minimumRate) * MIN_FEE_ETH_AMOUNT / equivalentEthAmountOf[stopRate - minimumRate] + // this will be cumulated to minimum output amount const externalAmountForFee = - !!chainId && !!diffOfStopAndMinRate && parseFloat(diffValueOfEth) > 0 + !!chainId && !!diffOfStopAndMinRate && convertIntWithMultiply(diffValueOfEth) > 0 ? BigNumber.from(diffOfStopAndMinRate?.quotient.toString()) - .mul(BigNumber.from(convertIntWithMultiply(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId]))) - .div(BigNumber.from(convertIntWithMultiply(diffValueOfEth))) + .mul(getBigNumberFromTinyFloat(STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM[chainId])) + .div(getBigNumberFromTinyFloat(diffValueOfEth)) : 0 return { @@ -140,6 +144,7 @@ export function useDiffOfStopAndMinimumRate({ } } +// register stop-limit order into autonomy registry const useStopLossExecute: UseLimitOrderExecute = () => { const { account, chainId, library } = useActiveWeb3React() diff --git a/src/features/stop-loss/useStopLossOrders.tsx b/src/features/stop-loss/useStopLossOrders.tsx index 9de453ee26..228f60646f 100644 --- a/src/features/stop-loss/useStopLossOrders.tsx +++ b/src/features/stop-loss/useStopLossOrders.tsx @@ -46,6 +46,7 @@ interface StopLossOrdersData { completed: OrdersData } +// fetch stop-limit orders history from autonomy moralis const useStopLossOrders = () => { const { account, chainId } = useActiveWeb3React() const limitOrderWrapperContract = useAutonomyLimitOrderWrapperContract() From eb9649355d41d88d011944bc7d33e14b6aabca0d Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 12 Aug 2022 21:52:09 +0900 Subject: [PATCH 54/60] feat: add more validation in stop-loss ui --- src/state/limit-order/hooks.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/state/limit-order/hooks.ts b/src/state/limit-order/hooks.ts index d7225a4bb6..6fb1810098 100644 --- a/src/state/limit-order/hooks.ts +++ b/src/state/limit-order/hooks.ts @@ -327,6 +327,8 @@ export const useLimitOrderDerivedInputError: UseLimitOrderDerivedInputError = ({ ? i18n._(t`Select a rate`) : stopPrice !== LimitPrice.CURRENT && parsedRate?.equalTo(ZERO) ? i18n._(t`Select a rate`) + : isStopLossOrder && (!rate || !stopRate) + ? i18n._(t`Fill all inputs to continue`) // for stop-loss orders only : isStopLossOrder && isLimitPriceBiggerThanStopPrice // for stop-loss orders only ? 'Minimum larger than stop rate' : isStopLossOrder && isStopPriceLargerThanMarketPrice // for stop-loss orders only From a468b7e2fd7038ad0819ea945cc409af03225a1f Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Sat, 13 Aug 2022 02:16:40 +0900 Subject: [PATCH 55/60] fix: stop-loss overflow --- src/features/stop-loss/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/stop-loss/utils.ts b/src/features/stop-loss/utils.ts index f0005a0d93..0f351933e7 100644 --- a/src/features/stop-loss/utils.ts +++ b/src/features/stop-loss/utils.ts @@ -71,7 +71,7 @@ export function prepareStopPriceOracleData( [outAggregator.address, inAggregator.address, BigNumber.from(10).pow(decimals)] ) - const inverseStopPrice = parseFloat(stopPrice.invert().toSignificant(18)) * 1e18 + const inverseStopPrice = Math.floor(parseFloat(stopPrice.invert().toSignificant(18)) * 1e18) return { stopPrice: inverseStopPrice.toString(), oracleData, From 74eeb946e9bfb4364c162ee9e8acb6f53606d306 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 17 Aug 2022 00:26:10 +0900 Subject: [PATCH 56/60] fix: dependency of moralis --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index fef26d8822..8849c9dd36 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,6 @@ "lottie-react": "2.1.0", "madge": "^5.0.1", "millify": "^4.0.0", - "moralis": "^2.0.1", "ms.macro": "^2.0.0", "next": "^12.1.5", "next-pwa": "5.4.7", @@ -254,5 +253,8 @@ "budget": 3584000, "budgetPercentIncreaseRed": 40, "showDetails": true + }, + "dependencies": { + "moralis": "^2.0.1" } } From a77beb316db209368db47a6f390898f7d8d4687c Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 17 Aug 2022 00:44:10 +0900 Subject: [PATCH 57/60] fix: moralis version --- package.json | 4 +- yarn.lock | 575 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 452 insertions(+), 127 deletions(-) diff --git a/package.json b/package.json index 8849c9dd36..76fab0a609 100644 --- a/package.json +++ b/package.json @@ -179,6 +179,7 @@ "lottie-react": "2.1.0", "madge": "^5.0.1", "millify": "^4.0.0", + "moralis": "^1.7.0", "ms.macro": "^2.0.0", "next": "^12.1.5", "next-pwa": "5.4.7", @@ -253,8 +254,5 @@ "budget": 3584000, "budgetPercentIncreaseRed": 40, "showDetails": true - }, - "dependencies": { - "moralis": "^2.0.1" } } diff --git a/yarn.lock b/yarn.lock index 8d5e89cfbc..132b1f2c75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -959,6 +959,14 @@ "@babel/plugin-transform-react-jsx-development" "^7.18.6" "@babel/plugin-transform-react-pure-annotations" "^7.18.6" +"@babel/runtime-corejs3@7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz#ea533d96eda6fdc76b1812248e9fbd0c11d4a1a7" + integrity sha512-3fKhuICS1lMz0plI5ktOE/yEtBRMVxplzRkdn6mJQ197XiY0JnrzYV0+Mxozq3JZ8SBV9Ecurmw1XsGbwOf+Sg== + dependencies: + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" + "@babel/runtime-corejs3@^7.10.2": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.6.tgz#6f02c5536911f4b445946a2179554b95c8838635" @@ -967,6 +975,13 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" +"@babel/runtime@7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" + integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/runtime@7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" @@ -1379,7 +1394,22 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" -"@ethersproject/abi@5.6.4", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.6.3": +"@ethersproject/abi@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.0.tgz#ea07cbc1eec2374d32485679c12408005895e9f3" + integrity sha512-AhVByTwdXCc2YQ20v300w6KVHle9g2OFc28ZAFCPnJyEpkv1xKXjZcSTgWOlv1i+0dqlgF8RCF2Rn2KC1t+1Vg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/abi@5.6.4", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.6.0", "@ethersproject/abi@^5.6.3": version "5.6.4" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.4.tgz#f6e01b6ed391a505932698ecc0d9e7a99ee60362" integrity sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg== @@ -1394,7 +1424,20 @@ "@ethersproject/properties" "^5.6.0" "@ethersproject/strings" "^5.6.1" -"@ethersproject/abstract-provider@5.6.1", "@ethersproject/abstract-provider@^5.4.0", "@ethersproject/abstract-provider@^5.6.1": +"@ethersproject/abstract-provider@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz#0c4ac7054650dbd9c476cf5907f588bbb6ef3061" + integrity sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + +"@ethersproject/abstract-provider@5.6.1", "@ethersproject/abstract-provider@^5.4.0", "@ethersproject/abstract-provider@^5.6.0", "@ethersproject/abstract-provider@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz#02ddce150785caf0c77fe036a0ebfcee61878c59" integrity sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ== @@ -1407,7 +1450,18 @@ "@ethersproject/transactions" "^5.6.2" "@ethersproject/web" "^5.6.1" -"@ethersproject/abstract-signer@5.6.2", "@ethersproject/abstract-signer@^5", "@ethersproject/abstract-signer@^5.4.0", "@ethersproject/abstract-signer@^5.6.2": +"@ethersproject/abstract-signer@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz#9cd7ae9211c2b123a3b29bf47aab17d4d016e3e7" + integrity sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/abstract-signer@5.6.2", "@ethersproject/abstract-signer@^5", "@ethersproject/abstract-signer@^5.4.0", "@ethersproject/abstract-signer@^5.6.0", "@ethersproject/abstract-signer@^5.6.2": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz#491f07fc2cbd5da258f46ec539664713950b0b33" integrity sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ== @@ -1418,6 +1472,17 @@ "@ethersproject/logger" "^5.6.0" "@ethersproject/properties" "^5.6.0" +"@ethersproject/address@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" + integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/address@5.6.1", "@ethersproject/address@^5", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.6.0", "@ethersproject/address@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.1.tgz#ab57818d9aefee919c5721d28cd31fd95eff413d" @@ -1429,14 +1494,29 @@ "@ethersproject/logger" "^5.6.0" "@ethersproject/rlp" "^5.6.1" -"@ethersproject/base64@5.6.1", "@ethersproject/base64@^5.6.1": +"@ethersproject/base64@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.0.tgz#a12c4da2a6fb86d88563216b0282308fc15907c9" + integrity sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + +"@ethersproject/base64@5.6.1", "@ethersproject/base64@^5.6.0", "@ethersproject/base64@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.1.tgz#2c40d8a0310c9d1606c2c37ae3092634b41d87cb" integrity sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw== dependencies: "@ethersproject/bytes" "^5.6.1" -"@ethersproject/basex@5.6.1", "@ethersproject/basex@^5.6.1": +"@ethersproject/basex@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.0.tgz#9ea7209bf0a1c3ddc2a90f180c3a7f0d7d2e8a69" + integrity sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/basex@5.6.1", "@ethersproject/basex@^5.6.0", "@ethersproject/basex@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.1.tgz#badbb2f1d4a6f52ce41c9064f01eab19cc4c5305" integrity sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA== @@ -1444,7 +1524,16 @@ "@ethersproject/bytes" "^5.6.1" "@ethersproject/properties" "^5.6.0" -"@ethersproject/bignumber@5.6.2", "@ethersproject/bignumber@^5.4.0", "@ethersproject/bignumber@^5.6.2": +"@ethersproject/bignumber@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.0.tgz#116c81b075c57fa765a8f3822648cf718a8a0e26" + integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + bn.js "^4.11.9" + +"@ethersproject/bignumber@5.6.2", "@ethersproject/bignumber@^5.4.0", "@ethersproject/bignumber@^5.6.0", "@ethersproject/bignumber@^5.6.2": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.2.tgz#72a0717d6163fab44c47bcc82e0c550ac0315d66" integrity sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw== @@ -1453,20 +1542,50 @@ "@ethersproject/logger" "^5.6.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.6.1": +"@ethersproject/bytes@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.0.tgz#81652f2a0e04533575befadce555213c11d8aa20" + integrity sha512-3hJPlYemb9V4VLfJF5BfN0+55vltPZSHU3QKUyP9M3Y2TcajbiRrz65UG+xVHOzBereB1b9mn7r12o177xgN7w== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.6.0", "@ethersproject/bytes@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== dependencies: "@ethersproject/logger" "^5.6.0" -"@ethersproject/constants@5.6.1", "@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.6.1": +"@ethersproject/constants@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.0.tgz#55e3eb0918584d3acc0688e9958b0cedef297088" + integrity sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + +"@ethersproject/constants@5.6.1", "@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.6.0", "@ethersproject/constants@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.1.tgz#e2e974cac160dd101cf79fdf879d7d18e8cb1370" integrity sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg== dependencies: "@ethersproject/bignumber" "^5.6.2" +"@ethersproject/contracts@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.0.tgz#60f2cfc7addd99a865c6c8cfbbcec76297386067" + integrity sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw== + dependencies: + "@ethersproject/abi" "^5.6.0" + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/contracts@5.6.2", "@ethersproject/contracts@^5", "@ethersproject/contracts@^5.4.0": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.2.tgz#20b52e69ebc1b74274ff8e3d4e508de971c287bc" @@ -1492,7 +1611,21 @@ ethers "^5.6.8" scrypt-js "3.0.1" -"@ethersproject/hash@5.6.1", "@ethersproject/hash@^5.4.0", "@ethersproject/hash@^5.6.1": +"@ethersproject/hash@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.0.tgz#d24446a5263e02492f9808baa99b6e2b4c3429a2" + integrity sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/hash@5.6.1", "@ethersproject/hash@^5.4.0", "@ethersproject/hash@^5.6.0", "@ethersproject/hash@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.1.tgz#224572ea4de257f05b4abf8ae58b03a67e99b0f4" integrity sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA== @@ -1506,7 +1639,25 @@ "@ethersproject/properties" "^5.6.0" "@ethersproject/strings" "^5.6.1" -"@ethersproject/hdnode@5.6.2", "@ethersproject/hdnode@^5.6.2": +"@ethersproject/hdnode@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.0.tgz#9dcbe8d629bbbcf144f2cae476337fe92d320998" + integrity sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + +"@ethersproject/hdnode@5.6.2", "@ethersproject/hdnode@^5.6.0", "@ethersproject/hdnode@^5.6.2": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.2.tgz#26f3c83a3e8f1b7985c15d1db50dc2903418b2d2" integrity sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q== @@ -1524,7 +1675,26 @@ "@ethersproject/transactions" "^5.6.2" "@ethersproject/wordlists" "^5.6.1" -"@ethersproject/json-wallets@5.6.1", "@ethersproject/json-wallets@^5.6.1": +"@ethersproject/json-wallets@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz#4c2fc27f17e36c583e7a252fb938bc46f98891e5" + integrity sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ== + dependencies: + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/json-wallets@5.6.1", "@ethersproject/json-wallets@^5.6.0", "@ethersproject/json-wallets@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.1.tgz#3f06ba555c9c0d7da46756a12ac53483fe18dd91" integrity sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ== @@ -1543,7 +1713,15 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.6.1", "@ethersproject/keccak256@^5.0.0-beta.130", "@ethersproject/keccak256@^5.4.0", "@ethersproject/keccak256@^5.6.1": +"@ethersproject/keccak256@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.0.tgz#fea4bb47dbf8f131c2e1774a1cecbfeb9d606459" + integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== + dependencies: + "@ethersproject/bytes" "^5.6.0" + js-sha3 "0.8.0" + +"@ethersproject/keccak256@5.6.1", "@ethersproject/keccak256@^5.0.0-beta.130", "@ethersproject/keccak256@^5.4.0", "@ethersproject/keccak256@^5.6.0", "@ethersproject/keccak256@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.1.tgz#b867167c9b50ba1b1a92bccdd4f2d6bd168a91cc" integrity sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA== @@ -1556,14 +1734,29 @@ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== -"@ethersproject/networks@5.6.4", "@ethersproject/networks@^5.6.3": +"@ethersproject/networks@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.0.tgz#486d03fff29b4b6b5414d47a232ded09fe10de5e" + integrity sha512-DaVzgyThzHgSDLuURhvkp4oviGoGe9iTZW4jMEORHDRCgSZ9K9THGFKqL+qGXqPAYLEgZTf5z2w56mRrPR1MjQ== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/networks@5.6.4", "@ethersproject/networks@^5.6.0", "@ethersproject/networks@^5.6.3": version "5.6.4" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.4.tgz#51296d8fec59e9627554f5a8a9c7791248c8dc07" integrity sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ== dependencies: "@ethersproject/logger" "^5.6.0" -"@ethersproject/pbkdf2@5.6.1", "@ethersproject/pbkdf2@^5.6.1": +"@ethersproject/pbkdf2@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz#04fcc2d7c6bff88393f5b4237d906a192426685a" + integrity sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + +"@ethersproject/pbkdf2@5.6.1", "@ethersproject/pbkdf2@^5.6.0", "@ethersproject/pbkdf2@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.1.tgz#f462fe320b22c0d6b1d72a9920a3963b09eb82d1" integrity sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ== @@ -1578,6 +1771,31 @@ dependencies: "@ethersproject/logger" "^5.6.0" +"@ethersproject/providers@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.0.tgz#08ec8e2666771e3a347e66c8f664a2af97366534" + integrity sha512-6+5PKXTWAttJWFWF8+xCDTCa2/dtq9BNrdKQHGl0IyIOwj99vM6OeThmIRcsIAzIOb8m0XS6w+1KFZwrf3j9nw== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/basex" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/web" "^5.6.0" + bech32 "1.1.4" + ws "7.4.6" + "@ethersproject/providers@5.6.8", "@ethersproject/providers@^5", "@ethersproject/providers@^5.4.0": version "5.6.8" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.8.tgz#22e6c57be215ba5545d3a46cf759d265bb4e879d" @@ -1604,7 +1822,15 @@ bech32 "1.1.4" ws "7.4.6" -"@ethersproject/random@5.6.1", "@ethersproject/random@^5.6.1": +"@ethersproject/random@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.0.tgz#1505d1ab6a250e0ee92f436850fa3314b2cb5ae6" + integrity sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/random@5.6.1", "@ethersproject/random@^5.6.0", "@ethersproject/random@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.1.tgz#66915943981bcd3e11bbd43733f5c3ba5a790255" integrity sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA== @@ -1612,7 +1838,15 @@ "@ethersproject/bytes" "^5.6.1" "@ethersproject/logger" "^5.6.0" -"@ethersproject/rlp@5.6.1", "@ethersproject/rlp@^5.6.1": +"@ethersproject/rlp@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.0.tgz#55a7be01c6f5e64d6e6e7edb6061aa120962a717" + integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/rlp@5.6.1", "@ethersproject/rlp@^5.6.0", "@ethersproject/rlp@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.1.tgz#df8311e6f9f24dcb03d59a2bac457a28a4fe2bd8" integrity sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ== @@ -1620,7 +1854,16 @@ "@ethersproject/bytes" "^5.6.1" "@ethersproject/logger" "^5.6.0" -"@ethersproject/sha2@5.6.1", "@ethersproject/sha2@^5.6.1": +"@ethersproject/sha2@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.0.tgz#364c4c11cc753bda36f31f001628706ebadb64d9" + integrity sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + hash.js "1.1.7" + +"@ethersproject/sha2@5.6.1", "@ethersproject/sha2@^5.6.0", "@ethersproject/sha2@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.1.tgz#211f14d3f5da5301c8972a8827770b6fd3e51656" integrity sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g== @@ -1629,7 +1872,19 @@ "@ethersproject/logger" "^5.6.0" hash.js "1.1.7" -"@ethersproject/signing-key@5.6.2", "@ethersproject/signing-key@^5.4.0", "@ethersproject/signing-key@^5.6.2": +"@ethersproject/signing-key@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.0.tgz#4f02e3fb09e22b71e2e1d6dc4bcb5dafa69ce042" + integrity sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.6.2", "@ethersproject/signing-key@^5.4.0", "@ethersproject/signing-key@^5.6.0", "@ethersproject/signing-key@^5.6.2": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.2.tgz#8a51b111e4d62e5a62aee1da1e088d12de0614a3" integrity sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ== @@ -1641,6 +1896,18 @@ elliptic "6.5.4" hash.js "1.1.7" +"@ethersproject/solidity@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.0.tgz#64657362a596bf7f5630bdc921c07dd78df06dc3" + integrity sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + "@ethersproject/solidity@5.6.1", "@ethersproject/solidity@^5.4.0": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.1.tgz#5845e71182c66d32e6ec5eefd041fca091a473e2" @@ -1653,7 +1920,16 @@ "@ethersproject/sha2" "^5.6.1" "@ethersproject/strings" "^5.6.1" -"@ethersproject/strings@5.6.1", "@ethersproject/strings@^5.4.0", "@ethersproject/strings@^5.6.1": +"@ethersproject/strings@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.0.tgz#9891b26709153d996bf1303d39a7f4bc047878fd" + integrity sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/strings@5.6.1", "@ethersproject/strings@^5.4.0", "@ethersproject/strings@^5.6.0", "@ethersproject/strings@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.1.tgz#dbc1b7f901db822b5cafd4ebf01ca93c373f8952" integrity sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw== @@ -1662,6 +1938,21 @@ "@ethersproject/constants" "^5.6.1" "@ethersproject/logger" "^5.6.0" +"@ethersproject/transactions@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.0.tgz#4b594d73a868ef6e1529a2f8f94a785e6791ae4e" + integrity sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/transactions@5.6.2", "@ethersproject/transactions@^5.4.0", "@ethersproject/transactions@^5.6.0", "@ethersproject/transactions@^5.6.2": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.2.tgz#793a774c01ced9fe7073985bb95a4b4e57a6370b" @@ -1677,6 +1968,15 @@ "@ethersproject/rlp" "^5.6.1" "@ethersproject/signing-key" "^5.6.2" +"@ethersproject/units@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.0.tgz#e5cbb1906988f5740254a21b9ded6bd51e826d9c" + integrity sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/units@5.6.1", "@ethersproject/units@^5.4.0": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.1.tgz#ecc590d16d37c8f9ef4e89e2005bda7ddc6a4e6f" @@ -1686,6 +1986,27 @@ "@ethersproject/constants" "^5.6.1" "@ethersproject/logger" "^5.6.0" +"@ethersproject/wallet@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.0.tgz#33d11a806d783864208f348709a5a3badac8e22a" + integrity sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.0" + "@ethersproject/abstract-signer" "^5.6.0" + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/hdnode" "^5.6.0" + "@ethersproject/json-wallets" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.0" + "@ethersproject/signing-key" "^5.6.0" + "@ethersproject/transactions" "^5.6.0" + "@ethersproject/wordlists" "^5.6.0" + "@ethersproject/wallet@5.6.2": version "5.6.2" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.2.tgz#cd61429d1e934681e413f4bc847a5f2f87e3a03c" @@ -1707,7 +2028,18 @@ "@ethersproject/transactions" "^5.6.2" "@ethersproject/wordlists" "^5.6.1" -"@ethersproject/web@5.6.1", "@ethersproject/web@^5.6.1": +"@ethersproject/web@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.0.tgz#4bf8b3cbc17055027e1a5dd3c357e37474eaaeb8" + integrity sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg== + dependencies: + "@ethersproject/base64" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/web@5.6.1", "@ethersproject/web@^5.6.0", "@ethersproject/web@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.1.tgz#6e2bd3ebadd033e6fe57d072db2b69ad2c9bdf5d" integrity sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA== @@ -1718,7 +2050,18 @@ "@ethersproject/properties" "^5.6.0" "@ethersproject/strings" "^5.6.1" -"@ethersproject/wordlists@5.6.1", "@ethersproject/wordlists@^5.6.1": +"@ethersproject/wordlists@5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.0.tgz#79e62c5276e091d8575f6930ba01a29218ded032" + integrity sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/wordlists@5.6.1", "@ethersproject/wordlists@^5.6.0", "@ethersproject/wordlists@^5.6.1": version "5.6.1" resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.1.tgz#1e78e2740a8a21e9e99947e47979d72e130aeda1" integrity sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw== @@ -2304,71 +2647,16 @@ messageformat-parser "^4.1.3" ramda "^0.27.1" +"@metamask/detect-provider@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@metamask/detect-provider/-/detect-provider-1.2.0.tgz#3667a7531f2a682e3c3a43eaf3a1958bdb42a696" + integrity sha512-ocA76vt+8D0thgXZ7LxFPyqw3H7988qblgzddTDA6B8a/yU0uKV42QR/DhA+Jh11rJjxW0jKvwb5htA6krNZDQ== + "@metamask/safe-event-emitter@2.0.0", "@metamask/safe-event-emitter@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q== -"@moralisweb3/api-utils@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@moralisweb3/api-utils/-/api-utils-2.0.1.tgz#b0719eb2ba6997a0614179200e791a520ca08b9e" - integrity sha512-bhqSyn0asNj+OO588jhP5whpZpSJvoLK5vTIoHvumnoY2ODQa8vroOLyVIDvMPCmMcHabfU/waSNHr2rQ6YbaA== - dependencies: - "@moralisweb3/core" "^2.0.1" - -"@moralisweb3/auth@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@moralisweb3/auth/-/auth-2.0.1.tgz#5d0b79745c01c1d091c0c575107cae7d121c73d4" - integrity sha512-Sq0e5wp1bnwJ97BToDe9DysWYc2Me17uBNwhfohZ82S14ir/R+RfVTJ0JRLvuhD6N0zL5Nh62AONQMWuNJiVYQ== - dependencies: - "@moralisweb3/api-utils" "^2.0.1" - "@moralisweb3/core" "^2.0.1" - "@moralisweb3/evm-utils" "^2.0.1" - -"@moralisweb3/core@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@moralisweb3/core/-/core-2.0.1.tgz#a9f047d3b3aacc165cdfcd69e0c97ec500053c82" - integrity sha512-/bYdAytUbNbHnWVm6NAQGGKFfm8UoIBHlqvfMT1SBVnyLI8Y2Xzv7C4N6csBtWlIxBQ7W0ho8nEu6xlfzptXpw== - dependencies: - "@xstate/fsm" "^2.0.0" - axios "^0.27.2" - eventemitter3 "^4.0.7" - typed-emitter "^2.1.0" - -"@moralisweb3/evm-api@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@moralisweb3/evm-api/-/evm-api-2.0.1.tgz#63a00893c787384e85558b68a240af9e7da6870c" - integrity sha512-waCwZ9tET0uJdRnUG2cWBauHmi85wnDALH8qdh23xwo6snSjxMYsV+LvtzQLe0jhShwyTAHvHgAuj5snpsKd6A== - dependencies: - "@moralisweb3/api-utils" "^2.0.1" - "@moralisweb3/core" "^2.0.1" - "@moralisweb3/evm-utils" "^2.0.1" - -"@moralisweb3/evm-utils@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@moralisweb3/evm-utils/-/evm-utils-2.0.1.tgz#cb229c47a7ae8d6e46bb72f58d8f5266ed72ce4b" - integrity sha512-KxnUxZiwOgRC5UnJTB4jUV945a78JZ0Y0BilZ5sQ2m9uyOHxp3VlOs1E63EHCeXM5Su1/BOlZmjr7i2hKzDEwQ== - dependencies: - "@ethersproject/address" "^5.6.0" - "@ethersproject/transactions" "^5.6.0" - "@moralisweb3/core" "^2.0.1" - -"@moralisweb3/sol-api@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@moralisweb3/sol-api/-/sol-api-2.0.1.tgz#32bca31fba4ce87d19d3c4dc91caace59f997144" - integrity sha512-Jcv64FgdIDhFBQUyecE2xeAjEJbhG8xdSi30+9u34CxJZG4U1GtqQUKJCXjXeaBGpxyE5sReFeBI3ZA2pNK5og== - dependencies: - "@moralisweb3/api-utils" "^2.0.1" - "@moralisweb3/core" "^2.0.1" - "@moralisweb3/sol-utils" "^2.0.1" - -"@moralisweb3/sol-utils@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@moralisweb3/sol-utils/-/sol-utils-2.0.1.tgz#853fb050610e0192a6509481186a591c74dba3a8" - integrity sha512-vcvq0/O/4qk88rDgZNLFdRIHVw+mgJJN5l7K4eqHoY/p21Ruwp7lLbBEvO2htuTTXB6w0glPUTvd998r6scjLA== - dependencies: - "@moralisweb3/core" "^2.0.1" - "@multiformats/base-x@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" @@ -3899,11 +4187,6 @@ dependencies: lodash "^4" -"@xstate/fsm@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@xstate/fsm/-/fsm-2.0.0.tgz#221db16b606df3f4675f5be6058b633ec4b8b44a" - integrity sha512-p/zcvBMoU2ap5byMefLkR+AM+Eh99CU/SDEQeccgKlmFNOMDwphaRGqdk+emvel/SaGZ7Rf9sDvzAplLzLdEVQ== - "@zeit/schemas@2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3" @@ -4343,6 +4626,13 @@ axe-core@^4.4.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.3.tgz#11c74d23d5013c0fa5d183796729bc3482bd2f6f" integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w== +axios@0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + axios@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" @@ -4358,14 +4648,6 @@ axios@^0.21.0, axios@^0.21.1: dependencies: follow-redirects "^1.14.0" -axios@^0.27.2: - version "0.27.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" - integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== - dependencies: - follow-redirects "^1.14.9" - form-data "^4.0.0" - axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -5459,6 +5741,11 @@ cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypto-js@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" @@ -6741,6 +7028,42 @@ ethereumjs-vm@^2.3.4: rustbn.js "~0.2.0" safe-buffer "^5.1.1" +ethers@5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.0.tgz#924eb965dc03963fad0a09ce687efdf49aca3b45" + integrity sha512-00FP71jt6bW3ndO5DhgH9mLIZhoCGnAKFLu8qig5KmV03ubEChKf2ilB3g6fX512tTYo+tSMDJ5WpCJWdBHkBQ== + dependencies: + "@ethersproject/abi" "5.6.0" + "@ethersproject/abstract-provider" "5.6.0" + "@ethersproject/abstract-signer" "5.6.0" + "@ethersproject/address" "5.6.0" + "@ethersproject/base64" "5.6.0" + "@ethersproject/basex" "5.6.0" + "@ethersproject/bignumber" "5.6.0" + "@ethersproject/bytes" "5.6.0" + "@ethersproject/constants" "5.6.0" + "@ethersproject/contracts" "5.6.0" + "@ethersproject/hash" "5.6.0" + "@ethersproject/hdnode" "5.6.0" + "@ethersproject/json-wallets" "5.6.0" + "@ethersproject/keccak256" "5.6.0" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.0" + "@ethersproject/pbkdf2" "5.6.0" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.0" + "@ethersproject/random" "5.6.0" + "@ethersproject/rlp" "5.6.0" + "@ethersproject/sha2" "5.6.0" + "@ethersproject/signing-key" "5.6.0" + "@ethersproject/solidity" "5.6.0" + "@ethersproject/strings" "5.6.0" + "@ethersproject/transactions" "5.6.0" + "@ethersproject/units" "5.6.0" + "@ethersproject/wallet" "5.6.0" + "@ethersproject/web" "5.6.0" + "@ethersproject/wordlists" "5.6.0" + ethers@^5.1.4, ethers@^5.4.7, ethers@^5.6.8: version "5.6.9" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.9.tgz#4e12f8dfcb67b88ae7a78a9519b384c23c576a4d" @@ -6806,7 +7129,7 @@ event-stream@=3.3.4: stream-combiner "~0.0.4" through "~2.3.1" -eventemitter3@4.0.7, eventemitter3@^4.0.7: +eventemitter3@4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -7124,7 +7447,7 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" -follow-redirects@^1.14.0, follow-redirects@^1.14.9: +follow-redirects@^1.14.0, follow-redirects@^1.14.8: version "1.15.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== @@ -7150,15 +7473,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -9686,17 +10000,22 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" -moralis@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/moralis/-/moralis-2.0.1.tgz#d31d952807e712428476f55d9ac4f36b45187420" - integrity sha512-mjEB7le5K9OyR11ypyyEVHsaHIqAXXOmgKSp/l5V10dQY2Eiq9/gQv/Jj4i4S1z4Xs7kAJD6NibuAC/AWLN8bQ== - dependencies: - "@moralisweb3/api-utils" "^2.0.1" - "@moralisweb3/auth" "^2.0.1" - "@moralisweb3/core" "^2.0.1" - "@moralisweb3/evm-api" "^2.0.1" - "@moralisweb3/evm-utils" "^2.0.1" - "@moralisweb3/sol-api" "^2.0.1" +moralis@^1.7.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/moralis/-/moralis-1.11.0.tgz#aa736cf5acbd3f65ac83d44f2e4e12e0e88566f8" + integrity sha512-oqoKqP47RuHq+SnztN48+YgWsKLt1YBy7IfeSBOixUW0Tzn9RQDjNKpkSBcKFttNZQ/KzCEes6TCqA9IxSoTPQ== + dependencies: + "@babel/runtime" "7.16.7" + "@babel/runtime-corejs3" "7.16.8" + "@metamask/detect-provider" "^1.2.0" + axios "0.26.1" + ethers "5.6.0" + react-native-crypto-js "1.0.0" + uuid "^8.3.2" + ws "^8.3.0" + xmlhttprequest "1.8.0" + optionalDependencies: + crypto-js "4.1.1" mrmime@^1.0.0: version "1.0.1" @@ -11212,6 +11531,11 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-native-crypto-js@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/react-native-crypto-js/-/react-native-crypto-js-1.0.0.tgz#e677e022e147f41b35614416c92d655f87e2450a" + integrity sha512-FNbLuG/HAdapQoybeZSoes1PWdOj0w242gb+e1R0hicf3Gyj/Mf8M9NaED2AnXVOX01b2FXomwUiw1xP1K+8sA== + react-popper@^2.2.5: version "2.3.0" resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba" @@ -11753,7 +12077,7 @@ rxjs@^6.6.0, rxjs@^6.6.3: dependencies: tslib "^1.9.0" -rxjs@^7.1.0, rxjs@^7.5.1, rxjs@^7.5.2: +rxjs@^7.1.0, rxjs@^7.5.1: version "7.5.6" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc" integrity sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw== @@ -12880,13 +13204,6 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -typed-emitter@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-2.1.0.tgz#ca78e3d8ef1476f228f548d62e04e3d4d3fd77fb" - integrity sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA== - optionalDependencies: - rxjs "^7.5.2" - typedarray-to-buffer@3.1.5, typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -13665,6 +13982,11 @@ ws@^7.3.1, ws@^7.4.0, ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.8.tgz#ac2729881ab9e7cbaf8787fe3469a48c5c7f636a" integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw== +ws@^8.3.0: + version "8.8.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" + integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== + xhr@^2.0.1, xhr@^2.2.0: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" @@ -13703,6 +14025,11 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== + xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From f28b4cad74bc092f3f3e55190665758eb16105a6 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 9 Sep 2022 02:36:41 +0900 Subject: [PATCH 58/60] fix: npm dependency --- package.json | 4 ++-- yarn.lock | 26 +++++--------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 68b45132b2..e2cae524b5 100644 --- a/package.json +++ b/package.json @@ -98,9 +98,9 @@ "@sushiswap/bentobox-sdk": "1.0.0-canary.114", "@sushiswap/chainlink-whitelist": "0.2.8", "@sushiswap/core": "^2.0.0-canary.1", - "@sushiswap/core-sdk": "1.0.0-canary.132", + "@sushiswap/core-sdk": "1.0.0-canary.133", "@sushiswap/default-token-list": "^31.1.0", - "@sushiswap/kashi-sdk": "1.0.0-canary.104", + "@sushiswap/kashi-sdk": "1.0.0-canary.105", "@sushiswap/limit-order-pair-list": "0.2.17", "@sushiswap/limit-order-sdk": "1.0.0-canary.114", "@sushiswap/miso": "1.0.0-canary.47", diff --git a/yarn.lock b/yarn.lock index 6addea6104..95b28d512b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3037,22 +3037,6 @@ resolved "https://registry.yarnpkg.com/@sushiswap/chainlink-whitelist/-/chainlink-whitelist-0.2.8.tgz#832dc80963b890a2eb02aaaf11ea8b57b2b7dde0" integrity sha512-YhhGfF/smND4jUdVWuTr3e9Np08zLyxrOfbQ6GkAhmrld4lWBs2sk4TV6oWSBWPbuUb3A2mw203uCnbMHpSoXw== -"@sushiswap/core-sdk@1.0.0-canary.132": - version "1.0.0-canary.132" - resolved "https://registry.yarnpkg.com/@sushiswap/core-sdk/-/core-sdk-1.0.0-canary.132.tgz#8456bbdc8cfff4f48b136bced944e7468923d4ba" - integrity sha512-qgZ/GMW37xaApFlDGqU/kMl8t4q55x8jo7eRIeK0BQheYmaoVZ+zNZxVS41RIG0BG09jxh8URxqWDrJDMFALHw== - dependencies: - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/providers" "^5.4.0" - "@ethersproject/solidity" "^5.4.0" - big.js "^6.1.1" - decimal.js-light "^2.5.0" - jsbi "^4.1.0" - tiny-invariant "^1.1.0" - tiny-warning "^1.0.0" - toformat "^2.0.0" - "@sushiswap/core-sdk@1.0.0-canary.133": version "1.0.0-canary.133" resolved "https://registry.yarnpkg.com/@sushiswap/core-sdk/-/core-sdk-1.0.0-canary.133.tgz#8a6c2566e1ceb23eec7ae0463dd474b1900b6a23" @@ -3079,14 +3063,14 @@ resolved "https://registry.yarnpkg.com/@sushiswap/default-token-list/-/default-token-list-31.1.0.tgz#d8babd1a1bfd0965b325aaae726beede930e7de3" integrity sha512-uicM8HGvGaBUd+Rz/XcpLaXJt+3qfIp1IeZnNz/xB9blW7e/UT97gGG5pz2GeHaw/TQLf+2AZYqZgiWGJPmmiA== -"@sushiswap/kashi-sdk@1.0.0-canary.104": - version "1.0.0-canary.104" - resolved "https://registry.yarnpkg.com/@sushiswap/kashi-sdk/-/kashi-sdk-1.0.0-canary.104.tgz#865fd39ff35cacfd350e4e8e687660e0874a4dc4" - integrity sha512-NcuUqm752T7D7oevwCS6B7W0Via0Yv2XlLySHm9aI7PwGH0ZBlz/VD+qxYum1ETkD6kiy2iNhrLTQySCx9/prA== +"@sushiswap/kashi-sdk@1.0.0-canary.105": + version "1.0.0-canary.105" + resolved "https://registry.yarnpkg.com/@sushiswap/kashi-sdk/-/kashi-sdk-1.0.0-canary.105.tgz#d1204ba18bd95d42376eb9efef5e44ea3eec1c81" + integrity sha512-GcfYMd7T5CeJiPsNf27UMLoC786W0yv3BUuAOaklgQVxb4ZBBuoMe6RhgHJXgxlkIRLpW4VrGoR11Ci6NKmP8A== dependencies: "@ethersproject/abi" "^5.4.0" "@ethersproject/contracts" "^5.4.0" - "@sushiswap/bentobox-sdk" "1.0.0-canary.113" + "@sushiswap/bentobox-sdk" "1.0.0-canary.114" "@sushiswap/limit-order-pair-list@0.2.17": version "0.2.17" From 8169b7362cb0260c0fb667462c9462e9bf5cb529 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Fri, 9 Sep 2022 20:21:39 +0900 Subject: [PATCH 59/60] fix: trade nav header --- src/config/features.ts | 3 --- src/features/trade/HeaderNew.tsx | 24 +++++++++++++----------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/config/features.ts b/src/config/features.ts index 0ff9af6aa9..adff13b2df 100644 --- a/src/config/features.ts +++ b/src/config/features.ts @@ -17,7 +17,6 @@ const features: FeatureMap = { Feature.INARI, Feature.VESTING, Feature.LIMIT_ORDERS, - Feature.STOP_LOSSES, Feature.SUSHIGUARD, ], [ChainId.ROPSTEN]: [Feature.AMM, Feature.LIQUIDITY_MINING, Feature.BENTOBOX, Feature.KASHI, Feature.MISO], @@ -37,7 +36,6 @@ const features: FeatureMap = { Feature.AMM, Feature.ANALYTICS, Feature.LIMIT_ORDERS, - Feature.STOP_LOSSES, Feature.LIQUIDITY_MINING, Feature.ANALYTICS, Feature.BENTOBOX, @@ -53,7 +51,6 @@ const features: FeatureMap = { Feature.MIGRATE, Feature.ANALYTICS, Feature.LIMIT_ORDERS, - Feature.STOP_LOSSES, Feature.TRIDENT, Feature.TRIDENT_MIGRATION, Feature.MISO, diff --git a/src/features/trade/HeaderNew.tsx b/src/features/trade/HeaderNew.tsx index a33122fc4a..6b4eff12db 100644 --- a/src/features/trade/HeaderNew.tsx +++ b/src/features/trade/HeaderNew.tsx @@ -64,17 +64,19 @@ const HeaderNew: FC = ({ inputCurrency, outputCurrency, trident ) : null} - - - {i18n._(t`Stop`)} - - + {featureEnabled(Feature.STOP_LOSSES, chainId) ? ( + + + {i18n._(t`Stop`)} + + + ) : null}
{isLimitOrder && } From 62c7c78802a0546d5fb11a480fb38eeaed272d40 Mon Sep 17 00:00:00 2001 From: unbreakablery Date: Wed, 14 Sep 2022 00:48:35 +0900 Subject: [PATCH 60/60] feat: add more stopLimitOrder wrapper --- src/config/features.ts | 1 + src/constants/autonomy.ts | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/config/features.ts b/src/config/features.ts index adff13b2df..04692cf0ad 100644 --- a/src/config/features.ts +++ b/src/config/features.ts @@ -51,6 +51,7 @@ const features: FeatureMap = { Feature.MIGRATE, Feature.ANALYTICS, Feature.LIMIT_ORDERS, + Feature.STOP_LOSSES, Feature.TRIDENT, Feature.TRIDENT_MIGRATION, Feature.MISO, diff --git a/src/constants/autonomy.ts b/src/constants/autonomy.ts index 7262efb57c..da47bd4083 100644 --- a/src/constants/autonomy.ts +++ b/src/constants/autonomy.ts @@ -3,17 +3,26 @@ import { AddressMap, ChainId } from '@sushiswap/core-sdk' export const QUERY_REQUEST_LIMIT = 10000 export const AUTONOMY_REGISTRY_ADDRESSES: AddressMap = { + [ChainId.ETHEREUM]: '0x973107d4b9A5B69fd99c23a3C31eFA8fafE7Ae38', + [ChainId.FANTOM]: '0x6e5Ec7f4C98B34e0aAAA02D8D2136e626ED33B10', [ChainId.BSC]: '0x18d087F8D22D409D3CD366AF00BD7AeF0BF225Db', [ChainId.AVALANCHE]: '0x68FCbECa74A7E5D386f74E14682c94DE0e1bC56b', + [ChainId.MATIC]: '0x18d02301E534cab22267460eD8fBdf2B8382A3ff', } export const STOP_LIMIT_ORDER_WRAPPER_ADDRESSES: AddressMap = { + [ChainId.ETHEREUM]: '0xeE1e77774225Fc9c1a4B5B32E0029c1768A9f338', + [ChainId.FANTOM]: '0xe2952F019d317d9e9FadaeeD4F61dF5879295c17', [ChainId.AVALANCHE]: '0x2f57dabe3dd1ecAed3F79a0D6d2530fCa5A11912', + [ChainId.MATIC]: '0x849F9303AC8fb345e3D07c78A6795d1989d9CE16', } export const CHAINLINK_ORACLE_ADDRESS: AddressMap = { + [ChainId.ETHEREUM]: '0x00632CFe43d8F9f8E6cD0d39Ffa3D4fa7ec73CFB', + [ChainId.FANTOM]: '0x4a8C72c1e443d2199D7D65D8EAE6cA7ac1E58226', [ChainId.BSC]: '0x00632CFe43d8F9f8E6cD0d39Ffa3D4fa7ec73CFB', [ChainId.AVALANCHE]: '0x232d595594585613F48aaE9c85861E4aB06CE3E5', + [ChainId.MATIC]: '0x4455AbEc4E3310F5Ba427D4Dd49e590c2A27f7d5', } type FeeAmountOfEthMap = { @@ -21,7 +30,10 @@ type FeeAmountOfEthMap = { } // it defines minimum amount of fee(ETH unit) that Autonomy wrapper contract charges when to execute orders. export const STOP_LIMIT_ORDER_WRAPPER_FEE_MINIMUM: FeeAmountOfEthMap = { + [ChainId.ETHEREUM]: '0.007', // 0.007 ETH + [ChainId.FANTOM]: '0.1', // 0.1 FTM [ChainId.AVALANCHE]: '0.025', // 0.025 AVAX + [ChainId.MATIC]: '0.03', // 0.03 MATIC } interface MoralisInfo { @@ -30,10 +42,22 @@ interface MoralisInfo { } export const MORALIS_INFO: { [chainId: number]: MoralisInfo } = { + [ChainId.ETHEREUM]: { + serverURL: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_URL_ETH || '', + key: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY_ETH || '', + }, + [ChainId.FANTOM]: { + serverURL: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_URL_FTM || '', + key: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY_FTM || '', + }, [ChainId.AVALANCHE]: { serverURL: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_URL_AVAX || '', key: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY_AVAX || '', }, + [ChainId.MATIC]: { + serverURL: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_URL_MATIC || '', + key: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY_MATIC || '', + }, [ChainId.BSC]: { serverURL: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_URL_BSC || '', key: process.env.NEXT_PUBLIC_AUTONOMY_MORALIS_KEY_BSC || '',