Skip to content

Commit

Permalink
wallet-ext: use paySui
Browse files Browse the repository at this point in the history
  • Loading branch information
pchrysochoidis committed Nov 17, 2022
1 parent 3b510d0 commit 980238d
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 257 deletions.
16 changes: 5 additions & 11 deletions apps/wallet/src/shared/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import BigNumber from 'bignumber.js';
import * as Yup from 'yup';

import { formatBalance } from '_app/hooks/useFormatCoin';
import {
DEFAULT_GAS_BUDGET_FOR_TRANSFER,
GAS_SYMBOL,
GAS_TYPE_ARG,
} from '_redux/slices/sui-objects/Coin';
import { GAS_SYMBOL, GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin';

export function createTokenValidation(
coinType: string,
Expand All @@ -18,7 +14,8 @@ export function createTokenValidation(
gasBalance: bigint,
decimals: number,
// TODO: We can move this to a constant when MIST is fully rolled out.
gasDecimals: number
gasDecimals: number,
gasBudget: number
) {
return Yup.mixed()
.transform((_, original) => {
Expand Down Expand Up @@ -63,24 +60,21 @@ export function createTokenValidation(
.test(
'gas-balance-check',
`Insufficient ${GAS_SYMBOL} balance to cover gas fee (${formatBalance(
DEFAULT_GAS_BUDGET_FOR_TRANSFER,
gasBudget,
gasDecimals
)} ${GAS_SYMBOL})`,
(amount?: BigNumber) => {
if (!amount) {
return false;
}

try {
let availableGas = gasBalance;
if (coinType === GAS_TYPE_ARG) {
availableGas -= BigInt(
amount.shiftedBy(decimals).toString()
);
}
// TODO: implement more sophisticated validation by taking
// the splitting/merging fee into account
return availableGas >= DEFAULT_GAS_BUDGET_FOR_TRANSFER;
return availableGas >= gasBudget;
} catch (e) {
return false;
}
Expand Down
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 BigNumber from 'bignumber.js';
import cl from 'classnames';
import { ErrorMessage, Field, Form, useFormikContext } from 'formik';
import { useEffect, useRef, memo } from 'react';
Expand All @@ -10,36 +11,66 @@ import Button from '_app/shared/button';
import ActiveCoinsCard from '_components/active-coins-card';
import Icon, { SuiIcons } from '_components/icon';
import NumberInput from '_components/number-input';
import { useCoinDecimals } from '_hooks';

import type { FormValues } from '../';

import st from './TransferCoinForm.module.scss';

function parseAmount(amount: string, coinDecimals: number) {
try {
return BigInt(
new BigNumber(amount)
.shiftedBy(coinDecimals)
.integerValue()
.toString()
);
} catch (e) {
return BigInt(0);
}
}

export type TransferCoinFormProps = {
submitError: string | null;
coinBalance: string;
coinSymbol: string;
coinType: string;
onClearSubmitError: () => void;
onAmountChanged: (amount: bigint) => void;
};

function StepOne({
submitError,
coinBalance,
coinSymbol,
coinType,
onClearSubmitError,
onAmountChanged,
}: TransferCoinFormProps) {
const {
isValid,
validateForm,
values: { amount },
} = useFormikContext<FormValues>();

const onClearRef = useRef(onClearSubmitError);
onClearRef.current = onClearSubmitError;
useEffect(() => {
onClearRef.current();
}, [amount]);
const [coinDecimals, { isLoading: isCoinDecimalsLoading }] =
useCoinDecimals(coinType);
useEffect(() => {
if (!isCoinDecimalsLoading) {
const parsedAmount = parseAmount(amount, coinDecimals);
onAmountChanged(parsedAmount);
// seems changing the validationSchema doesn't rerun the validation for the form
// trigger re-validation here when the amount to send is changed
// (changing the amount will probably change the gasBudget and in the end the validationSchema)
validateForm();
}
}, [
amount,
onAmountChanged,
coinDecimals,
isCoinDecimalsLoading,
validateForm,
]);
return (
<Form
className={cl(st.container, st.amount)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,25 @@ import AddressInput from '_components/address-input';
import Icon, { SuiIcons } from '_components/icon';
import LoadingIndicator from '_components/loading/LoadingIndicator';
import { useCoinDecimals, useFormatCoin } from '_hooks';
import {
DEFAULT_GAS_BUDGET_FOR_TRANSFER,
GAS_SYMBOL,
GAS_TYPE_ARG,
} from '_redux/slices/sui-objects/Coin';
import { GAS_SYMBOL, GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin';

import type { FormValues } from '../';

import st from './TransferCoinForm.module.scss';

export type TransferCoinFormProps = {
submitError: string | null;
coinBalance: string;
coinSymbol: string;
coinType: string;
gasBudget: number;
onClearSubmitError: () => void;
};

function StepTwo({
submitError,
coinBalance,
coinSymbol,
coinType,
gasBudget,
onClearSubmitError,
}: TransferCoinFormProps) {
const {
Expand All @@ -57,18 +53,15 @@ function StepTwo({
[amount, decimals]
);

const totalAmount = new BigNumber(DEFAULT_GAS_BUDGET_FOR_TRANSFER)
const totalAmount = new BigNumber(gasBudget)
.plus(GAS_SYMBOL === coinSymbol ? amountWithoutDecimals : 0)
.toString();

const validAddressBtn = !isValid || to === '' || isSubmitting;

const [formattedBalance] = useFormatCoin(amountWithoutDecimals, coinType);
const [formattedTotal] = useFormatCoin(totalAmount, GAS_TYPE_ARG);
const [formattedGas] = useFormatCoin(
DEFAULT_GAS_BUDGET_FOR_TRANSFER,
GAS_TYPE_ARG
);
const [formattedGas] = useFormatCoin(gasBudget, GAS_TYPE_ARG);

return (
<Form className={st.container} autoComplete="off" noValidate={true}>
Expand Down
32 changes: 26 additions & 6 deletions apps/wallet/src/ui/app/pages/home/transfer-coin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import PageTitle from '_app/shared/page-title';
import Loading from '_components/loading';
import ProgressBar from '_components/progress-bar';
import { useAppSelector, useAppDispatch, useCoinDecimals } from '_hooks';
import { accountAggregateBalancesSelector } from '_redux/slices/account';
import {
accountAggregateBalancesSelector,
accountCoinsSelector,
} from '_redux/slices/account';
import { Coin, GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin';
import { sendTokens } from '_redux/slices/transactions';
import { trackEvent } from '_src/shared/plausible';
Expand Down Expand Up @@ -64,7 +67,23 @@ function TransferCoinPage() {

const [coinDecimals] = useCoinDecimals(coinType);
const [gasDecimals] = useCoinDecimals(GAS_TYPE_ARG);

const allCoins = useAppSelector(accountCoinsSelector);
const allCoinsOfSelectedTypeArg = useMemo(
() =>
allCoins.filter(
(aCoin) => coinType && Coin.getCoinTypeArg(aCoin) === coinType
),
[coinType, allCoins]
);
const [amountToSend, setAmountToSend] = useState(BigInt(0));
const gasBudget = useMemo(
() =>
Coin.computeGasBudgetForPay(
allCoinsOfSelectedTypeArg,
amountToSend
),
[allCoinsOfSelectedTypeArg, amountToSend]
);
const validationSchemaStepOne = useMemo(
() =>
createValidationSchemaStepOne(
Expand All @@ -73,7 +92,8 @@ function TransferCoinPage() {
coinSymbol,
gasAggregateBalance,
coinDecimals,
gasDecimals
gasDecimals,
gasBudget
),
[
coinType,
Expand All @@ -82,6 +102,7 @@ function TransferCoinPage() {
coinDecimals,
gasDecimals,
gasAggregateBalance,
gasBudget,
]
);
const validationSchemaStepTwo = useMemo(
Expand Down Expand Up @@ -163,11 +184,10 @@ function TransferCoinPage() {
onSubmit={handleNextStep}
>
<StepOne
submitError={sendError}
coinBalance={coinBalance.toString()}
coinSymbol={coinSymbol}
coinType={coinType}
onClearSubmitError={handleOnClearSubmitError}
onAmountChanged={(anAmount) => setAmountToSend(anAmount)}
/>
</Formik>
);
Expand All @@ -181,7 +201,7 @@ function TransferCoinPage() {
>
<StepTwo
submitError={sendError}
coinBalance={coinBalance.toString()}
gasBudget={gasBudget}
coinSymbol={coinSymbol}
coinType={coinType}
onClearSubmitError={handleOnClearSubmitError}
Expand Down
6 changes: 4 additions & 2 deletions apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export function createValidationSchemaStepOne(
coinSymbol: string,
gasBalance: bigint,
decimals: number,
gasDecimals: number
gasDecimals: number,
gasBudget: number
) {
return Yup.object({
amount: createTokenValidation(
Expand All @@ -27,7 +28,8 @@ export function createValidationSchemaStepOne(
coinSymbol,
gasBalance,
decimals,
gasDecimals
gasDecimals,
gasBudget
),
});
}
Loading

0 comments on commit 980238d

Please sign in to comment.