Skip to content

Commit

Permalink
feat: add useTransaction (#1189)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsimao authored May 23, 2023
1 parent e9157c7 commit b04beda
Show file tree
Hide file tree
Showing 36 changed files with 960 additions and 447 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ISubmittableResult } from '@polkadot/types/types';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { FaCheckCircle } from 'react-icons/fa';
import { useMutation, useQueryClient } from 'react-query';
import { useQueryClient } from 'react-query';
import { toast } from 'react-toastify';

import { BTC_EXPLORER_TRANSACTION_API } from '@/config/blockstream-explorer-links';
Expand All @@ -16,7 +15,7 @@ import { TABLE_PAGE_LIMIT } from '@/utils/constants/general';
import { QUERY_PARAMETERS } from '@/utils/constants/links';
import { KUSAMA, POLKADOT } from '@/utils/constants/relay-chain-names';
import { getColorShade } from '@/utils/helpers/colors';
import { submitExtrinsicPromise } from '@/utils/helpers/extrinsic';
import { Transaction, useTransaction } from '@/utils/hooks/transaction';
import useQueryParams from '@/utils/hooks/use-query-params';

import ManualIssueExecutionUI from '../ManualIssueExecutionUI';
Expand All @@ -34,21 +33,15 @@ const ConfirmedIssueRequest = ({ request }: Props): JSX.Element => {
const selectedPageIndex = selectedPage - 1;

const queryClient = useQueryClient();
// TODO: should type properly (`Relay`)
const executeMutation = useMutation<ISubmittableResult, Error, any>(
(variables: any) => {
if (!variables.backingPayment.btcTxId) {
throw new Error('Bitcoin transaction ID not identified yet.');
}
return submitExtrinsicPromise(window.bridge.issue.execute(variables.id, variables.backingPayment.btcTxId));
},
{
onSuccess: (_, variables) => {
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: variables.id }));
}

// TODO: check if this transaction is necessary
const transaction = useTransaction(Transaction.ISSUE_EXECUTE, {
onSuccess: (_, variables) => {
const [requestId] = variables.args;
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: requestId }));
}
);
});

