Skip to content

Commit

Permalink
feat: add gas token (#1410)
Browse files Browse the repository at this point in the history
  • Loading branch information
euharrison authored Dec 18, 2024
1 parent e19b7da commit 15f5fa5
Show file tree
Hide file tree
Showing 43 changed files with 562 additions and 429 deletions.
2 changes: 1 addition & 1 deletion apps/namadillo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@namada/namadillo",
"version": "1.0.6",
"version": "1.1.0",
"description": "Namadillo",
"repository": "https://github.com/anoma/namada-interface/",
"author": "Heliax Dev <[email protected]>",
Expand Down
111 changes: 111 additions & 0 deletions apps/namadillo/src/App/Common/GasFeeModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { Modal, SkeletonLoading } from "@namada/components";
import { chainAssetsMapAtom, nativeTokenAddressAtom } from "atoms/chain";
import {
gasPriceForAllTokensAtom,
storageGasTokenAtom,
} from "atoms/fees/atoms";
import { tokenPricesFamily } from "atoms/prices/atoms";
import BigNumber from "bignumber.js";
import { useAtomValue, useSetAtom } 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";

export const GasFeeModal = ({
gasConfig,
onClose,
}: {
gasConfig: GasConfig;
onClose: () => void;
}): JSX.Element => {
const setStorageGasToken = useSetAtom(storageGasTokenAtom);
const gasPriceForAllTokens = useAtomValue(gasPriceForAllTokensAtom);
const chainAssetsMap = useAtomValue(chainAssetsMapAtom);
const nativeTokenAddress = useAtomValue(nativeTokenAddressAtom).data;

const data = gasPriceForAllTokens.data ?? [];

const tokenAddresses = data.map((item) => item.token);
const gasDollarMap = useAtomValue(tokenPricesFamily(tokenAddresses));

return (
<Modal onClose={onClose}>
<div
className={twMerge(
"fixed min-w-[550px] top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2",
"px-6 py-7 bg-rblack border border-neutral-500 rounded-md"
)}
>
<i
className={twMerge(
"cursor-pointer text-white absolute right-3 top-3 text-xl",
"hover:text-yellow transition-colors"
)}
onClick={onClose}
>
<IoClose />
</i>
<div className="text-center">
<h2 className="font-medium">Select Gas Token</h2>
<div className="text-sm mt-1">
Gas fees deducted from your Namada accounts
</div>
</div>
<div className="flex flex-col mt-4 max-h-[60vh] overflow-auto">
{!data.length ?
<SkeletonLoading height="100px" width="100%" />
: data
.sort((a, b) =>
a.token === nativeTokenAddress ? -1
: b.token === nativeTokenAddress ? 1
: 0
)
.map(({ token, minDenomAmount }) => {
const asset = chainAssetsMap[token] ?? unknownAsset(token);
const symbol = asset.symbol;
const fee = getDisplayGasFee({
gasLimit: gasConfig.gasLimit,
gasPrice: BigNumber(minDenomAmount),
gasToken: token,
asset,
});
const price = gasDollarMap.data?.[token];
const dollar = price ? fee.multipliedBy(price) : undefined;

const selected = token === gasConfig.gasToken;

return (
<button
key={token}
className={twMerge(
"flex justify-between items-center",
"bg-rblack rounded-sm px-5 min-h-[58px]",
"hover:text-yellow hover:border-yellow transition-colors duration-300",
selected ? "border border-white" : "m-px"
)}
type="button"
onClick={() => {
setStorageGasToken(token);
onClose();
}}
>
<div>{symbol}</div>
<div className="text-right">
{dollar && <FiatCurrency amount={dollar} />}
<div className="text-xs">
<TokenCurrency amount={fee} symbol={symbol} />
</div>
</div>
</button>
);
})
}
</div>
</div>
</Modal>
);
};
21 changes: 21 additions & 0 deletions apps/namadillo/src/App/Common/TransactionFee.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { GasConfig } from "types";
import { unknownAsset } from "utils/assets";
import { getDisplayGasFee } from "utils/gas";
import { TokenCurrency } from "./TokenCurrency";

export const TransactionFee = ({
gasConfig,
}: {
gasConfig: GasConfig;
}): JSX.Element => {
const asset = gasConfig.asset ?? unknownAsset(gasConfig.gasToken);
const symbol = asset.symbol;
const fee = getDisplayGasFee(gasConfig);

return (
<div className="text-sm">
<span className="underline">Transaction fee:</span>{" "}
<TokenCurrency symbol={symbol} amount={fee} className="font-medium " />
</div>
);
};
30 changes: 30 additions & 0 deletions apps/namadillo/src/App/Common/TransactionFeeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useState } from "react";
import { GasConfig } from "types";
import { GasFeeModal } from "./GasFeeModal";
import { TransactionFee } from "./TransactionFee";

