Skip to content

Commit 72de31e

Browse files
authored
Sui tssdk (#4629)
2 parents e07ab1b + 3f563b6 commit 72de31e

24 files changed

+1529
-3
lines changed

app2/app2.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ _: {
3737
../typescript-sdk
3838
../ts-sdk
3939
];
40-
hash = "sha256-KmVVH20FVlj7qxGSfB0hobb9V+3Fp0bptPA38ojbWZg=";
40+
hash = "sha256-Rre5X8ATXG/dSr50+RJXZVwpMdSSNs+rxoe6oK0TdQg";
4141
buildInputs = deps;
4242
nativeBuildInputs = buildInputs;
4343
pnpmWorkspaces = [

pnpm-lock.yaml

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { Decimal } from "@cosmjs/math"
2+
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"
3+
import { getFullnodeUrl } from "@mysten/sui/client"
4+
import { AddressCosmosZkgm } from "@unionlabs/sdk/schema/address"
5+
import { Instruction } from "@unionlabs/sdk/ucs03"
6+
import { Effect } from "effect"
7+
import { CosmosChannelDestination } from "../src/cosmos/channel.js"
8+
import { CosmosChannelSource } from "../src/cosmos/channel.js"
9+
import {
10+
CosmWasmClientDestination,
11+
CosmWasmClientSource,
12+
createCosmWasmClient,
13+
createSigningCosmWasmClient,
14+
SigningCosmWasmClientContext,
15+
} from "../src/cosmos/client.js"
16+
import { SuiChannelDestination } from "../src/sui/channel.js"
17+
import {
18+
createSuiPublicClient,
19+
SuiPublicClient,
20+
SuiPublicClientDestination,
21+
} from "../src/sui/client.js"
22+
23+
import { toHex } from "viem"
24+
import {
25+
createCosmosToSuiFungibleAssetOrder,
26+
createSuiToCosmosFungibleAssetOrder,
27+
} from "../src/ucs03/fungible-asset-order.js"
28+
// @ts-ignore
29+
BigInt["prototype"].toJSON = function() {
30+
return this.toString()
31+
}
32+
const MNEMONIC = process.env.MNEMONIC || "memo memo memo"
33+
34+
// Define token transfers
35+
const TRANSFERS = [
36+
{
37+
sender: AddressCosmosZkgm.make(toHex("union14qemq0vw6y3gc3u3e0aty2e764u4gs5lnxk4rv")),
38+
receiver: "0x97c9e78b9c3b18f3714544e300234ea873e0904032cf3706fd4e5fd30605df7e",
39+
baseToken: "muno",
40+
baseAmount: 11n,
41+
quoteAmount: 11n,
42+
},
43+
{
44+
sender: "0x97c9e78b9c3b18f3714544e300234ea873e0904032cf3706fd4e5fd30605df7e",
45+
receiver: AddressCosmosZkgm.make(toHex("union1jk9psyhvgkrt2cumz8eytll2244m2nnz4yt2g2")),
46+
baseTokenType:
47+
"0x76b0a4a20519477bb4dd1dc4215cddabad5bfe92ef9f791a78507f60da07c371::fungible_token::FUNGIBLE_TOKEN",
48+
baseAmount: 11n,
49+
quoteAmount: 11n,
50+
},
51+
] as const
52+
53+
const createFungibleAssetOrderCosmosToSui = Effect.gen(function*() {
54+
yield* Effect.log("creating transfer 1")
55+
return yield* createCosmosToSuiFungibleAssetOrder(TRANSFERS[0])
56+
}).pipe(Effect.withLogSpan("Cosmos to sui fungible asset order creation"))
57+
58+
const createFungibleAssetOrderSuiToCosmos = Effect.gen(function*() {
59+
yield* Effect.log("creating transfer 1")
60+
return yield* createSuiToCosmosFungibleAssetOrder(TRANSFERS[1])
61+
}).pipe(Effect.withLogSpan("Cosmos to sui fungible asset order creation"))
62+
63+
Effect.runPromiseExit(
64+
Effect.gen(function*() {
65+
const config = {
66+
url: getFullnodeUrl("testnet"),
67+
}
68+
const publicClient = yield* createSuiPublicClient(config)
69+
70+
const sender = "union1jk9psyhvgkrt2cumz8eytll2244m2nnz4yt2g2"
71+
const receiver = "0x97c9e78b9c3b18f3714544e300234ea873e0904032cf3706fd4e5fd30605df7e"
72+
const base_token = "muno"
73+
const baseAmount = 11n
74+
const quoteAmount = 11n
75+
76+
const cosmWasmClientSource = yield* createCosmWasmClient(
77+
"https://rpc.rpc-node.union-testnet-10.union.build",
78+
)
79+
// Create a wallet from mnemonic (in a real app, use a secure method to get this)
80+
const wallet = yield* Effect.tryPromise(() =>
81+
DirectSecp256k1HdWallet.fromMnemonic(MNEMONIC, { prefix: "union" })
82+
)
83+
84+
// Get the first account address
85+
const [firstAccount] = yield* Effect.tryPromise(() => wallet.getAccounts())
86+
87+
// Create a signing client
88+
const signingClient = yield* createSigningCosmWasmClient(
89+
"https://rpc.rpc-node.union-testnet-10.union.build",
90+
wallet,
91+
{
92+
gasPrice: { amount: Decimal.fromUserInput("1", 6), denom: "muno" },
93+
},
94+
)
95+
96+
yield* Effect.log("creating batch")
97+
const assetOrder = yield* createFungibleAssetOrderCosmosToSui.pipe(
98+
Effect.provideService(SigningCosmWasmClientContext, {
99+
client: signingClient,
100+
address: firstAccount.address,
101+
}),
102+
Effect.provideService(CosmWasmClientSource, { client: cosmWasmClientSource }),
103+
Effect.provideService(SuiPublicClientDestination, { client: publicClient }),
104+
Effect.provideService(SuiChannelDestination, {
105+
ucs03address: "0xf8e63d8dd3c083d0c87554a984d14cbbf6c3b314207a7ddde035ac33ea757d8a",
106+
channelId: 2,
107+
}),
108+
Effect.provideService(CosmosChannelSource, {
109+
ucs03address: "union15zcptld878lux44lvc0chzhz7dcdh62nh0xehwa8y7czuz3yljls7u4ry6",
110+
channelId: 1,
111+
}),
112+
)
113+
yield* Effect.log("assetOrder created", JSON.stringify(assetOrder, null, 2))
114+
const encoded = Instruction.encodeAbi(assetOrder)
115+
yield* Effect.log("Encoded:", encoded)
116+
117+
const assetOrder2 = yield* createFungibleAssetOrderSuiToCosmos.pipe(
118+
Effect.provideService(SigningCosmWasmClientContext, {
119+
client: signingClient,
120+
address: firstAccount.address,
121+
}),
122+
Effect.provideService(SuiPublicClient, { client: publicClient }),
123+
Effect.provideService(CosmWasmClientDestination, { client: cosmWasmClientSource }),
124+
Effect.provideService(CosmosChannelDestination, {
125+
ucs03address: "union15zcptld878lux44lvc0chzhz7dcdh62nh0xehwa8y7czuz3yljls7u4ry6",
126+
channelId: 3,
127+
}),
128+
Effect.catchAllCause(cause => {
129+
console.error("cause is:", cause)
130+
}),
131+
)
132+
yield* Effect.log("assetOrder2 created", JSON.stringify(assetOrder2, null, 2))
133+
const encoded2 = Instruction.encodeAbi(assetOrder2)
134+
yield* Effect.log("Encoded:", encoded2)
135+
}),
136+
).then(exit => console.log(JSON.stringify(exit, null, 2)))
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { getFullnodeUrl, SuiClientOptions } from "@mysten/sui/client"
2+
import { assert } from "console"
3+
import { Effect } from "effect"
4+
import { SuiChannelDestination } from "../src/sui/channel.js"
5+
import {
6+
createSuiPublicClient,
7+
SuiPublicClient,
8+
SuiPublicClientDestination,
9+
} from "../src/sui/client.js"
10+
import { getAllCoins, getAllCoinsUnique } from "../src/sui/sui_coin.js"
11+
12+
// @ts-ignore
13+
BigInt["prototype"].toJSON = function() {
14+
return this.toString()
15+
}
16+
17+
Effect.runPromiseExit(
18+
Effect.gen(function*() {
19+
const config = {
20+
url: getFullnodeUrl("testnet"),
21+
}
22+
23+
const publicClient = yield* createSuiPublicClient(config)
24+
25+
const user_address = "0x835e6a7d0e415c0f1791ae61241f59e1dd9d669d59369cd056f02b3275f68779"
26+
const result = yield* getAllCoins(user_address).pipe(
27+
Effect.provideService(SuiPublicClient, { client: publicClient }),
28+
Effect.tapErrorCause(cause => Effect.logError("Predict failed with cause", cause)),
29+
Effect.catchAllCause(cause => Effect.logError("Failed to read coin balance:", cause)),
30+
)
31+
yield* Effect.log("Result:", result)
32+
}),
33+
).then(exit => console.log(JSON.stringify(exit, null, 2)))
34+
35+
Effect.runPromiseExit(
36+
Effect.gen(function*() {
37+
const config = {
38+
url: getFullnodeUrl("testnet"),
39+
}
40+
41+
const publicClient = yield* createSuiPublicClient(config)
42+
43+
const user_address = "0x835e6a7d0e415c0f1791ae61241f59e1dd9d669d59369cd056f02b3275f68779"
44+
const result = yield* getAllCoinsUnique(user_address).pipe(
45+
Effect.provideService(SuiPublicClient, { client: publicClient }),
46+
Effect.tapErrorCause(cause => Effect.logError("Predict failed with cause", cause)),
47+
Effect.catchAllCause(cause => Effect.logError("Failed to read coin balance:", cause)),
48+
)
49+
yield* Effect.log("Result:", result)
50+
}),
51+
).then(exit => console.log(JSON.stringify(exit, null, 2)))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { getFullnodeUrl, SuiClientOptions } from "@mysten/sui/client"
2+
import { assert } from "console"
3+
import { Effect } from "effect"
4+
import { channelBalance } from "../src/sui/channel-balance.js"
5+
import { SuiChannelDestination } from "../src/sui/channel.js"
6+
import { createSuiPublicClient, SuiPublicClientDestination } from "../src/sui/client.js"
7+
8+
// @ts-ignore
9+
BigInt["prototype"].toJSON = function() {
10+
return this.toString()
11+
}
12+
13+
function bytesToHex(bs: number[]): `0x${string}` {
14+
return "0x" + bs.map(b => b.toString(16).padStart(2, "0")).join("")
15+
}
16+
17+
Effect.runPromiseExit(
18+
Effect.gen(function*() {
19+
const config = {
20+
url: getFullnodeUrl("testnet"),
21+
}
22+
23+
const publicClient = yield* createSuiPublicClient(config)
24+
25+
const token_address = "0x6d756e6f"
26+
const relay_store = "0x87c6df16da471be8a9abe4228b2b20673897e75e164419fec03cf45422f23646"
27+
const token = "0xacc51178ffc547cdfa36a8ab4a6ae3823edaa8f07ff9177d9d520aad080b28fd"
28+
const path = 0
29+
30+
const result = yield* channelBalance(path, token, relay_store).pipe(
31+
Effect.provideService(SuiPublicClientDestination, { client: publicClient }),
32+
Effect.provideService(SuiChannelDestination, {
33+
ucs03address: "0x0b04d5df6eaa283cc3f4ca62860221329d7b0c76e27828b48694b62c81a19a22",
34+
channelId: 2,
35+
}),
36+
Effect.tapErrorCause(cause => Effect.logError("Predict failed with cause", cause)),
37+
)
38+
39+
yield* Effect.log("Result:", result)
40+
}),
41+
).then(exit => console.log(JSON.stringify(exit, null, 2)))
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { getFullnodeUrl, SuiClientOptions } from "@mysten/sui/client"
2+
import { assert } from "console"
3+
import { Effect } from "effect"
4+
import { SuiChannelDestination } from "../src/sui/channel.js"
5+
import { createSuiPublicClient, SuiPublicClientDestination } from "../src/sui/client.js"
6+
import { predictQuoteToken } from "../src/sui/quote-token.js"
7+
8+
// @ts-ignore
9+
BigInt["prototype"].toJSON = function() {
10+
return this.toString()
11+
}
12+
13+
Effect.runPromiseExit(
14+
Effect.gen(function*() {
15+
const config = {
16+
url: getFullnodeUrl("testnet"),
17+
}
18+
19+
const publicClient = yield* createSuiPublicClient(config)
20+
21+
yield* Effect.log("Public client created:", publicClient)
22+
23+
const token_address = "0x6d756e6f"
24+
25+
const result = yield* predictQuoteToken(token_address).pipe(
26+
Effect.provideService(SuiPublicClientDestination, { client: publicClient }),
27+
Effect.provideService(SuiChannelDestination, {
28+
ucs03address: "0xbd3eb037fda14d910c5574b8c950222cc5c4211675b9c2265c07a66cef3a7691",
29+
channelId: 2,
30+
}),
31+
Effect.tapErrorCause(cause => Effect.logError("Predict failed with cause", cause)),
32+
)
33+
const expected_result = "0x4c18721deddf1ea8ec97b187aaf067c09111f350d956cb624b7b4002f0c5e246"
34+
assert!(
35+
result === expected_result,
36+
`Expected wrapped token to be ${expected_result}, but got ${result}`,
37+
)
38+
yield* Effect.log("Result:", result)
39+
}),
40+
).then(exit => console.log(JSON.stringify(exit, null, 2)))

0 commit comments

Comments
 (0)