Skip to content

Commit 845dddd

Browse files
committed
wip with complete example
Signed-off-by: Eric Hegnes <eric@hegnes.com>
1 parent 7599744 commit 845dddd

File tree

17 files changed

+536
-195
lines changed

17 files changed

+536
-195
lines changed

docs/src/content/docs/integrations/typescript/examples.mdx

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,84 @@
22
title: Examples
33
---
44

5-
## Babylon to BOB
5+
## Holesky to XION
6+
7+
```ts twoslash
8+
/// <reference types="effect" />
9+
/// <reference types="viem" />
10+
// @paths: {"@unionlabs/sdk": ["../ts-sdk/src"], "@unionlabs/sdk/*": ["../ts-sdk/src/*"]}
11+
// Polyfill for serializing BigInt as string in JSON
12+
// @ts-ignore
13+
if (typeof BigInt.prototype.toJSON !== "function") {
14+
// @ts-ignore
15+
BigInt.prototype.toJSON = function() {
16+
return this.toString()
17+
}
18+
}
19+
// ---cut---
20+
// EVM
21+
import { http, toHex } from "viem"
22+
import { holesky } from "viem/chains"
23+
import { privateKeyToAccount } from "viem/accounts"
24+
// Union
25+
import { Cosmos, Evm, FungibleAssetOrder, Ucs05 } from "@unionlabs/sdk"
26+
import { UniversalChainId } from "@unionlabs/sdk/schema/chain"
27+
import { ChannelId } from "@unionlabs/sdk/schema/channel"
28+
import { TokenRawDenom } from "@unionlabs/sdk/schema/token"
29+
30+
import { Effect, pipe } from "effect"
31+
32+
// We will send funds from sender to receiver
33+
const SENDER = Ucs05.AddressEvmZkgm.make("0xfaebe5bf141cc04a3f0598062b98d2df01ab3c4d")
34+
const RECEIVER = Ucs05.AddressCosmosZkgm.make(toHex("xion122ny3mep2l7nhtafpwav2y9e5jrslhekkyv629"))
35+
36+
// Create clients from source to destination ("Live" means "not mocked")
37+
const sourceClient = Evm.PublicClientSource.Live({
38+
chain: holesky,
39+
transport: http("https://rpc.17000.ethereum.chain.kitchen"),
40+
})
41+
const destinationClient = Cosmos.ClientDestination.Live(
42+
"https://rpc.xion-testnet-2.xion.chain.kitchen/",
43+
)
44+
const walletClient = Evm.WalletClient.Live({
45+
account: privateKeyToAccount("0x..."),
46+
chain: holesky,
47+
transport: http("https://rpc.17000.ethereum.chain.kitchen"),
48+
})
49+
// Specify the channel over which to send funds
50+
const sourceChannel = Evm.ChannelSource.Live({
51+
ucs03address: "0x5fbe74a283f7954f10aa04c2edf55578811aeb03",
52+
channelId: 4,
53+
})
54+
const destinationChannel = Cosmos.ChannelDestination.Live({
55+
ucs03address: "xion1336jj8ertl8h7rdvnz4dh5rqahd09cy0x43guhsxx6xyrztx292qlzhdk9",
56+
channelId: 1,
57+
})
58+
59+
// Build main program
60+
const main = pipe(
61+
// 1. Create order instruction
62+
FungibleAssetOrder.evmToCosmos({
63+
sender: SENDER,
64+
receiver: RECEIVER,
65+
baseToken: TokenRawDenom.make("0x685ce6742351ae9b618f383883d6d1e0c5a31b4b"),
66+
baseAmount: 100n,
67+
quoteAmount: 100n,
68+
sourceChainId: UniversalChainId.make("ethereum.17000"),
69+
sourceChannelId: ChannelId.make(4),
70+
}),
71+
// 2. Send order instruction
72+
Effect.andThen(Evm.sendInstruction),
73+
// 3. Provide clients & channel configuration
74+
Effect.provide(sourceClient),
75+
Effect.provide(walletClient),
76+
Effect.provide(destinationClient),
77+
Effect.provide(sourceChannel),
78+
Effect.provide(destinationChannel),
79+
)
80+
81+
// Run main program
82+
Effect.runPromise(main)
83+
.then(console.log)
84+
.catch(console.error)
85+
```

pnpm-lock.yaml

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,70 @@
1-
import { Decimal } from "@cosmjs/math"
1+
// CosmWasm
22
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"
3-
import { Cosmos, Evm, FungibleAssetOrder, Ucs03, Ucs05 } from "@unionlabs/sdk"
4-
import { UniversalChainId } from "@unionlabs/sdk/schema/chain"
5-
import { ChannelId } from "@unionlabs/sdk/schema/channel"
6-
import { Effect, Exit, pipe } from "effect"
3+
import { GasPrice } from "@cosmjs/stargate"
4+
// EVM
75
import { http, toHex } from "viem"
86
import { bobSepolia } from "viem/chains"
7+
// Union
8+
import { Cosmos, Evm, FungibleAssetOrder, Ucs05 } from "@unionlabs/sdk"
9+
import { UniversalChainId } from "@unionlabs/sdk/schema/chain"
10+
import { ChannelId } from "@unionlabs/sdk/schema/channel"
11+
import { Effect, pipe } from "effect"
912

