mirror of https://github.com/certusone/oyster.git
commit
c17300e8a9
|
@ -0,0 +1,44 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
|
||||||
|
import { useCorrectNetwork } from '../../hooks/useCorrectNetwork';
|
||||||
|
import metamaskIcon from '../../assets/metamask.svg';
|
||||||
|
import { shortenAddress } from '@oyster/common';
|
||||||
|
import { useEthereum } from '../../contexts';
|
||||||
|
|
||||||
|
export const EthereumConnect = () => {
|
||||||
|
const { accounts, onConnectEthereum, connected } = useEthereum();
|
||||||
|
const { hasCorrespondingNetworks } = useCorrectNetwork();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ marginRight: 8 }}>
|
||||||
|
{connected ? (
|
||||||
|
hasCorrespondingNetworks ? (
|
||||||
|
<>
|
||||||
|
<img
|
||||||
|
alt={'metamask-icon'}
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
src={metamaskIcon}
|
||||||
|
/>
|
||||||
|
{shortenAddress(accounts[0], 4)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Button danger type={'primary'}>
|
||||||
|
WRONG NETWORK
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Button onClick={() => onConnectEthereum && onConnectEthereum()}>
|
||||||
|
<img
|
||||||
|
alt={'metamask-icon'}
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
src={metamaskIcon}
|
||||||
|
/>
|
||||||
|
Connect Metamask
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -11,15 +11,17 @@ export const Footer = () => {
|
||||||
<SecurityAuditButton />
|
<SecurityAuditButton />
|
||||||
<Button
|
<Button
|
||||||
shape={'circle'}
|
shape={'circle'}
|
||||||
|
target={'_blank'}
|
||||||
|
href={'https://github.com/solana-labs/oyster'}
|
||||||
icon={<GithubOutlined />}
|
icon={<GithubOutlined />}
|
||||||
style={{ marginRight: '20px' }}
|
style={{ marginRight: '20px' }}
|
||||||
onClick={() => window.open('https://github.com/solana-labs/oyster', '_blank')}
|
></Button>
|
||||||
>
|
<Button
|
||||||
</Button>
|
shape={'circle'}
|
||||||
<Button shape={'circle'}
|
target={'_blank'}
|
||||||
|
href={'https://twitter.com/solana'}
|
||||||
icon={<TwitterOutlined />}
|
icon={<TwitterOutlined />}
|
||||||
onClick={() => window.open('https://twitter.com/solana', '_blank')}>
|
></Button>
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,20 +6,16 @@ import { Link, useLocation } from 'react-router-dom';
|
||||||
import metamaskIcon from '../../assets/metamask.svg';
|
import metamaskIcon from '../../assets/metamask.svg';
|
||||||
|
|
||||||
import { LABELS } from '../../constants';
|
import { LABELS } from '../../constants';
|
||||||
import { contexts, AppBar, shortenAddress, useWallet } from '@oyster/common';
|
import { AppBar } from '@oyster/common';
|
||||||
import Wormhole from '../Wormhole';
|
import Wormhole from '../Wormhole';
|
||||||
import { useEthereum } from '../../contexts';
|
|
||||||
import { useCorrectNetwork } from '../../hooks/useCorrectNetwork';
|
|
||||||
import { Footer as AppFooter } from './../Footer';
|
import { Footer as AppFooter } from './../Footer';
|
||||||
|
import { EthereumConnect } from '../EthereumConnect';
|
||||||
|
|
||||||
const { Header, Content, Footer } = Layout;
|
const { Header, Content, Footer } = Layout;
|
||||||
const { useConnectionConfig } = contexts.Connection;
|
|
||||||
|
|
||||||
export const AppLayout = React.memo((props: any) => {
|
export const AppLayout = React.memo((props: any) => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [wormholeReady, setWormholeReady] = useState(false);
|
const [wormholeReady, setWormholeReady] = useState(false);
|
||||||
const { accounts, provider } = useEthereum();
|
|
||||||
const hasCorrespondingNetworks = useCorrectNetwork();
|
|
||||||
|
|
||||||
const paths: { [key: string]: string } = {
|
const paths: { [key: string]: string } = {
|
||||||
'/faucet': '7',
|
'/faucet': '7',
|
||||||
|
@ -46,32 +42,7 @@ export const AppLayout = React.memo((props: any) => {
|
||||||
<h2>WORMHOLE</h2>
|
<h2>WORMHOLE</h2>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<AppBar
|
<AppBar useWalletBadge={true} left={<EthereumConnect />} />
|
||||||
useWalletBadge={true}
|
|
||||||
left={
|
|
||||||
<>
|
|
||||||
{accounts[0] && (
|
|
||||||
<div style={{ marginRight: 8 }}>
|
|
||||||
{hasCorrespondingNetworks ? (
|
|
||||||
<>
|
|
||||||
<img
|
|
||||||
alt={'metamask-icon'}
|
|
||||||
width={20}
|
|
||||||
height={20}
|
|
||||||
src={metamaskIcon}
|
|
||||||
/>
|
|
||||||
{shortenAddress(accounts[0], 4)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Button danger type={'primary'}>
|
|
||||||
WRONG NETWORK
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Header>
|
</Header>
|
||||||
)}
|
)}
|
||||||
<Content style={{ padding: '0 50px', flexDirection: 'column' }}>
|
<Content style={{ padding: '0 50px', flexDirection: 'column' }}>
|
||||||
|
|
|
@ -5,8 +5,11 @@ import './index.less';
|
||||||
|
|
||||||
export const SecurityAuditButton = () => {
|
export const SecurityAuditButton = () => {
|
||||||
return (
|
return (
|
||||||
<Button className={'audit-button'}
|
<Button
|
||||||
onClick={() => window.open('https://github.com/certusone/wormhole', '_blank')}>
|
className={'audit-button'}
|
||||||
|
target={'_blank'}
|
||||||
|
href={'https://github.com/certusone/wormhole'}
|
||||||
|
>
|
||||||
Security Audit
|
Security Audit
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,12 @@ import { Input } from '../Input';
|
||||||
|
|
||||||
import './style.less';
|
import './style.less';
|
||||||
import { ASSET_CHAIN, chainToName } from '../../utils/assets';
|
import { ASSET_CHAIN, chainToName } from '../../utils/assets';
|
||||||
import { fromSolana, ProgressUpdate, toSolana, TransferRequest } from '../../models/bridge';
|
import {
|
||||||
|
fromSolana,
|
||||||
|
ProgressUpdate,
|
||||||
|
toSolana,
|
||||||
|
TransferRequest,
|
||||||
|
} from '../../models/bridge';
|
||||||
import { useEthereum } from '../../contexts';
|
import { useEthereum } from '../../contexts';
|
||||||
import { TokenDisplay } from '../TokenDisplay';
|
import { TokenDisplay } from '../TokenDisplay';
|
||||||
import { WrappedAssetFactory } from '../../contracts/WrappedAssetFactory';
|
import { WrappedAssetFactory } from '../../contracts/WrappedAssetFactory';
|
||||||
|
@ -89,7 +94,6 @@ export const Transfer = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (request.from === ASSET_CHAIN.Solana) {
|
if (request.from === ASSET_CHAIN.Solana) {
|
||||||
const bridgeAddress = programIds().wormhole.bridge;
|
const bridgeAddress = programIds().wormhole.bridge;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ import { useWallet as useEthereumWallet } from 'use-wallet';
|
||||||
import WalletConnectProvider from '@walletconnect/web3-provider';
|
import WalletConnectProvider from '@walletconnect/web3-provider';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import Fortmatic from 'fortmatic';
|
import Fortmatic from 'fortmatic';
|
||||||
import Torus from '@toruslabs/torus-embed';
|
|
||||||
import { useConnectionConfig, useWallet, ENV } from '@oyster/common';
|
import { useConnectionConfig, useWallet, ENV } from '@oyster/common';
|
||||||
import { TokenList, TokenInfo } from '@uniswap/token-lists';
|
import { TokenList, TokenInfo } from '@uniswap/token-lists';
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
|
@ -24,20 +23,27 @@ export interface EthereumContextState {
|
||||||
tokens: TokenInfo[];
|
tokens: TokenInfo[];
|
||||||
tokenMap: Map<string, TokenInfo>;
|
tokenMap: Map<string, TokenInfo>;
|
||||||
accounts: string[];
|
accounts: string[];
|
||||||
|
connected: boolean;
|
||||||
|
chainId: number;
|
||||||
|
onConnectEthereum?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EthereumContext = createContext<EthereumContextState>({
|
export const EthereumContext = createContext<EthereumContextState>({
|
||||||
tokens: [],
|
tokens: [],
|
||||||
tokenMap: new Map<string, TokenInfo>(),
|
tokenMap: new Map<string, TokenInfo>(),
|
||||||
accounts: [''],
|
accounts: [''],
|
||||||
|
chainId: 0,
|
||||||
|
connected: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const EthereumProvider: FunctionComponent = ({ children }) => {
|
export const EthereumProvider: FunctionComponent = ({ children }) => {
|
||||||
const [accounts, setAccounts] = useState<string[]>(['']);
|
const [accounts, setAccounts] = useState<string[]>(['']);
|
||||||
const [provider, setProvider] = useState<ethers.providers.Web3Provider>();
|
const [provider, setProvider] = useState<ethers.providers.Web3Provider>();
|
||||||
const { env } = useConnectionConfig();
|
const [connected, setConnected] = useState<boolean>(false);
|
||||||
const { connected } = useWallet();
|
const [chainId, setChainId] = useState<number>(0);
|
||||||
const wallet = useEthereumWallet();
|
//const { env } = useConnectionConfig();
|
||||||
|
const { connected: walletConnected } = useWallet();
|
||||||
|
//const wallet = useEthereumWallet();
|
||||||
const [tokens, setTokens] = useState<{
|
const [tokens, setTokens] = useState<{
|
||||||
map: Map<string, TokenInfo>;
|
map: Map<string, TokenInfo>;
|
||||||
list: TokenInfo[];
|
list: TokenInfo[];
|
||||||
|
@ -94,10 +100,9 @@ export const EthereumProvider: FunctionComponent = ({ children }) => {
|
||||||
})();
|
})();
|
||||||
}, [setTokens]);
|
}, [setTokens]);
|
||||||
|
|
||||||
useEffect(() => {
|
const onConnectEthereum = () => {
|
||||||
if (connected) {
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.ethereum.enable().then(() => {
|
window.ethereum.request({ method: 'eth_requestAccounts' }).then(() => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const provider = new ethers.providers.Web3Provider(
|
const provider = new ethers.providers.Web3Provider(
|
||||||
(window as any).ethereum,
|
(window as any).ethereum,
|
||||||
|
@ -105,15 +110,49 @@ export const EthereumProvider: FunctionComponent = ({ children }) => {
|
||||||
const signer = provider.getSigner();
|
const signer = provider.getSigner();
|
||||||
signer.getAddress().then(account => {
|
signer.getAddress().then(account => {
|
||||||
setAccounts([account]);
|
setAccounts([account]);
|
||||||
|
setConnected(true);
|
||||||
|
});
|
||||||
|
provider.getNetwork().then(network => {
|
||||||
|
setChainId(network.chainId);
|
||||||
});
|
});
|
||||||
setProvider(provider);
|
setProvider(provider);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (connected) {
|
||||||
|
// @ts-ignore
|
||||||
|
window.ethereum.on('disconnect', error => {
|
||||||
|
setConnected(false);
|
||||||
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
window.ethereum.on('accountsChanged', accounts => {
|
||||||
|
if (!accounts || !accounts[0]) setConnected(false);
|
||||||
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
window.ethereum.on('chainChanged', (chainId: string) => {
|
||||||
|
setChainId(parseInt(chainId, 16));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [connected]);
|
}, [connected]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (walletConnected && !connected) {
|
||||||
|
onConnectEthereum();
|
||||||
|
}
|
||||||
|
}, [walletConnected]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EthereumContext.Provider
|
<EthereumContext.Provider
|
||||||
value={{ tokens: tokens.list, tokenMap: tokens.map, accounts, provider }}
|
value={{
|
||||||
|
tokens: tokens.list,
|
||||||
|
tokenMap: tokens.map,
|
||||||
|
accounts,
|
||||||
|
provider,
|
||||||
|
connected,
|
||||||
|
chainId,
|
||||||
|
onConnectEthereum: () => onConnectEthereum(),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</EthereumContext.Provider>
|
</EthereumContext.Provider>
|
||||||
|
|
|
@ -7,22 +7,21 @@ export const useCorrectNetwork = () => {
|
||||||
const [hasCorrespondingNetworks, setHasCorrespondingNetworks] = useState(
|
const [hasCorrespondingNetworks, setHasCorrespondingNetworks] = useState(
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
const { provider } = useEthereum();
|
const { connected, chainId } = useEthereum();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (provider) {
|
if (connected) {
|
||||||
provider.getNetwork().then(network => {
|
if (chainId === 5) {
|
||||||
if (network.chainId === 5) {
|
|
||||||
setHasCorrespondingNetworks(env === 'testnet');
|
setHasCorrespondingNetworks(env === 'testnet');
|
||||||
} else if (network.chainId === 1) {
|
} else if (chainId === 1) {
|
||||||
setHasCorrespondingNetworks(env === 'mainnet-beta');
|
setHasCorrespondingNetworks(env === 'mainnet-beta');
|
||||||
} else {
|
} else {
|
||||||
setHasCorrespondingNetworks(false);
|
setHasCorrespondingNetworks(false);
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
}
|
|
||||||
setHasCorrespondingNetworks(true);
|
setHasCorrespondingNetworks(true);
|
||||||
}, [provider, env]);
|
}
|
||||||
|
}, [connected, env, chainId]);
|
||||||
|
|
||||||
return hasCorrespondingNetworks;
|
return { hasCorrespondingNetworks };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue