parent
46a85b8e65
commit
d1e0af0dbf
@ -1,3 +1,5 @@
|
|||||||
|
import { connectEthereumWallet } from '../support/ethereum-wallet';
|
||||||
|
|
||||||
const assetSelectField = 'select[name="asset"]';
|
const assetSelectField = 'select[name="asset"]';
|
||||||
const toAddressField = 'input[name="to"]';
|
const toAddressField = 'input[name="to"]';
|
||||||
const amountField = 'input[name="amount"]';
|
const amountField = 'input[name="amount"]';
|
||||||
@ -18,6 +20,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('unable to select assets not enabled', () => {
|
it('unable to select assets not enabled', () => {
|
||||||
|
connectEthereumWallet();
|
||||||
cy.getByTestId('deposit-submit').click();
|
cy.getByTestId('deposit-submit').click();
|
||||||
// Assets not enabled in mocks
|
// Assets not enabled in mocks
|
||||||
cy.get(assetSelectField + ' option:contains(Asset 2)').should('not.exist');
|
cy.get(assetSelectField + ' option:contains(Asset 2)').should('not.exist');
|
||||||
@ -26,6 +29,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('handles empty fields', () => {
|
it('handles empty fields', () => {
|
||||||
|
connectEthereumWallet();
|
||||||
// Submit form to trigger any empty validation messages
|
// Submit form to trigger any empty validation messages
|
||||||
cy.getByTestId('deposit-submit').click();
|
cy.getByTestId('deposit-submit').click();
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { aliasQuery, mockConnectWallet } from '@vegaprotocol/cypress';
|
import { aliasQuery, mockConnectWallet } from '@vegaprotocol/cypress';
|
||||||
|
import { connectEthereumWallet } from '../support/ethereum-wallet';
|
||||||
import { generateNetworkParameters } from '../support/mocks/generate-network-parameters';
|
import { generateNetworkParameters } from '../support/mocks/generate-network-parameters';
|
||||||
|
|
||||||
const connectEthWalletBtn = 'connect-eth-wallet-btn';
|
const connectEthWalletBtn = 'connect-eth-wallet-btn';
|
||||||
@ -102,31 +103,30 @@ describe('ethereum wallet', { tags: '@smoke' }, () => {
|
|||||||
});
|
});
|
||||||
cy.mockGQLSubscription();
|
cy.mockGQLSubscription();
|
||||||
cy.get('main[data-testid="/portfolio"]').should('exist');
|
cy.get('main[data-testid="/portfolio"]').should('exist');
|
||||||
|
cy.connectVegaWallet();
|
||||||
cy.getByTestId('Withdrawals').click();
|
cy.getByTestId('Withdrawals').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can connect', () => {
|
it('can connect', () => {
|
||||||
cy.wait('@NetworkParams');
|
cy.wait('@NetworkParams');
|
||||||
|
cy.getByTestId('Deposits').click();
|
||||||
|
cy.getByTestId('deposit-button').click();
|
||||||
cy.getByTestId('connect-eth-wallet-btn').click();
|
cy.getByTestId('connect-eth-wallet-btn').click();
|
||||||
cy.getByTestId('web3-connector-list').should('exist');
|
cy.getByTestId('web3-connector-list').should('exist');
|
||||||
cy.getByTestId('web3-connector-MetaMask').click();
|
cy.getByTestId('web3-connector-MetaMask').click();
|
||||||
cy.getByTestId('web3-connector-list').should('not.exist');
|
cy.getByTestId('web3-connector-list').should('not.exist');
|
||||||
cy.getByTestId('tab-withdrawals').should('not.be.empty');
|
cy.getByTestId('tab-deposits').should('not.be.empty');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('able to disconnect eth wallet', () => {
|
it('able to disconnect eth wallet', () => {
|
||||||
const ethWalletAddress = Cypress.env('ETHEREUM_WALLET_ADDRESS');
|
const ethWalletAddress = Cypress.env('ETHEREUM_WALLET_ADDRESS');
|
||||||
cy.connectVegaWallet();
|
|
||||||
cy.getByTestId('Deposits').click();
|
cy.getByTestId('Deposits').click();
|
||||||
cy.getByTestId('deposit-button').click();
|
cy.getByTestId('deposit-button').click();
|
||||||
cy.get('#ethereum-address').should('have.value', ethWalletAddress).click();
|
connectEthereumWallet();
|
||||||
cy.getByTestId('dialog-content').within(() => {
|
cy.get('#ethereum-address').should('have.value', ethWalletAddress);
|
||||||
cy.get('p').should('have.text', `Connected with ${ethWalletAddress}`);
|
cy.getByTestId('disconnect-ethereum-wallet')
|
||||||
cy.getByTestId('disconnect-ethereum-wallet')
|
.should('have.text', 'Disconnect')
|
||||||
.should('have.text', 'Disconnect Ethereum Wallet')
|
.click();
|
||||||
.click();
|
|
||||||
});
|
|
||||||
cy.getByTestId('connect-eth-wallet-msg').should('exist');
|
|
||||||
cy.getByTestId(connectEthWalletBtn).should('exist');
|
cy.getByTestId(connectEthWalletBtn).should('exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -22,10 +22,11 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
|
|||||||
// Withdraw page requires vega wallet connection
|
// Withdraw page requires vega wallet connection
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
|
|
||||||
|
cy.getByTestId('withdraw-dialog-button').click();
|
||||||
|
|
||||||
// It also requires connection Ethereum wallet
|
// It also requires connection Ethereum wallet
|
||||||
connectEthereumWallet();
|
connectEthereumWallet();
|
||||||
|
|
||||||
cy.getByTestId('withdraw-dialog-button').click();
|
|
||||||
cy.wait('@Accounts');
|
cy.wait('@Accounts');
|
||||||
cy.wait('@Assets');
|
cy.wait('@Assets');
|
||||||
});
|
});
|
||||||
@ -78,10 +79,10 @@ describe('withdraw actions', { tags: '@regression' }, () => {
|
|||||||
// Withdraw page requires vega wallet connection
|
// Withdraw page requires vega wallet connection
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
|
|
||||||
// It also requires connection Ethereum wallet
|
cy.getByTestId('withdraw-dialog-button').click();
|
||||||
|
|
||||||
connectEthereumWallet();
|
connectEthereumWallet();
|
||||||
|
|
||||||
cy.getByTestId('withdraw-dialog-button').click();
|
|
||||||
cy.wait('@Accounts');
|
cy.wait('@Accounts');
|
||||||
cy.wait('@Assets');
|
cy.wait('@Assets');
|
||||||
cy.mockVegaWalletTransaction();
|
cy.mockVegaWalletTransaction();
|
||||||
|
@ -7,51 +7,48 @@ import {
|
|||||||
} from '@vegaprotocol/withdraws';
|
} from '@vegaprotocol/withdraws';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||||
import { Web3Container } from '@vegaprotocol/web3';
|
|
||||||
|
|
||||||
export const WithdrawalsContainer = () => {
|
export const WithdrawalsContainer = () => {
|
||||||
const { pending, completed, loading, error } = useWithdrawals();
|
const { pending, completed, loading, error } = useWithdrawals();
|
||||||
const openWithdrawDialog = useWithdrawalDialog((state) => state.open);
|
const openWithdrawDialog = useWithdrawalDialog((state) => state.open);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Web3Container>
|
<VegaWalletContainer>
|
||||||
<VegaWalletContainer>
|
<div className="h-full relative grid grid-rows-[1fr,min-content]">
|
||||||
<div className="h-full relative grid grid-rows-[1fr,min-content]">
|
<div className="h-full">
|
||||||
<div className="h-full">
|
<AsyncRenderer
|
||||||
<AsyncRenderer
|
data={{ pending, completed }}
|
||||||
data={{ pending, completed }}
|
loading={loading}
|
||||||
loading={loading}
|
error={error}
|
||||||
error={error}
|
render={({ pending, completed }) => (
|
||||||
render={({ pending, completed }) => (
|
<>
|
||||||
<>
|
{pending && pending.length > 0 && (
|
||||||
{pending && pending.length > 0 && (
|
<>
|
||||||
<>
|
<h4 className="pt-3 pb-1">{t('Pending withdrawals')}</h4>
|
||||||
<h4 className="pt-3 pb-1">{t('Pending withdrawals')}</h4>
|
<PendingWithdrawalsTable rowData={pending} />
|
||||||
<PendingWithdrawalsTable rowData={pending} />
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
{completed && completed.length > 0 && (
|
||||||
{completed && completed.length > 0 && (
|
<h4 className="pt-3 pb-1">{t('Withdrawal history')}</h4>
|
||||||
<h4 className="pt-3 pb-1">{t('Withdrawal history')}</h4>
|
)}
|
||||||
)}
|
<WithdrawalsTable
|
||||||
<WithdrawalsTable
|
data-testid="withdrawals-history"
|
||||||
data-testid="withdrawals-history"
|
rowData={completed}
|
||||||
rowData={completed}
|
/>
|
||||||
/>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
onClick={() => openWithdrawDialog()}
|
|
||||||
data-testid="withdraw-dialog-button"
|
|
||||||
>
|
|
||||||
{t('Make withdrawal')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</VegaWalletContainer>
|
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
|
||||||
</Web3Container>
|
<Button
|
||||||
|
size="sm"
|
||||||
|
onClick={() => openWithdrawDialog()}
|
||||||
|
data-testid="withdraw-dialog-button"
|
||||||
|
>
|
||||||
|
{t('Make withdrawal')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VegaWalletContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useMemo } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useEagerConnect } from '@vegaprotocol/wallet';
|
import { NetworkLoader, useEnvironment } from '@vegaprotocol/environment';
|
||||||
import { NetworkLoader } from '@vegaprotocol/environment';
|
|
||||||
import { Connectors } from '../../lib/vega-connectors';
|
|
||||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||||
|
import {
|
||||||
|
useEthereumConfig,
|
||||||
|
createConnectors,
|
||||||
|
Web3Provider as Web3ProviderInternal,
|
||||||
|
useWeb3ConnectStore,
|
||||||
|
} from '@vegaprotocol/web3';
|
||||||
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
interface AppLoaderProps {
|
interface AppLoaderProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@ -14,57 +19,87 @@ interface AppLoaderProps {
|
|||||||
* that must happen for it can be used
|
* that must happen for it can be used
|
||||||
*/
|
*/
|
||||||
export function AppLoader({ children }: AppLoaderProps) {
|
export function AppLoader({ children }: AppLoaderProps) {
|
||||||
// Get keys from vega wallet immediately
|
return <NetworkLoader cache={cacheConfig}>{children}</NetworkLoader>;
|
||||||
useEagerConnect(Connectors);
|
}
|
||||||
const cache: InMemoryCacheConfig = useMemo(
|
|
||||||
() => ({
|
export const Web3Provider = ({ children }: { children: ReactNode }) => {
|
||||||
typePolicies: {
|
const { config, loading, error } = useEthereumConfig();
|
||||||
Account: {
|
const { ETHEREUM_PROVIDER_URL } = useEnvironment();
|
||||||
keyFields: false,
|
const [connectors, initializeConnectors] = useWeb3ConnectStore((store) => [
|
||||||
fields: {
|
store.connectors,
|
||||||
balanceFormatted: {},
|
store.initialize,
|
||||||
},
|
]);
|
||||||
},
|
|
||||||
Instrument: {
|
useEffect(() => {
|
||||||
keyFields: false,
|
if (config?.chain_id) {
|
||||||
},
|
return initializeConnectors(
|
||||||
TradableInstrument: {
|
createConnectors(ETHEREUM_PROVIDER_URL, Number(config?.chain_id)),
|
||||||
keyFields: ['instrument'],
|
Number(config.chain_id)
|
||||||
},
|
);
|
||||||
Product: {
|
}
|
||||||
keyFields: ['settlementAsset', ['id']],
|
}, [config?.chain_id, ETHEREUM_PROVIDER_URL, initializeConnectors]);
|
||||||
},
|
|
||||||
MarketData: {
|
return (
|
||||||
keyFields: ['market', ['id']],
|
<AsyncRenderer
|
||||||
},
|
loading={loading}
|
||||||
Node: {
|
error={error}
|
||||||
keyFields: false,
|
data={connectors}
|
||||||
},
|
noDataCondition={(d) => {
|
||||||
Withdrawal: {
|
if (!d) return true;
|
||||||
fields: {
|
return d.length < 1;
|
||||||
pendingOnForeignChain: {
|
}}
|
||||||
read: (isPending = false) => isPending,
|
>
|
||||||
},
|
<Web3ProviderInternal connectors={connectors}>
|
||||||
},
|
<>{children}</>
|
||||||
},
|
</Web3ProviderInternal>
|
||||||
ERC20: {
|
</AsyncRenderer>
|
||||||
keyFields: ['contractAddress'],
|
);
|
||||||
},
|
};
|
||||||
PositionUpdate: {
|
|
||||||
keyFields: false,
|
const cacheConfig: InMemoryCacheConfig = {
|
||||||
},
|
typePolicies: {
|
||||||
AccountUpdate: {
|
Account: {
|
||||||
keyFields: false,
|
keyFields: false,
|
||||||
},
|
fields: {
|
||||||
Party: {
|
balanceFormatted: {},
|
||||||
keyFields: false,
|
},
|
||||||
},
|
},
|
||||||
Fees: {
|
Instrument: {
|
||||||
keyFields: false,
|
keyFields: false,
|
||||||
|
},
|
||||||
|
TradableInstrument: {
|
||||||
|
keyFields: ['instrument'],
|
||||||
|
},
|
||||||
|
Product: {
|
||||||
|
keyFields: ['settlementAsset', ['id']],
|
||||||
|
},
|
||||||
|
MarketData: {
|
||||||
|
keyFields: ['market', ['id']],
|
||||||
|
},
|
||||||
|
Node: {
|
||||||
|
keyFields: false,
|
||||||
|
},
|
||||||
|
Withdrawal: {
|
||||||
|
fields: {
|
||||||
|
pendingOnForeignChain: {
|
||||||
|
read: (isPending = false) => isPending,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
[]
|
ERC20: {
|
||||||
);
|
keyFields: ['contractAddress'],
|
||||||
return <NetworkLoader cache={cache}>{children}</NetworkLoader>;
|
},
|
||||||
}
|
PositionUpdate: {
|
||||||
|
keyFields: false,
|
||||||
|
},
|
||||||
|
AccountUpdate: {
|
||||||
|
keyFields: false,
|
||||||
|
},
|
||||||
|
Party: {
|
||||||
|
keyFields: false,
|
||||||
|
},
|
||||||
|
Fees: {
|
||||||
|
keyFields: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
@ -2,20 +2,25 @@ import Head from 'next/head';
|
|||||||
import type { AppProps } from 'next/app';
|
import type { AppProps } from 'next/app';
|
||||||
import { Navbar } from '../components/navbar';
|
import { Navbar } from '../components/navbar';
|
||||||
import { t, ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
import { t, ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||||
import { VegaWalletProvider } from '@vegaprotocol/wallet';
|
import {
|
||||||
|
useEagerConnect as useVegaEagerConnect,
|
||||||
|
VegaWalletProvider,
|
||||||
|
} from '@vegaprotocol/wallet';
|
||||||
import {
|
import {
|
||||||
EnvironmentProvider,
|
EnvironmentProvider,
|
||||||
envTriggerMapping,
|
envTriggerMapping,
|
||||||
Networks,
|
Networks,
|
||||||
useEnvironment,
|
useEnvironment,
|
||||||
} from '@vegaprotocol/environment';
|
} from '@vegaprotocol/environment';
|
||||||
import { AppLoader } from '../components/app-loader';
|
import { AppLoader, Web3Provider } from '../components/app-loader';
|
||||||
import './styles.css';
|
import './styles.css';
|
||||||
import { usePageTitleStore } from '../stores';
|
import { usePageTitleStore } from '../stores';
|
||||||
import { Footer } from '../components/footer';
|
import { Footer } from '../components/footer';
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import DialogsContainer from './dialogs-container';
|
import DialogsContainer from './dialogs-container';
|
||||||
import { HashRouter, useLocation } from 'react-router-dom';
|
import { HashRouter, useLocation } from 'react-router-dom';
|
||||||
|
import { Connectors } from '../lib/vega-connectors';
|
||||||
|
import { useEagerConnect as useEthereumEagerConnect } from '@vegaprotocol/web3';
|
||||||
|
|
||||||
const DEFAULT_TITLE = t('Welcome to Vega trading!');
|
const DEFAULT_TITLE = t('Welcome to Vega trading!');
|
||||||
|
|
||||||
@ -52,20 +57,25 @@ function AppBody({ Component }: AppProps) {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
</Head>
|
</Head>
|
||||||
<Title />
|
<Title />
|
||||||
<div className="h-full relative dark:bg-black dark:text-white z-0 grid grid-rows-[min-content,1fr,min-content]">
|
<VegaWalletProvider>
|
||||||
<AppLoader>
|
<AppLoader>
|
||||||
<Navbar
|
<Web3Provider>
|
||||||
theme={theme}
|
<div className="h-full relative dark:bg-black dark:text-white z-0 grid grid-rows-[min-content,1fr,min-content]">
|
||||||
toggleTheme={toggleTheme}
|
<Navbar
|
||||||
navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'}
|
theme={theme}
|
||||||
/>
|
toggleTheme={toggleTheme}
|
||||||
<main data-testid={location.pathname}>
|
navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'}
|
||||||
<Component />
|
/>
|
||||||
</main>
|
<main data-testid={location.pathname}>
|
||||||
<Footer />
|
<Component />
|
||||||
<DialogsContainer />
|
</main>
|
||||||
|
<Footer />
|
||||||
|
<DialogsContainer />
|
||||||
|
<MaybeConnectEagerly />
|
||||||
|
</div>
|
||||||
|
</Web3Provider>
|
||||||
</AppLoader>
|
</AppLoader>
|
||||||
</div>
|
</VegaWalletProvider>
|
||||||
</ThemeContext.Provider>
|
</ThemeContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -85,12 +95,16 @@ function VegaTradingApp(props: AppProps) {
|
|||||||
return (
|
return (
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<EnvironmentProvider>
|
<EnvironmentProvider>
|
||||||
<VegaWalletProvider>
|
<AppBody {...props} />
|
||||||
<AppBody {...props} />
|
|
||||||
</VegaWalletProvider>
|
|
||||||
</EnvironmentProvider>
|
</EnvironmentProvider>
|
||||||
</HashRouter>
|
</HashRouter>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VegaTradingApp;
|
export default VegaTradingApp;
|
||||||
|
|
||||||
|
const MaybeConnectEagerly = () => {
|
||||||
|
useVegaEagerConnect(Connectors);
|
||||||
|
useEthereumEagerConnect();
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
@ -7,7 +7,6 @@ import { Connectors } from '../lib/vega-connectors';
|
|||||||
import { RiskNoticeDialog } from '../components/risk-notice-dialog';
|
import { RiskNoticeDialog } from '../components/risk-notice-dialog';
|
||||||
import { WithdrawalDialog } from '@vegaprotocol/withdraws';
|
import { WithdrawalDialog } from '@vegaprotocol/withdraws';
|
||||||
import { DepositDialog } from '@vegaprotocol/deposits';
|
import { DepositDialog } from '@vegaprotocol/deposits';
|
||||||
import { Web3Container } from '@vegaprotocol/web3';
|
|
||||||
import { Web3ConnectUncontrolledDialog } from '@vegaprotocol/web3';
|
import { Web3ConnectUncontrolledDialog } from '@vegaprotocol/web3';
|
||||||
import { WelcomeNoticeDialog } from '../components/welcome-notice';
|
import { WelcomeNoticeDialog } from '../components/welcome-notice';
|
||||||
|
|
||||||
@ -25,9 +24,7 @@ const DialogsContainer = () => {
|
|||||||
<RiskNoticeDialog />
|
<RiskNoticeDialog />
|
||||||
<DepositDialog />
|
<DepositDialog />
|
||||||
<Web3ConnectUncontrolledDialog />
|
<Web3ConnectUncontrolledDialog />
|
||||||
<Web3Container childrenOnly connectEagerly>
|
<WithdrawalDialog />
|
||||||
<WithdrawalDialog />
|
|
||||||
</Web3Container>
|
|
||||||
<WelcomeNoticeDialog />
|
<WelcomeNoticeDialog />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
||||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Web3Container } from '@vegaprotocol/web3';
|
|
||||||
import { DepositManager } from './deposit-manager';
|
import { DepositManager } from './deposit-manager';
|
||||||
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
|
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { enabledAssetsProvider } from '@vegaprotocol/assets';
|
import { enabledAssetsProvider } from '@vegaprotocol/assets';
|
||||||
@ -24,14 +23,12 @@ export const DepositContainer = ({
|
|||||||
return (
|
return (
|
||||||
<AsyncRenderer data={data} loading={loading} error={error}>
|
<AsyncRenderer data={data} loading={loading} error={error}>
|
||||||
{data && data.length ? (
|
{data && data.length ? (
|
||||||
<Web3Container connectEagerly>
|
<DepositManager
|
||||||
<DepositManager
|
assetId={assetId}
|
||||||
assetId={assetId}
|
assets={data}
|
||||||
assets={data}
|
isFaucetable={VEGA_ENV !== Networks.MAINNET}
|
||||||
isFaucetable={VEGA_ENV !== Networks.MAINNET}
|
setDialogStyleProps={setDialogStyleProps}
|
||||||
setDialogStyleProps={setDialogStyleProps}
|
/>
|
||||||
/>
|
|
||||||
</Web3Container>
|
|
||||||
) : (
|
) : (
|
||||||
<Splash>
|
<Splash>
|
||||||
<p>{t('No assets on this network')}</p>
|
<p>{t('No assets on this network')}</p>
|
||||||
|
@ -4,7 +4,7 @@ import type { Intent } from '@vegaprotocol/ui-toolkit';
|
|||||||
import { Dialog } from '@vegaprotocol/ui-toolkit';
|
import { Dialog } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { DepositContainer } from './deposit-container';
|
import { DepositContainer } from './deposit-container';
|
||||||
import { useWeb3ConnectDialog } from '@vegaprotocol/web3';
|
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -41,7 +41,7 @@ const DEFAULT_STYLE: DepositDialogStyleProps = {
|
|||||||
|
|
||||||
export const DepositDialog = () => {
|
export const DepositDialog = () => {
|
||||||
const { assetId, isOpen, open, close } = useDepositDialog();
|
const { assetId, isOpen, open, close } = useDepositDialog();
|
||||||
const connectWalletDialogIsOpen = useWeb3ConnectDialog(
|
const connectWalletDialogIsOpen = useWeb3ConnectStore(
|
||||||
(state) => state.isOpen
|
(state) => state.isOpen
|
||||||
);
|
);
|
||||||
const [dialogStyleProps, _setDialogStyleProps] = useState(DEFAULT_STYLE);
|
const [dialogStyleProps, _setDialogStyleProps] = useState(DEFAULT_STYLE);
|
||||||
|
@ -10,6 +10,8 @@ import type { AssetFieldsFragment } from '@vegaprotocol/assets';
|
|||||||
jest.mock('@vegaprotocol/wallet');
|
jest.mock('@vegaprotocol/wallet');
|
||||||
jest.mock('@web3-react/core');
|
jest.mock('@web3-react/core');
|
||||||
|
|
||||||
|
const mockConnector = { deactivate: jest.fn() };
|
||||||
|
|
||||||
function generateAsset(): AssetFieldsFragment {
|
function generateAsset(): AssetFieldsFragment {
|
||||||
return {
|
return {
|
||||||
__typename: 'Asset',
|
__typename: 'Asset',
|
||||||
@ -53,7 +55,11 @@ beforeEach(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
(useVegaWallet as jest.Mock).mockReturnValue({ pubKey: null });
|
(useVegaWallet as jest.Mock).mockReturnValue({ pubKey: null });
|
||||||
(useWeb3React as jest.Mock).mockReturnValue({ account: MOCK_ETH_ADDRESS });
|
(useWeb3React as jest.Mock).mockReturnValue({
|
||||||
|
isActive: true,
|
||||||
|
account: MOCK_ETH_ADDRESS,
|
||||||
|
connector: mockConnector,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Deposit form', () => {
|
describe('Deposit form', () => {
|
||||||
@ -192,7 +198,11 @@ describe('Deposit form', () => {
|
|||||||
mockUseVegaWallet.mockReturnValue({ pubKey: null });
|
mockUseVegaWallet.mockReturnValue({ pubKey: null });
|
||||||
|
|
||||||
const mockUseWeb3React = useWeb3React as jest.Mock;
|
const mockUseWeb3React = useWeb3React as jest.Mock;
|
||||||
mockUseWeb3React.mockReturnValue({ account: undefined });
|
mockUseWeb3React.mockReturnValue({
|
||||||
|
account: MOCK_ETH_ADDRESS,
|
||||||
|
isActive: true,
|
||||||
|
connector: mockConnector,
|
||||||
|
});
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<DepositForm
|
<DepositForm
|
||||||
@ -219,7 +229,11 @@ describe('Deposit form', () => {
|
|||||||
|
|
||||||
const account = '0x72c22822A19D20DE7e426fB84aa047399Ddd8853';
|
const account = '0x72c22822A19D20DE7e426fB84aa047399Ddd8853';
|
||||||
const mockUseWeb3React = useWeb3React as jest.Mock;
|
const mockUseWeb3React = useWeb3React as jest.Mock;
|
||||||
mockUseWeb3React.mockReturnValue({ account });
|
mockUseWeb3React.mockReturnValue({
|
||||||
|
account,
|
||||||
|
isActive: true,
|
||||||
|
connector: mockConnector,
|
||||||
|
});
|
||||||
|
|
||||||
const balance = new BigNumber(50);
|
const balance = new BigNumber(50);
|
||||||
const max = new BigNumber(20);
|
const max = new BigNumber(20);
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
minSafe,
|
minSafe,
|
||||||
maxSafe,
|
maxSafe,
|
||||||
addDecimal,
|
addDecimal,
|
||||||
|
useLocalStorage,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@ -19,13 +20,17 @@ import {
|
|||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import { Web3WalletInput } from '@vegaprotocol/web3';
|
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import type { ReactNode } from 'react';
|
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Controller, useForm, useWatch } from 'react-hook-form';
|
import { Controller, useForm, useWatch } from 'react-hook-form';
|
||||||
import { DepositLimits } from './deposit-limits';
|
import { DepositLimits } from './deposit-limits';
|
||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
|
import {
|
||||||
|
ETHEREUM_EAGER_CONNECT,
|
||||||
|
useWeb3ConnectStore,
|
||||||
|
ChainIdMap,
|
||||||
|
} from '@vegaprotocol/web3';
|
||||||
|
|
||||||
interface FormFields {
|
interface FormFields {
|
||||||
asset: string;
|
asset: string;
|
||||||
@ -137,10 +142,19 @@ export const DepositForm = ({
|
|||||||
label={t('From (Ethereum address)')}
|
label={t('From (Ethereum address)')}
|
||||||
labelFor="ethereum-address"
|
labelFor="ethereum-address"
|
||||||
>
|
>
|
||||||
<Web3WalletInput
|
<Input
|
||||||
inputProps={{
|
id="ethereum-address"
|
||||||
id: 'ethereum-address',
|
{...register('from', {
|
||||||
...register('from', { validate: { required, ethereumAddress } }),
|
validate: {
|
||||||
|
required,
|
||||||
|
ethereumAddress,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<EthereumButton
|
||||||
|
clearAddress={() => {
|
||||||
|
setValue('from', '');
|
||||||
|
clearErrors('from');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{errors.from?.message && (
|
{errors.from?.message && (
|
||||||
@ -291,12 +305,38 @@ const FormButton = ({
|
|||||||
allowance,
|
allowance,
|
||||||
onApproveClick,
|
onApproveClick,
|
||||||
}: FormButtonProps) => {
|
}: FormButtonProps) => {
|
||||||
|
const { open, desiredChainId } = useWeb3ConnectStore((store) => ({
|
||||||
|
open: store.open,
|
||||||
|
desiredChainId: store.desiredChainId,
|
||||||
|
}));
|
||||||
|
const { isActive, chainId } = useWeb3React();
|
||||||
const approved =
|
const approved =
|
||||||
allowance && allowance.isGreaterThan(0) && amount.isLessThan(allowance);
|
allowance && allowance.isGreaterThan(0) && amount.isLessThan(allowance);
|
||||||
let button = null;
|
let button = null;
|
||||||
let message: ReactNode = '';
|
let message: ReactNode = '';
|
||||||
|
|
||||||
if (!selectedAsset) {
|
if (!isActive) {
|
||||||
|
button = (
|
||||||
|
<Button onClick={open} data-testid="connect-eth-wallet-btn">
|
||||||
|
{t('Connect Ethereum wallet')}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
} else if (chainId !== desiredChainId) {
|
||||||
|
console.log(chainId, desiredChainId);
|
||||||
|
const chainName = desiredChainId ? ChainIdMap[desiredChainId] : 'Unknown';
|
||||||
|
message = t(`This app only works on ${chainName}.`);
|
||||||
|
button = (
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
data-testid="deposit-submit"
|
||||||
|
variant="primary"
|
||||||
|
fill={true}
|
||||||
|
disabled={true}
|
||||||
|
>
|
||||||
|
{t('Deposit')}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
} else if (!selectedAsset) {
|
||||||
button = (
|
button = (
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
@ -346,19 +386,37 @@ const FormButton = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface UseButtonProps {
|
type UseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
|
||||||
children: ReactNode;
|
|
||||||
onClick: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const UseButton = ({ children, onClick }: UseButtonProps) => {
|
const UseButton = (props: UseButtonProps) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
{...props}
|
||||||
type="button"
|
type="button"
|
||||||
className="ml-auto text-sm absolute top-0 right-0 underline"
|
className="ml-auto text-sm absolute top-0 right-0 underline"
|
||||||
onClick={onClick}
|
/>
|
||||||
>
|
);
|
||||||
{children}
|
};
|
||||||
</button>
|
|
||||||
|
const EthereumButton = ({ clearAddress }: { clearAddress: () => void }) => {
|
||||||
|
const openDialog = useWeb3ConnectStore((state) => state.open);
|
||||||
|
const { isActive, connector } = useWeb3React();
|
||||||
|
const [, , removeEagerConnector] = useLocalStorage(ETHEREUM_EAGER_CONNECT);
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
return <UseButton onClick={openDialog}>{t('Connect')}</UseButton>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UseButton
|
||||||
|
onClick={() => {
|
||||||
|
connector.deactivate();
|
||||||
|
clearAddress();
|
||||||
|
removeEagerConnector();
|
||||||
|
}}
|
||||||
|
data-testid="disconnect-ethereum-wallet"
|
||||||
|
>
|
||||||
|
{t('Disconnect')}
|
||||||
|
</UseButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
export * from './lib/constants';
|
||||||
export * from './lib/ethereum-error';
|
export * from './lib/ethereum-error';
|
||||||
export * from './lib/use-bridge-contract';
|
export * from './lib/use-bridge-contract';
|
||||||
|
export * from './lib/use-eager-connect';
|
||||||
export * from './lib/use-token-contract';
|
export * from './lib/use-token-contract';
|
||||||
export * from './lib/use-token-decimals';
|
export * from './lib/use-token-decimals';
|
||||||
export * from './lib/use-ethereum-config';
|
export * from './lib/use-ethereum-config';
|
||||||
@ -7,6 +9,7 @@ export * from './lib/use-ethereum-read-contract';
|
|||||||
export * from './lib/use-ethereum-transaction';
|
export * from './lib/use-ethereum-transaction';
|
||||||
export * from './lib/ethereum-transaction-dialog';
|
export * from './lib/ethereum-transaction-dialog';
|
||||||
export * from './lib/web3-provider';
|
export * from './lib/web3-provider';
|
||||||
|
export * from './lib/web3-connectors';
|
||||||
export * from './lib/web3-connect-dialog';
|
export * from './lib/web3-connect-dialog';
|
||||||
export * from './lib/web3-wallet-input';
|
export * from './lib/web3-connect-store';
|
||||||
export * from './lib/web3-container';
|
export * from './lib/web3-container';
|
||||||
|
6
libs/web3/src/lib/constants.ts
Normal file
6
libs/web3/src/lib/constants.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export const ChainIdMap: {
|
||||||
|
[id: number]: string;
|
||||||
|
} = {
|
||||||
|
11155111: 'Sepolia',
|
||||||
|
1: 'Mainnet',
|
||||||
|
};
|
43
libs/web3/src/lib/use-eager-connect.ts
Normal file
43
libs/web3/src/lib/use-eager-connect.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||||
|
import type { Web3ReactHooks } from '@web3-react/core';
|
||||||
|
import { MetaMask } from '@web3-react/metamask';
|
||||||
|
import type { Connector } from '@web3-react/types';
|
||||||
|
import { WalletConnect } from '@web3-react/walletconnect';
|
||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
import { useWeb3ConnectStore } from './web3-connect-store';
|
||||||
|
|
||||||
|
export const ETHEREUM_EAGER_CONNECT = 'ethereum-eager-connect';
|
||||||
|
|
||||||
|
export const useEagerConnect = () => {
|
||||||
|
const connectors = useWeb3ConnectStore((store) => store.connectors);
|
||||||
|
const [eagerConnector] = useLocalStorage(ETHEREUM_EAGER_CONNECT);
|
||||||
|
const attemptedRef = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (attemptedRef.current || 'Cypress' in window) return;
|
||||||
|
|
||||||
|
const stored = getConnector(connectors, eagerConnector);
|
||||||
|
|
||||||
|
// found a valid connection option
|
||||||
|
if (stored && stored[0].connectEagerly) {
|
||||||
|
stored[0].connectEagerly();
|
||||||
|
}
|
||||||
|
|
||||||
|
attemptedRef.current = true;
|
||||||
|
}, [eagerConnector, connectors]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getConnector = (
|
||||||
|
connectors: [Connector, Web3ReactHooks][],
|
||||||
|
connectorName?: string | null
|
||||||
|
) => {
|
||||||
|
if (connectorName === 'MetaMask') {
|
||||||
|
return connectors.find(([c]) => c instanceof MetaMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectorName === 'WalletConnect') {
|
||||||
|
return connectors.find(([c]) => c instanceof WalletConnect);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
@ -5,7 +5,9 @@ import { initializeConnector } from '@web3-react/core';
|
|||||||
import { MetaMask } from '@web3-react/metamask';
|
import { MetaMask } from '@web3-react/metamask';
|
||||||
import type { Connector } from '@web3-react/types';
|
import type { Connector } from '@web3-react/types';
|
||||||
|
|
||||||
const [foo, fooHooks] = initializeConnector((actions) => new MetaMask(actions));
|
const [foo, fooHooks] = initializeConnector((actions) => {
|
||||||
|
return new MetaMask(actions);
|
||||||
|
});
|
||||||
|
|
||||||
const connectors: [Connector, Web3ReactHooks][] = [[foo, fooHooks]];
|
const connectors: [Connector, Web3ReactHooks][] = [[foo, fooHooks]];
|
||||||
|
|
||||||
|
@ -1,34 +1,16 @@
|
|||||||
import create from 'zustand';
|
import { t, useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
|
||||||
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
|
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
import { MetaMask } from '@web3-react/metamask';
|
import { MetaMask } from '@web3-react/metamask';
|
||||||
import { WalletConnect } from '@web3-react/walletconnect';
|
import { WalletConnect } from '@web3-react/walletconnect';
|
||||||
import type { Web3ReactHooks } from '@web3-react/core';
|
|
||||||
import type { Connector } from '@web3-react/types';
|
import type { Connector } from '@web3-react/types';
|
||||||
|
import { ETHEREUM_EAGER_CONNECT } from './use-eager-connect';
|
||||||
interface State {
|
import type { Web3ReactHooks } from '@web3-react/core';
|
||||||
isOpen: boolean;
|
import { useWeb3ConnectStore } from './web3-connect-store';
|
||||||
connectors: [Connector, Web3ReactHooks][];
|
|
||||||
desiredChainId?: number;
|
|
||||||
}
|
|
||||||
interface Actions {
|
|
||||||
open: (connectors: State['connectors'], desiredChainId?: number) => void;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useWeb3ConnectDialog = create<State & Actions>((set) => ({
|
|
||||||
isOpen: false,
|
|
||||||
connectors: [],
|
|
||||||
open: (connectors, desiredChainId) =>
|
|
||||||
set(() => ({ isOpen: true, connectors, desiredChainId })),
|
|
||||||
close: () =>
|
|
||||||
set(() => ({ isOpen: false, connectors: [], desiredChainId: undefined })),
|
|
||||||
}));
|
|
||||||
|
|
||||||
interface Web3ConnectDialogProps {
|
interface Web3ConnectDialogProps {
|
||||||
dialogOpen: boolean;
|
dialogOpen: boolean;
|
||||||
setDialogOpen: (isOpen: boolean) => void;
|
setDialogOpen: (isOpen: boolean) => void;
|
||||||
connectors: State['connectors'];
|
connectors: [Connector, Web3ReactHooks][];
|
||||||
desiredChainId?: number;
|
desiredChainId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +20,8 @@ export const Web3ConnectDialog = ({
|
|||||||
connectors,
|
connectors,
|
||||||
desiredChainId,
|
desiredChainId,
|
||||||
}: Web3ConnectDialogProps) => {
|
}: Web3ConnectDialogProps) => {
|
||||||
|
const [, setEagerConnector] = useLocalStorage(ETHEREUM_EAGER_CONNECT);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={dialogOpen}
|
open={dialogOpen}
|
||||||
@ -55,6 +39,7 @@ export const Web3ConnectDialog = ({
|
|||||||
data-testid={`web3-connector-${info.name}`}
|
data-testid={`web3-connector-${info.name}`}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await connector.activate(desiredChainId);
|
await connector.activate(desiredChainId);
|
||||||
|
setEagerConnector(info.name);
|
||||||
setDialogOpen(false);
|
setDialogOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -69,17 +54,16 @@ export const Web3ConnectDialog = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const Web3ConnectUncontrolledDialog = () => {
|
export const Web3ConnectUncontrolledDialog = () => {
|
||||||
const { isOpen, connectors, desiredChainId, open, close } =
|
const { isOpen, connectors, open, close, desiredChainId } =
|
||||||
useWeb3ConnectDialog();
|
useWeb3ConnectStore();
|
||||||
|
const onChange = (isOpen: boolean) => (isOpen ? open() : close());
|
||||||
const onChange = (isOpen: boolean) =>
|
|
||||||
isOpen ? open(connectors, desiredChainId) : close();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Web3ConnectDialog
|
<Web3ConnectDialog
|
||||||
dialogOpen={isOpen}
|
dialogOpen={isOpen}
|
||||||
setDialogOpen={onChange}
|
setDialogOpen={onChange}
|
||||||
connectors={connectors}
|
connectors={connectors}
|
||||||
|
desiredChainId={desiredChainId}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
29
libs/web3/src/lib/web3-connect-store.ts
Normal file
29
libs/web3/src/lib/web3-connect-store.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import create from 'zustand';
|
||||||
|
import type { MetaMask } from '@web3-react/metamask';
|
||||||
|
import type { WalletConnect } from '@web3-react/walletconnect';
|
||||||
|
import type { Web3ReactHooks } from '@web3-react/core';
|
||||||
|
import type { Connector } from '@web3-react/types';
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
isOpen: boolean;
|
||||||
|
connectors: [Connector, Web3ReactHooks][];
|
||||||
|
desiredChainId?: number;
|
||||||
|
}
|
||||||
|
interface Actions {
|
||||||
|
initialize: (
|
||||||
|
connectors: [MetaMask | WalletConnect, Web3ReactHooks][],
|
||||||
|
desiredChainId: number
|
||||||
|
) => void;
|
||||||
|
open: () => void;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useWeb3ConnectStore = create<State & Actions>((set) => ({
|
||||||
|
isOpen: false,
|
||||||
|
connectors: [],
|
||||||
|
initialize: (connectors, desiredChainId) => {
|
||||||
|
set({ connectors, desiredChainId });
|
||||||
|
},
|
||||||
|
open: () => set(() => ({ isOpen: true })),
|
||||||
|
close: () => set(() => ({ isOpen: false })),
|
||||||
|
}));
|
@ -6,7 +6,7 @@ import { t } from '@vegaprotocol/react-helpers';
|
|||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
import { Web3Provider } from './web3-provider';
|
import { Web3Provider } from './web3-provider';
|
||||||
import { useEthereumConfig } from './use-ethereum-config';
|
import { useEthereumConfig } from './use-ethereum-config';
|
||||||
import { useWeb3ConnectDialog } from './web3-connect-dialog';
|
import { useWeb3ConnectStore } from './web3-connect-store';
|
||||||
import { createConnectors } from './web3-connectors';
|
import { createConnectors } from './web3-connectors';
|
||||||
|
|
||||||
interface Web3ContainerProps {
|
interface Web3ContainerProps {
|
||||||
@ -62,7 +62,7 @@ export const Web3Content = ({
|
|||||||
connectors,
|
connectors,
|
||||||
}: Web3ContentProps) => {
|
}: Web3ContentProps) => {
|
||||||
const { isActive, error, connector, chainId } = useWeb3React();
|
const { isActive, error, connector, chainId } = useWeb3React();
|
||||||
const openDialog = useWeb3ConnectDialog((state) => state.open);
|
const openDialog = useWeb3ConnectStore((state) => state.open);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
@ -98,10 +98,7 @@ export const Web3Content = ({
|
|||||||
<p data-testid="connect-eth-wallet-msg" className="mb-4">
|
<p data-testid="connect-eth-wallet-msg" className="mb-4">
|
||||||
{t('Connect your Ethereum wallet')}
|
{t('Connect your Ethereum wallet')}
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button onClick={openDialog} data-testid="connect-eth-wallet-btn">
|
||||||
onClick={() => openDialog(connectors, chainId)}
|
|
||||||
data-testid="connect-eth-wallet-btn"
|
|
||||||
>
|
|
||||||
{t('Connect')}
|
{t('Connect')}
|
||||||
</Button>
|
</Button>
|
||||||
</SplashWrapper>
|
</SplashWrapper>
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
import type { ComponentProps } from 'react';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { useWeb3React } from '@web3-react/core';
|
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
|
||||||
import { Button, Input, Dialog } from '@vegaprotocol/ui-toolkit';
|
|
||||||
|
|
||||||
type Web3WalletInputProps = {
|
|
||||||
inputProps: Partial<
|
|
||||||
Omit<
|
|
||||||
ComponentProps<typeof Input>,
|
|
||||||
'appendIconName' | 'prependIconName' | 'appendElement' | 'prependElement'
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
||||||
const noop = () => {};
|
|
||||||
|
|
||||||
export const Web3WalletInput = ({ inputProps }: Web3WalletInputProps) => {
|
|
||||||
const [isDialogOpen, setDialogOpen] = useState(false);
|
|
||||||
const { account, connector } = useWeb3React();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Input
|
|
||||||
{...inputProps}
|
|
||||||
appendIconName="chevron-down"
|
|
||||||
className="cursor-pointer select-none"
|
|
||||||
onChange={noop}
|
|
||||||
onClick={() => setDialogOpen(true)}
|
|
||||||
/>
|
|
||||||
<Dialog open={isDialogOpen} onChange={setDialogOpen} size="small">
|
|
||||||
<p className="mb-2">
|
|
||||||
{t('Connected with ')}
|
|
||||||
<span className="font-mono">{account}</span>
|
|
||||||
</p>
|
|
||||||
<Button
|
|
||||||
onClick={() => connector.deactivate()}
|
|
||||||
data-testid="disconnect-ethereum-wallet"
|
|
||||||
>
|
|
||||||
{t('Disconnect Ethereum Wallet')}
|
|
||||||
</Button>
|
|
||||||
</Dialog>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
@ -37,16 +37,18 @@ export const useWithdrawAsset = (
|
|||||||
: new BigNumber(0);
|
: new BigNumber(0);
|
||||||
// Query collateral bridge for threshold for selected asset
|
// Query collateral bridge for threshold for selected asset
|
||||||
// and subsequent delay if withdrawal amount is larger than it
|
// and subsequent delay if withdrawal amount is larger than it
|
||||||
let threshold;
|
let threshold = new BigNumber(0);
|
||||||
let delay;
|
let delay = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await Promise.all([getThreshold(asset), getDelay()]);
|
const result = await Promise.all([getThreshold(asset), getDelay()]);
|
||||||
threshold = result[0];
|
threshold = result[0];
|
||||||
delay = result[1];
|
delay = result[1];
|
||||||
update({ asset, balance, min, threshold, delay });
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
captureException(err);
|
captureException(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update({ asset, balance, min, threshold, delay });
|
||||||
},
|
},
|
||||||
[accounts, assets, update, getThreshold, getDelay]
|
[accounts, assets, update, getThreshold, getDelay]
|
||||||
);
|
);
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
t,
|
t,
|
||||||
removeDecimal,
|
removeDecimal,
|
||||||
required,
|
required,
|
||||||
|
useLocalStorage,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { isAssetTypeERC20 } from '@vegaprotocol/assets';
|
import { isAssetTypeERC20 } from '@vegaprotocol/assets';
|
||||||
import {
|
import {
|
||||||
@ -16,10 +17,14 @@ import {
|
|||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
import type { ButtonHTMLAttributes } from 'react';
|
||||||
import { useForm, Controller, useWatch } from 'react-hook-form';
|
import { useForm, Controller, useWatch } from 'react-hook-form';
|
||||||
import type { WithdrawalArgs } from './use-create-withdraw';
|
import type { WithdrawalArgs } from './use-create-withdraw';
|
||||||
import { WithdrawLimits } from './withdraw-limits';
|
import { WithdrawLimits } from './withdraw-limits';
|
||||||
|
import {
|
||||||
|
ETHEREUM_EAGER_CONNECT,
|
||||||
|
useWeb3ConnectStore,
|
||||||
|
} from '@vegaprotocol/web3';
|
||||||
|
|
||||||
interface FormFields {
|
interface FormFields {
|
||||||
asset: string;
|
asset: string;
|
||||||
@ -133,16 +138,12 @@ export const WithdrawForm = ({
|
|||||||
label={t('To (Ethereum address)')}
|
label={t('To (Ethereum address)')}
|
||||||
labelFor="ethereum-address"
|
labelFor="ethereum-address"
|
||||||
>
|
>
|
||||||
{address && (
|
<EthereumButton
|
||||||
<UseButton
|
clearAddress={() => {
|
||||||
onClick={() => {
|
setValue('to', '');
|
||||||
setValue('to', address);
|
clearErrors('to');
|
||||||
clearErrors('to');
|
}}
|
||||||
}}
|
/>
|
||||||
>
|
|
||||||
{t('Use connected')}
|
|
||||||
</UseButton>
|
|
||||||
)}
|
|
||||||
<Input
|
<Input
|
||||||
id="ethereum-address"
|
id="ethereum-address"
|
||||||
data-testid="eth-address-input"
|
data-testid="eth-address-input"
|
||||||
@ -198,7 +199,12 @@ export const WithdrawForm = ({
|
|||||||
</UseButton>
|
</UseButton>
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<Button data-testid="submit-withdrawal" type="submit" variant="primary">
|
<Button
|
||||||
|
data-testid="submit-withdrawal"
|
||||||
|
type="submit"
|
||||||
|
variant="primary"
|
||||||
|
fill={true}
|
||||||
|
>
|
||||||
Release funds
|
Release funds
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
@ -206,18 +212,41 @@ export const WithdrawForm = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface UseButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
type UseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
|
||||||
children: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const UseButton = ({ children, ...rest }: UseButtonProps) => {
|
const UseButton = (props: UseButtonProps) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
{...rest}
|
{...props}
|
||||||
type="button"
|
type="button"
|
||||||
className="ml-auto text-sm absolute top-0 right-0 underline"
|
className="ml-auto text-sm absolute top-0 right-0 underline"
|
||||||
>
|
/>
|
||||||
{children}
|
);
|
||||||
</button>
|
};
|
||||||
|
|
||||||
|
const EthereumButton = ({ clearAddress }: { clearAddress: () => void }) => {
|
||||||
|
const openDialog = useWeb3ConnectStore((state) => state.open);
|
||||||
|
const { isActive, connector } = useWeb3React();
|
||||||
|
const [, , removeEagerConnector] = useLocalStorage(ETHEREUM_EAGER_CONNECT);
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
return (
|
||||||
|
<UseButton onClick={openDialog} data-testid="connect-eth-wallet-btn">
|
||||||
|
{t('Connect')}
|
||||||
|
</UseButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UseButton
|
||||||
|
onClick={() => {
|
||||||
|
connector.deactivate();
|
||||||
|
clearAddress();
|
||||||
|
removeEagerConnector();
|
||||||
|
}}
|
||||||
|
data-testid="disconnect-ethereum-wallet"
|
||||||
|
>
|
||||||
|
{t('Disconnect')}
|
||||||
|
</UseButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -6,8 +6,7 @@ import { useCompleteWithdraw } from './use-complete-withdraw';
|
|||||||
import { useCreateWithdraw } from './use-create-withdraw';
|
import { useCreateWithdraw } from './use-create-withdraw';
|
||||||
import { WithdrawFormContainer } from './withdraw-form-container';
|
import { WithdrawFormContainer } from './withdraw-form-container';
|
||||||
import { WithdrawalFeedback } from './withdrawal-feedback';
|
import { WithdrawalFeedback } from './withdrawal-feedback';
|
||||||
import { Web3Container } from '@vegaprotocol/web3';
|
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
|
||||||
import { useWeb3ConnectDialog } from '@vegaprotocol/web3';
|
|
||||||
interface State {
|
interface State {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
assetId?: string;
|
assetId?: string;
|
||||||
@ -30,7 +29,7 @@ export const WithdrawalDialog = () => {
|
|||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
const createWithdraw = useCreateWithdraw();
|
const createWithdraw = useCreateWithdraw();
|
||||||
const completeWithdraw = useCompleteWithdraw();
|
const completeWithdraw = useCompleteWithdraw();
|
||||||
const connectWalletDialogIsOpen = useWeb3ConnectDialog(
|
const connectWalletDialogIsOpen = useWeb3ConnectStore(
|
||||||
(state) => state.isOpen
|
(state) => state.isOpen
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@ -41,16 +40,14 @@ export const WithdrawalDialog = () => {
|
|||||||
onChange={(isOpen) => (isOpen ? open() : close())}
|
onChange={(isOpen) => (isOpen ? open() : close())}
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<Web3Container connectEagerly>
|
<WithdrawFormContainer
|
||||||
<WithdrawFormContainer
|
assetId={assetId}
|
||||||
assetId={assetId}
|
partyId={pubKey ? pubKey : undefined}
|
||||||
partyId={pubKey ? pubKey : undefined}
|
submit={(args) => {
|
||||||
submit={(args) => {
|
close();
|
||||||
close();
|
createWithdraw.submit(args);
|
||||||
createWithdraw.submit(args);
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
</Web3Container>
|
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<createWithdraw.Dialog
|
<createWithdraw.Dialog
|
||||||
content={{
|
content={{
|
||||||
|
@ -10,6 +10,8 @@ import {
|
|||||||
KeyValueTableRow,
|
KeyValueTableRow,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||||
|
import { ChainIdMap, useWeb3ConnectStore } from '@vegaprotocol/web3';
|
||||||
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import { formatDistanceToNow } from 'date-fns';
|
import { formatDistanceToNow } from 'date-fns';
|
||||||
import type { WithdrawalFieldsFragment } from './__generated__/Withdrawal';
|
import type { WithdrawalFieldsFragment } from './__generated__/Withdrawal';
|
||||||
|
|
||||||
@ -75,17 +77,7 @@ export const WithdrawalFeedback = ({
|
|||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
)}
|
)}
|
||||||
{isAvailable ? (
|
{isAvailable ? (
|
||||||
<Button
|
<ActionButton withdrawal={withdrawal} submitWithdraw={submitWithdraw} />
|
||||||
disabled={withdrawal === null ? true : false}
|
|
||||||
data-testid="withdraw-funds"
|
|
||||||
onClick={() => {
|
|
||||||
if (withdrawal) {
|
|
||||||
submitWithdraw(withdrawal.id);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('Withdraw funds')}
|
|
||||||
</Button>
|
|
||||||
) : (
|
) : (
|
||||||
<p className="text-danger">
|
<p className="text-danger">
|
||||||
{t(
|
{t(
|
||||||
@ -98,3 +90,51 @@ export const WithdrawalFeedback = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ActionButton = ({
|
||||||
|
withdrawal,
|
||||||
|
submitWithdraw,
|
||||||
|
}: {
|
||||||
|
withdrawal: WithdrawalFieldsFragment | null;
|
||||||
|
submitWithdraw: (withdrawalId: string) => void;
|
||||||
|
}) => {
|
||||||
|
const { isActive, chainId } = useWeb3React();
|
||||||
|
const { open, desiredChainId } = useWeb3ConnectStore((store) => ({
|
||||||
|
open: store.open,
|
||||||
|
desiredChainId: store.desiredChainId,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
return (
|
||||||
|
<Button onClick={() => open()}>
|
||||||
|
{t('Connect Ethereum wallet to complete')}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chainId !== desiredChainId) {
|
||||||
|
const chainName = desiredChainId ? ChainIdMap[desiredChainId] : 'Unknown';
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p className="text-danger mb-2">
|
||||||
|
{t(`This app only works on ${chainName}. Please change chain.`)}
|
||||||
|
</p>
|
||||||
|
<Button disabled={true}>{t('Withdraw funds')}</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
disabled={withdrawal === null ? true : false}
|
||||||
|
data-testid="withdraw-funds"
|
||||||
|
onClick={() => {
|
||||||
|
if (withdrawal) {
|
||||||
|
submitWithdraw(withdrawal.id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('Withdraw funds')}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user