Skip to content

Commit

Permalink
feat: support txv3 in estimateFee (UI) (#263)
Browse files Browse the repository at this point in the history
* feat: support txv3 in estimateFee and estimateFeeBulk

* feat: support txv3 in estimateFee (UI)

* chore: lint + prettier

* chore: lint + prettier

* chore: lint + prettier

* chore: lint + prettier

* fix: transactionVersion must be a type

* refactor: add transactionVersion request params only in required RPC

* fix: pr review comment

* fix: forced tx v2 in upgrade account

* fix: address PR feedback and update implementation

* fix: address PR feedback and update implementation
  • Loading branch information
khanti42 authored Aug 16, 2024
1 parent 3b80205 commit 52b07d0
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import { ethers } from 'ethers';
import { AddressInput } from 'components/ui/molecule/AddressInput';
import { isValidAddress } from 'utils/utils';
import { Bold, Normal } from '../../ConnectInfoModal/ConnectInfoModal.style';
import { DropDown } from 'components/ui/molecule/DropDown';
import { DEFAULT_FEE_TOKEN } from 'utils/constants';
import { FeeToken } from 'types';

interface Props {
closeModal?: () => void;
Expand All @@ -33,6 +36,7 @@ export const SendModalView = ({ closeModal }: Props) => {
networks.items.length > 0
? networks.items[networks.activeNetwork].chainId
: '',
feeToken: DEFAULT_FEE_TOKEN, // Default fee token
});
const [errors, setErrors] = useState({ amount: '', address: '' });

Expand Down Expand Up @@ -68,8 +72,13 @@ export const SendModalView = ({ closeModal }: Props) => {
}
}
break;
case 'feeToken':
setFields((prevFields) => ({
...prevFields,
feeToken: fieldValue as FeeToken,
}));
break;
}

