Skip to content

Commit 3d9c305

Browse files
authored
feat: contract integration test (#39)
* contract test; fixes * Update packages/btcindexer/src/sui-client.ts Signed-off-by: sczembor <stanislaw.czembor@gmail.com>
1 parent 91c8f3f commit 3d9c305

File tree

4 files changed

+79
-5
lines changed

4 files changed

+79
-5
lines changed

packages/btcindexer/src/btcindexer-http.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { Indexer } from "./btcindexer";
44
import { networks } from "bitcoinjs-lib";
55
import { SuiClient } from "./sui-client";
66

7+
const NBTC_MODULE = "nbtc";
8+
const MINT_FUNCTION = "mint";
9+
710
export class HIndexer {
811
public nbtcAddr: string;
912
public suiFallbackAddr: string;
@@ -20,6 +23,8 @@ export class HIndexer {
2023
const suiClient = new SuiClient({
2124
suiNetwork: env.SUI_NETWORK,
2225
suiPackageId: env.SUI_PACKAGE_ID,
26+
suiModule: NBTC_MODULE,
27+
suiFunction: MINT_FUNCTION,
2328
suiNbtcObjectId: env.NBTC_OBJECT_ID,
2429
suiLightClientObjectId: env.LIGHT_CLIENT_OBJECT_ID,
2530
suiSignerMnemonic: env.SUI_SIGNER_MNEMONIC,

packages/btcindexer/src/btcindexer.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ function mkMockD1() {
7272
const SUI_CLIENT_CONFIG: SuiClientConfig = {
7373
suiNetwork: "testnet",
7474
suiPackageId: "0xPACKAGE",
75+
suiModule: "test",
76+
suiFunction: "mint",
7577
suiNbtcObjectId: "0xNBTC",
7678
suiLightClientObjectId: "0xLIGHTCLIENT",
7779
suiSignerMnemonic:
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { describe, it, assert } from "vitest";
2+
import { Indexer } from "./btcindexer";
3+
import { SuiClient, SuiClientConfig } from "./sui-client";
4+
import { Block, networks } from "bitcoinjs-lib";
5+
6+
const REGTEST_DATA = {
7+
BLOCK_HEX:
8+
"000000305c2f30d99ad69f247638613dcca7f455159e252878ea6fe10bbc4574a0076914d98ada655d950ac6507d14584fa679d12fb5203c384e52ef292d063fe29b1b645c4b6d68ffff7f200200000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04022f0100ffffffff02de82814a0000000016001477174bfb906c0e52d750eac4b40fd86746ad50550000000000000000266a24aa21a9ed27611410788b35b819e10a0227f40f9bbc70df824e3a30879552f004b48451210120000000000000000000000000000000000000000000000000000000000000000000000000020000000001017fec0755f3524b89ad45383343f992a0d5cb797a695b59e30f2fc80794f001050000000000fdffffff032202089200000000160014b125723e78c2d779e3e299dfd95d72e9a067a0b780f0fa02000000001600144cc99479ada301056d78a8f3676cfb404d696abe00000000000000000d6a0b3078313233343536373839024730440220755610ff6b6fdea530c20d11b7765816beb75e16ce78fa200a7da25e251a7eb9022078e78bed1cc38822cd5dce3982e23c3cd401415ae72050b00c5f8b3441a2c178012103ef55b72bddf4960ddbb12a9a04f61f91fb613aa99b472115f25a5f8686e6c3f200000000",
9+
TX_ID: "2060dfd3cdbffb7db6c968357f3c9df91b52a4cef5c02fad0b0836b0f25cc4ca",
10+
BLOCK_HEIGHT: 303,
11+
};
12+
13+
const SUI_CLIENT_CONFIG: SuiClientConfig = {
14+
suiNetwork: "devnet",
15+
suiPackageId: "0x7a03af034ade1d5b4072ba4fdb9650bd5ce0cd4dcab40f0563540be0ebbe824b",
16+
suiModule: "indexer_test",
17+
suiFunction: "mint",
18+
suiNbtcObjectId: "0xd93cc7f6d91100990f9fa8ca11d533a69254e2f716ab69a22c6cc4e9a49a9374",
19+
suiLightClientObjectId:
20+
"0xd93cc7f6d91100990f9fa8ca11d533a69254e2f716ab69a22c6cc4e9a49a9374",
21+
suiSignerMnemonic:
22+
"your mnemonic your mnemonic your mnemonic your mnemonic your mnemonic your mnemonic",
23+
};
24+
25+
// NOTE: skip to prevent this test from running in CI
26+
describe.skip("Sui Contract Integration", () => {
27+
it("should successfully call the mint function on devnet", { timeout: 60000 }, async () => {
28+
const suiClient = new SuiClient(SUI_CLIENT_CONFIG);
29+
const indexer = new Indexer(
30+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
31+
{} as any,
32+
"bcrt1qfnyeg7dd5vqs2mtc4rekwm8mgpxkj647p39zhw",
33+
"fallback",
34+
networks.regtest,
35+
suiClient,
36+
);
37+
const block = Block.fromHex(REGTEST_DATA.BLOCK_HEX);
38+
const txIndex = block.transactions?.findIndex(
39+
(tx) => tx.getId() === REGTEST_DATA.TX_ID,
40+
);
41+
assert(txIndex);
42+
const targetTx = block.transactions?.[txIndex ?? -1];
43+
assert(targetTx);
44+
45+
const tree = indexer.constructMerkleTree(block);
46+
assert(tree);
47+
const proofResult = indexer.getTxProof(tree, targetTx);
48+
assert(proofResult);
49+
50+
const success = await suiClient.tryMintNbtc(
51+
targetTx,
52+
REGTEST_DATA.BLOCK_HEIGHT,
53+
txIndex,
54+
proofResult,
55+
);
56+
assert.isTrue(success);
57+
});
58+
});

packages/btcindexer/src/sui-client.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { ProofResult } from "./btcindexer";
88
export interface SuiClientConfig {
99
suiNetwork: "testnet" | "mainnet" | "devnet";
1010
suiPackageId: string;
11+
suiModule: string;
12+
suiFunction: string;
1113
suiNbtcObjectId: string;
1214
suiLightClientObjectId: string;
1315
suiSignerMnemonic: string;
@@ -17,13 +19,17 @@ export class SuiClient {
1719
private client: Client;
1820
private signer: Ed25519Keypair;
1921
private packageId: string;
22+
private module: string;
23+
private function: string;
2024
private nbtcObjectId: string;
2125
private lightClientObjectId: string;
2226

2327
constructor(config: SuiClientConfig) {
2428
this.client = new Client({ url: getFullnodeUrl(config.suiNetwork) });
2529
this.signer = Ed25519Keypair.deriveKeypair(config.suiSignerMnemonic);
2630
this.packageId = config.suiPackageId;
31+
this.module = config.suiModule;
32+
this.function = config.suiFunction;
2733
this.nbtcObjectId = config.suiNbtcObjectId;
2834
this.lightClientObjectId = config.suiLightClientObjectId;
2935
}
@@ -35,9 +41,12 @@ export class SuiClient {
3541
proof: ProofResult,
3642
): Promise<void> {
3743
const tx = new SuiTransaction();
38-
const target = `${this.packageId}::nbtc::mint` as const;
44+
const target = `${this.packageId}::${this.module}::${this.function}` as const;
3945
const serializedTx = serializeBtcTx(transaction);
4046

47+
// NOTE: the contract is expecting the proofs to be in big-endian format, while the bitcon-js lib operates internally on little-endian.
48+
const proofBigEndian = proof.proofPath.map((p) => Array.from(Buffer.from(p).reverse()));
49+
4150
tx.moveCall({
4251
target: target,
4352
arguments: [
@@ -49,15 +58,15 @@ export class SuiClient {
4958
tx.pure.u32(serializedTx.outputCount),
5059
tx.pure.vector("u8", serializedTx.outputs),
5160
tx.pure.vector("u8", serializedTx.lockTime),
52-
tx.pure.vector(
53-
"vector<u8>",
54-
proof.proofPath.map((p) => Array.from(p)),
55-
),
61+
tx.pure.vector("vector<u8>", proofBigEndian),
5662
tx.pure.u64(blockHeight),
5763
tx.pure.u64(txIndex),
5864
],
5965
});
6066

67+
// TODO: should we move it to config or set it as a constant
68+
tx.setGasBudget(1000000000);
69+
6170
const result = await this.client.signAndExecuteTransaction({
6271
signer: this.signer,
6372
transaction: tx,

0 commit comments

Comments
 (0)