IBC Transfers
CONX Chain has full IBC transfer capabilities through xplajs. Although IBC functionality is not readily exposed through XPLA Vault’s front-end, it can be fully incorporated into any dApp. It is up to a dApp’s front end to initiate IBC transfers.
MsgTransfer
xpla.js exports a MsgTransfer class that can be used to construct IBC transfers.
const msgTransfer = MsgTransfer.fromPartial({
sourcePort: "transfer", // IBC port
sourceChannel: "channel-0", // Outbound channel (Axelar)
token: {denom: "axpla", amount: "1000000000000000000"}, // 1 XPLA
sender: "xpla1npvwllfr9dqr8erajqqr6s0vxnk2ak55hh2h5f", // Source Address on CONX Chain
receiver: "axelar1npvwllfr9dqr8erajqqr6s0vxnk2ak55d7yr5m", // Destination address on Axelar network
memo: "",
timeoutTimestamp: BigInt(Date.now() + 60 * 60 * 10 ** 3) * (10n ** 6n) // Timeout timestamp (in nanoseconds) relative to the current block timestamp.
})
Supported Channels
Channels are defined when a relayer is set up between CONX Chain and an external chain. For each new connected chain the channel ID is incremented.
You can use Mintscan to find the available channels and their IDs.
Derive Cosmos Chain Addresses from a CONX Chain Address
Cosmos SDK based blockchains use bech32 to encode the public key for display. Assuming the same private key is used on multiple Cosmos SDK chains it is possible to decode a CONX Chain address and generate the corresponding public key on another chain.
Here’s a quick example using the @interchainjs/encoding JavaScript library:
import { fromBech32, toBech32 } from "@interchainjs/encoding/bech32";
const xplaAddress = 'xpla1npvwllfr9dqr8erajqqr6s0vxnk2ak55hh2h5f';
const {prefix, data: hex} = fromBech32(address)
const axelarAddress = toBech32("axelar", hex)
Complete Example
The following example demonstrates how to send 1 XPLA from CONX Chain to the Axelar network.
import { EthSecp256k1HDWallet } from "@xpla/xpla"
import { HDPath } from "@interchainjs/types"
import { DirectSigner } from "@interchainjs/cosmos"
import { createCosmosQueryClient } from "@interchainjs/cosmos"
import { DEFAULT_COSMOS_EVM_SIGNER_CONFIG, encodeCosmosEvmPublicKey } from "@xpla/xpla/signers/config";
import { MsgTransfer } from "@xpla/xplajs";
import { fromBech32, toBech32 } from "@interchainjs/encoding/bech32";
import { transfer } from "@xpla/xplajs"
const queryClient = await createCosmosQueryClient("https://cube-rpc.xpla.io");
const mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
const wallet = await EthSecp256k1HDWallet.fromMnemonic(mnemonic, {derivations: [{
prefix: "xpla",
hdPath: HDPath.eth().toString()
}]});
const baseSignConfig = {
queryClient: queryClient,
chainId: "cube_47-5",
addressPrefix: "xpla",
}
const signerConfig = {
...DEFAULT_COSMOS_EVM_SIGNER_CONFIG,
...baseSignConfig
}
const signer = new DirectSigner(wallet, signerConfig);
const signerAddress = (await signer.getAddresses())[0]
const {prefix, data: hex} = fromBech32(signerAddress)
const receiver = toBech32("axelar", hex)
const tx = await transfer(
signer,
signerAddress,
MsgTransfer.fromPartial({
sourcePort: "transfer", // IBC port
sourceChannel: "channel-0", // Outbound channel (Axelar)
token: {denom: "axpla", amount: "1000000000000000000"},
sender: signerAddress, // Source Address on CONX Chain
receiver: receiver, // Destination address on Axelar network
memo: "",
timeoutTimestamp: BigInt(Date.now() + 60 * 60 * 10 ** 3) * (10n ** 6n) // Timeout timestamp (in nanoseconds) relative to the current block timestamp.
}),
{
amount: [{denom: "axpla", amount: "56000000000000000"}],
gas: "200000",
},
""
)
const res = await tx.wait()
console.log(res)