Skip to content

Commit 15f5fa5

Browse files
authored
feat: add gas token (#1410)
1 parent e19b7da commit 15f5fa5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+562
-429
lines changed

apps/namadillo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@namada/namadillo",
3-
"version": "1.0.6",
3+
"version": "1.1.0",
44
"description": "Namadillo",
55
"repository": "https://github.com/anoma/namada-interface/",
66
"author": "Heliax Dev <info@heliax.dev>",
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { Modal, SkeletonLoading } from "@namada/components";
2+
import { chainAssetsMapAtom, nativeTokenAddressAtom } from "atoms/chain";
3+
import {
4+
gasPriceForAllTokensAtom,
5+
storageGasTokenAtom,
6+
} from "atoms/fees/atoms";
7+
import { tokenPricesFamily } from "atoms/prices/atoms";
8+
import BigNumber from "bignumber.js";
9+
import { useAtomValue, useSetAtom } from "jotai";
10+
import { IoClose } from "react-icons/io5";
11+
import { twMerge } from "tailwind-merge";
12+
import { GasConfig } from "types";
13+
import { unknownAsset } from "utils/assets";
14+
import { getDisplayGasFee } from "utils/gas";
15+
import { FiatCurrency } from "./FiatCurrency";
16+
import { TokenCurrency } from "./TokenCurrency";
17+
18+
export const GasFeeModal = ({
19+
gasConfig,
20+
onClose,
21+
}: {
22+
gasConfig: GasConfig;
23+
onClose: () => void;
24+
}): JSX.Element => {
25+
const setStorageGasToken = useSetAtom(storageGasTokenAtom);
26+
const gasPriceForAllTokens = useAtomValue(gasPriceForAllTokensAtom);
27+
const chainAssetsMap = useAtomValue(chainAssetsMapAtom);
28+
const nativeTokenAddress = useAtomValue(nativeTokenAddressAtom).data;
29+
30+
const data = gasPriceForAllTokens.data ?? [];
31+
32+
const tokenAddresses = data.map((item) => item.token);
33+
const gasDollarMap = useAtomValue(tokenPricesFamily(tokenAddresses));
34+
35+
return (
36+
<Modal onClose={onClose}>
37+
<div
38+
className={twMerge(
39+
"fixed min-w-[550px] top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2",
40+
"px-6 py-7 bg-rblack border border-neutral-500 rounded-md"
41+
)}
42+
>
43+
<i
44+
className={twMerge(
45+
"cursor-pointer text-white absolute right-3 top-3 text-xl",
46+
"hover:text-yellow transition-colors"
47+
)}
48+
onClick={onClose}
49+
>
50+
<IoClose />
51+
</i>
52+
<div className="text-center">
53+
<h2 className="font-medium">Select Gas Token</h2>
54+
<div className="text-sm mt-1">
55+
Gas fees deducted from your Namada accounts
56+
</div>
57+
</div>
58+
<div className="flex flex-col mt-4 max-h-[60vh] overflow-auto">
59+
{!data.length ?
60+
<SkeletonLoading height="100px" width="100%" />
61+
: data
62+
.sort((a, b) =>
63+
a.token === nativeTokenAddress ? -1
64+
: b.token === nativeTokenAddress ? 1
65+
: 0
66+
)
67+
.map(({ token, minDenomAmount }) => {
68+
const asset = chainAssetsMap[token] ?? unknownAsset(token);
69+
const symbol = asset.symbol;
70+
const fee = getDisplayGasFee({
71+
gasLimit: gasConfig.gasLimit,
72+
gasPrice: BigNumber(minDenomAmount),
73+
gasToken: token,
74+
asset,
75+
});
76+
const price = gasDollarMap.data?.[token];
77+
const dollar = price ? fee.multipliedBy(price) : undefined;
78+
79+
const selected = token === gasConfig.gasToken;
80+
81+
return (
82+
<button
83+
key={token}
84+
className={twMerge(
85+
"flex justify-between items-center",
86+
"bg-rblack rounded-sm px-5 min-h-[58px]",
87+
"hover:text-yellow hover:border-yellow transition-colors duration-300",
88+
selected ? "border border-white" : "m-px"
89+
)}
90+
type="button"
91+
onClick={() => {
92+
setStorageGasToken(token);
93+
onClose();
94+
}}
95+
>
96+
<div>{symbol}</div>
97+
<div className="text-right">
98+
{dollar && <FiatCurrency amount={dollar} />}
99+
<div className="text-xs">
100+
<TokenCurrency amount={fee} symbol={symbol} />
101+
</div>
102+
</div>
103+
</button>
104+
);
105+
})
106+
}
107+
</div>
108+
</div>
109+
</Modal>
110+
);
111+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { GasConfig } from "types";
2+
import { unknownAsset } from "utils/assets";
3+
import { getDisplayGasFee } from "utils/gas";
4+
import { TokenCurrency } from "./TokenCurrency";
5+
6+
export const TransactionFee = ({
7+
gasConfig,
8+
}: {
9+
gasConfig: GasConfig;
10+
}): JSX.Element => {
11+
const asset = gasConfig.asset ?? unknownAsset(gasConfig.gasToken);
12+
const symbol = asset.symbol;
13+
const fee = getDisplayGasFee(gasConfig);
14+
15+
return (
16+
<div className="text-sm">
17+
<span className="underline">Transaction fee:</span>{" "}
18+
<TokenCurrency symbol={symbol} amount={fee} className="font-medium " />
19+
</div>
20+
);
21+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useState } from "react";
2+
import { GasConfig } from "types";
3+
import { GasFeeModal } from "./GasFeeModal";
4+
import { TransactionFee } from "./TransactionFee";
5+
6+
export const TransactionFeeButton = ({
7+
gasConfig,
8+
}: {
9+
gasConfig: GasConfig;
10+
}): JSX.Element => {
11+
const [modalOpen, setModalOpen] = useState(false);
12+
13+
return (
14+
<>
15+
<button
16+
type="button"
17+
className="hover:underline cursor-pointer"
18+
onClick={() => setModalOpen(true)}
19+
>
20+
<TransactionFee gasConfig={gasConfig} />
21+
</button>
22+
{modalOpen && (
23+
<GasFeeModal
24+
gasConfig={gasConfig}
25+
onClose={() => setModalOpen(false)}
26+
/>
27+
)}
28+
</>
29+
);
30+
};

apps/namadillo/src/App/Common/TransactionFees.tsx

Lines changed: 0 additions & 23 deletions
This file was deleted.

apps/namadillo/src/App/Governance/SubmitVote.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
isVoteType,
1313
voteTypes,
1414
} from "@namada/types";
15-
import { TransactionFees } from "App/Common/TransactionFees";
15+
import { TransactionFeeButton } from "App/Common/TransactionFeeButton";
1616
import { defaultGasConfigFamily } from "atoms/fees";
1717
import {
1818
createNotificationId,
@@ -181,10 +181,9 @@ export const WithProposalId: React.FC<{ proposalId: bigint }> = ({
181181
</Stack>
182182
<footer>
183183
{gasConfig.isSuccess && (
184-
<TransactionFees
185-
className="flex justify-between"
186-
gasConfig={gasConfig.data}
187-
/>
184+
<div className="justify-self-end">
185+
<TransactionFeeButton gasConfig={gasConfig.data} />
186+
</div>
188187
)}
189188
</footer>
190189
<ActionButton

apps/namadillo/src/App/Ibc/IbcTransfer.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { useTransactionActions } from "hooks/useTransactionActions";
2121
import { useWalletManager } from "hooks/useWalletManager";
2222
import { wallets } from "integrations";
2323
import { KeplrWalletManager } from "integrations/Keplr";
24-
import { getTransactionFee } from "integrations/utils";
24+
import { getIbcGasConfig } from "integrations/utils";
2525
import { useAtomValue } from "jotai";
2626
import { useEffect, useMemo, useState } from "react";
2727
import namadaChain from "registry/namada.json";
@@ -71,9 +71,9 @@ export const IbcTransfer: React.FC = () => {
7171
selectedAssetAddress
7272
);
7373

74-
const transactionFee = useMemo(() => {
74+
const gasConfig = useMemo(() => {
7575
if (typeof registry !== "undefined") {
76-
return getTransactionFee(registry);
76+
return getIbcGasConfig(registry);
7777
}
7878
return undefined;
7979
}, [registry]);
@@ -144,7 +144,7 @@ export const IbcTransfer: React.FC = () => {
144144
throw new Error("Invalid IBC destination channel");
145145
}
146146

147-
if (typeof transactionFee === "undefined") {
147+
if (typeof gasConfig === "undefined") {
148148
throw new Error("No transaction fee is set");
149149
}
150150

@@ -179,7 +179,7 @@ export const IbcTransfer: React.FC = () => {
179179
destinationAddress,
180180
amount: displayAmount,
181181
asset: selectedAsset,
182-
transactionFee,
182+
gasConfig,
183183
sourceChannelId: sourceChannel.trim(),
184184
...(shielded ?
185185
{
@@ -254,7 +254,7 @@ export const IbcTransfer: React.FC = () => {
254254
isShielded: shielded,
255255
onChangeShielded: setShielded,
256256
}}
257-
transactionFee={transactionFee}
257+
gasConfig={gasConfig}
258258
isSubmitting={performIbcTransfer.isPending}
259259
isIbcTransfer={true}
260260
requiresIbcChannels={requiresIbcChannels}

apps/namadillo/src/App/Ibc/IbcWithdraw.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import { broadcastTx } from "lib/query";
2424
import { useEffect, useState } from "react";
2525
import namadaChainRegistry from "registry/namada.json";
2626
import { Address, PartialTransferTransactionData, TransferStep } from "types";
27-
import { namadaAsset } from "utils";
2827
import { IbcTopHeader } from "./IbcTopHeader";
2928

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

56-
const transactionFee = mapUndefined(
57-
({ gasLimit, gasPrice }) => ({
58-
originalAddress: namadaAsset().address,
59-
asset: namadaAsset(),
60-
amount: gasPrice.multipliedBy(gasLimit),
61-
}),
62-
gasConfig
63-
);
64-
6555
const {
6656
walletAddress: keplrAddress,
6757
connectToChainId,
@@ -203,7 +193,7 @@ export const IbcWithdraw: React.FC = () => {
203193
onChangeSourceChannel: setSourceChannel,
204194
}}
205195
onSubmitTransfer={submitIbcTransfer}
206-
transactionFee={transactionFee}
196+
gasConfig={gasConfig}
207197
errorMessage={generalErrorMessage}
208198
/>
209199
</>

apps/namadillo/src/App/Ibc/ShieldAllPanel.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import {
66
Stack,
77
} from "@namada/components";
88
import svgImg from "App/Assets/ShieldedParty.svg";
9+
import { TransactionFee } from "App/Common/TransactionFee";
910
import { SelectedWallet } from "App/Transfer/SelectedWallet";
10-
import { TransferTransactionFee } from "App/Transfer/TransferTransactionFee";
11-
import { getTransactionFee } from "integrations/utils";
11+
import { getIbcGasConfig } from "integrations/utils";
1212
import { useEffect, useMemo, useState } from "react";
1313
import {
1414
AddressWithAssetAndAmount,
@@ -20,6 +20,7 @@ import {
2020
ShieldAllAssetList,
2121
} from "./ShieldAllAssetList";
2222
import { ShieldAllContainer } from "./ShieldAllContainer";
23+
import ibcTransferImageBlack from "./assets/ibc-transfer-black.png";
2324

2425
type ShieldAllPanelProps = {
2526
registry: ChainRegistryEntry;
@@ -76,7 +77,7 @@ export const ShieldAllPanel = ({
7677
[selectableAssets]
7778
);
7879

79-
const transactionFee = getTransactionFee(registry);
80+
const gasConfig = getIbcGasConfig(registry);
8081

8182
return (
8283
<ShieldAllContainer>
@@ -115,13 +116,10 @@ export const ShieldAllPanel = ({
115116
}
116117
</Stack>
117118
<Stack as="footer" gap={4}>
118-
{transactionFee && (
119-
<TransferTransactionFee
120-
transactionFee={transactionFee}
121-
isIbcTransfer={true}
122-
textColor="black"
123-
/>
124-
)}
119+
<footer className="flex justify-between items-center">
120+
<img src={ibcTransferImageBlack} className="w-20" />
121+
{gasConfig && <TransactionFee gasConfig={gasConfig} />}
122+
</footer>
125123
<ActionButton
126124
backgroundColor="black"
127125
backgroundHoverColor="cyan"

apps/namadillo/src/App/Ibc/ShieldAllProgress.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Stack } from "@namada/components";
22
import svgImg from "App/Assets/ShieldedParty.svg";
33
import { Timeline } from "App/Common/Timeline";
4-
import ibcTransferBlack from "../Transfer/assets/ibc-transfer-black.png";
4+
import ibcTransferBlack from "./assets/ibc-transfer-black.png";
55
import { ShieldAllContainer } from "./ShieldAllContainer";
66

77
export const ShieldAllProgress = (): JSX.Element => {

0 commit comments

Comments
 (0)