From 21c890ecc5cee91426ef4cdd30f2760f15590eb8 Mon Sep 17 00:00:00 2001 From: Smart Sceptre Date: Fri, 19 Jan 2024 13:45:59 +0100 Subject: [PATCH] [FIX]: token approve context and rpc latency --- package.json | 1 + src/config.ts | 5 +++- src/hooks/callbacks/useApprove.ts | 24 ++++++++++-------- src/protocol/Protocol.ts | 28 ++++++++++++++++----- src/state/token/controller.ts | 8 +++--- src/utils/interface.ts | 1 + src/utils/provider.ts | 27 ++++++++++++++++++++ src/views/DebtPool/modal/DepositModal.tsx | 3 ++- src/views/dex/components/BuyOrdersCard.tsx | 14 +++++------ src/views/dex/components/BuySellTable.tsx | 4 +-- src/views/dex/components/SellOrdersCard.tsx | 14 +++++------ src/views/dex/index.tsx | 10 ++++---- src/views/dex/modals/BuySellOfferModal.tsx | 3 ++- 13 files changed, 97 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index 534b3c7..9b2e0fd 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@material-ui/data-grid": "^4.0.0-alpha.35", "@material-ui/icons": "^4.11.3", "@metamask/detect-provider": "^1.2.0", + "@rainbow-me/rainbowkit": "^1.3.3", "@reduxjs/toolkit": "^1.6.1", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^13.0.0", diff --git a/src/config.ts b/src/config.ts index ee58490..c27b10b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,7 +7,10 @@ const configurations: { [env: string]: Configuration } = { chainId: 137, etherscanUrl: 'https://polygonscan.com', defaultProvider: - 'https://polygon-rpc.com/', + // 'https://polygon-rpc.com/', + 'https://rpc.ankr.com/polygon', + logHistoryProvider: + 'https://polygon.llamarpc.com', deployments: require('./protocol/deployments/matic.json'), refreshInterval: 10000, gasLimitMultiplier: 1.1, diff --git a/src/hooks/callbacks/useApprove.ts b/src/hooks/callbacks/useApprove.ts index 44f28c9..5a6b43f 100644 --- a/src/hooks/callbacks/useApprove.ts +++ b/src/hooks/callbacks/useApprove.ts @@ -5,9 +5,7 @@ import ERC20 from '../../protocol/ERC20'; import useAllowance from '../state/useAllowance'; import { useHasPendingApproval, useTransactionAdder } from '../../state/transactions/hooks'; import useCore from '../useCore'; - -const APPROVE_AMOUNT = ethers.constants.MaxUint256; -const APPROVE_BASE_AMOUNT = BigNumber.from('1000000000000000000000000'); +import { current } from '@reduxjs/toolkit'; export enum ApprovalState { UNKNOWN, @@ -20,18 +18,21 @@ export enum ApprovalState { * Returns a variable indicating the state of the approval and a function which * approves if necessary or early returns. */ -function useApprove(token: ERC20, spender: string): [ApprovalState, () => Promise] { +function useApprove(token: ERC20, spender: string, approveAmount: string): [ApprovalState, () => Promise] { const core = useCore() const pendingApproval = useHasPendingApproval(token?.address, spender); const currentAllowance = useAllowance(token, spender, pendingApproval); - // Check the current approval status. const approvalState: ApprovalState = useMemo(() => { // We might not have enough data to know whether or not we need to approve. - if (!currentAllowance) return ApprovalState.UNKNOWN; + if (approveAmount == "") + return ApprovalState.UNKNOWN; + console.log(currentAllowance, BigNumber.from(String(Number(approveAmount) * 1000000))) + if (!currentAllowance || currentAllowance < BigNumber.from(String(Number(approveAmount) * 1000000))) { + return ApprovalState.NOT_APPROVED; + } - // The amountToApprove will be defined if currentAllowance is. - return currentAllowance.lt(APPROVE_BASE_AMOUNT) + return currentAllowance.lt(BigNumber.from(approveAmount)) ? pendingApproval ? ApprovalState.PENDING : ApprovalState.NOT_APPROVED @@ -39,9 +40,9 @@ function useApprove(token: ERC20, spender: string): [ApprovalState, () => Promis }, [currentAllowance, pendingApproval]); const addTransaction = useTransactionAdder(); - const approve = useCallback(async (): Promise => { - if (approvalState !== ApprovalState.NOT_APPROVED && approvalState !== ApprovalState.UNKNOWN) { + console.log('approval-state', approvalState); + if (approvalState !== ApprovalState.NOT_APPROVED) { console.error('Approve was called unnecessarily'); return; } @@ -50,7 +51,8 @@ function useApprove(token: ERC20, spender: string): [ApprovalState, () => Promis // @ts-ignore let symbol = token.symbol try { - const response = await token.approve(spender, APPROVE_AMOUNT); + console.log('-----', approveAmount, '-----'); + const response = await token.approve(spender, BigNumber.from(String(Number(approveAmount) * 1000000))); addTransaction(response, { summary: `Approve ${symbol}`, approval: { diff --git a/src/protocol/Protocol.ts b/src/protocol/Protocol.ts index e60248e..e6dcdc9 100644 --- a/src/protocol/Protocol.ts +++ b/src/protocol/Protocol.ts @@ -3,7 +3,7 @@ import { BigNumber, Contract, ethers, Overrides } from 'ethers'; import ERC20 from './ERC20'; import ABIS from './deployments/abi'; import { Configuration } from '../utils/interface'; -import { getDefaultProvider } from '../utils/provider'; +import { getDefaultProvider, getLogProvider } from '../utils/provider'; import Multicall from './Multicall'; import * as tokenState from '../state/token/controller'; @@ -19,7 +19,9 @@ export class Protocol { config: Configuration; contracts: { [name: string]: Contract }; + contractsLog: { [name: string]: Contract }; provider: ethers.providers.BaseProvider; + providerLog: ethers.providers.BaseProvider; // 'ARTH-DP': ERC20; // ARTH: ERC20; @@ -29,24 +31,31 @@ export class Protocol { tokens: { [name: string]: ERC20; }; + tokensLog: { + [name: string]: ERC20; + }; multicall!: { [chainId: number]: Multicall }; constructor(cfg: Configuration) { const { deployments, supportedTokens } = cfg; - console.log("deployments", deployments) + // console.log("deployments", deployments) const provider = getDefaultProvider(cfg); + const provider2 = getLogProvider(cfg); // @ts-ignore this.multicall = { 137: {} }; this.contracts = {}; + this.contractsLog = {}; this.tokens = {}; + this.tokensLog = {}; for (const [name, deployment] of Object.entries(deployments)) { if (!deployment.abi) continue; this.contracts[name] = new Contract(deployment.address, ABIS[deployment.abi], provider); + this.contractsLog[name] = new Contract(deployment.address, ABIS[deployment.abi], provider2); if (supportedTokens.includes(name)) { this.tokens[name] = new ERC20( deployments[name].address, @@ -54,6 +63,12 @@ export class Protocol { name, cfg.decimalOverrides[name] || 18, ); + this.tokensLog[name] = new ERC20( + deployments[name].address, + provider2, + name, + cfg.decimalOverrides[name] || 18, + ); } this.multicall[137] = new Multicall( @@ -64,6 +79,7 @@ export class Protocol { this.config = cfg; this.provider = provider; + this.providerLog = provider2; }; /** @@ -76,10 +92,10 @@ export class Protocol { this.signer = newProvider.getSigner() this.myAccount = account; - console.log('window.ethereum', window.ethereum) - console.log('newProvider', newProvider) - console.log('this.signer', this.signer) - console.log("Account:", await this.signer.getAddress()); + // console.log('window.ethereum', window.ethereum) + // console.log('newProvider', newProvider) + // console.log('this.signer', this.signer) + // console.log("Account:", await this.signer.getAddress()); for (const [name, contract] of Object.entries(this.contracts)) { this.contracts[name] = contract.connect(this.signer); diff --git a/src/state/token/controller.ts b/src/state/token/controller.ts index fb34921..a51f1af 100644 --- a/src/state/token/controller.ts +++ b/src/state/token/controller.ts @@ -21,7 +21,7 @@ const _initUser = (core: Protocol, dispatch: Dispatch, chainId: number) => { Actions.updateBalanceOf({ bal, who: core.myAccount, - token: core.tokens['ARTH-DP'].address, + token: core.tokensLog['ARTH-DP'].address, }), ) }); @@ -29,7 +29,7 @@ const _initUser = (core: Protocol, dispatch: Dispatch, chainId: number) => { dispatch( Actions.updateTotalSupply({ supply, - token: core.tokens['ARTH-DP'].address, + token: core.tokensLog['ARTH-DP'].address, }), ) }); @@ -66,13 +66,13 @@ const _initUser = (core: Protocol, dispatch: Dispatch, chainId: number) => { addCallsArray.push( { key: `BALANCE_OF_${token}`, - target: core.tokens['ARTH-DP'].address, + target: core.tokensLog['ARTH-DP'].address, call: ['balanceOf(address)(uint256)', core.myAccount], convertResult: (val: any) => val, }, { key: `TOTAL_SUPPLY_OF_${token}`, - target: core.tokens['ARTH-DP'].address, + target: core.tokensLog['ARTH-DP'].address, call: ['totalSupply()(uint256)'], convertResult: (val: any) => val, }, diff --git a/src/utils/interface.ts b/src/utils/interface.ts index ead2c15..ef2be20 100644 --- a/src/utils/interface.ts +++ b/src/utils/interface.ts @@ -70,6 +70,7 @@ export type Configuration = { networkDisplayName: string; etherscanUrl: string; defaultProvider: string; + logHistoryProvider: string; deployments: Deployments; config?: EthereumConfig; blockchainToken: 'MATIC' diff --git a/src/utils/provider.ts b/src/utils/provider.ts index 7bc9c67..3d1c2c2 100644 --- a/src/utils/provider.ts +++ b/src/utils/provider.ts @@ -30,6 +30,33 @@ export function getDefaultProvider(config: Configuration): ethers.providers.Base return new ethers.providers.JsonRpcProvider(config.defaultProvider); } +export function getLogProvider(config: Configuration): ethers.providers.BaseProvider { + // @ts-ignore + const _window: { ethereum?: any, web3?: any } = window; + + // Modern dapp browsers. + if (_window.ethereum) { + try { + // Request account access + // const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }) + // App.YOUR_ADDRESS = accounts[0] + } catch (error) { + // User denied account access... + console.error("User denied account access"); + } + + return new ethers.providers.Web3Provider(_window.ethereum); + } + + // Legacy dapp browsers... + if (_window.web3) { + return new ethers.providers.Web3Provider(_window.web3.currentProvider); + } + + // If no injected web3 instance is detected, fall back to backup node. + return new ethers.providers.JsonRpcProvider(config.logHistoryProvider); +} + export function getGanacheProvider(config: Configuration): ethers.providers.JsonRpcProvider { return new ethers.providers.JsonRpcProvider( web3ProviderFrom(config.defaultProvider), diff --git a/src/views/DebtPool/modal/DepositModal.tsx b/src/views/DebtPool/modal/DepositModal.tsx index 6e12178..22e63de 100644 --- a/src/views/DebtPool/modal/DepositModal.tsx +++ b/src/views/DebtPool/modal/DepositModal.tsx @@ -33,7 +33,8 @@ const DepositModal = (props: any) => { const [approveStatus, approve] = useApprove( token, - core.contracts['Staking-RewardsV2'].address + core.contracts['Staking-RewardsV2'].address, + formatToBN(val, token.decimal).toString() ); const depositAction = useDeposit(val) diff --git a/src/views/dex/components/BuyOrdersCard.tsx b/src/views/dex/components/BuyOrdersCard.tsx index 31e7889..51f1815 100644 --- a/src/views/dex/components/BuyOrdersCard.tsx +++ b/src/views/dex/components/BuyOrdersCard.tsx @@ -40,18 +40,18 @@ function BuyOrdersCard(props: IProps) { let buyOrderArr: any = [] let sellOrderArr: any = [] - const testLastOfferId = await core.contracts['MatchingMarket'].last_offer_id() + const testLastOfferId = await core.contractsLog['MatchingMarket'].last_offer_id() for(let i = 1; i <= testLastOfferId.toString(); i++){ - const offer = await core.contracts['MatchingMarket'].offers(i) + const offer = await core.contractsLog['MatchingMarket'].offers(i) if(offer[5]._hex !== "0x00"){ - if(offer.buy_gem.toLowerCase() === core.tokens['ARTH-DP'].address.toLowerCase()){ - if(offer.pay_gem.toLowerCase() === core.tokens['USDC'].address.toLowerCase()) + if(offer.buy_gem.toLowerCase() === core.tokensLog['ARTH-DP'].address.toLowerCase()){ + if(offer.pay_gem.toLowerCase() === core.tokensLog['USDC'].address.toLowerCase()) buyOrderArr.push({offer, i, exchangeToken: 'USDC'}) - if(offer.pay_gem.toLowerCase() === core.tokens['MAHA'].address.toLowerCase()) + if(offer.pay_gem.toLowerCase() === core.tokensLog['MAHA'].address.toLowerCase()) buyOrderArr.push({offer, i, exchangeToken: 'MAHA'}) - if(offer.pay_gem.toLowerCase() === core.tokens['SCLP'].address.toLowerCase()) + if(offer.pay_gem.toLowerCase() === core.tokensLog['SCLP'].address.toLowerCase()) buyOrderArr.push({offer, i, exchangeToken: 'SCLP'}) const finalArr = buyOrderArr.sort((a: any, b: any) => Number(getDisplayBalance(a.offer.buy_amt)) - Number(getDisplayBalance(b.offer.buy_amt))) @@ -68,7 +68,7 @@ function BuyOrdersCard(props: IProps) { cancelOrderAction(id) } - console.log("buyOrderData",buyOrderData) + // console.log("buyOrderData",buyOrderData) diff --git a/src/views/dex/components/BuySellTable.tsx b/src/views/dex/components/BuySellTable.tsx index e209557..aab7476 100644 --- a/src/views/dex/components/BuySellTable.tsx +++ b/src/views/dex/components/BuySellTable.tsx @@ -32,8 +32,8 @@ function BuySellTable(props: IProps) { const [sellTotal, setSellTotal] = useState('0') const [openOfferModal, setOpenOfferModal] = useState(false) - const usdcbal = useTokenBalance(core.tokens['USDC']) - const mahabal = useTokenBalance(core.tokens['MAHA']) + const usdcbal = useTokenBalance(core.tokensLog['USDC']) + const mahabal = useTokenBalance(core.tokensLog['MAHA']) let actionButton: boolean = false actionButton = diff --git a/src/views/dex/components/SellOrdersCard.tsx b/src/views/dex/components/SellOrdersCard.tsx index 704bb0b..f861e5e 100644 --- a/src/views/dex/components/SellOrdersCard.tsx +++ b/src/views/dex/components/SellOrdersCard.tsx @@ -33,17 +33,17 @@ function SellOrdersCard(props: IProps) { const getSellOrderData = async() => { let sellOrderArr: any = [] - const testLastOfferId = await core.contracts['MatchingMarket'].last_offer_id() + const testLastOfferId = await core.contractsLog['MatchingMarket'].last_offer_id() for(let i = 1; i <= testLastOfferId.toString(); i++){ - const offer = await core.contracts['MatchingMarket'].offers(i) + const offer = await core.contractsLog['MatchingMarket'].offers(i) if(offer[5]._hex !== "0x00"){ - if(offer.pay_gem.toLowerCase() === core.tokens['ARTH-DP'].address.toLowerCase()) { - if(offer.buy_gem.toLowerCase() === core.tokens['USDC'].address.toLowerCase()) + if(offer.pay_gem.toLowerCase() === core.tokensLog['ARTH-DP'].address.toLowerCase()) { + if(offer.buy_gem.toLowerCase() === core.tokensLog['USDC'].address.toLowerCase()) sellOrderArr.push({offer, i, exchangeToken: 'USDC'}) - if(offer.buy_gem.toLowerCase() == core.tokens['MAHA'].address.toLowerCase()) + if(offer.buy_gem.toLowerCase() == core.tokensLog['MAHA'].address.toLowerCase()) sellOrderArr.push({offer, i, exchangeToken: 'MAHA'}) - if(offer.buy_gem.toLowerCase() == core.tokens['SCLP'].address.toLowerCase()) + if(offer.buy_gem.toLowerCase() == core.tokensLog['SCLP'].address.toLowerCase()) sellOrderArr.push({offer, i, exchangeToken: 'SCLP'}) const finalArr = sellOrderArr.sort((a: any, b: any) => Number(getDisplayBalance(a.offer.pay_amt)) - Number(getDisplayBalance(b.offer.pay_amt))) @@ -61,7 +61,7 @@ function SellOrdersCard(props: IProps) { sellOrderAction(id) } - console.log('sellOrderData', sellOrderData) + // console.log('sellOrderData', sellOrderData) return ( diff --git a/src/views/dex/index.tsx b/src/views/dex/index.tsx index 97a98ec..8c57ad8 100644 --- a/src/views/dex/index.tsx +++ b/src/views/dex/index.tsx @@ -18,16 +18,16 @@ function Dex() { const core = useCore() const isMobile = useMediaQuery({ maxWidth: '600px' }); - const baseTokenBalance = useTokenBalance(core.tokens['ARTH-DP']) - const quoteTokenBalance = useTokenBalance(core.tokens['USDC']) + const baseTokenBalance = useTokenBalance(core.tokensLog['ARTH-DP']) + const quoteTokenBalance = useTokenBalance(core.tokensLog['USDC']) let arthUsdcPairStatus = localStorage.getItem('selectorQToken') || 'usdc' const [selectQuoteToken, setSelectQuoteToken] = useState('USDC') const [selectorQToken, setSelectorQToken] = useState(arthUsdcPairStatus) - const usdcbal = useTokenBalance(core.tokens['USDC']) - const mahabal = useTokenBalance(core.tokens['MAHA']) - const sclpbal = useTokenBalance(core.tokens['SCLP']) + const usdcbal = useTokenBalance(core.tokensLog['USDC']) + const mahabal = useTokenBalance(core.tokensLog['MAHA']) + const sclpbal = useTokenBalance(core.tokensLog['SCLP']) useEffect(() => { if (selectorQToken === 'maha') { diff --git a/src/views/dex/modals/BuySellOfferModal.tsx b/src/views/dex/modals/BuySellOfferModal.tsx index 81db02d..0076c81 100644 --- a/src/views/dex/modals/BuySellOfferModal.tsx +++ b/src/views/dex/modals/BuySellOfferModal.tsx @@ -48,7 +48,8 @@ function BuySellOffer(props: any) { const [approveStatus, approve] = useApprove( tokenToApprove, - core.contracts['MatchingMarket'].address + core.contracts['MatchingMarket'].address, + String(tableData.quote * tableData.base) ); const buyOfferAction = useBuyOffer(formatToBN(tableData.total, 6), formatToBN(baseToken), action, tableData.selectQuoteToken.name)