Cross Chain Contract Calls
This guide walks you through writing our example “Call”. The goal of this guide is to show you how to conduct a cross chain contract call using ucs03-zkgm. In this case we will be calling a contract on Ethereum from Babylon.
Relevant imports will be included with each step. Outside of libraries provided by Union, this guide uses Effect.
This first section is a walk through of creating the program section of the send funds example.
Begin by using Effect to create a program function.
The signer used for this transaction is also declared here.
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"import { Effect, Logger } from "effect"
const signer = await DirectSecp256k1HdWallet.fromMnemonic( process.env.MEMO ?? "memo memo memo", { prefix: "bbn" },)
const program = Effect.gen(function*() {})
Using the ChainRegistry
from the Union TS SDK, you can declare the source and destination chains used in this example. In this case, the source is Babylon (babylon.bbn-1
) and the destination is Ethereum (ethereum.1
).
import { ChainRegistry } from "@unionlabs/sdk/ChainRegistry"import { UniversalChainId } from "@unionlabs/sdk/schema/chain"import { Effect, Logger } from "effect"
const program = Effect.gen(function*() { const source = yield* ChainRegistry.byUniversalId( UniversalChainId.make("babylon.bbn-1"), )
const destination = yield* ChainRegistry.byUniversalId( UniversalChainId.make("ethereum.1"), )})
To create a Call
, we supply the sender
, contractAddress
, and contractCalldata
.
More information about Call
and its fields can be found in the Call docs.
import { Call, Ucs05, ZkgmClientRequest, ZkgmClientResponse } from "@unionlabs/sdk"import { Effect, Logger } from "effect"
const program = Effect.gen(function*() {
// ... snip ...
const call = Call.make({ sender: Ucs05.CosmosDisplay.make({ address: "bbn122ny3mep2l7nhtafpwav2y9e5jrslhekrn8frh", }), eureka: false, contractAddress: Ucs05.EvmDisplay.make({ address: "0x921e5b5091f431f84f14423ec487783a853bc4b0", }), contractCalldata: "0xDEADBEEF", })})
Finally, with the Call
ready - you can construct a ZkgmClientRequest
.
import { Call, Ucs05, ZkgmClientRequest, ZkgmClientResponse } from "@unionlabs/sdk"import { Effect, Logger } from "effect"
const program = Effect.gen(function*() {
// ... snip ...
const request = ZkgmClientRequest.make({ source, destination, channelId: ChannelId.make(3), ucs03Address: "bbn1336jj8ertl8h7rdvnz4dh5rqahd09cy0x43guhsxx6xyrztx292q77945h", instruction: call, })})
Now that you’ve created a full zkgm request, you can execute it and wait on the response to close out the program.
import { Call, Ucs05, ZkgmClientRequest, ZkgmClientResponse } from "@unionlabs/sdk"import { GasPrice } from "@cosmjs/stargate"import { Cosmos, CosmosZkgmClient } from "@unionlabs/sdk-cosmos"import { Effect, Logger } from "effect"const program = Effect.gen(function*() {
// ... snip ...
const client = yield* CosmosZkgmClient.make.pipe( Effect.provide(Cosmos.SigningClient.Live( "bbn122ny3mep2l7nhtafpwav2y9e5jrslhekrn8frh", "https://rpc.bbn-1.babylon.chain.kitchen", signer, { gasPrice: GasPrice.fromString("0.0007ubbn") }, )), Effect.provide(Cosmos.Client.Live("https://rpc.bbn-1.babylon.chain.kitchen")), )
const response: ZkgmClientResponse.ZkgmClientResponse = yield* client.execute(request)
yield* Effect.log("TX Hash:", response.txHash)})
With the program ready, we can now use Effect to execute our transfer and listen for a response.
const program = Effect.gen(function*() { // ... program ...}).pipe( Effect.provide(ChainRegistry.Default), Effect.provide(Logger.replace(Logger.defaultLogger, Logger.prettyLoggerDefault)),)
Effect.runPromise(program) .then(console.log) .catch(console.error)