Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6c048e2e2 | ||
|
|
86227a43eb | ||
|
|
ad058d8b5f | ||
|
|
1aaf97478b |
+1
-1
@@ -37,7 +37,7 @@
|
|||||||
"@cosmjs/proto-signing": "^0.31.0",
|
"@cosmjs/proto-signing": "^0.31.0",
|
||||||
"@cosmjs/stargate": "^0.31.0",
|
"@cosmjs/stargate": "^0.31.0",
|
||||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||||
"@dydxprotocol/v4-abacus": "^0.5.0",
|
"@dydxprotocol/v4-abacus": "^0.5.4",
|
||||||
"@dydxprotocol/v4-client-js": "^0.36.1",
|
"@dydxprotocol/v4-client-js": "^0.36.1",
|
||||||
"@dydxprotocol/v4-localization": "^0.1.11",
|
"@dydxprotocol/v4-localization": "^0.1.11",
|
||||||
"@ethersproject/providers": "^5.7.2",
|
"@ethersproject/providers": "^5.7.2",
|
||||||
|
|||||||
Generated
+4
-4
@@ -27,8 +27,8 @@ dependencies:
|
|||||||
specifier: ^0.31.0
|
specifier: ^0.31.0
|
||||||
version: 0.31.0
|
version: 0.31.0
|
||||||
'@dydxprotocol/v4-abacus':
|
'@dydxprotocol/v4-abacus':
|
||||||
specifier: ^0.5.0
|
specifier: ^0.5.4
|
||||||
version: 0.5.0
|
version: 0.5.4
|
||||||
'@dydxprotocol/v4-client-js':
|
'@dydxprotocol/v4-client-js':
|
||||||
specifier: ^0.36.1
|
specifier: ^0.36.1
|
||||||
version: 0.36.1
|
version: 0.36.1
|
||||||
@@ -979,8 +979,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@dydxprotocol/v4-abacus@0.5.0:
|
/@dydxprotocol/v4-abacus@0.5.4:
|
||||||
resolution: {integrity: sha512-K/aLJeOWzmToCn6p9vjBqfwn79/nuKxjZLSzaj1mKNxw25KBFh2q93njNbONFRA72zBElD0K+gw8J/skTpGg1Q==}
|
resolution: {integrity: sha512-LMwmyXCih2bBdLX3vO5OwbdGWg3oZ8WSGj+4nqr8tn/bn1qCSKdYdZZ9/U20Yir2rMAcoC0jmznMcBwthlSp/w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-client-js@0.36.1:
|
/@dydxprotocol/v4-client-js@0.36.1:
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ export const InputSelectionOption = Abacus.exchange.dydx.abacus.output.input.Sel
|
|||||||
|
|
||||||
// ------ Wallet ------ //
|
// ------ Wallet ------ //
|
||||||
export type Wallet = Abacus.exchange.dydx.abacus.output.Wallet;
|
export type Wallet = Abacus.exchange.dydx.abacus.output.Wallet;
|
||||||
|
export type AccountBalance = Abacus.exchange.dydx.abacus.output.AccountBalance;
|
||||||
export type Subaccount = Abacus.exchange.dydx.abacus.output.Subaccount;
|
export type Subaccount = Abacus.exchange.dydx.abacus.output.Subaccount;
|
||||||
export type SubaccountPosition = Abacus.exchange.dydx.abacus.output.SubaccountPosition;
|
export type SubaccountPosition = Abacus.exchange.dydx.abacus.output.SubaccountPosition;
|
||||||
export type SubaccountOrder = Abacus.exchange.dydx.abacus.output.SubaccountOrder;
|
export type SubaccountOrder = Abacus.exchange.dydx.abacus.output.SubaccountOrder;
|
||||||
@@ -188,6 +189,10 @@ export type HumanReadablePlaceOrderPayload =
|
|||||||
Abacus.exchange.dydx.abacus.state.manager.HumanReadablePlaceOrderPayload;
|
Abacus.exchange.dydx.abacus.state.manager.HumanReadablePlaceOrderPayload;
|
||||||
export type HumanReadableCancelOrderPayload =
|
export type HumanReadableCancelOrderPayload =
|
||||||
Abacus.exchange.dydx.abacus.state.manager.HumanReadableCancelOrderPayload;
|
Abacus.exchange.dydx.abacus.state.manager.HumanReadableCancelOrderPayload;
|
||||||
|
export type HumanReadableWithdrawPayload =
|
||||||
|
Abacus.exchange.dydx.abacus.state.manager.HumanReadableWithdrawPayload;
|
||||||
|
export type HumanReadableTransferPayload =
|
||||||
|
Abacus.exchange.dydx.abacus.state.manager.HumanReadableTransferPayload;
|
||||||
|
|
||||||
// ------ Helpers ------ //
|
// ------ Helpers ------ //
|
||||||
export const AbacusHelper = Abacus.exchange.dydx.abacus.utils.AbacusHelper;
|
export const AbacusHelper = Abacus.exchange.dydx.abacus.utils.AbacusHelper;
|
||||||
|
|||||||
@@ -383,12 +383,18 @@ export const DYDX_CHAIN_INFO: Parameters<typeof suggestChain>[0] = {
|
|||||||
features: [],
|
features: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: export this type from abacus instead
|
||||||
export enum DydxChainAsset {
|
export enum DydxChainAsset {
|
||||||
USDC = 'USDC',
|
USDC = 'usdc',
|
||||||
DYDX = 'Dv4TNT',
|
DYDX = 'dydx',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DYDX_CHAIN_ASSET_COIN_DENOM: Record<DydxChainAsset, string> = {
|
export const DYDX_CHAIN_ASSET_COIN_DENOM: Record<DydxChainAsset, string> = {
|
||||||
[DydxChainAsset.USDC]: USDC_DENOM,
|
[DydxChainAsset.USDC]: USDC_DENOM,
|
||||||
[DydxChainAsset.DYDX]: DYDX_DENOM,
|
[DydxChainAsset.DYDX]: DYDX_DENOM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DYDX_CHAIN_ASSET_TAGS: Record<DydxChainAsset, string> = {
|
||||||
|
[DydxChainAsset.USDC]: 'USDC',
|
||||||
|
[DydxChainAsset.DYDX]: 'Dv4TNT',
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { shallowEqual, useSelector } from 'react-redux';
|
||||||
import { useBalance } from 'wagmi';
|
import { useBalance } from 'wagmi';
|
||||||
import { StargateClient } from '@cosmjs/stargate';
|
import { StargateClient } from '@cosmjs/stargate';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { formatUnits } from 'viem';
|
import { formatUnits } from 'viem';
|
||||||
|
|
||||||
|
import { USDC_DENOM, DYDX_DENOM } from '@dydxprotocol/v4-client-js';
|
||||||
|
|
||||||
import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks';
|
import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks';
|
||||||
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||||
import { EvmAddress } from '@/constants/wallets';
|
import { EvmAddress } from '@/constants/wallets';
|
||||||
@@ -12,11 +14,10 @@ import { EvmAddress } from '@/constants/wallets';
|
|||||||
import { convertBech32Address } from '@/lib/addressUtils';
|
import { convertBech32Address } from '@/lib/addressUtils';
|
||||||
import { MustBigNumber } from '@/lib/numbers';
|
import { MustBigNumber } from '@/lib/numbers';
|
||||||
|
|
||||||
|
import { getBalances } from '@/state/accountSelectors';
|
||||||
import { getSelectedNetwork } from '@/state/appSelectors';
|
import { getSelectedNetwork } from '@/state/appSelectors';
|
||||||
|
|
||||||
import { useAccounts } from './useAccounts';
|
import { useAccounts } from './useAccounts';
|
||||||
import { usePollNativeTokenBalance } from './usePollNativeTokenBalance';
|
|
||||||
import { usePollUSDCBalance } from './usePollUSDCBalance';
|
|
||||||
|
|
||||||
type UseAccountBalanceProps = {
|
type UseAccountBalanceProps = {
|
||||||
// Token Items
|
// Token Items
|
||||||
@@ -50,6 +51,7 @@ export const useAccountBalance = ({
|
|||||||
const { evmAddress, dydxAddress } = useAccounts();
|
const { evmAddress, dydxAddress } = useAccounts();
|
||||||
|
|
||||||
const selectedNetwork = useSelector(getSelectedNetwork);
|
const selectedNetwork = useSelector(getSelectedNetwork);
|
||||||
|
const balances = useSelector(getBalances, shallowEqual);
|
||||||
const evmChainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork].ethereumChainId);
|
const evmChainId = Number(CLIENT_NETWORK_CONFIGS[selectedNetwork].ethereumChainId);
|
||||||
|
|
||||||
const evmQuery = useBalance({
|
const evmQuery = useBalance({
|
||||||
@@ -92,12 +94,12 @@ export const useAccountBalance = ({
|
|||||||
const { formatted: evmBalance } = evmQuery.data || {};
|
const { formatted: evmBalance } = evmQuery.data || {};
|
||||||
const balance = !assetSymbol ? '0' : isCosmosChain ? cosmosQuery.data : evmBalance;
|
const balance = !assetSymbol ? '0' : isCosmosChain ? cosmosQuery.data : evmBalance;
|
||||||
|
|
||||||
const nativeTokenCoinBalance = usePollNativeTokenBalance({ dydxAddress });
|
const nativeTokenCoinBalance = balances?.[DYDX_DENOM];
|
||||||
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount)
|
const nativeTokenBalance = MustBigNumber(nativeTokenCoinBalance?.amount)
|
||||||
.div(QUANTUM_MULTIPLIER)
|
.div(QUANTUM_MULTIPLIER)
|
||||||
.toNumber();
|
.toNumber();
|
||||||
|
|
||||||
const usdcCoinBalance = usePollUSDCBalance({ dydxAddress });
|
const usdcCoinBalance = balances?.[USDC_DENOM];
|
||||||
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).div(QUANTUM_MULTIPLIER).toNumber();
|
const usdcBalance = MustBigNumber(usdcCoinBalance?.amount).div(QUANTUM_MULTIPLIER).toNumber();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
import { useQuery } from 'react-query';
|
|
||||||
|
|
||||||
import { useAccounts } from '@/hooks';
|
|
||||||
|
|
||||||
import { DydxAddress } from '@/constants/wallets';
|
|
||||||
import { DYDX_DENOM } from '@dydxprotocol/v4-client-js';
|
|
||||||
|
|
||||||
const ACCOUNT_BALANCE_POLLING_INTERVAL = 60_000;
|
|
||||||
|
|
||||||
export const usePollNativeTokenBalance = ({
|
|
||||||
dydxAddress,
|
|
||||||
interval = ACCOUNT_BALANCE_POLLING_INTERVAL,
|
|
||||||
}: {
|
|
||||||
dydxAddress?: DydxAddress;
|
|
||||||
interval?: number;
|
|
||||||
}) => {
|
|
||||||
const { getAccountBalance } = useAccounts();
|
|
||||||
|
|
||||||
const { data } = useQuery({
|
|
||||||
enabled: dydxAddress !== undefined,
|
|
||||||
queryKey: ['usePollNativeTokenBalance', { dydxAddress }],
|
|
||||||
queryFn: async () => {
|
|
||||||
if (!dydxAddress) return;
|
|
||||||
return await getAccountBalance({ dydxAddress, denom: DYDX_DENOM });
|
|
||||||
},
|
|
||||||
refetchInterval: interval,
|
|
||||||
staleTime: interval,
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import { useQuery } from 'react-query';
|
|
||||||
|
|
||||||
import { useAccounts } from '@/hooks';
|
|
||||||
|
|
||||||
import { DydxAddress } from '@/constants/wallets';
|
|
||||||
|
|
||||||
const ACCOUNT_BALANCE_POLLING_INTERVAL = 60_000;
|
|
||||||
|
|
||||||
export const usePollUSDCBalance = ({
|
|
||||||
dydxAddress,
|
|
||||||
interval = ACCOUNT_BALANCE_POLLING_INTERVAL,
|
|
||||||
}: {
|
|
||||||
dydxAddress?: DydxAddress;
|
|
||||||
interval?: number;
|
|
||||||
}) => {
|
|
||||||
const { getAccountBalance } = useAccounts();
|
|
||||||
|
|
||||||
const { data } = useQuery({
|
|
||||||
enabled: dydxAddress !== undefined,
|
|
||||||
queryKey: ['usePollUSDCBalance', { dydxAddress }],
|
|
||||||
queryFn: async () => {
|
|
||||||
if (!dydxAddress) return;
|
|
||||||
return await getAccountBalance({ dydxAddress });
|
|
||||||
},
|
|
||||||
refetchInterval: interval,
|
|
||||||
staleTime: interval,
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
+12
-86
@@ -1,5 +1,5 @@
|
|||||||
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { shallowEqual, useSelector, useDispatch } from 'react-redux';
|
||||||
import type { Nullable } from '@dydxprotocol/v4-abacus';
|
import type { Nullable } from '@dydxprotocol/v4-abacus';
|
||||||
import Long from 'long';
|
import Long from 'long';
|
||||||
import type { IndexedTx } from '@cosmjs/stargate';
|
import type { IndexedTx } from '@cosmjs/stargate';
|
||||||
@@ -11,10 +11,10 @@ import {
|
|||||||
SubaccountClient,
|
SubaccountClient,
|
||||||
DYDX_DENOM,
|
DYDX_DENOM,
|
||||||
USDC_DENOM,
|
USDC_DENOM,
|
||||||
GAS_PRICE_DYDX_DENOM,
|
|
||||||
} from '@dydxprotocol/v4-client-js';
|
} from '@dydxprotocol/v4-client-js';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
AccountBalance,
|
||||||
HumanReadablePlaceOrderPayload,
|
HumanReadablePlaceOrderPayload,
|
||||||
ParsingError,
|
ParsingError,
|
||||||
SubAccountHistoricalPNLs,
|
SubAccountHistoricalPNLs,
|
||||||
@@ -26,6 +26,7 @@ import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
|||||||
import { DydxAddress } from '@/constants/wallets';
|
import { DydxAddress } from '@/constants/wallets';
|
||||||
|
|
||||||
import { setSubaccount, setHistoricalPnl, removeUncommittedOrderClientId } from '@/state/account';
|
import { setSubaccount, setHistoricalPnl, removeUncommittedOrderClientId } from '@/state/account';
|
||||||
|
import { getBalances } from '@/state/accountSelectors';
|
||||||
|
|
||||||
import abacusStateManager from '@/lib/abacus';
|
import abacusStateManager from '@/lib/abacus';
|
||||||
import { track } from '@/lib/analytics';
|
import { track } from '@/lib/analytics';
|
||||||
@@ -34,7 +35,7 @@ import { log } from '@/lib/telemetry';
|
|||||||
|
|
||||||
import { useAccounts } from './useAccounts';
|
import { useAccounts } from './useAccounts';
|
||||||
import { useDydxClient } from './useDydxClient';
|
import { useDydxClient } from './useDydxClient';
|
||||||
import { usePollUSDCBalance } from './usePollUSDCBalance';
|
|
||||||
|
|
||||||
type SubaccountContextType = ReturnType<typeof useSubaccountContext>;
|
type SubaccountContextType = ReturnType<typeof useSubaccountContext>;
|
||||||
const SubaccountContext = createContext<SubaccountContextType>({} as SubaccountContextType);
|
const SubaccountContext = createContext<SubaccountContextType>({} as SubaccountContextType);
|
||||||
@@ -70,10 +71,8 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
const {
|
const {
|
||||||
depositToSubaccount,
|
depositToSubaccount,
|
||||||
withdrawFromSubaccount,
|
withdrawFromSubaccount,
|
||||||
simulateWithdrawFromSubaccount,
|
|
||||||
transferFromSubaccountToAddress,
|
transferFromSubaccountToAddress,
|
||||||
transferNativeToken,
|
transferNativeToken,
|
||||||
simulateTransferNativeToken,
|
|
||||||
sendSquidWithdrawFromSubaccount,
|
sendSquidWithdrawFromSubaccount,
|
||||||
} = useMemo(
|
} = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@@ -95,31 +94,6 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
amount: number;
|
amount: number;
|
||||||
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount),
|
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount),
|
||||||
|
|
||||||
simulateWithdrawFromSubaccount: async ({
|
|
||||||
subaccountClient,
|
|
||||||
amount,
|
|
||||||
recipient,
|
|
||||||
}: {
|
|
||||||
subaccountClient: SubaccountClient;
|
|
||||||
amount: number;
|
|
||||||
recipient?: string;
|
|
||||||
}) => {
|
|
||||||
return await compositeClient?.simulate(
|
|
||||||
subaccountClient?.wallet,
|
|
||||||
() =>
|
|
||||||
new Promise((resolve) => {
|
|
||||||
const msg = compositeClient?.withdrawFromSubaccountMessage(
|
|
||||||
subaccountClient,
|
|
||||||
amount,
|
|
||||||
recipient
|
|
||||||
);
|
|
||||||
|
|
||||||
resolve([msg]);
|
|
||||||
}),
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
transferFromSubaccountToAddress: async ({
|
transferFromSubaccountToAddress: async ({
|
||||||
subaccountClient,
|
subaccountClient,
|
||||||
assetId = 0,
|
assetId = 0,
|
||||||
@@ -170,31 +144,6 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
Method.BroadcastTxCommit
|
Method.BroadcastTxCommit
|
||||||
),
|
),
|
||||||
|
|
||||||
simulateTransferNativeToken: async ({
|
|
||||||
subaccountClient,
|
|
||||||
amount,
|
|
||||||
recipient,
|
|
||||||
}: {
|
|
||||||
subaccountClient: SubaccountClient;
|
|
||||||
amount: number;
|
|
||||||
recipient: string;
|
|
||||||
}) =>
|
|
||||||
await compositeClient?.simulate(
|
|
||||||
subaccountClient?.wallet,
|
|
||||||
() =>
|
|
||||||
new Promise((resolve) => {
|
|
||||||
const msg = compositeClient?.validatorClient.post.composer.composeMsgSendToken(
|
|
||||||
subaccountClient.address,
|
|
||||||
recipient,
|
|
||||||
DYDX_DENOM,
|
|
||||||
Long.fromNumber(amount * QUANTUM_MULTIPLIER)
|
|
||||||
);
|
|
||||||
|
|
||||||
resolve([msg]);
|
|
||||||
}),
|
|
||||||
GAS_PRICE_DYDX_DENOM,
|
|
||||||
undefined
|
|
||||||
),
|
|
||||||
sendSquidWithdrawFromSubaccount: async ({
|
sendSquidWithdrawFromSubaccount: async ({
|
||||||
subaccountClient,
|
subaccountClient,
|
||||||
amount,
|
amount,
|
||||||
@@ -244,10 +193,10 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
|
|
||||||
// ------ Deposit/Withdraw Methods ------ //
|
// ------ Deposit/Withdraw Methods ------ //
|
||||||
const depositFunds = useCallback(
|
const depositFunds = useCallback(
|
||||||
async (balance?: Coin) => {
|
async (balance: AccountBalance) => {
|
||||||
if (!localDydxWallet) return;
|
if (!localDydxWallet) return;
|
||||||
|
|
||||||
const amountAfterDust = MustBigNumber(balance?.amount)
|
const amountAfterDust = MustBigNumber(balance.amount)
|
||||||
.minus(AMOUNT_RESERVED_FOR_GAS_USDC) // keep 0.1 USDC in user's wallet for gas
|
.minus(AMOUNT_RESERVED_FOR_GAS_USDC) // keep 0.1 USDC in user's wallet for gas
|
||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
@@ -261,11 +210,14 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
[localDydxWallet, depositToSubaccount]
|
[localDydxWallet, depositToSubaccount]
|
||||||
);
|
);
|
||||||
|
|
||||||
const balance = usePollUSDCBalance({ dydxAddress });
|
const balances = useSelector(getBalances, shallowEqual);
|
||||||
|
const usdcCoinBalance = balances?.[USDC_DENOM];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
depositFunds(balance);
|
if (usdcCoinBalance) {
|
||||||
}, [balance]);
|
depositFunds(usdcCoinBalance);
|
||||||
|
}
|
||||||
|
}, [usdcCoinBalance]);
|
||||||
|
|
||||||
const deposit = useCallback(
|
const deposit = useCallback(
|
||||||
async (amount: Long) => {
|
async (amount: Long) => {
|
||||||
@@ -304,30 +256,6 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
[subaccountClient, transferFromSubaccountToAddress, transferNativeToken]
|
[subaccountClient, transferFromSubaccountToAddress, transferNativeToken]
|
||||||
);
|
);
|
||||||
|
|
||||||
const simulateTransfer = useCallback(
|
|
||||||
async (amount: number, recipient: string, coinDenom: string) => {
|
|
||||||
if (!subaccountClient) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await (coinDenom === USDC_DENOM
|
|
||||||
? simulateWithdrawFromSubaccount
|
|
||||||
: simulateTransferNativeToken)({ subaccountClient, amount, recipient });
|
|
||||||
},
|
|
||||||
[subaccountClient, simulateWithdrawFromSubaccount, simulateTransferNativeToken]
|
|
||||||
);
|
|
||||||
|
|
||||||
const simulateWithdraw = useCallback(
|
|
||||||
async (amount: number) => {
|
|
||||||
if (!subaccountClient) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await simulateWithdrawFromSubaccount({ subaccountClient, amount });
|
|
||||||
},
|
|
||||||
[subaccountClient, simulateWithdrawFromSubaccount]
|
|
||||||
);
|
|
||||||
|
|
||||||
const sendSquidWithdraw = useCallback(
|
const sendSquidWithdraw = useCallback(
|
||||||
async (amount: number, payload: string) => {
|
async (amount: number, payload: string) => {
|
||||||
if (!subaccountClient) {
|
if (!subaccountClient) {
|
||||||
@@ -437,9 +365,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
requestFaucetFunds,
|
requestFaucetFunds,
|
||||||
|
|
||||||
// Transfer Methods
|
// Transfer Methods
|
||||||
simulateTransfer,
|
|
||||||
transfer,
|
transfer,
|
||||||
simulateWithdraw,
|
|
||||||
sendSquidWithdraw,
|
sendSquidWithdraw,
|
||||||
|
|
||||||
// Trading Methods
|
// Trading Methods
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {
|
|||||||
OrderSide,
|
OrderSide,
|
||||||
OrderTimeInForce,
|
OrderTimeInForce,
|
||||||
OrderExecution,
|
OrderExecution,
|
||||||
|
DYDX_DENOM,
|
||||||
|
GAS_PRICE_DYDX_DENOM,
|
||||||
} from '@dydxprotocol/v4-client-js';
|
} from '@dydxprotocol/v4-client-js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -24,10 +26,13 @@ import {
|
|||||||
type TransactionTypes,
|
type TransactionTypes,
|
||||||
type HumanReadablePlaceOrderPayload,
|
type HumanReadablePlaceOrderPayload,
|
||||||
type HumanReadableCancelOrderPayload,
|
type HumanReadableCancelOrderPayload,
|
||||||
|
type HumanReadableWithdrawPayload,
|
||||||
|
type HumanReadableTransferPayload,
|
||||||
} from '@/constants/abacus';
|
} from '@/constants/abacus';
|
||||||
|
|
||||||
import { DialogTypes } from '@/constants/dialogs';
|
import { DialogTypes } from '@/constants/dialogs';
|
||||||
import { UNCOMMITTED_ORDER_TIMEOUT_MS } from '@/constants/trade';
|
import { UNCOMMITTED_ORDER_TIMEOUT_MS } from '@/constants/trade';
|
||||||
|
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||||
|
|
||||||
import { RootStore } from '@/state/_store';
|
import { RootStore } from '@/state/_store';
|
||||||
import { addUncommittedOrderClientId, removeUncommittedOrderClientId } from '@/state/account';
|
import { addUncommittedOrderClientId, removeUncommittedOrderClientId } from '@/state/account';
|
||||||
@@ -229,6 +234,76 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async simulateWithdrawTransaction(params: HumanReadableWithdrawPayload): Promise<string> {
|
||||||
|
if (!this.compositeClient || !this.localWallet) {
|
||||||
|
throw new Error('Missing compositeClient or localWallet');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { subaccountNumber, amount } = params ?? {};
|
||||||
|
const compositeClient = this.compositeClient;
|
||||||
|
const subaccountClient = new SubaccountClient(this.localWallet, subaccountNumber);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tx = await compositeClient.simulate(
|
||||||
|
this.localWallet,
|
||||||
|
() =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount);
|
||||||
|
|
||||||
|
resolve([msg]);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsedTx = this.parseToPrimitives(tx);
|
||||||
|
|
||||||
|
return JSON.stringify(parsedTx);
|
||||||
|
} catch (error) {
|
||||||
|
log('DydxChainTransactions/simulateWithdrawTransaction', error);
|
||||||
|
|
||||||
|
return JSON.stringify({
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async simulateTransferNativeTokenTransaction(params: HumanReadableTransferPayload): Promise<string> {
|
||||||
|
if (!this.compositeClient || !this.localWallet) {
|
||||||
|
throw new Error('Missing compositeClient or localWallet');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { subaccountNumber, amount, recipient } = params ?? {};
|
||||||
|
const compositeClient = this.compositeClient;
|
||||||
|
const subaccountClient = new SubaccountClient(this.localWallet, subaccountNumber);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tx = await compositeClient.simulate(
|
||||||
|
this.localWallet,
|
||||||
|
() =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
const msg = compositeClient?.validatorClient.post.composer.composeMsgSendToken(
|
||||||
|
subaccountClient.address,
|
||||||
|
recipient,
|
||||||
|
DYDX_DENOM,
|
||||||
|
Long.fromNumber(amount * QUANTUM_MULTIPLIER)
|
||||||
|
);
|
||||||
|
|
||||||
|
resolve([msg]);
|
||||||
|
}),
|
||||||
|
GAS_PRICE_DYDX_DENOM,
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsedTx = this.parseToPrimitives(tx);
|
||||||
|
|
||||||
|
return JSON.stringify(parsedTx);
|
||||||
|
} catch (error) {
|
||||||
|
log('DydxChainTransactions/simulateTransferNativeTokenTransaction', error);
|
||||||
|
|
||||||
|
return JSON.stringify({
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async transaction(
|
async transaction(
|
||||||
type: TransactionTypes,
|
type: TransactionTypes,
|
||||||
paramsInJson: Abacus.Nullable<string>,
|
paramsInJson: Abacus.Nullable<string>,
|
||||||
@@ -248,6 +323,16 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
callback(result);
|
callback(result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TransactionType.simulateWithdraw: {
|
||||||
|
const result = await this.simulateWithdrawTransaction(params);
|
||||||
|
callback(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TransactionType.simulateTransferNativeToken: {
|
||||||
|
const result = await this.simulateTransferNativeTokenTransaction(params);
|
||||||
|
callback(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -310,6 +395,14 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
|||||||
const parsedUserStats = this.parseToPrimitives(userStats);
|
const parsedUserStats = this.parseToPrimitives(userStats);
|
||||||
callback(JSON.stringify(parsedUserStats));
|
callback(JSON.stringify(parsedUserStats));
|
||||||
break;
|
break;
|
||||||
|
case QueryType.GetAccountBalances:
|
||||||
|
if (!this.localWallet?.address) throw new Error('Missing localWallet');
|
||||||
|
const accountBalances = await this.compositeClient?.validatorClient.get.getAccountBalances(
|
||||||
|
this.localWallet.address
|
||||||
|
);
|
||||||
|
const parsedAccountBalances = this.parseToPrimitives(accountBalances);
|
||||||
|
callback(JSON.stringify(parsedAccountBalances));
|
||||||
|
break;
|
||||||
// Do not implement Transfers (yet)
|
// Do not implement Transfers (yet)
|
||||||
case QueryType.Transfers:
|
case QueryType.Transfers:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { kollections } from '@dydxprotocol/v4-abacus';
|
import { kollections } from '@dydxprotocol/v4-abacus';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
AccountBalance,
|
||||||
AbacusApiState,
|
AbacusApiState,
|
||||||
AbacusNotification,
|
AbacusNotification,
|
||||||
AbacusStateNotificationProtocol,
|
AbacusStateNotificationProtocol,
|
||||||
@@ -18,6 +19,7 @@ import { Changes } from '@/constants/abacus';
|
|||||||
import type { RootStore } from '@/state/_store';
|
import type { RootStore } from '@/state/_store';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
setBalances,
|
||||||
setFills,
|
setFills,
|
||||||
setFundingPayments,
|
setFundingPayments,
|
||||||
setHistoricalPnl,
|
setHistoricalPnl,
|
||||||
@@ -72,6 +74,16 @@ class AbacusStateNotifier implements AbacusStateNotificationProtocol {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changes.has(Changes.accountBalances)) {
|
||||||
|
if (updatedState.account?.balances) {
|
||||||
|
const balances: Record<string, AccountBalance> = {}
|
||||||
|
for (const { k, v } of updatedState.account.balances.toArray()) {
|
||||||
|
balances[k] = v;
|
||||||
|
}
|
||||||
|
dispatch(setBalances(balances));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (changes.has(Changes.configs)) {
|
if (changes.has(Changes.configs)) {
|
||||||
dispatch(setConfigs(updatedState.configs));
|
dispatch(setConfigs(updatedState.configs));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
|
import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
AccountBalance,
|
||||||
SubaccountFill,
|
SubaccountFill,
|
||||||
Nullable,
|
Nullable,
|
||||||
Subaccount,
|
Subaccount,
|
||||||
@@ -35,6 +36,7 @@ export type AccountState = {
|
|||||||
wallet?: Nullable<Wallet>;
|
wallet?: Nullable<Wallet>;
|
||||||
walletType?: WalletType;
|
walletType?: WalletType;
|
||||||
historicalPnlPeriod?: HistoricalPnlPeriods;
|
historicalPnlPeriod?: HistoricalPnlPeriods;
|
||||||
|
balances?: Record<string, AccountBalance>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialState: AccountState = {
|
const initialState: AccountState = {
|
||||||
@@ -149,6 +151,9 @@ export const accountSlice = createSlice({
|
|||||||
viewedOrders: (state) => {
|
viewedOrders: (state) => {
|
||||||
state.hasUnseenOrderUpdates = false;
|
state.hasUnseenOrderUpdates = false;
|
||||||
},
|
},
|
||||||
|
setBalances: (state, action: PayloadAction<Record<string, AccountBalance>>) => {
|
||||||
|
state.balances = action.payload;
|
||||||
|
},
|
||||||
addUncommittedOrderClientId: (state, action: PayloadAction<number>) => {
|
addUncommittedOrderClientId: (state, action: PayloadAction<number>) => {
|
||||||
state.uncommittedOrderClientIds.push(action.payload);
|
state.uncommittedOrderClientIds.push(action.payload);
|
||||||
},
|
},
|
||||||
@@ -173,6 +178,7 @@ export const {
|
|||||||
setWallet,
|
setWallet,
|
||||||
viewedFills,
|
viewedFills,
|
||||||
viewedOrders,
|
viewedOrders,
|
||||||
|
setBalances,
|
||||||
addUncommittedOrderClientId,
|
addUncommittedOrderClientId,
|
||||||
removeUncommittedOrderClientId,
|
removeUncommittedOrderClientId,
|
||||||
} = accountSlice.actions;
|
} = accountSlice.actions;
|
||||||
|
|||||||
@@ -332,3 +332,8 @@ export const getUserStats = (state: RootState) => ({
|
|||||||
makerVolume30D: state.account?.wallet?.user?.makerVolume30D,
|
makerVolume30D: state.account?.wallet?.user?.makerVolume30D,
|
||||||
takerVolume30D: state.account?.wallet?.user?.takerVolume30D,
|
takerVolume30D: state.account?.wallet?.user?.takerVolume30D,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns user wallet balances
|
||||||
|
*/
|
||||||
|
export const getBalances = (state: RootState) => state.account?.balances;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export const WithdrawForm = () => {
|
|||||||
const [error, setError] = useState<Error | null>(null);
|
const [error, setError] = useState<Error | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const { simulateWithdraw, sendSquidWithdraw } = useSubaccount();
|
const { sendSquidWithdraw } = useSubaccount();
|
||||||
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
||||||
|
|
||||||
// User input
|
// User input
|
||||||
@@ -97,16 +97,10 @@ export const WithdrawForm = () => {
|
|||||||
field: TransferInputField.usdcSize,
|
field: TransferInputField.usdcSize,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const stdFee = await simulateWithdraw(parseFloat(debouncedAmount));
|
|
||||||
const amount =
|
|
||||||
parseFloat(debouncedAmount) -
|
|
||||||
parseFloat(stdFee?.amount[0]?.amount || '0') / QUANTUM_MULTIPLIER;
|
|
||||||
|
|
||||||
abacusStateManager.setTransferValue({
|
abacusStateManager.setTransferValue({
|
||||||
value: amount.toString(),
|
value: debouncedAmount,
|
||||||
field: TransferInputField.usdcSize,
|
field: TransferInputField.usdcSize,
|
||||||
});
|
});
|
||||||
|
|
||||||
setError(null);
|
setError(null);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { ButtonShape, ButtonSize } from '@/constants/buttons';
|
|||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks';
|
import { CLIENT_NETWORK_CONFIGS } from '@/constants/networks';
|
||||||
import { NumberSign, QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
import { NumberSign, QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||||
import { DYDX_CHAIN_ASSET_COIN_DENOM, DydxChainAsset } from '@/constants/wallets';
|
import { DYDX_CHAIN_ASSET_COIN_DENOM, DYDX_CHAIN_ASSET_TAGS, DydxChainAsset } from '@/constants/wallets';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useAccountBalance,
|
useAccountBalance,
|
||||||
@@ -52,28 +52,6 @@ type TransferFormProps = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const debouncedEstimateFee = debounce(
|
|
||||||
async ({ amount, recipientAddress, asset, setFees, simulateTransfer }) => {
|
|
||||||
if (!amount || !recipientAddress) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const coinDenom = DYDX_CHAIN_ASSET_COIN_DENOM[asset as DydxChainAsset];
|
|
||||||
const stdFee: StdFee = await simulateTransfer(amount, recipientAddress, coinDenom);
|
|
||||||
|
|
||||||
const fee = stdFee?.amount.find((coin) => coin.denom === coinDenom)?.amount;
|
|
||||||
const feeAmount = MustBigNumber(fee).div(QUANTUM_MULTIPLIER).toNumber();
|
|
||||||
|
|
||||||
setFees(feeAmount);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('TransferForm > : debouncedEstimateFee > ', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
1000,
|
|
||||||
{ trailing: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
export const TransferForm = ({
|
export const TransferForm = ({
|
||||||
selectedAsset = DydxChainAsset.DYDX,
|
selectedAsset = DydxChainAsset.DYDX,
|
||||||
onDone,
|
onDone,
|
||||||
@@ -82,8 +60,8 @@ export const TransferForm = ({
|
|||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
||||||
const { dydxAddress } = useAccounts();
|
const { dydxAddress } = useAccounts();
|
||||||
const { address: recipientAddress, size } = useSelector(getTransferInputs, shallowEqual) || {};
|
const { address: recipientAddress, size, fee } = useSelector(getTransferInputs, shallowEqual) || {};
|
||||||
const { transfer, simulateTransfer } = useSubaccount();
|
const { transfer } = useSubaccount();
|
||||||
const { nativeTokenBalance, usdcBalance } = useAccountBalance();
|
const { nativeTokenBalance, usdcBalance } = useAccountBalance();
|
||||||
const { selectedNetwork } = useSelectedNetwork();
|
const { selectedNetwork } = useSelectedNetwork();
|
||||||
|
|
||||||
@@ -93,7 +71,6 @@ export const TransferForm = ({
|
|||||||
// Form states
|
// Form states
|
||||||
const [error, setError] = useState<Error | undefined>();
|
const [error, setError] = useState<Error | undefined>();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [fees, setFees] = useState<number>();
|
|
||||||
|
|
||||||
const balance = asset === DydxChainAsset.USDC ? freeCollateral?.current : nativeTokenBalance;
|
const balance = asset === DydxChainAsset.USDC ? freeCollateral?.current : nativeTokenBalance;
|
||||||
const newBalance =
|
const newBalance =
|
||||||
@@ -104,7 +81,7 @@ export const TransferForm = ({
|
|||||||
.toNumber();
|
.toNumber();
|
||||||
const amount = asset === DydxChainAsset.USDC ? size?.usdcSize : size?.size;
|
const amount = asset === DydxChainAsset.USDC ? size?.usdcSize : size?.size;
|
||||||
|
|
||||||
const showNotEnoughGasWarning = fees && asset === DydxChainAsset.USDC && usdcBalance < fees;
|
const showNotEnoughGasWarning = fee && asset === DydxChainAsset.USDC && usdcBalance < fee;
|
||||||
|
|
||||||
// BN
|
// BN
|
||||||
const amountBN = MustBigNumber(amount);
|
const amountBN = MustBigNumber(amount);
|
||||||
@@ -134,34 +111,21 @@ export const TransferForm = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
debouncedEstimateFee.cancel();
|
abacusStateManager.setTransferValue({
|
||||||
|
value: asset,
|
||||||
if (isAmountValid && isAddressValid) {
|
field: TransferInputField.token,
|
||||||
debouncedEstimateFee({
|
|
||||||
amount,
|
|
||||||
recipientAddress,
|
|
||||||
asset,
|
|
||||||
setFees,
|
|
||||||
simulateTransfer,
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
setFees(undefined);
|
|
||||||
}
|
|
||||||
}, [asset, amount, recipientAddress]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setError(undefined);
|
|
||||||
}, [asset]);
|
}, [asset]);
|
||||||
|
|
||||||
const onTransfer = async () => {
|
const onTransfer = async () => {
|
||||||
if (!isAmountValid || !isAddressValid || !fees) return;
|
if (!isAmountValid || !isAddressValid || !fee) return;
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Subtract fees from amount if sending native tokens
|
// Subtract fees from amount if sending native tokens
|
||||||
const amountToTransfer = (
|
const amountToTransfer = (
|
||||||
asset === DydxChainAsset.DYDX ? amountBN.minus(fees) : amountBN
|
asset === DydxChainAsset.DYDX ? amountBN.minus(fee) : amountBN
|
||||||
).toNumber();
|
).toNumber();
|
||||||
|
|
||||||
const txResponse = await transfer(
|
const txResponse = await transfer(
|
||||||
@@ -212,7 +176,7 @@ export const TransferForm = ({
|
|||||||
value: DydxChainAsset.USDC,
|
value: DydxChainAsset.USDC,
|
||||||
label: (
|
label: (
|
||||||
<Styled.InlineRow>
|
<Styled.InlineRow>
|
||||||
<AssetIcon symbol="USDC" /> USDC
|
<AssetIcon symbol="USDC" /> {DYDX_CHAIN_ASSET_TAGS[DydxChainAsset.USDC]}
|
||||||
</Styled.InlineRow>
|
</Styled.InlineRow>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -221,7 +185,7 @@ export const TransferForm = ({
|
|||||||
label: (
|
label: (
|
||||||
<Styled.InlineRow>
|
<Styled.InlineRow>
|
||||||
{/* <AssetIcon symbol="DYDX" /> */}
|
{/* <AssetIcon symbol="DYDX" /> */}
|
||||||
Dv4TNT
|
{DYDX_CHAIN_ASSET_TAGS[DydxChainAsset.DYDX]}
|
||||||
</Styled.InlineRow>
|
</Styled.InlineRow>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -243,7 +207,7 @@ export const TransferForm = ({
|
|||||||
key: 'amount',
|
key: 'amount',
|
||||||
label: (
|
label: (
|
||||||
<span>
|
<span>
|
||||||
{stringGetter({ key: STRING_KEYS.AVAILABLE })} <Tag>{asset}</Tag>
|
{stringGetter({ key: STRING_KEYS.AVAILABLE })} <Tag>{DYDX_CHAIN_ASSET_TAGS[asset]}</Tag>
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
value: (
|
value: (
|
||||||
@@ -375,9 +339,9 @@ export const TransferForm = ({
|
|||||||
<Styled.Footer>
|
<Styled.Footer>
|
||||||
<TransferButtonAndReceipt
|
<TransferButtonAndReceipt
|
||||||
selectedAsset={asset}
|
selectedAsset={asset}
|
||||||
fees={fees}
|
fees={fee || undefined}
|
||||||
isDisabled={!isAmountValid || !isAddressValid || !fees}
|
isDisabled={!isAmountValid || !isAddressValid || !fee}
|
||||||
isLoading={isLoading || Boolean(isAmountValid && isAddressValid && !fees)}
|
isLoading={isLoading || Boolean(isAmountValid && isAddressValid && !fee)}
|
||||||
/>
|
/>
|
||||||
</Styled.Footer>
|
</Styled.Footer>
|
||||||
</Styled.Form>
|
</Styled.Form>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { shallowEqual, useSelector } from 'react-redux';
|
|||||||
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
|
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { NumberSign } from '@/constants/numbers';
|
import { NumberSign } from '@/constants/numbers';
|
||||||
import { DydxChainAsset } from '@/constants/wallets';
|
import { DYDX_CHAIN_ASSET_TAGS, DydxChainAsset } from '@/constants/wallets';
|
||||||
|
|
||||||
import { useAccountBalance, useStringGetter } from '@/hooks';
|
import { useAccountBalance, useStringGetter } from '@/hooks';
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ export const TransferButtonAndReceipt = ({
|
|||||||
key: 'fees',
|
key: 'fees',
|
||||||
label: (
|
label: (
|
||||||
<span>
|
<span>
|
||||||
{stringGetter({ key: STRING_KEYS.FEES })} <Tag>{selectedAsset}</Tag>
|
{stringGetter({ key: STRING_KEYS.FEES })} <Tag>{DYDX_CHAIN_ASSET_TAGS[selectedAsset]}</Tag>
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
value: <Output type={OutputType.Asset} value={fees} />,
|
value: <Output type={OutputType.Asset} value={fees} />,
|
||||||
@@ -69,7 +69,7 @@ export const TransferButtonAndReceipt = ({
|
|||||||
key: 'balance',
|
key: 'balance',
|
||||||
label: (
|
label: (
|
||||||
<span>
|
<span>
|
||||||
{stringGetter({ key: STRING_KEYS.BALANCE })} <Tag>{selectedAsset}</Tag>
|
{stringGetter({ key: STRING_KEYS.BALANCE })} <Tag>{DYDX_CHAIN_ASSET_TAGS[selectedAsset]}</Tag>
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
value: (
|
value: (
|
||||||
|
|||||||
Reference in New Issue
Block a user