diff --git a/package.json b/package.json index 355ff83..ae82166 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@cosmjs/proto-signing": "^0.31.0", "@cosmjs/stargate": "^0.31.0", "@cosmjs/tendermint-rpc": "^0.31.0", - "@dydxprotocol/v4-abacus": "^0.6.4", + "@dydxprotocol/v4-abacus": "^0.7.0", "@dydxprotocol/v4-client-js": "^0.36.1", "@dydxprotocol/v4-localization": "^0.1.30", "@ethersproject/providers": "^5.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3e01552..541ef18 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,8 +27,8 @@ dependencies: specifier: ^0.31.0 version: 0.31.0 '@dydxprotocol/v4-abacus': - specifier: ^0.6.4 - version: 0.6.4 + specifier: ^0.7.0 + version: 0.7.0 '@dydxprotocol/v4-client-js': specifier: ^0.36.1 version: 0.36.1 @@ -979,8 +979,8 @@ packages: resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==} dev: true - /@dydxprotocol/v4-abacus@0.6.4: - resolution: {integrity: sha512-eH+/9Q/OnQtwzBwM1BJyXybFPdivGmFQWrxM71MFWGs6uIQGbZX775mpoa8deweSTyQ/QrRLRQ1mP2BPDgBQYg==} + /@dydxprotocol/v4-abacus@0.7.0: + resolution: {integrity: sha512-XheqfIpOODfQFG860oH0fneVgp9qQKPMDTwrvFXaM/JtKH9ekOUUO6De72EsJ7qOuxWwl1WgoALA8b4tRs0tiw==} dev: false /@dydxprotocol/v4-client-js@0.36.1: diff --git a/src/constants/abacus.ts b/src/constants/abacus.ts index 592cb33..4e761e3 100644 --- a/src/constants/abacus.ts +++ b/src/constants/abacus.ts @@ -59,16 +59,6 @@ export const TransactionType = Abacus.exchange.dydx.abacus.protocols.Transaction const transactionTypes = [...TransactionType.values()] as const; export type TransactionTypes = (typeof transactionTypes)[number]; -export type NetworkConfig = { - chainId: string; - indexerUrl: string; - indexerSocketUrl: string; - validatorUrl: string; - faucetUrl?: string | null; -}; - -export type ConnectNetworkEvent = CustomEvent>; - // ------ State ------ export type AbacusApiState = Abacus.exchange.dydx.abacus.state.manager.ApiState; export const AbacusApiStatus = Abacus.exchange.dydx.abacus.state.manager.ApiStatus; @@ -267,3 +257,20 @@ export const TRADE_TYPES: Record< [AbacusOrderType.liquidation.name]: null, [AbacusOrderType.trailingStop.name]: null, }; + +// Custom types involving Abacus + +export type NetworkConfig = Partial<{ + indexerUrl: Nullable; + websocketUrl: Nullable; + validatorUrl: Nullable; + chainId: Nullable; + faucetUrl: Nullable; + USDC_DENOM: Nullable; + USDC_DECIMALS: Nullable; + USDC_GAS_DENOM: Nullable; + CHAINTOKEN_DENOM: Nullable; + CHAINTOKEN_DECIMALS: Nullable; +}>; + +export type ConnectNetworkEvent = CustomEvent>; diff --git a/src/hooks/useCurrentMarketId.ts b/src/hooks/useCurrentMarketId.ts index 087ef9c..6026c88 100644 --- a/src/hooks/useCurrentMarketId.ts +++ b/src/hooks/useCurrentMarketId.ts @@ -44,6 +44,9 @@ export const useCurrentMarketId = () => { }, [validId]); useEffect(() => { - abacusStateManager.setMarket(marketId ?? DEFAULT_MARKETID); - }, [selectedNetwork, marketId]); + // Check for marketIds otherwise Abacus will silently fail its isMarketValid check + if (marketIds) { + abacusStateManager.setMarket(marketId ?? DEFAULT_MARKETID); + } + }, [selectedNetwork, marketIds, marketId]); }; diff --git a/src/hooks/useDydxClient.tsx b/src/hooks/useDydxClient.tsx index b8202ff..bcecdbb 100644 --- a/src/hooks/useDydxClient.tsx +++ b/src/hooks/useDydxClient.tsx @@ -13,7 +13,7 @@ import { import type { ResolutionString } from 'public/tradingview/charting_library'; -import type { NetworkConfig, ConnectNetworkEvent } from '@/constants/abacus'; +import type { ConnectNetworkEvent, NetworkConfig } from '@/constants/abacus'; import { type Candle, RESOLUTION_MAP } from '@/constants/candles'; import { getSelectedNetwork } from '@/state/appSelectors'; @@ -33,11 +33,12 @@ export const DydxProvider = ({ ...props }) => ( export const useDydxClient = () => useContext(DydxContext); const useDydxClientContext = () => { + const [isConnected, setIsConnected] = useState(false); // ------ Network ------ // const selectedNetwork = useSelector(getSelectedNetwork); - const [networkConfig, setNetworkConfig] = useState>(); + const [networkConfig, setNetworkConfig] = useState(); useEffect(() => { const onConnectNetwork = (event: ConnectNetworkEvent) => setNetworkConfig(event.detail); @@ -57,14 +58,14 @@ const useDydxClientContext = () => { if ( networkConfig?.chainId && networkConfig?.indexerUrl && - networkConfig?.indexerSocketUrl && + networkConfig?.websocketUrl && networkConfig?.validatorUrl ) { try { const initializedClient = await CompositeClient.connect( new Network( selectedNetwork, - new IndexerConfig(networkConfig.indexerUrl, networkConfig.indexerSocketUrl), + new IndexerConfig(networkConfig.indexerUrl, networkConfig.websocketUrl), new ValidatorConfig(networkConfig.validatorUrl, networkConfig.chainId, { broadcastPollIntervalMs: 3_000, broadcastTimeoutMs: 60_000, @@ -72,11 +73,14 @@ const useDydxClientContext = () => { ) ); setCompositeClient(initializedClient); + setIsConnected(true); } catch (error) { log('useDydxClient/initializeCompositeClient', error); + setIsConnected(false); } } else { setCompositeClient(undefined); + setIsConnected(false); } if (networkConfig?.faucetUrl) { @@ -209,6 +213,7 @@ const useDydxClientContext = () => { networkConfig, compositeClient, faucetClient, + isConnected, // Wallet Methods getWalletFromEvmSignature, diff --git a/src/lib/abacus/dydxChainTransactions.ts b/src/lib/abacus/dydxChainTransactions.ts index e82a3d0..45fc8a4 100644 --- a/src/lib/abacus/dydxChainTransactions.ts +++ b/src/lib/abacus/dydxChainTransactions.ts @@ -61,18 +61,17 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { } async connectNetwork( - indexerUrl: string, - indexerSocketUrl: string, - validatorUrl: string, - chainId: string, - faucetUrl: Nullable | undefined, + paramsInJson: Nullable, callback: (p0: Nullable) => void ): Promise { try { + const parsedParams = paramsInJson ? JSON.parse(paramsInJson) : {}; + const { indexerUrl, websocketUrl, validatorUrl, chainId } = parsedParams; + const compositeClient = await CompositeClient.connect( new Network( chainId, - new IndexerConfig(indexerUrl, indexerSocketUrl), + new IndexerConfig(indexerUrl, websocketUrl), new ValidatorConfig(validatorUrl, chainId, { broadcastPollIntervalMs: 3_000, broadcastTimeoutMs: 60_000, @@ -84,13 +83,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { // Dispatch custom event to notify other parts of the app that the network has been connected const customEvent = new CustomEvent('abacus:connectNetwork', { - detail: { - indexerUrl, - indexerSocketUrl, - validatorUrl, - chainId, - faucetUrl, - }, + detail: parsedParams, }); globalThis.dispatchEvent(customEvent); @@ -99,9 +92,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { this.store?.dispatch( openDialog({ type: DialogTypes.ExchangeOffline, dialogProps: { preventClose: true } }) ); - log('DydxChainTransactions/connectNetwork', error); - return; } } @@ -251,7 +242,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { const msg = compositeClient.withdrawFromSubaccountMessage(subaccountClient, amount); resolve([msg]); - }), + }) ); const parsedTx = this.parseToPrimitives(tx); @@ -266,7 +257,9 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { } } - async simulateTransferNativeTokenTransaction(params: HumanReadableTransferPayload): Promise { + async simulateTransferNativeTokenTransaction( + params: HumanReadableTransferPayload + ): Promise { if (!this.compositeClient || !this.localWallet) { throw new Error('Missing compositeClient or localWallet'); } @@ -289,7 +282,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { resolve([msg]); }), - GAS_PRICE_DYDX_DENOM, + GAS_PRICE_DYDX_DENOM ); const parsedTx = this.parseToPrimitives(tx); @@ -397,9 +390,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { 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 accountBalances = + await this.compositeClient?.validatorClient.get.getAccountBalances( + this.localWallet.address + ); const parsedAccountBalances = this.parseToPrimitives(accountBalances); callback(JSON.stringify(parsedAccountBalances)); break;