Skip to content

Commit

Permalink
Namadillo: Transfer Module - Part 3 (#1152)
Browse files Browse the repository at this point in the history
* refactor(namadillo): changing TransferModule params structure

* feat(namadillo): implementing custom address
  • Loading branch information
pedrorezende authored Oct 2, 2024
1 parent ed58ca3 commit cbdc8f7
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 147 deletions.
20 changes: 19 additions & 1 deletion apps/namadillo/src/App/Transfer/CustomAddressForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Input, Stack } from "@namada/components";

import { chain as osmosis } from "chain-registry/mainnet/osmosis";
import { useMemo } from "react";
import namadaShieldedSvg from "./assets/namada-shielded.svg";
import namadaTransparentSvg from "./assets/namada-transparent.svg";

type CustomAddressFormProps = {
onChangeAddress?: (address: string | undefined) => void;
customAddress?: string;
Expand All @@ -13,14 +18,27 @@ export const CustomAddressForm = ({
memo,
onChangeMemo,
}: CustomAddressFormProps): JSX.Element => {
const iconUrl = useMemo((): string | undefined => {
if (customAddress?.startsWith("osmo")) return osmosis.logo_URIs?.svg;
if (customAddress?.startsWith("znam")) return namadaShieldedSvg;
if (customAddress?.startsWith("tnam")) return namadaTransparentSvg;
return "";
}, [customAddress]);

return (
<Stack as="fieldset" gap={2}>
{onChangeAddress && (
<Input
label="Recipient address"
value={customAddress}
onChange={(e) => onChangeAddress(e.target.value)}
/>
>
{iconUrl && (
<i className="w-6 absolute right-4 top-1/2 -translate-y-1/2">
<img src={iconUrl} alt="" />
</i>
)}
</Input>
)}
{onChangeMemo && (
<Input
Expand Down
60 changes: 33 additions & 27 deletions apps/namadillo/src/App/Transfer/Example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const Example = (): JSX.Element => {
}, {});
}, []);

const sourceAssetList: Asset[] | undefined = useMemo(() => {
const availableAssets: Asset[] | undefined = useMemo(() => {
if (!chainId) return;
const config = sourceChainConfig.find(
(config) => config[0].chain_id === chainId
Expand All @@ -87,38 +87,44 @@ export const Example = (): JSX.Element => {
}
}, [chainId]);

const onChangeWallet = async (wallet: WalletProvider): Promise<void> => {
try {
await integrations[wallet.id].connect();
setWallet(wallet.id);
if (!chainId) {
setChainId(cosmos.chain_id);
}
} catch (err) {
console.error(err);
}
};

return (
<Panel className="py-20">
<TransferModule
isConnected={false}
onSubmitTransfer={() => {}}
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);
}
source={{
connected: true,
wallet: selectedWallet ? wallets[selectedWallet] : undefined,
onChangeWallet,
availableWallets: Object.values(wallets),
onChangeChain: (chain) => setChainId(chain.chain_id),
onChangeSelectedAsset: setSelectedAsset,
availableChains: Object.values(sourceChains),
availableAmount: new BigNumber(100),
chain: selectedSourceChain,
availableAssets,
selectedAsset,
}}
onChangeSourceChain={(chain) => {
setChainId(chain.chain_id);
destination={{
connected: true,
chain: namadaChain as Chain,
availableWallets: [wallets.namada!],
wallet: wallets.namada,
isShielded,
onChangeShielded: setShielded,
}}
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)}
onSubmitTransfer={console.log}
/>
</Panel>
);
Expand Down
114 changes: 114 additions & 0 deletions apps/namadillo/src/App/Transfer/ExampleFromNamada.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
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 { selectedIBCChainAtom, selectedIBCWallet } from "atoms/integrations";
import { wallets } from "integrations";
import { useAtom } from "jotai";
import { useMemo } from "react";
import { TransferModule } from "./TransferModule";

export const ExampleFromNamada = (): JSX.Element => {
const [selectedWallet] = useAtom(selectedIBCWallet);
const [selectedAsset, setSelectedAsset] = useState<Asset>();
const [chainId] = useAtom(selectedIBCChainAtom);

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<string, Chain> = useMemo(() => {
return sourceChainConfig.reduce((prev, current) => {
return {
...prev,
[current[0].chain_id]: current[0],
};
}, {});
}, []);

const availableAssets: Asset[] | undefined = useMemo(() => {
if (!chainId) return;
const config = sourceChainConfig.find(
(config) => config[0].chain_id === chainId
);
if (config) {
return config[1];
}
}, [chainId]);

const selectedChain =
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 (
<Panel className="py-20">
<TransferModule
source={{
connected: true,
wallet: wallets.namada!,
availableWallets: [],
onChangeSelectedAsset: setSelectedAsset,
availableChains: Object.values(sourceChains),
availableAmount: new BigNumber(100),
chain: namadaChain as Chain,
availableAssets,
selectedAsset,
}}
destination={{
connected: true,
wallet: selectedWallet ? wallets[selectedWallet] : undefined,
chain: selectedChain,
availableWallets: Object.values(wallets),
enableCustomAddress: true,
isShielded: true,
}}
transactionFee={new BigNumber(0.01)}
onSubmitTransfer={console.log}
/>
</Panel>
);
};
2 changes: 1 addition & 1 deletion apps/namadillo/src/App/Transfer/SelectedWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const SelectedWallet = ({
className={clsx(
"flex justify-between items-center gap-2 text-sm text-neutral-500",
"font-light text-right transition-colors",
{ "hover:text-neutral-400": Boolean(onClick) }
{ "hover:text-neutral-400": Boolean(onClick), "cursor-auto": !onClick }
)}
onClick={onClick}
>
Expand Down
78 changes: 36 additions & 42 deletions apps/namadillo/src/App/Transfer/TransferDestination.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Chain } from "@chain-registry/types";
import { Stack } from "@namada/components";
import { NamCurrency } from "App/Common/NamCurrency";
import { TabSelector } from "App/Common/TabSelector";
import BigNumber from "bignumber.js";
import clsx from "clsx";
import { WalletProvider } from "types";
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";
Expand All @@ -26,23 +25,6 @@ type TransferDestinationProps = {
onChangeMemo?: (address: string) => void;
};

const parseChainInfo = (
chain?: Chain,
isShielded?: boolean
): Chain | undefined => {
if (chain?.chain_name !== "namada") {
return chain;
}
return {
...chain,
pretty_name: isShielded ? "Namada Shielded" : "Namada Transparent",
logo_URIs: {
...chain.logo_URIs,
svg: isShielded ? namadaShieldedSvg : namadaTransparentSvg,
},
};
};

export const TransferDestination = ({
chain,
wallet,
Expand Down Expand Up @@ -83,33 +65,45 @@ export const TransferDestination = ({
)}

{onToggleCustomAddress && (
<TabSelector
active={customAddressActive ? "custom" : "my-address"}
onChange={() => onToggleCustomAddress(!customAddressActive)}
items={[
{ id: "my-address", text: "My Address", className: "text-white" },
{ id: "custom", text: "Custom Address", className: "text-white" },
]}
/>
<nav className="mb-6">
<TabSelector
active={customAddressActive ? "custom" : "my-address"}
onChange={() => onToggleCustomAddress(!customAddressActive)}
items={[
{ id: "my-address", text: "My Address", className: "text-white" },
{ id: "custom", text: "Custom Address", className: "text-white" },
]}
/>
</nav>
)}

<div className="flex justify-between items-center">
<SelectedChain
chain={parseChainInfo(chain, isShielded)}
wallet={wallet}
onClick={openChainSelector}
iconSize="42px"
/>
{wallet && <SelectedWallet wallet={wallet} isShielded={isShielded} />}
</div>
{!customAddressActive && (
<div className="flex justify-between items-center">
<SelectedChain
chain={chain}
wallet={wallet}
onClick={openChainSelector}
iconSize="42px"
/>
{wallet && <SelectedWallet wallet={wallet} isShielded={isShielded} />}
</div>
)}

{customAddressActive && (
<CustomAddressForm
memo={memo}
onChangeMemo={onChangeMemo}
customAddress={address}
onChangeAddress={onChangeAddress}
/>
<Stack gap={8}>
<SelectedChain
chain={chain}
wallet={wallet}
onClick={openChainSelector}
iconSize="42px"
/>
<CustomAddressForm
memo={memo}
onChangeMemo={onChangeMemo}
customAddress={address}
onChangeAddress={onChangeAddress}
/>
</Stack>
)}

{transactionFee && (
Expand Down
Loading

1 comment on commit cbdc8f7

@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.