* feat: add enviromnemt provider to the ui-toolkit * chore: replace etherscan links * chore: wrap trading app into environment provider * chore: move env provider to react-helpers and wrap every app * chore: remove more env variables from libs and replace them with the env hook * fix: lint * fix: update readme with correct formatting command * fix: warnings for web3 hook * fix: wrap warning in conditional, print message only when env keys are missing * fix: incorrect condition on deposit manager fauceting param Co-authored-by: Matthew Russell <mattrussell36@gmail.com> * fix: cleanup token app ethereum config * chore: add better error handling to the useEnvironment hook * fix: lint * fix: formatting * fix: more lint * fix: throw error if required env variables are missing * fix: remove default eth chain id * fix: add back etherscan testid to withdrawals links * fix: imports * fix: try using babel jest for smart contracts test transpilation * fix: uniform ts syntax * chore: set resolveJsonModule in base tsconfig * fix: add missing data-ids for etherscan links Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
This commit is contained in:
parent
bf07dac445
commit
3a27172e04
@ -96,7 +96,7 @@ To run tests locally using your own wallets you can add the following environmen
|
|||||||
In CI linting, formatting and also run. These checks can be seen in the [CI workflow file](.github/workflows//test.yml).
|
In CI linting, formatting and also run. These checks can be seen in the [CI workflow file](.github/workflows//test.yml).
|
||||||
|
|
||||||
- To fix linting errors locally run `yarn nx lint --fix`
|
- To fix linting errors locally run `yarn nx lint --fix`
|
||||||
- To fix formatting errors local run `yarn nx format`
|
- To fix formatting errors local run `yarn nx format:write`
|
||||||
- For either command you may use `--all` to run across the entire repository
|
- For either command you may use `--all` to run across the entire repository
|
||||||
|
|
||||||
### Further help with Nx
|
### Further help with Nx
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,10 @@ import { useState, useEffect, useMemo } from 'react';
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { ApolloProvider } from '@apollo/client';
|
import { ApolloProvider } from '@apollo/client';
|
||||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
import {
|
||||||
|
useThemeSwitcher,
|
||||||
|
EnvironmentProvider,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { createClient } from './lib/apollo-client';
|
import { createClient } from './lib/apollo-client';
|
||||||
import { Nav } from './components/nav';
|
import { Nav } from './components/nav';
|
||||||
import { Header } from './components/header';
|
import { Header } from './components/header';
|
||||||
@ -23,27 +26,29 @@ function App() {
|
|||||||
const client = useMemo(() => createClient(DATA_SOURCES.dataNodeUrl), []);
|
const client = useMemo(() => createClient(DATA_SOURCES.dataNodeUrl), []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Provider value={theme}>
|
<EnvironmentProvider>
|
||||||
<TendermintWebsocketProvider>
|
<ThemeContext.Provider value={theme}>
|
||||||
<ApolloProvider client={client}>
|
<TendermintWebsocketProvider>
|
||||||
<div
|
<ApolloProvider client={client}>
|
||||||
className={`${
|
<div
|
||||||
menuOpen && 'h-[100vh] overflow-hidden'
|
className={`${
|
||||||
} antialiased m-0 bg-white dark:bg-black text-black dark:text-white`}
|
menuOpen && 'h-[100vh] overflow-hidden'
|
||||||
>
|
} antialiased m-0 bg-white dark:bg-black text-black dark:text-white`}
|
||||||
<div className="min-h-[100vh] max-w-[1300px] grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-black dark:border-white lg:border-l-1 lg:border-r-1 mx-auto">
|
>
|
||||||
<Header
|
<div className="min-h-[100vh] max-w-[1300px] grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-black dark:border-white lg:border-l-1 lg:border-r-1 mx-auto">
|
||||||
toggleTheme={toggleTheme}
|
<Header
|
||||||
menuOpen={menuOpen}
|
toggleTheme={toggleTheme}
|
||||||
setMenuOpen={setMenuOpen}
|
menuOpen={menuOpen}
|
||||||
/>
|
setMenuOpen={setMenuOpen}
|
||||||
<Nav menuOpen={menuOpen} />
|
/>
|
||||||
<Main />
|
<Nav menuOpen={menuOpen} />
|
||||||
|
<Main />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ApolloProvider>
|
||||||
</ApolloProvider>
|
</TendermintWebsocketProvider>
|
||||||
</TendermintWebsocketProvider>
|
</ThemeContext.Provider>
|
||||||
</ThemeContext.Provider>
|
</EnvironmentProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
"noPropertyAccessFromIndexSignature": false,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"lib": ["es5", "es6", "dom", "dom.iterable"],
|
"lib": ["es5", "es6", "dom", "dom.iterable"]
|
||||||
"resolveJsonModule": true
|
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
"include": [],
|
"include": [],
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
VegaManageDialog,
|
VegaManageDialog,
|
||||||
VegaWalletProvider,
|
VegaWalletProvider,
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
|
import { EnvironmentProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { VegaWalletConnectButton } from './components/vega-wallet-connect-button';
|
import { VegaWalletConnectButton } from './components/vega-wallet-connect-button';
|
||||||
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Connectors } from './lib/vega-connectors';
|
import { Connectors } from './lib/vega-connectors';
|
||||||
@ -37,51 +38,53 @@ function App() {
|
|||||||
}, [location]);
|
}, [location]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Provider value={theme}>
|
<EnvironmentProvider>
|
||||||
<ApolloProvider client={client}>
|
<ThemeContext.Provider value={theme}>
|
||||||
<VegaWalletProvider>
|
<ApolloProvider client={client}>
|
||||||
<AppLoader>
|
<VegaWalletProvider>
|
||||||
<div className="h-full dark:bg-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]">
|
<AppLoader>
|
||||||
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
|
<div className="h-full dark:bg-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]">
|
||||||
<DrawerToggle
|
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
|
||||||
onToggle={onToggle}
|
<DrawerToggle
|
||||||
variant={DRAWER_TOGGLE_VARIANTS.OPEN}
|
onToggle={onToggle}
|
||||||
className="xs:py-32 xs:px-16"
|
variant={DRAWER_TOGGLE_VARIANTS.OPEN}
|
||||||
/>
|
className="xs:py-32 xs:px-16"
|
||||||
|
|
||||||
<div className="flex items-center gap-4 ml-auto mr-8">
|
|
||||||
<VegaWalletConnectButton
|
|
||||||
setConnectDialog={(open) =>
|
|
||||||
setVegaWallet((x) => ({ ...x, connect: open }))
|
|
||||||
}
|
|
||||||
setManageDialog={(open) =>
|
|
||||||
setVegaWallet((x) => ({ ...x, manage: open }))
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
|
||||||
|
<div className="flex items-center gap-4 ml-auto mr-8">
|
||||||
|
<VegaWalletConnectButton
|
||||||
|
setConnectDialog={(open) =>
|
||||||
|
setVegaWallet((x) => ({ ...x, connect: open }))
|
||||||
|
}
|
||||||
|
setManageDialog={(open) =>
|
||||||
|
setVegaWallet((x) => ({ ...x, manage: open }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Main isMenuOpen={menuOpen} onToggle={onToggle} />
|
||||||
|
|
||||||
|
<VegaConnectDialog
|
||||||
|
connectors={Connectors}
|
||||||
|
dialogOpen={vegaWallet.connect}
|
||||||
|
setDialogOpen={(open) =>
|
||||||
|
setVegaWallet((x) => ({ ...x, connect: open }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<VegaManageDialog
|
||||||
|
dialogOpen={vegaWallet.manage}
|
||||||
|
setDialogOpen={(open) =>
|
||||||
|
setVegaWallet((x) => ({ ...x, manage: open }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</AppLoader>
|
||||||
<Main isMenuOpen={menuOpen} onToggle={onToggle} />
|
</VegaWalletProvider>
|
||||||
|
</ApolloProvider>
|
||||||
<VegaConnectDialog
|
</ThemeContext.Provider>
|
||||||
connectors={Connectors}
|
</EnvironmentProvider>
|
||||||
dialogOpen={vegaWallet.connect}
|
|
||||||
setDialogOpen={(open) =>
|
|
||||||
setVegaWallet((x) => ({ ...x, connect: open }))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<VegaManageDialog
|
|
||||||
dialogOpen={vegaWallet.manage}
|
|
||||||
setDialogOpen={(open) =>
|
|
||||||
setVegaWallet((x) => ({ ...x, manage: open }))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</AppLoader>
|
|
||||||
</VegaWalletProvider>
|
|
||||||
</ApolloProvider>
|
|
||||||
</ThemeContext.Provider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -3,6 +3,7 @@ import { DATA_SOURCES } from './config';
|
|||||||
import { Header } from './components/header';
|
import { Header } from './components/header';
|
||||||
import { StatsManager } from '@vegaprotocol/network-stats';
|
import { StatsManager } from '@vegaprotocol/network-stats';
|
||||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||||
|
import { EnvironmentProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
const envName = DATA_SOURCES.envName;
|
const envName = DATA_SOURCES.envName;
|
||||||
@ -14,19 +15,21 @@ function App() {
|
|||||||
const [theme, toggleTheme] = useThemeSwitcher();
|
const [theme, toggleTheme] = useThemeSwitcher();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Provider value={theme}>
|
<EnvironmentProvider>
|
||||||
<div className="w-screen min-h-screen grid pb-24 bg-white text-black-95 dark:bg-black dark:text-white-80">
|
<ThemeContext.Provider value={theme}>
|
||||||
<div className="layout-grid w-screen justify-self-center">
|
<div className="w-screen min-h-screen grid pb-24 bg-white text-black-95 dark:bg-black dark:text-white-80">
|
||||||
<Header toggleTheme={toggleTheme} />
|
<div className="layout-grid w-screen justify-self-center">
|
||||||
<StatsManager
|
<Header toggleTheme={toggleTheme} />
|
||||||
envName={envName}
|
<StatsManager
|
||||||
statsEndpoint={statsEndpoint}
|
envName={envName}
|
||||||
nodesEndpoint={nodesEndpoint}
|
statsEndpoint={statsEndpoint}
|
||||||
className="max-w-3xl px-24"
|
nodesEndpoint={nodesEndpoint}
|
||||||
/>
|
className="max-w-3xl px-24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ThemeContext.Provider>
|
||||||
</ThemeContext.Provider>
|
</EnvironmentProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -20,37 +20,40 @@ import { Web3Provider } from '@vegaprotocol/web3';
|
|||||||
import { Connectors } from './lib/web3-connectors';
|
import { Connectors } from './lib/web3-connectors';
|
||||||
import { VegaWalletDialogs } from './components/vega-wallet-dialogs';
|
import { VegaWalletDialogs } from './components/vega-wallet-dialogs';
|
||||||
import { VegaWalletProvider } from '@vegaprotocol/wallet';
|
import { VegaWalletProvider } from '@vegaprotocol/wallet';
|
||||||
|
import { EnvironmentProvider } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const sideBar = React.useMemo(() => [<EthWallet />, <VegaWallet />], []);
|
const sideBar = React.useMemo(() => [<EthWallet />, <VegaWallet />], []);
|
||||||
return (
|
return (
|
||||||
<GraphQlProvider>
|
<GraphQlProvider>
|
||||||
<Router>
|
<Router>
|
||||||
<AppStateProvider>
|
<EnvironmentProvider>
|
||||||
<Web3Provider connectors={Connectors}>
|
<AppStateProvider>
|
||||||
<Web3Connector>
|
<Web3Provider connectors={Connectors}>
|
||||||
<VegaWalletProvider>
|
<Web3Connector>
|
||||||
<ContractsProvider>
|
<VegaWalletProvider>
|
||||||
<AppLoader>
|
<ContractsProvider>
|
||||||
<BalanceManager>
|
<AppLoader>
|
||||||
<>
|
<BalanceManager>
|
||||||
<div className="app dark max-w-[1300px] mx-auto my-0 grid grid-rows-[min-content_1fr_min-content] min-h-full lg:border-l-1 lg:border-r-1 lg:border-white font-sans text-body lg:text-body-large text-white-80">
|
<>
|
||||||
<AppBanner />
|
<div className="app dark max-w-[1300px] mx-auto my-0 grid grid-rows-[min-content_1fr_min-content] min-h-full lg:border-l-1 lg:border-r-1 lg:border-white font-sans text-body lg:text-body-large text-white-80">
|
||||||
<TemplateSidebar sidebar={sideBar}>
|
<AppBanner />
|
||||||
<AppRouter />
|
<TemplateSidebar sidebar={sideBar}>
|
||||||
</TemplateSidebar>
|
<AppRouter />
|
||||||
<AppFooter />
|
</TemplateSidebar>
|
||||||
</div>
|
<AppFooter />
|
||||||
<VegaWalletDialogs />
|
</div>
|
||||||
<TransactionModal />
|
<VegaWalletDialogs />
|
||||||
</>
|
<TransactionModal />
|
||||||
</BalanceManager>
|
</>
|
||||||
</AppLoader>
|
</BalanceManager>
|
||||||
</ContractsProvider>
|
</AppLoader>
|
||||||
</VegaWalletProvider>
|
</ContractsProvider>
|
||||||
</Web3Connector>
|
</VegaWalletProvider>
|
||||||
</Web3Provider>
|
</Web3Connector>
|
||||||
</AppStateProvider>
|
</Web3Provider>
|
||||||
|
</AppStateProvider>
|
||||||
|
</EnvironmentProvider>
|
||||||
</Router>
|
</Router>
|
||||||
</GraphQlProvider>
|
</GraphQlProvider>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { ADDRESSES } from '../../config';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { useAddAssetSupported } from '../../hooks/use-add-asset-to-wallet';
|
import { useAddAssetSupported } from '../../hooks/use-add-asset-to-wallet';
|
||||||
import vegaVesting from '../../images/vega_vesting.png';
|
import vegaVesting from '../../images/vega_vesting.png';
|
||||||
import { AddTokenButtonLink } from '../add-token-button/add-token-button';
|
import { AddTokenButtonLink } from '../add-token-button/add-token-button';
|
||||||
import { Callout } from '@vegaprotocol/ui-toolkit';
|
import { Callout } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
export const AddLockedTokenAddress = () => {
|
export const AddLockedTokenAddress = () => {
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const addSupported = useAddAssetSupported();
|
const addSupported = useAddAssetSupported();
|
||||||
return (
|
return (
|
||||||
|
@ -2,7 +2,7 @@ import * as Sentry from '@sentry/react';
|
|||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { ADDRESSES } from '../../config';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import {
|
import {
|
||||||
AppStateActionType,
|
AppStateActionType,
|
||||||
useAppState,
|
useAppState,
|
||||||
@ -17,6 +17,7 @@ interface BalanceManagerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BalanceManager = ({ children }: BalanceManagerProps) => {
|
export const BalanceManager = ({ children }: BalanceManagerProps) => {
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
const contracts = useContracts();
|
const contracts = useContracts();
|
||||||
const { account } = useWeb3React();
|
const { account } = useWeb3React();
|
||||||
const { appDispatch } = useAppState();
|
const { appDispatch } = useAppState();
|
||||||
@ -55,7 +56,13 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateBalances();
|
updateBalances();
|
||||||
}, [appDispatch, contracts?.token, contracts?.vesting, account]);
|
}, [
|
||||||
|
appDispatch,
|
||||||
|
contracts?.token,
|
||||||
|
contracts?.vesting,
|
||||||
|
account,
|
||||||
|
ADDRESSES.stakingBridge,
|
||||||
|
]);
|
||||||
|
|
||||||
// This use effect hook is very expensive and is kept separate to prevent expensive reloading of data.
|
// This use effect hook is very expensive and is kept separate to prevent expensive reloading of data.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -3,7 +3,8 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import type { TransactionState } from '../../hooks/transaction-reducer';
|
import type { TransactionState } from '../../hooks/transaction-reducer';
|
||||||
import { TxState } from '../../hooks/transaction-reducer';
|
import { TxState } from '../../hooks/transaction-reducer';
|
||||||
import { truncateMiddle } from '../../lib/truncate-middle';
|
import { truncateMiddle } from '../../lib/truncate-middle';
|
||||||
import { Button, EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Button, Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { Error, HandUp, Tick } from '../icons';
|
import { Error, HandUp, Tick } from '../icons';
|
||||||
import { Loader } from '../loader';
|
import { Loader } from '../loader';
|
||||||
import { StatefulButton } from '../stateful-button';
|
import { StatefulButton } from '../stateful-button';
|
||||||
@ -122,6 +123,7 @@ export const TransactionButtonFooter = ({
|
|||||||
txHash,
|
txHash,
|
||||||
message,
|
message,
|
||||||
}: TransactionButtonFooterProps) => {
|
}: TransactionButtonFooterProps) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
if (message) {
|
if (message) {
|
||||||
@ -142,7 +144,12 @@ export const TransactionButtonFooter = ({
|
|||||||
<div className="transaction-button__footer">
|
<div className="transaction-button__footer">
|
||||||
<p className="flex justify-between items-start m-0 text-ui">
|
<p className="flex justify-between items-start m-0 text-ui">
|
||||||
<span>{t('transaction')}</span>
|
<span>{t('transaction')}</span>
|
||||||
<EtherscanLink text={truncateMiddle(txHash)} tx={txHash} />
|
<Link
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${txHash}`}
|
||||||
|
title={t('View on Etherscan')}
|
||||||
|
>
|
||||||
|
{truncateMiddle(txHash)}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
import { Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
|
|
||||||
export const TransactionComplete = ({
|
export const TransactionComplete = ({
|
||||||
@ -14,6 +15,7 @@ export const TransactionComplete = ({
|
|||||||
footer?: ReactElement | string;
|
footer?: ReactElement | string;
|
||||||
body?: ReactElement | string;
|
body?: ReactElement | string;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Callout
|
<Callout
|
||||||
@ -23,7 +25,12 @@ export const TransactionComplete = ({
|
|||||||
>
|
>
|
||||||
{body && <p data-testid="transaction-complete-body">{body}</p>}
|
{body && <p data-testid="transaction-complete-body">{body}</p>}
|
||||||
<p>
|
<p>
|
||||||
<EtherscanLink tx={hash} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${hash}`}
|
||||||
|
>
|
||||||
|
{hash}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
{footer && <p data-testid="transaction-complete-footer">{footer}</p>}
|
{footer && <p data-testid="transaction-complete-footer">{footer}</p>}
|
||||||
</Callout>
|
</Callout>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Button, Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
import { Button, Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { Error } from '../icons';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export interface TransactionErrorProps {
|
export interface TransactionErrorProps {
|
||||||
error: Error | null;
|
error: Error | null;
|
||||||
@ -15,6 +15,7 @@ export const TransactionError = ({
|
|||||||
hash,
|
hash,
|
||||||
onActionClick,
|
onActionClick,
|
||||||
}: TransactionErrorProps) => {
|
}: TransactionErrorProps) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -22,7 +23,12 @@ export const TransactionError = ({
|
|||||||
<p>{error ? error.message : t('Something went wrong')}</p>
|
<p>{error ? error.message : t('Something went wrong')}</p>
|
||||||
{hash ? (
|
{hash ? (
|
||||||
<p>
|
<p>
|
||||||
<EtherscanLink tx={hash} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${hash}`}
|
||||||
|
>
|
||||||
|
{hash}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
<Button onClick={() => onActionClick()}>{t('Try again')}</Button>
|
<Button onClick={() => onActionClick()}>{t('Try again')}</Button>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Callout } from '@vegaprotocol/ui-toolkit';
|
import { Callout } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export const TransactionPending = ({
|
export const TransactionPending = ({
|
||||||
hash,
|
hash,
|
||||||
@ -18,6 +19,7 @@ export const TransactionPending = ({
|
|||||||
footer?: React.ReactElement | string;
|
footer?: React.ReactElement | string;
|
||||||
body?: React.ReactElement | string;
|
body?: React.ReactElement | string;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const remainingConfirmations = React.useMemo(() => {
|
const remainingConfirmations = React.useMemo(() => {
|
||||||
if (requiredConfirmations) {
|
if (requiredConfirmations) {
|
||||||
@ -38,7 +40,12 @@ export const TransactionPending = ({
|
|||||||
<Callout iconName="refresh" title={title}>
|
<Callout iconName="refresh" title={title}>
|
||||||
{body && <p data-testid="transaction-pending-body">{body}</p>}
|
{body && <p data-testid="transaction-pending-body">{body}</p>}
|
||||||
<p>
|
<p>
|
||||||
<EtherscanLink tx={hash} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${hash}`}
|
||||||
|
>
|
||||||
|
{hash}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
{footer && <p data-testid="transaction-pending-footer">{footer}</p>}
|
{footer && <p data-testid="transaction-pending-footer">{footer}</p>}
|
||||||
</Callout>
|
</Callout>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { TxData } from '@vegaprotocol/smart-contracts';
|
import type { TxData } from '@vegaprotocol/smart-contracts';
|
||||||
import { Dialog, EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Dialog, Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ const TransactionModalStatus = ({
|
|||||||
}) => <span className="flex gap-4 items-center">{children}</span>;
|
}) => <span className="flex gap-4 items-center">{children}</span>;
|
||||||
|
|
||||||
export const TransactionModal = () => {
|
export const TransactionModal = () => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { transactions } = useContracts();
|
const { transactions } = useContracts();
|
||||||
const { appState, appDispatch } = useAppState();
|
const { appState, appDispatch } = useAppState();
|
||||||
@ -76,16 +78,20 @@ export const TransactionModal = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{transactions.map((t) => {
|
{transactions.map((transaction) => {
|
||||||
return (
|
return (
|
||||||
<tr key={t.tx.hash}>
|
<tr key={transaction.tx.hash}>
|
||||||
<TransactionModalTd>
|
<TransactionModalTd>
|
||||||
<EtherscanLink
|
<Link
|
||||||
tx={t.tx.hash}
|
title={t('View transaction on Etherscan')}
|
||||||
text={truncateMiddle(t.tx.hash)}
|
href={`${ETHERSCAN_URL}/tx/${transaction.tx.hash}`}
|
||||||
/>
|
>
|
||||||
|
{truncateMiddle(transaction.tx.hash)}
|
||||||
|
</Link>
|
||||||
|
</TransactionModalTd>
|
||||||
|
<TransactionModalTd>
|
||||||
|
{renderStatus(transaction)}
|
||||||
</TransactionModalTd>
|
</TransactionModalTd>
|
||||||
<TransactionModalTd>{renderStatus(t)}</TransactionModalTd>
|
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -6,7 +6,6 @@ import React from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { AccountType } from '../../__generated__/globalTypes';
|
import { AccountType } from '../../__generated__/globalTypes';
|
||||||
import { ADDRESSES } from '../../config';
|
|
||||||
import noIcon from '../../images/token-no-icon.png';
|
import noIcon from '../../images/token-no-icon.png';
|
||||||
import vegaBlack from '../../images/vega_black.png';
|
import vegaBlack from '../../images/vega_black.png';
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
import { BigNumber } from '../../lib/bignumber';
|
||||||
@ -18,6 +17,7 @@ import type {
|
|||||||
DelegationsVariables,
|
DelegationsVariables,
|
||||||
} from './__generated__/Delegations';
|
} from './__generated__/Delegations';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
const DELEGATIONS_QUERY = gql`
|
const DELEGATIONS_QUERY = gql`
|
||||||
query Delegations($partyId: ID!) {
|
query Delegations($partyId: ID!) {
|
||||||
@ -60,6 +60,7 @@ const DELEGATIONS_QUERY = gql`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const usePollForDelegations = () => {
|
export const usePollForDelegations = () => {
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { keypair } = useVegaWallet();
|
const { keypair } = useVegaWallet();
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
@ -227,7 +228,7 @@ export const usePollForDelegations = () => {
|
|||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
mounted = false;
|
mounted = false;
|
||||||
};
|
};
|
||||||
}, [client, keypair?.pub, t]);
|
}, [client, keypair?.pub, t, ADDRESSES.vegaTokenAddress]);
|
||||||
|
|
||||||
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
|
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
|
||||||
};
|
};
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
import type { EthereumChainId } from '@vegaprotocol/smart-contracts';
|
|
||||||
import {
|
|
||||||
EnvironmentConfig,
|
|
||||||
EthereumChainIds,
|
|
||||||
} from '@vegaprotocol/smart-contracts';
|
|
||||||
|
|
||||||
import type { Networks } from './vega';
|
|
||||||
|
|
||||||
type VegaContracts = typeof EnvironmentConfig[Networks];
|
|
||||||
|
|
||||||
const appChainId = Number(process.env['NX_ETHEREUM_CHAIN_ID'] || 3);
|
|
||||||
|
|
||||||
export const APP_ENV = process.env['NX_VEGA_ENV'] as Networks;
|
|
||||||
|
|
||||||
const Addresses: Record<number, VegaContracts> = {
|
|
||||||
1: EnvironmentConfig.MAINNET,
|
|
||||||
3: EnvironmentConfig[APP_ENV],
|
|
||||||
};
|
|
||||||
|
|
||||||
export type { EthereumChainId };
|
|
||||||
export { EthereumChainIds };
|
|
||||||
|
|
||||||
/** Contract addresses for the different contracts in the VEGA ecosystem */
|
|
||||||
export const ADDRESSES = Addresses[appChainId];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Chain ID the environment is configured for.
|
|
||||||
* Normally this is 0x3 (Ropsten) for dev and 0x1 (Mainnet) for prod
|
|
||||||
*/
|
|
||||||
export const APP_CHAIN_ID = appChainId;
|
|
@ -1,5 +1,4 @@
|
|||||||
export * from './flags';
|
export * from './flags';
|
||||||
export * from './ethereum';
|
|
||||||
export * from './links';
|
export * from './links';
|
||||||
export * from './network-params';
|
export * from './network-params';
|
||||||
export * from './vega';
|
export * from './vega';
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
export enum Networks {
|
import { Networks } from '@vegaprotocol/smart-contracts';
|
||||||
CUSTOM = 'CUSTOM',
|
|
||||||
TESTNET = 'TESTNET',
|
|
||||||
STAGNET = 'STAGNET',
|
|
||||||
STAGNET2 = 'STAGNET2',
|
|
||||||
DEVNET = 'DEVNET',
|
|
||||||
MAINNET = 'MAINNET',
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VegaNode {
|
interface VegaNode {
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -10,9 +10,9 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
|
|||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import uniqBy from 'lodash/uniqBy';
|
import uniqBy from 'lodash/uniqBy';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
import { SplashLoader } from '../../components/splash-loader';
|
import { SplashLoader } from '../../components/splash-loader';
|
||||||
import { ADDRESSES, APP_ENV } from '../../config';
|
|
||||||
import type { ContractsContextShape } from './contracts-context';
|
import type { ContractsContextShape } from './contracts-context';
|
||||||
import { ContractsContext } from './contracts-context';
|
import { ContractsContext } from './contracts-context';
|
||||||
import { defaultProvider } from '../../lib/web3-connectors';
|
import { defaultProvider } from '../../lib/web3-connectors';
|
||||||
@ -21,6 +21,7 @@ import { defaultProvider } from '../../lib/web3-connectors';
|
|||||||
* Provides Vega Ethereum contract instances to its children.
|
* Provides Vega Ethereum contract instances to its children.
|
||||||
*/
|
*/
|
||||||
export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
|
export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
|
||||||
|
const { ADDRESSES, VEGA_ENV } = useEnvironment();
|
||||||
const { provider: activeProvider, account } = useWeb3React();
|
const { provider: activeProvider, account } = useWeb3React();
|
||||||
const [txs, setTxs] = React.useState<TxData[]>([]);
|
const [txs, setTxs] = React.useState<TxData[]>([]);
|
||||||
const [contracts, setContracts] = React.useState<Pick<
|
const [contracts, setContracts] = React.useState<Pick<
|
||||||
@ -53,20 +54,20 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
|
|||||||
signer
|
signer
|
||||||
),
|
),
|
||||||
// @ts-ignore Cant accept JsonRpcProvider provider
|
// @ts-ignore Cant accept JsonRpcProvider provider
|
||||||
staking: new VegaStaking(APP_ENV, provider, signer),
|
staking: new VegaStaking(VEGA_ENV, provider, signer),
|
||||||
// @ts-ignore Cant accept JsonRpcProvider provider
|
// @ts-ignore Cant accept JsonRpcProvider provider
|
||||||
vesting: new VegaVesting(APP_ENV, provider, signer),
|
vesting: new VegaVesting(VEGA_ENV, provider, signer),
|
||||||
// @ts-ignore Cant accept JsonRpcProvider provider
|
// @ts-ignore Cant accept JsonRpcProvider provider
|
||||||
claim: new VegaClaim(APP_ENV, provider, signer),
|
claim: new VegaClaim(VEGA_ENV, provider, signer),
|
||||||
erc20Bridge: new VegaErc20Bridge(
|
erc20Bridge: new VegaErc20Bridge(
|
||||||
APP_ENV,
|
VEGA_ENV,
|
||||||
// @ts-ignore Cant accept JsonRpcProvider provider
|
// @ts-ignore Cant accept JsonRpcProvider provider
|
||||||
provider,
|
provider,
|
||||||
signer
|
signer
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [activeProvider, account]);
|
}, [activeProvider, account, ADDRESSES.vegaTokenAddress, VEGA_ENV]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!contracts) return;
|
if (!contracts) return;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
import * as Sentry from '@sentry/react';
|
import * as Sentry from '@sentry/react';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import { MetaMask } from '@web3-react/metamask';
|
import { MetaMask } from '@web3-react/metamask';
|
||||||
import React from 'react';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
import { Networks } from '@vegaprotocol/smart-contracts';
|
||||||
import { APP_ENV, Networks } from '../config';
|
|
||||||
|
|
||||||
export const useAddAssetSupported = () => {
|
export const useAddAssetSupported = () => {
|
||||||
const { connector } = useWeb3React();
|
const { connector } = useWeb3React();
|
||||||
@ -19,6 +19,7 @@ export const useAddAssetToWallet = (
|
|||||||
decimals: number,
|
decimals: number,
|
||||||
image: string
|
image: string
|
||||||
) => {
|
) => {
|
||||||
|
const { VEGA_ENV } = useEnvironment();
|
||||||
const { provider } = useWeb3React();
|
const { provider } = useWeb3React();
|
||||||
const addSupported = useAddAssetSupported();
|
const addSupported = useAddAssetSupported();
|
||||||
const add = React.useCallback(async () => {
|
const add = React.useCallback(async () => {
|
||||||
@ -35,10 +36,10 @@ export const useAddAssetToWallet = (
|
|||||||
address,
|
address,
|
||||||
symbol: `${symbol}${
|
symbol: `${symbol}${
|
||||||
// Add the environment if not mainnet
|
// Add the environment if not mainnet
|
||||||
APP_ENV === Networks.MAINNET
|
VEGA_ENV === Networks.MAINNET
|
||||||
? ''
|
? ''
|
||||||
: // Remove NET as VEGA(TESTNET) is too long
|
: // Remove NET as VEGA(TESTNET) is too long
|
||||||
` ${APP_ENV.replace('NET', '')}`
|
` ${VEGA_ENV.replace('NET', '')}`
|
||||||
}`,
|
}`,
|
||||||
decimals,
|
decimals,
|
||||||
image,
|
image,
|
||||||
@ -48,7 +49,7 @@ export const useAddAssetToWallet = (
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
Sentry.captureException(error);
|
Sentry.captureException(error);
|
||||||
}
|
}
|
||||||
}, [address, decimals, image, provider, symbol]);
|
}, [address, decimals, image, provider, symbol, VEGA_ENV]);
|
||||||
|
|
||||||
return React.useMemo(() => {
|
return React.useMemo(() => {
|
||||||
return {
|
return {
|
||||||
|
@ -2,7 +2,7 @@ import * as Sentry from '@sentry/react';
|
|||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { ADDRESSES } from '../config';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import {
|
import {
|
||||||
AppStateActionType,
|
AppStateActionType,
|
||||||
useAppState,
|
useAppState,
|
||||||
@ -10,6 +10,7 @@ import {
|
|||||||
import { useContracts } from '../contexts/contracts/contracts-context';
|
import { useContracts } from '../contexts/contracts/contracts-context';
|
||||||
|
|
||||||
export const useRefreshBalances = (address: string) => {
|
export const useRefreshBalances = (address: string) => {
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
const { appDispatch } = useAppState();
|
const { appDispatch } = useAppState();
|
||||||
const { keypair } = useVegaWallet();
|
const { keypair } = useVegaWallet();
|
||||||
const { token, staking, vesting } = useContracts();
|
const { token, staking, vesting } = useContracts();
|
||||||
@ -44,5 +45,13 @@ export const useRefreshBalances = (address: string) => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
}
|
}
|
||||||
}, [address, appDispatch, keypair?.pub, staking, token, vesting]);
|
}, [
|
||||||
|
address,
|
||||||
|
appDispatch,
|
||||||
|
keypair?.pub,
|
||||||
|
staking,
|
||||||
|
token,
|
||||||
|
vesting,
|
||||||
|
ADDRESSES.stakingBridge,
|
||||||
|
]);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||||
import type { Networks, Tranche } from '@vegaprotocol/smart-contracts';
|
import type { Networks, Tranche } from '@vegaprotocol/smart-contracts';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { APP_ENV } from '../config';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
import { BigNumber } from '../lib/bignumber';
|
import { BigNumber } from '../lib/bignumber';
|
||||||
|
|
||||||
@ -15,8 +15,9 @@ const TRANCHES_URLS: { [N in Networks]: string } = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function useTranches() {
|
export function useTranches() {
|
||||||
|
const { VEGA_ENV } = useEnvironment();
|
||||||
const [tranches, setTranches] = React.useState<Tranche[] | null>(null);
|
const [tranches, setTranches] = React.useState<Tranche[] | null>(null);
|
||||||
const url = React.useMemo(() => TRANCHES_URLS[APP_ENV], []);
|
const url = React.useMemo(() => TRANCHES_URLS[VEGA_ENV], [VEGA_ENV]);
|
||||||
const {
|
const {
|
||||||
state: { data, loading, error },
|
state: { data, loading, error },
|
||||||
} = useFetch<Tranche[] | null>(url);
|
} = useFetch<Tranche[] | null>(url);
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import {
|
import { Callout, Intent, Link, Button } from '@vegaprotocol/ui-toolkit';
|
||||||
Callout,
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
Intent,
|
|
||||||
EtherscanLink,
|
|
||||||
Button,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link as RouteLink } from 'react-router-dom';
|
||||||
|
|
||||||
import type { BigNumber } from '../../lib/bignumber';
|
import type { BigNumber } from '../../lib/bignumber';
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
@ -22,6 +18,7 @@ export const Complete = ({
|
|||||||
commitTxHash: string | null;
|
commitTxHash: string | null;
|
||||||
claimTxHash: string | null;
|
claimTxHash: string | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -38,18 +35,28 @@ export const Complete = ({
|
|||||||
{commitTxHash && (
|
{commitTxHash && (
|
||||||
<p style={{ margin: 0 }}>
|
<p style={{ margin: 0 }}>
|
||||||
{t('Link transaction')}:{' '}
|
{t('Link transaction')}:{' '}
|
||||||
<EtherscanLink tx={commitTxHash} text={commitTxHash} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${commitTxHash}`}
|
||||||
|
>
|
||||||
|
{commitTxHash}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{claimTxHash && (
|
{claimTxHash && (
|
||||||
<p>
|
<p>
|
||||||
{t('Claim transaction')}:{' '}
|
{t('Claim transaction')}:{' '}
|
||||||
<EtherscanLink tx={claimTxHash} text={claimTxHash} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${claimTxHash}`}
|
||||||
|
>
|
||||||
|
{claimTxHash}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<Link to={Routes.VESTING}>
|
<RouteLink to={Routes.VESTING}>
|
||||||
<Button className="fill">{t('Check your vesting VEGA tokens')}</Button>
|
<Button className="fill">{t('Check your vesting VEGA tokens')}</Button>
|
||||||
</Link>
|
</RouteLink>
|
||||||
</Callout>
|
</Callout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { Heading } from '../../components/heading';
|
import { Heading } from '../../components/heading';
|
||||||
import { ADDRESSES } from '../../config';
|
|
||||||
|
|
||||||
const Contracts = () => {
|
const Contracts = () => {
|
||||||
|
const { ADDRESSES, ETHERSCAN_URL } = useEnvironment();
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<Heading title={'Contracts'} />
|
<Heading title={'Contracts'} />
|
||||||
@ -10,7 +13,12 @@ const Contracts = () => {
|
|||||||
{Object.entries(ADDRESSES).map(([key, value]) => (
|
{Object.entries(ADDRESSES).map(([key, value]) => (
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<div>{key}:</div>
|
<div>{key}:</div>
|
||||||
<EtherscanLink address={value as string} text={value as string} />
|
<Link
|
||||||
|
title={t('View address on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/address/${value}`}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import {
|
import { Callout, Link, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
Callout,
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
EtherscanLink,
|
|
||||||
Intent,
|
|
||||||
Splash,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
import { ADDRESSES } from '../../../config';
|
|
||||||
import { useTranches } from '../../../hooks/use-tranches';
|
import { useTranches } from '../../../hooks/use-tranches';
|
||||||
import type { BigNumber } from '../../../lib/bignumber';
|
import type { BigNumber } from '../../../lib/bignumber';
|
||||||
import { formatNumber } from '../../../lib/format-number';
|
import { formatNumber } from '../../../lib/format-number';
|
||||||
@ -21,6 +16,7 @@ export const TokenDetails = ({
|
|||||||
totalSupply: BigNumber;
|
totalSupply: BigNumber;
|
||||||
totalStaked: BigNumber;
|
totalStaked: BigNumber;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { ADDRESSES, ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { tranches, loading, error } = useTranches();
|
const { tranches, loading, error } = useTranches();
|
||||||
@ -45,21 +41,25 @@ export const TokenDetails = ({
|
|||||||
<KeyValueTable className={'token-details'}>
|
<KeyValueTable className={'token-details'}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
{t('Token address').toUpperCase()}
|
{t('Token address').toUpperCase()}
|
||||||
<EtherscanLink
|
<Link
|
||||||
data-testid="token-address"
|
data-testid="token-address"
|
||||||
address={ADDRESSES.vegaTokenAddress}
|
title={t('View address on Etherscan')}
|
||||||
text={ADDRESSES.vegaTokenAddress}
|
|
||||||
className="font-mono"
|
className="font-mono"
|
||||||
/>
|
href={`${ETHERSCAN_URL}/address/${ADDRESSES.vegaTokenAddress}`}
|
||||||
|
>
|
||||||
|
{ADDRESSES.vegaTokenAddress}
|
||||||
|
</Link>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
{t('Vesting contract'.toUpperCase())}
|
{t('Vesting contract'.toUpperCase())}
|
||||||
<EtherscanLink
|
<Link
|
||||||
data-testid="token-contract"
|
data-testid="token-contract"
|
||||||
address={ADDRESSES.vestingAddress}
|
title={t('View address on Etherscan')}
|
||||||
text={ADDRESSES.vestingAddress}
|
|
||||||
className="font-mono"
|
className="font-mono"
|
||||||
/>
|
href={`${ETHERSCAN_URL}/address/${ADDRESSES.vestingAddress}`}
|
||||||
|
>
|
||||||
|
{ADDRESSES.vestingAddress}
|
||||||
|
</Link>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
{t('Total supply').toUpperCase()}
|
{t('Total supply').toUpperCase()}
|
||||||
|
@ -3,7 +3,7 @@ import { Trans, useTranslation } from 'react-i18next';
|
|||||||
import { Link, useParams, useOutletContext } from 'react-router-dom';
|
import { Link, useParams, useOutletContext } from 'react-router-dom';
|
||||||
|
|
||||||
import { TransactionCallout } from '../../../components/transaction-callout';
|
import { TransactionCallout } from '../../../components/transaction-callout';
|
||||||
import { ADDRESSES } from '../../../config';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||||
import { useContracts } from '../../../contexts/contracts/contracts-context';
|
import { useContracts } from '../../../contexts/contracts/contracts-context';
|
||||||
import {
|
import {
|
||||||
@ -25,6 +25,7 @@ export const RedeemFromTranche = () => {
|
|||||||
address: string;
|
address: string;
|
||||||
}>();
|
}>();
|
||||||
const { vesting } = useContracts();
|
const { vesting } = useContracts();
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
appState: { lien, totalVestedBalance, trancheBalances, totalLockedBalance },
|
appState: { lien, totalVestedBalance, trancheBalances, totalLockedBalance },
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
import {
|
import { Button, Callout, Link, Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
Button,
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
Callout,
|
|
||||||
EtherscanLink,
|
|
||||||
Intent,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link as RouteLink } from 'react-router-dom';
|
||||||
|
|
||||||
import { TransactionCallout } from '../../../components/transaction-callout';
|
import { TransactionCallout } from '../../../components/transaction-callout';
|
||||||
import type {
|
import type {
|
||||||
@ -35,6 +31,7 @@ export const AssociateTransaction = ({
|
|||||||
requiredConfirmations: number;
|
requiredConfirmations: number;
|
||||||
linking: PartyStakeLinkings_party_stake_linkings | null;
|
linking: PartyStakeLinkings_party_stake_linkings | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const remainingConfirmations = React.useMemo(() => {
|
const remainingConfirmations = React.useMemo(() => {
|
||||||
@ -71,7 +68,12 @@ export const AssociateTransaction = ({
|
|||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<EtherscanLink tx={state.txData.hash || ''} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${state.txData.hash}`}
|
||||||
|
>
|
||||||
|
{state.txData.hash}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
<p data-testid="transaction-pending-footer">
|
<p data-testid="transaction-pending-footer">
|
||||||
{t('pendingAssociationText', {
|
{t('pendingAssociationText', {
|
||||||
@ -90,11 +92,11 @@ export const AssociateTransaction = ({
|
|||||||
{ vegaKey }
|
{ vegaKey }
|
||||||
)}
|
)}
|
||||||
completeFooter={
|
completeFooter={
|
||||||
<Link to={Routes.STAKING}>
|
<RouteLink to={Routes.STAKING}>
|
||||||
<Button className="fill">
|
<Button className="fill">
|
||||||
{t('Nominate Stake to Validator Node')}
|
{t('Nominate Stake to Validator Node')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</RouteLink>
|
||||||
}
|
}
|
||||||
pendingHeading={t('Associating Tokens')}
|
pendingHeading={t('Associating Tokens')}
|
||||||
pendingBody={t(
|
pendingBody={t(
|
||||||
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { TokenInput } from '../../../components/token-input';
|
import { TokenInput } from '../../../components/token-input';
|
||||||
import { ADDRESSES } from '../../../config';
|
|
||||||
import {
|
import {
|
||||||
AppStateActionType,
|
AppStateActionType,
|
||||||
useAppState,
|
useAppState,
|
||||||
@ -13,6 +12,7 @@ import { useTransaction } from '../../../hooks/use-transaction';
|
|||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { AssociateInfo } from './associate-info';
|
import { AssociateInfo } from './associate-info';
|
||||||
import type { VegaKeyExtended } from '@vegaprotocol/wallet';
|
import type { VegaKeyExtended } from '@vegaprotocol/wallet';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export const WalletAssociate = ({
|
export const WalletAssociate = ({
|
||||||
perform,
|
perform,
|
||||||
@ -27,6 +27,7 @@ export const WalletAssociate = ({
|
|||||||
vegaKey: VegaKeyExtended;
|
vegaKey: VegaKeyExtended;
|
||||||
address: string;
|
address: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
appDispatch,
|
appDispatch,
|
||||||
@ -56,7 +57,13 @@ export const WalletAssociate = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
run();
|
run();
|
||||||
}, [address, appDispatch, approveState.txState, token]);
|
}, [
|
||||||
|
address,
|
||||||
|
appDispatch,
|
||||||
|
approveState.txState,
|
||||||
|
token,
|
||||||
|
ADDRESSES.stakingBridge,
|
||||||
|
]);
|
||||||
|
|
||||||
let pageContent = null;
|
let pageContent = null;
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Button, Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
import { Button, Callout, Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link as RouteLink } from 'react-router-dom';
|
||||||
|
|
||||||
import { BulletHeader } from '../../components/bullet-header';
|
import { BulletHeader } from '../../components/bullet-header';
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { Links } from '../../config';
|
import { Links } from '../../config';
|
||||||
import {
|
import {
|
||||||
AppStateActionType,
|
AppStateActionType,
|
||||||
@ -29,14 +30,9 @@ export const Staking = ({ data }: { data?: StakingQueryResult }) => {
|
|||||||
<p className="mb-12">{t('stakingDescription3')}</p>
|
<p className="mb-12">{t('stakingDescription3')}</p>
|
||||||
<p className="mb-12">{t('stakingDescription4')}</p>
|
<p className="mb-12">{t('stakingDescription4')}</p>
|
||||||
<p className="mb-12">
|
<p className="mb-12">
|
||||||
<a
|
<Link href={Links.STAKING_GUIDE} target="_blank">
|
||||||
className="underline"
|
|
||||||
href={Links.STAKING_GUIDE}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
{t('readMoreStaking')}
|
{t('readMoreStaking')}
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -65,6 +61,7 @@ export const Staking = ({ data }: { data?: StakingQueryResult }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const StakingStepConnectWallets = () => {
|
export const StakingStepConnectWallets = () => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { account } = useWeb3React();
|
const { account } = useWeb3React();
|
||||||
const { keypair } = useVegaWallet();
|
const { keypair } = useVegaWallet();
|
||||||
@ -75,7 +72,12 @@ export const StakingStepConnectWallets = () => {
|
|||||||
<Callout intent={Intent.Success} iconName="tick" title={'Connected'}>
|
<Callout intent={Intent.Success} iconName="tick" title={'Connected'}>
|
||||||
<p>
|
<p>
|
||||||
{t('Connected Ethereum address')}
|
{t('Connected Ethereum address')}
|
||||||
<EtherscanLink address={account} text={account} />
|
<Link
|
||||||
|
title={t('View address on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${account}`}
|
||||||
|
>
|
||||||
|
{account}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{t('stakingVegaWalletConnected', {
|
{t('stakingVegaWalletConnected', {
|
||||||
@ -94,7 +96,7 @@ export const StakingStepConnectWallets = () => {
|
|||||||
components={{
|
components={{
|
||||||
vegaWalletLink: (
|
vegaWalletLink: (
|
||||||
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
||||||
<a href={Links.WALLET_GUIDE} target="_blank" rel="noreferrer" />
|
<Link href={Links.WALLET_GUIDE} target="_blank" />
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -171,17 +173,17 @@ export const StakingStepAssociate = ({
|
|||||||
title={t('stakingHasAssociated', { tokens: formatNumber(associated) })}
|
title={t('stakingHasAssociated', { tokens: formatNumber(associated) })}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
<Link to="/staking/associate">
|
<RouteLink to="/staking/associate">
|
||||||
<Button data-testid="associate-more-tokens-btn">
|
<Button data-testid="associate-more-tokens-btn">
|
||||||
{t('stakingAssociateMoreButton')}
|
{t('stakingAssociateMoreButton')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</RouteLink>
|
||||||
</p>
|
</p>
|
||||||
<Link to="/staking/disassociate">
|
<RouteLink to="/staking/disassociate">
|
||||||
<Button data-testid="disassociate-tokens-btn">
|
<Button data-testid="disassociate-tokens-btn">
|
||||||
{t('stakingDisassociateButton')}
|
{t('stakingDisassociateButton')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</RouteLink>
|
||||||
</Callout>
|
</Callout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -189,11 +191,11 @@ export const StakingStepAssociate = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p>{t('stakingStep2Text')}</p>
|
<p>{t('stakingStep2Text')}</p>
|
||||||
<Link to="/staking/associate">
|
<RouteLink to="/staking/associate">
|
||||||
<Button data-testid="associate-tokens-btn">
|
<Button data-testid="associate-tokens-btn">
|
||||||
{t('associateButton')}
|
{t('associateButton')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</RouteLink>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
import { BigNumber } from '../../lib/bignumber';
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
@ -22,6 +23,7 @@ export const ValidatorTable = ({
|
|||||||
stakedTotal,
|
stakedTotal,
|
||||||
stakeThisEpoch,
|
stakeThisEpoch,
|
||||||
}: ValidatorTableProps) => {
|
}: ValidatorTableProps) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const stakePercentage = React.useMemo(() => {
|
const stakePercentage = React.useMemo(() => {
|
||||||
const total = new BigNumber(stakedTotal);
|
const total = new BigNumber(stakedTotal);
|
||||||
@ -56,10 +58,12 @@ export const ValidatorTable = ({
|
|||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<span>{t('ETHEREUM ADDRESS')}</span>
|
<span>{t('ETHEREUM ADDRESS')}</span>
|
||||||
<span>
|
<span>
|
||||||
<EtherscanLink
|
<Link
|
||||||
text={node.ethereumAdddress}
|
title={t('View address on Etherscan')}
|
||||||
address={node.ethereumAdddress}
|
href={`${ETHERSCAN_URL}/address/${node.ethereumAdddress}`}
|
||||||
/>
|
>
|
||||||
|
{node.ethereumAdddress}
|
||||||
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { ADDRESSES, EthereumChainIds } from '../../config';
|
import {
|
||||||
|
EthereumChainIds,
|
||||||
|
EnvironmentConfig,
|
||||||
|
Networks,
|
||||||
|
} from '@vegaprotocol/smart-contracts';
|
||||||
import type { TrancheLabelProps } from './tranche-label';
|
import type { TrancheLabelProps } from './tranche-label';
|
||||||
import { TrancheLabel } from './tranche-label';
|
import { TrancheLabel } from './tranche-label';
|
||||||
|
|
||||||
@ -9,7 +13,7 @@ let props: TrancheLabelProps;
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
props = {
|
props = {
|
||||||
chainId: EthereumChainIds.Mainnet,
|
chainId: EthereumChainIds.Mainnet,
|
||||||
contract: ADDRESSES.vestingAddress,
|
contract: EnvironmentConfig[Networks.MAINNET].vestingAddress,
|
||||||
id: 5,
|
id: 5,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ADDRESSES, EthereumChainIds } from '../../config';
|
import type { EthereumChainId } from '@vegaprotocol/smart-contracts';
|
||||||
import type { EthereumChainId } from '../../config';
|
import { EthereumChainIds } from '@vegaprotocol/smart-contracts';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
const TRANCHE_LABELS: Record<number, string[]> = {
|
const TRANCHE_LABELS: Record<number, string[]> = {
|
||||||
'5': ['Coinlist Option 1', 'Community Whitelist'],
|
'5': ['Coinlist Option 1', 'Community Whitelist'],
|
||||||
@ -26,6 +27,7 @@ export interface TrancheLabelProps {
|
|||||||
* @param id The tranche ID on this contract
|
* @param id The tranche ID on this contract
|
||||||
*/
|
*/
|
||||||
export const TrancheLabel = ({ contract, chainId, id }: TrancheLabelProps) => {
|
export const TrancheLabel = ({ contract, chainId, id }: TrancheLabelProps) => {
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
// Only mainnet tranches on the known vesting contract have useful name
|
// Only mainnet tranches on the known vesting contract have useful name
|
||||||
if (
|
if (
|
||||||
chainId &&
|
chainId &&
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import type { Tranche as ITranche } from '@vegaprotocol/smart-contracts';
|
import type {
|
||||||
|
Tranche as ITranche,
|
||||||
|
EthereumChainId,
|
||||||
|
} from '@vegaprotocol/smart-contracts';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -6,9 +9,8 @@ import { useParams } from 'react-router';
|
|||||||
import { Navigate } from 'react-router-dom';
|
import { Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { useOutletContext } from 'react-router-dom';
|
import { useOutletContext } from 'react-router-dom';
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { EthereumChainId } from '../../config';
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { ADDRESSES } from '../../config';
|
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
import { BigNumber } from '../../lib/bignumber';
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
import { TrancheItem } from '../redemption/tranche-item';
|
import { TrancheItem } from '../redemption/tranche-item';
|
||||||
@ -27,6 +29,7 @@ const TrancheProgressContents = ({
|
|||||||
|
|
||||||
export const Tranche = () => {
|
export const Tranche = () => {
|
||||||
const tranches = useOutletContext<ITranche[]>();
|
const tranches = useOutletContext<ITranche[]>();
|
||||||
|
const { ADDRESSES, ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { trancheId } = useParams<{ trancheId: string }>();
|
const { trancheId } = useParams<{ trancheId: string }>();
|
||||||
const { chainId } = useWeb3React();
|
const { chainId } = useWeb3React();
|
||||||
@ -81,7 +84,12 @@ export const Tranche = () => {
|
|||||||
const locked = user.remaining_tokens.times(lockedData?.locked || 0);
|
const locked = user.remaining_tokens.times(lockedData?.locked || 0);
|
||||||
return (
|
return (
|
||||||
<li className="pb-4" key={i}>
|
<li className="pb-4" key={i}>
|
||||||
<EtherscanLink address={user.address} text={user.address} />
|
<Link
|
||||||
|
title={t('View address on Etherscan')}
|
||||||
|
href={`${ETHERSCAN_URL}/tx/${user.address}`}
|
||||||
|
>
|
||||||
|
{user.address}
|
||||||
|
</Link>
|
||||||
<TrancheProgressContents>
|
<TrancheProgressContents>
|
||||||
<span>{t('Locked')}</span>
|
<span>{t('Locked')}</span>
|
||||||
<span>{t('Unlocked')}</span>
|
<span>{t('Unlocked')}</span>
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import { useOutletContext } from 'react-router-dom';
|
import { useOutletContext } from 'react-router-dom';
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
import type { Tranche, EthereumChainId } from '@vegaprotocol/smart-contracts';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { EthereumChainId } from '../../config';
|
|
||||||
import { ADDRESSES } from '../../config';
|
|
||||||
import { TrancheItem } from '../redemption/tranche-item';
|
import { TrancheItem } from '../redemption/tranche-item';
|
||||||
import { TrancheLabel } from './tranche-label';
|
import { TrancheLabel } from './tranche-label';
|
||||||
import { VestingChart } from './vesting-chart';
|
import { VestingChart } from './vesting-chart';
|
||||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
const trancheMinimum = 10;
|
const trancheMinimum = 10;
|
||||||
|
|
||||||
@ -17,6 +16,7 @@ const shouldShowTranche = (t: Tranche) =>
|
|||||||
!t.total_added.isLessThanOrEqualTo(trancheMinimum);
|
!t.total_added.isLessThanOrEqualTo(trancheMinimum);
|
||||||
|
|
||||||
export const Tranches = () => {
|
export const Tranches = () => {
|
||||||
|
const { ADDRESSES } = useEnvironment();
|
||||||
const tranches = useOutletContext<Tranche[]>();
|
const tranches = useOutletContext<Tranche[]>();
|
||||||
const [showAll, setShowAll] = React.useState<boolean>(false);
|
const [showAll, setShowAll] = React.useState<boolean>(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -4,7 +4,8 @@ import orderBy from 'lodash/orderBy';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { Heading } from '../../components/heading';
|
import { Heading } from '../../components/heading';
|
||||||
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
import { SplashLoader } from '../../components/splash-loader';
|
import { SplashLoader } from '../../components/splash-loader';
|
||||||
@ -99,6 +100,7 @@ interface WithdrawalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const Withdrawal = ({ withdrawal, complete }: WithdrawalProps) => {
|
export const Withdrawal = ({ withdrawal, complete }: WithdrawalProps) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const renderStatus = ({
|
const renderStatus = ({
|
||||||
@ -148,12 +150,12 @@ export const Withdrawal = ({ withdrawal, complete }: WithdrawalProps) => {
|
|||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
{t('toEthereum')}
|
{t('toEthereum')}
|
||||||
<span>
|
<span>
|
||||||
<EtherscanLink
|
<Link
|
||||||
address={withdrawal.details?.receiverAddress as string}
|
title={t('View address on Etherscan')}
|
||||||
text={truncateMiddle(
|
href={`${ETHERSCAN_URL}/tx/${withdrawal.details?.receiverAddress}`}
|
||||||
withdrawal.details?.receiverAddress as string
|
>
|
||||||
)}
|
{truncateMiddle(withdrawal.details?.receiverAddress ?? '')}
|
||||||
/>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
@ -169,10 +171,12 @@ export const Withdrawal = ({ withdrawal, complete }: WithdrawalProps) => {
|
|||||||
{t('withdrawalTransaction', { foreignChain: 'Ethereum' })}
|
{t('withdrawalTransaction', { foreignChain: 'Ethereum' })}
|
||||||
<span>
|
<span>
|
||||||
{withdrawal.txHash ? (
|
{withdrawal.txHash ? (
|
||||||
<EtherscanLink
|
<Link
|
||||||
tx={withdrawal.txHash}
|
title={t('View transaction on Etherscan')}
|
||||||
text={truncateMiddle(withdrawal.txHash)}
|
href={`${ETHERSCAN_URL}/tx/${withdrawal.txHash}`}
|
||||||
/>
|
>
|
||||||
|
{truncateMiddle(withdrawal.txHash)}
|
||||||
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
'-'
|
'-'
|
||||||
)}
|
)}
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": false,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true
|
||||||
"resolveJsonModule": true
|
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
"include": [],
|
"include": [],
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
VegaManageDialog,
|
VegaManageDialog,
|
||||||
VegaWalletProvider,
|
VegaWalletProvider,
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
|
import { EnvironmentProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { Connectors } from '../lib/vega-connectors';
|
import { Connectors } from '../lib/vega-connectors';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { createClient } from '../lib/apollo-client';
|
import { createClient } from '../lib/apollo-client';
|
||||||
@ -25,63 +26,68 @@ function VegaTradingApp({ Component, pageProps }: AppProps) {
|
|||||||
const [theme, toggleTheme] = useThemeSwitcher();
|
const [theme, toggleTheme] = useThemeSwitcher();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Provider value={theme}>
|
<EnvironmentProvider>
|
||||||
<ApolloProvider client={client}>
|
<ThemeContext.Provider value={theme}>
|
||||||
<VegaWalletProvider>
|
<ApolloProvider client={client}>
|
||||||
<AppLoader>
|
<VegaWalletProvider>
|
||||||
<Head>
|
<AppLoader>
|
||||||
<link
|
<Head>
|
||||||
rel="preload"
|
<link
|
||||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
rel="preload"
|
||||||
as="font"
|
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||||
type="font/woff2"
|
as="font"
|
||||||
crossOrigin="anonymous"
|
type="font/woff2"
|
||||||
/>
|
crossOrigin="anonymous"
|
||||||
<title>{t('Welcome to Vega trading!')}</title>
|
/>
|
||||||
<link
|
<title>{t('Welcome to Vega trading!')}</title>
|
||||||
rel="icon"
|
<link
|
||||||
type="image/x-icon"
|
rel="icon"
|
||||||
href="https://static.vega.xyz/favicon.ico"
|
type="image/x-icon"
|
||||||
/>
|
href="https://static.vega.xyz/favicon.ico"
|
||||||
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
/>
|
||||||
</Head>
|
<link
|
||||||
<div className="h-full dark:bg-black dark:text-white-60 bg-white relative z-0 text-black-60 grid grid-rows-[min-content,1fr]">
|
rel="stylesheet"
|
||||||
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
|
href="https://static.vega.xyz/fonts.css"
|
||||||
<Navbar />
|
/>
|
||||||
<div className="flex items-center gap-4 ml-auto mr-8">
|
</Head>
|
||||||
<VegaWalletConnectButton
|
<div className="h-full dark:bg-black dark:text-white-60 bg-white relative z-0 text-black-60 grid grid-rows-[min-content,1fr]">
|
||||||
setConnectDialog={(open) =>
|
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
|
||||||
setVegaWallet((x) => ({ ...x, connect: open }))
|
<Navbar />
|
||||||
}
|
<div className="flex items-center gap-4 ml-auto mr-8">
|
||||||
setManageDialog={(open) =>
|
<VegaWalletConnectButton
|
||||||
setVegaWallet((x) => ({ ...x, manage: open }))
|
setConnectDialog={(open) =>
|
||||||
}
|
setVegaWallet((x) => ({ ...x, connect: open }))
|
||||||
/>
|
}
|
||||||
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
setManageDialog={(open) =>
|
||||||
|
setVegaWallet((x) => ({ ...x, manage: open }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<main data-testid={pageProps.page}>
|
||||||
|
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</main>
|
||||||
|
<VegaConnectDialog
|
||||||
|
connectors={Connectors}
|
||||||
|
dialogOpen={vegaWallet.connect}
|
||||||
|
setDialogOpen={(open) =>
|
||||||
|
setVegaWallet((x) => ({ ...x, connect: open }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<VegaManageDialog
|
||||||
|
dialogOpen={vegaWallet.manage}
|
||||||
|
setDialogOpen={(open) =>
|
||||||
|
setVegaWallet((x) => ({ ...x, manage: open }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<main data-testid={pageProps.page}>
|
</AppLoader>
|
||||||
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
|
</VegaWalletProvider>
|
||||||
<Component {...pageProps} />
|
</ApolloProvider>
|
||||||
</main>
|
</ThemeContext.Provider>
|
||||||
<VegaConnectDialog
|
</EnvironmentProvider>
|
||||||
connectors={Connectors}
|
|
||||||
dialogOpen={vegaWallet.connect}
|
|
||||||
setDialogOpen={(open) =>
|
|
||||||
setVegaWallet((x) => ({ ...x, connect: open }))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<VegaManageDialog
|
|
||||||
dialogOpen={vegaWallet.manage}
|
|
||||||
setDialogOpen={(open) =>
|
|
||||||
setVegaWallet((x) => ({ ...x, manage: open }))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</AppLoader>
|
|
||||||
</VegaWalletProvider>
|
|
||||||
</ApolloProvider>
|
|
||||||
</ThemeContext.Provider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
|
|||||||
import { PageQueryContainer } from '../../../components/page-query-container';
|
import { PageQueryContainer } from '../../../components/page-query-container';
|
||||||
import type { DepositPage } from './__generated__/DepositPage';
|
import type { DepositPage } from './__generated__/DepositPage';
|
||||||
import { DepositManager } from '@vegaprotocol/deposits';
|
import { DepositManager } from '@vegaprotocol/deposits';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t, useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { ASSET_FRAGMENT } from '../../../lib/query-fragments';
|
import { ASSET_FRAGMENT } from '../../../lib/query-fragments';
|
||||||
|
|
||||||
@ -28,6 +28,8 @@ export const DepositContainer = ({
|
|||||||
ethereumConfig,
|
ethereumConfig,
|
||||||
assetId,
|
assetId,
|
||||||
}: DepositContainerProps) => {
|
}: DepositContainerProps) => {
|
||||||
|
const { VEGA_ENV } = useEnvironment();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageQueryContainer<DepositPage>
|
<PageQueryContainer<DepositPage>
|
||||||
query={DEPOSIT_PAGE_QUERY}
|
query={DEPOSIT_PAGE_QUERY}
|
||||||
@ -46,6 +48,7 @@ export const DepositContainer = ({
|
|||||||
requiredConfirmations={ethereumConfig.confirmations}
|
requiredConfirmations={ethereumConfig.confirmations}
|
||||||
assets={data.assets}
|
assets={data.assets}
|
||||||
initialAssetId={assetId}
|
initialAssetId={assetId}
|
||||||
|
isFaucetable={VEGA_ENV !== 'MAINNET'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"incremental": true
|
"incremental": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export const FAUCETABLE = process.env['NX_VEGA_ENV'] !== 'MAINNET';
|
|
@ -41,6 +41,7 @@ beforeEach(() => {
|
|||||||
max: new BigNumber(20),
|
max: new BigNumber(20),
|
||||||
},
|
},
|
||||||
allowance: new BigNumber(30),
|
allowance: new BigNumber(30),
|
||||||
|
isFaucetable: true,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ import { useMemo } from 'react';
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useForm, useWatch } from 'react-hook-form';
|
import { useForm, useWatch } from 'react-hook-form';
|
||||||
import { DepositLimits } from './deposit-limits';
|
import { DepositLimits } from './deposit-limits';
|
||||||
import { FAUCETABLE } from '../config';
|
|
||||||
import type { Asset } from './deposit-manager';
|
import type { Asset } from './deposit-manager';
|
||||||
|
|
||||||
interface FormFields {
|
interface FormFields {
|
||||||
@ -51,6 +50,7 @@ export interface DepositFormProps {
|
|||||||
max: BigNumber;
|
max: BigNumber;
|
||||||
} | null;
|
} | null;
|
||||||
allowance: BigNumber | undefined;
|
allowance: BigNumber | undefined;
|
||||||
|
isFaucetable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DepositForm = ({
|
export const DepositForm = ({
|
||||||
@ -63,6 +63,7 @@ export const DepositForm = ({
|
|||||||
requestFaucet,
|
requestFaucet,
|
||||||
limits,
|
limits,
|
||||||
allowance,
|
allowance,
|
||||||
|
isFaucetable,
|
||||||
}: DepositFormProps) => {
|
}: DepositFormProps) => {
|
||||||
const { account } = useWeb3React();
|
const { account } = useWeb3React();
|
||||||
const { keypair } = useVegaWallet();
|
const { keypair } = useVegaWallet();
|
||||||
@ -166,7 +167,7 @@ export const DepositForm = ({
|
|||||||
{errors.asset.message}
|
{errors.asset.message}
|
||||||
</InputError>
|
</InputError>
|
||||||
)}
|
)}
|
||||||
{FAUCETABLE && selectedAsset && (
|
{isFaucetable && selectedAsset && (
|
||||||
<UseButton onClick={requestFaucet}>
|
<UseButton onClick={requestFaucet}>
|
||||||
{t(`Get ${selectedAsset.symbol}`)}
|
{t(`Get ${selectedAsset.symbol}`)}
|
||||||
</UseButton>
|
</UseButton>
|
||||||
|
@ -34,6 +34,7 @@ interface DepositManagerProps {
|
|||||||
bridgeAddress: string;
|
bridgeAddress: string;
|
||||||
assets: Asset[];
|
assets: Asset[];
|
||||||
initialAssetId?: string;
|
initialAssetId?: string;
|
||||||
|
isFaucetable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DepositManager = ({
|
export const DepositManager = ({
|
||||||
@ -41,6 +42,7 @@ export const DepositManager = ({
|
|||||||
bridgeAddress,
|
bridgeAddress,
|
||||||
assets,
|
assets,
|
||||||
initialAssetId,
|
initialAssetId,
|
||||||
|
isFaucetable,
|
||||||
}: DepositManagerProps) => {
|
}: DepositManagerProps) => {
|
||||||
const [assetId, setAssetId] = useState<string | undefined>(initialAssetId);
|
const [assetId, setAssetId] = useState<string | undefined>(initialAssetId);
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ export const DepositManager = ({
|
|||||||
asset?.source.__typename === 'ERC20'
|
asset?.source.__typename === 'ERC20'
|
||||||
? asset.source.contractAddress
|
? asset.source.contractAddress
|
||||||
: undefined,
|
: undefined,
|
||||||
process.env['NX_VEGA_ENV'] !== 'MAINNET'
|
isFaucetable
|
||||||
);
|
);
|
||||||
const bridgeContract = useBridgeContract();
|
const bridgeContract = useBridgeContract();
|
||||||
|
|
||||||
@ -101,6 +103,7 @@ export const DepositManager = ({
|
|||||||
requestFaucet={faucet.perform}
|
requestFaucet={faucet.perform}
|
||||||
limits={limits}
|
limits={limits}
|
||||||
allowance={allowance}
|
allowance={allowance}
|
||||||
|
isFaucetable={isFaucetable}
|
||||||
/>
|
/>
|
||||||
<TransactionDialog {...approve.transaction} name="approve" />
|
<TransactionDialog {...approve.transaction} name="approve" />
|
||||||
<TransactionDialog {...faucet.transaction} name="faucet" />
|
<TransactionDialog {...faucet.transaction} name="faucet" />
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -2,3 +2,4 @@ export * from './use-apply-grid-transaction';
|
|||||||
export * from './use-data-provider';
|
export * from './use-data-provider';
|
||||||
export * from './use-theme-switcher';
|
export * from './use-theme-switcher';
|
||||||
export * from './use-fetch';
|
export * from './use-fetch';
|
||||||
|
export * from './use-environment';
|
||||||
|
125
libs/react-helpers/src/hooks/use-environment.tsx
Normal file
125
libs/react-helpers/src/hooks/use-environment.tsx
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import type { Networks } from '@vegaprotocol/smart-contracts';
|
||||||
|
import { EnvironmentConfig } from '@vegaprotocol/smart-contracts';
|
||||||
|
import { createContext, useContext } from 'react';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
_ENV?: RawEnvironment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type VegaContracts = typeof EnvironmentConfig[Networks];
|
||||||
|
|
||||||
|
type EnvironmentProviderProps = {
|
||||||
|
definintions?: Partial<RawEnvironment>;
|
||||||
|
children?: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ENV_KEYS = [
|
||||||
|
'VEGA_URL',
|
||||||
|
'VEGA_ENV',
|
||||||
|
'ETHEREUM_CHAIN_ID',
|
||||||
|
'ETHEREUM_PROVIDER_URL',
|
||||||
|
'ETHERSCAN_URL',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
type EnvKey = typeof ENV_KEYS[number];
|
||||||
|
|
||||||
|
type RawEnvironment = Record<EnvKey, string>;
|
||||||
|
|
||||||
|
export type Environment = {
|
||||||
|
VEGA_URL: string;
|
||||||
|
VEGA_ENV: Networks;
|
||||||
|
ETHEREUM_CHAIN_ID: number;
|
||||||
|
ETHEREUM_PROVIDER_URL: string;
|
||||||
|
ETHERSCAN_URL: string;
|
||||||
|
ADDRESSES: VegaContracts;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBundledEnvironmentValue = (key: EnvKey) => {
|
||||||
|
switch (key) {
|
||||||
|
// need to have these hardcoded so on build time we can insert sensible defaults
|
||||||
|
case 'VEGA_URL':
|
||||||
|
return process.env['NX_VEGA_URL'];
|
||||||
|
case 'VEGA_ENV':
|
||||||
|
return process.env['NX_VEGA_ENV'];
|
||||||
|
case 'ETHEREUM_CHAIN_ID':
|
||||||
|
return process.env['NX_ETHEREUM_CHAIN_ID'];
|
||||||
|
case 'ETHEREUM_PROVIDER_URL':
|
||||||
|
return process.env['NX_ETHEREUM_PROVIDER_URL'];
|
||||||
|
case 'ETHERSCAN_URL':
|
||||||
|
return process.env['NX_ETHERSCAN_URL'];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const transformValue = (key: EnvKey, value?: string) => {
|
||||||
|
switch (key) {
|
||||||
|
case 'VEGA_ENV':
|
||||||
|
return value as Networks;
|
||||||
|
case 'ETHEREUM_CHAIN_ID':
|
||||||
|
return value && Number(value);
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getValue = (key: EnvKey, definintions: Partial<RawEnvironment> = {}) => {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return transformValue(
|
||||||
|
key,
|
||||||
|
definintions[key] ?? getBundledEnvironmentValue(key)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return transformValue(
|
||||||
|
key,
|
||||||
|
window._ENV?.[key] ?? definintions[key] ?? getBundledEnvironmentValue(key)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const EnvironmentContext = createContext({} as Environment);
|
||||||
|
|
||||||
|
export const EnvironmentProvider = ({
|
||||||
|
definintions,
|
||||||
|
children,
|
||||||
|
}: EnvironmentProviderProps) => {
|
||||||
|
const environment = ENV_KEYS.reduce(
|
||||||
|
(acc, key) => ({
|
||||||
|
...acc,
|
||||||
|
[key]: getValue(key, definintions),
|
||||||
|
}),
|
||||||
|
{} as Environment
|
||||||
|
);
|
||||||
|
|
||||||
|
const missingKeys = Object.keys(environment)
|
||||||
|
.filter((key) => typeof environment[key as EnvKey] === undefined)
|
||||||
|
.map((key) => `"${key}"`)
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
if (missingKeys.length) {
|
||||||
|
throw new Error(
|
||||||
|
`Error setting up the app environment. The following variables are missing from your environment: ${missingKeys}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EnvironmentContext.Provider
|
||||||
|
value={{
|
||||||
|
...environment,
|
||||||
|
ADDRESSES: EnvironmentConfig[environment['VEGA_ENV']],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</EnvironmentContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useEnvironment = () => {
|
||||||
|
const context = useContext(EnvironmentContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
'Error running "useEnvironment". No context found, make sure your component is wrapped in an <EnvironmentProvider />.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
{
|
{
|
||||||
"presets": ["@babel/preset-typescript"]
|
"presets": [
|
||||||
|
[
|
||||||
|
"@nrwl/react/babel",
|
||||||
|
{
|
||||||
|
"runtime": "automatic",
|
||||||
|
"useBuiltIns": "usage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"plugins": []
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
displayName: 'smart-contracts',
|
displayName: 'smart-contracts',
|
||||||
preset: '../../jest.preset.js',
|
preset: '../../jest.preset.js',
|
||||||
globals: {
|
|
||||||
'ts-jest': {
|
|
||||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.[tj]s$': 'ts-jest',
|
'^.+\\.[tj]sx?$': 'babel-jest',
|
||||||
},
|
},
|
||||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||||
coverageDirectory: '../../coverage/libs/smart-contracts',
|
coverageDirectory: '../../coverage/libs/smart-contracts',
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": false,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"resolveJsonModule": true,
|
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -6,6 +6,5 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||||
coverageDirectory: '../../coverage/libs/ui-toolkit',
|
coverageDirectory: '../../coverage/libs/ui-toolkit',
|
||||||
setupFiles: ['./src/setup-test-env.ts'],
|
|
||||||
setupFilesAfterEnv: ['./src/setup-tests.ts'],
|
setupFilesAfterEnv: ['./src/setup-tests.ts'],
|
||||||
};
|
};
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import { EtherscanLink } from '.';
|
|
||||||
|
|
||||||
it('renders a link with the text', () => {
|
|
||||||
render(<EtherscanLink text="foo" tx="tx" />);
|
|
||||||
expect(screen.getByText('foo')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders a link with the tx hash if no text is provided', () => {
|
|
||||||
render(<EtherscanLink tx="tx" />);
|
|
||||||
expect(screen.getByText('tx')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders a link with the address if no text is provided', () => {
|
|
||||||
render(<EtherscanLink address="address" />);
|
|
||||||
expect(screen.getByText('address')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('links to etherscan address', () => {
|
|
||||||
const hash = 'hash';
|
|
||||||
render(<EtherscanLink address={hash} />);
|
|
||||||
expect(screen.getByTestId('etherscan-link')).toHaveAttribute(
|
|
||||||
'href',
|
|
||||||
`${process.env['NX_ETHERSCAN_URL']}/address/${hash}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('links to etherscan transaction', () => {
|
|
||||||
const hash = 'hash';
|
|
||||||
render(<EtherscanLink tx={hash} />);
|
|
||||||
expect(screen.getByTestId('etherscan-link')).toHaveAttribute(
|
|
||||||
'href',
|
|
||||||
`${process.env['NX_ETHERSCAN_URL']}/tx/${hash}`
|
|
||||||
);
|
|
||||||
});
|
|
@ -1,24 +0,0 @@
|
|||||||
import type { ComponentStory, ComponentMeta } from '@storybook/react';
|
|
||||||
|
|
||||||
import { EtherscanLink } from '.';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: 'EtherscanLink',
|
|
||||||
component: EtherscanLink,
|
|
||||||
} as ComponentMeta<typeof EtherscanLink>;
|
|
||||||
|
|
||||||
const Template: ComponentStory<typeof EtherscanLink> = (args) => (
|
|
||||||
<EtherscanLink {...args} />
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Transaction = Template.bind({});
|
|
||||||
Transaction.args = {
|
|
||||||
tx: 'foo',
|
|
||||||
text: 'View transaction on Etherscan',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Address = Template.bind({});
|
|
||||||
Address.args = {
|
|
||||||
address: 'foo',
|
|
||||||
text: 'View transaction on Etherscan',
|
|
||||||
};
|
|
@ -1,65 +0,0 @@
|
|||||||
import classNames from 'classnames';
|
|
||||||
import type { AnchorHTMLAttributes } from 'react';
|
|
||||||
|
|
||||||
const ETHERSCAN_URL = process.env['NX_ETHERSCAN_URL'] as string;
|
|
||||||
|
|
||||||
interface BaseEtherscanLinkProps
|
|
||||||
extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
||||||
text?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EtherscanAddressLinkProps extends BaseEtherscanLinkProps {
|
|
||||||
address: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EtherscanTransactionLinkProps extends BaseEtherscanLinkProps {
|
|
||||||
tx: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type EtherscanLinkProps =
|
|
||||||
| EtherscanAddressLinkProps
|
|
||||||
| EtherscanTransactionLinkProps;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Form an HTML link tag pointing to an appropriate Etherscan page
|
|
||||||
*/
|
|
||||||
export const EtherscanLink = ({
|
|
||||||
text,
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: EtherscanLinkProps) => {
|
|
||||||
let hash: string;
|
|
||||||
let txLink: string | null;
|
|
||||||
const anchorClasses = classNames('underline', className);
|
|
||||||
|
|
||||||
if ('tx' in props) {
|
|
||||||
hash = props.tx;
|
|
||||||
txLink = `${ETHERSCAN_URL}/tx/${hash}`;
|
|
||||||
} else if ('address' in props) {
|
|
||||||
hash = props.address;
|
|
||||||
txLink = `${ETHERSCAN_URL}/address/${hash}`;
|
|
||||||
} else {
|
|
||||||
throw new Error('Must provider either "tx" or "address" prop');
|
|
||||||
}
|
|
||||||
|
|
||||||
const linkText = text ? text : hash;
|
|
||||||
|
|
||||||
// Fallback: just render the TX id
|
|
||||||
if (!txLink) {
|
|
||||||
return <span>{hash}</span>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
data-testid="etherscan-link"
|
|
||||||
href={txLink}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className={anchorClasses}
|
|
||||||
>
|
|
||||||
{linkText}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
EtherscanLink.displayName = 'EtherScanLink';
|
|
@ -1 +0,0 @@
|
|||||||
export { EtherscanLink } from './etherscan-link';
|
|
@ -7,7 +7,7 @@ export * from './card';
|
|||||||
export * from './copy-with-tooltip';
|
export * from './copy-with-tooltip';
|
||||||
export * from './dialog';
|
export * from './dialog';
|
||||||
export * from './dropdown-menu';
|
export * from './dropdown-menu';
|
||||||
export * from './etherscan-link';
|
export * from './link';
|
||||||
export * from './form-group';
|
export * from './form-group';
|
||||||
export * from './icon';
|
export * from './icon';
|
||||||
export * from './indicator';
|
export * from './indicator';
|
||||||
|
1
libs/ui-toolkit/src/components/link/index.ts
Normal file
1
libs/ui-toolkit/src/components/link/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Link } from './link';
|
34
libs/ui-toolkit/src/components/link/link.spec.tsx
Normal file
34
libs/ui-toolkit/src/components/link/link.spec.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { Link } from '.';
|
||||||
|
|
||||||
|
it('renders a link with a text', () => {
|
||||||
|
render(
|
||||||
|
<Link href="127.0.0.1" title="Link title">
|
||||||
|
Link text
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
const link = screen.getByRole('link', { name: 'Link title' });
|
||||||
|
expect(link).toBeInTheDocument();
|
||||||
|
expect(link).toHaveAttribute('data-testid', 'link');
|
||||||
|
expect(link).toHaveAttribute('referrerPolicy', 'strict-origin');
|
||||||
|
expect(link).toHaveAttribute('href', '127.0.0.1');
|
||||||
|
expect(link).toHaveAttribute('title', 'Link title');
|
||||||
|
expect(link).toHaveClass('cursor-pointer');
|
||||||
|
expect(link).toHaveClass('underline');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a link with children elements', () => {
|
||||||
|
render(
|
||||||
|
<Link href="127.0.0.1" title="Link title">
|
||||||
|
<span>Link text</span>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
const link = screen.getByRole('link', { name: 'Link title' });
|
||||||
|
expect(link).toBeInTheDocument();
|
||||||
|
expect(link).toHaveAttribute('data-testid', 'link');
|
||||||
|
expect(link).toHaveAttribute('referrerPolicy', 'strict-origin');
|
||||||
|
expect(link).toHaveAttribute('href', '127.0.0.1');
|
||||||
|
expect(link).toHaveAttribute('title', 'Link title');
|
||||||
|
expect(link).toHaveClass('cursor-pointer');
|
||||||
|
expect(link).not.toHaveClass('underline');
|
||||||
|
});
|
25
libs/ui-toolkit/src/components/link/link.stories.tsx
Normal file
25
libs/ui-toolkit/src/components/link/link.stories.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import type { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||||
|
|
||||||
|
import { Link } from '.';
|
||||||
|
import { VegaLogo } from '../vega-logo';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Link',
|
||||||
|
component: Link,
|
||||||
|
} as ComponentMeta<typeof Link>;
|
||||||
|
|
||||||
|
const Template: ComponentStory<typeof Link> = (args) => <Link {...args} />;
|
||||||
|
|
||||||
|
export const Text = Template.bind({});
|
||||||
|
Text.args = {
|
||||||
|
title: 'Link title',
|
||||||
|
href: '/',
|
||||||
|
children: 'View link',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Element = Template.bind({});
|
||||||
|
Element.args = {
|
||||||
|
title: 'Link title',
|
||||||
|
href: '/',
|
||||||
|
children: <VegaLogo />,
|
||||||
|
};
|
29
libs/ui-toolkit/src/components/link/link.tsx
Normal file
29
libs/ui-toolkit/src/components/link/link.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
|
import type { ReactNode, AnchorHTMLAttributes } from 'react';
|
||||||
|
|
||||||
|
type LinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||||
|
children?: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form an HTML link tag
|
||||||
|
*/
|
||||||
|
export const Link = ({ className, children, ...props }: LinkProps) => {
|
||||||
|
const anchorClassName = classNames(className, 'cursor-pointer', {
|
||||||
|
underline: typeof children === 'string',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
role="link"
|
||||||
|
data-testid="link"
|
||||||
|
referrerPolicy="strict-origin"
|
||||||
|
className={anchorClassName}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Link.displayName = 'Link';
|
@ -1 +0,0 @@
|
|||||||
process.env['NX_ETHERSCAN_URL'] = 'https://etherscan.io';
|
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
import { EthTxStatus } from '../use-ethereum-transaction';
|
import { EthTxStatus } from '../use-ethereum-transaction';
|
||||||
|
|
||||||
const ACTIVE_CLASSES = 'text-black dark:text-white';
|
const ACTIVE_CLASSES = 'text-black dark:text-white';
|
||||||
@ -31,6 +32,8 @@ export const TxRow = ({
|
|||||||
requiredConfirmations,
|
requiredConfirmations,
|
||||||
highlightComplete = true,
|
highlightComplete = true,
|
||||||
}: TxRowProps) => {
|
}: TxRowProps) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
|
|
||||||
if (status === EthTxStatus.Pending) {
|
if (status === EthTxStatus.Pending) {
|
||||||
return (
|
return (
|
||||||
<p className={`flex justify-between ${ACTIVE_CLASSES}`}>
|
<p className={`flex justify-between ${ACTIVE_CLASSES}`}>
|
||||||
@ -39,11 +42,13 @@ export const TxRow = ({
|
|||||||
`Awaiting Ethereum transaction ${confirmations}/${requiredConfirmations} confirmations...`
|
`Awaiting Ethereum transaction ${confirmations}/${requiredConfirmations} confirmations...`
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<EtherscanLink
|
<Link
|
||||||
tx={txHash || ''}
|
href={`${ETHERSCAN_URL}/tx/${txHash}`}
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
className="text-vega-pink dark:text-vega-yellow"
|
className="text-vega-pink dark:text-vega-yellow"
|
||||||
text={t('View on Etherscan')}
|
>
|
||||||
/>
|
{t('View on Etherscan')}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -56,11 +61,13 @@ export const TxRow = ({
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span>{t('Ethereum transaction complete')}</span>
|
<span>{t('Ethereum transaction complete')}</span>
|
||||||
<EtherscanLink
|
<Link
|
||||||
tx={txHash || ''}
|
href={`${ETHERSCAN_URL}/tx/${txHash}`}
|
||||||
|
title={t('View on Etherscan')}
|
||||||
className="text-vega-pink dark:text-vega-yellow"
|
className="text-vega-pink dark:text-vega-yellow"
|
||||||
text={t('View on Etherscan')}
|
>
|
||||||
/>
|
{t('View transaction on Etherscan')}
|
||||||
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ it('Dialog states', () => {
|
|||||||
expect(
|
expect(
|
||||||
screen.getByText('Awaiting Ethereum transaction 0/1 confirmations...')
|
screen.getByText('Awaiting Ethereum transaction 0/1 confirmations...')
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('etherscan-link')).toBeInTheDocument();
|
expect(screen.getByTestId('link')).toBeInTheDocument();
|
||||||
|
|
||||||
rerender(generateJsx({ status: EthTxStatus.Complete, confirmations: 1 }));
|
rerender(generateJsx({ status: EthTxStatus.Complete, confirmations: 1 }));
|
||||||
expect(screen.getByText(`${props.name} complete`)).toBeInTheDocument();
|
expect(screen.getByText(`${props.name} complete`)).toBeInTheDocument();
|
||||||
|
@ -1,21 +1,18 @@
|
|||||||
import type { Networks } from '@vegaprotocol/smart-contracts';
|
|
||||||
import { VegaErc20Bridge } from '@vegaprotocol/smart-contracts';
|
import { VegaErc20Bridge } from '@vegaprotocol/smart-contracts';
|
||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export const useBridgeContract = () => {
|
export const useBridgeContract = () => {
|
||||||
|
const { VEGA_ENV } = useEnvironment();
|
||||||
const { provider } = useWeb3React();
|
const { provider } = useWeb3React();
|
||||||
|
|
||||||
const contract = useMemo(() => {
|
const contract = useMemo(() => {
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new VegaErc20Bridge(
|
return new VegaErc20Bridge(VEGA_ENV, provider, provider?.getSigner());
|
||||||
process.env['NX_VEGA_ENV'] as Networks,
|
}, [provider, VEGA_ENV]);
|
||||||
provider,
|
|
||||||
provider?.getSigner()
|
|
||||||
);
|
|
||||||
}, [provider]);
|
|
||||||
|
|
||||||
return contract;
|
return contract;
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
import {
|
import { Link, Dialog, Icon, Intent, Loader } from '@vegaprotocol/ui-toolkit';
|
||||||
Dialog,
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
EtherscanLink,
|
|
||||||
Icon,
|
|
||||||
Intent,
|
|
||||||
Loader,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
@ -28,7 +23,8 @@ export const WithdrawDialog = ({
|
|||||||
dialogOpen,
|
dialogOpen,
|
||||||
onDialogChange,
|
onDialogChange,
|
||||||
}: WithdrawDialogProps) => {
|
}: WithdrawDialogProps) => {
|
||||||
const { intent, ...props } = getProps(approval, vegaTx, ethTx);
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
|
const { intent, ...props } = getProps(approval, vegaTx, ethTx, ETHERSCAN_URL);
|
||||||
return (
|
return (
|
||||||
<Dialog open={dialogOpen} intent={intent} onChange={onDialogChange}>
|
<Dialog open={dialogOpen} intent={intent} onChange={onDialogChange}>
|
||||||
<DialogWrapper {...props} />
|
<DialogWrapper {...props} />
|
||||||
@ -85,7 +81,8 @@ interface DialogProps {
|
|||||||
const getProps = (
|
const getProps = (
|
||||||
approval: Erc20Approval_erc20WithdrawalApproval | null,
|
approval: Erc20Approval_erc20WithdrawalApproval | null,
|
||||||
vegaTx: VegaTxState,
|
vegaTx: VegaTxState,
|
||||||
ethTx: EthTxState
|
ethTx: EthTxState,
|
||||||
|
ethUrl: string
|
||||||
) => {
|
) => {
|
||||||
const vegaTxPropsMap: Record<VegaTxStatus, DialogProps> = {
|
const vegaTxPropsMap: Record<VegaTxStatus, DialogProps> = {
|
||||||
[VegaTxStatus.Default]: {
|
[VegaTxStatus.Default]: {
|
||||||
@ -156,11 +153,13 @@ const getProps = (
|
|||||||
`Awaiting Ethereum transaction ${ethTx.confirmations}/1 confirmations...`
|
`Awaiting Ethereum transaction ${ethTx.confirmations}/1 confirmations...`
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<EtherscanLink
|
<Link
|
||||||
tx={ethTx.txHash || ''}
|
href={`${ethUrl}/tx/${ethTx.txHash}`}
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
className="text-vega-pink dark:text-vega-yellow"
|
className="text-vega-pink dark:text-vega-yellow"
|
||||||
text={t('View on Etherscan')}
|
>
|
||||||
/>
|
{t('View on Etherscan')}
|
||||||
|
</Link>
|
||||||
</Step>
|
</Step>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -171,11 +170,13 @@ const getProps = (
|
|||||||
children: (
|
children: (
|
||||||
<Step>
|
<Step>
|
||||||
<span>{t('Ethereum transaction complete')}</span>
|
<span>{t('Ethereum transaction complete')}</span>
|
||||||
<EtherscanLink
|
<Link
|
||||||
tx={ethTx.txHash || ''}
|
href={`${ethUrl}/tx/${ethTx.txHash}`}
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
className="text-vega-pink dark:text-vega-yellow"
|
className="text-vega-pink dark:text-vega-yellow"
|
||||||
text={t('View on Etherscan')}
|
>
|
||||||
/>
|
{t('View on Etherscan')}
|
||||||
|
</Link>
|
||||||
</Step>
|
</Step>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -10,10 +10,8 @@ import {
|
|||||||
formatNumber,
|
formatNumber,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { WithdrawalStatus } from '@vegaprotocol/types';
|
import { WithdrawalStatus } from '@vegaprotocol/types';
|
||||||
import {
|
import { Link, AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||||
EtherscanLink,
|
import { useEnvironment } from '@vegaprotocol/react-helpers';
|
||||||
AgGridDynamic as AgGrid,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { TransactionDialog } from '@vegaprotocol/web3';
|
import { TransactionDialog } from '@vegaprotocol/web3';
|
||||||
import { useCompleteWithdraw } from './use-complete-withdraw';
|
import { useCompleteWithdraw } from './use-complete-withdraw';
|
||||||
import type { Withdrawals_party_withdrawals } from './__generated__/Withdrawals';
|
import type { Withdrawals_party_withdrawals } from './__generated__/Withdrawals';
|
||||||
@ -23,6 +21,7 @@ export interface WithdrawalsTableProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const WithdrawalsTable = ({ withdrawals }: WithdrawalsTableProps) => {
|
export const WithdrawalsTable = ({ withdrawals }: WithdrawalsTableProps) => {
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
const { transaction, submit } = useCompleteWithdraw();
|
const { transaction, submit } = useCompleteWithdraw();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -47,6 +46,7 @@ export const WithdrawalsTable = ({ withdrawals }: WithdrawalsTableProps) => {
|
|||||||
headerName="Recipient"
|
headerName="Recipient"
|
||||||
field="details.receiverAddress"
|
field="details.receiverAddress"
|
||||||
cellRenderer="RecipientCell"
|
cellRenderer="RecipientCell"
|
||||||
|
cellRendererParams={{ ethUrl: ETHERSCAN_URL }}
|
||||||
valueFormatter={({ value }: ValueFormatterParams) => {
|
valueFormatter={({ value }: ValueFormatterParams) => {
|
||||||
return truncateByChars(value);
|
return truncateByChars(value);
|
||||||
}}
|
}}
|
||||||
@ -62,7 +62,7 @@ export const WithdrawalsTable = ({ withdrawals }: WithdrawalsTableProps) => {
|
|||||||
headerName="Status"
|
headerName="Status"
|
||||||
field="status"
|
field="status"
|
||||||
cellRenderer="StatusCell"
|
cellRenderer="StatusCell"
|
||||||
cellRendererParams={{ complete: submit }}
|
cellRendererParams={{ complete: submit, ethUrl: ETHERSCAN_URL }}
|
||||||
/>
|
/>
|
||||||
</AgGrid>
|
</AgGrid>
|
||||||
<TransactionDialog name="withdraw" {...transaction} />
|
<TransactionDialog name="withdraw" {...transaction} />
|
||||||
@ -71,16 +71,28 @@ export const WithdrawalsTable = ({ withdrawals }: WithdrawalsTableProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface StatusCellProps extends ICellRendererParams {
|
export interface StatusCellProps extends ICellRendererParams {
|
||||||
|
ethUrl: string;
|
||||||
complete: (withdrawalId: string) => void;
|
complete: (withdrawalId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const StatusCell = ({ value, data, complete }: StatusCellProps) => {
|
export const StatusCell = ({
|
||||||
|
ethUrl,
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
complete,
|
||||||
|
}: StatusCellProps) => {
|
||||||
if (data.pendingOnForeignChain) {
|
if (data.pendingOnForeignChain) {
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between gap-8">
|
<div className="flex justify-between gap-8">
|
||||||
{t('Pending')}
|
{t('Pending')}
|
||||||
{data.txHash && (
|
{data.txHash && (
|
||||||
<EtherscanLink tx={data.txHash} text={t('View on Etherscan')} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ethUrl}/tx/${data.txHash}`}
|
||||||
|
data-testid="etherscan-link"
|
||||||
|
>
|
||||||
|
{t('View on Etherscan')}
|
||||||
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -92,7 +104,13 @@ export const StatusCell = ({ value, data, complete }: StatusCellProps) => {
|
|||||||
{data.txHash ? (
|
{data.txHash ? (
|
||||||
<>
|
<>
|
||||||
{t('Finalized')}
|
{t('Finalized')}
|
||||||
<EtherscanLink tx={data.txHash} text={t('View on Etherscan')} />
|
<Link
|
||||||
|
title={t('View transaction on Etherscan')}
|
||||||
|
href={`${ethUrl}/tx/${data.txHash}`}
|
||||||
|
data-testid="etherscan-link"
|
||||||
|
>
|
||||||
|
{t('View on Etherscan')}
|
||||||
|
</Link>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@ -109,6 +127,22 @@ export const StatusCell = ({ value, data, complete }: StatusCellProps) => {
|
|||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
const RecipientCell = ({ value, valueFormatted }: ICellRendererParams) => {
|
export interface RecipientCellProps extends ICellRendererParams {
|
||||||
return <EtherscanLink address={value} text={valueFormatted} />;
|
ethUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RecipientCell = ({
|
||||||
|
ethUrl,
|
||||||
|
value,
|
||||||
|
valueFormatted,
|
||||||
|
}: RecipientCellProps) => {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
title={t('View address on Etherscan')}
|
||||||
|
href={`${ethUrl}/address/${value}`}
|
||||||
|
data-testid="etherscan-link"
|
||||||
|
>
|
||||||
|
{valueFormatted}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
"noPropertyAccessFromIndexSignature": false,
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"resolveJsonModule": true,
|
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"skipDefaultLibCheck": true,
|
"skipDefaultLibCheck": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
|
"resolveJsonModule": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@vegaprotocol/accounts": ["libs/accounts/src/index.ts"],
|
"@vegaprotocol/accounts": ["libs/accounts/src/index.ts"],
|
||||||
"@vegaprotocol/candles-chart": ["libs/candles-chart/src/index.ts"],
|
"@vegaprotocol/candles-chart": ["libs/candles-chart/src/index.ts"],
|
||||||
|
Loading…
Reference in New Issue
Block a user