Skip to content

Commit 2cd514d

Browse files
committed
merge
2 parents 8347fbd + 36bd3c9 commit 2cd514d

File tree

7 files changed

+337
-9
lines changed

7 files changed

+337
-9
lines changed

examples/kava.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { kavaToUkava, Kiln } from "../src/kiln";
2+
import fs from "node:fs";
3+
import 'dotenv/config'
4+
import type { FireblocksIntegration } from "../src/fireblocks.ts";
5+
6+
7+
const apiSecret = fs.readFileSync(`${__dirname}/fireblocks_secret_prod.key`, 'utf8');
8+
9+
const k = new Kiln({
10+
baseUrl: process.env.KILN_API_URL as string,
11+
apiToken: process.env.KILN_API_KEY as string,
12+
});
13+
14+
const vault: FireblocksIntegration = {
15+
provider: 'fireblocks',
16+
fireblocksApiKey: process.env.FIREBLOCKS_API_KEY as string,
17+
fireblocksSecretKey: apiSecret,
18+
vaultId: 37
19+
};
20+
21+
try {
22+
console.log('crafting...');
23+
const tx = await k.client.POST(
24+
'/v1/kava/transaction/stake',
25+
{
26+
body: {
27+
account_id: process.env.KILN_ACCOUNT_ID as string,
28+
pubkey: '0233335b6c68a85e01b85055d0e8c2fcef42fed977898422ef3a5f6baf9a9a413e',
29+
validator: 'kavavaloper1djqecw6nn5tydxq0shan7srv8j65clsf79myt8',
30+
amount_ukava: kavaToUkava('0.01').toString(),
31+
}
32+
}
33+
);
34+
console.log('signing...');
35+
if(!tx.data?.data) throw new Error('No data in response');
36+
const signResponse = await k.fireblocks.signKavaTx(vault, tx.data.data);
37+
console.log('broadcasting...');
38+
if(!signResponse.signed_tx?.data?.signed_tx_serialized) throw new Error('No signed_tx in response');
39+
const broadcastedTx = await k.client.POST("/v1/kava/transaction/broadcast", {
40+
body: {
41+
tx_serialized: signResponse.signed_tx.data.signed_tx_serialized,
42+
}
43+
});
44+
console.log(broadcastedTx);
45+
46+
} catch (err) {
47+
console.log(err);
48+
}

examples/noble.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Kiln, usdcToUusdc } from "../src/kiln";
2+
import fs from "node:fs";
3+
import 'dotenv/config'
4+
import type { FireblocksIntegration } from "../src/fireblocks.ts";
5+
6+
7+
const apiSecret = fs.readFileSync(`${__dirname}/fireblocks_secret_prod.key`, 'utf8');
8+
9+
const k = new Kiln({
10+
baseUrl: process.env.KILN_API_URL as string,
11+
apiToken: process.env.KILN_API_KEY as string,
12+
});
13+
14+
const vault: FireblocksIntegration = {
15+
provider: 'fireblocks',
16+
fireblocksApiKey: process.env.FIREBLOCKS_API_KEY as string,
17+
fireblocksSecretKey: apiSecret,
18+
vaultId: 37
19+
};
20+
21+
try {
22+
console.log('crafting...');
23+
// const s = await k.fireblocks.getSdk(vault);
24+
// const p = await s.getPublicKeyInfoForVaultAccount({
25+
// assetId: "DYDX_DYDX",
26+
// compressed: true,
27+
// vaultAccountId: 37,
28+
// change: 0,
29+
// addressIndex: 0,
30+
// });
31+
// console.log(getCosmosAddress('02d92b48d3e9ef34f2016eac7857a02768c88e30aea7a2366bc5ba032a22eceb8b', 'noble'));
32+
const tx = await k.client.POST(
33+
'/v1/noble/transaction/burn-usdc',
34+
{
35+
body: {
36+
pubkey: '02d92b48d3e9ef34f2016eac7857a02768c88e30aea7a2366bc5ba032a22eceb8b',
37+
recipient: '0xBC86717BaD3F8CcF86d2882a6bC351C94580A994',
38+
amount_uusdc: usdcToUusdc('0.01').toString(),
39+
}
40+
}
41+
);
42+
console.log('signing...');
43+
if(!tx.data?.data) throw new Error('No data in response');
44+
const signResponse = await k.fireblocks.signNobleTx(vault, tx.data.data);
45+
console.log('broadcasting...');
46+
if(!signResponse.signed_tx?.data?.signed_tx_serialized) throw new Error('No signed_tx in response');
47+
const broadcastedTx = await k.client.POST("/v1/noble/transaction/broadcast", {
48+
body: {
49+
tx_serialized: signResponse.signed_tx.data.signed_tx_serialized,
50+
}
51+
});
52+
console.log(broadcastedTx);
53+
54+
} catch (err) {
55+
console.log(err);
56+
}