setFields((prevFields) => ({
...prevFields,
[fieldName]: fieldValue,
Expand Down Expand Up @@ -116,6 +125,20 @@ export const SendModalView = ({ closeModal }: Props) => {
decimalsMax={wallet.erc20TokenBalanceSelected.decimals}
asset={wallet.erc20TokenBalanceSelected}
/>
<SeparatorSmall />
<div>
<label htmlFor="feeToken">
Select Token for Transaction Fees
</label>
<DropDown
value={fields.feeToken}
options={Object.values(FeeToken).map((token) => ({
label: token,
value: token,
}))}
onChange={(e) => handleChange('feeToken', e.value)}
/>
</div>
</Wrapper>
<Buttons>
<ButtonStyled
Expand All @@ -141,6 +164,7 @@ export const SendModalView = ({ closeModal }: Props) => {
address={fields.address}
amount={fields.amount}
chainId={fields.chainId}
selectedFeeToken={fields.feeToken} // Pass the selected fee token
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,23 @@ import { useEffect, useState } from 'react';
import { useStarkNetSnap } from 'services';
import { ethers } from 'ethers';
import Toastr from 'toastr2';
import { constants } from 'starknet';
import { FeeToken } from 'types';

interface Props {
address: string;
amount: string;
chainId: string;
closeModal?: () => void;
selectedFeeToken: FeeToken;
}

export const SendSummaryModalView = ({
address,
amount,
chainId,
closeModal,
selectedFeeToken,
}: Props) => {
const wallet = useAppSelector((state) => state.wallet);
const [estimatingGas, setEstimatingGas] = useState(true);
Expand All @@ -61,6 +65,12 @@ export const SendSummaryModalView = ({
const [totalExceedsBalance, setTotalExceedsBalance] = useState(false);
const { estimateFees, sendTransaction, getTransactions } = useStarkNetSnap();

const ethToken = wallet.erc20TokenBalances[0];
const feeToken =
wallet.erc20TokenBalances.find(
(token) => token.symbol === selectedFeeToken,
) ?? ethToken;

const toastr = new Toastr({
closeDuration: 10000000,
showDuration: 1000000000,
Expand All @@ -83,6 +93,9 @@ export const SendSummaryModalView = ({
callData,
wallet.accounts[0] as unknown as string,
chainId,
selectedFeeToken === FeeToken.ETH
? constants.TRANSACTION_VERSION.V2
: constants.TRANSACTION_VERSION.V3,
)
.then((response) => {
if (response.message && response.message.includes('Error')) {
Expand All @@ -103,50 +116,52 @@ export const SendSummaryModalView = ({

useEffect(() => {
if (gasFees?.suggestedMaxFee) {
//We assume the first token for the user will always be ETH
const ethToken = wallet.erc20TokenBalances[0];
const gasFeesBN = ethers.utils.parseUnits(
gasFees.suggestedMaxFee,
gasFees.unit,
);
let totalToCheck = gasFeesBN;
const gasFeesStr = ethers.utils.formatUnits(gasFeesBN, ethToken.decimals);

const gasFeesStr = ethers.utils.formatUnits(gasFeesBN, feeToken.decimals);
const gasFeesFloat = parseFloat(gasFeesStr);
setGasFeesAmount(getMaxDecimalsReadable(ethToken, gasFeesStr));
if (ethToken.usdPrice) {
setGasFeesAmountUSD(getAmountPrice(ethToken, gasFeesFloat, false));
setGasFeesAmount(getMaxDecimalsReadable(feeToken, gasFeesStr));
if (feeToken.usdPrice) {
setGasFeesAmountUSD(getAmountPrice(feeToken, gasFeesFloat, false));
}
const amountBN = ethers.utils.parseUnits(
amount,
wallet.erc20TokenBalanceSelected.decimals,
);
if (wallet.erc20TokenBalanceSelected.address === ethToken.address) {
//We add the fees with the amount if the current token is ETH
// Combine the transaction amount and fee amount if they are the same token.
// And verify if the combined amount is not exceeding the total balance.
if (wallet.erc20TokenBalanceSelected.address === feeToken.address) {
const totalAmountBN = gasFeesBN.add(amountBN);
totalToCheck = totalAmountBN;
const totalAmount = ethers.utils.formatUnits(
totalAmountBN,
ethToken.decimals,
feeToken.decimals,
);
setTotalAmount(getMaxDecimalsReadable(ethToken, totalAmount));
setTotalAmount(getMaxDecimalsReadable(feeToken, totalAmount));
const totalAmountFloat = parseFloat(totalAmount);
if (ethToken.usdPrice) {
setTotalAmountUSD(getAmountPrice(ethToken, totalAmountFloat, false));
if (feeToken.usdPrice) {
setTotalAmountUSD(getAmountPrice(feeToken, totalAmountFloat, false));
}
} else if (amountUsdPrice) {
const amountGasFeeUSDFloat = parseFloat(
getAmountPrice(ethToken, gasFeesFloat, false),
getAmountPrice(feeToken, gasFeesFloat, false),
);
const amountUSDFloat = parseFloat(amountUsdPrice);
const totalUSDAmount = amountUSDFloat + amountGasFeeUSDFloat;
setTotalAmountUSD(totalUSDAmount.toFixed(2));
}
//Check if total amount exceeds or gasFees exceeds ETH balance
if (totalToCheck.gt(ethToken.amount)) {

if (totalToCheck.gt(feeToken.amount)) {
setTotalExceedsBalance(true);
} else {
setTotalExceedsBalance(false);
}
} else {
setTotalExceedsBalance(true);
}
}, [gasFees]);

Expand Down Expand Up @@ -203,20 +218,16 @@ export const SendSummaryModalView = ({

const totalAmountDisplay = () => {
if (wallet.erc20TokenBalances.length > 0) {
if (
wallet.erc20TokenBalanceSelected.address ===
wallet.erc20TokenBalances[0].address
) {
//ETH selected
return totalAmount + ' ETH';
if (wallet.erc20TokenBalanceSelected.address === feeToken.address) {
return totalAmount + ` ${feeToken.symbol}`;
} else {
return (
getHumanReadableAmount(wallet.erc20TokenBalanceSelected, amount) +
' ' +
wallet.erc20TokenBalanceSelected.symbol +
' + ' +
gasFeesAmount +
' ETH'
` ${feeToken.symbol}`
);
}
}
Expand Down Expand Up @@ -261,14 +272,18 @@ export const SendSummaryModalView = ({
{estimatingGas && <LoadingWrapper />}
{!estimatingGas && (
<>
<CurrencyAmount>{gasFeesAmount} ETH</CurrencyAmount>
<CurrencyAmount>
{gasFeesAmount} {selectedFeeToken}
</CurrencyAmount>
<USDAmount>{gasFeesAmountUSD} USD</USDAmount>
</>
)}
</RightSummary>
</Summary>
{!estimatingGas && (
<TotalAmount>Maximum fees: {gasFeesAmount} ETH</TotalAmount>
<TotalAmount>
Maximum fees: {gasFeesAmount} {selectedFeeToken}
</TotalAmount>
)}
{gasFees.includeDeploy && (
<IncludeDeploy>*Fees include a one-time deployment fee</IncludeDeploy>
Expand All @@ -289,7 +304,9 @@ export const SendSummaryModalView = ({
</RightSummary>
</Summary>
{totalAmount && (
<TotalAmount>Maximum amount: {totalAmount} ETH</TotalAmount>
<TotalAmount>
Maximum amount: {totalAmount} {selectedFeeToken}
</TotalAmount>
)}
{totalExceedsBalance && (
<AlertTotalExceedsAmount
Expand Down
5 changes: 5 additions & 0 deletions packages/wallet-ui/src/services/useStarkNetSnap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { ethers } from 'ethers';
import { getAssetPriceUSD } from './coinGecko';
import semver from 'semver/preload';
import { setActiveNetwork } from 'slices/networkSlice';
import { constants } from 'starknet';

export const useStarkNetSnap = () => {
const dispatch = useAppDispatch();
Expand Down Expand Up @@ -332,6 +333,9 @@ export const useStarkNetSnap = () => {
contractCallData: string,
senderAddress: string,
chainId: string,
transactionVersion?:
| typeof constants.TRANSACTION_VERSION.V2
| typeof constants.TRANSACTION_VERSION.V3,
) {
try {
const response = await provider.request({
Expand All @@ -347,6 +351,7 @@ export const useStarkNetSnap = () => {
contractCallData,
senderAddress,
chainId,
transactionVersion,
},
},
},
Expand Down
5 changes: 5 additions & 0 deletions packages/wallet-ui/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,8 @@ export interface TokenBalance {
balancePending: BigNumber;
balanceLatest: BigNumber;
}

export enum FeeToken { // for retrieving txns from Voyager
ETH = 'ETH',
STRK = 'STRK',
}
3 changes: 3 additions & 0 deletions packages/wallet-ui/src/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { constants } from 'starknet';
import { FeeToken } from 'types';

// TODO: Importing directly from constants when upgrading to starknet.js v6
export const SEPOLIA_CHAINID = '0x534e5f5345504f4c4941';
Expand Down Expand Up @@ -61,3 +62,5 @@ export const TIMEOUT_DURATION = 10000;

export const MIN_ACC_CONTRACT_VERSION = [0, 3, 0];
export const DUMMY_ADDRESS = '0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

export const DEFAULT_FEE_TOKEN = FeeToken.ETH;

0 comments on commit 52b07d0

Please sign in to comment.