return (
<>
Expand Down Expand Up @@ -82,16 +75,14 @@ const ConfirmedIssueRequest = ({ request }: Props): JSX.Element => {
</p>
<ManualIssueExecutionUI request={request} />
</RequestWrapper>
{executeMutation.isError && executeMutation.error && (
{transaction.isError && transaction.error && (
<ErrorModal
open={!!executeMutation.error}
open={!!transaction.error}
onClose={() => {
executeMutation.reset();
transaction.reset();
}}
title='Error'
description={
typeof executeMutation.error === 'string' ? executeMutation.error : executeMutation.error.message
}
description={typeof transaction.error === 'string' ? transaction.error : transaction.error.message}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import {
newAccountId,
newMonetaryAmount
} from '@interlay/interbtc-api';
import { ISubmittableResult } from '@polkadot/types/types';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { useQuery, useQueryClient } from 'react-query';
import { toast } from 'react-toastify';

import { displayMonetaryAmount } from '@/common/utils/utils';
Expand All @@ -21,7 +20,7 @@ import { TABLE_PAGE_LIMIT } from '@/utils/constants/general';
import { QUERY_PARAMETERS } from '@/utils/constants/links';
import { KUSAMA, POLKADOT } from '@/utils/constants/relay-chain-names';
import { getColorShade } from '@/utils/helpers/colors';
import { submitExtrinsicPromise } from '@/utils/helpers/extrinsic';
import { Transaction, useTransaction } from '@/utils/hooks/transaction';
import useQueryParams from '@/utils/hooks/use-query-params';

// TODO: issue requests should not be typed here but further above in the app
Expand Down Expand Up @@ -57,21 +56,13 @@ const ManualIssueExecutionUI = ({ request }: Props): JSX.Element => {

const queryClient = useQueryClient();

// TODO: should type properly (`Relay`)
const executeMutation = useMutation<ISubmittableResult, Error, any>(
(variables: any) => {
if (!variables.backingPayment.btcTxId) {
throw new Error('Bitcoin transaction ID not identified yet.');
}
return submitExtrinsicPromise(window.bridge.issue.execute(variables.id, variables.backingPayment.btcTxId));
},
{
onSuccess: (_, variables) => {
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: variables.id }));
}
const transaction = useTransaction(Transaction.ISSUE_EXECUTE, {
onSuccess: (_, variables) => {
const [requestId] = variables.args;
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: requestId }));
}
);
});

const { data: vaultCapacity, error: vaultCapacityError } = useQuery({
queryKey: 'vault-capacity',
Expand All @@ -91,7 +82,12 @@ const ManualIssueExecutionUI = ({ request }: Props): JSX.Element => {

// TODO: should type properly (`Relay`)
const handleExecute = (request: any) => () => {
executeMutation.mutate(request);
if (!request.backingPayment.btcTxId) {
console.error('Bitcoin transaction ID not identified yet.');
return;
}

transaction.execute(request.id, request.backingPayment.btcTxId);
};

const backingPaymentAmount = newMonetaryAmount(request.backingPayment.amount, WRAPPED_TOKEN);
Expand Down Expand Up @@ -135,24 +131,22 @@ const ManualIssueExecutionUI = ({ request }: Props): JSX.Element => {
)}
<InterlayDenimOrKintsugiMidnightOutlinedButton
className='w-full'
pending={executeMutation.isLoading}
pending={transaction.isLoading}
disabled={!executable || !isOwner}
onClick={handleExecute(request)}
>
{t('issue_page.claim_interbtc', {
wrappedTokenSymbol: WRAPPED_TOKEN_SYMBOL
})}
</InterlayDenimOrKintsugiMidnightOutlinedButton>
{executeMutation.isError && executeMutation.error && (
{transaction.isError && transaction.error && (
<ErrorModal
open={!!executeMutation.error}
open={!!transaction.error}
onClose={() => {
executeMutation.reset();
transaction.reset();
}}
title='Error'
description={
typeof executeMutation.error === 'string' ? executeMutation.error : executeMutation.error.message
}
description={typeof transaction.error === 'string' ? transaction.error : transaction.error.message}
/>
)}
</div>
Expand Down
26 changes: 6 additions & 20 deletions src/pages/AMM/Pools/components/DepositForm/DepositForm.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { CurrencyExt, LiquidityPool, newMonetaryAmount, PooledCurrencies } from '@interlay/interbtc-api';
import { AccountId } from '@polkadot/types/interfaces';
import { ISubmittableResult } from '@polkadot/types/types';
import { CurrencyExt, LiquidityPool, newMonetaryAmount } from '@interlay/interbtc-api';
import { mergeProps } from '@react-aria/utils';
import Big from 'big.js';
import { ChangeEventHandler, RefObject, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation } from 'react-query';
import { toast } from 'react-toastify';

import { displayMonetaryAmountInUSDFormat, newSafeMonetaryAmount } from '@/common/utils/utils';
Expand All @@ -21,10 +18,10 @@ import {
} from '@/lib/form';
import { SlippageManager } from '@/pages/AMM/shared/components';
import { AMM_DEADLINE_INTERVAL } from '@/utils/constants/api';
import { submitExtrinsic } from '@/utils/helpers/extrinsic';
import { getTokenPrice } from '@/utils/helpers/prices';
import { useGetBalances } from '@/utils/hooks/api/tokens/use-get-balances';
import { useGetPrices } from '@/utils/hooks/api/use-get-prices';
import { Transaction, useTransaction } from '@/utils/hooks/transaction';
import useAccountId from '@/utils/hooks/use-account-id';

import { PoolName } from '../PoolName';
Expand All @@ -35,17 +32,6 @@ import { DepositOutputAssets } from './DepositOutputAssets';
const isCustomAmountsMode = (form: ReturnType<typeof useForm>) =>
form.dirty && Object.values(form.touched).filter(Boolean).length > 0;

type DepositData = {
amounts: PooledCurrencies;
pool: LiquidityPool;
slippage: number;
deadline: number;
accountId: AccountId;
};

const mutateDeposit = ({ amounts, pool, slippage, deadline, accountId }: DepositData) =>
submitExtrinsic(window.bridge.amm.addLiquidity(amounts, pool, slippage, deadline, accountId));

type DepositFormProps = {
pool: LiquidityPool;
slippageModalRef: RefObject<HTMLDivElement>;
Expand All @@ -65,7 +51,7 @@ const DepositForm = ({ pool, slippageModalRef, onDeposit }: DepositFormProps): J

const governanceBalance = getBalance(GOVERNANCE_TOKEN.ticker)?.free || newMonetaryAmount(0, GOVERNANCE_TOKEN);

const depositMutation = useMutation<ISubmittableResult, Error, DepositData>(mutateDeposit, {
const transaction = useTransaction(Transaction.AMM_ADD_LIQUIDITY, {
onSuccess: () => {
onDeposit?.();
toast.success('Deposit successful');
Expand All @@ -85,7 +71,7 @@ const DepositForm = ({ pool, slippageModalRef, onDeposit }: DepositFormProps): J

const deadline = await window.bridge.system.getFutureBlockNumber(AMM_DEADLINE_INTERVAL);

return depositMutation.mutate({ amounts, pool, slippage, deadline, accountId });
return transaction.execute(amounts, pool, slippage, deadline, accountId);
} catch (err: any) {
toast.error(err.toString());
}
Expand All @@ -106,7 +92,7 @@ const DepositForm = ({ pool, slippageModalRef, onDeposit }: DepositFormProps): J
initialValues: defaultValues,
validationSchema: depositLiquidityPoolSchema({ transactionFee: TRANSACTION_FEE_AMOUNT, governanceBalance, tokens }),
onSubmit: handleSubmit,
disableValidation: depositMutation.isLoading
disableValidation: transaction.isLoading
});

const handleChange: ChangeEventHandler<HTMLInputElement> = (e) => {
Expand Down Expand Up @@ -203,7 +189,7 @@ const DepositForm = ({ pool, slippageModalRef, onDeposit }: DepositFormProps): J
</Dd>
</DlGroup>
</StyledDl>
<AuthCTA type='submit' size='large' disabled={isBtnDisabled} loading={depositMutation.isLoading}>
<AuthCTA type='submit' size='large' disabled={isBtnDisabled} loading={transaction.isLoading}>
{t('amm.pools.add_liquidity')}
</AuthCTA>
</Flex>
Expand Down
15 changes: 4 additions & 11 deletions src/pages/AMM/Pools/components/PoolsInsights/PoolsInsights.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { LiquidityPool } from '@interlay/interbtc-api';
import Big from 'big.js';
import { useTranslation } from 'react-i18next';
import { useMutation } from 'react-query';
import { toast } from 'react-toastify';

import { formatUSD } from '@/common/utils/utils';
import { Card, Dl, DlGroup } from '@/component-library';
import { AuthCTA } from '@/components';
import { calculateAccountLiquidityUSD, calculateTotalLiquidityUSD } from '@/pages/AMM/shared/utils';
import { submitExtrinsic } from '@/utils/helpers/extrinsic';
import { AccountPoolsData } from '@/utils/hooks/api/amm/use-get-account-pools';
import { useGetPrices } from '@/utils/hooks/api/use-get-prices';
import { Transaction, useTransaction } from '@/utils/hooks/transaction';

import { StyledDd, StyledDt } from './PoolsInsights.style';
import { calculateClaimableFarmingRewardUSD } from './utils';
Expand Down Expand Up @@ -55,17 +54,11 @@ const PoolsInsights = ({ pools, accountPoolsData, refetch }: PoolsInsightsProps)
refetch();
};

const mutateClaimRewards = async () => {
if (accountPoolsData !== undefined) {
await submitExtrinsic(window.bridge.amm.claimFarmingRewards(accountPoolsData.claimableRewards));
}
};

const claimRewardsMutation = useMutation<void, Error, void>(mutateClaimRewards, {
const transaction = useTransaction(Transaction.AMM_CLAIM_REWARDS, {
onSuccess: handleSuccess
});

const handleClickClaimRewards = () => claimRewardsMutation.mutate();
const handleClickClaimRewards = () => accountPoolsData && transaction.execute(accountPoolsData.claimableRewards);

const hasClaimableRewards = totalClaimableRewardUSD > 0;
return (
Expand All @@ -88,7 +81,7 @@ const PoolsInsights = ({ pools, accountPoolsData, refetch }: PoolsInsightsProps)
<StyledDd color='secondary'>{formatUSD(totalClaimableRewardUSD, { compact: true })}</StyledDd>
</DlGroup>
{hasClaimableRewards && (
<AuthCTA onPress={handleClickClaimRewards} loading={claimRewardsMutation.isLoading}>
<AuthCTA onPress={handleClickClaimRewards} loading={transaction.isLoading}>
Claim
</AuthCTA>
)}
Expand Down
25 changes: 5 additions & 20 deletions src/pages/AMM/Pools/components/WithdrawForm/WithdrawForm.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { LiquidityPool, LpCurrency, newMonetaryAmount } from '@interlay/interbtc-api';
import { MonetaryAmount } from '@interlay/monetary-js';
import { AccountId } from '@polkadot/types/interfaces';
import { ISubmittableResult } from '@polkadot/types/types';
import { LiquidityPool, newMonetaryAmount } from '@interlay/interbtc-api';
import Big from 'big.js';
import { RefObject, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation } from 'react-query';
import { toast } from 'react-toastify';

import {
Expand All @@ -20,27 +16,16 @@ import { isFormDisabled, useForm, WITHDRAW_LIQUIDITY_POOL_FIELD } from '@/lib/fo
import { WithdrawLiquidityPoolFormData, withdrawLiquidityPoolSchema } from '@/lib/form/schemas';
import { SlippageManager } from '@/pages/AMM/shared/components';
import { AMM_DEADLINE_INTERVAL } from '@/utils/constants/api';
import { submitExtrinsic } from '@/utils/helpers/extrinsic';
import { getTokenPrice } from '@/utils/helpers/prices';
import { useGetBalances } from '@/utils/hooks/api/tokens/use-get-balances';
import { useGetPrices } from '@/utils/hooks/api/use-get-prices';
import { Transaction, useTransaction } from '@/utils/hooks/transaction';
import useAccountId from '@/utils/hooks/use-account-id';

import { PoolName } from '../PoolName';
import { WithdrawAssets } from './WithdrawAssets';
import { StyledDl } from './WithdrawForm.styles';

type DepositData = {
amount: MonetaryAmount<LpCurrency>;
pool: LiquidityPool;
slippage: number;
deadline: number;
accountId: AccountId;
};

const mutateWithdraw = ({ amount, pool, slippage, deadline, accountId }: DepositData) =>
submitExtrinsic(window.bridge.amm.removeLiquidity(amount, pool, slippage, deadline, accountId));

type WithdrawFormProps = {
pool: LiquidityPool;
slippageModalRef: RefObject<HTMLDivElement>;
Expand All @@ -55,7 +40,7 @@ const WithdrawForm = ({ pool, slippageModalRef, onWithdraw }: WithdrawFormProps)
const prices = useGetPrices();
const { getBalance } = useGetBalances();

const withdrawMutation = useMutation<ISubmittableResult, Error, DepositData>(mutateWithdraw, {
const transaction = useTransaction(Transaction.AMM_REMOVE_LIQUIDITY, {
onSuccess: () => {
onWithdraw?.();
toast.success('Withdraw successful');
Expand Down Expand Up @@ -85,7 +70,7 @@ const WithdrawForm = ({ pool, slippageModalRef, onWithdraw }: WithdrawFormProps)
const amount = newMonetaryAmount(data[WITHDRAW_LIQUIDITY_POOL_FIELD] || 0, lpToken, true);
const deadline = await window.bridge.system.getFutureBlockNumber(AMM_DEADLINE_INTERVAL);

return withdrawMutation.mutate({ amount, pool, deadline, slippage, accountId });
return transaction.execute(amount, pool, slippage, deadline, accountId);
} catch (err: any) {
toast.error(err.toString());
}
Expand Down Expand Up @@ -157,7 +142,7 @@ const WithdrawForm = ({ pool, slippageModalRef, onWithdraw }: WithdrawFormProps)
</Dd>
</DlGroup>
</StyledDl>
<AuthCTA type='submit' size='large' disabled={isBtnDisabled} loading={withdrawMutation.isLoading}>
<AuthCTA type='submit' size='large' disabled={isBtnDisabled} loading={transaction.isLoading}>
{t('amm.pools.remove_liquidity')}
</AuthCTA>
</Flex>
Expand Down
Loading

2 comments on commit b04beda

@vercel
Copy link

@vercel vercel bot commented on b04beda May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on b04beda May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.