Skip to content

Commit 62dd194

Browse files
authored
ton support (#101)
* ton support * update readme + version
1 parent 82d635b commit 62dd194

File tree

6 files changed

+184
-2
lines changed

6 files changed

+184
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Check out the [full documentation](https://docs.kiln.fi/v1/connect/overview).
2121
- OSMO
2222
- SOL
2323
- TIA
24+
- TON
2425
- XTZ
2526
- More protocol to come, don't hesitate to contact us ([email protected])
2627

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kilnfi/sdk",
3-
"version": "2.14.2",
3+
"version": "2.15.0",
44
"autor": "Kiln <[email protected]> (https://kiln.fi)",
55
"license": "BUSL-1.1",
66
"description": "JavaScript sdk for Kiln API",

src/integrations/fb_signer.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ type AssetId =
3333
| "DV4TNT_TEST"
3434
| "DYDX_DYDX"
3535
| "CELESTIA"
36-
| "INJ_INJ";
36+
| "INJ_INJ"
37+
| "TON_TEST"
38+
| "TON";
3739

3840
export class FbSigner {
3941
protected fireblocks: FireblocksSDK;

src/kiln.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { TiaService } from "./services/tia";
1616
import { XtzService } from "./services/xtz";
1717
import { KILN_VALIDATORS as v } from "./validators";
1818
import { InjService } from "./services/inj";
19+
import { TonService } from "./services/ton";
1920

2021
type Config = {
2122
apiToken: string;
@@ -42,6 +43,7 @@ export class Kiln {
4243
noble: NobleService;
4344
fet: FetService;
4445
inj: InjService;
46+
ton: TonService;
4547

4648
constructor({ testnet, apiToken, baseUrl }: Config) {
4749
api.defaults.headers.common.Authorization = `Bearer ${apiToken}`;
@@ -64,5 +66,6 @@ export class Kiln {
6466
this.noble = new NobleService({ testnet });
6567
this.fet = new FetService({ testnet });
6668
this.inj = new InjService({ testnet });
69+
this.ton = new TonService({ testnet });
6770
}
6871
}

src/services/ton.ts

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import api from "../api";
2+
import { Service } from "./service";
3+
import { ServiceProps } from "../types/service";
4+
import { Integration } from "../types/integrations";
5+
import { parseUnits } from "viem";
6+
import { TonSignedTx, TonTx, TonTxHash, TonTxStatus } from "../types/ton";
7+
8+
export class TonService extends Service {
9+
constructor({ testnet }: ServiceProps) {
10+
super({ testnet });
11+
}
12+
13+
/**
14+
* Craft TON staking transaction to a single nomination pool
15+
* @param accountId id of the kiln account to use for the stake transaction
16+
* @param walletAddress used to create the stake account and retrieve rewards in the future
17+
* @param poolAddress vote account address of the validator that you wish to delegate to
18+
* @param amountTon how much to stake in TON
19+
*/
20+
async craftStakeSingleNominationPoolTx(
21+
accountId: string,
22+
walletAddress: string,
23+
poolAddress: string,
24+
amountTon: number,
25+
): Promise<TonTx> {
26+
const { data } = await api.post<TonTx>(`/v1/ton/transaction/stake-single-nomination-pool`, {
27+
account_id: accountId,
28+
wallet: walletAddress,
29+
amount_nanoton: this.tonToNanoTon(amountTon.toString()),
30+
pool_address: poolAddress,
31+
});
32+
return data;
33+
}
34+
35+
/**
36+
* Craft TON staking transaction to a nomination pool
37+
* @param accountId id of the kiln account to use for the stake transaction
38+
* @param walletAddress used to create the stake account and retrieve rewards in the future
39+
* @param poolAddress vote account address of the validator that you wish to delegate to
40+
* @param amountTon how much to stake in TON
41+
*/
42+
async craftStakeNominationPoolTx(
43+
accountId: string,
44+
walletAddress: string,
45+
poolAddress: string,
46+
amountTon: number,
47+
): Promise<TonTx> {
48+
const { data } = await api.post<TonTx>(`/v1/ton/transaction/stake-nomination-pool`, {
49+
account_id: accountId,
50+
wallet: walletAddress,
51+
amount_nanoton: this.tonToNanoTon(amountTon.toString()),
52+
pool_address: poolAddress,
53+
});
54+
return data;
55+
}
56+
57+
/**
58+
* Craft TON unstake transaction from a single nomination pool
59+
* @param walletAddress used to create the stake account and retrieve rewards in the future
60+
* @param poolAddress vote account address of the validator that you wish to delegate to
61+
* @param amountTon how much to stake in TON
62+
*/
63+
async craftUnstakeSingleNominationPoolTx(
64+
walletAddress: string,
65+
poolAddress: string,
66+
amountTon?: number,
67+
): Promise<TonTx> {
68+
const { data } = await api.post<TonTx>(`/v1/ton/transaction/unstake-single-nomination-pool`, {
69+
wallet: walletAddress,
70+
amount_nanoton: amountTon ? this.tonToNanoTon(amountTon.toString()) : undefined,
71+
pool_address: poolAddress,
72+
});
73+
return data;
74+
}
75+
76+
/**
77+
* Craft TON unstake transaction from a nomination pool
78+
* @param walletAddress used to create the stake account and retrieve rewards in the future
79+
* @param poolAddress vote account address of the validator that you wish to delegate to
80+
*/
81+
async craftUnstakeNominationPoolTx(walletAddress: string, poolAddress: string): Promise<TonTx> {
82+
const { data } = await api.post<TonTx>(`/v1/ton/transaction/unstake-nomination-pool`, {
83+
wallet: walletAddress,
84+
pool_address: poolAddress,
85+
});
86+
return data;
87+
}
88+
89+
/**
90+
* Sign transaction with given integration
91+
* @param integration custody solution to sign with
92+
* @param tx raw transaction
93+
* @param note note to identify the transaction in your custody solution
94+
*/
95+
async sign(integration: Integration, tx: TonTx, note?: string): Promise<TonSignedTx> {
96+
const payload = {
97+
rawMessageData: {
98+
messages: [
99+
{
100+
content: tx.data.unsigned_tx_hash,
101+
},
102+
],
103+
},
104+
};
105+
106+
const fbSigner = this.getFbSigner(integration);
107+
const fbNote = note ? note : "TON tx from @kilnfi/sdk";
108+
const fbTx = await fbSigner.sign(payload, this.testnet ? "TON_TEST" : "TON", fbNote);
109+
const signature =
110+
fbTx.signedMessages && fbTx.signedMessages.length > 0 ? fbTx.signedMessages[0].signature.fullSig : undefined;
111+
112+
const { data } = await api.post<TonSignedTx>(`/v1/ton/transaction/prepare`, {
113+
unsigned_tx_serialized: tx.data.unsigned_tx_serialized,
114+
signature: signature,
115+
from: tx.data.from,
116+
});
117+
data.data.fireblocks_tx = fbTx;
118+
return data;
119+
}
120+
121+
/**
122+
* Broadcast transaction to the network
123+
* @param signedTx serialized signed tx
124+
*/
125+
async broadcast(signedTx: TonSignedTx): Promise<TonTxHash> {
126+
const { data } = await api.post<TonTxHash>(`/v1/ton/transaction/broadcast`, {
127+
tx_serialized: signedTx.data.signed_tx_serialized,
128+
});
129+
return data;
130+
}
131+
132+
/**
133+
* Get transaction status by message hash
134+
* @param msgHash transaction hash
135+
*/
136+
async getTxStatus(msgHash: string): Promise<TonTxStatus> {
137+
const { data } = await api.get<TonTxStatus>(`/v1/ton/transaction/status?msg_hash=${msgHash}`);
138+
return data;
139+
}
140+
141+
/**
142+
* Convert TON to nanoTON
143+
* @param ton
144+
*/
145+
tonToNanoTon(ton: string): string {
146+
return parseUnits(ton, 9).toString();
147+
}
148+
}

src/types/ton.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { TransactionResponse } from "fireblocks-sdk";
2+
3+
export type TonTx = {
4+
data: {
5+
unsigned_tx_hash: string;
6+
unsigned_tx_serialized: string;
7+
from: string;
8+
};
9+
};
10+
11+
export type TonSignedTx = {
12+
data: {
13+
fireblocks_tx: TransactionResponse;
14+
signed_tx_serialized: string;
15+
};
16+
};
17+
18+
export type TonTxHash = {
19+
data: {
20+
tx_hash: string;
21+
};
22+
};
23+
export type TonTxStatus = {
24+
data: {
25+
status: "success" | "error";
26+
receipt: TransactionResponse | null;
27+
};
28+
};

0 commit comments

Comments
 (0)