@shogun-sdk/one-shot
Version:
Shogun SDK - One Shot: React Components and hooks for cross-chain swaps
133 lines (118 loc) • 3.63 kB
text/typescript
import {
decodeErrorMessage,
DEFAULT_ERROR_MESSAGE,
FeeService,
getMaxAmount,
getSwapWeiAmount,
ICollectedFees,
INSUFFICIENT_FUNDS_ERROR_MSG,
QuoteParams,
QuoteTypes,
Token,
} from '@shogun-sdk/money-legos';
import { useCallback, useEffect, useState } from 'react';
// Custom hook to handle fee calculations
export const useFeeCalculations = (props: {
address: string | undefined;
inputAmount: string;
tokenIn: Token;
hasInput: boolean;
tokenInBalance: bigint | undefined;
queryParams: QuoteParams | null;
setLatestSuggestedAutoSlippageValue: (slippage: number) => void;
notifyAboutError: (error: Error) => void;
}) => {
const {
address,
inputAmount,
tokenIn,
hasInput,
tokenInBalance,
queryParams,
setLatestSuggestedAutoSlippageValue,
notifyAboutError,
} = props;
const [fees, setFees] = useState<ICollectedFees | undefined>(undefined);
const [balanceError, setBalanceError] = useState<string | null>(null);
const resetBalanceError = useCallback(() => {
if (tokenInBalance && getSwapWeiAmount(inputAmount, tokenIn.decimals) > tokenInBalance) {
setBalanceError(INSUFFICIENT_FUNDS_ERROR_MSG);
return { fees: undefined, maxAmount: null };
}
setBalanceError(null);
return { fees: undefined, maxAmount: null };
}, [tokenIn, tokenInBalance, inputAmount]);
useEffect(() => {
resetBalanceError();
}, [resetBalanceError]);
const calculateFees = useCallback(
async (quotes: QuoteTypes): Promise<{ fees: ICollectedFees | undefined; maxAmount: string | null }> => {
if (!quotes || !address || !queryParams || !tokenIn || !hasInput) {
resetBalanceError();
return { fees: undefined, maxAmount: null };
}
try {
const feeService = new FeeService();
const feeData = await feeService.checkHasSufficientBalanceForGas(
address as string,
queryParams.srcChain as number,
quotes,
setLatestSuggestedAutoSlippageValue,
);
if (!feeData) {
return { fees: undefined, maxAmount: null };
}
setFees(feeData.fees);
if (feeData.error && feeData.error !== DEFAULT_ERROR_MESSAGE) {
const decodedError = decodeErrorMessage(feeData.error);
if (decodedError !== DEFAULT_ERROR_MESSAGE) {
setBalanceError(decodedError);
} else {
resetBalanceError();
}
} else {
resetBalanceError();
}
if (!tokenInBalance) {
return { fees: feeData.fees, maxAmount: null };
}
const { maxAmount } = getMaxAmount({
balance: tokenInBalance,
tokenAddress: tokenIn.address,
chainId: tokenIn.chainId,
decimals: tokenIn.decimals,
fees: feeData.fees,
quote: quotes,
});
if (!maxAmount) {
setBalanceError(INSUFFICIENT_FUNDS_ERROR_MSG);
return { fees: feeData.fees, maxAmount: null };
}
return { fees: feeData.fees, maxAmount };
} catch (error: unknown) {
console.error('Error in fee calculation:', error);
notifyAboutError(error as Error);
resetBalanceError();
return { fees: undefined, maxAmount: null };
}
},
[
address,
queryParams,
tokenIn,
tokenInBalance,
notifyAboutError,
setLatestSuggestedAutoSlippageValue,
hasInput,
resetBalanceError,
setBalanceError,
],
);
return {
fees,
balanceError,
calculateFees,
setFees,
resetBalanceError,
};
};