diff --git a/apps/namadillo/src/atoms/transfer/atoms.ts b/apps/namadillo/src/atoms/transfer/atoms.ts index 6c8c3777a..0ccbc7259 100644 --- a/apps/namadillo/src/atoms/transfer/atoms.ts +++ b/apps/namadillo/src/atoms/transfer/atoms.ts @@ -1,12 +1,20 @@ import { + DatedViewingKey, ShieldedTransferMsgValue, ShieldingTransferMsgValue, TransparentTransferMsgValue, UnshieldingTransferMsgValue, } from "@namada/types"; -import { chainAtom } from "atoms/chain"; -import { rpcUrlAtom } from "atoms/settings"; +import { shieldedSyncProgress, viewingKeysAtom } from "atoms/balance"; +import { shieldedSync } from "atoms/balance/services"; +import { + chainAtom, + chainParametersAtom, + nativeTokenAddressAtom, +} from "atoms/chain"; +import { maspIndexerUrlAtom, rpcUrlAtom } from "atoms/settings"; import invariant from "invariant"; +import { getDefaultStore, Getter } from "jotai"; import { atomWithMutation } from "jotai-tanstack-query"; import { BuildTxAtomParams } from "types"; import { @@ -40,7 +48,8 @@ export const createTransparentTransferAtom = atomWithMutation((get) => { export const createShieldedTransferAtom = atomWithMutation((get) => { const chain = get(chainAtom); - const rpcUrl = get(rpcUrlAtom); + const { rpcUrl, maspIndexerUrl, allViewingKeys, namTokenAddress, chainId } = + getProps(get); return { mutationKey: ["create-shielded-transfer-tx"], @@ -53,6 +62,15 @@ export const createShieldedTransferAtom = atomWithMutation((get) => { signer, }: BuildTxAtomParams) => { invariant(signer, "Disposable signer is required for shielded transfers"); + + await sync( + allViewingKeys, + chainId, + namTokenAddress, + rpcUrl, + maspIndexerUrl + ); + return createShieldedTransferTx( chain.data!, account, @@ -91,7 +109,9 @@ export const createShieldingTransferAtom = atomWithMutation((get) => { export const createUnshieldingTransferAtom = atomWithMutation((get) => { const chain = get(chainAtom); - const rpcUrl = get(rpcUrlAtom); + const { rpcUrl, maspIndexerUrl, allViewingKeys, namTokenAddress, chainId } = + getProps(get); + return { mutationKey: ["create-unshielding-transfer-tx"], enabled: chain.isSuccess, @@ -106,6 +126,15 @@ export const createUnshieldingTransferAtom = atomWithMutation((get) => { signer, "Disposable signer is required for unshielding transfers" ); + + await sync( + allViewingKeys, + chainId, + namTokenAddress, + rpcUrl, + maspIndexerUrl + ); + return createUnshieldingTransferTx( chain.data!, account, @@ -118,3 +147,55 @@ export const createUnshieldingTransferAtom = atomWithMutation((get) => { }, }; }); + +const getProps = ( + get: Getter +): { + rpcUrl: string; + maspIndexerUrl: string; + allViewingKeys: DatedViewingKey[] | undefined; + namTokenAddress: string | undefined; + chainId: string | undefined; +} => { + const rpcUrl = get(rpcUrlAtom); + const maspIndexerUrl = get(maspIndexerUrlAtom); + const namTokenAddressQuery = get(nativeTokenAddressAtom); + const viewingKeysQuery = get(viewingKeysAtom); + const chainParametersQuery = get(chainParametersAtom); + + const [_, allViewingKeys] = viewingKeysQuery.data ?? []; + const namTokenAddress = namTokenAddressQuery.data; + const chainId = chainParametersQuery.data?.chainId; + + return { + rpcUrl, + maspIndexerUrl, + allViewingKeys, + namTokenAddress, + chainId, + }; +}; + +const sync = async ( + allViewingKeys: DatedViewingKey[] | undefined, + chainId: string | undefined, + namTokenAddress: string | undefined, + rpcUrl: string | undefined, + maspIndexerUrl: string | undefined +): Promise => { + invariant(allViewingKeys, "Viewing keys are required for shielded sync"); + invariant(chainId, "Chain ID is required for shielded sync"); + invariant(namTokenAddress, "NAM token address is required for shielded sync"); + invariant(rpcUrl, "RPC URL is required for shielded sync"); + invariant(maspIndexerUrl, "Masp indexer URL is required for shielded sync"); + + const { set } = getDefaultStore(); + await shieldedSync({ + rpcUrl, + maspIndexerUrl, + token: namTokenAddress, + viewingKeys: allViewingKeys, + chainId, + onProgress: (perc) => set(shieldedSyncProgress, perc), + }); +};