From 3bf9eaad7aab0f81088a15eb0abd2cca5515a113 Mon Sep 17 00:00:00 2001 From: juan Date: Fri, 12 Mar 2021 13:02:08 -0500 Subject: [PATCH 1/2] make sure correct network is set --- .../bridge/src/components/Layout/index.tsx | 36 ++++--- .../bridge/src/components/Transfer/index.tsx | 101 +++++++++++------- packages/bridge/src/constants/labels.ts | 3 + packages/bridge/src/contexts/chainPair.tsx | 17 +-- packages/bridge/src/contexts/ethereum.tsx | 20 ++-- .../bridge/src/hooks/useCorrectNetwork.tsx | 28 +++++ 6 files changed, 128 insertions(+), 77 deletions(-) create mode 100644 packages/bridge/src/hooks/useCorrectNetwork.tsx diff --git a/packages/bridge/src/components/Layout/index.tsx b/packages/bridge/src/components/Layout/index.tsx index 93842fb..6153248 100644 --- a/packages/bridge/src/components/Layout/index.tsx +++ b/packages/bridge/src/components/Layout/index.tsx @@ -1,23 +1,24 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import './../../App.less'; import './index.less'; -import { Layout } from 'antd'; +import { Layout, Button } from 'antd'; import { Link, useLocation } from 'react-router-dom'; import metamaskIcon from '../../assets/metamask.svg'; import { LABELS } from '../../constants'; -import { contexts, AppBar, shortenAddress } from '@oyster/common'; +import { contexts, AppBar, shortenAddress, useWallet } from '@oyster/common'; import Wormhole from '../Wormhole'; import { useEthereum } from '../../contexts'; +import { useCorrectNetwork } from '../../hooks/useCorrectNetwork'; const { Header, Content } = Layout; const { useConnectionConfig } = contexts.Connection; export const AppLayout = React.memo((props: any) => { - const { env } = useConnectionConfig(); const location = useLocation(); const [wormholeReady, setWormholeReady] = useState(false); - const { accounts } = useEthereum(); + const { accounts, provider } = useEthereum(); + const hasCorrespondingNetworks = useCorrectNetwork(); const paths: { [key: string]: string } = { '/faucet': '7', @@ -48,15 +49,22 @@ export const AppLayout = React.memo((props: any) => { left={ <> {accounts[0] && ( -
- {'metamask-icon'} - {shortenAddress(accounts[0], 4)} +
+ {hasCorrespondingNetworks ? ( + <> + {'metamask-icon'} + {shortenAddress(accounts[0], 4)} + + ) : ( + + )}
)} diff --git a/packages/bridge/src/components/Transfer/index.tsx b/packages/bridge/src/components/Transfer/index.tsx index 74ba2a0..d35edab 100644 --- a/packages/bridge/src/components/Transfer/index.tsx +++ b/packages/bridge/src/components/Transfer/index.tsx @@ -5,6 +5,7 @@ import { ConnectButton, programIds, formatAmount, + notify, } from '@oyster/common'; import { Input } from './../Input'; @@ -17,6 +18,8 @@ import { WrappedAssetFactory } from '../../contracts/WrappedAssetFactory'; import { WormholeFactory } from '../../contracts/WormholeFactory'; import BN from 'bn.js'; import { useTokenChainPairState } from '../../contexts/chainPair'; +import { LABELS } from '../../constants'; +import { useCorrectNetwork } from '../../hooks/useCorrectNetwork'; const { useConnection } = contexts.Connection; const { useWallet } = contexts.Wallet; @@ -40,7 +43,8 @@ export const typeToIcon = (type: string, isLast: boolean) => { export const Transfer = () => { const connection = useConnection(); const { wallet } = useWallet(); - const { provider, tokenMap, tokens } = useEthereum(); + const { provider, accounts, tokenMap } = useEthereum(); + const hasCorrespondingNetworks = useCorrectNetwork(); const { A, B, @@ -87,54 +91,62 @@ export const Transfer = () => { } (async () => { - if (!provider) { + if (!provider || !accounts[0]) { return; } + try { + const bridgeAddress = programIds().wormhole.bridge; - const bridgeAddress = programIds().wormhole.bridge; + let signer = provider.getSigner(); + let e = WrappedAssetFactory.connect(asset, provider); + let addr = await signer.getAddress(); + let balance = await e.balanceOf(addr); + let decimals = await e.decimals(); + let symbol = await e.symbol(); - let signer = provider.getSigner(); - let e = WrappedAssetFactory.connect(asset, provider); - let addr = await signer.getAddress(); - let balance = await e.balanceOf(addr); - let decimals = await e.decimals(); - let symbol = await e.symbol(); + let allowance = await e.allowance(addr, bridgeAddress); - let allowance = await e.allowance(addr, bridgeAddress); + let info = { + address: asset, + name: symbol, + balance: balance, + balanceAsNumber: + new BN(balance.toString()) + .div(new BN(10).pow(new BN(decimals - 2))) + .toNumber() / 100, + allowance: allowance, + decimals: decimals, + isWrapped: false, + chainID: ASSET_CHAIN.Ethereum, + assetAddress: Buffer.from(asset.slice(2), 'hex'), + mint: '', + }; - let info = { - address: asset, - name: symbol, - balance: balance, - balanceAsNumber: - new BN(balance.toString()) - .div(new BN(10).pow(new BN(decimals - 2))) - .toNumber() / 100, - allowance: allowance, - decimals: decimals, - isWrapped: false, - chainID: ASSET_CHAIN.Ethereum, - assetAddress: Buffer.from(asset.slice(2), 'hex'), - mint: '', - }; + let b = WormholeFactory.connect(bridgeAddress, provider); - let b = WormholeFactory.connect(bridgeAddress, provider); + let isWrapped = await b.isWrappedAsset(asset); + if (isWrapped) { + info.chainID = await e.assetChain(); + info.assetAddress = Buffer.from( + (await e.assetAddress()).slice(2), + 'hex', + ); + info.isWrapped = true; + } - let isWrapped = await b.isWrappedAsset(asset); - if (isWrapped) { - info.chainID = await e.assetChain(); - info.assetAddress = Buffer.from( - (await e.assetAddress()).slice(2), - 'hex', - ); - info.isWrapped = true; + setRequest({ + ...request, + asset, + info, + }); + } catch (e) { + console.error(e.toString()); + notify({ + message: `Error getting asset (${asset}) information`, + description: e.toString(), + type: 'error', + }); } - - setRequest({ - ...request, - asset, - info, - }); })(); }, [request, provider]); @@ -193,6 +205,9 @@ export const Transfer = () => {
{ if (!wallet || !provider) { return; @@ -307,7 +322,11 @@ export const Transfer = () => { }); }} > - Transfer + {hasCorrespondingNetworks + ? !(A.amount && B.amount) + ? LABELS.ENTER_AMOUNT + : LABELS.TRANSFER + : LABELS.SET_CORRECT_WALLET_NETWORK} ); diff --git a/packages/bridge/src/constants/labels.ts b/packages/bridge/src/constants/labels.ts index 5962d12..e7dd339 100644 --- a/packages/bridge/src/constants/labels.ts +++ b/packages/bridge/src/constants/labels.ts @@ -17,4 +17,7 @@ export const LABELS = { SETTINGS_TOOLTIP: 'Settings', GO_BACK_ACTION: 'Go back', TOTAL_TITLE: 'Total', + ENTER_AMOUNT: 'Enter an amount', + TRANSFER: 'Transfer', + SET_CORRECT_WALLET_NETWORK: 'Set correct wallet network', }; diff --git a/packages/bridge/src/contexts/chainPair.tsx b/packages/bridge/src/contexts/chainPair.tsx index 992052d..e0d777d 100644 --- a/packages/bridge/src/contexts/chainPair.tsx +++ b/packages/bridge/src/contexts/chainPair.tsx @@ -62,7 +62,7 @@ function getDefaultTokens(tokens: TokenInfo[], search: string) { const from = urlParams.get('from'); defaultChain = from === 'SOL' ? from : 'ETH'; const token = urlParams.get('token') || defaultToken; - if (nameToToken.has(token) || isValidAddress(token)) { + if (nameToToken.has(token)) { defaultToken = token; } } @@ -116,35 +116,26 @@ export function TokenChainPairProvider({ children = null as any }) { // updates browser history on token changes useEffect(() => { // set history - const token = - tokens.find(t => t.address === mintAddress)?.symbol || mintAddress; + const token = tokens.find(t => t.address === mintAddress)?.symbol; if (token && chainA) { history.push({ search: `?from=${toChainSymbol(chainA)}&token=${token}`, }); - } else { - if (mintAddress) { - history.push({ - search: ``, - }); - } else { - return; - } } }, [mintAddress, tokens, chainA]); // Updates tokens on location change useEffect(() => { if ( - !tokens.length || + !ethTokens.length || (!location.search && mintAddress) || location.pathname.indexOf('move') < 0 ) { return; } let { defaultChain, defaultToken } = getDefaultTokens( - tokens, + ethTokens, location.search, ); if (!defaultToken || !defaultChain) { diff --git a/packages/bridge/src/contexts/ethereum.tsx b/packages/bridge/src/contexts/ethereum.tsx index e1fee97..6514ced 100644 --- a/packages/bridge/src/contexts/ethereum.tsx +++ b/packages/bridge/src/contexts/ethereum.tsx @@ -97,15 +97,17 @@ export const EthereumProvider: FunctionComponent = ({ children }) => { useEffect(() => { if (connected) { // @ts-ignore - window.ethereum.enable(); - // @ts-ignore - const provider = new ethers.providers.Web3Provider( - (window as any).ethereum, - ); - const signer = provider.getSigner(); - signer.getAddress().then(account => setAccounts([account])); - - setProvider(provider); + window.ethereum.enable().then(() => { + // @ts-ignore + const provider = new ethers.providers.Web3Provider( + (window as any).ethereum, + ); + const signer = provider.getSigner(); + signer.getAddress().then(account => { + setAccounts([account]); + }); + setProvider(provider); + }); } }, [connected]); diff --git a/packages/bridge/src/hooks/useCorrectNetwork.tsx b/packages/bridge/src/hooks/useCorrectNetwork.tsx new file mode 100644 index 0000000..f3a832f --- /dev/null +++ b/packages/bridge/src/hooks/useCorrectNetwork.tsx @@ -0,0 +1,28 @@ +import { useEthereum } from '../contexts'; +import { useEffect, useState } from 'react'; +import { useConnectionConfig } from '@oyster/common'; + +export const useCorrectNetwork = () => { + const { env } = useConnectionConfig(); + const [hasCorrespondingNetworks, setHasCorrespondingNetworks] = useState( + true, + ); + const { provider } = useEthereum(); + + useEffect(() => { + if (provider) { + provider.getNetwork().then(network => { + if (network.chainId === 5) { + setHasCorrespondingNetworks(env === 'testnet'); + } else if (network.chainId === 1) { + setHasCorrespondingNetworks(env === 'mainnet-beta'); + } else { + setHasCorrespondingNetworks(false); + } + }); + } + setHasCorrespondingNetworks(true); + }, [provider, env]); + + return hasCorrespondingNetworks; +}; From 227937ab4678964ed30d67bc42c07344ce7a4682 Mon Sep 17 00:00:00 2001 From: juan Date: Fri, 12 Mar 2021 15:36:35 -0500 Subject: [PATCH 2/2] make sure prices are queried only once --- packages/bridge/src/contexts/coingecko.tsx | 2 +- packages/bridge/src/hooks/useWormholeAccounts.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bridge/src/contexts/coingecko.tsx b/packages/bridge/src/contexts/coingecko.tsx index 308be9a..6519d90 100644 --- a/packages/bridge/src/contexts/coingecko.tsx +++ b/packages/bridge/src/contexts/coingecko.tsx @@ -2,7 +2,7 @@ import { EventEmitter } from '@oyster/common'; import React, { useContext, useEffect, useState } from 'react'; import { MarketsContextState } from './market'; -export const COINGECKO_POOL_INTERVAL = 10000; // 2 min +export const COINGECKO_POOL_INTERVAL = 1000 * 30; // 30 sec export const COINGECKO_API = 'https://api.coingecko.com/api/v3/'; export const COINGECKO_COIN_LIST_API = `${COINGECKO_API}coins/list`; export const COINGECKO_COIN_PRICE_API = `${COINGECKO_API}simple/price`; diff --git a/packages/bridge/src/hooks/useWormholeAccounts.tsx b/packages/bridge/src/hooks/useWormholeAccounts.tsx index 4e8101b..8fa705b 100644 --- a/packages/bridge/src/hooks/useWormholeAccounts.tsx +++ b/packages/bridge/src/hooks/useWormholeAccounts.tsx @@ -362,14 +362,14 @@ export const useWormholeAccounts = () => { }, [externalAssets, setAmountInUSD]); useEffect(() => { - if (externalAssets && coinList) { + if (externalAssets && coinList && !loading) { dataSourcePriceQuery(); } return () => { window.clearTimeout(coingeckoTimer.current); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [externalAssets, coinList, dataSourcePriceQuery]); + }, [externalAssets, coinList, loading]); return { loading,