fix(trading): usdt approvals (#5939)

This commit is contained in:
Matthew Russell 2024-03-07 14:21:31 +00:00 committed by GitHub
parent 654dd1e7b0
commit 05b39e2c08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 53 additions and 20 deletions

View File

@ -62,3 +62,10 @@ export const DENY_LIST: Record<string, string[]> = {
'fdf0ec118d98393a7702cf72e46fc87ad680b152f64b2aac59e093ac2d688fbb', 'fdf0ec118d98393a7702cf72e46fc87ad680b152f64b2aac59e093ac2d688fbb',
], ],
}; };
// We need a record of USDT on mainnet as it needs special handling for
// deposits and approvals due to the contract not conforming exactly
// to ERC20
export const USDT_ID = {
MAINNET: 'bf1e88d19db4b3ca0d1d5bdb73718a01686b18cf731ca26adedf3c8b83802bba',
} as const;

View File

@ -1,5 +1,9 @@
import type { Asset } from '@vegaprotocol/assets'; import { USDT_ID, type Asset } from '@vegaprotocol/assets';
import { EtherscanLink } from '@vegaprotocol/environment'; import {
EtherscanLink,
Networks,
useEnvironment,
} from '@vegaprotocol/environment';
import { Intent, Notification } from '@vegaprotocol/ui-toolkit'; import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { import {
formatNumber, formatNumber,
@ -15,7 +19,7 @@ import { useT } from './use-t';
interface ApproveNotificationProps { interface ApproveNotificationProps {
isActive: boolean; isActive: boolean;
selectedAsset?: Asset; selectedAsset?: Asset;
onApprove: () => void; onApprove: (amount?: string) => void;
approved: boolean; approved: boolean;
balances: DepositBalances | null; balances: DepositBalances | null;
amount: string; amount: string;
@ -33,6 +37,7 @@ export const ApproveNotification = ({
approveTxId, approveTxId,
intent = Intent.Warning, intent = Intent.Warning,
}: ApproveNotificationProps) => { }: ApproveNotificationProps) => {
const { VEGA_ENV } = useEnvironment();
const t = useT(); const t = useT();
const tx = useEthTransactionStore((state) => { const tx = useEthTransactionStore((state) => {
return state.transactions.find((t) => t?.id === approveTxId); return state.transactions.find((t) => t?.id === approveTxId);
@ -64,28 +69,45 @@ export const ApproveNotification = ({
text: t('Approve {{assetSymbol}}', { text: t('Approve {{assetSymbol}}', {
assetSymbol: selectedAsset?.symbol, assetSymbol: selectedAsset?.symbol,
}), }),
action: onApprove, action: () => onApprove(),
dataTestId: 'approve-submit', dataTestId: 'approve-submit',
}} }}
/> />
</div> </div>
); );
let message = t('Approve again to deposit more than {{allowance}}', {
allowance: formatNumber(balances.allowance.toString()),
});
const buttonProps = {
size: 'small' as const,
text: t('Approve {{assetSymbol}}', {
assetSymbol: selectedAsset?.symbol,
}),
action: () => onApprove(),
dataTestId: 'reapprove-submit',
};
if (VEGA_ENV === Networks.MAINNET && selectedAsset.id === USDT_ID[VEGA_ENV]) {
message = t(
'USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.',
{
allowance: formatNumber(balances.allowance.toString()),
}
);
buttonProps.text = t('Revoke {{assetSymbol}} approval', {
assetSymbol: selectedAsset?.symbol,
});
buttonProps.action = () => onApprove('0');
}
const reApprovePrompt = ( const reApprovePrompt = (
<div className="mb-4"> <div className="mb-4">
<Notification <Notification
intent={intent} intent={intent}
testId="reapprove-default" testId="reapprove-default"
message={t('Approve again to deposit more than {{allowance}}', { message={message}
allowance: formatNumber(balances.allowance.toString()), buttonProps={buttonProps}
})}
buttonProps={{
size: 'small',
text: t('Approve {{assetSymbol}}', {
assetSymbol: selectedAsset?.symbol,
}),
action: onApprove,
dataTestId: 'reapprove-submit',
}}
/> />
</div> </div>
); );

View File

@ -58,7 +58,7 @@ export interface DepositFormProps {
onSelectAsset: (assetId: string) => void; onSelectAsset: (assetId: string) => void;
handleAmountChange: (amount: string) => void; handleAmountChange: (amount: string) => void;
onDisconnect: () => void; onDisconnect: () => void;
submitApprove: () => void; submitApprove: (amount?: string) => void;
approveTxId: number | null; approveTxId: number | null;
submitFaucet: () => void; submitFaucet: () => void;
faucetTxId: number | null; faucetTxId: number | null;
@ -423,8 +423,8 @@ export const DepositForm = ({
isActive={isActive} isActive={isActive}
approveTxId={approveTxId} approveTxId={approveTxId}
selectedAsset={selectedAsset} selectedAsset={selectedAsset}
onApprove={() => { onApprove={(amount) => {
submitApprove(); submitApprove(amount);
setApproveNotificationIntent(Intent.Warning); setApproveNotificationIntent(Intent.Warning);
}} }}
balances={balances} balances={balances}

View File

@ -35,11 +35,11 @@ export const useSubmitApproval = (
reset: () => { reset: () => {
setId(null); setId(null);
}, },
perform: () => { perform: (amount?: string) => {
if (!asset || !config) return; if (!asset || !config) return;
const id = createEthTransaction(contract, 'approve', [ const id = createEthTransaction(contract, 'approve', [
config?.collateral_bridge_contract.address, config?.collateral_bridge_contract.address,
MaxUint256.toString(), amount ? amount : MaxUint256.toString(),
]); ]);
setId(id); setId(id);
}, },

View File

@ -4,6 +4,7 @@
"Approval failed": "Approval failed", "Approval failed": "Approval failed",
"Approve {{assetSymbol}}": "Approve {{assetSymbol}}", "Approve {{assetSymbol}}": "Approve {{assetSymbol}}",
"Approve again to deposit more than {{allowance}}": "Approve again to deposit more than {{allowance}}", "Approve again to deposit more than {{allowance}}": "Approve again to deposit more than {{allowance}}",
"USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.": "USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.",
"Asset": "Asset", "Asset": "Asset",
"Balance available": "Balance available", "Balance available": "Balance available",
"Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet": "Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet", "Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet": "Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet",
@ -23,6 +24,7 @@
"Please select": "Please select", "Please select": "Please select",
"Please select an asset": "Please select an asset", "Please select an asset": "Please select an asset",
"Remaining deposit allowance": "Remaining deposit allowance", "Remaining deposit allowance": "Remaining deposit allowance",
"Revoke {{assetSymbol}} approval": "Revoke {{assetSymbol}} approval",
"Select from wallet": "Select from wallet", "Select from wallet": "Select from wallet",
"The {{symbol}} faucet is not available at this time": "The {{symbol}} faucet is not available at this time", "The {{symbol}} faucet is not available at this time": "The {{symbol}} faucet is not available at this time",
"The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.": "The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.", "The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.": "The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.",

View File

@ -27,6 +27,7 @@ export const useEthTransactionManager = () => {
confirmations: 0, confirmations: 0,
notify: true, notify: true,
}); });
const { const {
contract, contract,
methodName, methodName,
@ -44,6 +45,7 @@ export const useEthTransactionManager = () => {
) { ) {
throw new Error('method not found on contract'); throw new Error('method not found on contract');
} }
await contract.contract.callStatic[methodName](...args); await contract.contract.callStatic[methodName](...args);
} catch (err) { } catch (err) {
update(transaction.id, { update(transaction.id, {