Compare commits

..
Author SHA1 Message Date
Bill He dc037c1d63 add comments 2024-01-23 14:46:44 -08:00
Bill He 1776f9183b Upgrade v4-client and @cosmjs packages 2024-01-23 14:44:45 -08:00
Bill e93850484b CCTP deposit/withdraw to throw error if nobleClient is not initialized (#215)
* CCTP deposit/withdraw to throw error if nobleClient is not initialized

* update error str
2024-01-22 09:55:26 -08:00
aleka 521b6d6135 test flag for sign in option (#236) 2024-01-17 16:22:17 -08:00
aleka 94772bf4dc bump abacus to remove base position notional (#235) 2024-01-17 15:52:02 -08:00
18 changed files with 462 additions and 1120 deletions
+8 -10
View File
@@ -33,19 +33,17 @@
"packageManager": "pnpm@8.6.6",
"dependencies": {
"@0xsquid/sdk": "^1.10.0",
"@cosmjs/amino": "^0.31.0",
"@cosmjs/crypto": "^0.31.0",
"@cosmjs/encoding": "^0.31.0",
"@cosmjs/proto-signing": "^0.31.0",
"@cosmjs/stargate": "^0.31.0",
"@cosmjs/tendermint-rpc": "^0.31.0",
"@dydxprotocol/v4-abacus": "^1.2.4",
"@dydxprotocol/v4-client-js": "^1.0.11",
"@cosmjs/amino": "^0.32.1",
"@cosmjs/crypto": "^0.32.1",
"@cosmjs/encoding": "^0.32.1",
"@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.2.5",
"@dydxprotocol/v4-client-js": "^1.0.14",
"@dydxprotocol/v4-localization": "^1.1.11",
"@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3",
"@privy-io/react-auth": "^1.53.0",
"@privy-io/wagmi-connector": "^0.1.12",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-collapsible": "^1.0.3",
+400 -992
View File
File diff suppressed because it is too large Load Diff
+1 -9
View File
@@ -2,9 +2,6 @@ import { lazy, Suspense } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import styled, { AnyStyledComponent, css } from 'styled-components';
import { WagmiConfig } from 'wagmi';
import type { PrivyClientConfig } from '@privy-io/react-auth';
import { PrivyProvider } from '@privy-io/react-auth';
import { PrivyWagmiConnector } from '@privy-io/wagmi-connector';
import { QueryClient, QueryClientProvider } from 'react-query';
import { GrazProvider } from 'graz';
@@ -35,7 +32,7 @@ import { NotificationsToastArea } from '@/layout/NotificationsToastArea';
import { DialogManager } from '@/layout/DialogManager';
import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog';
import { config, privyConfig } from '@/lib/wagmi';
import { config } from '@/lib/wagmi';
import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
@@ -123,13 +120,8 @@ const wrapProvider = (Component: React.ComponentType<any>, props?: any) => {
};
const providers = [
wrapProvider(PrivyProvider, {
appId: import.meta.env.VITE_PRIVY_APP_ID,
config: privyConfig,
}),
wrapProvider(QueryClientProvider, { client: queryClient }),
wrapProvider(GrazProvider),
wrapProvider(PrivyWagmiConnector, { wagmiChainsConfig: config }),
wrapProvider(WagmiConfig, { config }),
wrapProvider(LocaleProvider),
wrapProvider(RestrictionProvider),
-11
View File
@@ -31,7 +31,6 @@ import { DydxNetwork, ENVIRONMENT_CONFIG_MAP } from './networks';
export enum WalletConnectionType {
CoinbaseWalletSdk = 'coinbaseWalletSdk',
CosmosSigner = 'CosmosSigner',
Privy = 'Privy',
InjectedEip1193 = 'injectedEip1193',
WalletConnect2 = 'walletConnect2',
}
@@ -69,9 +68,6 @@ export const walletConnectionTypes: Record<WalletConnectionType, WalletConnectio
[WalletConnectionType.CosmosSigner]: {
name: 'CosmosSigner',
},
[WalletConnectionType.Privy]: {
name: 'Privy',
},
};
// Wallets
@@ -94,7 +90,6 @@ export enum WalletType {
WalletConnect2 = 'WALLETCONNECT_2',
// TestWallet = 'TEST_WALLET',
OtherWallet = 'OTHER_WALLET',
Privy = 'PRIVY',
}
const WALLET_CONNECT_EXPLORER_RECOMMENDED_WALLETS = {
@@ -248,12 +243,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: KeplrIcon,
connectionTypes: [WalletConnectionType.CosmosSigner],
},
[WalletType.Privy]: {
type: WalletType.Privy,
stringKey: STRING_KEYS.KEPLR,
icon: GenericWalletIcon,
connectionTypes: [WalletConnectionType.Privy],
},
};
// Injected EIP-1193 Providers
+3 -39
View File
@@ -1,19 +1,13 @@
import { useCallback, useContext, createContext, useEffect, useState, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import { AES, enc } from 'crypto-js';
import { NOBLE_BECH32_PREFIX, LocalWallet, type Subaccount } from '@dydxprotocol/v4-client-js';
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
import { DialogTypes } from '@/constants/dialogs';
import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage';
import {
DydxAddress,
EvmAddress,
PrivateInformation,
WalletConnectionType,
getSignTypedData,
} from '@/constants/wallets';
import { DydxAddress, EvmAddress, PrivateInformation } from '@/constants/wallets';
import { setOnboardingState, setOnboardingGuard } from '@/state/account';
import { forceOpenDialog } from '@/state/dialogs';
@@ -26,11 +20,6 @@ import { useLocalStorage } from './useLocalStorage';
import { useRestrictions } from './useRestrictions';
import { useWalletConnection } from './useWalletConnection';
import { useSignTypedData } from 'wagmi';
import { getSelectedNetwork } from '@/state/appSelectors';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { usePrivy } from '@privy-io/react-auth';
const AccountsContext = createContext<ReturnType<typeof useAccountsContext> | undefined>(undefined);
AccountsContext.displayName = 'Accounts';
@@ -187,21 +176,6 @@ const useAccountsContext = () => {
}
}, [evmAddress, dydxAddress]);
// 1. Switch network
const selectedNetwork = useSelector(getSelectedNetwork);
const chainId = Number(ENVIRONMENT_CONFIG_MAP[selectedNetwork].ethereumChainId);
const signTypedData = getSignTypedData(selectedNetwork);
const { signTypedDataAsync } = useSignTypedData({
...signTypedData,
domain: {
...signTypedData.domain,
chainId,
},
});
const { ready, authenticated } = usePrivy();
useEffect(() => {
(async () => {
if (connectedDydxAddress && signerGraz) {
@@ -218,17 +192,7 @@ const useAccountsContext = () => {
const evmDerivedAccount = evmDerivedAddresses[evmAddress];
if (walletConnectionType === WalletConnectionType.Privy && authenticated && ready) {
try {
const signature = await signTypedDataAsync();
await setWalletFromEvmSignature(signature);
dispatch(setOnboardingState(OnboardingState.AccountConnected));
} catch (error) {
log('useAccounts/decryptSignature', error);
forgetEvmSignature();
}
} else if (evmDerivedAccount?.encryptedSignature) {
if (evmDerivedAccount?.encryptedSignature) {
try {
const signature = decryptSignature(evmDerivedAccount.encryptedSignature);
-1
View File
@@ -21,7 +21,6 @@ export const useDisplayedWallets = () => {
// WalletType.BitKeep,
// WalletType.Coin98,
WalletType.Privy,
WalletType.OtherWallet,
].filter(isTruthy);
};
+2 -13
View File
@@ -1,9 +1,5 @@
import { useCallback, useEffect, useMemo } from 'react';
import { useNetwork, useSwitchNetwork } from 'wagmi';
import { useSwitchNetwork as useSwitchNetworkPrivy } from '@privy-io/wagmi-connector';
import { WalletConnectionType } from '@/constants/wallets';
import { useWalletConnection } from './useWalletConnection';
export const useMatchingEvmNetwork = ({
chainId,
@@ -15,10 +11,7 @@ export const useMatchingEvmNetwork = ({
onError?: (error: Error) => void;
}) => {
const { chain } = useNetwork();
const { walletConnectionType } = useWalletConnection();
const { isLoading, switchNetworkAsync } = useSwitchNetwork({ onError });
const { isLoading: isLoadingPrivy, switchNetworkAsync: switchNetworkAsyncPrivy } =
useSwitchNetworkPrivy({ onError });
// If chainId is not a number, we can assume it is a non EVM compatible chain
const isMatchingNetwork = useMemo(
@@ -28,11 +21,7 @@ export const useMatchingEvmNetwork = ({
const matchNetwork = useCallback(async () => {
if (!isMatchingNetwork) {
if (walletConnectionType === WalletConnectionType.Privy) {
await switchNetworkAsyncPrivy?.(Number(chainId));
} else {
await switchNetworkAsync?.(Number(chainId));
}
await switchNetworkAsync?.(Number(chainId));
}
}, [chainId, chain]);
@@ -45,6 +34,6 @@ export const useMatchingEvmNetwork = ({
return {
isMatchingNetwork,
matchNetwork,
isSwitchingNetwork: isLoading || isLoadingPrivy,
isSwitchingNetwork: isLoading,
};
};
+7 -1
View File
@@ -198,7 +198,13 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
);
const ibcMsg: EncodeObject = {
typeUrl: transaction.msgTypeUrl,
value: transaction.msg,
value: {
...transaction.msg,
timeoutTimestamp: transaction.msg.timeoutTimestamp
// Squid returns timeoutTimestamp as Long, but the signer expects BigInt
? BigInt(Long.fromValue(transaction.msg.timeoutTimestamp).toString())
: undefined,
},
};
return await compositeClient.send(
+1 -11
View File
@@ -1,6 +1,5 @@
import { useCallback, useEffect, useState, useMemo } from 'react';
import { useSelector } from 'react-redux';
import { usePrivy, useLogout } from '@privy-io/react-auth';
import { LocalStorageKey } from '@/constants/localStorage';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
@@ -105,10 +104,8 @@ export const useWalletConnection = () => {
[walletConnectConfig, walletType, walletConnectionType]
);
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector });
const { connectAsync: connectWagmi } = useConnectWagmi({ connector: wagmiConnector })
const { suggestAndConnect: connectGraz } = useConnectGraz();
const { login, ready, authenticated } = usePrivy();
const { logout } = useLogout();
const connectWallet = useCallback(
async ({ walletType }: { walletType: WalletType }) => {
@@ -117,12 +114,6 @@ export const useWalletConnection = () => {
try {
if (!walletConnection) {
throw new Error('Onboarding: No wallet connection found.');
} else if (walletConnection.type === WalletConnectionType.Privy) {
console.log({ isConnectedWagmi, authenticated, ready });
if (!isConnectedWagmi && !authenticated && ready) {
login();
}
} else if (walletConnection.type === WalletConnectionType.CosmosSigner) {
const cosmosWalletType = {
[WalletType.Keplr as string]: CosmosWalletType.KEPLR,
@@ -174,7 +165,6 @@ export const useWalletConnection = () => {
if (isConnectedWagmi) await disconnectWagmi();
if (isConnectedGraz) await disconnectGraz();
if (authenticated) await logout();
}, [isConnectedGraz, isConnectedWagmi]);
// Wallet selection
+22 -2
View File
@@ -56,6 +56,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
this.store = undefined;
}
get isNobleClientConnected(): boolean {
return this.nobleClient?.isConnected ?? false;
}
setStore(store: RootStore): void {
this.store = store;
}
@@ -169,6 +173,10 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
return parsedObj as T;
}
if (typeof x === 'bigint') {
return x.toString() as T;
}
throw new Error(`Unsupported data type: ${typeof x}`);
}
@@ -359,7 +367,13 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
try {
const ibcMsg = {
typeUrl: params.msgTypeUrl, // '/ibc.applications.transfer.v1.MsgTransfer',
value: params.msg,
value: {
...params.msg,
timeoutTimestamp: params.msg.timeoutTimestamp
// Squid returns timeoutTimestamp as Long, but the signer expects BigInt
? BigInt(Long.fromValue(params.msg.timeoutTimestamp).toString())
: undefined,
},
};
const fee = await this.nobleClient.simulateTransaction([ibcMsg]);
@@ -409,7 +423,13 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol {
);
const ibcMsg: EncodeObject = {
typeUrl: parsedIbcPayload.msgTypeUrl,
value: parsedIbcPayload.msg,
value: {
...parsedIbcPayload.msg,
timeoutTimestamp: parsedIbcPayload.msg.timeoutTimestamp
// Squid returns timeoutTimestamp as Long, but the signer expects BigInt
? BigInt(Long.fromValue(parsedIbcPayload.msg.timeoutTimestamp).toString())
: undefined,
},
};
const tx = await this.compositeClient.send(
+4 -4
View File
@@ -11,16 +11,16 @@ class TestFlags {
const params = new URLSearchParams(queryParamsString);
for (const [key, value] of params) {
this.queryParams[key] = value;
this.queryParams[key.toLowerCase()] = value;
}
}
get displayInitializingMarkets() {
return !!this.queryParams.displayInitializingMarkets;
return !!this.queryParams.displayinitializingmarkets;
}
get withCCTP() {
return !!this.queryParams.withCCTP;
get showMobileSignInOption() {
return !!this.queryParams.mobilesignin;
}
}
-11
View File
@@ -1,6 +1,5 @@
import { createConfig, configureChains, mainnet, Chain } from 'wagmi';
import { goerli } from 'wagmi/chains';
import type { PrivyClientConfig } from '@privy-io/react-auth';
import {
arbitrum,
@@ -86,16 +85,6 @@ export const WAGMI_SUPPORTED_CHAINS: Chain[] = [
kava,
];
export const privyConfig: PrivyClientConfig = {
embeddedWallets: {
createOnLogin: 'users-without-wallets',
requireUserPasswordOnCreate: true,
noPromptOnSignature: true,
},
loginMethods: ['email', 'sms', 'twitter'],
defaultChain: sepolia
};
const { chains, publicClient, webSocketPublicClient } = configureChains(
WAGMI_SUPPORTED_CHAINS,
[
-6
View File
@@ -62,12 +62,6 @@ export const getWalletConnection = ({
type: WalletConnectionType.CosmosSigner,
};
}
case WalletConnectionType.Privy: {
return {
type: WalletConnectionType.Privy,
};
}
}
}
};
-1
View File
@@ -29,7 +29,6 @@ export const MarketDetails: React.FC = () => {
if (!configs) return null;
const {
basePositionNotional,
tickSize,
stepSize,
initialMarginFraction,
@@ -56,11 +56,7 @@ export const ChooseWallet = () => {
slotLeft={<Styled.Icon iconComponent={wallets[walletType].icon} />}
size={ButtonSize.Small}
>
<div>
{walletType !== WalletType.Privy && import.meta.env.VITE_PRIVY_APP_ID
? stringGetter({ key: wallets[walletType].stringKey })
: 'Socials (Email, SMS, etc.)'}
</div>
<div>{stringGetter({ key: wallets[walletType].stringKey })}</div>
</Styled.WalletButton>
))}
</Styled.Wallets>
@@ -235,6 +235,10 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
throw new Error('Missing request payload');
}
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
throw new Error('Noble RPC endpoint unaccessible');
}
setIsLoading(true);
await validateTokenApproval();
@@ -148,6 +148,10 @@ export const WithdrawForm = () => {
throw new Error('Invalid request payload');
}
if (isCctp && !abacusStateManager.chainTransactions.isNobleClientConnected) {
throw new Error('Noble RPC endpoint unaccessible');
}
setIsLoading(true);
setError(undefined);
+5 -4
View File
@@ -10,6 +10,9 @@ import { STRING_KEYS, StringGetterFunction, TOOLTIP_STRING_KEYS } from '@/consta
import { isMainnet } from '@/constants/networks';
import { DydxChainAsset, wallets } from '@/constants/wallets';
import { layoutMixins } from '@/styles/layoutMixins';
import { headerMixins } from '@/styles/headerMixins';
import {
useAccounts,
useBreakpoints,
@@ -35,10 +38,8 @@ import { getOnboardingState, getSubaccount } from '@/state/accountSelectors';
import { isTruthy } from '@/lib/isTruthy';
import { truncateAddress } from '@/lib/wallet';
import { layoutMixins } from '@/styles/layoutMixins';
import { headerMixins } from '@/styles/headerMixins';
import { MustBigNumber } from '@/lib/numbers';
import { testFlags } from '@/lib/testFlags';
export const AccountMenu = () => {
const stringGetter = useStringGetter();
@@ -178,7 +179,7 @@ export const AccountMenu = () => {
},
...(onboardingState === OnboardingState.AccountConnected && hdKey
? [
!isMainnet && {
(!isMainnet || testFlags.showMobileSignInOption) && {
value: 'MobileQrSignIn',
icon: <Icon iconName={IconName.Qr} />,
label: stringGetter({ key: STRING_KEYS.TITLE_SIGN_INTO_MOBILE }),