Skip to content

Commit

Permalink
Namadillo: more stages to IBC transactions (#1483)
Browse files Browse the repository at this point in the history
* feat(namadillo): refactoring ibc transactions to have more stages described

* feat: adding back 'generating masp params'
  • Loading branch information
pedrorezende authored Jan 8, 2025
1 parent e1e3032 commit 4b0d3d7
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 101 deletions.
16 changes: 14 additions & 2 deletions apps/namadillo/src/App/Ibc/IbcTransfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const IbcTransfer = (): JSX.Element => {
const [generalErrorMessage, setGeneralErrorMessage] = useState("");
const [sourceChannel, setSourceChannel] = useState("");
const [destinationChannel, setDestinationChannel] = useState("");
const [currentProgress, setCurrentProgress] = useState<string>();

// Derived data
const availableAmount = mapUndefined(
Expand Down Expand Up @@ -115,14 +116,24 @@ export const IbcTransfer = (): JSX.Element => {
const onSubmitTransfer = async ({
displayAmount,
destinationAddress,
memo,
}: OnSubmitTransferParams): Promise<void> => {
try {
invariant(selectedAsset?.originalAddress, "Error: Asset not selected");
invariant(registry?.chain, "Error: Chain not selected");
setGeneralErrorMessage("");
const result = await transferToNamada(destinationAddress, displayAmount);
setCurrentProgress("Submitting...");
const result = await transferToNamada(
destinationAddress,
displayAmount,
memo,
setCurrentProgress
);
storeTransaction(result);
redirectToTimeline(result);
} catch (err) {
setGeneralErrorMessage(err + "");
setCurrentProgress(undefined);
}
};

Expand Down Expand Up @@ -170,7 +181,8 @@ export const IbcTransfer = (): JSX.Element => {
onChangeShielded: setShielded,
}}
gasConfig={gasConfig}
isSubmitting={transferStatus === "pending"}
submittingText={currentProgress}
isSubmitting={transferStatus === "pending" || !!currentProgress}
isIbcTransfer={true}
requiresIbcChannels={requiresIbcChannels}
ibcOptions={{
Expand Down
4 changes: 3 additions & 1 deletion apps/namadillo/src/App/Transfer/TransferModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export type TransferModuleProps = {
destination: TransferDestinationProps;
requiresIbcChannels?: boolean;
gasConfig?: GasConfig;
submittingText?: string;
isSubmitting?: boolean;
errorMessage?: string;
onSubmitTransfer: (params: OnSubmitTransferParams) => void;
Expand All @@ -91,6 +92,7 @@ export const TransferModule = ({
source,
destination,
gasConfig,
submittingText,
isSubmitting,
isIbcTransfer,
ibcOptions,
Expand Down Expand Up @@ -213,7 +215,7 @@ export const TransferModule = ({

const getButtonText = (): string => {
if (isSubmitting) {
return "Submitting...";
return submittingText || "Submitting...";
}

if (validationResult === "NoSourceWallet") {
Expand Down
36 changes: 10 additions & 26 deletions apps/namadillo/src/atoms/integrations/atoms.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AssetList, Chain } from "@chain-registry/types";
import { DeliverTxResponse, SigningStargateClient } from "@cosmjs/stargate";
import {
ExtensionKey,
IbcTransferMsgValue,
Expand All @@ -8,19 +9,17 @@ import { defaultAccountAtom } from "atoms/accounts";
import { chainAtom, chainParametersAtom } from "atoms/chain";
import { defaultServerConfigAtom, settingsAtom } from "atoms/settings";
import { queryDependentFn } from "atoms/utils";
import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
import { atom } from "jotai";
import { atomWithMutation, atomWithQuery } from "jotai-tanstack-query";
import { atomFamily, atomWithStorage } from "jotai/utils";
import { TransactionPair } from "lib/query";
import { createTransferDataFromIbc } from "lib/transactions";
import {
AddressWithAssetAndAmountMap,
BuildTxAtomParams,
ChainId,
ChainRegistryEntry,
RpcStorage,
TransferStep,
TransferTransactionData,
} from "types";
import {
addLocalnetToRegistry,
Expand All @@ -32,16 +31,15 @@ import {
mapCoinsToAssets,
} from "./functions";
import {
broadcastIbcTransaction,
fetchLocalnetTomlConfig,
IbcTransferParams,
queryAndStoreRpc,
queryAssetBalances,
submitIbcTransfer,
} from "./services";

type IBCTransferAtomParams = {
transferParams: IbcTransferParams;
chain: Chain;
client: SigningStargateClient;
tx: TxRaw;
};

type AssetBalanceAtomParams = {
Expand Down Expand Up @@ -69,28 +67,14 @@ export const rpcByChainAtom = atomWithStorage<
Record<string, RpcStorage> | undefined
>("namadillo:rpc:active", undefined);

export const ibcTransferAtom = atomWithMutation(() => {
export const broadcastIbcTransactionAtom = atomWithMutation(() => {
return {
mutationKey: ["ibc-transfer"],
mutationFn: async ({
transferParams,
chain,
}: IBCTransferAtomParams): Promise<TransferTransactionData> => {
return await queryAndStoreRpc(chain, async (rpc: string) => {
const txResponse = await submitIbcTransfer(rpc, transferParams);
return createTransferDataFromIbc(
txResponse,
rpc,
transferParams.asset.asset,
transferParams.chainId,
transferParams.isShielded ?
{ type: "IbcToShielded", currentStep: TransferStep.ZkProof }
: {
type: "IbcToTransparent",
currentStep: TransferStep.IbcToTransparent,
}
);
});
client,
tx,
}: IBCTransferAtomParams): Promise<DeliverTxResponse> => {
return await broadcastIbcTransaction(client, tx);
},
};
});
Expand Down
60 changes: 30 additions & 30 deletions apps/namadillo/src/atoms/integrations/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
assertIsDeliverTxSuccess,
calculateFee,
} from "@cosmjs/stargate";
import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";

import { getIndexerApi } from "atoms/api";
import { queryForAck, queryForIbcTimeout } from "atoms/transactions";
import BigNumber from "bignumber.js";
Expand All @@ -23,6 +25,7 @@ import {
TransferStep,
} from "types";
import { toBaseAmount } from "utils";
import { getKeplrWallet } from "utils/ibc";
import { getSdkInstance } from "utils/sdk";
import { rpcByChainAtom } from "./atoms";
import { getRpcByIndex } from "./functions";
Expand All @@ -46,7 +49,7 @@ type ShieldedParams = CommonParams & {

export type IbcTransferParams = TransparentParams | ShieldedParams;

const getShieldedArgs = async (
export const getShieldedArgs = async (
target: string,
token: string,
amount: BigNumber,
Expand Down Expand Up @@ -82,26 +85,31 @@ export const queryAssetBalances = async (
}));
};

export const submitIbcTransfer = async (
export const createStargateClient = async (
rpc: string,
transferParams: IbcTransferParams
): Promise<DeliverTxResponse> => {
chain: Chain
): Promise<SigningStargateClient> => {
const keplr = getKeplrWallet();
const signer = keplr.getOfflineSigner(chain.chain_id);
return await SigningStargateClient.connectWithSigner(rpc, signer, {
broadcastPollIntervalMs: 300,
broadcastTimeoutMs: 8_000,
});
};

export const getSignedMessage = async (
client: SigningStargateClient,
transferParams: IbcTransferParams,
maspCompatibleMemo: string = ""
): Promise<TxRaw> => {
const {
signer,
sourceAddress,
destinationAddress,
amount: displayAmount,
asset,
sourceChannelId,
isShielded,
gasConfig,
} = transferParams;

const client = await SigningStargateClient.connectWithSigner(rpc, signer, {
broadcastPollIntervalMs: 300,
broadcastTimeoutMs: 8_000,
});

// cosmjs expects amounts to be represented in the base denom, so convert
const baseAmount = toBaseAmount(asset.asset, displayAmount);

Expand All @@ -110,32 +118,24 @@ export const submitIbcTransfer = async (
`${gasConfig.gasPrice.toString()}${gasConfig.gasToken}`
);

const token = asset.originalAddress;
const { receiver, memo }: { receiver: string; memo?: string } =
isShielded ?
await getShieldedArgs(
destinationAddress,
token,
baseAmount,
transferParams.destinationChannelId
)
: { receiver: destinationAddress };

const transferMsg = createIbcTransferMessage(
sourceChannelId,
sourceAddress,
receiver,
transferParams.destinationAddress,
baseAmount,
asset.originalAddress,
memo
maspCompatibleMemo
);

const response = await client.signAndBroadcast(
sourceAddress,
[transferMsg],
fee
);
return await client.sign(sourceAddress, [transferMsg], fee, "");
};

export const broadcastIbcTransaction = async (
client: SigningStargateClient,
tx: TxRaw
): Promise<DeliverTxResponse> => {
const txBytes = TxRaw.encode(tx).finish();
const response = await client.broadcastTx(txBytes);
assertIsDeliverTxSuccess(response);
return response;
};
Expand Down
Loading

1 comment on commit 4b0d3d7

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