Compare commits

...

7 Commits

Author SHA1 Message Date
Bill He
fb21e27233
parse error message in abacus 2023-11-09 10:31:00 -08:00
Bill He
74958ea3af
disable slippage editor 2023-11-08 21:11:22 -08:00
Bill He
4c5737ff6b
fix max 2023-11-08 21:01:04 -08:00
Bill He
4bbb2ce89d
address comments 2023-11-08 20:50:34 -08:00
Bill He
9eb2bec10b
add dep 2023-11-08 14:00:15 -08:00
Bill He
af242d4f03
bump abacus 2023-11-08 13:35:00 -08:00
Bill He
534970d475
Handle squid route errors 2023-11-08 13:28:54 -08:00
8 changed files with 65 additions and 24 deletions

View File

@ -39,7 +39,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": "^1.0.19", "@dydxprotocol/v4-abacus": "^1.0.24",
"@dydxprotocol/v4-client-js": "^1.0.0", "@dydxprotocol/v4-client-js": "^1.0.0",
"@dydxprotocol/v4-localization": "^1.0.5", "@dydxprotocol/v4-localization": "^1.0.5",
"@ethersproject/providers": "^5.7.2", "@ethersproject/providers": "^5.7.2",

8
pnpm-lock.yaml generated
View File

@ -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: ^1.0.19 specifier: ^1.0.24
version: 1.0.19 version: 1.0.24
'@dydxprotocol/v4-client-js': '@dydxprotocol/v4-client-js':
specifier: ^1.0.0 specifier: ^1.0.0
version: 1.0.0 version: 1.0.0
@ -982,8 +982,8 @@ packages:
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==} resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
dev: true dev: true
/@dydxprotocol/v4-abacus@1.0.19: /@dydxprotocol/v4-abacus@1.0.24:
resolution: {integrity: sha512-XhvSHGr503gNwHWEiOYP7M2uYeLu+Qm4szpE5w5H6hWFCanSGz6zAsTbPuyPLtt7IE1gj5z8mlL9J3tw2AZROg==} resolution: {integrity: sha512-wDGSjkrc3Se6Ev7UTjPgJV7PiyzZSz2mJwOTZikLwH7W3k1iPYGQmaCd7TudFk8h2aSdlEwNsQBCf0sLoyvHaQ==}
dev: false dev: false
/@dydxprotocol/v4-client-js@1.0.0: /@dydxprotocol/v4-client-js@1.0.0:

View File

