diff --git a/apps/bridge-dapp/src/containers/DepositContainer/DepositContainer.tsx b/apps/bridge-dapp/src/containers/DepositContainer/DepositContainer.tsx index a204cf1fbe..5879c928f6 100644 --- a/apps/bridge-dapp/src/containers/DepositContainer/DepositContainer.tsx +++ b/apps/bridge-dapp/src/containers/DepositContainer/DepositContainer.tsx @@ -10,6 +10,7 @@ import { calculateTypedChainId } from '@webb-tools/sdk-core'; import { DepositCard, TokenListCard, + numberToString, useWebbUI, } from '@webb-tools/webb-ui-components'; import { TokenType } from '@webb-tools/webb-ui-components/components/BridgeInputs/types'; @@ -35,6 +36,7 @@ import { DepositConfirmContainerProps, DepositContainerProps } from './types'; import { CurrencyType } from '@webb-tools/dapp-types'; import { useEducationCardStep } from '../../hooks/useEducationCardStep'; import { isTokenAddedToMetamask } from '../../hooks/useAddCurrency'; +import { parseUnits } from 'viem'; interface MainComponentPropsVariants { ['source-chain-list-card']: ChainListCardWrapperProps; @@ -426,6 +428,8 @@ export const DepositContainer = forwardRef< return; } + const decimals = fungibleCurrency.getDecimals(); + const amountBI = parseUnits(numberToString(amount), decimals); const newNote = await noteManager.generateNote( activeApi.backend, sourceTypedChainId, @@ -433,8 +437,8 @@ export const DepositContainer = forwardRef< destTypedChainId, destId, fungibleCurrency.view.symbol, - fungibleCurrency.getDecimals(), - amount + decimals, + amountBI ); setIsGeneratingNote(false); diff --git a/apps/bridge-dapp/src/containers/TransferContainer/TransferContainer.tsx b/apps/bridge-dapp/src/containers/TransferContainer/TransferContainer.tsx index ca8dc5c932..0f8ac9b8b6 100644 --- a/apps/bridge-dapp/src/containers/TransferContainer/TransferContainer.tsx +++ b/apps/bridge-dapp/src/containers/TransferContainer/TransferContainer.tsx @@ -1,9 +1,9 @@ import { utxoFromVAnchorNote } from '@webb-tools/abstract-api-provider'; import { useWebContext } from '@webb-tools/api-provider-environment'; import { - ZERO_BIG_INT, Chain, CurrencyConfig, + ZERO_BIG_INT, getNativeCurrencyFromConfig, } from '@webb-tools/dapp-config'; import { isValidPublicKey } from '@webb-tools/dapp-types'; @@ -27,6 +27,7 @@ import { TokenListCard, TransferCard, getRoundedAmountString, + numberToString, useWebbUI, } from '@webb-tools/webb-ui-components'; import { ChainType as InputChainType } from '@webb-tools/webb-ui-components/components/BridgeInputs/types'; @@ -36,8 +37,8 @@ import { RelayerType, } from '@webb-tools/webb-ui-components/components/ListCard/types'; import { TransferCardProps } from '@webb-tools/webb-ui-components/containers/TransferCard/types'; -import { formatEther, parseUnits, formatUnits } from 'viem'; import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'; +import { formatEther, formatUnits, parseUnits } from 'viem'; import { ChainListCardWrapper } from '../../components'; import { WalletState, @@ -45,12 +46,12 @@ import { useConnectWallet, useMaxFeeInfo, } from '../../hooks'; +import { isTokenAddedToMetamask } from '../../hooks/useAddCurrency'; import { useEducationCardStep } from '../../hooks/useEducationCardStep'; import useStatesFromNotes from '../../hooks/useStatesFromNotes'; import { TransferConfirmContainer } from './TransferConfirmContainer'; import { RecipientPublicKeyTooltipContent } from './shared'; import { TransferContainerProps } from './types'; -import { isTokenAddedToMetamask } from '../../hooks/useAddCurrency'; export const TransferContainer = forwardRef< HTMLDivElement, @@ -531,7 +532,10 @@ export const TransferContainer = forwardRef< return undefined; } - return parseUnits(`${transferAmount}`, fungibleCurrency.view.decimals); + return parseUnits( + numberToString(transferAmount), + fungibleCurrency.view.decimals + ); }, [fungibleCurrency, transferAmount]); // Calculate input notes for current amount diff --git a/apps/bridge-dapp/src/containers/WithdrawContainer/WithdrawContainer.tsx b/apps/bridge-dapp/src/containers/WithdrawContainer/WithdrawContainer.tsx index a89732d63f..844ba96bf3 100644 --- a/apps/bridge-dapp/src/containers/WithdrawContainer/WithdrawContainer.tsx +++ b/apps/bridge-dapp/src/containers/WithdrawContainer/WithdrawContainer.tsx @@ -25,6 +25,7 @@ import { TokenListCard, WithdrawCard, getRoundedAmountString, + numberToString, useWebbUI, } from '@webb-tools/webb-ui-components'; import { @@ -342,11 +343,14 @@ export const WithdrawContainer = forwardRef< : currentNativeCurrency?.decimals; if (refundAmount && isRefund) { - const parsedRefundAmount = decimals - ? parseUnits(`${refundAmount}`, decimals) - : parseEther(`${refundAmount}`); + const parsedExchangeRate = Number( + formatEther(feeInfoOrBigInt.refundExchangeRate) + ); + const refundFee = numberToString(refundAmount * parsedExchangeRate); - feeWei += parsedRefundAmount * feeInfoOrBigInt.refundExchangeRate; + feeWei += decimals + ? parseUnits(refundFee, decimals) + : parseEther(refundFee); } const feeFormatted = decimals @@ -419,9 +423,10 @@ export const WithdrawContainer = forwardRef< const decimals = wrappableCurrency?.getDecimals() ?? fungibleCurrency?.getDecimals(); + const amountStr = numberToString(amount); const amountWei = decimals - ? parseUnits(`${amount}`, decimals) - : parseEther(`${amount}`); + ? parseUnits(amountStr, decimals) + : parseEther(amountStr); // If no fee or no active relayer, then return the original amount // as the fee is not deducted from the amount @@ -582,7 +587,7 @@ export const WithdrawContainer = forwardRef< // Get the notes that will be spent for this withdraw const inputNotes = NoteManager.getNotesFifo( availableNotesFromManager ?? [], - parseUnits(amount.toString() as `${number}`, fungibleDecimals) + parseUnits(numberToString(amount), fungibleDecimals) ); if (!inputNotes) { @@ -595,8 +600,7 @@ export const WithdrawContainer = forwardRef< }, BigInt(0)); const changeAmountBI = - sumInputNotes - - parseUnits(amount.toString() as `${number}`, fungibleDecimals); + sumInputNotes - parseUnits(numberToString(amount), fungibleDecimals); const keypair = noteManager.getKeypair(); if (!keypair.privkey) { @@ -620,7 +624,7 @@ export const WithdrawContainer = forwardRef< destAddress, fungibleCurrency.view.symbol, fungibleDecimals, - formattedChangeAmount + changeAmountBI ); } @@ -672,7 +676,7 @@ export const WithdrawContainer = forwardRef< } feeInfo={transactionFeeInfo} receivingInfo={refundInfo} - refundAmount={parseEther(`${refundAmount}`)} + refundAmount={parseEther(numberToString(refundAmount))} refundToken={currentNativeCurrency?.symbol} recipient={recipient} onResetState={handleResetState} diff --git a/apps/bridge-dapp/src/hooks/useShieldedAssets.ts b/apps/bridge-dapp/src/hooks/useShieldedAssets.ts index 16287cabfd..ad5fa2dbf0 100644 --- a/apps/bridge-dapp/src/hooks/useShieldedAssets.ts +++ b/apps/bridge-dapp/src/hooks/useShieldedAssets.ts @@ -1,10 +1,9 @@ -import { Currency } from '@webb-tools/abstract-api-provider'; import { useWebContext } from '@webb-tools/api-provider-environment'; import { chainsPopulated } from '@webb-tools/dapp-config'; import { useCurrencies, useNoteAccount } from '@webb-tools/react-hooks'; import { calculateTypedChainId } from '@webb-tools/sdk-core'; +import numberToString from '@webb-tools/webb-ui-components/utils/numberToString'; import React from 'react'; - import { formatUnits, parseUnits } from 'viem'; import { ShieldedAssetDataType } from '../containers/note-account-tables/ShieldedAssetsTableContainer/types'; @@ -49,7 +48,7 @@ export const useShieldedAssets = (): ShieldedAssetDataType[] => { if (existedChain) { const parsedAvailableBalance = parseUnits( - `${existedChain.availableBalance}`, + numberToString(existedChain.availableBalance), denomination ); diff --git a/libs/dapp-config/src/chains/chain-config.interface.ts b/libs/dapp-config/src/chains/chain-config.interface.ts index d7d597dc6a..4b036ffbcb 100644 --- a/libs/dapp-config/src/chains/chain-config.interface.ts +++ b/libs/dapp-config/src/chains/chain-config.interface.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { ChainType } from '@webb-tools/sdk-core'; -import type { Chain } from '@wagmi/chains'; +import type { Chain } from 'viem/chains'; import { AppEnvironment } from '../types'; diff --git a/libs/dapp-config/src/chains/evm/index.tsx b/libs/dapp-config/src/chains/evm/index.tsx index e067213756..37ee7f43cf 100644 --- a/libs/dapp-config/src/chains/evm/index.tsx +++ b/libs/dapp-config/src/chains/evm/index.tsx @@ -11,7 +11,7 @@ import { scrollTestnet, sepolia, type Chain, -} from '@wagmi/chains'; +} from 'viem/chains'; import { EVMChainId, PresetTypedChainId } from '@webb-tools/dapp-types'; import { ChainType } from '@webb-tools/sdk-core/typed-chain-id'; import merge from 'lodash/merge'; @@ -223,15 +223,15 @@ export const chainsConfig: Record = { }, }, env: ['development', 'test'], - contracts: { - multicall3: hostedOrbitMulticall3Address - ? { + contracts: hostedOrbitMulticall3Address + ? { + multicall3: { address: `0x${hostedOrbitMulticall3Address.replace(/^0x/, '')}`, blockCreated: hermesOrbitMulticall3DeploymentBlock, - } - : undefined, - }, - }, + }, + } + : undefined, + } satisfies ChainConfig, [PresetTypedChainId.AthenaOrbit]: { chainType: ChainType.EVM, @@ -256,15 +256,15 @@ export const chainsConfig: Record = { }, }, env: ['development', 'test'], - contracts: { - multicall3: hostedOrbitMulticall3Address - ? { + contracts: hostedOrbitMulticall3Address + ? { + multicall3: { address: `0x${hostedOrbitMulticall3Address.replace(/^0x/, '')}`, blockCreated: athenaOrbitMulticall3DeploymentBlock, - } - : undefined, - }, - }, + }, + } + : undefined, + } satisfies ChainConfig, [PresetTypedChainId.DemeterOrbit]: { chainType: ChainType.EVM, @@ -289,15 +289,15 @@ export const chainsConfig: Record = { }, }, env: ['development', 'test'], - contracts: { - multicall3: hostedOrbitMulticall3Address - ? { + contracts: hostedOrbitMulticall3Address + ? { + multicall3: { address: `0x${hostedOrbitMulticall3Address.replace(/^0x/, '')}`, blockCreated: demeterOrbitMulticall3DeploymentBlock, - } - : undefined, - }, - }, + }, + } + : undefined, + } satisfies ChainConfig, [PresetTypedChainId.TangleTestnet]: { chainType: ChainType.EVM, @@ -326,10 +326,8 @@ export const chainsConfig: Record = { }, }, env: ['development', 'test'], - contracts: { - multicall3: undefined, - }, - }, + } satisfies ChainConfig, + // Localnet [PresetTypedChainId.HermesLocalnet]: { chainType: ChainType.EVM, @@ -348,15 +346,15 @@ export const chainsConfig: Record = { }, }, env: ['development'], - contracts: { - multicall3: localOrbitMulticall3Address - ? { + contracts: localOrbitMulticall3Address + ? { + multicall3: { address: `0x${localOrbitMulticall3Address.replace(/^0x/, '')}`, blockCreated: localHermesMulticall3DeploymentBlock, - } - : undefined, - }, - }, + }, + } + : undefined, + } satisfies ChainConfig, [PresetTypedChainId.AthenaLocalnet]: { chainType: ChainType.EVM, @@ -375,15 +373,15 @@ export const chainsConfig: Record = { }, }, env: ['development'], - contracts: { - multicall3: localOrbitMulticall3Address - ? { + contracts: localOrbitMulticall3Address + ? { + multicall3: { address: `0x${localOrbitMulticall3Address.replace(/^0x/, '')}`, blockCreated: localAthenaMulticall3DeploymentBlock, - } - : undefined, - }, - }, + }, + } + : undefined, + } satisfies ChainConfig, [PresetTypedChainId.DemeterLocalnet]: { chainType: ChainType.EVM, @@ -402,13 +400,13 @@ export const chainsConfig: Record = { }, }, env: ['development'], - contracts: { - multicall3: localOrbitMulticall3Address - ? { + contracts: localOrbitMulticall3Address + ? { + multicall3: { address: `0x${localOrbitMulticall3Address.replace(/^0x/, '')}`, blockCreated: localDemeterMulticall3DeploymentBlock, - } - : undefined, - }, - }, + }, + } + : undefined, + } satisfies ChainConfig, }; diff --git a/libs/note-manager/src/note-manager.ts b/libs/note-manager/src/note-manager.ts index a8ddbb31e5..bc0472c61e 100644 --- a/libs/note-manager/src/note-manager.ts +++ b/libs/note-manager/src/note-manager.ts @@ -6,7 +6,6 @@ import { resetNoteStorage, } from '@webb-tools/browser-utils/storage'; import { ZERO_BIG_INT } from '@webb-tools/dapp-config'; -import { parseUnits } from 'viem'; import Storage from '@webb-tools/dapp-types/Storage'; import { CircomUtxo, @@ -20,6 +19,7 @@ import { import { hexToU8a } from '@webb-tools/utils'; import { Backend } from '@webb-tools/wasm-utils'; import { BehaviorSubject } from 'rxjs'; +import { parseUnits } from 'viem'; type DefaultNoteGenInput = Pick< NoteGenInput, @@ -349,15 +349,9 @@ export class NoteManager { destAnchorAddress: string, tokenSymbol: string, tokenDecimals: number, - amount: number | bigint + amount: bigint ): Promise { - let amountStr: string; - - if (typeof amount === 'number') { - amountStr = parseUnits(amount.toString(), tokenDecimals).toString(); - } else { - amountStr = amount.toString(); - } + const amountStr = amount.toString(); const input: UtxoGenInput = { curve: this.defaultNoteGenInput.curve, diff --git a/libs/webb-ui-components/src/utils/index.ts b/libs/webb-ui-components/src/utils/index.ts index 0425b88d52..8a525398c7 100644 --- a/libs/webb-ui-components/src/utils/index.ts +++ b/libs/webb-ui-components/src/utils/index.ts @@ -1,10 +1,11 @@ export * from './arrayFrom'; export * from './calculateDateProgress'; export * from './formatDateToUtc'; +export * from './formatTokenAmount'; +export * from './getHumanFileSize'; export * from './getPaginationItems'; export * from './getRoundedAmountString'; +export { default as numberToString } from './numberToString'; export * from './range'; export * from './shortenHex'; export * from './shortenString'; -export * from './getHumanFileSize'; -export * from './formatTokenAmount'; diff --git a/libs/webb-ui-components/src/utils/numberToString.ts b/libs/webb-ui-components/src/utils/numberToString.ts new file mode 100644 index 0000000000..36d0303abd --- /dev/null +++ b/libs/webb-ui-components/src/utils/numberToString.ts @@ -0,0 +1,18 @@ +/** + * Converts a number to a string without scientific notation + * @param num the number to be converted to string + * @returns the string representation of the number + */ +function numberToString(num: number): string { + let str = String(num); + + // Check if the number is in scientific notation + if (str.indexOf('e') !== -1) { + const exponent = parseInt(str.split('-')[1], 10); + str = num.toFixed(exponent); + } + + return str; +} + +export default numberToString;