From d8bf88724538b6fb2af7b04ba778563d3950b911 Mon Sep 17 00:00:00 2001
From: Matthew Russell
Date: Tue, 17 May 2022 09:04:41 -0400
Subject: [PATCH] chore(#315): Convert token to use wallet lib
* delete token version of vega wallet serivce
* update use-user-vote to use new wallet service
* remove typo
* add further types for transaction submissions, add assets to withdraw page query
* update api client package to get generated types, adjust render logic of withdrawals page
* fix withdrawals list rendering
* update determine id function to not use nodejs buffer
* update service api client so it accepts new tx types
* remove stray logs and formatting
* make filtering erc20 assets the responsibility of the withdraw/deposit lib and not the app
* remove sha3 dep and use js-sha3 and ethers to determine ids
* use hook for fetching withdrawals form lib, add type policy to ensure withdrawal state is updated correctly
* fix: markets page feature
---
apps/token/src/components/nav/nav.tsx | 1 +
.../transaction-complete.tsx | 1 -
apps/token/src/hooks/use-create-withdrawal.ts | 143 ---------
.../src/hooks/use-erc-poll20-approval.ts | 66 ----
apps/token/src/i18n/translations/dev.json | 3 +-
apps/token/src/lib/apollo-client.ts | 7 +
apps/token/src/lib/sig-to-id.test.ts | 9 -
apps/token/src/lib/sig-to-id.ts | 18 --
.../lib/vega-wallet/vega-wallet-service.ts | 303 ------------------
.../src/lib/vega-wallet/vega-wallet-types.ts | 3 -
.../components/vote-details/use-user-vote.tsx | 14 +-
.../staking/associate/associate-page.tsx | 2 +
.../src/routes/staking/pending-stake.tsx | 34 +-
.../token/src/routes/staking/staking-form.tsx | 24 +-
.../withdraw/__generated__/WithdrawPage.ts | 42 +++
apps/token/src/routes/withdraw/index.tsx | 56 ++--
.../src/routes/withdraw/withdraw-form.tsx | 153 ---------
.../__generated__/WithdrawalsPage.ts | 105 ------
apps/token/src/routes/withdrawals/index.tsx | 194 ++++-------
.../src/integration/markets-page.feature | 2 +
.../src/support/pages/markets-page.ts | 3 +
.../step_definitions/markets-page.step.ts | 8 +-
apps/trading/lib/assets.ts | 18 --
.../portfolio/deposit/deposit-container.tsx | 3 +-
.../withdraw/withdraw-page-container.tsx | 3 +-
libs/deposits/src/lib/deposit-form.tsx | 16 +-
libs/deposits/src/lib/deposit-manager.tsx | 19 +-
.../src/lib/use-get-deposit-limits.ts | 2 +-
libs/react-helpers/src/lib/determine-id.ts | 17 +-
libs/wallet/src/connectors/index.ts | 5 +-
libs/wallet/src/connectors/rest-connector.ts | 9 +-
libs/wallet/src/provider.tsx | 20 +-
libs/wallet/src/types.ts | 8 +-
libs/withdraws/src/index.ts | 1 +
libs/withdraws/src/lib/test-helpers.ts | 1 +
libs/withdraws/src/lib/types.ts | 15 +-
libs/withdraws/src/lib/withdraw-form.tsx | 12 +-
package.json | 4 +-
yarn.lock | 27 +-
39 files changed, 265 insertions(+), 1106 deletions(-)
delete mode 100644 apps/token/src/hooks/use-create-withdrawal.ts
delete mode 100644 apps/token/src/hooks/use-erc-poll20-approval.ts
delete mode 100644 apps/token/src/lib/sig-to-id.test.ts
delete mode 100644 apps/token/src/lib/sig-to-id.ts
delete mode 100644 apps/token/src/lib/vega-wallet/vega-wallet-service.ts
delete mode 100644 apps/token/src/lib/vega-wallet/vega-wallet-types.ts
delete mode 100644 apps/token/src/routes/withdraw/withdraw-form.tsx
delete mode 100644 apps/token/src/routes/withdrawals/__generated__/WithdrawalsPage.ts
delete mode 100644 apps/trading/lib/assets.ts
diff --git a/apps/token/src/components/nav/nav.tsx b/apps/token/src/components/nav/nav.tsx
index 5b6a1dfe6..816e074d8 100644
--- a/apps/token/src/components/nav/nav.tsx
+++ b/apps/token/src/components/nav/nav.tsx
@@ -147,6 +147,7 @@ const IconLine = ({ inverted }: { inverted: boolean }) => (
const NavDrawer = ({ inverted }: { inverted: boolean }) => {
const { appState, appDispatch } = useAppState();
+
return (
<>
- LINK
{footer && {footer}
}
);
diff --git a/apps/token/src/hooks/use-create-withdrawal.ts b/apps/token/src/hooks/use-create-withdrawal.ts
deleted file mode 100644
index 806c72776..000000000
--- a/apps/token/src/hooks/use-create-withdrawal.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-import React from 'react';
-import * as Sentry from '@sentry/react';
-import { gql, useApolloClient } from '@apollo/client';
-import { sigToId } from '../lib/sig-to-id';
-import { vegaWalletService } from '../lib/vega-wallet/vega-wallet-service';
-
-import type { WithdrawSubmissionInput } from '../lib/vega-wallet/vega-wallet-service';
-import type {
- WithdrawalPoll,
- WithdrawalPollVariables,
-} from './__generated__/WithdrawalPoll';
-
-export enum Status {
- Idle,
- Submitted,
- Pending,
- Success,
- Failure,
-}
-
-type Submit = (
- amount: string,
- asset: string,
- receiverAddress: string
-) => Promise;
-
-const WITHDRAWAL_QUERY = gql`
- query WithdrawalPoll($partyId: ID!) {
- party(id: $partyId) {
- id
- withdrawals {
- id
- amount
- status
- asset {
- id
- symbol
- decimals
- }
- createdTimestamp
- withdrawnTimestamp
- txHash
- details {
- ... on Erc20WithdrawalDetails {
- receiverAddress
- }
- }
- }
- }
- }
-`;
-
-export function useCreateWithdrawal(pubKey: string): [Status, Submit] {
- const mountedRef = React.useRef(true);
- const client = useApolloClient();
- const [status, setStatus] = React.useState(Status.Idle);
- const [id, setId] = React.useState('');
-
- const safeSetStatus = (status: Status) => {
- if (mountedRef.current) {
- setStatus(status);
- }
- };
-
- const submit = React.useCallback(
- async (amount: string, asset: string, receiverAddress: string) => {
- const command: WithdrawSubmissionInput = {
- pubKey,
- withdrawSubmission: {
- amount,
- asset,
- ext: {
- erc20: {
- receiverAddress,
- },
- },
- },
- };
-
- safeSetStatus(Status.Submitted);
-
- try {
- const [err, res] = await vegaWalletService.commandSync(command);
-
- if (err || !res) {
- safeSetStatus(Status.Failure);
- } else {
- const id = sigToId(res.signature.value);
- setId(id);
- // Now await subscription
- }
-
- safeSetStatus(Status.Pending);
- } catch (err) {
- safeSetStatus(Status.Failure);
- Sentry.captureException(err);
- }
- },
- [pubKey]
- );
-
- React.useEffect(() => {
- let interval: ReturnType;
- if (status === Status.Pending) {
- interval = setInterval(async () => {
- try {
- const { data } = await client.query<
- WithdrawalPoll,
- WithdrawalPollVariables
- >({
- fetchPolicy: 'network-only',
- query: WITHDRAWAL_QUERY,
- variables: { partyId: pubKey },
- });
-
- // find matching withdrawals
- const withdrawal = data?.party?.withdrawals?.find((e) => {
- return e.id === id;
- });
- if (withdrawal) {
- safeSetStatus(Status.Success);
- clearInterval(interval);
- }
- } catch (err) {
- clearInterval(interval);
- }
- }, 1000);
- }
-
- return () => {
- clearInterval(interval);
- };
- }, [client, id, pubKey, status]);
-
- React.useEffect(() => {
- mountedRef.current = true;
- return () => {
- mountedRef.current = false;
- };
- }, []);
-
- return [status, submit];
-}
diff --git a/apps/token/src/hooks/use-erc-poll20-approval.ts b/apps/token/src/hooks/use-erc-poll20-approval.ts
deleted file mode 100644
index 9302126c2..000000000
--- a/apps/token/src/hooks/use-erc-poll20-approval.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import React from 'react';
-import { gql, useApolloClient } from '@apollo/client';
-
-import type {
- Erc20ApprovalPoll,
- Erc20ApprovalPoll_erc20WithdrawalApproval,
- Erc20ApprovalPollVariables,
-} from './__generated__/Erc20ApprovalPoll';
-
-const ERC20_APPROVAL_QUERY = gql`
- query Erc20ApprovalPoll($withdrawalId: ID!) {
- erc20WithdrawalApproval(withdrawalId: $withdrawalId) {
- assetSource
- amount
- nonce
- signatures
- targetAddress
- expiry
- }
- }
-`;
-
-export const usePollERC20Approval = (withdrawalId: string) => {
- const mountedRef = React.useRef(true);
- const client = useApolloClient();
- const [erc20Approval, setErc20Approval] =
- React.useState(null);
-
- const safeSetErc20Approval = (
- approval: Erc20ApprovalPoll_erc20WithdrawalApproval
- ) => {
- if (mountedRef.current) {
- setErc20Approval(approval);
- }
- };
-
- React.useEffect(() => {
- const interval = setInterval(async () => {
- try {
- const res = await client.query<
- Erc20ApprovalPoll,
- Erc20ApprovalPollVariables
- >({
- query: ERC20_APPROVAL_QUERY,
- variables: { withdrawalId },
- });
-
- if (res.data.erc20WithdrawalApproval) {
- safeSetErc20Approval(res.data.erc20WithdrawalApproval);
- clearInterval(interval);
- }
- } catch (err) {
- // No op. If the erc20 withdrawal is not created yet it will error
- // but we will just want to poll until it is. There is no bus event for
- // erc20 approvals yet..
- }
- }, 1000);
-
- return () => {
- clearInterval(interval);
- mountedRef.current = false;
- };
- }, [withdrawalId, client]);
-
- return erc20Approval;
-};
diff --git a/apps/token/src/i18n/translations/dev.json b/apps/token/src/i18n/translations/dev.json
index 0fbc294ae..27ce04728 100644
--- a/apps/token/src/i18n/translations/dev.json
+++ b/apps/token/src/i18n/translations/dev.json
@@ -76,6 +76,7 @@
"Loading": "Loading...",
"Something went wrong": "Something went wrong",
"Try again": "Try again",
+ "Incomplete": "Incomplete",
"Complete": "Complete",
"View on Etherscan (opens in a new tab)": "View on Etherscan (opens in a new tab)",
"Transaction in progress": "Transaction in progress",
@@ -437,7 +438,7 @@
"withdrawalsText": "These withdrawals need to be completed with an Ethereum transaction.",
"withdrawalsNone": "You don't have any pending withdrawals.",
"withdrawalsCompleteButton": "Finish withdrawal",
- "withdrawalsPreparingButton": "Preparing withdrawal",
+ "withdrawalTransaction": "Transaction ({{foreignChain}})",
"signature": "Signature",
"created": "Created",
"toEthereum": "To (Ethereum)",
diff --git a/apps/token/src/lib/apollo-client.ts b/apps/token/src/lib/apollo-client.ts
index fe9be7d10..d1462176c 100644
--- a/apps/token/src/lib/apollo-client.ts
+++ b/apps/token/src/lib/apollo-client.ts
@@ -136,6 +136,13 @@ export function createClient() {
},
},
},
+ Withdrawal: {
+ fields: {
+ pendingOnForeignChain: {
+ read: (isPending = false) => isPending,
+ },
+ },
+ },
},
});
diff --git a/apps/token/src/lib/sig-to-id.test.ts b/apps/token/src/lib/sig-to-id.test.ts
deleted file mode 100644
index 07f771740..000000000
--- a/apps/token/src/lib/sig-to-id.test.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { sigToId } from './sig-to-id';
-
-test('creating an id from a signature', () => {
- const sig =
- '3594b7f4e1c078aaa65b3efac57e1436da64d60c2961bf432dc62daa36f8b0b2602ed9c990ee46dd8ab5181e19c19b06587f080d22fc4543c1869970e678f20f';
- const expected =
- '9ebd2c424a9426bf5f38112878eb2f99bfdf5ec17b5782b944e6be8177084327';
- expect(sigToId(sig)).toEqual(expected);
-});
diff --git a/apps/token/src/lib/sig-to-id.ts b/apps/token/src/lib/sig-to-id.ts
deleted file mode 100644
index 3bcd97fee..000000000
--- a/apps/token/src/lib/sig-to-id.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { ethers } from 'ethers';
-import { SHA3 } from 'sha3';
-
-export const sigToId = (sig: string) => {
- // Prepend 0x
- if (sig.slice(0, 2) !== '0x') {
- sig = '0x' + sig;
- }
-
- // Create the ID
- const hash = new SHA3(256);
- const bytes = ethers.utils.arrayify(sig);
- hash.update(Buffer.from(bytes));
- const id = ethers.utils.hexlify(hash.digest());
-
- // Remove 0x as core doesn't keep them in the API
- return id.substring(2);
-};
diff --git a/apps/token/src/lib/vega-wallet/vega-wallet-service.ts b/apps/token/src/lib/vega-wallet/vega-wallet-service.ts
deleted file mode 100644
index 4d13ec082..000000000
--- a/apps/token/src/lib/vega-wallet/vega-wallet-service.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-import type { VoteValue } from '../../__generated__/globalTypes';
-import type { VegaKey } from '../../contexts/app-state/app-state-context';
-import type { VOTE_VALUE_MAP } from '../../routes/governance/components/vote-details';
-import { LocalStorage } from '@vegaprotocol/react-helpers';
-import type { GenericErrorResponse } from './vega-wallet-types';
-
-export const MINIMUM_WALLET_VERSION =
- process.env['NX_SUPPORTED_WALLET_VERSION'];
-
-export const DEFAULT_WALLET_URL = 'http://localhost:1789';
-export const HOSTED_WALLET_URL = 'https://wallet.testnet.vega.xyz';
-const TOKEN_STORAGE_KEY = 'vega_wallet_token';
-const WALLET_URL_KEY = 'vega_wallet_url';
-const KEY_STORAGE_KEY = 'vega_wallet_key';
-
-const Endpoints = {
- STATUS: 'status',
- TOKEN: 'auth/token',
- KEYS: 'keys',
- COMMAND: 'command/sync',
- VERSION: 'version',
-};
-
-export const Errors = {
- NO_TOKEN: 'No token',
- SERVICE_UNAVAILABLE: 'Wallet service unavailable',
- SESSION_EXPIRED: 'Session expired',
- INVALID_CREDENTIALS: 'Invalid credentials',
- COMMAND_FAILED: 'Command failed',
- INVALID_URL: 'Invalid wallet URL',
-};
-
-export interface DelegateSubmissionInput {
- pubKey: string;
- delegateSubmission: {
- nodeId: string;
- amount: string;
- };
-}
-
-export interface UndelegateSubmissionInput {
- pubKey: string;
- undelegateSubmission: {
- nodeId: string;
- amount: string;
- method: 'METHOD_NOW' | 'METHOD_AT_END_OF_EPOCH';
- };
-}
-
-export interface VoteSubmissionInput {
- pubKey: string;
- voteSubmission: {
- value: typeof VOTE_VALUE_MAP[VoteValue];
- proposalId: string;
- };
-}
-
-export interface WithdrawSubmissionInput {
- pubKey: string;
- withdrawSubmission: {
- amount: string;
- asset: string;
- ext: {
- erc20: {
- receiverAddress: string;
- };
- };
- };
-}
-
-export type CommandSyncInput =
- | DelegateSubmissionInput
- | UndelegateSubmissionInput
- | VoteSubmissionInput
- | WithdrawSubmissionInput;
-
-export interface CommandSyncResponse {
- inputData: string;
- pubKey: string;
- signature: {
- algo: string;
- value: string;
- version: number;
- };
- version: number;
-}
-
-export interface IVegaWalletService {
- url: string;
- token: string;
- getToken(params: {
- wallet: string;
- passphrase: string;
- }): Promise<[string | undefined, string | undefined]>;
- revokeToken(): Promise<[string | undefined, boolean]>;
- getKeys(): Promise<[string | undefined, VegaKey[] | undefined]>;
-}
-
-export class VegaWalletService implements IVegaWalletService {
- version: number;
- url: string;
- token: string;
- key: string;
-
- constructor() {
- this.version = 1;
- this.url = LocalStorage.getItem(WALLET_URL_KEY) || DEFAULT_WALLET_URL;
- this.token = LocalStorage.getItem(TOKEN_STORAGE_KEY) || '';
- this.key = LocalStorage.getItem(KEY_STORAGE_KEY) || '';
- }
-
- async getToken(params: {
- wallet: string;
- passphrase: string;
- url: string;
- }): Promise<[string | undefined, string | undefined]> {
- const urlValid = this.validateUrl(params.url);
-
- if (urlValid) {
- this.setWalletUrl(params.url);
- } else {
- return [Errors.INVALID_URL, undefined];
- }
-
- try {
- const res = await fetch(`${this.getUrl()}/${Endpoints.TOKEN}`, {
- method: 'post',
- body: JSON.stringify(params),
- });
- const json = await res.json();
-
- if ('token' in json) {
- this.setToken(json.token);
- return [undefined, json.token];
- } else {
- return [Errors.INVALID_CREDENTIALS, undefined];
- }
- } catch (err) {
- return this.handleServiceUnavailable();
- }
- }
-
- async revokeToken(): Promise<[string | undefined, boolean]> {
- if (!this.token) {
- return [Errors.NO_TOKEN, false];
- }
-
- try {
- const res = await fetch(`${this.getUrl()}/${Endpoints.TOKEN}`, {
- method: 'delete',
- headers: { authorization: `Bearer ${this.token}` },
- });
- const json = await res.json();
-
- if (json.success) {
- this.clearKey();
- this.clearToken();
- this.clearWalletUrl();
- return [undefined, true];
- } else {
- return [undefined, false];
- }
- } catch (err) {
- return this.handleServiceUnavailable(false);
- }
- }
-
- async getKeys(): Promise<[string | undefined, VegaKey[] | undefined]> {
- if (!this.token) {
- return [Errors.NO_TOKEN, undefined];
- }
-
- try {
- const res = await fetch(`${this.getUrl()}/${Endpoints.KEYS}`, {
- headers: { authorization: `Bearer ${this.token}` },
- });
-
- const err = this.verifyResponse(res);
-
- if (err) {
- return [err, undefined];
- }
-
- const json = await res.json();
-
- return [undefined, json.keys];
- } catch (err) {
- return this.handleServiceUnavailable();
- }
- }
-
- async commandSync(
- body: CommandSyncInput
- ): Promise<[string | undefined, CommandSyncResponse | undefined]> {
- if (!this.token) {
- return [Errors.NO_TOKEN, undefined];
- }
-
- try {
- const res = await fetch(`${this.getUrl()}/${Endpoints.COMMAND}`, {
- method: 'post',
- body: JSON.stringify({
- ...body,
- propagate: true,
- }),
- headers: { authorization: `Bearer ${this.token}` },
- });
-
- const err = this.verifyResponse(res);
-
- if (err) {
- return [err, undefined];
- }
-
- const json = await res.json();
-
- if ('errors' in json) {
- return [Errors.COMMAND_FAILED, undefined];
- } else {
- return [undefined, json];
- }
- } catch (err) {
- return this.handleServiceUnavailable();
- }
- }
-
- setKey(key: string) {
- this.key = key;
- LocalStorage.setItem(KEY_STORAGE_KEY, key);
- }
-
- private clearKey() {
- this.key = '';
- LocalStorage.removeItem(KEY_STORAGE_KEY);
- }
-
- private setToken(token: string) {
- this.token = token;
- LocalStorage.setItem(TOKEN_STORAGE_KEY, token);
- }
-
- private clearToken() {
- this.token = '';
- LocalStorage.removeItem(TOKEN_STORAGE_KEY);
- }
-
- private setWalletUrl(url: string) {
- this.url = url;
- LocalStorage.setItem(WALLET_URL_KEY, url);
- }
-
- private clearWalletUrl() {
- this.url = DEFAULT_WALLET_URL;
- LocalStorage.removeItem(WALLET_URL_KEY);
- }
-
- private getUrl() {
- return `${this.url}/api/v${this.version}`;
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- private handleServiceUnavailable(returnVal?: boolean): [string, any] {
- this.clearWalletUrl();
- return [Errors.SERVICE_UNAVAILABLE, returnVal];
- }
-
- private validateUrl(url: string) {
- try {
- new URL(url);
- } catch (err) {
- return false;
- }
- return true;
- }
-
- /**
- * Parses the response object to either return an error string or null if
- * everything looks good. Clears token 403 response returned
- */
- private verifyResponse(res: Response): string | null {
- if (res.status === 403) {
- this.clearToken();
- return Errors.SESSION_EXPIRED;
- } else if (!res.ok) {
- return Errors.COMMAND_FAILED;
- }
-
- return null;
- }
-}
-
-export function hasErrorProperty(obj: unknown): obj is GenericErrorResponse {
- if (
- (obj as GenericErrorResponse).error !== undefined &&
- typeof (obj as GenericErrorResponse).error === 'string'
- ) {
- return true;
- }
-
- return false;
-}
-
-export const vegaWalletService = new VegaWalletService();
diff --git a/apps/token/src/lib/vega-wallet/vega-wallet-types.ts b/apps/token/src/lib/vega-wallet/vega-wallet-types.ts
deleted file mode 100644
index 32b2a7bb3..000000000
--- a/apps/token/src/lib/vega-wallet/vega-wallet-types.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface GenericErrorResponse {
- error: string;
-}
diff --git a/apps/token/src/routes/governance/components/vote-details/use-user-vote.tsx b/apps/token/src/routes/governance/components/vote-details/use-user-vote.tsx
index 816ad91e5..a9fd5be7d 100644
--- a/apps/token/src/routes/governance/components/vote-details/use-user-vote.tsx
+++ b/apps/token/src/routes/governance/components/vote-details/use-user-vote.tsx
@@ -2,8 +2,6 @@ import { captureException, captureMessage } from '@sentry/minimal';
import * as React from 'react';
import { VoteValue } from '../../../../__generated__/globalTypes';
-import type { VoteSubmissionInput } from '../../../../lib/vega-wallet/vega-wallet-service';
-import { vegaWalletService } from '../../../../lib/vega-wallet/vega-wallet-service';
import { VOTE_VALUE_MAP } from './vote-types';
import { useVegaWallet } from '@vegaprotocol/wallet';
@@ -44,7 +42,7 @@ export function useUserVote(
yesVotes: Votes | null,
noVotes: Votes | null
) {
- const { keypair } = useVegaWallet();
+ const { keypair, sendTx } = useVegaWallet();
const yes = React.useMemo(() => yesVotes || [], [yesVotes]);
const no = React.useMemo(() => noVotes || [], [noVotes]);
@@ -98,19 +96,15 @@ export function useUserVote(
setVoteState(VoteState.Pending);
try {
- const variables: VoteSubmissionInput = {
+ const variables = {
pubKey: keypair.pub,
+ propagate: true,
voteSubmission: {
value: VOTE_VALUE_MAP[value],
proposalId,
},
};
- const [err] = await vegaWalletService.commandSync(variables);
-
- if (err) {
- setVoteState(VoteState.Failed);
- captureException(err);
- }
+ await sendTx(variables);
// Now await vote via poll in parent component
} catch (err) {
diff --git a/apps/token/src/routes/staking/associate/associate-page.tsx b/apps/token/src/routes/staking/associate/associate-page.tsx
index 3bcb2dc05..ab8922553 100644
--- a/apps/token/src/routes/staking/associate/associate-page.tsx
+++ b/apps/token/src/routes/staking/associate/associate-page.tsx
@@ -58,10 +58,12 @@ export const AssociatePage = ({
() => totalVestedBalance.plus(totalLockedBalance).isEqualTo(0),
[totalLockedBalance, totalVestedBalance]
);
+
const zeroVega = React.useMemo(
() => walletBalance.isEqualTo(0),
[walletBalance]
);
+
React.useEffect(() => {
if (zeroVega && !zeroVesting) {
setSelectedStakingMethod(StakingMethod.Contract);
diff --git a/apps/token/src/routes/staking/pending-stake.tsx b/apps/token/src/routes/staking/pending-stake.tsx
index 5dbffbaca..79747c4e2 100644
--- a/apps/token/src/routes/staking/pending-stake.tsx
+++ b/apps/token/src/routes/staking/pending-stake.tsx
@@ -5,8 +5,8 @@ import { useTranslation } from 'react-i18next';
import { useAppState } from '../../contexts/app-state/app-state-context';
import { BigNumber } from '../../lib/bignumber';
import { removeDecimal } from '../../lib/decimals';
-import { vegaWalletService } from '../../lib/vega-wallet/vega-wallet-service';
-import type { UndelegateSubmissionInput } from '../../lib/vega-wallet/vega-wallet-service';
+import { useVegaWallet } from '@vegaprotocol/wallet';
+import type { UndelegateSubmissionBody } from '@vegaprotocol/vegawallet-service-api-client';
interface PendingStakeProps {
pendingAmount: BigNumber;
@@ -27,28 +27,26 @@ export const PendingStake = ({
pubkey,
}: PendingStakeProps) => {
const { t } = useTranslation();
+ const { sendTx } = useVegaWallet();
const { appState } = useAppState();
const [formState, setFormState] = React.useState(FormState.Default);
const removeStakeNow = async () => {
setFormState(FormState.Pending);
- const undelegateInput: UndelegateSubmissionInput = {
- pubKey: pubkey,
- undelegateSubmission: {
- nodeId,
- amount: removeDecimal(new BigNumber(pendingAmount), appState.decimals),
- method: 'METHOD_NOW',
- },
- };
-
try {
- const command = undelegateInput;
- const [err] = await vegaWalletService.commandSync(command);
-
- if (err) {
- setFormState(FormState.Failure);
- Sentry.captureException(err);
- }
+ const command: UndelegateSubmissionBody = {
+ pubKey: pubkey,
+ propagate: true,
+ undelegateSubmission: {
+ nodeId,
+ amount: removeDecimal(
+ new BigNumber(pendingAmount),
+ appState.decimals
+ ),
+ method: 'METHOD_NOW',
+ },
+ };
+ await sendTx(command);
} catch (err) {
setFormState(FormState.Failure);
Sentry.captureException(err);
diff --git a/apps/token/src/routes/staking/staking-form.tsx b/apps/token/src/routes/staking/staking-form.tsx
index 5de314529..cd49f7b22 100644
--- a/apps/token/src/routes/staking/staking-form.tsx
+++ b/apps/token/src/routes/staking/staking-form.tsx
@@ -12,11 +12,6 @@ import { useNetworkParam } from '../../hooks/use-network-param';
import { useSearchParams } from '../../hooks/use-search-params';
import { BigNumber } from '../../lib/bignumber';
import { addDecimal, removeDecimal } from '../../lib/decimals';
-import type {
- DelegateSubmissionInput,
- UndelegateSubmissionInput,
-} from '../../lib/vega-wallet/vega-wallet-service';
-import { vegaWalletService } from '../../lib/vega-wallet/vega-wallet-service';
import type {
PartyDelegations,
PartyDelegationsVariables,
@@ -25,6 +20,11 @@ import { StakeFailure } from './stake-failure';
import { StakePending } from './stake-pending';
import { StakeSuccess } from './stake-success';
import { Button, FormGroup } from '@vegaprotocol/ui-toolkit';
+import { useVegaWallet } from '@vegaprotocol/wallet';
+import type {
+ DelegateSubmissionBody,
+ UndelegateSubmissionBody,
+} from '@vegaprotocol/vegawallet-service-api-client';
export const PARTY_DELEGATIONS_QUERY = gql`
query PartyDelegations($partyId: ID!) {
@@ -81,6 +81,7 @@ export const StakingForm = ({
const navigate = useNavigate();
const client = useApolloClient();
const { appState } = useAppState();
+ const { sendTx } = useVegaWallet();
const [formState, setFormState] = React.useState(FormState.Default);
const { t } = useTranslation();
const [action, setAction] = React.useState(params.action);
@@ -114,15 +115,17 @@ export const StakingForm = ({
async function onSubmit() {
setFormState(FormState.Pending);
- const delegateInput: DelegateSubmissionInput = {
+ const delegateInput: DelegateSubmissionBody = {
pubKey: pubkey,
+ propagate: true,
delegateSubmission: {
nodeId,
amount: removeDecimal(new BigNumber(amount), appState.decimals),
},
};
- const undelegateInput: UndelegateSubmissionInput = {
+ const undelegateInput: UndelegateSubmissionBody = {
pubKey: pubkey,
+ propagate: true,
undelegateSubmission: {
nodeId,
amount: removeDecimal(new BigNumber(amount), appState.decimals),
@@ -134,12 +137,7 @@ export const StakingForm = ({
};
try {
const command = action === Actions.Add ? delegateInput : undelegateInput;
- const [err] = await vegaWalletService.commandSync(command);
-
- if (err) {
- setFormState(FormState.Failure);
- Sentry.captureException(err);
- }
+ await sendTx(command);
// await success via poll
} catch (err) {
diff --git a/apps/token/src/routes/withdraw/__generated__/WithdrawPage.ts b/apps/token/src/routes/withdraw/__generated__/WithdrawPage.ts
index 0a8b95c75..bb6f1aacf 100644
--- a/apps/token/src/routes/withdraw/__generated__/WithdrawPage.ts
+++ b/apps/token/src/routes/withdraw/__generated__/WithdrawPage.ts
@@ -140,11 +140,53 @@ export interface WithdrawPage_party {
withdrawals: WithdrawPage_party_withdrawals[] | null;
}
+export interface WithdrawPage_assets_source_BuiltinAsset {
+ __typename: "BuiltinAsset";
+}
+
+export interface WithdrawPage_assets_source_ERC20 {
+ __typename: "ERC20";
+ /**
+ * The address of the erc20 contract
+ */
+ contractAddress: string;
+}
+
+export type WithdrawPage_assets_source = WithdrawPage_assets_source_BuiltinAsset | WithdrawPage_assets_source_ERC20;
+
+export interface WithdrawPage_assets {
+ __typename: "Asset";
+ /**
+ * The id of the asset
+ */
+ id: string;
+ /**
+ * The symbol of the asset (e.g: GBP)
+ */
+ symbol: string;
+ /**
+ * The full name of the asset (e.g: Great British Pound)
+ */
+ name: string;
+ /**
+ * The precision of the asset
+ */
+ decimals: number;
+ /**
+ * The origin source of the asset (e.g: an erc20 asset)
+ */
+ source: WithdrawPage_assets_source;
+}
+
export interface WithdrawPage {
/**
* An entity that is trading on the VEGA network
*/
party: WithdrawPage_party | null;
+ /**
+ * The list of all assets in use in the vega network
+ */
+ assets: WithdrawPage_assets[] | null;
}
export interface WithdrawPageVariables {
diff --git a/apps/token/src/routes/withdraw/index.tsx b/apps/token/src/routes/withdraw/index.tsx
index 10dfed0ee..89dc9b1ac 100644
--- a/apps/token/src/routes/withdraw/index.tsx
+++ b/apps/token/src/routes/withdraw/index.tsx
@@ -5,7 +5,6 @@ import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { AccountType } from '../../__generated__/globalTypes';
-import { EthWalletContainer } from '../../components/eth-wallet-container';
import { Heading } from '../../components/heading';
import { SplashLoader } from '../../components/splash-loader';
import { VegaWalletContainer } from '../../components/vega-wallet-container';
@@ -15,7 +14,7 @@ import type {
WithdrawPage,
WithdrawPageVariables,
} from './__generated__/WithdrawPage';
-import { WithdrawForm } from './withdraw-form';
+import { WithdrawManager } from '@vegaprotocol/withdraws';
const Withdraw = () => {
const { t } = useTranslation();
@@ -24,9 +23,11 @@ const Withdraw = () => {
<>
{t('withdrawPageText')}
-
- {(currVegaKey) => }
-
+
+
+ {(currVegaKey) => }
+
+
{t('withdrawPageInfoCalloutText')}
@@ -74,6 +75,17 @@ const WITHDRAW_PAGE_QUERY = gql`
}
}
}
+ assets {
+ id
+ symbol
+ name
+ decimals
+ source {
+ ... on ERC20 {
+ contractAddress
+ }
+ }
+ }
}
`;
@@ -123,27 +135,21 @@ export const WithdrawContainer = ({ currVegaKey }: WithdrawContainerProps) => {
return (
<>
{hasPendingWithdrawals && (
-
- {t('pendingWithdrawalsCalloutText')}
-
-
- {t('pendingWithdrawalsCalloutButton')}
-
-
-
+
+
+ {t('pendingWithdrawalsCalloutText')}
+
+
+ {t('pendingWithdrawalsCalloutButton')}
+
+
+
+
)}
-
- {(connectedAddress) => (
-
- )}
-
+
>
);
};
diff --git a/apps/token/src/routes/withdraw/withdraw-form.tsx b/apps/token/src/routes/withdraw/withdraw-form.tsx
deleted file mode 100644
index d8e7b3cca..000000000
--- a/apps/token/src/routes/withdraw/withdraw-form.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import { Callout, FormGroup, Intent, Select } from '@vegaprotocol/ui-toolkit';
-import { ethers } from 'ethers';
-import React from 'react';
-import { useTranslation } from 'react-i18next';
-import { useNavigate } from 'react-router';
-
-import { Loader } from '../../components/loader';
-import { StatefulButton } from '../../components/stateful-button';
-import { AmountInput } from '../../components/token-input';
-import type { VegaKeyExtended } from '@vegaprotocol/wallet';
-import {
- Status as WithdrawStatus,
- useCreateWithdrawal,
-} from '../../hooks/use-create-withdrawal';
-import { BigNumber } from '../../lib/bignumber';
-import { removeDecimal } from '../../lib/decimals';
-import { Routes } from '../router-config';
-import type { WithdrawPage_party_accounts } from './__generated__/WithdrawPage';
-import { EthAddressInput } from './eth-address-input';
-
-interface WithdrawFormProps {
- accounts: WithdrawPage_party_accounts[];
- currVegaKey: VegaKeyExtended;
- connectedAddress: string;
-}
-
-export const WithdrawForm = ({
- accounts,
- currVegaKey,
- connectedAddress,
-}: WithdrawFormProps) => {
- const { t } = useTranslation();
- const navigate = useNavigate();
- const [amountStr, setAmount] = React.useState('');
- const [account, setAccount] = React.useState(accounts[0]);
- const [status, submit] = useCreateWithdrawal(currVegaKey.pub);
- const [destinationAddress, setDestinationAddress] =
- React.useState(connectedAddress);
- const amount = React.useMemo(
- () => new BigNumber(amountStr || 0),
- [amountStr]
- );
-
- const maximum = React.useMemo(() => {
- if (account) {
- return new BigNumber(account.balanceFormatted);
- }
-
- return new BigNumber(0);
- }, [account]);
-
- const valid = React.useMemo(() => {
- if (
- !destinationAddress ||
- amount.isLessThanOrEqualTo(0) ||
- amount.isGreaterThan(maximum)
- ) {
- return false;
- }
- return true;
- }, [destinationAddress, amount, maximum]);
-
- const addressValid = React.useMemo(() => {
- return ethers.utils.isAddress(destinationAddress);
- }, [destinationAddress]);
-
- // Navigate to complete withdrawals page once withdrawal
- // creation is complete
- React.useEffect(() => {
- if (status === WithdrawStatus.Success) {
- navigate(Routes.WITHDRAWALS);
- }
- }, [status, navigate]);
-
- return (
-
- );
-};
diff --git a/apps/token/src/routes/withdrawals/__generated__/WithdrawalsPage.ts b/apps/token/src/routes/withdrawals/__generated__/WithdrawalsPage.ts
deleted file mode 100644
index b7f5a993d..000000000
--- a/apps/token/src/routes/withdrawals/__generated__/WithdrawalsPage.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-/* tslint:disable */
-/* eslint-disable */
-// @generated
-// This file was automatically generated and should not be edited.
-
-import { WithdrawalStatus } from "@vegaprotocol/types";
-
-// ====================================================
-// GraphQL query operation: WithdrawalsPage
-// ====================================================
-
-export interface WithdrawalsPage_party_withdrawals_asset {
- __typename: "Asset";
- /**
- * The id of the asset
- */
- id: string;
- /**
- * The symbol of the asset (e.g: GBP)
- */
- symbol: string;
- /**
- * The precision of the asset
- */
- decimals: number;
-}
-
-export interface WithdrawalsPage_party_withdrawals_party {
- __typename: "Party";
- /**
- * Party identifier
- */
- id: string;
-}
-
-export interface WithdrawalsPage_party_withdrawals_details {
- __typename: "Erc20WithdrawalDetails";
- /**
- * The ethereum address of the receiver of the asset funds
- */
- receiverAddress: string;
-}
-
-export interface WithdrawalsPage_party_withdrawals {
- __typename: "Withdrawal";
- /**
- * The Vega internal id of the withdrawal
- */
- id: string;
- /**
- * The amount to be withdrawn
- */
- amount: string;
- /**
- * The asset to be withdrawn
- */
- asset: WithdrawalsPage_party_withdrawals_asset;
- /**
- * The PartyID initiating the withdrawal
- */
- party: WithdrawalsPage_party_withdrawals_party;
- /**
- * The current status of the withdrawal
- */
- status: WithdrawalStatus;
- /**
- * RFC3339Nano time at which the withdrawal was created
- */
- createdTimestamp: string;
- /**
- * RFC3339Nano time at which the withdrawal was finalized
- */
- withdrawnTimestamp: string | null;
- /**
- * Hash of the transaction on the foreign chain
- */
- txHash: string | null;
- /**
- * Foreign chain specific details about the withdrawal
- */
- details: WithdrawalsPage_party_withdrawals_details | null;
-}
-
-export interface WithdrawalsPage_party {
- __typename: "Party";
- /**
- * Party identifier
- */
- id: string;
- /**
- * The list of all withdrawals initiated by the party
- */
- withdrawals: WithdrawalsPage_party_withdrawals[] | null;
-}
-
-export interface WithdrawalsPage {
- /**
- * An entity that is trading on the VEGA network
- */
- party: WithdrawalsPage_party | null;
-}
-
-export interface WithdrawalsPageVariables {
- partyId: string;
-}
diff --git a/apps/token/src/routes/withdrawals/index.tsx b/apps/token/src/routes/withdrawals/index.tsx
index 57a754042..fb5685f2f 100644
--- a/apps/token/src/routes/withdrawals/index.tsx
+++ b/apps/token/src/routes/withdrawals/index.tsx
@@ -1,6 +1,4 @@
-import { gql, useQuery } from '@apollo/client';
-import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
-import { useWeb3React } from '@web3-react/core';
+import { Splash } from '@vegaprotocol/ui-toolkit';
import { format } from 'date-fns';
import orderBy from 'lodash/orderBy';
import React from 'react';
@@ -10,23 +8,16 @@ import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../components/heading';
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
import { SplashLoader } from '../../components/splash-loader';
-import { TransactionButton } from '../../components/transaction-button';
import { VegaWalletContainer } from '../../components/vega-wallet-container';
import type { VegaKeyExtended } from '@vegaprotocol/wallet';
-import { useContracts } from '../../contexts/contracts/contracts-context';
-import { TxState } from '../../hooks/transaction-reducer';
-import { usePollERC20Approval } from '../../hooks/use-erc-poll20-approval';
-import { useRefreshBalances } from '../../hooks/use-refresh-balances';
-import { useTransaction } from '../../hooks/use-transaction';
import { BigNumber } from '../../lib/bignumber';
import { DATE_FORMAT_DETAILED } from '../../lib/date-formats';
import { addDecimal } from '../../lib/decimals';
import { truncateMiddle } from '../../lib/truncate-middle';
-import type {
- WithdrawalsPage,
- WithdrawalsPage_party_withdrawals,
- WithdrawalsPageVariables,
-} from './__generated__/WithdrawalsPage';
+import type { Withdrawals_party_withdrawals } from '@vegaprotocol/withdraws';
+import { useCompleteWithdraw, useWithdrawals } from '@vegaprotocol/withdraws';
+import { TransactionDialog } from '@vegaprotocol/web3';
+import { WithdrawalStatus } from '../../__generated__/globalTypes';
const Withdrawals = () => {
const { t } = useTranslation();
@@ -34,13 +25,6 @@ const Withdrawals = () => {
return (
<>
- {t('withdrawalsText')}
-
- {t('withdrawalsPreparedWarningText')}
-
{(currVegaKey) => (
@@ -54,51 +38,12 @@ interface WithdrawPendingContainerProps {
currVegaKey: VegaKeyExtended;
}
-const WITHDRAWALS_PAGE_QUERY = gql`
- query WithdrawalsPage($partyId: ID!) {
- party(id: $partyId) {
- id
- withdrawals {
- id
- amount
- asset {
- id
- symbol
- decimals
- }
- party {
- id
- }
- status
- createdTimestamp
- withdrawnTimestamp
- txHash
- details {
- ... on Erc20WithdrawalDetails {
- receiverAddress
- }
- }
- }
- }
- }
-`;
-
const WithdrawPendingContainer = ({
currVegaKey,
}: WithdrawPendingContainerProps) => {
const { t } = useTranslation();
- const { account } = useWeb3React();
- const refreshBalances = useRefreshBalances(account || '');
- const { data, loading, error, refetch } = useQuery<
- WithdrawalsPage,
- WithdrawalsPageVariables
- >(WITHDRAWALS_PAGE_QUERY, {
- variables: { partyId: currVegaKey.pub },
- // This must be network-only because you are navigated to this page automatically after the withdrawal is created,
- // if you have already visited this page the query result is cached with 0 withdrawals, so we need to refetch every
- // time to ensure the withdrawal is shown immediately
- fetchPolicy: 'network-only',
- });
+ const { transaction, submit } = useCompleteWithdraw();
+ const { data, loading, error } = useWithdrawals();
const withdrawals = React.useMemo(() => {
if (!data?.party?.withdrawals?.length) return [];
@@ -132,61 +77,60 @@ const WithdrawPendingContainer = ({
}
return (
-
- {withdrawals.map((w) => (
- -
-
-
- ))}
-
+ <>
+ {t('withdrawalsPreparedWarningHeading')}
+ {t('withdrawalsText')}
+ {t('withdrawalsPreparedWarningText')}
+
+ {withdrawals.map((w) => (
+ -
+
+
+ ))}
+
+
+ >
);
};
interface WithdrawalProps {
- withdrawal: WithdrawalsPage_party_withdrawals;
- refetchWithdrawals: () => void;
- refetchBalances: () => void;
+ withdrawal: Withdrawals_party_withdrawals;
+ complete: (withdrawalId: string) => void;
}
-export const Withdrawal = ({
- withdrawal,
- refetchWithdrawals,
- refetchBalances,
-}: WithdrawalProps) => {
+export const Withdrawal = ({ withdrawal, complete }: WithdrawalProps) => {
const { t } = useTranslation();
- const erc20Approval = usePollERC20Approval(withdrawal.id);
- const { erc20Bridge } = useContracts();
- const { state, perform, reset } = useTransaction(() => {
- if (!erc20Approval) {
- throw new Error('Withdraw needs approval object');
- }
- if (!withdrawal.details?.receiverAddress) {
- throw new Error('Missing receiver address');
+
+ const renderStatus = ({
+ id,
+ status,
+ txHash,
+ pendingOnForeignChain,
+ }: Withdrawals_party_withdrawals) => {
+ if (pendingOnForeignChain) {
+ return t('Pending');
}
- return erc20Bridge.withdraw({
- assetSource: erc20Approval.assetSource,
- amount: erc20Approval.amount,
- nonce: erc20Approval.nonce,
- signatures: erc20Approval.signatures,
- // TODO: switch when targetAddress is populated and deployed to mainnet data.erc20WithdrawalApproval.targetAddress,
- targetAddress: withdrawal.details.receiverAddress,
- });
- });
-
- React.useEffect(() => {
- // Once complete we need to refetch the withdrawals so that pending withdrawal
- // is updated to have a txHash indicating it is complete. Updating your account balance
- // is already handled by the query in the VegaWallet that polls
- if (state.txState === TxState.Complete) {
- refetchWithdrawals();
- refetchBalances();
+ if (status === WithdrawalStatus.Finalized) {
+ if (txHash) {
+ return t('Complete');
+ } else {
+ return (
+ <>
+ {t('Incomplete')}{' '}
+
+ >
+ );
+ }
}
- }, [state, refetchWithdrawals, refetchBalances]);
+
+ return status;
+ };
return (
@@ -201,10 +145,6 @@ export const Withdrawal = ({
{withdrawal.asset.symbol}
-
- {t('from')}
- {truncateMiddle(withdrawal.party.id)}
-
{t('toEthereum')}
@@ -226,27 +166,23 @@ export const Withdrawal = ({
- {t('Signature')}
-
- {!erc20Approval?.signatures
- ? t('Loading')
- : truncateMiddle(erc20Approval.signatures)}
+ {t('withdrawalTransaction', { foreignChain: 'Ethereum' })}
+
+ {withdrawal.txHash ? (
+
+ ) : (
+ '-'
+ )}
+
+ {t('status')}
+ {renderStatus(withdrawal)}
+
-
);
};
diff --git a/apps/trading-e2e/src/integration/markets-page.feature b/apps/trading-e2e/src/integration/markets-page.feature
index 81698cba6..e9fb1886a 100644
--- a/apps/trading-e2e/src/integration/markets-page.feature
+++ b/apps/trading-e2e/src/integration/markets-page.feature
@@ -8,10 +8,12 @@ Feature: Markets page
Scenario: Select active market
Given I am on the markets page
+ And I can view markets
When I click on "Active" mocked market
Then trading page for "active" market is displayed
Scenario: Select suspended market
Given I am on the markets page
+ And I can view markets
When I click on "Suspended" mocked market
Then trading page for "suspended" market is displayed
diff --git a/apps/trading-e2e/src/support/pages/markets-page.ts b/apps/trading-e2e/src/support/pages/markets-page.ts
index 28cd5c782..7d16abd0f 100644
--- a/apps/trading-e2e/src/support/pages/markets-page.ts
+++ b/apps/trading-e2e/src/support/pages/markets-page.ts
@@ -10,6 +10,9 @@ export default class MarketPage extends BasePage {
marketStateColId = 'data';
validateMarketsAreDisplayed() {
+ // We need this to ensure that ag-grid is fully rendered before asserting
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(1000);
cy.get('.ag-root-wrapper').should('be.visible');
}
diff --git a/apps/trading-e2e/src/support/step_definitions/markets-page.step.ts b/apps/trading-e2e/src/support/step_definitions/markets-page.step.ts
index 4a70f607f..d46982c5c 100644
--- a/apps/trading-e2e/src/support/step_definitions/markets-page.step.ts
+++ b/apps/trading-e2e/src/support/step_definitions/markets-page.step.ts
@@ -15,21 +15,19 @@ const mockMarkets = () => {
});
};
-beforeEach(() => {
- mockMarkets();
-});
-
Then('I navigate to markets page', () => {
+ mockMarkets();
marketsPage.navigateToMarkets();
+ cy.wait('@Markets');
});
Given('I am on the markets page', () => {
+ mockMarkets();
cy.visit('/markets');
cy.wait('@Markets');
});
Then('I can view markets', () => {
- cy.wait('@Markets');
marketsPage.validateMarketsAreDisplayed();
});
diff --git a/apps/trading/lib/assets.ts b/apps/trading/lib/assets.ts
deleted file mode 100644
index e3d629176..000000000
--- a/apps/trading/lib/assets.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { AssetFields } from './__generated__/AssetFields';
-
-export interface ERC20Asset extends AssetFields {
- source: {
- __typename: 'ERC20';
- contractAddress: string;
- };
-}
-
-type UnknownAsset = Pick;
-
-// Type guard to ensure an asset is an ERC20 token
-export const isERC20Asset = (asset: UnknownAsset): asset is ERC20Asset => {
- if (asset.source.__typename === 'ERC20') {
- return true;
- }
- return false;
-};
diff --git a/apps/trading/pages/portfolio/deposit/deposit-container.tsx b/apps/trading/pages/portfolio/deposit/deposit-container.tsx
index 3526644e9..feea5b361 100644
--- a/apps/trading/pages/portfolio/deposit/deposit-container.tsx
+++ b/apps/trading/pages/portfolio/deposit/deposit-container.tsx
@@ -6,7 +6,6 @@ import { DepositManager } from '@vegaprotocol/deposits';
import { t } from '@vegaprotocol/react-helpers';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { ASSET_FRAGMENT } from '../../../lib/query-fragments';
-import { isERC20Asset } from '../../../lib/assets';
const DEPOSIT_PAGE_QUERY = gql`
${ASSET_FRAGMENT}
@@ -45,7 +44,7 @@ export const DepositContainer = ({
);
diff --git a/apps/trading/pages/portfolio/withdraw/withdraw-page-container.tsx b/apps/trading/pages/portfolio/withdraw/withdraw-page-container.tsx
index cb7901c27..aaf61156a 100644
--- a/apps/trading/pages/portfolio/withdraw/withdraw-page-container.tsx
+++ b/apps/trading/pages/portfolio/withdraw/withdraw-page-container.tsx
@@ -6,7 +6,6 @@ import { WithdrawManager } from '@vegaprotocol/withdraws';
import { ASSET_FRAGMENT } from '../../../lib/query-fragments';
import Link from 'next/link';
import { PageQueryContainer } from '../../../components/page-query-container';
-import { isERC20Asset } from '../../../lib/assets';
import type {
WithdrawPageQuery,
WithdrawPageQueryVariables,
@@ -85,7 +84,7 @@ export const WithdrawPageContainer = ({
) : null}
diff --git a/libs/deposits/src/lib/deposit-form.tsx b/libs/deposits/src/lib/deposit-form.tsx
index 9624b7ab9..1b888cd4f 100644
--- a/libs/deposits/src/lib/deposit-form.tsx
+++ b/libs/deposits/src/lib/deposit-form.tsx
@@ -82,8 +82,8 @@ export const DepositForm = ({
});
const onDeposit = async (fields: FormFields) => {
- if (!selectedAsset) {
- throw new Error('Asset not selected');
+ if (!selectedAsset || selectedAsset.source.__typename !== 'ERC20') {
+ throw new Error('Invalid asset');
}
submitDeposit({
@@ -153,11 +153,13 @@ export const DepositForm = ({
{errors.asset?.message && (
diff --git a/libs/deposits/src/lib/deposit-manager.tsx b/libs/deposits/src/lib/deposit-manager.tsx
index 462466fff..36858ccfb 100644
--- a/libs/deposits/src/lib/deposit-manager.tsx
+++ b/libs/deposits/src/lib/deposit-manager.tsx
@@ -10,16 +10,23 @@ import { useSubmitFaucet } from './use-submit-faucet';
import { EthTxStatus, TransactionDialog } from '@vegaprotocol/web3';
import { useTokenContract, useBridgeContract } from '@vegaprotocol/web3';
+interface ERC20AssetSource {
+ __typename: 'ERC20';
+ contractAddress: string;
+}
+
+interface BuiltinAssetSource {
+ __typename: 'BuiltinAsset';
+}
+
+type AssetSource = ERC20AssetSource | BuiltinAssetSource;
export interface Asset {
__typename: 'Asset';
id: string;
symbol: string;
name: string;
decimals: number;
- source: {
- __typename: 'ERC20';
- contractAddress: string;
- };
+ source: AssetSource;
}
interface DepositManagerProps {
@@ -44,7 +51,9 @@ export const DepositManager = ({
}, [assets, assetId]);
const tokenContract = useTokenContract(
- asset?.source.contractAddress,
+ asset?.source.__typename === 'ERC20'
+ ? asset.source.contractAddress
+ : undefined,
process.env['NX_VEGA_ENV'] !== 'MAINNET'
);
const bridgeContract = useBridgeContract();
diff --git a/libs/deposits/src/lib/use-get-deposit-limits.ts b/libs/deposits/src/lib/use-get-deposit-limits.ts
index d36943876..eb743896f 100644
--- a/libs/deposits/src/lib/use-get-deposit-limits.ts
+++ b/libs/deposits/src/lib/use-get-deposit-limits.ts
@@ -14,7 +14,7 @@ export const useGetDepositLimits = (
asset?: Asset
): Limits | null => {
const getLimits = useCallback(async () => {
- if (!contract || !asset) {
+ if (!contract || !asset || asset.source.__typename !== 'ERC20') {
return;
}
diff --git a/libs/react-helpers/src/lib/determine-id.ts b/libs/react-helpers/src/lib/determine-id.ts
index ba2861fe6..23e4e2d60 100644
--- a/libs/react-helpers/src/lib/determine-id.ts
+++ b/libs/react-helpers/src/lib/determine-id.ts
@@ -1,23 +1,10 @@
import { ethers } from 'ethers';
-import { SHA3 } from 'sha3';
-import { remove0x } from './remove-0x';
+import { sha3_256 } from 'js-sha3';
/**
* This function creates an ID in the same way that core does on the backend. This way we
* Can match up the newly created order with incoming orders via a subscription
*/
export const determineId = (sig: string) => {
- // Prepend 0x
- if (sig.slice(0, 2) !== '0x') {
- sig = '0x' + sig;
- }
-
- // Create the ID
- const hash = new SHA3(256);
- const bytes = ethers.utils.arrayify(sig);
- hash.update(Buffer.from(bytes));
- const id = ethers.utils.hexlify(hash.digest());
-
- // Remove 0x as core doesn't keep them in the API
- return remove0x(id);
+ return sha3_256(ethers.utils.arrayify('0x' + sig));
};
diff --git a/libs/wallet/src/connectors/index.ts b/libs/wallet/src/connectors/index.ts
index dcc534768..c23e90638 100644
--- a/libs/wallet/src/connectors/index.ts
+++ b/libs/wallet/src/connectors/index.ts
@@ -1,9 +1,8 @@
import type {
VegaKey,
TransactionResponse,
- OrderSubmissionBody,
- WithdrawSubmissionBody,
} from '@vegaprotocol/vegawallet-service-api-client';
+import type { TransactionSubmission } from '../types';
export { RestConnector } from './rest-connector';
type ErrorResponse =
@@ -26,6 +25,6 @@ export interface VegaConnector {
/** Send a TX to the network. Only support order submission for now */
sendTx: (
- body: OrderSubmissionBody | WithdrawSubmissionBody
+ body: TransactionSubmission
) => Promise;
}
diff --git a/libs/wallet/src/connectors/rest-connector.ts b/libs/wallet/src/connectors/rest-connector.ts
index 75d19591a..2dfe240f3 100644
--- a/libs/wallet/src/connectors/rest-connector.ts
+++ b/libs/wallet/src/connectors/rest-connector.ts
@@ -1,8 +1,4 @@
-import type {
- Configuration,
- OrderSubmissionBody,
- WithdrawSubmissionBody,
-} from '@vegaprotocol/vegawallet-service-api-client';
+import type { Configuration } from '@vegaprotocol/vegawallet-service-api-client';
import {
createConfiguration,
DefaultApi,
@@ -10,6 +6,7 @@ import {
import { LocalStorage } from '@vegaprotocol/react-helpers';
import { WALLET_CONFIG } from '../storage-keys';
import type { VegaConnector } from '.';
+import type { TransactionSubmission } from '../types';
// Perhaps there should be a default ConnectorConfig that others can extend off. Do all connectors
// need to use local storage, I don't think so...
@@ -88,7 +85,7 @@ export class RestConnector implements VegaConnector {
}
}
- async sendTx(body: OrderSubmissionBody | WithdrawSubmissionBody) {
+ async sendTx(body: TransactionSubmission) {
try {
return await this.service.commandSyncPost(body);
} catch (err) {
diff --git a/libs/wallet/src/provider.tsx b/libs/wallet/src/provider.tsx
index d45b0e0b4..7428cbe63 100644
--- a/libs/wallet/src/provider.tsx
+++ b/libs/wallet/src/provider.tsx
@@ -5,10 +5,7 @@ import type { VegaKeyExtended, VegaWalletContextShape } from '.';
import type { VegaConnector } from './connectors';
import { VegaWalletContext } from './context';
import { WALLET_KEY } from './storage-keys';
-import type {
- OrderSubmissionBody,
- WithdrawSubmissionBody,
-} from '@vegaprotocol/vegawallet-service-api-client';
+import type { TransactionSubmission } from './types';
interface VegaWalletProviderProps {
children: ReactNode;
@@ -72,16 +69,13 @@ export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => {
}
}, []);
- const sendTx = useCallback(
- (body: OrderSubmissionBody | WithdrawSubmissionBody) => {
- if (!connector.current) {
- return null;
- }
+ const sendTx = useCallback((body: TransactionSubmission) => {
+ if (!connector.current) {
+ return null;
+ }
- return connector.current.sendTx(body);
- },
- []
- );
+ return connector.current.sendTx(body);
+ }, []);
// Current selected keypair derived from publicKey state
const keypair = useMemo(() => {
diff --git a/libs/wallet/src/types.ts b/libs/wallet/src/types.ts
index 5430c6632..c4e85c95d 100644
--- a/libs/wallet/src/types.ts
+++ b/libs/wallet/src/types.ts
@@ -1,5 +1,8 @@
import type {
+ DelegateSubmissionBody,
OrderSubmissionBody,
+ UndelegateSubmissionBody,
+ VoteSubmissionBody,
WithdrawSubmissionBody,
} from '@vegaprotocol/vegawallet-service-api-client';
@@ -25,4 +28,7 @@ export enum OrderTimeInForce {
// Will make Transaction a union type as other transactions are added
export type TransactionSubmission =
| OrderSubmissionBody
- | WithdrawSubmissionBody;
+ | WithdrawSubmissionBody
+ | VoteSubmissionBody
+ | DelegateSubmissionBody
+ | UndelegateSubmissionBody;
diff --git a/libs/withdraws/src/index.ts b/libs/withdraws/src/index.ts
index 0f76390cd..41cbea1fe 100644
--- a/libs/withdraws/src/index.ts
+++ b/libs/withdraws/src/index.ts
@@ -4,3 +4,4 @@ export * from './lib/withdrawals-table';
export * from './lib/use-complete-withdraw';
export * from './lib/use-withdraw';
export * from './lib/use-withdrawals';
+export * from './lib/__generated__/Withdrawals';
diff --git a/libs/withdraws/src/lib/test-helpers.ts b/libs/withdraws/src/lib/test-helpers.ts
index 320f4ab1e..afd650b86 100644
--- a/libs/withdraws/src/lib/test-helpers.ts
+++ b/libs/withdraws/src/lib/test-helpers.ts
@@ -11,6 +11,7 @@ export const generateAsset = (override?: PartialDeep) => {
name: 'asset-name',
decimals: 5,
source: {
+ __typename: 'ERC20',
contractAddress: 'contract-address',
},
};
diff --git a/libs/withdraws/src/lib/types.ts b/libs/withdraws/src/lib/types.ts
index b3a14d3e6..27a95ab91 100644
--- a/libs/withdraws/src/lib/types.ts
+++ b/libs/withdraws/src/lib/types.ts
@@ -1,13 +1,22 @@
import type { AccountType } from '@vegaprotocol/types';
+interface ERC20AssetSource {
+ __typename: 'ERC20';
+ contractAddress: string;
+}
+
+interface BuiltinAssetSource {
+ __typename: 'BuiltinAsset';
+}
+
+type AssetSource = ERC20AssetSource | BuiltinAssetSource;
+
export interface Asset {
id: string;
symbol: string;
name: string;
decimals: number;
- source: {
- contractAddress: string;
- };
+ source: AssetSource;
}
export interface Account {
diff --git a/libs/withdraws/src/lib/withdraw-form.tsx b/libs/withdraws/src/lib/withdraw-form.tsx
index adad298f2..8bea38b0a 100644
--- a/libs/withdraws/src/lib/withdraw-form.tsx
+++ b/libs/withdraws/src/lib/withdraw-form.tsx
@@ -90,11 +90,13 @@ export const WithdrawForm = ({
id="asset"
>
- {assets.map((a) => (
-
- ))}
+ {assets
+ .filter((a) => a.source.__typename === 'ERC20')
+ .map((a) => (
+
+ ))}
)}
/>
diff --git a/package.json b/package.json
index d2b383912..0062653b3 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,7 @@
"@sentry/react": "^6.19.2",
"@sentry/tracing": "^6.19.2",
"@vegaprotocol/smart-contracts-sdk": "^1.6.0",
- "@vegaprotocol/vegawallet-service-api-client": "^0.4.9",
+ "@vegaprotocol/vegawallet-service-api-client": "^0.4.11",
"@walletconnect/ethereum-provider": "^1.7.5",
"@web3-react/core": "8.0.20-beta.0",
"@web3-react/metamask": "8.0.16-beta.0",
@@ -52,6 +52,7 @@
"i18next": "^20.3.5",
"i18next-browser-languagedetector": "^6.1.2",
"immer": "^9.0.12",
+ "js-sha3": "^0.8.0",
"lodash": "^4.17.21",
"next": "^12.0.7",
"pennant": "0.4.8",
@@ -69,7 +70,6 @@
"react-window-infinite-loader": "^1.0.7",
"recharts": "^2.1.2",
"regenerator-runtime": "0.13.7",
- "sha3": "^2.1.4",
"tailwindcss": "^3.0.23",
"tslib": "^2.0.0",
"uuid": "^8.3.2",
diff --git a/yarn.lock b/yarn.lock
index ef251676b..1bc5077b3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6205,10 +6205,10 @@
ethers "^5.5.2"
lodash "^4.17.21"
-"@vegaprotocol/vegawallet-service-api-client@^0.4.9":
- version "0.4.9"
- resolved "https://registry.yarnpkg.com/@vegaprotocol/vegawallet-service-api-client/-/vegawallet-service-api-client-0.4.9.tgz#9c2566407e9c86248f2c170b1f495afdcb347d87"
- integrity sha512-zqppuVu3VrsHpdcNBvu6G+qMMt0CBXi5wHBb/0ryiXdXD9dmQci5Qz8zoGx5syOupFMdUDNstmGOaFWbBOuvbg==
+"@vegaprotocol/vegawallet-service-api-client@^0.4.11":
+ version "0.4.11"
+ resolved "https://registry.yarnpkg.com/@vegaprotocol/vegawallet-service-api-client/-/vegawallet-service-api-client-0.4.11.tgz#41a623afc9957dcf8b5425f74280ba7861e92b74"
+ integrity sha512-yiodc3YFWG+RGG+wjpTjYmNAECP/Nv244mVu8IGVtj8LZo02KC/LpNCgmMhGaK4ZcqVtxHv9t7OUCSEWZhSgOg==
dependencies:
es6-promise "^4.2.4"
url-parse "^1.4.3"
@@ -8438,14 +8438,6 @@ buffer@5.6.0:
base64-js "^1.0.2"
ieee754 "^1.1.4"
-buffer@6.0.3:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
- integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
- dependencies:
- base64-js "^1.3.1"
- ieee754 "^1.2.1"
-
buffer@^4.3.0:
version "4.9.2"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
@@ -13304,7 +13296,7 @@ identity-obj-proxy@3.0.0:
dependencies:
harmony-reflect "^1.4.6"
-ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1:
+ieee754@^1.1.13, ieee754@^1.1.4:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@@ -14693,7 +14685,7 @@ jest@27.2.3:
import-local "^3.0.2"
jest-cli "^27.2.3"
-js-sha3@0.8.0:
+js-sha3@0.8.0, js-sha3@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
@@ -19310,13 +19302,6 @@ sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8, sha.js@~2.4.4:
inherits "^2.0.1"
safe-buffer "^5.0.1"
-sha3@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/sha3/-/sha3-2.1.4.tgz#000fac0fe7c2feac1f48a25e7a31b52a6492cc8f"
- integrity sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg==
- dependencies:
- buffer "6.0.3"
-
shallow-clone@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"