diff --git a/apps/namadillo/src/App/Common/SelectModal.tsx b/apps/namadillo/src/App/Common/SelectModal.tsx index 6e92dcc7f..448596d51 100644 --- a/apps/namadillo/src/App/Common/SelectModal.tsx +++ b/apps/namadillo/src/App/Common/SelectModal.tsx @@ -2,31 +2,39 @@ import { Modal } from "@namada/components"; import clsx from "clsx"; import React from "react"; import { IoClose } from "react-icons/io5"; +import { twMerge } from "tailwind-merge"; import { ModalTransition } from "./ModalTransition"; type SelectModalProps = { children: React.ReactNode; title: React.ReactNode; onClose: () => void; -}; +} & React.ComponentPropsWithoutRef<"div">; export const SelectModal = ({ children, title, onClose, + className, + ...props }: SelectModalProps): JSX.Element => { return (
-
+
{title} diff --git a/apps/namadillo/src/App/Common/TabSelector.tsx b/apps/namadillo/src/App/Common/TabSelector.tsx index 29e0eea6b..b25c5864f 100644 --- a/apps/namadillo/src/App/Common/TabSelector.tsx +++ b/apps/namadillo/src/App/Common/TabSelector.tsx @@ -18,25 +18,25 @@ export const TabSelector = ({ onChange, }: TabSelectorProps): JSX.Element => { return ( - +
    + {items.map((item) => ( +
  • + +
  • + ))} +
); }; diff --git a/apps/namadillo/src/App/Transfer/AssetCard.tsx b/apps/namadillo/src/App/Transfer/AssetCard.tsx new file mode 100644 index 000000000..7f48a72c1 --- /dev/null +++ b/apps/namadillo/src/App/Transfer/AssetCard.tsx @@ -0,0 +1,26 @@ +import { Asset } from "@chain-registry/types"; +import clsx from "clsx"; + +type AssetCardProps = { + asset: Asset; +}; + +export const AssetCard = ({ asset }: AssetCardProps): JSX.Element => { + const image = asset.logo_URIs?.svg || asset.logo_URIs?.png; + return ( + + {image ? + {asset.name + : } + {asset.name} + + ); +}; diff --git a/apps/namadillo/src/App/Transfer/AvailableAmountFooter.tsx b/apps/namadillo/src/App/Transfer/AvailableAmountFooter.tsx index e4a50c47a..093f72d19 100644 --- a/apps/namadillo/src/App/Transfer/AvailableAmountFooter.tsx +++ b/apps/namadillo/src/App/Transfer/AvailableAmountFooter.tsx @@ -18,6 +18,7 @@ export const AvailableAmountFooter = ({ return <>; } + // TODO: Replace usage here return (
diff --git a/apps/namadillo/src/App/Transfer/ChainCard.tsx b/apps/namadillo/src/App/Transfer/ChainCard.tsx index e69de29bb..8d76014ce 100644 --- a/apps/namadillo/src/App/Transfer/ChainCard.tsx +++ b/apps/namadillo/src/App/Transfer/ChainCard.tsx @@ -0,0 +1,19 @@ +import { Chain } from "@chain-registry/types"; +import clsx from "clsx"; + +type ChainCardProps = { + chain: Chain; +}; + +export const ChainCard = ({ chain }: ChainCardProps): JSX.Element => { + return ( + + {chain.pretty_name + {chain.pretty_name} + + ); +}; diff --git a/apps/namadillo/src/App/Transfer/Example.tsx b/apps/namadillo/src/App/Transfer/Example.tsx new file mode 100644 index 000000000..a113e7000 --- /dev/null +++ b/apps/namadillo/src/App/Transfer/Example.tsx @@ -0,0 +1,125 @@ +import BigNumber from "bignumber.js"; +import { useEffect, useState } from "react"; + +// This can be loaded async using @chain-registry/client +import { + chain as celestia, + assets as celestiaAssets, +} from "chain-registry/mainnet/celestia"; +import { + chain as cosmos, + assets as cosmosAssets, +} from "chain-registry/mainnet/cosmoshub"; +import { + chain as dydx, + assets as dydxAssets, +} from "chain-registry/mainnet/dydx"; +import { + chain as osmosis, + assets as osmosisAssets, +} from "chain-registry/mainnet/osmosis"; +import { + chain as stargaze, + assets as stargazeAssets, +} from "chain-registry/mainnet/stargaze"; +import { + chain as stride, + assets as strideAssets, +} from "chain-registry/mainnet/stride"; + +// This will be replaced by namada registry in the future +import namadaChain from "registry/namada.json"; + +import { Asset, Chain } from "@chain-registry/types"; +import { Panel } from "@namada/components"; +import { integrations } from "@namada/integrations"; +import { selectedIBCChainAtom, selectedIBCWallet } from "atoms/integrations"; +import { wallets } from "integrations"; +import { useAtom } from "jotai"; +import { useMemo } from "react"; +import { WalletProvider } from "types"; +import { TransferModule } from "./TransferModule"; + +export const Example = (): JSX.Element => { + const [selectedWallet, setWallet] = useAtom(selectedIBCWallet); + const [chainId, setChainId] = useAtom(selectedIBCChainAtom); + const [selectedAsset, setSelectedAsset] = useState(); + const [isShielded, setShielded] = useState(true); + + const sourceChainConfig: [Chain, Asset[]][] = [ + [cosmos, cosmosAssets.assets], + [osmosis, osmosisAssets.assets], + [celestia, celestiaAssets.assets], + [dydx, dydxAssets.assets], + [stride, strideAssets.assets], + [stargaze, stargazeAssets.assets], + ]; + + const sourceChains: Record = useMemo(() => { + return sourceChainConfig.reduce((prev, current) => { + return { + ...prev, + [current[0].chain_id]: current[0], + }; + }, {}); + }, []); + + const sourceAssetList: Asset[] | undefined = useMemo(() => { + if (!chainId) return; + const config = sourceChainConfig.find( + (config) => config[0].chain_id === chainId + ); + if (config) { + return config[1]; + } + }, [chainId]); + + const selectedSourceChain = + chainId && chainId in sourceChains ? sourceChains[chainId] : undefined; + + useEffect(() => { + const config = sourceChainConfig.find( + (config) => config[0].chain_id === chainId + ); + + if (config) { + setSelectedAsset(config[1][0]); + } + }, [chainId]); + + return ( + + {}} + availableWallets={Object.values(wallets)} + sourceWallet={selectedWallet ? wallets[selectedWallet] : undefined} + onChangeWallet={async (wallet: WalletProvider) => { + try { + await integrations[wallet.id].connect(); + setWallet(wallet.id); + if (!chainId) { + setChainId(cosmos.chain_id); + } + } catch (err) { + console.error(err); + } + }} + onChangeSourceChain={(chain) => { + setChainId(chain.chain_id); + }} + onChangeSelectedAsset={setSelectedAsset} + availableSourceChains={Object.values(sourceChains)} + availableAssets={sourceAssetList} + selectedAsset={selectedAsset} + sourceChain={selectedSourceChain} + destinationChain={namadaChain as Chain} + destinationWallet={wallets.namada} + isShielded={isShielded} + onChangeShielded={setShielded} + availableAmount={new BigNumber(100) /* Change this */} + transactionFee={new BigNumber(0.01)} + /> + + ); +}; diff --git a/apps/namadillo/src/App/Transfer/IBCFromNamadaModule.tsx b/apps/namadillo/src/App/Transfer/IBCFromNamadaModule.tsx deleted file mode 100644 index 15489d25c..000000000 --- a/apps/namadillo/src/App/Transfer/IBCFromNamadaModule.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { chain as celestia } from "chain-registry/mainnet/celestia"; -import { chain as cosmos } from "chain-registry/mainnet/cosmoshub"; -import { chain as dydx } from "chain-registry/mainnet/dydx"; -import { chain as osmosis } from "chain-registry/mainnet/osmosis"; -import { chain as stargaze } from "chain-registry/mainnet/stargaze"; -import { chain as stride } from "chain-registry/mainnet/stride"; - -import { integrations } from "@namada/integrations"; -import { selectedIBCChainAtom, selectedIBCWallet } from "atoms/integrations"; -import { wallets } from "integrations"; -import { useAtom } from "jotai"; -import { WalletProvider } from "types"; -import { TransferModule } from "./TransferModule"; - -export const IBCFromNamadaModule = (): JSX.Element => { - const [selectedWallet, setWallet] = useAtom(selectedIBCWallet); - const [chainId, setChainId] = useAtom(selectedIBCChainAtom); - const sourceChains = [cosmos, osmosis, celestia, dydx, stride, stargaze]; - - return ( -
- {}} - availableWallets={Object.values(wallets)} - selectedWallet={selectedWallet ? wallets[selectedWallet] : undefined} - onChangeWallet={async (wallet: WalletProvider) => { - try { - await integrations[wallet.id].connect(); - setWallet(wallet.id); - if (!chainId) { - setChainId(cosmos.chain_id); - } - } catch (err) { - console.error(err); - } - }} - onChangeSourceChain={(chain) => setChainId(chain.chain_id)} - availableSourceChains={sourceChains} - /> -
- ); -}; diff --git a/apps/namadillo/src/App/Transfer/IBCTransfers.tsx b/apps/namadillo/src/App/Transfer/IBCTransfers.tsx deleted file mode 100644 index 3a551ec52..000000000 --- a/apps/namadillo/src/App/Transfer/IBCTransfers.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Panel } from "@namada/components"; -import { IBCFromNamadaModule } from "./IBCFromNamadaModule"; - -export const IBCTransfers = (): JSX.Element => { - return ( -
- - - -
- ); -}; diff --git a/apps/namadillo/src/App/Transfer/SelectAssetModal.tsx b/apps/namadillo/src/App/Transfer/SelectAssetModal.tsx new file mode 100644 index 000000000..4dbb76ea6 --- /dev/null +++ b/apps/namadillo/src/App/Transfer/SelectAssetModal.tsx @@ -0,0 +1,61 @@ +import { Asset } from "@chain-registry/types"; +import { Stack } from "@namada/components"; +import { Search } from "App/Common/Search"; +import { SelectModal } from "App/Common/SelectModal"; +import clsx from "clsx"; +import { useMemo, useState } from "react"; +import { twMerge } from "tailwind-merge"; +import { AssetCard } from "./AssetCard"; + +type SelectWalletModalProps = { + onClose: () => void; + onSelect: (asset: Asset) => void; + assets: Asset[]; +}; + +export const SelectAssetModal = ({ + onClose, + onSelect, + assets, +}: SelectWalletModalProps): JSX.Element => { + const [filter, setFilter] = useState(""); + + const filteredAssets = useMemo(() => { + return assets.filter( + (asset) => + asset.name.indexOf(filter) >= 0 || asset.symbol.indexOf(filter) >= 0 + ); + }, [assets, filter]); + + return ( + +
+ +
+ + {filteredAssets.map((asset: Asset, index: number) => ( +
  • + +
  • + ))} +
    +
    + ); +}; diff --git a/apps/namadillo/src/App/Transfer/SelectChainModal.tsx b/apps/namadillo/src/App/Transfer/SelectChainModal.tsx index 774763aef..48056abd0 100644 --- a/apps/namadillo/src/App/Transfer/SelectChainModal.tsx +++ b/apps/namadillo/src/App/Transfer/SelectChainModal.tsx @@ -1,7 +1,11 @@ import { Chain, Chains } from "@chain-registry/types"; import { Stack } from "@namada/components"; +import { Search } from "App/Common/Search"; import { SelectModal } from "App/Common/SelectModal"; import clsx from "clsx"; +import { useMemo, useState } from "react"; +import { twMerge } from "tailwind-merge"; +import { ChainCard } from "./ChainCard"; type SelectChainModalProps = { onClose: () => void; @@ -14,30 +18,44 @@ export const SelectChainModal = ({ onSelect, chains, }: SelectChainModalProps): JSX.Element => { + const [filter, setFilter] = useState(""); + + const filteredChains = useMemo(() => { + return chains.filter((chain) => chain.pretty_name.indexOf(filter) >= 0); + }, [chains, filter]); + return ( - {chains.length > 0 && ( - - {chains.map((chain) => ( +
    + +
    + {filteredChains.length > 0 && ( + + {filteredChains.map((chain) => (
  • ))}
    )} - {chains.length === 0 &&

    There are no available chains

    } + {filteredChains.length === 0 &&

    There are no available chains

    }
    ); }; diff --git a/apps/namadillo/src/App/Transfer/SelectWalletModal.tsx b/apps/namadillo/src/App/Transfer/SelectWalletModal.tsx index 164e3ea34..4011dac83 100644 --- a/apps/namadillo/src/App/Transfer/SelectWalletModal.tsx +++ b/apps/namadillo/src/App/Transfer/SelectWalletModal.tsx @@ -26,18 +26,20 @@ export const SelectWalletModal = ({ }; return ( - +
      - {wallets.map((wallet: WalletProvider, index) => ( -
    • - onConnect(wallet)} - /> -
    • - ))} + {wallets + .filter((wallet) => wallet.id !== "namada") + .map((wallet: WalletProvider, index) => ( +
    • + onConnect(wallet)} + /> +
    • + ))}
    ); diff --git a/apps/namadillo/src/App/Transfer/SelectedAsset.tsx b/apps/namadillo/src/App/Transfer/SelectedAsset.tsx index 800388fa5..ca101a544 100644 --- a/apps/namadillo/src/App/Transfer/SelectedAsset.tsx +++ b/apps/namadillo/src/App/Transfer/SelectedAsset.tsx @@ -1,7 +1,6 @@ -import { Chain } from "@chain-registry/types"; +import { Asset, Chain } from "@chain-registry/types"; import clsx from "clsx"; import { GoChevronDown } from "react-icons/go"; -import { Asset } from "types"; import { EmptyResourceIcon } from "./EmptyResourceIcon"; type SelectedAssetProps = { @@ -16,7 +15,7 @@ export const SelectedAsset = ({ onClick, }: SelectedAssetProps): JSX.Element => { const selectorClassList = clsx( - `flex items-center gap-2.5 text-lg text-white font-light cursor-pointer uppercase` + `flex items-center gap-4 text-xl text-white font-light cursor-pointer uppercase` ); const isDisabled = !chain; @@ -35,20 +34,30 @@ export const SelectedAsset = ({ > {!asset && ( - + Asset )} {asset && ( - + {`${asset.name} - {asset.denomination} - + + {asset.symbol} + + + + )} diff --git a/apps/namadillo/src/App/Transfer/SelectedChain.tsx b/apps/namadillo/src/App/Transfer/SelectedChain.tsx index b888d35a9..619fa4df2 100644 --- a/apps/namadillo/src/App/Transfer/SelectedChain.tsx +++ b/apps/namadillo/src/App/Transfer/SelectedChain.tsx @@ -9,15 +9,18 @@ type SelectedChainProps = { chain?: Chain; wallet?: WalletProvider; onClick?: () => void; + iconSize?: string; }; export const SelectedChain = ({ chain, wallet, onClick, + iconSize, }: SelectedChainProps): JSX.Element => { const selectorClassList = clsx( - `flex items-center gap-2.5 text-white font-light cursor-pointer` + `flex items-center gap-2.5 text-white font-light`, + { "cursor-auto": !onClick } ); const isDisabled = !wallet; @@ -46,12 +49,13 @@ export const SelectedChain = ({ {wallet && chain && ( {`${chain.pretty_name} {chain.pretty_name} - + {onClick && } )} diff --git a/apps/namadillo/src/App/Transfer/SelectedWallet.tsx b/apps/namadillo/src/App/Transfer/SelectedWallet.tsx index b5628b6fa..d73d8189f 100644 --- a/apps/namadillo/src/App/Transfer/SelectedWallet.tsx +++ b/apps/namadillo/src/App/Transfer/SelectedWallet.tsx @@ -7,11 +7,13 @@ import { WalletProvider } from "types"; type SelectedWalletProps = { wallet: WalletProvider; onClick?: () => void; + isShielded?: boolean; }; export const SelectedWallet = ({ wallet, onClick, + isShielded, }: SelectedWalletProps): JSX.Element => { const [walletAddress, setWalletAddress] = useState(""); @@ -21,7 +23,12 @@ export const SelectedWallet = ({ integration.detect(); await integration.connect(); const accounts = await integration.accounts(); + if (accounts && accounts.length > 0) { + if (wallet.id === "namada" && isShielded && accounts.length > 1) { + setWalletAddress(accounts[1].address); + return; + } setWalletAddress(accounts[0].address); } } catch { @@ -31,19 +38,24 @@ export const SelectedWallet = ({ useEffect(() => { loadAccounts(); - }, []); + }, [isShielded]); return (
    {walletAddress && shortenAddress(walletAddress, 8, 6)} - {wallet.name + {wallet.name
    ); }; diff --git a/apps/namadillo/src/App/Transfer/Transfer.tsx b/apps/namadillo/src/App/Transfer/Transfer.tsx index 26bc34d25..b46002c5d 100644 --- a/apps/namadillo/src/App/Transfer/Transfer.tsx +++ b/apps/namadillo/src/App/Transfer/Transfer.tsx @@ -1,5 +1,5 @@ import { Route, Routes } from "react-router-dom"; -import { IBCTransfers } from "./IBCTransfers"; +import { Example } from "./Example"; import { NamTransfer } from "./NamTransfer"; import { Shield } from "./Shield"; import { ShieldAll } from "./ShieldAll"; @@ -17,10 +17,7 @@ export const Transfer: React.FC = () => ( path={TransferRoutes.shieldAll().toString()} element={} /> - } - /> + } /> ); diff --git a/apps/namadillo/src/App/Transfer/TransferArrow.tsx b/apps/namadillo/src/App/Transfer/TransferArrow.tsx new file mode 100644 index 000000000..ff7158087 --- /dev/null +++ b/apps/namadillo/src/App/Transfer/TransferArrow.tsx @@ -0,0 +1,26 @@ +type TransferArrowProps = { + color: string; +}; + +export const TransferArrow = ({ color }: TransferArrowProps): JSX.Element => ( + + + + + +); diff --git a/apps/namadillo/src/App/Transfer/TransferDestination.tsx b/apps/namadillo/src/App/Transfer/TransferDestination.tsx index 8547ddbab..47c29d66f 100644 --- a/apps/namadillo/src/App/Transfer/TransferDestination.tsx +++ b/apps/namadillo/src/App/Transfer/TransferDestination.tsx @@ -8,6 +8,7 @@ import namadaShieldedSvg from "./assets/namada-shielded.svg"; import namadaTransparentSvg from "./assets/namada-transparent.svg"; import { CustomAddressForm } from "./CustomAddressForm"; import { SelectedChain } from "./SelectedChain"; +import { SelectedWallet } from "./SelectedWallet"; type TransferDestinationProps = { isShielded?: boolean; @@ -17,6 +18,7 @@ type TransferDestinationProps = { className?: string; transactionFee?: BigNumber; customAddressActive?: boolean; + openChainSelector?: () => void; onToggleCustomAddress?: (isActive: boolean) => void; onChangeAddress?: (address: string | undefined) => void; address?: string; @@ -53,22 +55,31 @@ export const TransferDestination = ({ onChangeAddress, memo, onChangeMemo, + openChainSelector, }: TransferDestinationProps): JSX.Element => { return (
    {onChangeShielded && chain?.chain_name === "namada" && ( - onChangeShielded(!isShielded)} - /> + )} {onToggleCustomAddress && ( @@ -82,10 +93,15 @@ export const TransferDestination = ({ /> )} - +
    + + {wallet && } +
    {customAddressActive && ( +
    Transaction Fee
    diff --git a/apps/namadillo/src/App/Transfer/TransferModule.tsx b/apps/namadillo/src/App/Transfer/TransferModule.tsx index 1e4564911..35658dc7f 100644 --- a/apps/namadillo/src/App/Transfer/TransferModule.tsx +++ b/apps/namadillo/src/App/Transfer/TransferModule.tsx @@ -1,79 +1,110 @@ -import { Chain, Chains } from "@chain-registry/types"; -import { Stack } from "@namada/components"; +import { Asset, Chain, Chains } from "@chain-registry/types"; +import { ActionButton, Stack } from "@namada/components"; import BigNumber from "bignumber.js"; import { useState } from "react"; -import { Asset, WalletProvider } from "types"; +import { WalletProvider } from "types"; +import { SelectAssetModal } from "./SelectAssetModal"; import { SelectChainModal } from "./SelectChainModal"; import { SelectWalletModal } from "./SelectWalletModal"; +import { TransferArrow } from "./TransferArrow"; import { TransferDestination } from "./TransferDestination"; import { TransferSource } from "./TransferSource"; type TransferModuleProps = { isConnected: boolean; + availableAmount?: BigNumber; availableWallets: WalletProvider[]; onSubmitTransfer: () => void; onChangeWallet?: (wallet: WalletProvider) => void; - selectedWallet?: WalletProvider; + sourceWallet?: WalletProvider; availableSourceChains?: Chains; sourceChain?: Chain; onChangeSourceChain?: (chain: Chain) => void; availableDestinationChains?: Chains; destinationChain?: Chain; + destinationWallet?: WalletProvider; onChangeDestinationChain?: (chain: Chain) => void; selectedAsset?: Asset; + availableAssets?: Asset[]; onChangeSelectedAsset?: (asset: Asset | undefined) => void; isShielded?: boolean; onChangeShielded?: (isShielded: boolean) => void; enableCustomAddress?: boolean; + transactionFee?: BigNumber; }; export const TransferModule = ({ isConnected, selectedAsset, + availableAssets, + onChangeSelectedAsset, availableSourceChains, sourceChain, onChangeSourceChain, - availableDestinationChains: availableDestinationChain, + availableDestinationChains, destinationChain, + destinationWallet, onChangeDestinationChain, isShielded, onChangeShielded, enableCustomAddress, onChangeWallet, availableWallets, - selectedWallet, + sourceWallet, + availableAmount, + transactionFee, }: TransferModuleProps): JSX.Element => { const [providerSelectorModalOpen, setProviderSelectorModalOpen] = useState(false); const [sourceChainModalOpen, setSourceChainModalOpen] = useState(false); - const [destinationChainModalOpen, _setDestinationChainModalOpen] = + const [destinationChainModalOpen, setDestinationChainModalOpen] = useState(false); const [assetSelectorModalOpen, setAssetSelectorModalOpen] = useState(false); const [customAddressActive, setCustomAddressActive] = useState(false); const [memo, setMemo] = useState(""); const [customAddress, setCustomAddress] = useState(""); - const [amount, setAmount] = useState(new BigNumber(0)); + const [amount, setAmount] = useState(new BigNumber(0)); + + const validateTransfer = (): boolean => { + if (!amount || amount.eq(0)) return false; + if (!sourceWallet || !sourceChain || !selectedAsset) return false; + if (!destinationWallet || !destinationChain) return false; + if ( + !availableAmount || + availableAmount.lt(amount.plus(transactionFee || 0)) + ) { + return false; + } + return true; + }; + + const onSubmit = (e: React.FormEvent): void => { + // TODO: implement submit + e.preventDefault(); + }; return ( <>
    - + setProviderSelectorModalOpen(true)} openChainSelector={() => setSourceChainModalOpen(true)} openAssetSelector={() => setAssetSelectorModalOpen(true)} amount={amount} - onChangeAmount={(e) => - setAmount(e.target.value || new BigNumber(0)) - } + availableAmount={availableAmount} + onChangeAmount={setAmount} /> + + + + + {sourceWallet ? "Submit" : "Select Wallet"} +
    {providerSelectorModalOpen && onChangeWallet && ( @@ -94,21 +132,29 @@ export const TransferModule = ({ onConnect={onChangeWallet} /> )} - {sourceChainModalOpen && onChangeSourceChain && ( + {sourceChainModalOpen && onChangeSourceChain && sourceWallet && ( setSourceChainModalOpen(false)} chains={availableSourceChains || []} onSelect={onChangeSourceChain} /> )} - {destinationChainModalOpen && onChangeDestinationChain && ( - setSourceChainModalOpen(false)} - chains={availableDestinationChain || []} - onSelect={onChangeDestinationChain} + {destinationChainModalOpen && + onChangeDestinationChain && + destinationWallet && ( + setDestinationChainModalOpen(false)} + chains={availableDestinationChains || []} + onSelect={onChangeDestinationChain} + /> + )} + {assetSelectorModalOpen && onChangeSelectedAsset && sourceWallet && ( + setAssetSelectorModalOpen(false)} + assets={availableAssets || []} + onSelect={onChangeSelectedAsset} /> )} - {assetSelectorModalOpen &&
    } ); }; diff --git a/apps/namadillo/src/App/Transfer/TransferSource.tsx b/apps/namadillo/src/App/Transfer/TransferSource.tsx index 8c55dc97c..b4c415b73 100644 --- a/apps/namadillo/src/App/Transfer/TransferSource.tsx +++ b/apps/namadillo/src/App/Transfer/TransferSource.tsx @@ -1,8 +1,8 @@ -import { Chain } from "@chain-registry/types"; -import { AmountInput, ChangeAmountEvent } from "@namada/components"; +import { Asset, Chain } from "@chain-registry/types"; +import { AmountInput } from "@namada/components"; import BigNumber from "bignumber.js"; import clsx from "clsx"; -import { Asset, WalletProvider } from "types"; +import { WalletProvider } from "types"; import { AvailableAmountFooter } from "./AvailableAmountFooter"; import { ConnectProviderButton } from "./ConnectProviderButton"; import { SelectedAsset } from "./SelectedAsset"; @@ -18,7 +18,8 @@ export type TransferSourceProps = { openAssetSelector?: () => void; openProviderSelector?: () => void; amount?: BigNumber; - onChangeAmount?: ChangeAmountEvent; + availableAmount?: BigNumber; + onChangeAmount?: (amount: BigNumber | undefined) => void; }; export const TransferSource = ({ @@ -29,6 +30,7 @@ export const TransferSource = ({ openChainSelector, openAssetSelector, amount, + availableAmount, onChangeAmount, }: TransferSourceProps): JSX.Element => { return ( @@ -44,7 +46,7 @@ export const TransferSource = ({ )}
    -
    +
    onChangeAmount && onChangeAmount(e.target.value)} />
    -
    - -
    + {asset && availableAmount && ( +
    + onChangeAmount && onChangeAmount(availableAmount)} + /> +
    + )}
    ); }; diff --git a/apps/namadillo/src/App/Transfer/__tests__/SelectedAsset.test.tsx b/apps/namadillo/src/App/Transfer/__tests__/SelectedAsset.test.tsx index 63c3d3ec6..386206ce7 100644 --- a/apps/namadillo/src/App/Transfer/__tests__/SelectedAsset.test.tsx +++ b/apps/namadillo/src/App/Transfer/__tests__/SelectedAsset.test.tsx @@ -1,15 +1,16 @@ -import { Chain } from "@chain-registry/types"; +import { Asset, Chain } from "@chain-registry/types"; import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; import { SelectedAsset } from "App/Transfer/SelectedAsset"; // Adjust the path accordingly -import { Asset } from "types"; // Adjust the path accordingly import { randomChainMock } from "../__mocks__/chains"; describe("SelectedAsset", () => { const mockAsset: Partial = { name: "Ethereum", - denomination: "ETH", - iconUrl: "https://example.com/eth-icon.png", + symbol: "ETH", + logo_URIs: { + svg: "https://example.com/eth-icon.png", + }, }; it("renders with no chain and disables the button", () => { @@ -45,13 +46,11 @@ describe("SelectedAsset", () => { const button = screen.getByRole("button"); expect(button).toBeEnabled(); - const assetDenomination = screen.getByText(mockAsset.denomination!); + const assetDenomination = screen.getByText(mockAsset.symbol!); expect(assetDenomination).toBeInTheDocument(); const assetImage = screen.getByAltText(`${mockAsset.name} image`); - expect(assetImage).toHaveStyle( - `background-image: url(${mockAsset.iconUrl})` - ); + expect(assetImage).toHaveAttribute("src", mockAsset.logo_URIs?.svg); fireEvent.click(button); expect(handleClick).toHaveBeenCalledTimes(1); diff --git a/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx b/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx index 3792b9c3c..d00eae5cf 100644 --- a/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx +++ b/apps/namadillo/src/App/Transfer/__tests__/SelectedChain.test.tsx @@ -45,10 +45,7 @@ describe("Component: SelectedChain", () => { exact: false, }); expect(chainImage).toBeInTheDocument(); - expect(chainImage).toHaveAttribute( - "style", - `background-image: url(${randomChainMock.logo_URIs?.svg});` - ); + expect(chainImage).toHaveAttribute("src", randomChainMock.logo_URIs?.svg); }); it("calls onClick when the component is clicked", () => { diff --git a/apps/namadillo/src/App/Transfer/routes.ts b/apps/namadillo/src/App/Transfer/routes.ts index 524459c38..df2ccb003 100644 --- a/apps/namadillo/src/App/Transfer/routes.ts +++ b/apps/namadillo/src/App/Transfer/routes.ts @@ -12,7 +12,7 @@ export const shield = (): RouteOutput => routeOutput("/shield"); export const shieldAll = (): RouteOutput => routeOutput(`/shield-all`); -export const ibcTransfer = (): RouteOutput => routeOutput(`/ibc`); +export const example = (): RouteOutput => routeOutput(`/example`); export default { index, @@ -20,5 +20,5 @@ export default { namTransfer, shield, shieldAll, - ibcTransfer, + example, }; diff --git a/apps/namadillo/src/integrations/assets/namada.svg b/apps/namadillo/src/integrations/assets/namada.svg new file mode 100644 index 000000000..7f4e2a7fa --- /dev/null +++ b/apps/namadillo/src/integrations/assets/namada.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/namadillo/src/integrations/index.ts b/apps/namadillo/src/integrations/index.ts index c77d48cda..a2604356d 100644 --- a/apps/namadillo/src/integrations/index.ts +++ b/apps/namadillo/src/integrations/index.ts @@ -1,6 +1,7 @@ import { ExtensionKey } from "@namada/types"; import { WalletProvider } from "types"; import keplrSvg from "./assets/keplr.svg"; +import namadaSvg from "./assets/namada.svg"; export const wallets: Partial> = { keplr: { @@ -13,4 +14,15 @@ export const wallets: Partial> = { firefox: "https://addons.mozilla.org/en-US/firefox/addon/keplr/", }, }, + + namada: { + id: "namada", + name: "Namada", + iconUrl: namadaSvg, + downloadUrl: { + chrome: + "https://chromewebstore.google.com/detail/namada-keychain/hnebcbhjpeejiclgbohcijljcnjdofek", + firefox: "", + }, + }, }; diff --git a/apps/namadillo/src/registry/index.ts b/apps/namadillo/src/registry/index.ts index 86b83d5cf..d108a645f 100644 --- a/apps/namadillo/src/registry/index.ts +++ b/apps/namadillo/src/registry/index.ts @@ -1,5 +1,5 @@ import cosmoshub from "./cosmoshub.json"; -import namada from "./namada.json"; +import namada from "./namada-temp.json"; type MinimalDenom = string; type ConfigName = string; diff --git a/apps/namadillo/src/registry/namada-temp.json b/apps/namadillo/src/registry/namada-temp.json new file mode 100644 index 000000000..7ec080145 --- /dev/null +++ b/apps/namadillo/src/registry/namada-temp.json @@ -0,0 +1,22 @@ +{ + "chainName": "Namada", + "currencies": [ + { + "coinDecimals": 6, + "coinDenom": "NAM", + "coinMinimalDenom": "namnam" + } + ], + "feeCurrencies": [ + { + "coinDecimals": 6, + "coinDenom": "NAM", + "coinMinimalDenom": "namnam" + } + ], + "stakeCurrency": { + "coinDecimals": 6, + "coinDenom": "NAM", + "coinMinimalDenom": "namnam" + } +} diff --git a/apps/namadillo/src/registry/namada.json b/apps/namadillo/src/registry/namada.json index 7ec080145..60f075611 100644 --- a/apps/namadillo/src/registry/namada.json +++ b/apps/namadillo/src/registry/namada.json @@ -1,22 +1,101 @@ { - "chainName": "Namada", - "currencies": [ - { - "coinDecimals": 6, - "coinDenom": "NAM", - "coinMinimalDenom": "namnam" + "chain_name": "namada", + "status": "live", + "network_type": "mainnet", + "website": "https://namada.net/", + "update_link": "", + "pretty_name": "Namada", + "chain_type": "namada", + "chain_id": "namada-1", + "bech32_prefix": "nam", + "daemon_name": "nam", + "node_home": "", + "key_algos": ["secp256k1"], + "slip44": 118, + "fees": { + "fee_tokens": [ + { + "denom": "namnam", + "fixed_min_gas_price": 0.0025, + "low_gas_price": 0.0025, + "average_gas_price": 0.025, + "high_gas_price": 0.04 + } + ] + }, + "staking": { + "staking_tokens": [ + { + "denom": "nam" + } + ], + "lock_duration": { + "time": "1209600s" } - ], - "feeCurrencies": [ + }, + "codebase": { + "git_repo": "https://github.com/anoma/namada", + "genesis": { + "name": "", + "genesis_url": "" + }, + "recommended_version": "", + "compatible_versions": [""], + "cosmos_sdk_version": "", + "consensus": { + "type": "", + "version": "" + }, + "cosmwasm_version": "", + "cosmwasm_enabled": true, + "ibc_go_version": "v7.4.0", + "ics_enabled": ["ics20-1"], + "binaries": { + "linux/amd64": "", + "linux/arm64": "" + }, + "language": { + "type": "rust", + "version": "1.21.4" + }, + "sdk": { + "type": "", + "repo": "", + "version": "", + "tag": "" + }, + "ibc": { + "type": "", + "version": "", + "ics_enabled": [""] + }, + "cosmwasm": { + "version": "", + "repo": "", + "tag": "", + "enabled": true + } + }, + "images": [ { - "coinDecimals": 6, - "coinDenom": "NAM", - "coinMinimalDenom": "namnam" + "image_sync": { + "chain_name": "namada", + "base_denom": "namnam" + }, + "svg": "", + "png": "", + "theme": { + "primary_color_hex": "#ffff00" + } } ], - "stakeCurrency": { - "coinDecimals": 6, - "coinDenom": "NAM", - "coinMinimalDenom": "namnam" - } + "logo_URIs": { + "png": "", + "svg": "" + }, + "description": "", + "peers": { + "seeds": [] + }, + "keywords": ["dex"] }