Skip to main content

Messages

MsgTransfer

This message is used to send coins from the sender’s Bank module on Injective to the receiver’s Bank module on another Cosmos chain through IBC, which is Cosmos’s Inter-Blockchain Communication Protocol. Note that Injective only supports mainnet transfers across IBC for most networks. Application to application communication in IBC is conducted over channels, which route between an application module on one chain, and the corresponding application module on another one. More info on IBC channels can be found at https://tutorials.cosmos.network/academy/3-ibc/3-channels.html. A list of canonical channel Ids for mainnet transfers to and from Injective can be found in the Injective Lists repository. Also noteworthy is that the application module on each chain has a portId to designate the type of module on each end. For example, transfer is the portId designating the transfer of ICS-20 tokens between bank modules. In this example, we will transfer ATOM from Injective to CosmosHub
For token metadata (symbols, decimals, channel mappings), please use Injective Lists which provides up-to-date token information in JSON format.
import { toChainFormat, toBigNumber } from "@injectivelabs/utils";
import { ChainId, CosmosChainId } from "@injectivelabs/ts-types";
import { MsgTransfer } from "@injectivelabs/sdk-ts/core/modules";
import { getNetworkEndpoints, Network } from "@injectivelabs/networks";
import { ChainGrpcBankApi } from "@injectivelabs/sdk-ts/client/chain";
import { MsgBroadcasterWithPk } from "@injectivelabs/sdk-ts/core/tx";
import { makeTimeoutTimestampInNs } from "@injectivelabs/sdk-ts/utils";
import { ChainRestTendermintApi } from "@injectivelabs/sdk-ts/client/chain";

const injectiveChainId = CosmosChainId["Injective"];
const destinationChainId = CosmosChainId["Cosmoshub"];

const endpointsForNetwork = getNetworkEndpoints(Network.Mainnet);

/**
 * For IBC transfers, you need:
 * 1. The IBC denom hash for the token on Injective
 * 2. The channel ID for the destination chain
 *
 * You can find this information in the Injective Lists repository:
 * https://github.com/InjectiveLabs/injective-lists
 */
const injectiveToCosmosHubChannelId = "channel-1";

/**
 * The IBC denom for ATOM on Injective
 * Format: ibc/{hash} where hash is derived from the channel and base denom
 */
const atomIbcDenom =
  "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9";

/* format amount for transfer (0.001 ATOM with 6 decimals) */
const amount = {
  denom: atomIbcDenom,
  amount: toChainFormat(0.001, 6).toFixed(),
};

const injectiveAddress = "inj...";
const destinationAddress = "cosmos...";
const port = "transfer";
const timeoutTimestamp = makeTimeoutTimestampInNs();

/* get the latestBlock from the origin chain */
const tendermintRestApi = new ChainRestTendermintApi(endpointsForNetwork.rest);

/* Block details from the origin chain */
const latestBlock = await tendermintRestApi.fetchLatestBlock();
const latestHeight = latestBlock.header.height;
const timeoutHeight = toBigNumber(latestHeight).plus(
  30 // default block timeout height
);

/* create message in proto format */
const msg = MsgTransfer.fromJSON({
  port,
  memo: `IBC transfer from ${injectiveChainId} to ${destinationChainId}`,
  sender: injectiveAddress,
  receiver: destinationAddress,
  channelId: injectiveToCosmosHubChannelId,
  timeout: timeoutTimestamp,
  height: {
    revisionHeight: timeoutHeight.toNumber(),
    revisionNumber: parseInt(latestBlock.header.version.block, 10),
  },
  amount,
});

const privateKey = "0x...";

/* broadcast transaction */
const txHash = await new MsgBroadcasterWithPk({
  privateKey,
  network: Network.Mainnet,
}).broadcast({
  msgs: msg,
});

console.log(txHash);