Skip to content

Commit fedb8d3

Browse files
committed
[v2] add babylon craft stake + sign (#166)
* add `@fireblocks/psbt-sdk` + `bitcoinjs-lib` * add babylon functions * nit * fix
1 parent f11283f commit fedb8d3

File tree

5 files changed

+89
-0
lines changed

5 files changed

+89
-0
lines changed

bun.lockb

7.57 KB
Binary file not shown.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
"@cosmjs/proto-signing": "^0.30.1",
3232
"@cosmjs/stargate": "^0.30.1",
3333
"@emurgo/cardano-serialization-lib-nodejs": "^11.5.0",
34+
"@fireblocks/psbt-sdk": "^0.0.5",
3435
"@solana/web3.js": "^1.93.0",
3536
"@substrate/txwrapper-polkadot": "^7.5.1",
3637
"@taquito/local-forging": "^17.5.2",
3738
"@taquito/rpc": "^16.2.0",
3839
"@types/bn.js": "^5.1.5",
3940
"axios": "^1.7.2",
41+
"bitcoinjs-lib": "^6.1.6",
4042
"bn.js": "^5.2.1",
4143
"ethers": "^5.7.2",
4244
"fireblocks-sdk": "^4.2.0",

src/kiln.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ZetaService } from "./services/zeta";
2121
import { KILN_VALIDATORS as v } from "./validators";
2222
import { KavaService } from "./services/kava";
2323
import { PolService } from "./services/pol";
24+
import { BabylonService } from "./services/babylon";
2425

2526
type Config = {
2627
apiToken: string;
@@ -52,6 +53,7 @@ export class Kiln {
5253
zeta: ZetaService;
5354
kava: KavaService;
5455
pol: PolService;
56+
babylon: BabylonService;
5557

5658
constructor({ testnet, apiToken, baseUrl }: Config) {
5759
api.defaults.headers.common.Authorization = `Bearer ${apiToken}`;
@@ -79,5 +81,6 @@ export class Kiln {
7981
this.zeta = new ZetaService({ testnet });
8082
this.kava = new KavaService({ testnet });
8183
this.pol = new PolService({ testnet });
84+
this.babylon = new BabylonService({ testnet });
8285
}
8386
}

src/services/babylon.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Service } from "./service";
2+
import type { BitcoinTx, BitcoinSignedTx, BitcoinTxHash } from "../types/bitcoin";
3+
import api from "../api";
4+
import { Psbt } from "bitcoinjs-lib";
5+
import type { ServiceProps } from "../types/service";
6+
import type { Integration } from "../types/integrations";
7+
import { FireblocksSigner as FireblocksPsbtSigner } from "@fireblocks/psbt-sdk";
8+
9+
export class BabylonService extends Service {
10+
constructor({ testnet }: ServiceProps) {
11+
super({ testnet });
12+
}
13+
14+
/**
15+
* Craft a babylon stake transaction
16+
*/
17+
async craftStakeTx(accountId: string, publicKey: string, amountSatoshi: number, timeLock: number, feeRate: number): Promise<BitcoinTx> {
18+
const { data } = await api.post<BitcoinTx>('/v1/babylon/transaction/stake', {
19+
account_id: accountId,
20+
public_key: publicKey,
21+
amount_satoshi: amountSatoshi,
22+
time_lock: timeLock,
23+
fee_rate: feeRate,
24+
});
25+
return data;
26+
}
27+
28+
/**
29+
* Sign transaction with given integration
30+
* @param integration custody solution to sign with
31+
* @param tx raw babylon transaction
32+
* @param note note to identify the transaction in your custody solution
33+
*/
34+
async sign(integration: Integration, tx: BitcoinTx, note?: string): Promise<BitcoinSignedTx> {
35+
const fbSigner = await FireblocksPsbtSigner.create({
36+
fireblocks: {
37+
basePath: "https://api.fireblocks.io/v1",
38+
apiKey: integration.fireblocksApiKey,
39+
secretKey: integration.fireblocksSecretKey,
40+
},
41+
assetId: this.testnet ? "BTC_TEST" : "BTC",
42+
vaultId: integration.vaultId.toString(),
43+
addressIndex: 0,
44+
note: note ?? "BTC tx from @kilnfi/sdk",
45+
});
46+
47+
const psbt = Psbt.fromHex(tx.data.unsigned_tx_serialized);
48+
49+
await psbt.signAllInputsAsync(fbSigner);
50+
51+
psbt.finalizeAllInputs();
52+
const signedTransaction = psbt.extractTransaction().toHex();
53+
54+
return { data: { signed_tx_serialized: signedTransaction } };
55+
}
56+
57+
/**
58+
* Broadcast transaction to the network
59+
* @param signedTx the transaction to broadcast
60+
*/
61+
async broadcast(signedTx: BitcoinSignedTx): Promise<BitcoinTxHash> {
62+
const { data } = await api.post<BitcoinTxHash>('/v1/babylon/transaction/broadcast', {
63+
tx_serialized: signedTx.data.signed_tx_serialized,
64+
});
65+
return data;
66+
}
67+
}

src/types/bitcoin.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export type BitcoinTx = {
2+
data: {
3+
unsigned_tx_serialized: string;
4+
};
5+
};
6+
7+
export type BitcoinSignedTx = {
8+
data: {
9+
signed_tx_serialized: string;
10+
};
11+
};
12+
13+
export type BitcoinTxHash = {
14+
data: {
15+
tx_id: string;
16+
};
17+
};

0 commit comments

Comments
 (0)