@ -56,13 +56,8 @@ class AbacusRest implements AbacusRestProtocol {
.then(async (response) => { .then(async (response) => {
const data = await response.text(); const data = await response.text();
if (response.ok) { callback(data, response.status);
callback(data, response.status);
} else {
// response not OK, call callback with null data and the status, this includes 400/500 status codes
callback(null, response.status);
}
try { try {
lastSuccessfulRestRequestByOrigin[new URL(url).origin] = Date.now(); lastSuccessfulRestRequestByOrigin[new URL(url).origin] = Date.now();
} catch {} } catch {}

View File

@ -2,7 +2,7 @@ import { type FormEvent, useCallback, useEffect, useMemo, useState } from 'react
import styled, { type AnyStyledComponent } from 'styled-components'; import styled, { type AnyStyledComponent } from 'styled-components';
import { type NumberFormatValues } from 'react-number-format'; import { type NumberFormatValues } from 'react-number-format';
import { shallowEqual, useSelector } from 'react-redux'; import { shallowEqual, useSelector } from 'react-redux';
import { parseUnits } from 'viem' import { parseUnits } from 'viem';
import erc20 from '@/abi/erc20.json'; import erc20 from '@/abi/erc20.json';
import { TransferInputField, TransferInputTokenResource, TransferType } from '@/constants/abacus'; import { TransferInputField, TransferInputTokenResource, TransferType } from '@/constants/abacus';
@ -65,6 +65,8 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
chain: chainIdStr, chain: chainIdStr,
resources, resources,
summary, summary,
errors: routeErrors,
errorMessage: routeErrorMessage,
} = useSelector(getTransferInputs, shallowEqual) || {}; } = useSelector(getTransferInputs, shallowEqual) || {};
const chainId = chainIdStr ? parseInt(chainIdStr) : undefined; const chainId = chainIdStr ? parseInt(chainIdStr) : undefined;
@ -97,7 +99,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
useEffect(() => { useEffect(() => {
const hasInvalidInput = const hasInvalidInput =
debouncedAmountBN.isNaN() || debouncedAmountBN.lte(0) || debouncedAmountBN.gte(balanceBN); debouncedAmountBN.isNaN() || debouncedAmountBN.lte(0) || debouncedAmountBN.gt(balanceBN);
abacusStateManager.setTransferValue({ abacusStateManager.setTransferValue({
value: hasInvalidInput ? 0 : debouncedAmount, value: hasInvalidInput ? 0 : debouncedAmount,
@ -171,7 +173,8 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
const validateTokenApproval = useCallback(async () => { const validateTokenApproval = useCallback(async () => {
if (!signerWagmi || !publicClientWagmi) throw new Error('Missing signer'); if (!signerWagmi || !publicClientWagmi) throw new Error('Missing signer');
if (!sourceToken?.address || !sourceToken.decimals) throw new Error('Missing source token address'); if (!sourceToken?.address || !sourceToken.decimals)
throw new Error('Missing source token address');
if (!sourceChain?.rpc) throw new Error('Missing source chain rpc'); if (!sourceChain?.rpc) throw new Error('Missing source chain rpc');
if (!requestPayload?.targetAddress) throw new Error('Missing target address'); if (!requestPayload?.targetAddress) throw new Error('Missing target address');
if (!requestPayload?.value) throw new Error('Missing transaction value'); if (!requestPayload?.value) throw new Error('Missing transaction value');
@ -181,11 +184,11 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
address: sourceToken.address as EvmAddress, address: sourceToken.address as EvmAddress,
abi: erc20, abi: erc20,
functionName: 'allowance', functionName: 'allowance',
args: [evmAddress as EvmAddress, requestPayload.targetAddress as EvmAddress] args: [evmAddress as EvmAddress, requestPayload.targetAddress as EvmAddress],
}); });
const sourceAmountBN = parseUnits(debouncedAmount, sourceToken.decimals); const sourceAmountBN = parseUnits(debouncedAmount, sourceToken.decimals);
if (sourceAmountBN > (allowance as bigint)) { if (sourceAmountBN > (allowance as bigint)) {
const { request } = await publicClientWagmi.simulateContract({ const { request } = await publicClientWagmi.simulateContract({
account: evmAddress, account: evmAddress,
@ -193,12 +196,12 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
abi: erc20, abi: erc20,
functionName: 'approve', functionName: 'approve',
args: [requestPayload.targetAddress as EvmAddress, sourceAmountBN], args: [requestPayload.targetAddress as EvmAddress, sourceAmountBN],
}) });
const approveTx = await signerWagmi.writeContract(request); const approveTx = await signerWagmi.writeContract(request);
await publicClientWagmi.waitForTransactionReceipt({ await publicClientWagmi.waitForTransactionReceipt({
hash: approveTx, hash: approveTx,
}) });
} }
}, [signerWagmi, sourceToken, sourceChain, requestPayload, publicClientWagmi]); }, [signerWagmi, sourceToken, sourceChain, requestPayload, publicClientWagmi]);
@ -228,8 +231,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
to: requestPayload.targetAddress as EvmAddress, to: requestPayload.targetAddress as EvmAddress,
data: requestPayload.data as EvmAddress, data: requestPayload.data as EvmAddress,
gasLimit: BigInt(requestPayload.gasLimit), gasLimit: BigInt(requestPayload.gasLimit),
value: value: requestPayload.routeType !== 'SEND' ? BigInt(requestPayload.value) : undefined,
requestPayload.routeType !== 'SEND' ? BigInt(requestPayload.value) : undefined,
}; };
const txHash = await signerWagmi.sendTransaction(tx); const txHash = await signerWagmi.sendTransaction(tx);
@ -287,6 +289,15 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
return parseWalletError({ error, stringGetter }).message; return parseWalletError({ error, stringGetter }).message;
} }
if (routeErrors) {
return routeErrorMessage
? stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: { ERROR_MESSAGE: routeErrorMessage },
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG });
}
if (fromAmount) { if (fromAmount) {
if (!chainId) { if (!chainId) {
return stringGetter({ key: STRING_KEYS.MUST_SPECIFY_CHAIN }); return stringGetter({ key: STRING_KEYS.MUST_SPECIFY_CHAIN });
@ -300,7 +311,16 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
} }
return undefined; return undefined;
}, [error, balance, chainId, fromAmount, sourceToken]); }, [
error,
routeErrors,
routeErrorMessage,
balance,
chainId,
fromAmount,
sourceToken,
stringGetter,
]);
const isDisabled = const isDisabled =
Boolean(errorMessage) || Boolean(errorMessage) ||

View File