10-
const MNEMONIC = process.env.MNEMONIC || "memo memo memo"
11-
13+
// We will send funds from sender to receiver
1214
const SENDER = Ucs05.AddressCosmosZkgm.make(toHex("bbn122ny3mep2l7nhtafpwav2y9e5jrslhekrn8frh"))
1315
const RECEIVER = Ucs05.AddressEvmZkgm.make("0xfaebe5bf141cc04a3f0598062b98d2df01ab3c4d")
14-
const SOURCE_UCS03_ADDRESS =
15-
"bbn15zcptld878lux44lvc0chzhz7dcdh62nh0xehwa8y7czuz3yljlspm2re6" as const
1616

17-
const main = Effect.gen(function*() {
18-
const sourceClient = Cosmos.ClientSource.Live(
19-
"https://rpc.bbn-1.babylon.chain.kitchen",
20-
)
21-
const destinationClient = Evm.PublicClientDestination.Live({
22-
chain: bobSepolia,
23-
transport: http(),
24-
})
25-
const wallet = yield* Effect.tryPromise(() =>
26-
DirectSecp256k1HdWallet.fromMnemonic(MNEMONIC, { prefix: "bbn" })
27-
)
28-
const signingClient = Cosmos.SigningClientContext.Live(
29-
"https://rest.bbn-1.babylon.chain.kitchen",
30-
wallet,
31-
{ gasPrice: { amount: Decimal.fromUserInput("1", 6), denom: "ubbn" } },
32-
)
17+
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(process.env.MNEMONIC as string, {
18+
prefix: "bbn",
19+
})
20+
21+
const accounts = await wallet.getAccounts()
22+
23+
console.log({ accounts })
3324

34-
return yield* pipe(
35-
FungibleAssetOrder.cosmosToEvm({
36-
sender: SENDER,
37-
receiver: RECEIVER,
38-
baseToken: "ubbn",
39-
baseAmount: 100n,
40-
quoteAmount: 100n,
41-
sourceChainId: UniversalChainId.make("babylon.bbn-1"),
42-
sourceChannelId: ChannelId.make(1),
43-
}),
44-
Effect.map((intent) => Ucs03.Batch.make({ operand: [intent] })),
45-
Effect.andThen((instruction) => Cosmos.sendInstruction(instruction, SENDER)),
46-
Effect.provide(signingClient),
47-
Effect.provide(sourceClient),
48-
Effect.provide(destinationClient),
49-
Effect.provideService(Evm.ChannelDestination, {
50-
ucs03address: "0xe33534b7f8D38C6935a2F6Ad35E09228dA239962",
51-
channelId: 1,
52-
}),
53-
Effect.provideService(Cosmos.ChannelSource, {
54-
ucs03address: SOURCE_UCS03_ADDRESS,
55-
channelId: 1,
56-
}),
57-
)
25+
// Create clients from source to destination ("Live" means "not mocked")
26+
const sourceClient = Cosmos.ClientSource.Live("https://rpc.bbn-1.babylon.chain.kitchen")
27+
const destinationClient = Evm.PublicClientDestination.Live({ chain: bobSepolia, transport: http() })
28+
const signingClient = Cosmos.SigningClient.Live(
29+
"https://rpc.bbn-1.babylon.chain.kitchen",
30+
// await DirectSecp256k1HdWallet.fromMnemonic("memo memo memo", { prefix: "bbn" }),
31+
await DirectSecp256k1HdWallet.fromMnemonic(process.env.MNEMONIC as string, { prefix: "bbn" }),
32+
{ gasPrice: GasPrice.fromString("0.000006ubbn") },
33+
)
34+
// Specify the channel over which to send funds
35+
const sourceChannel = Cosmos.ChannelSource.Live({
36+
// @ts-ignore
37+
ucs03address: "bbn15zcptld878lux44lvc0chzhz7dcdh62nh0xehwa8y7czuz3yljlspm2re6",
38+
channelId: 1,
5839
})
40+
const destinationChannel = Evm.ChannelDestination.Live({
41+
ucs03address: "0xe33534b7f8D38C6935a2F6Ad35E09228dA239962",
42+
channelId: 1,
43+
})
44+
45+
// Build main program
46+
const main = pipe(
47+
// 1. Create order instruction
48+
FungibleAssetOrder.cosmosToEvm({
49+
sender: SENDER,
50+
receiver: RECEIVER,
51+
baseToken: "ubbn",
52+
baseAmount: 100n,
53+
quoteAmount: 100n,
54+
sourceChainId: UniversalChainId.make("babylon.bbn-1"),
55+
sourceChannelId: ChannelId.make(1),
56+
}),
57+
// 2. Send order instruction
58+
Effect.andThen((instruction) => Cosmos.sendInstruction(instruction, SENDER)),
59+
// 3. Provide clients & channel configuration
60+
Effect.provide(signingClient),
61+
Effect.provide(sourceClient),
62+
Effect.provide(destinationClient),
63+
Effect.provide(sourceChannel),
64+
Effect.provide(destinationChannel),
65+
)
5966

60-
Effect.runPromiseExit(main).then(Exit.match({
61-
onFailure: (cause) => console.error(JSON.stringify(cause, null, 2)),
62-
onSuccess: (result) => console.log(result),
63-
}))
67+
// Run main program
68+
Effect.runPromise(main)
69+
.then(console.log)
70+
.catch(console.error)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Polyfill for serializing BigInt as string in JSON
2+
// @ts-ignore
3+
if (typeof BigInt.prototype.toJSON !== "function") {
4+
// @ts-ignore
5+
BigInt.prototype.toJSON = function() {
6+
return this.toString()
7+
}
8+
}
9+
// ---cut---
10+
// EVM
11+
import { http, toHex } from "viem"
12+
import { holesky } from "viem/chains"
13+
// Union
14+
import { Cosmos, Evm, FungibleAssetOrder, Ucs05 } from "@unionlabs/sdk"
15+
import { UniversalChainId } from "@unionlabs/sdk/schema/chain"
16+
import { ChannelId } from "@unionlabs/sdk/schema/channel"
17+
import { Effect, pipe } from "effect"
18+
import { privateKeyToAccount } from "viem/accounts"
19+
import { TokenRawDenom } from "../src/schema/token.js"
20+
21+
// We will send funds from sender to receiver
22+
const SENDER = Ucs05.AddressEvmZkgm.make("0xfaebe5bf141cc04a3f0598062b98d2df01ab3c4d")
23+
const RECEIVER = Ucs05.AddressCosmosZkgm.make(toHex("xion122ny3mep2l7nhtafpwav2y9e5jrslhekkyv629"))
24+
25+
// Create clients from source to destination ("Live" means "not mocked")
26+
const sourceClient = Evm.PublicClientSource.Live({
27+
chain: holesky,
28+
transport: http("https://rpc.17000.ethereum.chain.kitchen"),
29+
})
30+
const destinationClient = Cosmos.ClientDestination.Live(
31+
"https://rpc.xion-testnet-2.xion.chain.kitchen/",
32+
)
33+
const walletClient = Evm.WalletClient.Live({
34+
account: privateKeyToAccount("0x..."),
35+
chain: holesky,
36+
transport: http("https://rpc.17000.ethereum.chain.kitchen"),
37+
})
38+
// Specify the channel over which to send funds
39+
const sourceChannel = Evm.ChannelSource.Live({
40+
ucs03address: "0x5fbe74a283f7954f10aa04c2edf55578811aeb03",
41+
channelId: 4,
42+
})
43+
const destinationChannel = Cosmos.ChannelDestination.Live({
44+
ucs03address: "xion1336jj8ertl8h7rdvnz4dh5rqahd09cy0x43guhsxx6xyrztx292qlzhdk9",
45+
channelId: 1,
46+
})
47+
48+
// Build main program
49+
const main = pipe(
50+
// 1. Create order instruction
51+
FungibleAssetOrder.evmToCosmos({
52+
sender: SENDER,
53+
receiver: RECEIVER,
54+
baseToken: TokenRawDenom.make("0x685ce6742351ae9b618f383883d6d1e0c5a31b4b"),
55+
baseAmount: 100n,
56+
quoteAmount: 100n,
57+
sourceChainId: UniversalChainId.make("ethereum.17000"),
58+
sourceChannelId: ChannelId.make(4),
59+
}),
60+
// 2. Send order instruction
61+
Effect.andThen(Evm.sendInstruction),
62+
// 3. Provide clients & channel configuration
63+
Effect.provide(sourceClient),
64+
Effect.provide(walletClient),
65+
Effect.provide(destinationClient),
66+
Effect.provide(sourceChannel),
67+
Effect.provide(destinationChannel),
68+
)
69+
70+
// Run main program
71+
Effect.runPromise(main)
72+
.then(console.log)
73+
.catch(console.error)

ts-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
4242
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
4343
"@cosmjs/math": "^0.33.1",
44-
"@cosmjs/proto-signing": "^0.33.0",
4544
"@effect/build-utils": "^0.8.3",
4645
"@effect/platform": "0.84.6",
4746
"@types/node": "^22.13.1",
@@ -55,6 +54,7 @@
5554
"dependencies": {
5655
"@aptos-labs/ts-sdk": "1.34.0",
5756
"@cosmjs/cosmwasm-stargate": "^0.33.1",
57+
"@cosmjs/proto-signing": "^0.33.0",
5858
"@cosmjs/stargate": "^0.33.1",
5959
"@cosmjs/tendermint-rpc": "^0.33.1",
6060
"@mysten/sui": "^1.30.1",

0 commit comments

Comments
 (0)