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