Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45e1b874fd | ||
|
|
8d5bf1a721 | ||
|
|
7f3d57b46a | ||
|
|
c292c84c2c | ||
|
|
2d37ff676b | ||
|
|
68f3552569 | ||
|
|
18b12591ca | ||
|
|
3f963ffb07 | ||
|
|
aac024fd5e | ||
|
|
4913c690ec |
@@ -1,6 +1,9 @@
|
||||
Copyright (C) 2023 dYdX Trading Inc.
|
||||
|
||||
Subject to your compliance with applicable law, you are granted the right to use the Licensed Work (defined below) under the terms of the GNU Affero General Public License as set forth below; provided, however, that if you violate any such applicable law in your use of the Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Licensed Work will automatically and immediately terminate.
|
||||
Subject to your compliance with applicable law and the v4 Terms of Use, available at dydx.exchange/legal, you are granted the right to use the Program or Licensed Work (defined below) under the terms of the GNU Affero General Public License as set forth below; provided, however, that if you violate any such applicable law in your use of the Program or Licensed Work, all of your rights and licenses to use (including any rights to reproduce, distribute, install or modify) the Program or Licensed Work will automatically and immediately terminate.
|
||||
|
||||
|
||||
The “Program” or “Licensed Work” shall mean any of the following: dydxprotocol/cosmos-sdk, dydxprotocol/cometbft, dydxprotocol/v4-chain, dydxprotocol/v4-clients, dydxprotocol/v4-web, dydxprotocol/v4-abacus, dydxprotocol/v4-localization, dydxprotocol/v4-documentation, and any dYdX or dYdX Trading Inc. repository reflecting a copy of, or link to, this license.
|
||||
|
||||
|
||||
The GNU Affero General Public License
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"apps": {
|
||||
"ios": {
|
||||
"scheme": "dydxv4"
|
||||
}
|
||||
},
|
||||
"deployments": {
|
||||
"MAINNET": {
|
||||
"environments": [
|
||||
@@ -203,8 +208,8 @@
|
||||
"endpoints": {
|
||||
"indexers": [
|
||||
{
|
||||
"api": "http://indexer.v4dev4.dydx.exchange",
|
||||
"socket": "ws://indexer.v4dev4.dydx.exchange"
|
||||
"api": "https://indexer.v4dev4.dydx.exchange",
|
||||
"socket": "wss://indexer.v4dev4.dydx.exchange"
|
||||
}
|
||||
],
|
||||
"validators": [
|
||||
@@ -888,6 +893,7 @@
|
||||
"privacy": "https://dydx.exchange/privacy",
|
||||
"statusPage": "https://status.v4testnet.dydx.exchange/",
|
||||
"mintscan": "https://testnet.mintscan.io/dydx-testnet/txs/{tx_hash}",
|
||||
"mintscanBase": "https://testnet.mintscan.io/dydx-testnet",
|
||||
"documentation": "https://docs.dydx.exchange/",
|
||||
"community": "https://discord.com/invite/dydx",
|
||||
"feedback": "https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform",
|
||||
@@ -1028,7 +1034,7 @@
|
||||
"tos": "[HTTP link to TOS]",
|
||||
"privacy": "[HTTP link to Privacy Policy]",
|
||||
"mintscan": "[HTTP link to Mintscan, with {tx_hash} placeholder]",
|
||||
"mintscanBase": "[HTTP link to TOS mintsacn base url]",
|
||||
"mintscanBase": "[HTTP link to TOS mintscan base url]",
|
||||
"feedback": "[HTTP link to feedback form, can be null]",
|
||||
"blogs": "[HTTP link to blogs, can be null]",
|
||||
"foundation": "[HTTP link to foundation, can be null]",
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import environments from '../../public/configs/env.json';
|
||||
|
||||
// TODO: Update for Mainnet deployment
|
||||
export const AVAILABLE_ENVIRONMENTS =
|
||||
import.meta.env.MODE === 'production'
|
||||
? environments.deployments.TESTNET
|
||||
: environments.deployments.DEV;
|
||||
const CURRENT_MODE = ({
|
||||
production: 'MAINNET',
|
||||
testnet: 'TESTNET',
|
||||
staging: 'DEV',
|
||||
development: 'DEV',
|
||||
}[import.meta.env.MODE] ?? 'MAINNET') as 'MAINNET' | 'TESTNET' | 'DEV';
|
||||
|
||||
export const CURRENT_ABACUS_DEPLOYMENT = import.meta.env.MODE === 'production' ? 'TESTNET' : 'DEV';
|
||||
export const isMainnet = CURRENT_MODE === 'MAINNET';
|
||||
export const isTestnet = CURRENT_MODE === 'TESTNET';
|
||||
export const isDev = CURRENT_MODE === 'DEV';
|
||||
|
||||
export const AVAILABLE_ENVIRONMENTS = environments.deployments[CURRENT_MODE];
|
||||
export const CURRENT_ABACUS_DEPLOYMENT = CURRENT_MODE;
|
||||
export const ENVIRONMENT_CONFIG_MAP = environments.environments;
|
||||
export type DydxNetwork = keyof typeof ENVIRONMENT_CONFIG_MAP;
|
||||
export const DEFAULT_APP_ENVIRONMENT = AVAILABLE_ENVIRONMENTS.default as DydxNetwork;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { isDev } from '@/constants/networks';
|
||||
import { WalletType } from '@/constants/wallets';
|
||||
|
||||
import { isTruthy } from '@/lib/isTruthy';
|
||||
@@ -6,7 +7,7 @@ export const useDisplayedWallets = () => {
|
||||
return [
|
||||
WalletType.MetaMask,
|
||||
|
||||
import.meta.env.MODE !== 'production' && WalletType.Keplr,
|
||||
isDev && WalletType.Keplr,
|
||||
|
||||
WalletType.WalletConnect2,
|
||||
|
||||
|
||||
@@ -7,9 +7,11 @@ import { AlertType } from '@/constants/alerts';
|
||||
import { AbacusOrderStatus, ORDER_SIDES } from '@/constants/abacus';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS, StringKey } from '@/constants/localization';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { type NotificationTypeConfig, NotificationType } from '@/constants/notifications';
|
||||
import { ORDER_SIDE_STRINGS } from '@/constants/trade';
|
||||
|
||||
import { useSelectedNetwork } from '@/hooks';
|
||||
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
|
||||
|
||||
import { Icon, IconName } from '@/components/Icon';
|
||||
@@ -23,7 +25,6 @@ import { OrderStatusIcon } from '@/views/OrderStatusIcon';
|
||||
|
||||
import { useStringGetter } from './useStringGetter';
|
||||
import { TransferStatusSteps } from '@/views/TransferStatusSteps';
|
||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
||||
|
||||
export const notificationTypes = [
|
||||
{
|
||||
@@ -124,6 +125,7 @@ export const notificationTypes = [
|
||||
useTrigger: ({ trigger }) => {
|
||||
const stringGetter = useStringGetter();
|
||||
const { transferNotifications } = useLocalNotifications();
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
|
||||
const getTitleStringKey = useCallback((type: 'deposit' | 'withdrawal', finished: boolean) => {
|
||||
if (type === 'deposit' && !finished) return STRING_KEYS.DEPOSIT_IN_PROGRESS;
|
||||
@@ -136,7 +138,7 @@ export const notificationTypes = [
|
||||
for (const transfer of transferNotifications) {
|
||||
const { fromChainId, status, txHash, toAmount } = transfer;
|
||||
const finished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing';
|
||||
const type = fromChainId === TESTNET_CHAIN_ID ? 'withdrawal' : 'deposit';
|
||||
const type = fromChainId === ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId ? 'withdrawal' : 'deposit';
|
||||
// @ts-ignore status.errors is not in the type definition but can be returned
|
||||
const error = status?.errors?.length ? status?.errors[0] : status?.error;
|
||||
|
||||
|
||||
+91
-60
@@ -48,7 +48,7 @@ export const useSubaccount = () => useContext(SubaccountContext);
|
||||
|
||||
export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: LocalWallet }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { usdcDenom } = useTokenConfigs();
|
||||
const { usdcDenom, usdcDecimals } = useTokenConfigs();
|
||||
const { compositeClient, faucetClient } = useDydxClient();
|
||||
|
||||
const { getFaucetFunds } = useMemo(
|
||||
@@ -79,16 +79,34 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
subaccountClient: SubaccountClient;
|
||||
assetId?: number;
|
||||
amount: number;
|
||||
}) => await compositeClient?.depositToSubaccount(subaccountClient, amount.toString()),
|
||||
|
||||
}) => {
|
||||
try {
|
||||
return await compositeClient?.depositToSubaccount(
|
||||
subaccountClient,
|
||||
amount.toFixed(usdcDecimals)
|
||||
);
|
||||
} catch (error) {
|
||||
log('useSubaccount/depositToSubaccount', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
withdrawFromSubaccount: async ({
|
||||
subaccountClient,
|
||||
amount,
|
||||
}: {
|
||||
subaccountClient: SubaccountClient;
|
||||
amount: number;
|
||||
}) => await compositeClient?.withdrawFromSubaccount(subaccountClient, amount.toString()),
|
||||
|
||||
}) => {
|
||||
try {
|
||||
return await compositeClient?.withdrawFromSubaccount(
|
||||
subaccountClient,
|
||||
amount.toFixed(usdcDecimals)
|
||||
);
|
||||
} catch (error) {
|
||||
log('useSubaccount/withdrawFromSubaccount', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
transferFromSubaccountToAddress: async ({
|
||||
subaccountClient,
|
||||
assetId = 0,
|
||||
@@ -99,27 +117,33 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
assetId?: number;
|
||||
amount: number;
|
||||
recipient: string;
|
||||
}) =>
|
||||
await compositeClient?.validatorClient.post.send(
|
||||
subaccountClient?.wallet,
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
const msg =
|
||||
compositeClient?.validatorClient.post.composer.composeMsgWithdrawFromSubaccount(
|
||||
subaccountClient.address,
|
||||
subaccountClient.subaccountNumber,
|
||||
assetId,
|
||||
Long.fromNumber(amount * QUANTUM_MULTIPLIER),
|
||||
recipient
|
||||
);
|
||||
}) => {
|
||||
try {
|
||||
return await compositeClient?.validatorClient.post.send(
|
||||
subaccountClient?.wallet,
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
const msg =
|
||||
compositeClient?.validatorClient.post.composer.composeMsgWithdrawFromSubaccount(
|
||||
subaccountClient.address,
|
||||
subaccountClient.subaccountNumber,
|
||||
assetId,
|
||||
Long.fromNumber(amount * QUANTUM_MULTIPLIER),
|
||||
recipient
|
||||
);
|
||||
|
||||
resolve([msg]);
|
||||
}),
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
Method.BroadcastTxCommit
|
||||
),
|
||||
resolve([msg]);
|
||||
}),
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
Method.BroadcastTxCommit
|
||||
);
|
||||
} catch (error) {
|
||||
log('useSubaccount/transferFromSubaccountToAddress', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
transferNativeToken: async ({
|
||||
subaccountClient,
|
||||
@@ -129,24 +153,30 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
subaccountClient: SubaccountClient;
|
||||
amount: number;
|
||||
recipient: string;
|
||||
}) =>
|
||||
await compositeClient?.validatorClient.post.send(
|
||||
subaccountClient.wallet,
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
const msg = compositeClient?.sendTokenMessage(
|
||||
subaccountClient.wallet,
|
||||
amount.toString(),
|
||||
recipient,
|
||||
);
|
||||
}) => {
|
||||
try {
|
||||
return await compositeClient?.validatorClient.post.send(
|
||||
subaccountClient.wallet,
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
const msg = compositeClient?.sendTokenMessage(
|
||||
subaccountClient.wallet,
|
||||
amount.toString(),
|
||||
recipient
|
||||
);
|
||||
|
||||
resolve([msg]);
|
||||
}),
|
||||
false,
|
||||
compositeClient?.validatorClient?.post.defaultDydxGasPrice,
|
||||
undefined,
|
||||
Method.BroadcastTxCommit
|
||||
),
|
||||
resolve([msg]);
|
||||
}),
|
||||
false,
|
||||
compositeClient?.validatorClient?.post.defaultDydxGasPrice,
|
||||
undefined,
|
||||
Method.BroadcastTxCommit
|
||||
);
|
||||
} catch (error) {
|
||||
log('useSubaccount/transferNativeToken', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
sendSquidWithdrawFromSubaccount: async ({
|
||||
subaccountClient,
|
||||
@@ -158,20 +188,27 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
payload: string;
|
||||
}) => {
|
||||
if (!compositeClient) throw new Error('client not initialized');
|
||||
try {
|
||||
const transaction = JSON.parse(payload);
|
||||
|
||||
const transaction = JSON.parse(payload);
|
||||
const msg = compositeClient.withdrawFromSubaccountMessage(
|
||||
subaccountClient,
|
||||
amount.toFixed(usdcDecimals)
|
||||
);
|
||||
const ibcMsg: EncodeObject = {
|
||||
typeUrl: transaction.msgTypeUrl,
|
||||
value: transaction.msg,
|
||||
};
|
||||
|
||||
const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount.toString());
|
||||
const ibcMsg: EncodeObject = {
|
||||
typeUrl: transaction.msgTypeUrl,
|
||||
value: transaction.msg,
|
||||
};
|
||||
|
||||
return await compositeClient.send(
|
||||
subaccountClient.wallet,
|
||||
() => Promise.resolve([msg, ibcMsg]),
|
||||
false
|
||||
);
|
||||
return await compositeClient.send(
|
||||
subaccountClient.wallet,
|
||||
() => Promise.resolve([msg, ibcMsg]),
|
||||
false
|
||||
);
|
||||
} catch (error) {
|
||||
log('useSubaccount/sendSquidWithdrawFromSubaccount', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
}),
|
||||
[compositeClient]
|
||||
@@ -313,11 +350,6 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
placeOrderParams = abacusStateManager.placeOrder(callback);
|
||||
}
|
||||
|
||||
track(AnalyticsEvent.TradePlaceOrder, {
|
||||
...placeOrderParams,
|
||||
isClosePosition,
|
||||
} as HumanReadablePlaceOrderPayload & { isClosePosition: boolean });
|
||||
|
||||
return placeOrderParams;
|
||||
},
|
||||
[subaccountClient]
|
||||
@@ -346,7 +378,6 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
||||
}) => {
|
||||
const callback = (success: boolean, parsingError?: Nullable<ParsingError>) => {
|
||||
if (success) {
|
||||
track(AnalyticsEvent.TradeCancelOrder);
|
||||
onSuccess?.();
|
||||
} else {
|
||||
onError?.({ errorStringKey: parsingError?.stringKey });
|
||||
|
||||
@@ -19,8 +19,10 @@ export const useTokenConfigs = (): {
|
||||
},
|
||||
};
|
||||
usdcDenom: string;
|
||||
usdcDecimals: number;
|
||||
usdcLabel: string;
|
||||
chainTokenDenom: string;
|
||||
chainTokenDecimals: number;
|
||||
chainTokenLabel: string;
|
||||
} => {
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
@@ -29,8 +31,10 @@ export const useTokenConfigs = (): {
|
||||
return {
|
||||
tokensConfigs,
|
||||
usdcDenom: tokensConfigs[DydxChainAsset.USDC].denom,
|
||||
usdcDecimals: tokensConfigs[DydxChainAsset.USDC].decimals,
|
||||
usdcLabel: tokensConfigs[DydxChainAsset.USDC].name,
|
||||
chainTokenDenom: tokensConfigs[DydxChainAsset.CHAINTOKEN].denom,
|
||||
chainTokenDecimals: tokensConfigs[DydxChainAsset.CHAINTOKEN].decimals,
|
||||
chainTokenLabel: tokensConfigs[DydxChainAsset.CHAINTOKEN].name,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import styled, { type AnyStyledComponent, css } from 'styled-components';
|
||||
import { AbacusApiStatus } from '@/constants/abacus';
|
||||
import { ButtonSize } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { ENVIRONMENT_CONFIG_MAP, isDev } from '@/constants/networks';
|
||||
|
||||
import { useApiState, useSelectedNetwork, useStringGetter } from '@/hooks';
|
||||
import { ChatIcon, LinkOutIcon } from '@/icons';
|
||||
@@ -75,7 +75,7 @@ export const FooterDesktop = () => {
|
||||
)}
|
||||
</Styled.Row>
|
||||
|
||||
{import.meta.env.MODE !== 'production' && (
|
||||
{isDev && (
|
||||
<Styled.Details
|
||||
withSeparators
|
||||
items={[
|
||||
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { UNCOMMITTED_ORDER_TIMEOUT_MS } from '@/constants/trade';
|
||||
import { QUANTUM_MULTIPLIER } from '@/constants/numbers';
|
||||
import { ENVIRONMENT_CONFIG_MAP, DydxNetwork, isTestnet } from '@/constants/networks';
|
||||
|
||||
import { RootStore } from '@/state/_store';
|
||||
import { addUncommittedOrderClientId, removeUncommittedOrderClientId } from '@/state/account';
|
||||
@@ -198,8 +198,13 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
const parsedTx = this.parseToPrimitives(tx);
|
||||
const hash = parsedTx?.hash;
|
||||
|
||||
if (import.meta.env.MODE === 'production') {
|
||||
console.log(`https://testnet.mintscan.io/dydx-testnet/txs/${hash}`);
|
||||
if (isTestnet) {
|
||||
console.log(
|
||||
`${
|
||||
ENVIRONMENT_CONFIG_MAP[this.compositeClient.network.getString() as DydxNetwork]?.links
|
||||
?.mintscanBase
|
||||
}/txs/${hash}`
|
||||
);
|
||||
} else console.log(`txHash: ${hash}`);
|
||||
|
||||
return JSON.stringify(parsedTx);
|
||||
@@ -229,7 +234,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
orderFlags,
|
||||
clobPairId,
|
||||
goodTilBlock || undefined,
|
||||
goodTilBlockTime || undefined,
|
||||
goodTilBlockTime || undefined
|
||||
);
|
||||
|
||||
const parsedTx = this.parseToPrimitives(tx);
|
||||
@@ -295,15 +300,11 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
|
||||
if (!this.localWallet) {
|
||||
throw new Error('Missing compositeClient or localWallet');
|
||||
}
|
||||
const msg = compositeClient?.sendTokenMessage(
|
||||
this.localWallet,
|
||||
amount,
|
||||
recipient,
|
||||
);
|
||||
const msg = compositeClient?.sendTokenMessage(this.localWallet, amount, recipient);
|
||||
|
||||
resolve([msg]);
|
||||
}),
|
||||
this.compositeClient?.validatorClient?.post.defaultDydxGasPrice,
|
||||
this.compositeClient?.validatorClient?.post.defaultDydxGasPrice
|
||||
);
|
||||
|
||||
const parsedTx = this.parseToPrimitives(tx);
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import type { AbacusFileSystemProtocol, FileLocation, Nullable } from '@/constants/abacus';
|
||||
|
||||
export const ENDPOINTS_PATH =
|
||||
import.meta.env.MODE === 'production'
|
||||
? 'config/prod/endpoints.json'
|
||||
: 'config/staging/dev_endpoints.json';
|
||||
|
||||
class AbacusFileSystem implements AbacusFileSystemProtocol {
|
||||
readTextFile(location: FileLocation, path: string): Nullable<string> {
|
||||
return null;
|
||||
|
||||
@@ -41,7 +41,7 @@ import AbacusStateNotifier from './stateNotification';
|
||||
import AbacusLocalizer from './localizer';
|
||||
import AbacusFormatter from './formatter';
|
||||
import AbacusThreading from './threading';
|
||||
import AbacusFileSystem, { ENDPOINTS_PATH } from './filesystem';
|
||||
import AbacusFileSystem from './filesystem';
|
||||
import { LocaleSeparators } from '../numbers';
|
||||
class AbacusStateManager {
|
||||
private store: RootStore | undefined;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AbacusWebsocketProtocol } from '@/constants/abacus';
|
||||
import type { TradingViewBar } from '@/constants/candles';
|
||||
import { isDev } from '@/constants/networks';
|
||||
|
||||
import {
|
||||
PING_INTERVAL_MS,
|
||||
@@ -161,13 +162,13 @@ class AbacusWebsocket implements Omit<AbacusWebsocketProtocol, '__doNotUseOrImpl
|
||||
|
||||
this.socket.onclose = (e) => {
|
||||
this.connectedCallback?.(false);
|
||||
if (import.meta.env.MODE === 'production') return;
|
||||
if (!isDev) return;
|
||||
console.warn('AbacusStateManager > WS > close > ', e);
|
||||
};
|
||||
|
||||
this.socket.onerror = (e) => {
|
||||
this.connectedCallback?.(false);
|
||||
if (import.meta.env.MODE === 'production') return;
|
||||
if (!isDev) return;
|
||||
console.error('AbacusStateManager > WS > error > ', e);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { isDev } from "@/constants/networks";
|
||||
|
||||
export const log = (location: string, error: Error, metadata?: any) => {
|
||||
if (import.meta.env.MODE !== 'production') {
|
||||
if (isDev) {
|
||||
console.warn('telemetry/log:', { location, error, metadata });
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ export const AccountDetailsAndHistory = () => {
|
||||
key: 'BuyingPower',
|
||||
labelKey: STRING_KEYS.BUYING_POWER,
|
||||
type: OutputType.Fiat,
|
||||
value: buyingPower?.current,
|
||||
value: MustBigNumber(buyingPower?.current).lt(0) ? undefined : buyingPower?.current, // show '-' when buying power is negative
|
||||
},
|
||||
].filter(isTruthy);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
import { AbacusApiStatus } from '@/constants/abacus';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { isDev } from '@/constants/networks';
|
||||
|
||||
import { setApiState, setSelectedNetwork } from '@/state/app';
|
||||
import { resetPerpetualsState } from '@/state/perpetuals';
|
||||
@@ -30,7 +31,7 @@ export default (store: any) => (next: any) => async (action: PayloadAction<any>)
|
||||
store.dispatch(
|
||||
openDialog({
|
||||
type: DialogTypes.ExchangeOffline,
|
||||
dialogProps: { preventClose: import.meta.env.MODE === 'production' },
|
||||
dialogProps: { preventClose: !isDev },
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -151,7 +151,10 @@ export const AccountInfoConnectedState = () => {
|
||||
),
|
||||
label: stringGetter({ key: STRING_KEYS.BUYING_POWER }),
|
||||
type: OutputType.Fiat,
|
||||
value: buyingPower,
|
||||
value:
|
||||
MustBigNumber(buyingPower?.current).lt(0) && buyingPower?.postOrder === null
|
||||
? undefined
|
||||
: buyingPower,
|
||||
},
|
||||
].map(
|
||||
({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
|
||||
import { isMainnet } from '@/constants/networks';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { useBreakpoints, useStringGetter } from '@/hooks';
|
||||
|
||||
@@ -27,14 +28,22 @@ export const DepositDialog = ({ setIsOpen }: ElementProps) => {
|
||||
isOpen
|
||||
setIsOpen={setIsOpen}
|
||||
title={stringGetter({ key: STRING_KEYS.DEPOSIT })}
|
||||
description={showTestDeposit && 'Test funds will be sent directly to your dYdX account.'}
|
||||
description={
|
||||
!isMainnet && showTestDeposit && 'Test funds will be sent directly to your dYdX account.'
|
||||
}
|
||||
placement={isMobile ? DialogPlacement.FullScreen : DialogPlacement.Default}
|
||||
>
|
||||
<Styled.Content>
|
||||
{showTestDeposit ? <TestnetDepositForm onDeposit={closeDialog} /> : <DepositForm />}
|
||||
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
|
||||
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
|
||||
</Styled.TextToggle>
|
||||
{!isMainnet && showTestDeposit ? (
|
||||
<TestnetDepositForm onDeposit={closeDialog} />
|
||||
) : (
|
||||
<DepositForm />
|
||||
)}
|
||||
{!isMainnet && (
|
||||
<Styled.TextToggle onClick={() => setShowTestDeposit(!showTestDeposit)}>
|
||||
{showTestDeposit ? 'Show deposit form (Under Construction)' : 'Show test faucet'}
|
||||
</Styled.TextToggle>
|
||||
)}
|
||||
</Styled.Content>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
import { AbacusApiStatus } from '@/constants/abacus';
|
||||
import { DialogTypes } from '@/constants/dialogs';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { isDev } from '@/constants/networks';
|
||||
|
||||
import { useApiState, useStringGetter } from '@/hooks';
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
@@ -45,7 +46,7 @@ export const ExchangeOfflineDialog = ({ preventClose, setIsOpen }: ElementProps)
|
||||
>
|
||||
<Styled.Content>
|
||||
<p>{statusErrorMessage}</p>
|
||||
{import.meta.env.MODE !== 'production' && <NetworkSelectMenu />}
|
||||
{isDev && <NetworkSelectMenu />}
|
||||
</Styled.Content>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ import { type FormEvent, useCallback, useEffect, useMemo, useState } from 'react
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import { type NumberFormatValues } from 'react-number-format';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
||||
import { parseUnits } from 'viem'
|
||||
|
||||
import erc20 from '@/abi/erc20.json';
|
||||
@@ -10,10 +9,11 @@ import { TransferInputField, TransferInputTokenResource, TransferType } from '@/
|
||||
import { AlertType } from '@/constants/alerts';
|
||||
import { ButtonSize } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { NumberSign } from '@/constants/numbers';
|
||||
import type { EvmAddress } from '@/constants/wallets';
|
||||
|
||||
import { useAccounts, useDebounce, useStringGetter } from '@/hooks';
|
||||
import { useAccounts, useDebounce, useStringGetter, useSelectedNetwork } from '@/hooks';
|
||||
import { useAccountBalance, CHAIN_DEFAULT_TOKEN_ADDRESS } from '@/hooks/useAccountBalance';
|
||||
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
|
||||
import { NATIVE_TOKEN_ADDRESS, useSquid } from '@/hooks/useSquid';
|
||||
@@ -54,6 +54,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
const stringGetter = useStringGetter();
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
|
||||
const { evmAddress, signerWagmi } = useAccounts();
|
||||
const { publicClientWagmi } = useWalletConnection();
|
||||
@@ -239,7 +240,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
|
||||
if (txHash) {
|
||||
addTransferNotification({
|
||||
txHash: txHash,
|
||||
toChainId: TESTNET_CHAIN_ID,
|
||||
toChainId: ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId,
|
||||
fromChainId: chainIdStr || undefined,
|
||||
toAmount: summary?.usdcSize || undefined,
|
||||
triggeredAt: Date.now(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type Dispatch, type SetStateAction, useState, type ReactNode } from 'react';
|
||||
import styled, { type AnyStyledComponent, } from 'styled-components';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
import type { RouteData } from '@0xsquid/sdk';
|
||||
|
||||
@@ -32,6 +32,8 @@ import { WithReceipt } from '@/components/WithReceipt';
|
||||
import { getSubaccountBuyingPower, getSubaccountEquity } from '@/state/accountSelectors';
|
||||
import { getTransferInputs } from '@/state/inputsSelectors';
|
||||
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
|
||||
import { SlippageEditor } from '../SlippageEditor';
|
||||
|
||||
type ElementProps = {
|
||||
@@ -131,7 +133,7 @@ export const DepositButtonAndReceipt = ({
|
||||
value: (
|
||||
<DiffOutput
|
||||
type={OutputType.Fiat}
|
||||
value={buyingPower}
|
||||
value={MustBigNumber(buyingPower).lt(0) ? undefined : buyingPower}
|
||||
newValue={newBuyingPower}
|
||||
sign={NumberSign.Positive}
|
||||
withDiff={Boolean(newBuyingPower) && buyingPower !== newBuyingPower}
|
||||
|
||||
@@ -3,13 +3,13 @@ import type { ChangeEvent, FormEvent } from 'react';
|
||||
import styled, { type AnyStyledComponent } from 'styled-components';
|
||||
import type { NumberFormatValues } from 'react-number-format';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
|
||||
import { isAddress } from 'viem';
|
||||
|
||||
import { TransferInputField, TransferInputTokenResource, TransferType } from '@/constants/abacus';
|
||||
import { AlertType } from '@/constants/alerts';
|
||||
import { ButtonSize } from '@/constants/buttons';
|
||||
import { STRING_KEYS } from '@/constants/localization';
|
||||
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||
import { NumberSign } from '@/constants/numbers';
|
||||
|
||||
import {
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
useDebounce,
|
||||
useDydxClient,
|
||||
useRestrictions,
|
||||
useSelectedNetwork,
|
||||
useStringGetter,
|
||||
useSubaccount,
|
||||
} from '@/hooks';
|
||||
@@ -52,6 +53,7 @@ export const WithdrawForm = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
const [error, setError] = useState<string>();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { selectedNetwork } = useSelectedNetwork();
|
||||
|
||||
const { sendSquidWithdraw } = useSubaccount();
|
||||
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
|
||||
@@ -164,7 +166,7 @@ export const WithdrawForm = () => {
|
||||
const hash = `0x${Buffer.from(txHash.hash).toString('hex')}`;
|
||||
addTransferNotification({
|
||||
txHash: hash,
|
||||
fromChainId: TESTNET_CHAIN_ID,
|
||||
fromChainId: ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId,
|
||||
toChainId: chainIdStr || undefined,
|
||||
toAmount: debouncedAmountBN.toNumber(),
|
||||
triggeredAt: Date.now(),
|
||||
|
||||
@@ -36,6 +36,7 @@ import { truncateAddress } from '@/lib/wallet';
|
||||
|
||||
import { layoutMixins } from '@/styles/layoutMixins';
|
||||
import { headerMixins } from '@/styles/headerMixins';
|
||||
import { MustBigNumber } from '@/lib/numbers';
|
||||
|
||||
export const AccountMenu = () => {
|
||||
const stringGetter = useStringGetter();
|
||||
@@ -49,6 +50,8 @@ export const AccountMenu = () => {
|
||||
|
||||
const { evmAddress, walletType, dydxAddress, hdKey } = useAccounts();
|
||||
|
||||
const usdcBalance = freeCollateral?.current || 0;
|
||||
|
||||
const onRecoverKeys = () => {
|
||||
dispatch(openDialog({ type: DialogTypes.Onboarding }));
|
||||
};
|
||||
@@ -122,7 +125,11 @@ export const AccountMenu = () => {
|
||||
</Styled.label>
|
||||
<Styled.BalanceOutput type={OutputType.Asset} value={nativeTokenBalance} />
|
||||
</div>
|
||||
<AssetActions asset={DydxChainAsset.CHAINTOKEN} dispatch={dispatch} />
|
||||
<AssetActions
|
||||
asset={DydxChainAsset.CHAINTOKEN}
|
||||
dispatch={dispatch}
|
||||
hasBalance={nativeTokenBalance.gt(0)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
@@ -135,11 +142,16 @@ export const AccountMenu = () => {
|
||||
</Styled.label>
|
||||
<Styled.BalanceOutput
|
||||
type={OutputType.Asset}
|
||||
value={freeCollateral?.current || 0}
|
||||
value={usdcBalance}
|
||||
fractionDigits={2}
|
||||
/>
|
||||
</div>
|
||||
<AssetActions asset={DydxChainAsset.USDC} dispatch={dispatch} withOnboarding />
|
||||
<AssetActions
|
||||
asset={DydxChainAsset.USDC}
|
||||
dispatch={dispatch}
|
||||
hasBalance={MustBigNumber(usdcBalance).gt(0)}
|
||||
withOnboarding
|
||||
/>
|
||||
</div>
|
||||
</Styled.Balances>
|
||||
</Styled.AccountInfo>
|
||||
@@ -217,22 +229,25 @@ const AssetActions = memo(
|
||||
asset,
|
||||
dispatch,
|
||||
withOnboarding,
|
||||
hasBalance,
|
||||
}: {
|
||||
asset: DydxChainAsset;
|
||||
dispatch: Dispatch;
|
||||
withOnboarding?: boolean;
|
||||
hasBalance?: boolean;
|
||||
}) => (
|
||||
<Styled.InlineRow>
|
||||
{[
|
||||
withOnboarding && {
|
||||
dialogType: DialogTypes.Withdraw,
|
||||
iconName: IconName.Withdraw,
|
||||
},
|
||||
withOnboarding &&
|
||||
hasBalance && {
|
||||
dialogType: DialogTypes.Withdraw,
|
||||
iconName: IconName.Withdraw,
|
||||
},
|
||||
withOnboarding && {
|
||||
dialogType: DialogTypes.Deposit,
|
||||
iconName: IconName.Deposit,
|
||||
},
|
||||
{
|
||||
hasBalance && {
|
||||
dialogType: DialogTypes.Transfer,
|
||||
dialogProps: { selectedAsset: asset },
|
||||
iconName: IconName.Send,
|
||||
|
||||
Reference in New Issue
Block a user