examples/ton.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Kiln, tonToNanoton } from "../src/kiln";
2+
import fs from "node:fs";
3+
import 'dotenv/config'
4+
import type { FireblocksIntegration } from "../src/fireblocks.ts";
5+
6+
7+
const apiSecret = fs.readFileSync(`${__dirname}/fireblocks_secret_prod.key`, 'utf8');
8+
9+
const k = new Kiln({
10+
baseUrl: process.env.KILN_API_URL as string,
11+
apiToken: process.env.KILN_API_KEY as string,
12+
});
13+
14+
const vault: FireblocksIntegration = {
15+
provider: 'fireblocks',
16+
fireblocksApiKey: process.env.FIREBLOCKS_API_KEY as string,
17+
fireblocksSecretKey: apiSecret,
18+
vaultId: 17
19+
};
20+
21+
try {
22+
console.log('crafting...');
23+
const tx = await k.client.POST(
24+
'/v1/ton/transaction/stake-ton-whales-pool',
25+
{
26+
body: {
27+
account_id: process.env.KILN_ACCOUNT_ID as string,
28+
wallet: 'UQAd57R6nYTCpgo1OxSmpbFRsIO6HIIfO2SW6WcfCe5qIo08',
29+
pool_address: 'EQBXDSbE9s03Waq62YuGdtqe-bcjsN6K9fi64eUy9M8H_Yhf',
30+
vesting_contract_address: 'EQBdL-upJbGStg4MF8acfEfilqd34cfoHe_k2E-yecki3yS6',
31+
amount_nanoton: tonToNanoton('2').toString(),
32+
}
33+
}
34+
);
35+
// const tx = await k.client.POST(
36+
// '/v1/ton/transaction/unstake-ton-whales-pool',
37+
// {
38+
// body: {
39+
// wallet: 'UQAd57R6nYTCpgo1OxSmpbFRsIO6HIIfO2SW6WcfCe5qIo08',
40+
// pool_address: 'EQBXDSbE9s03Waq62YuGdtqe-bcjsN6K9fi64eUy9M8H_Yhf',
41+
// vesting_contract_address: 'EQBdL-upJbGStg4MF8acfEfilqd34cfoHe_k2E-yecki3yS6',
42+
// amount_nanoton: tonToNanoton('0.5').toString(),
43+
// }
44+
// }
45+
// );
46+
console.log('signing...');
47+
if(!tx.data?.data) throw new Error('No data in response');
48+
const signResponse = await k.fireblocks.signTonTx(vault, tx.data.data, "TON");
49+
console.log('broadcasting...');
50+
if(!signResponse.signed_tx?.data?.signed_tx_serialized) throw new Error('No signed_tx in response');
51+
const broadcastedTx = await k.client.POST("/v1/ton/transaction/broadcast", {
52+
body: {
53+
tx_serialized: signResponse.signed_tx.data.signed_tx_serialized,
54+
}
55+
});
56+
console.log(broadcastedTx);
57+
58+
} catch (err) {
59+
console.log(err);
60+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kilnfi/sdk",
3-
"version": "3.1.15",
3+
"version": "3.1.16",
44
"autor": "Kiln <[email protected]> (https://kiln.fi)",
55
"license": "BUSL-1.1",
66
"description": "JavaScript sdk for Kiln API",
@@ -35,6 +35,7 @@
3535
"homepage": "https://github.com/kilnfi/sdk-js#readme",
3636
"dependencies": {
3737
"@types/bun": "^1.1.11",
38+
"bech32": "^2.0.0",
3839
"fireblocks-sdk": "^5.32.0",
3940
"openapi-fetch": "^0.12.0",
4041
"viem": "^2.21.29"

src/fireblocks.ts

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,18 +414,20 @@ export class FireblocksService {
414414
messages: [
415415
{
416416
content: tx.unsigned_tx_hash,
417+
derivationPath: [44, 459, integration.vaultId, 0, 0],
417418
preHash: {
418419
content: tx.unsigned_tx_serialized,
419420
hashAlgorithm: 'SHA256',
420421
},
421422
},
422423
],
424+
algorithm: SigningAlgorithm.MPC_ECDSA_SECP256K1,
423425
},
424426
};
425427

426428
const fbSigner = this.getSigner(integration);
427429
const fbNote = note ? note : 'KAVA tx from @kilnfi/sdk';
428-
const fbTx = await fbSigner.sign(payload, 'KAVA_KAVA', fbNote);
430+
const fbTx = await fbSigner.sign(payload, undefined, fbNote);
429431
const signature = fbTx.signedMessages?.[0]?.signature.fullSig;
430432

431433
if (!signature) {
@@ -451,6 +453,61 @@ export class FireblocksService {
451453
};
452454
}
453455

456+
/**
457+
* Sign a NOBLE transaction on Fireblocks
458+
*/
459+
async signNobleTx(
460+
integration: FireblocksIntegration,
461+
tx: components['schemas']['DYDXUnsignedTx'],
462+
note?: string,
463+
): Promise<{
464+
signed_tx: { data: components['schemas']['DYDXSignedTx'] };
465+
fireblocks_tx: TransactionResponse;
466+
}> {
467+
const payload = {
468+
rawMessageData: {
469+
messages: [
470+
{
471+
content: tx.unsigned_tx_hash,
472+
derivationPath: [44, 118, integration.vaultId, 0, 0],
473+
preHash: {
474+
content: tx.unsigned_tx_serialized,
475+
hashAlgorithm: 'SHA256',
476+
},
477+
},
478+
],
479+
algorithm: SigningAlgorithm.MPC_ECDSA_SECP256K1,
480+
},
481+
};
482+
483+
const fbSigner = this.getSigner(integration);
484+
const fbNote = note ? note : 'NOBLE tx from @kilnfi/sdk';
485+
const fbTx = await fbSigner.sign(payload, undefined, fbNote);
486+
const signature = fbTx.signedMessages?.[0]?.signature.fullSig;
487+
488+
if (!signature) {
489+
throw new Error('Fireblocks signature is missing');
490+
}
491+
492+
const preparedTx = await this.client.POST('/v1/noble/transaction/prepare', {
493+
body: {
494+
pubkey: tx.pubkey,
495+
tx_body: tx.tx_body,
496+
tx_auth_info: tx.tx_auth_info,
497+
signature: signature,
498+
},
499+
});
500+
501+
if (preparedTx.error) {
502+
throw new Error('Failed to prepare transaction');
503+
}
504+
505+
return {
506+
signed_tx: preparedTx.data,
507+
fireblocks_tx: fbTx,
508+
};
509+
}
510+
454511
/**
455512
* Sign a OSMO transaction on Fireblocks
456513
*/
@@ -699,7 +756,7 @@ export class FireblocksService {
699756
}
700757

701758
/**
702-
* Sign and broadcast an ETH transaction with given integration using Fireblocks contract call feature
759+
* Sign an ETH transaction with given integration using Fireblocks raw signing
703760
*/
704761
async signEthTx(
705762
integration: FireblocksIntegration,
@@ -774,6 +831,61 @@ export class FireblocksService {
774831
return await fbSigner.signAndBroadcastWith(payload, assetId, tx, integration.fireblocksDestinationId, true, fbNote);
775832
}
776833

834+
/**
835+
* Sign a POL transaction with given integration using Fireblocks raw signing
836+
*/
837+
async signPolTx(
838+
integration: FireblocksIntegration,
839+
tx: components['schemas']['POLUnsignedTx'],
840+
assetId: 'ETH_TEST5' | 'ETH',
841+
note?: string,
842+
): Promise<{
843+
signed_tx: { data: components['schemas']['POLSignedTx'] };
844+
fireblocks_tx: TransactionResponse;
845+
}> {
846+
const payload = {
847+
rawMessageData: {
848+
messages: [
849+
{
850+
content: tx.unsigned_tx_hash,
851+
preHash: {
852+
content: tx.unsigned_tx_serialized,
853+
hashAlgorithm: 'KECCAK256',
854+
},
855+
},
856+
],
857+
},
858+
};
859+
860+
const fbSigner = this.getSigner(integration);
861+
const fbNote = note ? note : 'POL tx from @kilnfi/sdk';
862+
const fbTx = await fbSigner.sign(payload, assetId, fbNote);
863+
864+
const signature = fbTx?.signedMessages?.[0]?.signature;
865+
866+
if (!signature) {
867+
throw new Error('Fireblocks signature is missing');
868+
}
869+
870+
const preparedTx = await this.client.POST('/v1/pol/transaction/prepare', {
871+
body: {
872+
unsigned_tx_serialized: tx.unsigned_tx_serialized,
873+
r: `0x${signature.r}`,
874+
s: `0x${signature.s}`,
875+
v: signature.v ?? 0,
876+
},
877+
});
878+
879+
if (preparedTx.error) {
880+
throw new Error('Failed to prepare transaction');
881+
}
882+
883+
return {
884+
signed_tx: preparedTx.data,
885+
fireblocks_tx: fbTx,
886+
};
887+
}
888+
777889
/**
778890
* Sign and broadcast a POL transaction with given integration using Fireblocks contract call feature
779891
*/

src/openapi/schema.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44984,7 +44984,7 @@ export interface operations {
4498444984
};
4498544985
content: {
4498644986
"application/json; charset=utf-8": {
44987-
data?: components["schemas"]["TONTx"];
44987+
data: components["schemas"]["TONTx"];
4498844988
};
4498944989
};
4499044990
};
@@ -45032,7 +45032,7 @@ export interface operations {
4503245032
};
4503345033
content: {
4503445034
"application/json; charset=utf-8": {
45035-
data?: components["schemas"]["TONTx"];
45035+
data: components["schemas"]["TONTx"];
4503645036
};
4503745037
};
4503845038
};
@@ -45080,7 +45080,7 @@ export interface operations {
4508045080
};
4508145081
content: {
4508245082
"application/json; charset=utf-8": {
45083-
data?: components["schemas"]["TONTx"];
45083+
data: components["schemas"]["TONTx"];
4508445084
};
4508545085
};
4508645086
};
@@ -45128,7 +45128,7 @@ export interface operations {
4512845128
};
4512945129
content: {
4513045130
"application/json; charset=utf-8": {
45131-
data?: components["schemas"]["TONTx"];
45131+
data: components["schemas"]["TONTx"];
4513245132
};
4513345133
};
4513445134
};
@@ -45176,7 +45176,7 @@ export interface operations {
4517645176
};
4517745177
content: {
4517845178
"application/json; charset=utf-8": {
45179-
data?: components["schemas"]["TONTx"];
45179+
data: components["schemas"]["TONTx"];
4518045180
};
4518145181
};
4518245182
};

0 commit comments

Comments
 (0)