Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88992fa6e6 | ||
|
|
abe650cf95 | ||
|
|
2298c434c8 | ||
|
|
41126111a5 | ||
|
|
f4b11e83df | ||
|
|
0e77062cc6 | ||
|
|
1391db5eed | ||
|
|
717b470a9e | ||
|
|
4df59b9c64 | ||
|
|
23bc8335cc |
@@ -6,7 +6,7 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
|
||||
NX_TENDERMINT_URL=https://tm.sandbox.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.sandbox.vega.xyz/websocket
|
||||
NX_TENDERMINT_URL=https://tm.n01.sandbox.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.sandbox.vega.xyz/websocket
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz
|
||||
|
||||
@@ -66,9 +66,7 @@ export const Search = () => {
|
||||
className="text-white"
|
||||
hasError={Boolean(error?.message)}
|
||||
type="text"
|
||||
placeholder={t(
|
||||
'Enter block number, public key or transaction hash'
|
||||
)}
|
||||
placeholder={t('Enter block number, party id or transaction hash')}
|
||||
/>
|
||||
{error?.message && (
|
||||
<div className="bg-white border border-t-0 border-accent absolute top-[100%] flex-1 w-full pb-2 px-2 rounded-b text-black">
|
||||
|
||||
@@ -20,7 +20,6 @@ import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel';
|
||||
import { TxDetailsDataSubmission } from './tx-data-submission';
|
||||
import { TxProposalVote } from './tx-proposal-vote';
|
||||
import { TxDetailsProtocolUpgrade } from './tx-details-protocol-upgrade';
|
||||
import { TxDetailsIssueSignatures } from './tx-issue-signatures';
|
||||
|
||||
interface TxDetailsWrapperProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -68,8 +67,6 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
|
||||
|
||||
// These come from https://github.com/vegaprotocol/vega/blob/develop/core/txn/command.go#L72-L98
|
||||
switch (txData.type) {
|
||||
case 'Issue Signatures':
|
||||
return TxDetailsIssueSignatures;
|
||||
case 'Submit Order':
|
||||
return TxDetailsOrder;
|
||||
case 'Submit Oracle Data':
|
||||
|
||||
@@ -11,7 +11,8 @@ interface TxDetailsGenericProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* A node is
|
||||
* If there is not yet a custom component for a transaction, just display
|
||||
* the basic details. This allows someone to view the decoded transaction.
|
||||
*/
|
||||
export const TxDetailsGeneric = ({
|
||||
txData,
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableRow, TableCell, TableWithTbody } from '../../table';
|
||||
|
||||
import type { components } from '../../../../types/explorer';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../links/eth-explorer-link/eth-explorer-link';
|
||||
import { NodeLink } from '../../links';
|
||||
|
||||
type Command = components['schemas']['v1IssueSignatures'];
|
||||
|
||||
const kind: Record<components['schemas']['v1NodeSignatureKind'], string> = {
|
||||
NODE_SIGNATURE_KIND_UNSPECIFIED: 'Unspecified',
|
||||
NODE_SIGNATURE_KIND_ASSET_NEW: 'New asset',
|
||||
NODE_SIGNATURE_KIND_ASSET_WITHDRAWAL: 'Asset withdrawal',
|
||||
NODE_SIGNATURE_KIND_ASSET_UPDATE: ' Asset update',
|
||||
NODE_SIGNATURE_KIND_ERC20_MULTISIG_SIGNER_ADDED: 'Multisig signer added',
|
||||
NODE_SIGNATURE_KIND_ERC20_MULTISIG_SIGNER_REMOVED: 'Multisig signer removed',
|
||||
};
|
||||
|
||||
interface TxDetailsGenericProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
pubKey: string | undefined;
|
||||
blockData: TendermintBlocksResponse | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is not yet a custom component for a transaction, just display
|
||||
* the basic details. This allows someone to view the decoded transaction.
|
||||
*/
|
||||
export const TxDetailsIssueSignatures = ({
|
||||
txData,
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxDetailsGenericProps) => {
|
||||
if (!txData) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const cmd: Command = txData.command;
|
||||
const k = cmd.kind ? kind[cmd.kind] : null;
|
||||
|
||||
return (
|
||||
<TableWithTbody className="mb-8">
|
||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||
{k ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Kind')}</TableCell>
|
||||
<TableCell>{k}</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
{cmd.submitter ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('ETH key')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={cmd.submitter}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
{cmd.validatorNodeId ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Validator')}</TableCell>
|
||||
<TableCell>
|
||||
<NodeLink id={cmd.validatorNodeId} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
</TableWithTbody>
|
||||
);
|
||||
};
|
||||
@@ -10,7 +10,7 @@ import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
export const JumpToParty = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
useDocumentTitle(['Public keys']);
|
||||
useDocumentTitle(['Parties']);
|
||||
|
||||
const handleSubmit = (e: React.SyntheticEvent) => {
|
||||
e.preventDefault();
|
||||
@@ -27,8 +27,8 @@ export const JumpToParty = () => {
|
||||
};
|
||||
return (
|
||||
<JumpTo
|
||||
label={t('Go to public key')}
|
||||
placeholder={t('Public key')}
|
||||
label={t('Go to party')}
|
||||
placeholder={t('Party id')}
|
||||
inputId="party-input"
|
||||
inputType="text"
|
||||
inputName="partyId"
|
||||
@@ -40,7 +40,7 @@ export const JumpToParty = () => {
|
||||
const Parties = () => {
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="parties-header">{t('Public keys')}</RouteTitle>
|
||||
<RouteTitle data-testid="parties-header">{t('Parties')}</RouteTitle>
|
||||
<JumpToParty />
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@ type PartyIdErrorProps = {
|
||||
const PartyIdError = ({ id, error }: PartyIdErrorProps) => {
|
||||
const end = isValidPartyId(id)
|
||||
? t('No accounts or transactions found for: ')
|
||||
: 'Invalid public key: ';
|
||||
: 'Invalid party id: ';
|
||||
return (
|
||||
<section>
|
||||
<p>
|
||||
|
||||
@@ -16,7 +16,7 @@ import { PartyAccounts } from './components/party-accounts';
|
||||
const Party = () => {
|
||||
const { party } = useParams<{ party: string }>();
|
||||
|
||||
useDocumentTitle(['Public keys', party || '-']);
|
||||
useDocumentTitle(['Parties', party || '-']);
|
||||
const partyId = toNonHex(party ? party : '');
|
||||
const { isMobile } = useScreenDimensions();
|
||||
const visibleChars = useMemo(() => (isMobile ? 10 : 14), [isMobile]);
|
||||
@@ -44,7 +44,7 @@ const Party = () => {
|
||||
/>
|
||||
) : (
|
||||
<Panel>
|
||||
<p>No data found for public key {party}</p>
|
||||
<p>No party found for key {party}</p>
|
||||
</Panel>
|
||||
);
|
||||
|
||||
@@ -71,7 +71,7 @@ const Party = () => {
|
||||
className="font-alpha uppercase font-xl mb-4 text-zinc-800 dark:text-zinc-200"
|
||||
data-testid="parties-header"
|
||||
>
|
||||
{t('Public key')}
|
||||
{t('Party')}
|
||||
</h1>
|
||||
{partyRes.data ? (
|
||||
<>
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "86666.297",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "71290.812100647638944706",
|
||||
"locked_amount": "71527.9874377224479678513",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "86666.297",
|
||||
@@ -170,7 +170,7 @@
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1555.5670024420025",
|
||||
"locked_amount": "1569.28784467846975",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
@@ -558,7 +558,7 @@
|
||||
"tranche_end": "2023-08-01T00:00:00.000Z",
|
||||
"total_added": "37500",
|
||||
"total_removed": "183.137181525",
|
||||
"locked_amount": "36100.54097605893375",
|
||||
"locked_amount": "36307.49069597912625",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -624,7 +624,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "71225.768204759715901935",
|
||||
"locked_amount": "71462.72714918200044174",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -690,7 +690,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "62600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "35543.98462709284528",
|
||||
"locked_amount": "35715.29892820902776",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10000",
|
||||
@@ -883,7 +883,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "3030.7572298325725",
|
||||
"locked_amount": "3044.440480720446",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -1094,7 +1094,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "97499.58",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "13088.045251352428418448",
|
||||
"locked_amount": "13320.4799021065353983616",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "97499.58",
|
||||
@@ -1127,7 +1127,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "135173.4239508",
|
||||
"total_removed": "98230.390980249184455396",
|
||||
"locked_amount": "17889.0983018495693667123126",
|
||||
"locked_amount": "18206.796341262034809441102696",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "135173.4239508",
|
||||
@@ -1173,7 +1173,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "32499.86",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "5505.914618791834455152",
|
||||
"locked_amount": "5603.6958624323669808404",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "32499.86",
|
||||
@@ -1206,7 +1206,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "10833.29",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1792.1217802859475346957",
|
||||
"locked_amount": "1823.94862624421256173",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@@ -1239,7 +1239,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "22749.93",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "6699.35147787958153563",
|
||||
"locked_amount": "6818.3273364692396522472",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "6500",
|
||||
@@ -1378,7 +1378,7 @@
|
||||
"tranche_end": "2023-05-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "3995.28612255",
|
||||
"locked_amount": "10223.86049723756925",
|
||||
"locked_amount": "10348.030329189685875",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -1576,7 +1576,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "928642.9598472029154",
|
||||
"locked_amount": "607199.059293409416755688",
|
||||
"locked_amount": "612507.96463901900484135",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -2876,7 +2876,7 @@
|
||||
"tranche_start": "2021-09-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-30T00:00:00.000Z",
|
||||
"total_added": "60916.66666633337",
|
||||
"total_removed": "39088.634764730198755268",
|
||||
"total_removed": "34173.43587066019652061",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -2976,16 +2976,6 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "3395.631843574",
|
||||
"user": "0xa0fF757077B5D796259582b2b9Db99c906277007",
|
||||
"tx": "0x335be76fc5ff37d4272a624f47822e6163d395e0d8a3a9cfcbcc5f7207239361"
|
||||
},
|
||||
{
|
||||
"amount": "1519.567050496002234658",
|
||||
"user": "0x6E14D4e15E245d6ECfe3181B08c2FF30d2c1Da19",
|
||||
"tx": "0x3d0b5ec97be95410571cbc03dd4edd1406243cafbafc40d7c4740f88287efcd3"
|
||||
},
|
||||
{
|
||||
"amount": "1366.363766241335342692",
|
||||
"user": "0xef633C319801eB899354030DFF2BBD0024C0b39c",
|
||||
@@ -3616,12 +3606,6 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1519.567050496002234658",
|
||||
"user": "0x6E14D4e15E245d6ECfe3181B08c2FF30d2c1Da19",
|
||||
"tranche_id": 13,
|
||||
"tx": "0x3d0b5ec97be95410571cbc03dd4edd1406243cafbafc40d7c4740f88287efcd3"
|
||||
},
|
||||
{
|
||||
"amount": "747.099616170667765342",
|
||||
"user": "0x6E14D4e15E245d6ECfe3181B08c2FF30d2c1Da19",
|
||||
@@ -3630,8 +3614,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "2266.66666666667",
|
||||
"withdrawn_tokens": "2266.66666666667",
|
||||
"remaining_tokens": "0"
|
||||
"withdrawn_tokens": "747.099616170667765342",
|
||||
"remaining_tokens": "1519.567050496002234658"
|
||||
},
|
||||
{
|
||||
"address": "0xb14025f7eB7717cFF43e7a33b66d86eaBd6bC7d7",
|
||||
@@ -3674,12 +3658,6 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "3395.631843574",
|
||||
"user": "0xa0fF757077B5D796259582b2b9Db99c906277007",
|
||||
"tranche_id": 13,
|
||||
"tx": "0x335be76fc5ff37d4272a624f47822e6163d395e0d8a3a9cfcbcc5f7207239361"
|
||||
},
|
||||
{
|
||||
"amount": "4.368156426",
|
||||
"user": "0xa0fF757077B5D796259582b2b9Db99c906277007",
|
||||
@@ -3688,8 +3666,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "3400",
|
||||
"withdrawn_tokens": "3400",
|
||||
"remaining_tokens": "0"
|
||||
"withdrawn_tokens": "4.368156426",
|
||||
"remaining_tokens": "3395.631843574"
|
||||
},
|
||||
{
|
||||
"address": "0x2D69BAB9738b05048be16DE3E5E0A945b8EeEf3a",
|
||||
@@ -33559,7 +33537,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "589730.8667090699299",
|
||||
"locked_amount": "957554.874604284746674723657",
|
||||
"locked_amount": "965712.81375596155222172624",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -34873,8 +34851,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "560317.67585805941693952",
|
||||
"locked_amount": "8695115.6900884208257391762291393526601783",
|
||||
"total_removed": "557133.30560592463281452",
|
||||
"locked_amount": "8724043.2185305122313058695420656514828332",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -35438,16 +35416,6 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xa344428c2b1bf9b4685959441983da46bcd434ac0ee5ada325876c8733eba603"
|
||||
},
|
||||
{
|
||||
"amount": "2667.021494",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tx": "0x94fe358ee7c973dd1d28ca4c56250dfaccbcb718673872c8e9cf8651a22a1108"
|
||||
},
|
||||
{
|
||||
"amount": "517.348758134784125",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xb6a33b8b8855789fbc2d0f9545ba5c2258e52f143d90bc75bbe2411bd2f9b4a5"
|
||||
},
|
||||
{
|
||||
"amount": "858.360074993579125",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -37067,12 +37035,6 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0xa344428c2b1bf9b4685959441983da46bcd434ac0ee5ada325876c8733eba603"
|
||||
},
|
||||
{
|
||||
"amount": "517.348758134784125",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xb6a33b8b8855789fbc2d0f9545ba5c2258e52f143d90bc75bbe2411bd2f9b4a5"
|
||||
},
|
||||
{
|
||||
"amount": "858.360074993579125",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -38161,8 +38123,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "259998.8875",
|
||||
"withdrawn_tokens": "117484.092376092228875",
|
||||
"remaining_tokens": "142514.795123907771125"
|
||||
"withdrawn_tokens": "116966.74361795744475",
|
||||
"remaining_tokens": "143032.14388204255525"
|
||||
},
|
||||
{
|
||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||
@@ -38816,12 +38778,6 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0x606ddaa3882cccb0062bc2827cfcfceb64cef8a6c4df41d06747ae651e5dd52e"
|
||||
},
|
||||
{
|
||||
"amount": "2667.021494",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x94fe358ee7c973dd1d28ca4c56250dfaccbcb718673872c8e9cf8651a22a1108"
|
||||
},
|
||||
{
|
||||
"amount": "1099.300488",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -39004,8 +38960,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200000",
|
||||
"withdrawn_tokens": "90095.748006",
|
||||
"remaining_tokens": "109904.251994"
|
||||
"withdrawn_tokens": "87428.726512",
|
||||
"remaining_tokens": "112571.273488"
|
||||
},
|
||||
{
|
||||
"address": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
|
||||
@@ -40351,8 +40307,8 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "3921707.576409189114087282",
|
||||
"locked_amount": "2305830.059961451513978716150659574",
|
||||
"total_removed": "3920990.096830703963164282",
|
||||
"locked_amount": "2332535.769515174096512550505057687",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@@ -40611,11 +40567,6 @@
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0xc73c47dcfac4093bb6325fe92986dd010d5a773af4bb97e188ad57359a309a52"
|
||||
},
|
||||
{
|
||||
"amount": "717.479578485150923",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x0c292f2355b5cdc3b389ed35e6e138e593b1db9d91fcd58f132835343724bf90"
|
||||
},
|
||||
{
|
||||
"amount": "8950.14985089483210984",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
@@ -43453,12 +43404,6 @@
|
||||
"tranche_id": 3,
|
||||
"tx": "0xc73c47dcfac4093bb6325fe92986dd010d5a773af4bb97e188ad57359a309a52"
|
||||
},
|
||||
{
|
||||
"amount": "717.479578485150923",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x0c292f2355b5cdc3b389ed35e6e138e593b1db9d91fcd58f132835343724bf90"
|
||||
},
|
||||
{
|
||||
"amount": "1192.05386354121365675",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -45849,8 +45794,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "359123.469575",
|
||||
"withdrawn_tokens": "302309.38363864041348675",
|
||||
"remaining_tokens": "56814.08593635958651325"
|
||||
"withdrawn_tokens": "301591.90406015526256375",
|
||||
"remaining_tokens": "57531.56551484473743625"
|
||||
},
|
||||
{
|
||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||
@@ -47188,7 +47133,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "2730068.739915456784546642",
|
||||
"locked_amount": "594143.998694685843745742950916108",
|
||||
"locked_amount": "604695.586054148570133080743399363",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@@ -49170,8 +49115,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "32476.7515062512685",
|
||||
"locked_amount": "151730.043498066832591983753120252",
|
||||
"total_removed": "32361.4666889012685",
|
||||
"locked_amount": "153022.71558941830041836828209032",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -55830,16 +55775,6 @@
|
||||
"user": "0x0e199b123f71f964d6567869B6B849C1f255A855",
|
||||
"tx": "0x6df8666e49f7d491c740d6a36df031aac232a6cf37fa197aa1f6b2bb481be99c"
|
||||
},
|
||||
{
|
||||
"amount": "99.47735921",
|
||||
"user": "0x2E32F49389CF3039ab6365ca59329002922Cc01D",
|
||||
"tx": "0x7de3c1703d23970f04ce1bebe2cece8a2fe3fbe6b876502da1812c312151b954"
|
||||
},
|
||||
{
|
||||
"amount": "15.80745814",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
"tx": "0xc0f953d7ecc45bfc1d7b69ecd491a63e8b00b0d732ff006bee008e917a04179f"
|
||||
},
|
||||
{
|
||||
"amount": "78.261187214",
|
||||
"user": "0x479F059c46c6873C6B970A92911084b3eA036d56",
|
||||
@@ -68095,12 +68030,6 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "99.47735921",
|
||||
"user": "0x2E32F49389CF3039ab6365ca59329002922Cc01D",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x7de3c1703d23970f04ce1bebe2cece8a2fe3fbe6b876502da1812c312151b954"
|
||||
},
|
||||
{
|
||||
"amount": "35.842421358",
|
||||
"user": "0x2E32F49389CF3039ab6365ca59329002922Cc01D",
|
||||
@@ -68109,8 +68038,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200",
|
||||
"withdrawn_tokens": "135.319780568",
|
||||
"remaining_tokens": "64.680219432"
|
||||
"withdrawn_tokens": "35.842421358",
|
||||
"remaining_tokens": "164.157578642"
|
||||
},
|
||||
{
|
||||
"address": "0x2F2588aCd44253312b4A94bF6753bE67514A5Cc6",
|
||||
@@ -69185,12 +69114,6 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "15.80745814",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xc0f953d7ecc45bfc1d7b69ecd491a63e8b00b0d732ff006bee008e917a04179f"
|
||||
},
|
||||
{
|
||||
"amount": "32.761796044",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
@@ -69265,8 +69188,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "270.64275748",
|
||||
"remaining_tokens": "129.35724252"
|
||||
"withdrawn_tokens": "254.83529934",
|
||||
"remaining_tokens": "145.16470066"
|
||||
},
|
||||
{
|
||||
"address": "0x5c90765F50629570738fEe7b7FA82ae118f81Ed1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
addDecimal,
|
||||
fromISONano,
|
||||
fromNanoSeconds,
|
||||
t,
|
||||
useThemeSwitcher,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
@@ -228,7 +228,7 @@ export const AccountHistoryChart = ({
|
||||
.reduce((acc, edge) => {
|
||||
if (edge.node.accountType === accountType) {
|
||||
acc?.push({
|
||||
datetime: fromISONano(edge.node.timestamp),
|
||||
datetime: fromNanoSeconds(edge.node.timestamp),
|
||||
balance: Number(addDecimal(edge.node.balance, asset.decimals)),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { Footer, NodeHealth } from './footer';
|
||||
import { useEnvironment, useNodeHealth } from '@vegaprotocol/environment';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
jest.mock('@vegaprotocol/environment');
|
||||
|
||||
@@ -12,14 +12,10 @@ describe('Footer', () => {
|
||||
// @ts-ignore mock env hook
|
||||
useEnvironment.mockImplementation(() => ({
|
||||
VEGA_URL: `https://api.${node}/graphql`,
|
||||
blockDifference: 0,
|
||||
setNodeSwitcherOpen: mockOpenNodeSwitcher,
|
||||
}));
|
||||
|
||||
// @ts-ignore mock env hook
|
||||
useNodeHealth.mockImplementation(() => ({
|
||||
blockDiff: 0,
|
||||
}));
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
fireEvent.click(screen.getByText(node));
|
||||
@@ -33,14 +29,10 @@ describe('Footer', () => {
|
||||
// @ts-ignore mock env hook
|
||||
useEnvironment.mockImplementation(() => ({
|
||||
VEGA_URL: `https://api.${node}/graphql`,
|
||||
blockDifference: 0,
|
||||
setNodeSwitcherOpen: mockOpenNodeSwitcher,
|
||||
}));
|
||||
|
||||
// @ts-ignore mock env hook
|
||||
useNodeHealth.mockImplementation(() => ({
|
||||
blockDiff: 0,
|
||||
}));
|
||||
|
||||
render(<Footer />);
|
||||
|
||||
fireEvent.click(screen.getByText('Operational'));
|
||||
@@ -51,9 +43,8 @@ describe('Footer', () => {
|
||||
describe('NodeHealth', () => {
|
||||
const cases = [
|
||||
{ diff: 0, classname: 'bg-success', text: 'Operational' },
|
||||
{ diff: -1, classname: 'bg-success', text: 'Operational' },
|
||||
{ diff: 5, classname: 'bg-warning', text: '5 Blocks behind' },
|
||||
{ diff: null, classname: 'bg-danger', text: 'Non operational' },
|
||||
{ diff: -1, classname: 'bg-danger', text: 'Non operational' },
|
||||
];
|
||||
it.each(cases)(
|
||||
'renders correct text and indicator color for $diff block difference',
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { useEnvironment, useNodeHealth } from '@vegaprotocol/environment';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { t, useNavigatorOnline } from '@vegaprotocol/react-helpers';
|
||||
import { ButtonLink, Indicator, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
export const Footer = () => {
|
||||
const { VEGA_URL, setNodeSwitcherOpen } = useEnvironment();
|
||||
const { blockDiff } = useNodeHealth();
|
||||
const { VEGA_URL, blockDifference, setNodeSwitcherOpen } = useEnvironment();
|
||||
return (
|
||||
<footer className="px-4 py-1 text-xs border-t border-default">
|
||||
<div className="flex justify-between">
|
||||
@@ -12,9 +11,10 @@ export const Footer = () => {
|
||||
{VEGA_URL && (
|
||||
<>
|
||||
<NodeHealth
|
||||
blockDiff={blockDiff}
|
||||
blockDiff={blockDifference}
|
||||
openNodeSwitcher={setNodeSwitcherOpen}
|
||||
/>
|
||||
{' | '}
|
||||
<NodeUrl url={VEGA_URL} openNodeSwitcher={setNodeSwitcherOpen} />
|
||||
</>
|
||||
)}
|
||||
@@ -37,8 +37,8 @@ const NodeUrl = ({ url, openNodeSwitcher }: NodeUrlProps) => {
|
||||
};
|
||||
|
||||
interface NodeHealthProps {
|
||||
blockDiff: number | null;
|
||||
openNodeSwitcher: () => void;
|
||||
blockDiff: number;
|
||||
}
|
||||
|
||||
// How many blocks behind the most advanced block that is
|
||||
@@ -57,7 +57,7 @@ export const NodeHealth = ({
|
||||
if (!online) {
|
||||
text = t('Offline');
|
||||
intent = Intent.Danger;
|
||||
} else if (blockDiff === null) {
|
||||
} else if (blockDiff < 0) {
|
||||
// Block height query failed and null was returned
|
||||
text = t('Non operational');
|
||||
intent = Intent.Danger;
|
||||
@@ -67,9 +67,9 @@ export const NodeHealth = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>
|
||||
<Indicator variant={intent} />
|
||||
<ButtonLink onClick={openNodeSwitcher}>{text}</ButtonLink>
|
||||
</>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from './lib/apollo-client';
|
||||
export * from './lib/header-store';
|
||||
|
||||
@@ -13,11 +13,7 @@ import { createClient as createWSClient } from 'graphql-ws';
|
||||
import { onError } from '@apollo/client/link/error';
|
||||
import { RetryLink } from '@apollo/client/link/retry';
|
||||
import ApolloLinkTimeout from 'apollo-link-timeout';
|
||||
import {
|
||||
fromNanoSeconds,
|
||||
localLoggerFactory,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { useHeaderStore } from './header-store';
|
||||
import { localLoggerFactory } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const isBrowser = typeof window !== 'undefined';
|
||||
|
||||
@@ -28,7 +24,6 @@ export type ClientOptions = {
|
||||
cacheConfig?: InMemoryCacheConfig;
|
||||
retry?: boolean;
|
||||
connectToDevTools?: boolean;
|
||||
connectToHeaderStore?: boolean;
|
||||
};
|
||||
|
||||
export function createClient({
|
||||
@@ -36,7 +31,6 @@ export function createClient({
|
||||
cacheConfig,
|
||||
retry = true,
|
||||
connectToDevTools = true,
|
||||
connectToHeaderStore = true,
|
||||
}: ClientOptions) {
|
||||
if (!url) {
|
||||
throw new Error('url must be passed into createClient!');
|
||||
@@ -50,28 +44,6 @@ export function createClient({
|
||||
return forward(operation);
|
||||
});
|
||||
|
||||
const headerLink = connectToHeaderStore
|
||||
? new ApolloLink((operation, forward) => {
|
||||
return forward(operation).map((response) => {
|
||||
const context = operation.getContext();
|
||||
const headers = context['response'].headers;
|
||||
const blockHeight = headers.get('x-block-height');
|
||||
const timestamp = headers.get('x-block-timestamp');
|
||||
if (blockHeight && timestamp) {
|
||||
const state = useHeaderStore.getState();
|
||||
useHeaderStore.setState({
|
||||
...state,
|
||||
[context['response'].url]: {
|
||||
blockHeight: Number(blockHeight),
|
||||
timestamp: fromNanoSeconds(timestamp),
|
||||
},
|
||||
});
|
||||
}
|
||||
return response;
|
||||
});
|
||||
})
|
||||
: noOpLink;
|
||||
|
||||
const timeoutLink = new ApolloLinkTimeout(10000);
|
||||
const enlargedTimeoutLink = new ApolloLinkTimeout(100000);
|
||||
|
||||
@@ -132,13 +104,7 @@ export function createClient({
|
||||
);
|
||||
|
||||
return new ApolloClient({
|
||||
link: from([
|
||||
errorLink,
|
||||
composedTimeoutLink,
|
||||
headerLink,
|
||||
retryLink,
|
||||
splitLink,
|
||||
]),
|
||||
link: from([errorLink, composedTimeoutLink, retryLink, splitLink]),
|
||||
cache: new InMemoryCache(cacheConfig),
|
||||
connectToDevTools,
|
||||
});
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
type HeaderStore = {
|
||||
[url: string]: {
|
||||
blockHeight: number;
|
||||
timestamp: Date;
|
||||
};
|
||||
};
|
||||
|
||||
export const useHeaderStore = create<HeaderStore>(() => ({}));
|
||||
@@ -10,9 +10,9 @@ interface Props {
|
||||
|
||||
export const DealTicketButton = ({ disabled, variant }: Props) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const openVegaWalletDialog = useVegaWalletDialogStore(
|
||||
(store) => store.openVegaWalletDialog
|
||||
);
|
||||
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
|
||||
openVegaWalletDialog: store.openVegaWalletDialog,
|
||||
}));
|
||||
return pubKey ? (
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
|
||||
@@ -31,6 +31,8 @@ import {
|
||||
usePersistedOrderStoreSubscription,
|
||||
} from '@vegaprotocol/orders';
|
||||
|
||||
export type TransactionStatus = 'default' | 'pending';
|
||||
|
||||
export interface DealTicketProps {
|
||||
market: MarketDealTicket;
|
||||
submit: (order: OrderSubmissionBody['orderSubmission']) => void;
|
||||
|
||||
@@ -13,10 +13,6 @@ type NodeStatsContentProps = {
|
||||
setBlock: (value: number) => void;
|
||||
children?: ReactNode;
|
||||
dataTestId?: string;
|
||||
headers?: {
|
||||
blockHeight: number;
|
||||
timestamp: Date;
|
||||
};
|
||||
};
|
||||
|
||||
const getResponseTimeDisplayValue = (
|
||||
@@ -32,13 +28,13 @@ const getResponseTimeDisplayValue = (
|
||||
};
|
||||
|
||||
const getBlockDisplayValue = (
|
||||
block: number | undefined,
|
||||
block: NodeData['block'] | undefined,
|
||||
setBlock: (block: number) => void
|
||||
) => {
|
||||
if (block) {
|
||||
return <NodeBlockHeight value={block} setValue={setBlock} />;
|
||||
if (block?.value) {
|
||||
return <NodeBlockHeight value={block?.value} setValue={setBlock} />;
|
||||
}
|
||||
if (!block) {
|
||||
if (block?.hasError) {
|
||||
return t('n/a');
|
||||
}
|
||||
return '-';
|
||||
@@ -63,7 +59,6 @@ const NodeStatsContent = ({
|
||||
setBlock,
|
||||
children,
|
||||
dataTestId,
|
||||
headers,
|
||||
}: NodeStatsContentProps) => {
|
||||
return (
|
||||
<LayoutRow dataTestId={dataTestId}>
|
||||
@@ -77,12 +72,15 @@ const NodeStatsContent = ({
|
||||
{getResponseTimeDisplayValue(data.responseTime)}
|
||||
</LayoutCell>
|
||||
<LayoutCell
|
||||
label={t('Header block')}
|
||||
isLoading={false}
|
||||
hasError={headers ? highestBlock - 3 > headers.blockHeight : false}
|
||||
dataTestId="header-block-cell"
|
||||
label={t('Block')}
|
||||
isLoading={data.block?.isLoading}
|
||||
hasError={
|
||||
data.block?.hasError ||
|
||||
(!!data.block?.value && highestBlock > data.block.value)
|
||||
}
|
||||
dataTestId="block-cell"
|
||||
>
|
||||
{getBlockDisplayValue(headers?.blockHeight, setBlock)}
|
||||
{getBlockDisplayValue(data.block, setBlock)}
|
||||
</LayoutCell>
|
||||
<LayoutCell
|
||||
label={t('Subscription')}
|
||||
@@ -115,10 +113,6 @@ export type NodeStatsProps = {
|
||||
highestBlock: number;
|
||||
setBlock: (value: number) => void;
|
||||
children?: ReactNode;
|
||||
headers: {
|
||||
blockHeight: number;
|
||||
timestamp: Date;
|
||||
};
|
||||
};
|
||||
|
||||
export const NodeStats = ({
|
||||
@@ -127,7 +121,6 @@ export const NodeStats = ({
|
||||
highestBlock,
|
||||
children,
|
||||
setBlock,
|
||||
headers,
|
||||
}: NodeStatsProps) => {
|
||||
return (
|
||||
<Wrapper client={client}>
|
||||
@@ -136,7 +129,6 @@ export const NodeStats = ({
|
||||
highestBlock={highestBlock}
|
||||
setBlock={setBlock}
|
||||
dataTestId="node-row"
|
||||
headers={headers}
|
||||
>
|
||||
{children}
|
||||
</NodeStatsContent>
|
||||
|
||||
@@ -21,7 +21,6 @@ import type { Configuration, NodeData, ErrorType } from '../../types';
|
||||
import { LayoutRow } from './layout-row';
|
||||
import { NodeError } from './node-error';
|
||||
import { NodeStats } from './node-stats';
|
||||
import { useHeaderStore } from '@vegaprotocol/apollo-client';
|
||||
|
||||
type NodeSwitcherProps = {
|
||||
error?: string;
|
||||
@@ -47,7 +46,6 @@ export const NodeSwitcher = ({
|
||||
onConnect,
|
||||
}: NodeSwitcherProps) => {
|
||||
const { VEGA_ENV, VEGA_URL } = useEnvironment();
|
||||
const headerStore = useHeaderStore();
|
||||
const [networkError, setNetworkError] = useState(
|
||||
getErrorByType(initialErrorType, VEGA_ENV, VEGA_URL)
|
||||
);
|
||||
@@ -98,7 +96,7 @@ export const NodeSwitcher = ({
|
||||
<LayoutRow>
|
||||
<div />
|
||||
<span className="text-right">{t('Response time')}</span>
|
||||
<span className="text-right">{t('Block height')}</span>
|
||||
<span className="text-right">{t('Block')}</span>
|
||||
<span className="text-right">{t('Subscription')}</span>
|
||||
</LayoutRow>
|
||||
</div>
|
||||
@@ -117,7 +115,6 @@ export const NodeSwitcher = ({
|
||||
client={clients[node]}
|
||||
highestBlock={highestBlock}
|
||||
setBlock={(block) => updateNodeBlock(node, block)}
|
||||
headers={headerStore[node]}
|
||||
>
|
||||
<div className="break-all" data-testid="node">
|
||||
<Radio
|
||||
@@ -134,7 +131,6 @@ export const NodeSwitcher = ({
|
||||
client={customUrl ? clients[customUrl] : undefined}
|
||||
highestBlock={highestBlock}
|
||||
setBlock={(block) => updateNodeBlock(CUSTOM_NODE_KEY, block)}
|
||||
headers={headerStore[CUSTOM_NODE_KEY]}
|
||||
>
|
||||
<div className="flex w-full mb-2">
|
||||
<Radio
|
||||
|
||||
@@ -37,7 +37,6 @@ export const getMockStatisticsResult = (
|
||||
__typename: 'Statistics',
|
||||
chainId: `${env.toLowerCase()}-0123`,
|
||||
blockHeight: '11',
|
||||
vegaTime: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -46,7 +45,6 @@ export const getMockQueryResult = (env: Networks): StatisticsQuery => ({
|
||||
__typename: 'Statistics',
|
||||
chainId: `${env.toLowerCase()}-0123`,
|
||||
blockHeight: '11',
|
||||
vegaTime: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -17,10 +17,6 @@ jest.mock('react-dom', () => ({
|
||||
createPortal: (node: ReactNode) => node,
|
||||
}));
|
||||
|
||||
jest.mock('../components/node-switcher', () => ({
|
||||
NodeSwitcher: () => <div />,
|
||||
}));
|
||||
|
||||
global.fetch = jest.fn();
|
||||
|
||||
const MockWrapper = (props: ComponentProps<typeof EnvironmentProvider>) => {
|
||||
@@ -50,6 +46,7 @@ const mockEnvironmentState = {
|
||||
GITHUB_FEEDBACK_URL: 'https://github.com/test/feedback',
|
||||
MAINTENANCE_PAGE: false,
|
||||
configLoading: false,
|
||||
blockDifference: 0,
|
||||
nodeSwitcherOpen: false,
|
||||
setNodeSwitcherOpen: noop,
|
||||
networkError: undefined,
|
||||
|
||||
@@ -25,6 +25,7 @@ import type {
|
||||
NodeData,
|
||||
Configuration,
|
||||
} from '../types';
|
||||
import { useNodeHealth } from './use-node-health';
|
||||
|
||||
type EnvironmentProviderProps = {
|
||||
config?: Configuration;
|
||||
@@ -35,6 +36,7 @@ type EnvironmentProviderProps = {
|
||||
export type EnvironmentState = Environment & {
|
||||
configLoading: boolean;
|
||||
networkError?: ErrorType;
|
||||
blockDifference: number;
|
||||
nodeSwitcherOpen: boolean;
|
||||
setNodeSwitcherOpen: () => void;
|
||||
};
|
||||
@@ -84,6 +86,8 @@ export const EnvironmentProvider = ({
|
||||
environment.MAINTENANCE_PAGE
|
||||
);
|
||||
|
||||
const blockDifference = useNodeHealth(clients, environment.VEGA_URL);
|
||||
|
||||
const nodeKeys = Object.keys(nodes);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -146,6 +150,7 @@ export const EnvironmentProvider = ({
|
||||
...environment,
|
||||
configLoading: loading,
|
||||
networkError,
|
||||
blockDifference,
|
||||
nodeSwitcherOpen: isNodeSwitcherOpen,
|
||||
setNodeSwitcherOpen: () => setNodeSwitcherOpen(true),
|
||||
}}
|
||||
|
||||
@@ -1,118 +1,117 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { useNodeHealth } from './use-node-health';
|
||||
import type { MockedResponse } from '@apollo/react-testing';
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import type { StatisticsQuery } from '../utils/__generated__/Node';
|
||||
import { StatisticsDocument } from '../utils/__generated__/Node';
|
||||
import { useEnvironment } from './use-environment';
|
||||
import { useHeaderStore } from '@vegaprotocol/apollo-client';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import {
|
||||
useNodeHealth,
|
||||
NODE_SUBSET_COUNT,
|
||||
INTERVAL_TIME,
|
||||
} from './use-node-health';
|
||||
import type { createClient } from '@vegaprotocol/apollo-client';
|
||||
import type { ClientCollection } from './use-nodes';
|
||||
|
||||
const vegaUrl = 'https://foo.bar.com';
|
||||
function setup(...args: Parameters<typeof useNodeHealth>) {
|
||||
return renderHook(() => useNodeHealth(...args));
|
||||
}
|
||||
|
||||
jest.mock('./use-environment');
|
||||
jest.mock('@vegaprotocol/apollo-client');
|
||||
|
||||
// @ts-ignore ignore mock implementation
|
||||
useEnvironment.mockImplementation(() => ({
|
||||
VEGA_URL: vegaUrl,
|
||||
}));
|
||||
|
||||
const createStatsMock = (
|
||||
blockHeight: number
|
||||
): MockedResponse<StatisticsQuery> => {
|
||||
function createMockClient(blockHeight: number) {
|
||||
return {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
},
|
||||
result: {
|
||||
query: jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
statistics: {
|
||||
chainId: 'chain-id',
|
||||
blockHeight: blockHeight.toString(),
|
||||
vegaTime: '12345',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
function setup(
|
||||
mock: MockedResponse<StatisticsQuery>,
|
||||
headers:
|
||||
| {
|
||||
blockHeight: number;
|
||||
timestamp: Date;
|
||||
}
|
||||
| undefined
|
||||
) {
|
||||
// @ts-ignore ignore mock implementation
|
||||
useHeaderStore.mockImplementation(() => ({
|
||||
[vegaUrl]: headers,
|
||||
}));
|
||||
|
||||
return renderHook(() => useNodeHealth(), {
|
||||
wrapper: ({ children }) => (
|
||||
<MockedProvider mocks={[mock]}>{children}</MockedProvider>
|
||||
),
|
||||
});
|
||||
}),
|
||||
} as unknown as ReturnType<typeof createClient>;
|
||||
}
|
||||
|
||||
describe('useNodeHealth', () => {
|
||||
it.each([
|
||||
{ core: 1, node: 1, expected: 0 },
|
||||
{ core: 1, node: 5, expected: -4 },
|
||||
{ core: 10, node: 5, expected: 5 },
|
||||
])(
|
||||
'provides difference core block $core and node block $node',
|
||||
async (cases) => {
|
||||
const { result } = setup(createStatsMock(cases.core), {
|
||||
blockHeight: cases.node,
|
||||
timestamp: new Date(),
|
||||
});
|
||||
expect(result.current.blockDiff).toEqual(null);
|
||||
expect(result.current.coreBlockHeight).toEqual(undefined);
|
||||
expect(result.current.datanodeBlockHeight).toEqual(cases.node);
|
||||
await waitFor(() => {
|
||||
expect(result.current.blockDiff).toEqual(cases.expected);
|
||||
expect(result.current.coreBlockHeight).toEqual(cases.core);
|
||||
expect(result.current.datanodeBlockHeight).toEqual(cases.node);
|
||||
});
|
||||
}
|
||||
);
|
||||
function createRejectingClient() {
|
||||
return {
|
||||
query: () => Promise.reject(new Error('request failed')),
|
||||
} as unknown as ReturnType<typeof createClient>;
|
||||
}
|
||||
|
||||
it('block diff is null if query fails indicating non operational', async () => {
|
||||
const failedQuery: MockedResponse<StatisticsQuery> = {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
},
|
||||
result: {
|
||||
// @ts-ignore failed query with no result
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
const { result } = setup(failedQuery, {
|
||||
blockHeight: 1,
|
||||
timestamp: new Date(),
|
||||
});
|
||||
expect(result.current.blockDiff).toEqual(null);
|
||||
expect(result.current.coreBlockHeight).toEqual(undefined);
|
||||
expect(result.current.datanodeBlockHeight).toEqual(1);
|
||||
await waitFor(() => {
|
||||
expect(result.current.blockDiff).toEqual(null);
|
||||
expect(result.current.coreBlockHeight).toEqual(undefined);
|
||||
expect(result.current.datanodeBlockHeight).toEqual(1);
|
||||
});
|
||||
function createErroringClient() {
|
||||
return {
|
||||
query: () =>
|
||||
Promise.resolve({
|
||||
error: new Error('failed'),
|
||||
}),
|
||||
} as unknown as ReturnType<typeof createClient>;
|
||||
}
|
||||
|
||||
const CURRENT_URL = 'https://current.test.com';
|
||||
|
||||
describe('useNodeHealth', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
it('returns 0 if no headers are found (wait until stats query resolves)', async () => {
|
||||
const { result } = setup(createStatsMock(1), undefined);
|
||||
expect(result.current.blockDiff).toEqual(null);
|
||||
expect(result.current.coreBlockHeight).toEqual(undefined);
|
||||
expect(result.current.datanodeBlockHeight).toEqual(undefined);
|
||||
await waitFor(() => {
|
||||
expect(result.current.blockDiff).toEqual(0);
|
||||
expect(result.current.coreBlockHeight).toEqual(1);
|
||||
expect(result.current.datanodeBlockHeight).toEqual(undefined);
|
||||
it('provides difference between the highest block and the current block', async () => {
|
||||
const highest = 100;
|
||||
const curr = 97;
|
||||
const clientCollection: ClientCollection = {
|
||||
[CURRENT_URL]: createMockClient(curr),
|
||||
'https://n02.test.com': createMockClient(98),
|
||||
'https://n03.test.com': createMockClient(highest),
|
||||
};
|
||||
const { result } = setup(clientCollection, CURRENT_URL);
|
||||
await act(async () => {
|
||||
jest.advanceTimersByTime(INTERVAL_TIME);
|
||||
});
|
||||
expect(result.current).toBe(highest - curr);
|
||||
});
|
||||
|
||||
it('returns -1 if the current node query fails', async () => {
|
||||
const clientCollection: ClientCollection = {
|
||||
[CURRENT_URL]: createRejectingClient(),
|
||||
'https://n02.test.com': createMockClient(200),
|
||||
'https://n03.test.com': createMockClient(102),
|
||||
};
|
||||
const { result } = setup(clientCollection, CURRENT_URL);
|
||||
await act(async () => {
|
||||
jest.advanceTimersByTime(INTERVAL_TIME);
|
||||
});
|
||||
expect(result.current).toBe(-1);
|
||||
});
|
||||
|
||||
it('returns -1 if the current node query returns an error', async () => {
|
||||
const clientCollection: ClientCollection = {
|
||||
[CURRENT_URL]: createErroringClient(),
|
||||
'https://n02.test.com': createMockClient(200),
|
||||
'https://n03.test.com': createMockClient(102),
|
||||
};
|
||||
const { result } = setup(clientCollection, CURRENT_URL);
|
||||
await act(async () => {
|
||||
jest.advanceTimersByTime(INTERVAL_TIME);
|
||||
});
|
||||
expect(result.current).toBe(-1);
|
||||
});
|
||||
|
||||
it('queries against 5 random nodes along with the current url', async () => {
|
||||
const clientCollection: ClientCollection = new Array(20)
|
||||
.fill(null)
|
||||
.reduce((obj, x, i) => {
|
||||
obj[`https://n${i}.test.com`] = createMockClient(100);
|
||||
return obj;
|
||||
}, {} as ClientCollection);
|
||||
clientCollection[CURRENT_URL] = createMockClient(100);
|
||||
const spyOnCurrent = jest.spyOn(clientCollection[CURRENT_URL], 'query');
|
||||
|
||||
const { result } = setup(clientCollection, CURRENT_URL);
|
||||
await act(async () => {
|
||||
jest.advanceTimersByTime(INTERVAL_TIME);
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
Object.values(clientCollection).forEach((client) => {
|
||||
// @ts-ignore jest.fn() in client setup means mock will be present
|
||||
if (client?.query.mock.calls.length) {
|
||||
count++;
|
||||
}
|
||||
});
|
||||
|
||||
expect(count).toBe(NODE_SUBSET_COUNT + 1);
|
||||
expect(spyOnCurrent).toHaveBeenCalledTimes(1);
|
||||
expect(result.current).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,37 +1,88 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useStatisticsQuery } from '../utils/__generated__/Node';
|
||||
import { useHeaderStore } from '@vegaprotocol/apollo-client';
|
||||
import { fromISONano } from '@vegaprotocol/react-helpers';
|
||||
import { useEnvironment } from './use-environment';
|
||||
import compact from 'lodash/compact';
|
||||
import shuffle from 'lodash/shuffle';
|
||||
import type { createClient } from '@vegaprotocol/apollo-client';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { StatisticsQuery } from '../utils/__generated__/Node';
|
||||
import { StatisticsDocument } from '../utils/__generated__/Node';
|
||||
import type { ClientCollection } from './use-nodes';
|
||||
|
||||
export const useNodeHealth = () => {
|
||||
const { VEGA_URL } = useEnvironment();
|
||||
const headerStore = useHeaderStore();
|
||||
const headers = VEGA_URL ? headerStore[VEGA_URL] : undefined;
|
||||
const { data } = useStatisticsQuery({
|
||||
pollInterval: 1000,
|
||||
fetchPolicy: 'no-cache',
|
||||
});
|
||||
// How often to query other nodes
|
||||
export const INTERVAL_TIME = 30 * 1000;
|
||||
// Number of nodes to query against
|
||||
export const NODE_SUBSET_COUNT = 5;
|
||||
|
||||
const blockDiff = useMemo(() => {
|
||||
if (!data?.statistics.blockHeight) {
|
||||
return null;
|
||||
}
|
||||
// Queries all nodes from the environment provider via an interval
|
||||
// to calculate and return the difference between the most advanced block
|
||||
// and the block height of the current node
|
||||
export const useNodeHealth = (clients: ClientCollection, vegaUrl?: string) => {
|
||||
const [blockDiff, setBlockDiff] = useState(0);
|
||||
|
||||
if (!headers) {
|
||||
return 0;
|
||||
}
|
||||
useEffect(() => {
|
||||
if (!clients || !vegaUrl) return;
|
||||
|
||||
return Number(data.statistics.blockHeight) - headers.blockHeight;
|
||||
}, [data, headers]);
|
||||
const fetchBlockHeight = async (
|
||||
client?: ReturnType<typeof createClient>
|
||||
) => {
|
||||
try {
|
||||
const result = await client?.query<StatisticsQuery>({
|
||||
query: StatisticsDocument,
|
||||
fetchPolicy: 'no-cache', // always fetch and never cache
|
||||
});
|
||||
|
||||
return {
|
||||
coreBlockHeight: data?.statistics.blockHeight
|
||||
? Number(data?.statistics.blockHeight)
|
||||
: undefined,
|
||||
coreVegaTime: fromISONano(data?.statistics.vegaTime),
|
||||
datanodeBlockHeight: headers?.blockHeight,
|
||||
datanodeVegaTime: headers?.timestamp,
|
||||
blockDiff,
|
||||
};
|
||||
if (!result) return null;
|
||||
if (result.error) return null;
|
||||
return result;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const getBlockHeights = async () => {
|
||||
const nodes = Object.keys(clients).filter((key) => key !== vegaUrl);
|
||||
// make sure that your current vega url is always included
|
||||
// so we can compare later
|
||||
const testNodes = [vegaUrl, ...randomSubset(nodes, NODE_SUBSET_COUNT)];
|
||||
const result = await Promise.all(
|
||||
testNodes.map((node) => fetchBlockHeight(clients[node]))
|
||||
);
|
||||
const blockHeights: { [node: string]: number | null } = {};
|
||||
testNodes.forEach((node, i) => {
|
||||
const data = result[i];
|
||||
const blockHeight = data
|
||||
? Number(data?.data.statistics.blockHeight)
|
||||
: null;
|
||||
blockHeights[node] = blockHeight;
|
||||
});
|
||||
return blockHeights;
|
||||
};
|
||||
|
||||
// Every INTERVAL_TIME get block heights of a random subset
|
||||
// of nodes and determine if your current node is falling behind
|
||||
const interval = setInterval(async () => {
|
||||
const blockHeights = await getBlockHeights();
|
||||
const highestBlock = Math.max.apply(
|
||||
null,
|
||||
compact(Object.values(blockHeights))
|
||||
);
|
||||
const currNodeBlock = blockHeights[vegaUrl];
|
||||
|
||||
if (!currNodeBlock) {
|
||||
// Block height query failed and null was returned
|
||||
setBlockDiff(-1);
|
||||
} else {
|
||||
setBlockDiff(highestBlock - currNodeBlock);
|
||||
}
|
||||
}, INTERVAL_TIME);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [clients, vegaUrl]);
|
||||
|
||||
return blockDiff;
|
||||
};
|
||||
|
||||
const randomSubset = (arr: string[], size: number) => {
|
||||
const shuffled = shuffle(arr);
|
||||
return shuffled.slice(0, size);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ query Statistics {
|
||||
statistics {
|
||||
chainId
|
||||
blockHeight
|
||||
vegaTime
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -6,7 +6,7 @@ const defaultOptions = {} as const;
|
||||
export type StatisticsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type StatisticsQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string, vegaTime: any } };
|
||||
export type StatisticsQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string } };
|
||||
|
||||
export type BlockTimeSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -19,7 +19,6 @@ export const StatisticsDocument = gql`
|
||||
statistics {
|
||||
chainId
|
||||
blockHeight
|
||||
vegaTime
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -10,7 +10,6 @@ export const statisticsQuery = (
|
||||
__typename: 'Statistics',
|
||||
chainId: 'chain-id',
|
||||
blockHeight: '11',
|
||||
vegaTime: new Date().toISOString(),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
DateRangeFilter,
|
||||
fromISONano,
|
||||
fromNanoSeconds,
|
||||
getDateTimeFormat,
|
||||
SetFilter,
|
||||
t,
|
||||
@@ -199,7 +199,7 @@ export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
|
||||
valueFormatter={({
|
||||
value,
|
||||
}: VegaValueFormatterParams<LedgerEntry, 'vegaTime'>) =>
|
||||
value ? getDateTimeFormat().format(fromISONano(value)) : '-'
|
||||
value ? getDateTimeFormat().format(fromNanoSeconds(value)) : '-'
|
||||
}
|
||||
filter={DateRangeFilter}
|
||||
/>
|
||||
|
||||
@@ -4,12 +4,7 @@ export const toNanoSeconds = (date: Date | string) => {
|
||||
return new Date(date).getTime().toString() + '000000';
|
||||
};
|
||||
|
||||
export const fromISONano = (ts: string) => {
|
||||
export const fromNanoSeconds = (ts: string) => {
|
||||
const val = parseISO(ts);
|
||||
return new Date(isValid(val) ? val : 0);
|
||||
};
|
||||
|
||||
export const fromNanoSeconds = (ts: string | number) => {
|
||||
const ms = Number(String(ts).slice(0, -6));
|
||||
return new Date(ms);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Splash } from '../splash';
|
||||
import type { ReactNode } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import * as Sentry from '@sentry/react';
|
||||
|
||||
interface AsyncRendererProps<T> {
|
||||
loading: boolean;
|
||||
@@ -26,6 +27,7 @@ export function AsyncRenderer<T = object>({
|
||||
render,
|
||||
}: AsyncRendererProps<T>) {
|
||||
if (error) {
|
||||
Sentry.captureException(`Error rendering data: ${error.message}`);
|
||||
if (!data) {
|
||||
return (
|
||||
<Splash>
|
||||
|
||||
@@ -13,12 +13,10 @@ const mockSendTx = jest.fn<Promise<Partial<TransactionResponse> | null>, []>();
|
||||
|
||||
const pubKey = 'pubKey';
|
||||
|
||||
const mockDisconnect = jest.fn();
|
||||
jest.mock('./use-vega-wallet', () => ({
|
||||
useVegaWallet: () => ({
|
||||
sendTx: mockSendTx,
|
||||
pubKey,
|
||||
disconnect: mockDisconnect,
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -106,17 +104,6 @@ describe('useVegaTransactionManager', () => {
|
||||
mockSendTx.mockRejectedValue(null);
|
||||
renderHook(useVegaTransactionManager);
|
||||
await waitForNextTick();
|
||||
expect(mockDisconnect).not.toHaveBeenCalledWith();
|
||||
expect(update).toBeCalled();
|
||||
expect(update.mock.calls[0][1]?.status).toEqual(VegaTxStatus.Error);
|
||||
});
|
||||
|
||||
it('call disconnect if detect no service error', async () => {
|
||||
mockTransactionStoreState.mockReturnValue(defaultState);
|
||||
mockSendTx.mockRejectedValue(new TypeError('Failed to fetch'));
|
||||
renderHook(useVegaTransactionManager);
|
||||
await waitForNextTick();
|
||||
expect(mockDisconnect).toHaveBeenCalledWith();
|
||||
expect(update).toBeCalled();
|
||||
expect(update.mock.calls[0][1]?.status).toEqual(VegaTxStatus.Error);
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useVegaWallet } from './use-vega-wallet';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import type { WalletError } from './connectors';
|
||||
import { ClientErrors } from './connectors';
|
||||
import { VegaTxStatus, orderErrorResolve } from './use-vega-transaction';
|
||||
import { VegaTxStatus } from './use-vega-transaction';
|
||||
import { useVegaTransactionStore } from './use-vega-transaction-store';
|
||||
import { WalletClientError } from '@vegaprotocol/wallet-client';
|
||||
|
||||
export const useVegaTransactionManager = () => {
|
||||
const { sendTx, pubKey, disconnect } = useVegaWallet();
|
||||
const { sendTx, pubKey } = useVegaWallet();
|
||||
const processed = useRef<Set<number>>(new Set());
|
||||
const transaction = useVegaTransactionStore((state) =>
|
||||
state.transactions.find(
|
||||
@@ -38,14 +38,10 @@ export const useVegaTransactionManager = () => {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
const error = orderErrorResolve(err);
|
||||
if ((error as WalletError).code === ClientErrors.NO_SERVICE.code) {
|
||||
disconnect();
|
||||
}
|
||||
update(transaction.id, {
|
||||
error,
|
||||
error: err instanceof WalletClientError ? err : ClientErrors.UNKNOWN,
|
||||
status: VegaTxStatus.Error,
|
||||
});
|
||||
});
|
||||
}, [transaction, pubKey, del, sendTx, update, disconnect]);
|
||||
}, [transaction, pubKey, del, sendTx, update]);
|
||||
};
|
||||
|
||||
@@ -6,18 +6,17 @@ import {
|
||||
useTransactionEventSubscription,
|
||||
} from './__generated__/TransactionResult';
|
||||
import { useVegaTransactionStore } from './use-vega-transaction-store';
|
||||
|
||||
import { waitForWithdrawalApproval } from './wait-for-withdrawal-approval';
|
||||
|
||||
export const useVegaTransactionUpdater = () => {
|
||||
const client = useApolloClient();
|
||||
const updateWithdrawal = useVegaTransactionStore(
|
||||
(state) => state.updateWithdrawal
|
||||
);
|
||||
const updateOrder = useVegaTransactionStore((state) => state.updateOrder);
|
||||
const updateTransaction = useVegaTransactionStore(
|
||||
(state) => state.updateTransactionResult
|
||||
);
|
||||
|
||||
const { updateWithdrawal, updateOrder, updateTransaction } =
|
||||
useVegaTransactionStore((state) => ({
|
||||
updateWithdrawal: state.updateWithdrawal,
|
||||
updateOrder: state.updateOrder,
|
||||
updateTransaction: state.updateTransactionResult,
|
||||
}));
|
||||
const { pubKey } = useVegaWallet();
|
||||
const variables = { partyId: pubKey || '' };
|
||||
const skip = !pubKey;
|
||||
|
||||
@@ -87,7 +87,7 @@ describe('useVegaTransaction', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('handles an unknown error', () => {
|
||||
it('handles an unkwown error', () => {
|
||||
const unknownThrow = { foo: 'bar' };
|
||||
const mockSendTx = jest.fn(() => {
|
||||
throw unknownThrow;
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import {
|
||||
WalletClientError,
|
||||
WalletHttpError,
|
||||
} from '@vegaprotocol/wallet-client';
|
||||
import { useVegaWallet } from './use-vega-wallet';
|
||||
import type { VegaTransactionContentMap } from './vega-transaction-dialog';
|
||||
import { VegaTransactionDialog } from './vega-transaction-dialog';
|
||||
import type { Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import type { Transaction } from './connectors';
|
||||
import type { WalletError } from './connectors';
|
||||
import { ClientErrors } from './connectors';
|
||||
|
||||
export interface DialogProps {
|
||||
@@ -43,21 +38,8 @@ export const initialState = {
|
||||
dialogOpen: false,
|
||||
};
|
||||
|
||||
export const orderErrorResolve = (err: Error | unknown): Error => {
|
||||
if (err instanceof WalletClientError) {
|
||||
return err;
|
||||
} else if (err instanceof WalletHttpError) {
|
||||
return ClientErrors.UNKNOWN;
|
||||
} else if (err instanceof TypeError) {
|
||||
return ClientErrors.NO_SERVICE;
|
||||
} else if (err instanceof Error) {
|
||||
return err;
|
||||
}
|
||||
return ClientErrors.UNKNOWN;
|
||||
};
|
||||
|
||||
export const useVegaTransaction = () => {
|
||||
const { sendTx, disconnect } = useVegaWallet();
|
||||
const { sendTx } = useVegaWallet();
|
||||
const [transaction, _setTransaction] = useState<VegaTxState>(initialState);
|
||||
|
||||
const setTransaction = useCallback((update: Partial<VegaTxState>) => {
|
||||
@@ -106,10 +88,7 @@ export const useVegaTransaction = () => {
|
||||
|
||||
return null;
|
||||
} catch (err) {
|
||||
const error = orderErrorResolve(err);
|
||||
if ((error as WalletError).code === ClientErrors.NO_SERVICE.code) {
|
||||
disconnect();
|
||||
}
|
||||
const error = err instanceof Error ? err : ClientErrors.UNKNOWN;
|
||||
setTransaction({
|
||||
error,
|
||||
status: VegaTxStatus.Error,
|
||||
@@ -117,7 +96,7 @@ export const useVegaTransaction = () => {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
[sendTx, setTransaction, reset, disconnect]
|
||||
[sendTx, setTransaction, reset]
|
||||
);
|
||||
|
||||
const Dialog = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user