@ -164,6 +164,7 @@ export const DepositButtonAndReceipt = ({
label: <span>{stringGetter({ key: STRING_KEYS.SLIPPAGE })}</span>, label: <span>{stringGetter({ key: STRING_KEYS.SLIPPAGE })}</span>,
value: ( value: (
<SlippageEditor <SlippageEditor
disabled
slippage={slippage} slippage={slippage}
setIsEditing={setIsEditingSlipapge} setIsEditing={setIsEditingSlipapge}
setSlippage={setSlippage} setSlippage={setSlippage}

View File

@ -24,11 +24,17 @@ type ElementProps = {
slippage: number; slippage: number;
setIsEditing?: Dispatch<SetStateAction<boolean>>; setIsEditing?: Dispatch<SetStateAction<boolean>>;
setSlippage: (slippage: number) => void; setSlippage: (slippage: number) => void;
disabled?: boolean;
}; };
export type SlippageEditorProps = ElementProps; export type SlippageEditorProps = ElementProps;
export const SlippageEditor = ({ slippage, setIsEditing, setSlippage }: SlippageEditorProps) => { export const SlippageEditor = ({
disabled,
slippage,
setIsEditing,
setSlippage,
}: SlippageEditorProps) => {
const percentSlippage = slippage * 100; const percentSlippage = slippage * 100;
const [slippageInputValue, setSlippageInputValue] = useState(percentSlippage.toString()); const [slippageInputValue, setSlippageInputValue] = useState(percentSlippage.toString());
const [editorState, setEditorState] = useState(EditorState.Viewing); const [editorState, setEditorState] = useState(EditorState.Viewing);
@ -80,6 +86,10 @@ export const SlippageEditor = ({ slippage, setIsEditing, setSlippage }: Slippage
} }
}; };
if (disabled) {
return <Output type={OutputType.Percent} value={slippage} />;
}
return ( return (
<Styled.WithConfirmationPopover <Styled.WithConfirmationPopover
open={editorState !== EditorState.Viewing} open={editorState !== EditorState.Viewing}

View File

@ -44,10 +44,10 @@ import { getTransferInputs } from '@/state/inputsSelectors';
import abacusStateManager from '@/lib/abacus'; import abacusStateManager from '@/lib/abacus';
import { MustBigNumber } from '@/lib/numbers'; import { MustBigNumber } from '@/lib/numbers';
import { log } from '@/lib/telemetry';
import { TokenSelectMenu } from './TokenSelectMenu'; import { TokenSelectMenu } from './TokenSelectMenu';
import { WithdrawButtonAndReceipt } from './WithdrawForm/WithdrawButtonAndReceipt'; import { WithdrawButtonAndReceipt } from './WithdrawForm/WithdrawButtonAndReceipt';
import { join } from 'path';
export const WithdrawForm = () => { export const WithdrawForm = () => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
@ -69,6 +69,8 @@ export const WithdrawForm = () => {
chain: chainIdStr, chain: chainIdStr,
address: toAddress, address: toAddress,
resources, resources,
errors: routeErrors,
errorMessage: routeErrorMessage,
} = useSelector(getTransferInputs, shallowEqual) || {}; } = useSelector(getTransferInputs, shallowEqual) || {};
const isValidAddress = toAddress && isAddress(toAddress); const isValidAddress = toAddress && isAddress(toAddress);
@ -281,6 +283,15 @@ export const WithdrawForm = () => {
}); });
} }
if (routeErrors) {
return routeErrorMessage
? stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: { ERROR_MESSAGE: routeErrorMessage },
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG });
}
if (!toAddress) return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ADDRESS }); if (!toAddress) return stringGetter({ key: STRING_KEYS.WITHDRAW_MUST_SPECIFY_ADDRESS });
if (sanctionedAddresses.has(toAddress)) if (sanctionedAddresses.has(toAddress))
@ -303,12 +314,15 @@ export const WithdrawForm = () => {
return undefined; return undefined;
}, [ }, [
error, error,
routeErrors,
routeErrorMessage,
freeCollateralBN, freeCollateralBN,
chainIdStr, chainIdStr,
debouncedAmountBN, debouncedAmountBN,
toToken, toToken,
toAddress, toAddress,
sanctionedAddresses, sanctionedAddresses,
stringGetter,
]); ]);
const isDisabled = const isDisabled =

View File

@ -147,6 +147,7 @@ export const WithdrawButtonAndReceipt = ({
label: <span>{stringGetter({ key: STRING_KEYS.SLIPPAGE })}</span>, label: <span>{stringGetter({ key: STRING_KEYS.SLIPPAGE })}</span>,
value: ( value: (
<SlippageEditor <SlippageEditor
disabled
slippage={slippage} slippage={slippage}
setIsEditing={setIsEditingSlipapge} setIsEditing={setIsEditingSlipapge}
setSlippage={setSlippage} setSlippage={setSlippage}