diff --git a/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx b/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx index f93c38b85c..dfa088d372 100644 --- a/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx +++ b/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx @@ -272,7 +272,8 @@ export const IbcWithdraw = (): JSX.Element => { invariant(props, "Invalid transaction data"); const transferTransaction: IbcTransferTransactionData = { - hash: tx.encodedTxData.txs[0].innerTxHashes[0].toLowerCase(), + hash: tx.encodedTxData.txs[0].hash, + innerHash: tx.encodedTxData.txs[0].innerTxHashes[0].toLowerCase(), currentStep: TransferStep.WaitingConfirmation, rpc: "", type: shielded ? "ShieldedToIbc" : "TransparentToIbc", diff --git a/apps/namadillo/src/App/Staking/StakingRewards.tsx b/apps/namadillo/src/App/Staking/StakingRewards.tsx index de468bca5e..c156f3a9d3 100644 --- a/apps/namadillo/src/App/Staking/StakingRewards.tsx +++ b/apps/namadillo/src/App/Staking/StakingRewards.tsx @@ -72,7 +72,7 @@ export const StakingRewards = (): JSX.Element => { params: rewardsToClaim, eventType: ["ClaimRewards", "Bond"], parsePendingTxNotification: () => ({ - title: "Claim rewards transaction is in progress", + title: "Claim and stake rewards transaction is in progress", description: ( <> Your rewards claim is being processed and will be staked to the same diff --git a/apps/namadillo/src/App/Transactions/TransactionCard.tsx b/apps/namadillo/src/App/Transactions/TransactionCard.tsx index 0788c650dd..ab202cbd3c 100644 --- a/apps/namadillo/src/App/Transactions/TransactionCard.tsx +++ b/apps/namadillo/src/App/Transactions/TransactionCard.tsx @@ -39,7 +39,7 @@ export function getToken( txn: Tx["tx"], nativeToken: string ): string | undefined { - if (txn?.kind === "bond") return nativeToken; + if (txn?.kind === "bond" || txn?.kind === "unbond") return nativeToken; let parsed; try { parsed = txn?.data ? JSON.parse(txn.data) : undefined; @@ -62,7 +62,7 @@ export function getToken( return undefined; } -const getBondTransactionInfo = ( +const getBondOrUnbondTransactionInfo = ( tx: Tx["tx"] ): { amount: BigNumber; sender?: string; receiver?: string } | undefined => { if (!tx?.data) return undefined; @@ -118,10 +118,12 @@ export const TransactionCard = ({ const token = getToken(transaction, nativeToken ?? ""); const chainAssetsMap = useAtomValue(chainAssetsMapAtom); const asset = token ? chainAssetsMap[token] : undefined; - const isBondingTransaction = transactionTopLevel?.tx?.kind === "bond"; + const isBondingOrUnbondingTransaction = ["bond", "unbond"].includes( + transactionTopLevel?.tx?.kind ?? "" + ); const txnInfo = - isBondingTransaction ? - getBondTransactionInfo(transaction) + isBondingOrUnbondingTransaction ? + getBondOrUnbondTransactionInfo(transaction) : getTransactionInfo(transaction); const receiver = txnInfo?.receiver; const sender = txnInfo?.sender; @@ -134,7 +136,8 @@ export const TransactionCard = ({ const getBaseAmount = (): BigNumber | undefined => { if (asset && txnInfo?.amount) { - if (isBondingTransaction) return toDisplayAmount(asset, txnInfo.amount); + if (isBondingOrUnbondingTransaction) + return toDisplayAmount(asset, txnInfo.amount); if (isNamadaAsset(asset)) return txnInfo.amount; return toDisplayAmount(asset, txnInfo.amount); } else return undefined; @@ -154,6 +157,7 @@ export const TransactionCard = ({ if (isReceived) return "Receive"; if (kind.startsWith("ibc")) return "IBC Transfer"; if (kind === "bond") return "Stake"; + if (kind === "unbond") return "Unstake"; if (kind === "claimRewards") return "Claim Rewards"; if (kind === "transparentTransfer") return "Transparent Transfer"; if (kind === "shieldingTransfer") return "Shielding Transfer"; @@ -171,7 +175,9 @@ export const TransactionCard = ({ "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 items-center my-1 font-semibold", "gap-5 bg-neutral-800 rounded-sm px-5 text-white border border-transparent", "transition-colors duration-200 hover:border-neutral-500", - isBondingTransaction && validator?.imageUrl ? "py-3" : "py-5" + isBondingOrUnbondingTransaction && validator?.imageUrl ? + "py-3" + : "py-5" ) )} > @@ -205,7 +211,7 @@ export const TransactionCard = ({
Copy transaction hash @@ -239,7 +245,7 @@ export const TransactionCard = ({ />
- {!isBondingTransaction && ( + {!isBondingOrUnbondingTransaction && (

From @@ -260,14 +266,14 @@ export const TransactionCard = ({

- {isBondingTransaction ? "Validator" : "To"} + {isBondingOrUnbondingTransaction ? "Validator" : "To"}

{isShieldedAddress(receiver ?? "") ? Shielded - : isBondingTransaction ? + : isBondingOrUnbondingTransaction ? validator?.imageUrl ? { value: "Stake", ariaLabel: "Stake", }, + { + id: "unbond", + value: "Unstake", + ariaLabel: "Unstake", + }, ]} />
diff --git a/apps/namadillo/src/atoms/integrations/services.ts b/apps/namadillo/src/atoms/integrations/services.ts index 8c7d44042d..deea9e0f0d 100644 --- a/apps/namadillo/src/atoms/integrations/services.ts +++ b/apps/namadillo/src/atoms/integrations/services.ts @@ -272,7 +272,8 @@ export const updateIbcWithdrawalStatus = async ( if (!tx.hash) throw new Error("Transaction hash not defined"); const api = getIndexerApi(); - const response = await api.apiV1IbcTxIdStatusGet(tx.hash); + // We have to pass inner hash here to get specific transaction status + const response = await api.apiV1IbcTxIdStatusGet(tx.innerHash); const { status } = response.data; if (status === "success") { diff --git a/apps/namadillo/src/atoms/notifications/functions.ts b/apps/namadillo/src/atoms/notifications/functions.ts index 81c78261e3..cd1c8164e3 100644 --- a/apps/namadillo/src/atoms/notifications/functions.ts +++ b/apps/namadillo/src/atoms/notifications/functions.ts @@ -1,11 +1,8 @@ export const notificationIdSeparator = ";"; import { TxProps } from "@namada/types"; -export const createNotificationId = ( - data?: TxProps["hash"] | TxProps["hash"][] -): string => { +export const createNotificationId = (data?: TxProps["hash"][]): string => { if (!data) return Date.now().toString(); - if (typeof data === "string") return data; if (Array.isArray(data)) return data.join(notificationIdSeparator); return data; }; diff --git a/apps/namadillo/src/hooks/useIbcTransaction.tsx b/apps/namadillo/src/hooks/useIbcTransaction.tsx index e4ecd42fd4..ee3b326b92 100644 --- a/apps/namadillo/src/hooks/useIbcTransaction.tsx +++ b/apps/namadillo/src/hooks/useIbcTransaction.tsx @@ -113,7 +113,7 @@ export const useIbcTransaction = ({ const dispatchPendingTxNotification = (tx: TransferTransactionData): void => { invariant(tx.hash, "Error: Transaction hash not provided"); dispatchNotification({ - id: createNotificationId(tx.hash), + id: createNotificationId([tx.hash]), title: "IBC transfer transaction in progress", description: ( <> @@ -129,7 +129,7 @@ export const useIbcTransaction = ({ const dispatchErrorTxNotification = (error: unknown): void => { if (!txHash) return; dispatchNotification({ - id: createNotificationId(txHash), + id: createNotificationId([txHash]), title: "IBC transfer transaction failed", description: "", details: error instanceof Error ? error.message : undefined, diff --git a/apps/namadillo/src/hooks/useTransaction.tsx b/apps/namadillo/src/hooks/useTransaction.tsx index ad220bf137..5387d590fa 100644 --- a/apps/namadillo/src/hooks/useTransaction.tsx +++ b/apps/namadillo/src/hooks/useTransaction.tsx @@ -61,6 +61,14 @@ export type UseTransactionOutput = { unknown >; +const getNotificationId = (tx: TransactionPair): string => { + const notificationId = createNotificationId( + tx.encodedTxData.txs.map((tx) => tx.hash) + ); + + return notificationId; +}; + export const useTransaction = ({ params, createTxAtom, @@ -101,10 +109,8 @@ export const useTransaction = ({ tx: TransactionPair, notification: PartialNotification ): void => { - const notificationId = - tx.encodedTxData.type === "buildIbcTransfer" ? - createNotificationId(tx.encodedTxData.txs[0].innerTxHashes) - : createNotificationId(tx.encodedTxData.txs[0].hash); + const notificationId = getNotificationId(tx); + dispatchNotification({ ...notification, id: notificationId, @@ -118,10 +124,7 @@ export const useTransaction = ({ notification: PartialNotification, tx: TransactionPair ): void => { - const notificationId = - tx.encodedTxData.type === "buildIbcTransfer" ? - createNotificationId(tx.encodedTxData.txs[0].innerTxHashes) - : createNotificationId(tx.encodedTxData.txs[0].hash); + const notificationId = getNotificationId(tx); dispatchNotification({ ...notification, id: notificationId, diff --git a/apps/namadillo/src/hooks/useTransactionNotifications.tsx b/apps/namadillo/src/hooks/useTransactionNotifications.tsx index 6b85732481..fc51976cff 100644 --- a/apps/namadillo/src/hooks/useTransactionNotifications.tsx +++ b/apps/namadillo/src/hooks/useTransactionNotifications.tsx @@ -28,7 +28,7 @@ const parseTxsData = ( data: T[] ): { id: string; total: BigNumber } => { const id = createNotificationId( - Array.isArray(tx) ? tx.map((t) => t.hash) : tx.hash + Array.isArray(tx) ? tx.map((t) => t.hash) : [tx.hash] ); const total = getTotalAmountFromTransactionList(data); return { total, id }; @@ -414,7 +414,7 @@ export const useTransactionNotifications = (): void => { detail: tx, }: CustomEvent): void => { if (!tx.hash) return; - const id = createNotificationId(tx.hash); + const id = createNotificationId([tx.hash]); const storedTx = searchAllStoredTxByHash(tx.hash); dispatchNotification({ id, @@ -443,7 +443,7 @@ export const useTransactionNotifications = (): void => { detail: tx, }: CustomEvent): void => { if (!tx.hash) return; - const id = createNotificationId(tx.hash); + const id = createNotificationId([tx.hash]); const storedTx = searchAllStoredTxByHash(tx.hash); dispatchNotification({ id, @@ -473,7 +473,7 @@ export const useTransactionNotifications = (): void => { if (!tx.hash) return; invariant(tx.hash, "Notification error: Invalid Tx hash"); - const id = createNotificationId(tx.hash); + const id = createNotificationId([tx.hash]); const title = tx.type === "ShieldedToIbc" || tx.type === "TransparentToIbc" ? "IBC withdraw transaction succeeded" @@ -498,7 +498,7 @@ export const useTransactionNotifications = (): void => { if (!tx) return; invariant(tx.hash, "Notification error: Invalid Tx provider"); - const id = createNotificationId(tx.hash); + const id = createNotificationId([tx.hash]); const title = tx.type === "ShieldedToIbc" || tx.type === "TransparentToIbc" ? "IBC withdraw transaction failed" @@ -523,7 +523,7 @@ export const useTransactionNotifications = (): void => { if (!tx) return; invariant(tx.hash, "Notification error: Invalid Tx provider"); - const id = createNotificationId(tx.hash); + const id = createNotificationId([tx.hash]); const title = "IBC withdraw transaction failed"; dispatchNotification({ diff --git a/apps/namadillo/src/lib/query.ts b/apps/namadillo/src/lib/query.ts index e50f460f0f..02057959c2 100644 --- a/apps/namadillo/src/lib/query.ts +++ b/apps/namadillo/src/lib/query.ts @@ -27,10 +27,9 @@ export type TransactionPair = { export type EncodedTxData = { type: string; - txs: TxProps[] & - { - innerTxHashes: string[]; - }[]; + txs: (TxProps & { + innerTxHashes: string[]; + })[]; wrapperTxProps: WrapperTxProps; meta?: { props: T[]; diff --git a/apps/namadillo/src/lib/transactions.ts b/apps/namadillo/src/lib/transactions.ts index 56c641ce44..9f55a5eeb6 100644 --- a/apps/namadillo/src/lib/transactions.ts +++ b/apps/namadillo/src/lib/transactions.ts @@ -162,6 +162,8 @@ export const createTransferDataFromIbc = ( const transferTx: IbcTransferTransactionData = { ...details, hash: tx.transactionHash, + // For IBC transfers(deposits), the innerHash is the same as the transaction hash + innerHash: tx.transactionHash, rpc, asset, feePaid, diff --git a/apps/namadillo/src/types.ts b/apps/namadillo/src/types.ts index 0b08e6265b..b521b7ed33 100644 --- a/apps/namadillo/src/types.ts +++ b/apps/namadillo/src/types.ts @@ -341,7 +341,8 @@ export type TransferStage = IbcTransferStage | NamadaTransferStage; export type BaseTransferTransaction = TransferStage & { rpc: string; asset: Asset; - hash?: string; + hash: string; + innerHash: string; displayAmount: BigNumber; chainId: string; sourceAddress: string;