Skip to content

Commit

Permalink
[Wallet]: Add error message and retry for swap errors (MystenLabs#15549)
Browse files Browse the repository at this point in the history
## Description 

https://mysten.atlassian.net/browse/APPS-2049

![error-swap](https://github.com/MystenLabs/sui/assets/127577476/aaebbf2b-cdef-42d5-8ab4-2ac519a4e4e3)



## Test Plan 

How did you test the new or updated feature?

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
  • Loading branch information
plam-ml authored Jan 6, 2024
1 parent 394df08 commit 8e936a9
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 9 deletions.
6 changes: 5 additions & 1 deletion apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
import BigNumber from 'bignumber.js';

const MAX_COINS_PER_REQUEST = 10;
const ESTIMATE_RETRY_COUNT = 3;
const ESTIMATE_RETRY_COUNT = 10;

async function getCoinsByBalance({
coinType,
Expand All @@ -30,6 +30,7 @@ async function getCoinsByBalance({
let currentBalance = 0n;
let hasNextPage = true;
const coins = [];

const bigIntBalance = BigInt(new BigNumber(balance).integerValue(BigNumber.ROUND_UP).toString());

while (currentBalance < bigIntBalance && hasNextPage) {
Expand Down Expand Up @@ -224,6 +225,7 @@ export function useGetEstimate({
totalQuoteBalance,
baseConversionRate,
quoteConversionRate,
enabled,
}: {
accountCapId: string;
signer: WalletSigner | null;
Expand All @@ -236,6 +238,7 @@ export function useGetEstimate({
totalQuoteBalance: string;
baseConversionRate: number;
quoteConversionRate: number;
enabled?: boolean;
}) {
const walletFeeAddress = useDeepBookContext().walletFeeAddress;
const queryClient = useQueryClient();
Expand Down Expand Up @@ -313,6 +316,7 @@ export function useGetEstimate({
};
},
enabled:
enabled &&
!!baseBalance &&
baseBalance !== '0' &&
!!quoteBalance &&
Expand Down
25 changes: 23 additions & 2 deletions apps/wallet/src/ui/app/pages/swap/ToAssetSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
import { useRecognizedCoins } from '_app/hooks/deepbook';
import { Button } from '_app/shared/ButtonUI';
import { InputWithActionButton } from '_app/shared/InputWithAction';
import { Text } from '_app/shared/text';
import Alert from '_components/alert';
Expand Down Expand Up @@ -28,12 +29,18 @@ export function ToAssetSection({
slippageErrorString,
baseCoinType,
quoteCoinType,
loading,
refetch,
error,
}: {
activeCoinType: string | null;
balanceChanges: BalanceChange[];
slippageErrorString: string;
baseCoinType: string;
quoteCoinType: string;
loading: boolean;
refetch: () => void;
error: Error | null;
}) {
const coinsMap = useDeepBookContext().configs.coinsMap;
const recognizedCoins = useRecognizedCoins();
Expand Down Expand Up @@ -104,13 +111,15 @@ export function ToAssetSection({

<InputWithActionButton
name="output-amount"
type="number"
disabled
noBorder={!isValid}
placeholder="--"
value={toAssetAmountAsNum || '--'}
loading={loading}
loadingText="Calculating..."
suffix={
!!toAssetAmountAsNum && (
!!toAssetAmountAsNum &&
!loading && (
<Text variant="body" weight="semibold" color="steel">
{toAssetSymbol}
</Text>
Expand Down Expand Up @@ -141,6 +150,18 @@ export function ToAssetSection({
/>
</div>
) : null}

{error && (
<div className="flex flex-col gap-4">
<Alert>
<Text variant="pBody" weight="semibold">
Calculation failed
</Text>
<Text variant="pBodySmall">{error.message || 'An error has occurred, try again.'}</Text>
</Alert>
<Button text="Recalculate" onClick={refetch} />
</div>
)}
</div>
);
}
21 changes: 16 additions & 5 deletions apps/wallet/src/ui/app/pages/swap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ export function SwapPageContent() {
control,
});

const baseBalance = new BigNumber(amount).shiftedBy(USDC_CONVERSION_RATE).toString();
const quoteBalance = new BigNumber(amount).shiftedBy(SUI_CONVERSION_RATE).toString();
const baseBalance = amount && new BigNumber(amount).shiftedBy(USDC_CONVERSION_RATE).toString();
const quoteBalance = amount && new BigNumber(amount).shiftedBy(SUI_CONVERSION_RATE).toString();

const isPayAll = amount === (isAsk ? formattedBaseTokenBalance : formattedQuoteTokenBalance);

Expand All @@ -256,9 +256,12 @@ export function SwapPageContent() {
}, [isAsk, baseCoinSymbol, baseCoinType, coinsMap, quoteCoinSymbol, quoteCoinType]);

const {
error: estimateError,
data: dataFromEstimate,
isPending: dataFromEstimateLoading,
isError: dataFromEstimateError,
isPending: dataFromEstimatePending,
isFetching: dataFromEstimateFetching,
isError: isDataFromEstimateError,
refetch: refetchEstimate,
} = useGetEstimate({
signer,
accountCapId,
Expand All @@ -271,6 +274,7 @@ export function SwapPageContent() {
totalQuoteBalance: formattedQuoteTokenBalance,
baseConversionRate: USDC_CONVERSION_RATE,
quoteConversionRate: SUI_CONVERSION_RATE,
enabled: isValid,
});

const recognizedPackagesList = useRecognizedPackages();
Expand Down Expand Up @@ -445,6 +449,9 @@ export function SwapPageContent() {
balanceChanges={balanceChanges}
baseCoinType={baseCoinType}
quoteCoinType={quoteCoinType}
refetch={refetchEstimate}
loading={isValid && dataFromEstimateFetching}
error={isValid && estimateError ? estimateError : null}
/>

{isValid && (
Expand Down Expand Up @@ -477,7 +484,11 @@ export function SwapPageContent() {
variant="primary"
loading={isSubmitting || isSwapLoading}
disabled={
!isValid || isSubmitting || dataFromEstimateLoading || dataFromEstimateError
!isValid ||
isSubmitting ||
dataFromEstimatePending ||
dataFromEstimateFetching ||
isDataFromEstimateError
}
size="tall"
text={atcText}
Expand Down
25 changes: 24 additions & 1 deletion apps/wallet/src/ui/app/shared/InputWithAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { Text } from '_app/shared/text';
import LoadingIndicator from '_components/loading/LoadingIndicator';
import NumberInput from '_components/number-input';
import { cva, type VariantProps } from 'class-variance-authority';
import clsx from 'clsx';
Expand Down Expand Up @@ -170,6 +171,8 @@ type InputWithActionZodFormProps = VariantProps<typeof inputWithActionZodFormSty
errorString?: string;
suffix?: ReactNode;
prefix?: ReactNode;
loading?: boolean;
loadingText?: string;
onActionClicked?: PillProps['onClick'];
info?: ReactNode;
actionDisabled?: boolean;
Expand All @@ -191,6 +194,8 @@ export const InputWithActionButton = forwardRef<HTMLInputElement, InputWithActio
prefix,
info,
noBorder,
loading,
loadingText,
...props
},
forwardRef,
Expand All @@ -214,12 +219,30 @@ export const InputWithActionButton = forwardRef<HTMLInputElement, InputWithActio
type={type}
className={clsx(
'bg-transparent z-10 border-none p-0 text-heading5 text-steel-darker font-semibold h-6 caret-hero',
loading && 'text-transparent',
)}
disabled={disabled}
ref={forwardRef}
/>
{loading && (
<div className="absolute">
<div className="flex items-center gap-1 text-steel">
<LoadingIndicator color="inherit" />
{loadingText && (
<Text variant="body" color="steel">
{loadingText}
</Text>
)}
</div>
</div>
)}
{suffix && value && (
<div className="absolute z-0 flex h-full max-w-full items-center border border-transparent">
<div
className={clsx(
'absolute z-0 flex h-full max-w-full items-center border border-transparent',
loading && 'text-transparent',
)}
>
{prefixContent}
<span className="invisible max-w-full text-heading5">{value}</span>
<span className="ml-2 font-medium text-body text-steel">{suffix}</span>
Expand Down

0 comments on commit 8e936a9

Please sign in to comment.