diff --git a/apps/namadillo/src/App/Common/GasFeeModal.tsx b/apps/namadillo/src/App/Common/GasFeeModal.tsx
index 230418881..849944537 100644
--- a/apps/namadillo/src/App/Common/GasFeeModal.tsx
+++ b/apps/namadillo/src/App/Common/GasFeeModal.tsx
@@ -13,7 +13,6 @@ import { useAtomValue } from "jotai";
import { IoClose } from "react-icons/io5";
import { twMerge } from "tailwind-merge";
import { GasConfig } from "types";
-import { unknownAsset } from "utils/assets";
import { getDisplayGasFee } from "utils/gas";
import { FiatCurrency } from "./FiatCurrency";
import { TokenCurrency } from "./TokenCurrency";
@@ -34,6 +33,7 @@ const useBuildGasOption = ({
gasPriceTable: GasPriceTable | undefined;
}) => {
const chainAssetsMap = useAtomValue(chainAssetsMapAtom);
+
const gasDollarMap =
useAtomValue(
tokenPricesFamily(gasPriceTable?.map((item) => item.token) ?? [])
@@ -54,10 +54,12 @@ const useBuildGasOption = ({
...override,
};
- const displayAmount = getDisplayGasFee(option);
+ const displayGasFee = getDisplayGasFee(option, chainAssetsMap);
+ const { totalDisplayAmount: displayAmount, asset } = displayGasFee;
+ const { symbol } = asset;
+
const price = gasDollarMap[option.gasToken];
const dollar = price ? price.multipliedBy(displayAmount) : undefined;
-
const selected =
!gasConfig.gasLimit.isEqualTo(0) &&
option.gasLimit.isEqualTo(gasConfig.gasLimit) &&
@@ -67,10 +69,6 @@ const useBuildGasOption = ({
const disabled =
gasConfig.gasLimit.isEqualTo(0) || gasConfig.gasPrice.isEqualTo(0);
- const asset =
- chainAssetsMap[option.gasToken] ?? unknownAsset(option.gasToken);
- const symbol = asset.symbol;
-
return {
option,
selected,
diff --git a/apps/namadillo/src/App/Common/TransactionFee.tsx b/apps/namadillo/src/App/Common/TransactionFee.tsx
index d2d5a100c..dc9c23211 100644
--- a/apps/namadillo/src/App/Common/TransactionFee.tsx
+++ b/apps/namadillo/src/App/Common/TransactionFee.tsx
@@ -1,28 +1,21 @@
-import { chainAssetsMapAtom } from "atoms/chain";
-import { useAtomValue } from "jotai";
-import { GasConfig } from "types";
-import { unknownAsset } from "utils/assets";
-import { getDisplayGasFee } from "utils/gas";
+import BigNumber from "bignumber.js";
import { TokenCurrency } from "./TokenCurrency";
-export const TransactionFee = ({
- gasConfig,
-}: {
- gasConfig: GasConfig;
-}): JSX.Element => {
- const chainAssetsMap = useAtomValue(chainAssetsMapAtom);
-
- const { gasToken } = gasConfig;
- const asset = chainAssetsMap[gasToken] ?? unknownAsset(gasToken);
-
- const amount = getDisplayGasFee(gasConfig);
+type TransactionFeeProps = {
+ displayAmount: BigNumber;
+ symbol: string;
+};
+export const TransactionFee = ({
+ displayAmount,
+ symbol,
+}: TransactionFeeProps): JSX.Element => {
return (
Transaction fee:{" "}
diff --git a/apps/namadillo/src/App/Common/TransactionFeeButton.tsx b/apps/namadillo/src/App/Common/TransactionFeeButton.tsx
index 11e605ff1..96a988ed0 100644
--- a/apps/namadillo/src/App/Common/TransactionFeeButton.tsx
+++ b/apps/namadillo/src/App/Common/TransactionFeeButton.tsx
@@ -1,5 +1,8 @@
+import { chainAssetsMapAtom } from "atoms/chain";
import { TransactionFeeProps } from "hooks/useTransactionFee";
-import { useState } from "react";
+import { useAtomValue } from "jotai";
+import { useMemo, useState } from "react";
+import { getDisplayGasFee } from "utils/gas";
import { GasFeeModal } from "./GasFeeModal";
import { TransactionFee } from "./TransactionFee";
@@ -9,6 +12,11 @@ export const TransactionFeeButton = ({
feeProps: TransactionFeeProps;
}): JSX.Element => {
const [modalOpen, setModalOpen] = useState(false);
+ const chainAssetsMap = useAtomValue(chainAssetsMapAtom);
+ const gasDisplayAmount = useMemo(() => {
+ return getDisplayGasFee(feeProps.gasConfig, chainAssetsMap);
+ }, [feeProps]);
+
return (
<>
{modalOpen && (
setModalOpen(false)} />
diff --git a/apps/namadillo/src/App/Ibc/ShieldAllPanel.tsx b/apps/namadillo/src/App/Ibc/ShieldAllPanel.tsx
index 0d6f4cde4..b1ed6573e 100644
--- a/apps/namadillo/src/App/Ibc/ShieldAllPanel.tsx
+++ b/apps/namadillo/src/App/Ibc/ShieldAllPanel.tsx
@@ -6,9 +6,7 @@ import {
Stack,
} from "@namada/components";
import svgImg from "App/Assets/ShieldedParty.svg";
-import { TransactionFee } from "App/Common/TransactionFee";
import { SelectedWallet } from "App/Transfer/SelectedWallet";
-import { getIbcGasConfig } from "integrations/utils";
import { useEffect, useMemo, useState } from "react";
import {
AddressWithAssetAndAmount,
@@ -32,7 +30,6 @@ type ShieldAllPanelProps = {
};
export const ShieldAllPanel = ({
- registry,
wallet,
walletAddress,
isLoading,
@@ -77,7 +74,7 @@ export const ShieldAllPanel = ({
[selectableAssets]
);
- const gasConfig = getIbcGasConfig(registry);
+ //const gasConfig = getIbcGasConfig(registry);
return (
@@ -118,7 +115,7 @@ export const ShieldAllPanel = ({
}
{changeFeeEnabled ?
feeProps &&
- : gasConfig && }
+ : gasDisplayAmount &&
+ gasAsset && (
+
+ )
+ }
diff --git a/apps/namadillo/src/App/Transfer/TransferModule.tsx b/apps/namadillo/src/App/Transfer/TransferModule.tsx
index 15d640e70..72ad999cb 100644
--- a/apps/namadillo/src/App/Transfer/TransferModule.tsx
+++ b/apps/namadillo/src/App/Transfer/TransferModule.tsx
@@ -2,8 +2,10 @@ import { Chain, Chains } from "@chain-registry/types";
import { ActionButton, Stack } from "@namada/components";
import { mapUndefined } from "@namada/utils";
import { InlineError } from "App/Common/InlineError";
+import { chainAssetsMapAtom } from "atoms/chain";
import BigNumber from "bignumber.js";
import { TransactionFeeProps } from "hooks/useTransactionFee";
+import { useAtomValue } from "jotai";
import { useMemo, useState } from "react";
import {
Address,
@@ -115,9 +117,16 @@ export const TransferModule = ({
const [customAddressActive, setCustomAddressActive] = useState(
destination.enableCustomAddress && !destination.availableWallets
);
+ const chainAssetsMap = useAtomValue(chainAssetsMapAtom);
+
const [memo, setMemo] = useState();
const gasConfig = gasConfigProp ?? feeProps?.gasConfig;
+
+ const displayGasFee = useMemo(() => {
+ return gasConfig ? getDisplayGasFee(gasConfig, chainAssetsMap) : undefined;
+ }, [gasConfig]);
+
const selectedAsset = mapUndefined(
(address) => source.availableAssets?.[address],
source.selectedAssetAddress
@@ -132,14 +141,16 @@ export const TransferModule = ({
return undefined;
}
- if (!gasConfig || gasConfig.gasToken !== selectedAssetAddress) {
+ if (!displayGasFee || !displayGasFee.totalDisplayAmount) {
return availableAmount;
}
- const totalFees = getDisplayGasFee(gasConfig);
- const amountMinusFees = availableAmount.minus(totalFees);
+ const amountMinusFees = availableAmount.minus(
+ displayGasFee.totalDisplayAmount
+ );
+
return BigNumber.max(amountMinusFees, 0);
- }, [source.selectedAssetAddress, source.availableAmount, gasConfig]);
+ }, [source.selectedAssetAddress, source.availableAmount, displayGasFee]);
const validationResult = useMemo((): ValidationResult => {
if (!source.wallet) {
@@ -323,9 +334,10 @@ export const TransferModule = ({
onChangeAddress={destination.onChangeCustomAddress}
memo={memo}
onChangeMemo={setMemo}
- gasConfig={gasConfig}
feeProps={feeProps}
changeFeeEnabled={changeFeeEnabled}
+ gasDisplayAmount={displayGasFee?.totalDisplayAmount}
+ gasAsset={displayGasFee?.asset}
/>
{isIbcTransfer && requiresIbcChannels && (
"ibc-transfer-white.png");
jest.mock("../../Common/GasFeeModal", () => null);
@@ -8,7 +9,7 @@ import {
randomChainMock,
} from "App/Transfer/__mocks__/chains";
import { TransferDestination } from "App/Transfer/TransferDestination";
-import BigNumber from "bignumber.js";
+import { namadaAsset } from "utils";
import { walletMock } from "../__mocks__/providers";
import { parseChainInfo } from "../common";
@@ -99,11 +100,8 @@ describe("Component: TransferDestination", () => {
render(
);
const transactionFee = screen.getByText("Transaction fee:");
diff --git a/apps/namadillo/src/App/Transfer/common.ts b/apps/namadillo/src/App/Transfer/common.ts
index c273785a2..c8c77cbf4 100644
--- a/apps/namadillo/src/App/Transfer/common.ts
+++ b/apps/namadillo/src/App/Transfer/common.ts
@@ -23,5 +23,9 @@ export const parseChainInfo = (
};
export const isShieldedAddress = (address: string): boolean => {
- return address.startsWith("znam"); // TODO: integrate with registry
+ return address.startsWith("znam");
+};
+
+export const isTransparentAddress = (address: string): boolean => {
+ return address.startsWith("tnam");
};
diff --git a/apps/namadillo/src/integrations/utils.ts b/apps/namadillo/src/integrations/utils.ts
index b44e15913..3e93c3b23 100644
--- a/apps/namadillo/src/integrations/utils.ts
+++ b/apps/namadillo/src/integrations/utils.ts
@@ -1,7 +1,11 @@
import { Asset, Chain } from "@chain-registry/types";
import { Bech32Config, ChainInfo, Currency } from "@keplr-wallet/types";
import tokenImage from "App/Common/assets/token.svg";
-import { getRestApiAddressByIndex, getRpcByIndex } from "atoms/integrations";
+import {
+ getKnownChains,
+ getRestApiAddressByIndex,
+ getRpcByIndex,
+} from "atoms/integrations";
import BigNumber from "bignumber.js";
import { ChainId, ChainRegistryEntry, GasConfig } from "types";
@@ -27,11 +31,16 @@ export const findRegistryByChainId = (
return undefined;
};
-export const findAssetByDenom = (
- registry: ChainRegistryEntry,
- denom: string
-): Asset | undefined => {
- return registry.assets.assets.find((asset) => asset.base === denom);
+export const findAssetByDenom = (denom: string): Asset | undefined => {
+ const chainRegistry = getKnownChains();
+ if (!chainRegistry) return undefined;
+
+ for (const registry of chainRegistry) {
+ const asset = registry.assets.assets.find((asset) => asset.base === denom);
+ if (asset) return asset;
+ }
+
+ return undefined;
};
export const getAssetImageUrl = (asset?: Asset): string => {
diff --git a/apps/namadillo/src/types.ts b/apps/namadillo/src/types.ts
index 3621c48a1..e6f90231d 100644
--- a/apps/namadillo/src/types.ts
+++ b/apps/namadillo/src/types.ts
@@ -42,6 +42,11 @@ export type GasConfig = {
gasToken: GasToken;
};
+export type GasConfigToDisplay = {
+ totalDisplayAmount: BigNumber;
+ asset: Asset;
+};
+
export type TxGas = Record;
export type GasTable = Record;
diff --git a/apps/namadillo/src/utils/gas.ts b/apps/namadillo/src/utils/gas.ts
index c5dd1ef77..ba194b9e0 100644
--- a/apps/namadillo/src/utils/gas.ts
+++ b/apps/namadillo/src/utils/gas.ts
@@ -1,8 +1,37 @@
+import { Asset } from "@chain-registry/types";
+import { isTransparentAddress } from "App/Transfer/common";
import BigNumber from "bignumber.js";
-import { GasConfig } from "types";
+import { findAssetByDenom } from "integrations/utils";
+import { Address, GasConfig, GasConfigToDisplay } from "types";
+import { isNamadaAsset, toDisplayAmount } from "utils";
+import { unknownAsset } from "./assets";
-export const getDisplayGasFee = (gasConfig: GasConfig): BigNumber => {
- return BigNumber(gasConfig.gasPrice)
- .multipliedBy(gasConfig.gasLimit)
- .decimalPlaces(6);
+export const calculateGasFee = (gasConfig: GasConfig): BigNumber => {
+ return BigNumber(gasConfig.gasPrice).multipliedBy(gasConfig.gasLimit);
+};
+
+export const getDisplayGasFee = (
+ gasConfig: GasConfig,
+ chainAssetsMap?: Record
+): GasConfigToDisplay => {
+ const { gasToken } = gasConfig;
+ let asset: Asset;
+
+ if (isTransparentAddress(gasToken) && chainAssetsMap) {
+ // The gasConfig token might be the address of the token on Namada chain
+ asset = chainAssetsMap[gasToken] ?? unknownAsset(gasToken);
+ } else {
+ // However, if the gasConfig contains a token used by Keplr, it could be the asset
+ // denomination unit, like "uosmo"
+ asset = findAssetByDenom(gasToken) ?? unknownAsset(gasToken);
+ }
+
+ const totalDisplayAmount = calculateGasFee(gasConfig);
+ return {
+ totalDisplayAmount:
+ isNamadaAsset(asset) ? totalDisplayAmount : (
+ toDisplayAmount(asset, totalDisplayAmount).decimalPlaces(6)
+ ),
+ asset,
+ };
};