address comments

This commit is contained in:
Bill He
2023-09-05 10:59:44 -07:00
parent 9f32c6b0f2
commit 1608a27e3e
9 changed files with 104 additions and 62 deletions
+1 -1
View File
@@ -37,7 +37,7 @@
"@cosmjs/proto-signing": "^0.31.0",
"@cosmjs/stargate": "^0.31.0",
"@cosmjs/tendermint-rpc": "^0.31.0",
"@dydxprotocol/abacus": "^0.4.6",
"@dydxprotocol/abacus": "^0.4.7",
"@dydxprotocol/v4-client-js": "^0.32.0",
"@dydxprotocol/v4-localization": "^0.0.25",
"@ethersproject/providers": "^5.7.2",
+4 -4
View File
@@ -27,8 +27,8 @@ dependencies:
specifier: ^0.31.0
version: 0.31.0
'@dydxprotocol/abacus':
specifier: ^0.4.6
version: 0.4.6
specifier: ^0.4.7
version: 0.4.7
'@dydxprotocol/v4-client-js':
specifier: ^0.32.0
version: 0.32.0
@@ -1145,8 +1145,8 @@ packages:
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
dev: true
/@dydxprotocol/abacus@0.4.6:
resolution: {integrity: sha512-nvF9B1JuWzsnrPtQ/mKo06XWuqFc9fy6TEFcFwlIGGbxKortod7fSDj9sEZGKGdRyIj5wvl7H/Rgh+dlywO+aQ==}
/@dydxprotocol/abacus@0.4.7:
resolution: {integrity: sha512-3c7Dx5H+KeXZYDpAOJs6fqxSNerKqNSD4tuMNn5F7RXAPWUOU8ADQHAFPnrP1PgTxPjfZBZQzLIziKpyXww4NQ==}
dev: false
/@dydxprotocol/dydxjs@0.3.0:
+2 -2
View File
@@ -1,4 +1,4 @@
export const erc20 = [
[
{
"constant": true,
"inputs": [],
@@ -219,4 +219,4 @@ export const erc20 = [
"name": "Transfer",
"type": "event"
}
] as const;
]
+8 -4
View File
@@ -65,10 +65,14 @@ const useLocalNotificationsContext = () => {
fromChainId,
status: currentStatus,
} of transferNotifications) {
if (currentStatus && currentStatus?.squidTransactionStatus !== 'ongoing') continue;
const status = await squid?.getStatus({ transactionId: txHash, toChainId, fromChainId });
if (status) statuses[txHash] = status;
try {
if (currentStatus && currentStatus?.squidTransactionStatus !== 'ongoing') continue;
const status = await squid?.getStatus({ transactionId: txHash, toChainId, fromChainId });
if (status) statuses[txHash] = status;
} catch (error) {
console.error(error);
}
}
return statuses;
},
+4 -8
View File
@@ -1,17 +1,13 @@
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { TESTNET_CHAIN_ID } from '@dydxprotocol/v4-client-js';
import { Squid } from '@0xsquid/sdk';
import { DydxV4Network, isDydxV4Network } from '@/constants/networks';
import { CLIENT_NETWORK_CONFIGS, DydxV4Network, isDydxV4Network } from '@/constants/networks';
import { getSelectedNetwork } from '@/state/appSelectors';
const SQUID_BASE_URL: Record<DydxV4Network, string | undefined> = {
[DydxV4Network.V4Testnet2]: 'https://squid-api-git-feat-cosmos-maintestnet-0xsquid.vercel.app',
[DydxV4Network.V4Staging]: undefined,
[DydxV4Network.V4Local]: undefined,
[DydxV4Network.V4Mainnet]: 'https://api.0xsquid.com',
};
export const NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
const useSquidContext = () => {
const selectedNetwork = useSelector(getSelectedNetwork);
@@ -27,7 +23,7 @@ const useSquidContext = () => {
const squid = useMemo(
() =>
isDydxV4Network(selectedNetwork)
? new Squid({ baseUrl: SQUID_BASE_URL[selectedNetwork as DydxV4Network] })
? new Squid({ baseUrl: CLIENT_NETWORK_CONFIGS[selectedNetwork]?.endpoints['0xsquid'] })
: undefined,
[selectedNetwork]
);
+4 -1
View File
@@ -17,6 +17,7 @@ import {
useConnect as useConnectWagmi,
useAccount as useAccountWagmi,
useDisconnect as useDisconnectWagmi,
usePublicClient as usePublicClientWagmi,
useWalletClient as useWalletClientWagmi,
} from 'wagmi';
import {
@@ -42,6 +43,7 @@ export const useWalletConnection = () => {
defaultValue: undefined,
});
const { address: evmAddressWagmi, isConnected: isConnectedWagmi } = useAccountWagmi();
const publicClientWagmi = usePublicClientWagmi();
const { data: signerWagmi } = useWalletClientWagmi();
const { disconnectAsync: disconnectWagmi } = useDisconnectWagmi();
@@ -214,7 +216,8 @@ export const useWalletConnection = () => {
evmAddress,
evmAddressWagmi,
signerWagmi,
publicClientWagmi,
// Wallet connection (Cosmos)
dydxAddress,
dydxAddressGraz,
+1 -1
View File
@@ -34,7 +34,7 @@ export const TransferStatusToast = ({
const [secondsLeft, setSecondsLeft] = useState<number | undefined>();
const type = useMemo(
() => (status?.toChain?.chainData.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
() => (status?.toChain?.chainData?.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
[status]
);
+33 -36
View File
@@ -27,38 +27,17 @@ enum TransferStatusStep {
export const TransferStatusSteps = ({ status }: ElementProps) => {
const stringGetter = useStringGetter();
const type = useMemo(
() => (status?.toChain?.chainData.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
[status]
);
const currentStep = useMemo(() => {
const { currentStep, steps, type } = useMemo(() => {
const routeStatus = status?.routeStatus;
const fromChain = status?.fromChain?.chainData.chainId;
const toChain = status?.toChain?.chainData.chainId;
const fromChain = status?.fromChain?.chainData?.chainId;
const toChain = status?.toChain?.chainData?.chainId;
const type = toChain === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal';
if (!routeStatus?.length) return TransferStatusStep.FromChain;
const currentStatus = routeStatus[routeStatus?.length - 1];
if (currentStatus.chainId === toChain) {
return currentStatus.status !== 'success'
? TransferStatusStep.ToChain
: TransferStatusStep.Complete;
}
if (currentStatus.chainId === fromChain && currentStatus.status !== 'success') {
return TransferStatusStep.FromChain;
}
return TransferStatusStep.Bridge;
}, [status]);
const steps = useMemo(
() => [
const steps = [
{
label: stringGetter({
key: type === 'deposit' ? STRING_KEYS.INITIATED_DEPOSIT : STRING_KEYS.INITIATED_WITHDRAWAL,
key:
type === 'deposit' ? STRING_KEYS.INITIATED_DEPOSIT : STRING_KEYS.INITIATED_WITHDRAWAL,
}),
step: TransferStatusStep.FromChain,
link: status?.fromChain?.transactionUrl,
@@ -72,15 +51,35 @@ export const TransferStatusSteps = ({ status }: ElementProps) => {
label: stringGetter({
key: type === 'deposit' ? STRING_KEYS.DEPOSIT_TO_CHAIN : STRING_KEYS.WITHDRAW_TO_CHAIN,
params: {
CHAIN: status?.toChain?.chainData.chainName,
}
CHAIN: status?.toChain?.chainData?.chainName,
},
}),
step: TransferStatusStep.ToChain,
link: status?.toChain?.transactionUrl,
},
],
[status]
);
];
const currentStatus = routeStatus[routeStatus?.length - 1];
let currentStep = TransferStatusStep.Bridge;
if (!routeStatus?.length) {
currentStep = TransferStatusStep.FromChain;
} else if (currentStatus.chainId === toChain) {
currentStep =
currentStatus.status !== 'success'
? TransferStatusStep.ToChain
: TransferStatusStep.Complete;
} else if (currentStatus.chainId === fromChain && currentStatus.status !== 'success') {
currentStep = TransferStatusStep.FromChain;
}
return {
currentStep,
steps,
type,
};
}, [status, stringGetter]);
if (!status) return <LoadingDots size={3} />;
@@ -108,9 +107,7 @@ export const TransferStatusSteps = ({ status }: ElementProps) => {
</Styled.Label>
</Link>
) : (
<Styled.Label highlighted={currentStep >= step.step}>
{step.label}
</Styled.Label>
<Styled.Label highlighted={currentStep >= step.step}>{step.label}</Styled.Label>
)}
</Styled.row>
</Styled.Step>
@@ -3,8 +3,8 @@ 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 { ethers } from 'ethers';
import erc20 from '@/abi/erc20.json';
import { TransferInputField, TransferInputTokenResource, TransferType } from '@/constants/abacus';
import { AlertType } from '@/constants/alerts';
import { ButtonSize } from '@/constants/buttons';
@@ -14,6 +14,8 @@ import { NumberSign } from '@/constants/numbers';
import { useAccounts, useDebounce, useStringGetter } from '@/hooks';
import { useAccountBalance } from '@/hooks/useAccountBalance';
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
import { NATIVE_TOKEN_ADDRESS, useSquid } from '@/hooks/useSquid';
import { useWalletConnection } from '@/hooks/useWalletConnection';
import { layoutMixins } from '@/styles/layoutMixins';
import { formMixins } from '@/styles/formMixins';
@@ -49,7 +51,8 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
const [error, setError] = useState<Error | null>(null);
const [isLoading, setIsLoading] = useState(false);
const { signerWagmi } = useAccounts();
const { evmAddress, signerWagmi } = useAccounts();
const { publicClientWagmi } = useWalletConnection();
const { addTransferNotification } = useLocalNotifications();
@@ -68,6 +71,11 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
[token, resources]
);
const sourceChain = useMemo(
() => (chainIdStr ? resources?.chainResources?.get(chainIdStr) : undefined),
[chainId, resources]
);
const [fromAmount, setFromAmount] = useState('');
const [slippage, setSlippage] = useState(0.01); // 1% slippage
const debouncedAmount = useDebounce<string>(fromAmount, 500);
@@ -159,6 +167,36 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
}
}, [balance, setFromAmount]);
const validateTokenApproval = useCallback(async () => {
if (!signerWagmi || !publicClientWagmi) throw new Error('Missing signer');
if (!sourceToken?.address) throw new Error('Missing source token address');
if (!sourceChain?.rpc) throw new Error('Missing source chain rpc');
if (!requestPayload?.targetAddress) throw new Error('Missing target address');
if (!requestPayload?.value) throw new Error('Missing transaction value');
if (sourceToken?.address === NATIVE_TOKEN_ADDRESS) return;
const allowance = await publicClientWagmi.readContract({
address: sourceToken.address as `0x${string}`,
abi: erc20,
functionName: 'allowance',
args: [evmAddress as `0x${string}`, requestPayload.targetAddress as `0x${string}`]
});
const sourceAmountBN = BigInt(requestPayload.value)
if (sourceAmountBN > (allowance as bigint)) {
const { request } = await publicClientWagmi.simulateContract({
account: evmAddress,
address: sourceToken.address as `0x${string}`,
abi: erc20,
functionName: 'approve',
args: [requestPayload.targetAddress as `0x${string}`, sourceAmountBN],
})
await signerWagmi.writeContract(request);
}
}, [signerWagmi, sourceToken, sourceChain, requestPayload, publicClientWagmi]);
const onSubmit = useCallback(
async (e: FormEvent) => {
try {
@@ -179,20 +217,23 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
}
setIsLoading(true);
validateTokenApproval();
let tx = {
to: requestPayload.targetAddress as `0x${string}`,
data: requestPayload.data as `0x${string}`,
gasLimit: ethers.toBigInt(requestPayload.gasLimit),
gasLimit: BigInt(requestPayload.gasLimit),
value:
requestPayload.routeType !== 'SEND' ? ethers.toBigInt(requestPayload.value) : undefined,
requestPayload.routeType !== 'SEND' ? BigInt(requestPayload.value) : undefined,
};
const txHash = await signerWagmi.sendTransaction(tx);
onDeposit?.();
if (txHash) {
addTransferNotification({
txHash,
txHash: txHash,
toChainId: TESTNET_CHAIN_ID,
fromChainId: chainIdStr || undefined,
toAmount: summary?.usdcSize || undefined,
@@ -202,6 +243,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
setFromAmount('');
}
} catch (error) {
console.error(error);
setError(error);
} finally {
setIsLoading(false);