export const TransactionFeeButton = ({
gasConfig,
}: {
gasConfig: GasConfig;
}): JSX.Element => {
const [modalOpen, setModalOpen] = useState(false);

return (
<>
<button
type="button"
className="hover:underline cursor-pointer"
onClick={() => setModalOpen(true)}
>
<TransactionFee gasConfig={gasConfig} />
</button>
{modalOpen && (
<GasFeeModal
gasConfig={gasConfig}
onClose={() => setModalOpen(false)}
/>
)}
</>
);
};
23 changes: 0 additions & 23 deletions apps/namadillo/src/App/Common/TransactionFees.tsx

This file was deleted.

9 changes: 4 additions & 5 deletions apps/namadillo/src/App/Governance/SubmitVote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
isVoteType,
voteTypes,
} from "@namada/types";
import { TransactionFees } from "App/Common/TransactionFees";
import { TransactionFeeButton } from "App/Common/TransactionFeeButton";
import { defaultGasConfigFamily } from "atoms/fees";
import {
createNotificationId,
Expand Down Expand Up @@ -181,10 +181,9 @@ export const WithProposalId: React.FC<{ proposalId: bigint }> = ({
</Stack>
<footer>
{gasConfig.isSuccess && (
<TransactionFees
className="flex justify-between"
gasConfig={gasConfig.data}
/>
<div className="justify-self-end">
<TransactionFeeButton gasConfig={gasConfig.data} />
</div>
)}
</footer>
<ActionButton
Expand Down
12 changes: 6 additions & 6 deletions apps/namadillo/src/App/Ibc/IbcTransfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useTransactionActions } from "hooks/useTransactionActions";
import { useWalletManager } from "hooks/useWalletManager";
import { wallets } from "integrations";
import { KeplrWalletManager } from "integrations/Keplr";
import { getTransactionFee } from "integrations/utils";
import { getIbcGasConfig } from "integrations/utils";
import { useAtomValue } from "jotai";
import { useEffect, useMemo, useState } from "react";
import namadaChain from "registry/namada.json";
Expand Down Expand Up @@ -71,9 +71,9 @@ export const IbcTransfer: React.FC = () => {
selectedAssetAddress
);

const transactionFee = useMemo(() => {
const gasConfig = useMemo(() => {
if (typeof registry !== "undefined") {
return getTransactionFee(registry);
return getIbcGasConfig(registry);
}
return undefined;
}, [registry]);
Expand Down Expand Up @@ -144,7 +144,7 @@ export const IbcTransfer: React.FC = () => {
throw new Error("Invalid IBC destination channel");
}

if (typeof transactionFee === "undefined") {
if (typeof gasConfig === "undefined") {
throw new Error("No transaction fee is set");
}

Expand Down Expand Up @@ -179,7 +179,7 @@ export const IbcTransfer: React.FC = () => {
destinationAddress,
amount: displayAmount,
asset: selectedAsset,
transactionFee,
gasConfig,
sourceChannelId: sourceChannel.trim(),
...(shielded ?
{
Expand Down Expand Up @@ -254,7 +254,7 @@ export const IbcTransfer: React.FC = () => {
isShielded: shielded,
onChangeShielded: setShielded,
}}
transactionFee={transactionFee}
gasConfig={gasConfig}
isSubmitting={performIbcTransfer.isPending}
isIbcTransfer={true}
requiresIbcChannels={requiresIbcChannels}
Expand Down
12 changes: 1 addition & 11 deletions apps/namadillo/src/App/Ibc/IbcWithdraw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { broadcastTx } from "lib/query";
import { useEffect, useState } from "react";
import namadaChainRegistry from "registry/namada.json";
import { Address, PartialTransferTransactionData, TransferStep } from "types";
import { namadaAsset } from "utils";
import { IbcTopHeader } from "./IbcTopHeader";

const defaultChainId = "cosmoshub-4";
Expand Down Expand Up @@ -53,15 +52,6 @@ export const IbcWithdraw: React.FC = () => {
defaultGasConfigFamily(["IbcTransfer"])
);

const transactionFee = mapUndefined(
({ gasLimit, gasPrice }) => ({
originalAddress: namadaAsset().address,
asset: namadaAsset(),
amount: gasPrice.multipliedBy(gasLimit),
}),
gasConfig
);

const {
walletAddress: keplrAddress,
connectToChainId,
Expand Down Expand Up @@ -203,7 +193,7 @@ export const IbcWithdraw: React.FC = () => {
onChangeSourceChannel: setSourceChannel,
}}
onSubmitTransfer={submitIbcTransfer}
transactionFee={transactionFee}
gasConfig={gasConfig}
errorMessage={generalErrorMessage}
/>
</>
Expand Down
18 changes: 8 additions & 10 deletions apps/namadillo/src/App/Ibc/ShieldAllPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ 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 { TransferTransactionFee } from "App/Transfer/TransferTransactionFee";
import { getTransactionFee } from "integrations/utils";
import { getIbcGasConfig } from "integrations/utils";
import { useEffect, useMemo, useState } from "react";
import {
AddressWithAssetAndAmount,
Expand All @@ -20,6 +20,7 @@ import {
ShieldAllAssetList,
} from "./ShieldAllAssetList";
import { ShieldAllContainer } from "./ShieldAllContainer";
import ibcTransferImageBlack from "./assets/ibc-transfer-black.png";

type ShieldAllPanelProps = {
registry: ChainRegistryEntry;
Expand Down Expand Up @@ -76,7 +77,7 @@ export const ShieldAllPanel = ({
[selectableAssets]
);

const transactionFee = getTransactionFee(registry);
const gasConfig = getIbcGasConfig(registry);

return (
<ShieldAllContainer>
Expand Down Expand Up @@ -115,13 +116,10 @@ export const ShieldAllPanel = ({
}
</Stack>
<Stack as="footer" gap={4}>
{transactionFee && (
<TransferTransactionFee
transactionFee={transactionFee}
isIbcTransfer={true}
textColor="black"
/>
)}
<footer className="flex justify-between items-center">
<img src={ibcTransferImageBlack} className="w-20" />
{gasConfig && <TransactionFee gasConfig={gasConfig} />}
</footer>
<ActionButton
backgroundColor="black"
backgroundHoverColor="cyan"
Expand Down
2 changes: 1 addition & 1 deletion apps/namadillo/src/App/Ibc/ShieldAllProgress.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Stack } from "@namada/components";
import svgImg from "App/Assets/ShieldedParty.svg";
import { Timeline } from "App/Common/Timeline";
import ibcTransferBlack from "../Transfer/assets/ibc-transfer-black.png";
import ibcTransferBlack from "./assets/ibc-transfer-black.png";
import { ShieldAllContainer } from "./ShieldAllContainer";

export const ShieldAllProgress = (): JSX.Element => {
Expand Down
12 changes: 1 addition & 11 deletions apps/namadillo/src/App/Masp/MaspShield.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Timeline } from "App/Common/Timeline";
import { params } from "App/routes";
import {
OnSubmitTransferParams,
TransactionFee,
TransferModule,
} from "App/Transfer/TransferModule";
import { allDefaultAccountsAtom } from "atoms/accounts";
Expand Down Expand Up @@ -71,15 +70,6 @@ export const MaspShield: React.FC = () => {
defaultGasConfigFamily(["ShieldingTransfer"])
);

const transactionFee: TransactionFee | undefined =
selectedAsset && gasConfig ?
{
originalAddress: selectedAsset.originalAddress,
asset: selectedAsset.asset,
amount: gasConfig.gasPrice.multipliedBy(gasConfig.gasLimit),
}
: undefined;

const assetImage = selectedAsset ? getAssetImageUrl(selectedAsset.asset) : "";

useEffect(() => {
Expand Down Expand Up @@ -207,7 +197,7 @@ export const MaspShield: React.FC = () => {
walletAddress: destinationAddress,
isShielded: true,
}}
transactionFee={transactionFee}
gasConfig={gasConfig}
isSubmitting={performShieldTransfer.isPending}
errorMessage={generalErrorMessage}
onSubmitTransfer={onSubmitTransfer}
Expand Down
Loading

1 comment on commit 15f5fa5

@github-actions
Copy link

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.