Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion apps/namadillo/src/App/Ibc/IbcWithdraw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IbcTransferProps } from "@namada/sdk-multicore";
import { AccountType } from "@namada/types";
import { mapUndefined } from "@namada/utils";
import { routes } from "App/routes";
import { isShieldedAddress } from "App/Transfer/common";
import { isIbcAddress, isShieldedAddress } from "App/Transfer/common";
import { TransferModule } from "App/Transfer/TransferModule";
import { OnSubmitTransferParams } from "App/Transfer/types";
import {
Expand All @@ -28,6 +28,7 @@ import { useTransaction } from "hooks/useTransaction";
import { useTransactionActions } from "hooks/useTransactionActions";
import { useWalletManager } from "hooks/useWalletManager";
import { KeplrWalletManager } from "integrations/Keplr";
import { getChainFromAddress } from "integrations/utils";
import invariant from "invariant";
import { useAtom, useAtomValue } from "jotai";
import { TransactionPair } from "lib/query";
Expand Down Expand Up @@ -84,6 +85,7 @@ export const IbcWithdraw = ({
walletAddress: keplrAddress,
chainId,
registry,
connectToChainId,
} = useWalletManager(keplrWalletManager);
const transparentAccount = useAtomValue(defaultAccountAtom);
const namadaChain = useAtomValue(chainAtom);
Expand Down Expand Up @@ -142,6 +144,22 @@ export const IbcWithdraw = ({
}
};

// Connect to IBC chain if destination address is an IBC address
useEffect(() => {
const connectIfIbc = async (address: string): Promise<void> => {
const chain = getChainFromAddress(address);
if (chain?.chain_id) {
try {
await connectToChainId(chain.chain_id);
} catch (error) {
console.error("Failed to connect to IBC chain:", error);
}
}
};

if (isIbcAddress(destinationAddress)) connectIfIbc(destinationAddress);
}, [destinationAddress]);

const {
data: ibcChannels,
isError: unknownIbcChannels,
Expand Down
15 changes: 15 additions & 0 deletions apps/namadillo/src/App/Transfer/SelectToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
connectedWalletsAtom,
getChainRegistryByChainName,
namadaRegistryChainAssetsMapAtom,
SUPPORTED_ASSETS_MAP,
} from "atoms/integrations";
import { tokenPricesFamily } from "atoms/prices/atoms";
import clsx from "clsx";
Expand Down Expand Up @@ -125,6 +126,7 @@ export const SelectToken = ({
async (token: AssetWithAmountAndChain): Promise<void> => {
// Check if current address is Keplr and if we need to connect to specific chain for this token
const isIbcOrKeplrToken = !isNamadaAddress(sourceAddress);
const destinationIsIbcOrKeplrToken = !isNamadaAddress(destinationAddress);
// only used for IBC tokens
let newSourceAddress: string | undefined;
try {
Expand Down Expand Up @@ -163,6 +165,19 @@ export const SelectToken = ({
} finally {
setIsConnectingKeplr(false);
}
} else if (destinationIsIbcOrKeplrToken) {
// Because IbcWithdraw uses registry from KeplrWalletManager, we need to connect to
// the source chain of the selected asset. Otherwise channels may not be correct as
// ibcChannelsFamily relies on connected registry.
const chainName = [...SUPPORTED_ASSETS_MAP.entries()].find(
([_, assetSymbols]) => {
return assetSymbols.includes(token.asset.symbol);
}
)?.[0];
invariant(chainName, "Chain name not found for selected asset");
const registry = getChainRegistryByChainName(chainName);
invariant(registry, "Chain registry not found for counterparty");
await connectToChainId(registry.chain.chain_id);
}

onSelect?.(token, newSourceAddress);
Expand Down
6 changes: 3 additions & 3 deletions apps/namadillo/src/App/Transfer/TransferLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { determineTransferType } from "./utils";

export const TransferLayout: React.FC = () => {
const keplrWalletManager = new KeplrWalletManager();

const userHasAccount = useUserHasAccount();
const [sourceAddressUrl, setSourceAddressUrl] = useUrlState("source");
const [destinationAddressUrl, setDestinationAddressUrl] =
Expand Down Expand Up @@ -59,12 +60,11 @@ export const TransferLayout: React.FC = () => {

// Refetch shielded balance for MASP operations
useEffect(() => {
if (transferType === "shield" || transferType === "unshield") {
refetchShieldedBalance();
}
if (["shield", "unshield"].includes(transferType)) refetchShieldedBalance();
}, [transferType, refetchShieldedBalance]);

// Validate source address - check if it's from keyring or Keplr
// If not it means the address is invalid at best, poisoned at worst.
useEffect(() => {
const validateSourceAddress = async (): Promise<void> => {
if (!sourceAddressUrl || !userHasAccount || !accounts) return;
Expand Down