@kilnfi/sdk
Version:
JavaScript sdk for Kiln API
1,013 lines • 37.8 kB
JavaScript
import { Fireblocks, SignedMessageAlgorithmEnum, } from '@fireblocks/ts-sdk';
import { FireblocksSigner } from './fireblocks_signer.js';
const ERRORS = {
MISSING_SIGNATURE: 'An error occurred while attempting to retrieve the signature from Fireblocks.',
FAILED_TO_PREPARE: 'An error occurred while attempting to add the signature to the transaction.',
MISSING_PUBLIC_KEY: 'An error occurred while attempting to retrieve the public key from Fireblocks.',
};
export class FireblocksService {
constructor(client) {
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.client = client;
}
/**
* Retrieve a fireblocks SDK from a Fireblocks integration
*/
getSdk(integration) {
if (integration.instance) {
return integration.instance;
}
return new Fireblocks(integration.config);
}
/**
* Retrieve a fireblocks signer from a Fireblocks integration
*/
getSigner(integration) {
const sdk = this.getSdk(integration);
return new FireblocksSigner(sdk, integration.vaultId);
}
/**
* Get fireblocks wallet pubkey compressed
*/
async getPubkey(integration, assetId) {
const fbSdk = this.getSdk(integration);
const data = await fbSdk.vaults.getPublicKeyInfoForAddress({
assetId: assetId,
vaultAccountId: integration.vaultId,
change: 0,
addressIndex: 0,
compressed: true,
});
return data.data;
}
/**
* List Fireblocks supported assets
*/
async getAssets(integration) {
const fbSdk = this.getSdk(integration);
return (await fbSdk.blockchainsAssets.getSupportedAssets()).data;
}
/**
* Sign a Solana transaction on Fireblocks
*/
async signSolTx(integration, tx, assetId, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'SOL tx from @kilnfi/sdk';
const fbTx = await fbSigner.sign(payload, assetId, fbNote);
const signatures = fbTx.signedMessages
?.filter((signedMessage) => signedMessage.derivationPath?.[3] === 0)
.map((signedMessage) => signedMessage.signature?.fullSig)
.filter((s) => s !== undefined);
if (!signatures) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/sol/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
signatures: signatures,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: fbTx,
};
}
/**
* Create a Cardano transaction in Fireblocks without waiting for completion
*
* The payload must not contain an inputsSelection: it is only meaningful for
* Fireblocks-built transfers (not RAW signing, where the tx is already built)
* and the Fireblocks API rejects ADA RAW transactions carrying it with
* HTTP 500 {"message":"Unexpected error","code":1404}.
*/
async createAdaTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_body_serialized,
hashAlgorithm: 'BLAKE2',
},
},
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_body_serialized,
hashAlgorithm: 'BLAKE2',
},
bip44change: 2,
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'ADA tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'ADA', fbNote);
}
/**
* Wait for a Cardano transaction to complete and prepare it for broadcast
*/
async waitForAdaTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signedMessages = completedTx.signedMessages?.map((message) => ({
pubkey: message.publicKey,
signature: message.signature?.fullSig,
}));
if (!signedMessages) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/ada/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
signed_messages: signedMessages,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a Cardano transaction on Fireblocks
*/
async signAdaTx(integration, tx, note) {
const fbTx = await this.createAdaTx(integration, tx, note);
return await this.waitForAdaTxCompletion(integration, tx, fbTx);
}
/**
* Create an ATOM transaction in Fireblocks without waiting for completion
*/
async createAtomTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'ATOM tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'ATOM_COS', fbNote);
}
/**
* Wait for an ATOM transaction to complete and prepare it for broadcast
*/
async waitForAtomTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/atom/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign an ATOM transaction on Fireblocks (combines createAtomTx and waitForAtomTxCompletion)
*/
async signAtomTx(integration, tx, note) {
const fbTx = await this.createAtomTx(integration, tx, note);
return await this.waitForAtomTxCompletion(integration, tx, fbTx);
}
/**
* Sign a DYDX transaction on Fireblocks
*/
/**
* Create a DYDX transaction in Fireblocks without waiting for completion
*/
async createDydxTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'DYDX tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'DYDX_DYDX', fbNote);
}
/**
* Wait for a DYDX transaction to complete and prepare it for broadcast
*/
async waitForDydxTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/dydx/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a DYDX transaction on Fireblocks (combines createDydxTx and waitForDydxTxCompletion)
*/
async signDydxTx(integration, tx, note) {
const fbTx = await this.createDydxTx(integration, tx, note);
return await this.waitForDydxTxCompletion(integration, tx, fbTx);
}
/**
* Sign a FET transaction on Fireblocks
*/
/**
* Create a FET transaction in Fireblocks without waiting for completion
*/
async createFetTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
derivationPath: [44, 118, Number(integration.vaultId), 0, 0],
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
algorithm: SignedMessageAlgorithmEnum.EcdsaSecp256K1,
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'FET tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, undefined, fbNote);
}
/**
* Wait for a FET transaction to complete and prepare it for broadcast
*/
async waitForFetTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/fet/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a FET transaction on Fireblocks (combines createFetTx and waitForFetTxCompletion)
*/
async signFetTx(integration, tx, note) {
const fbTx = await this.createFetTx(integration, tx, note);
return await this.waitForFetTxCompletion(integration, tx, fbTx);
}
/**
* Sign a INJ transaction on Fireblocks
*/
/**
* Create a INJ transaction in Fireblocks without waiting for completion
*/
async createInjTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'INJ tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'INJ_INJ', fbNote);
}
/**
* Wait for a INJ transaction to complete and prepare it for broadcast
*/
async waitForInjTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/inj/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a INJ transaction on Fireblocks (combines createInjTx and waitForInjTxCompletion)
*/
async signInjTx(integration, tx, note) {
const fbTx = await this.createInjTx(integration, tx, note);
return await this.waitForInjTxCompletion(integration, tx, fbTx);
}
/**
* Sign a CRO transaction on Fireblocks
*/
/**
* Create a CRO transaction in Fireblocks without waiting for completion
*/
async createCroTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
derivationPath: [44, 394, Number(integration.vaultId), 0, 0],
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
algorithm: SignedMessageAlgorithmEnum.EcdsaSecp256K1,
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'CRO tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, undefined, fbNote);
}
/**
* Wait for a CRO transaction to complete and prepare it for broadcast
*/
async waitForCroTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/cro/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a CRO transaction on Fireblocks (combines createCroTx and waitForCroTxCompletion)
*/
async signCroTx(integration, tx, note) {
const fbTx = await this.createCroTx(integration, tx, note);
return await this.waitForCroTxCompletion(integration, tx, fbTx);
}
/**
* Sign a NOBLE transaction on Fireblocks
*/
/**
* Create a NOBLE transaction in Fireblocks without waiting for completion
*/
async createNobleTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
derivationPath: [44, 118, Number(integration.vaultId), 0, 0],
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
algorithm: SignedMessageAlgorithmEnum.EcdsaSecp256K1,
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'NOBLE tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, undefined, fbNote);
}
/**
* Wait for a NOBLE transaction to complete and prepare it for broadcast
*/
async waitForNobleTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/noble/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a NOBLE transaction on Fireblocks (combines createNobleTx and waitForNobleTxCompletion)
*/
async signNobleTx(integration, tx, note) {
const fbTx = await this.createNobleTx(integration, tx, note);
return await this.waitForNobleTxCompletion(integration, tx, fbTx);
}
/**
* Sign a OSMO transaction on Fireblocks
*/
/**
* Create a OSMO transaction in Fireblocks without waiting for completion
*/
async createOsmoTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'OSMO tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'OSMO', fbNote);
}
/**
* Wait for a OSMO transaction to complete and prepare it for broadcast
*/
async waitForOsmoTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/osmo/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a OSMO transaction on Fireblocks (combines createOsmoTx and waitForOsmoTxCompletion)
*/
async signOsmoTx(integration, tx, note) {
const fbTx = await this.createOsmoTx(integration, tx, note);
return await this.waitForOsmoTxCompletion(integration, tx, fbTx);
}
/**
* Sign a TIA transaction on Fireblocks
*/
/**
* Create a TIA transaction in Fireblocks without waiting for completion
*/
async createTiaTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'TIA tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'CELESTIA', fbNote);
}
/**
* Wait for a TIA transaction to complete and prepare it for broadcast
*/
async waitForTiaTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/tia/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a TIA transaction on Fireblocks (combines createTiaTx and waitForTiaTxCompletion)
*/
async signTiaTx(integration, tx, note) {
const fbTx = await this.createTiaTx(integration, tx, note);
return await this.waitForTiaTxCompletion(integration, tx, fbTx);
}
/**
* Sign an ETH transaction with given integration using Fireblocks raw signing
*/
async signEthTx(integration, tx, assetId, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'KECCAK256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'ETH tx from @kilnfi/sdk';
const fbTx = await fbSigner.sign(payload, assetId, fbNote);
const signature = fbTx?.signedMessages?.[0]?.signature;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/eth/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
r: `0x${signature.r}`,
s: `0x${signature.s}`,
v: signature.v ?? 0,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: fbTx,
};
}
/**
* Sign and broadcast an ETH transaction with given integration using Fireblocks contract call feature
*/
async signAndBroadcastEthTx(integration, tx, assetId, fireblocksDestinationId, note) {
const payload = {
contractCallData: tx.contract_call_data,
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'ETH tx from @kilnfi/sdk';
return await fbSigner.signAndBroadcastWith(payload, assetId, tx, fireblocksDestinationId, true, fbNote);
}
/**
* Sign a POL transaction with given integration using Fireblocks raw signing
*/
async signPolTx(integration, tx, assetId, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'KECCAK256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'POL tx from @kilnfi/sdk';
const fbTx = await fbSigner.sign(payload, assetId, fbNote);
const signature = fbTx?.signedMessages?.[0]?.signature;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/pol/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
r: `0x${signature.r}`,
s: `0x${signature.s}`,
v: signature.v ?? 0,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: fbTx,
};
}
/**
* Sign and broadcast a POL transaction with given integration using Fireblocks contract call feature
*/
async signAndBroadcastPolTx(integration, tx, assetId, fireblocksDestinationId, note) {
const payload = {
contractCallData: tx.contract_call_data,
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'POL tx from @kilnfi/sdk';
return await fbSigner.signAndBroadcastWith(payload, assetId, tx, fireblocksDestinationId, true, fbNote);
}
/**
* Create a TON transaction in Fireblocks without waiting for completion
*/
async createTonTx(integration, tx, assetId, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
//TODO : ADD PREHASH LATER IF FB SUPPORT TON HASH ALGORITHM
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'TON tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, assetId, fbNote);
}
/**
* Wait for a TON transaction to complete and prepare it for broadcast
*/
async waitForTonTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/ton/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
signature: signature,
from: tx.from,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a TON transaction on Fireblocks
*/
async signTonTx(integration, tx, assetId, note) {
const fbTx = await this.createTonTx(integration, tx, assetId, note);
return await this.waitForTonTxCompletion(integration, tx, fbTx);
}
/**
* Create a XTZ transaction in Fireblocks without waiting for completion
*/
async createXtzTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'XTZ tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'XTZ', fbNote);
}
/**
* Wait for a XTZ transaction to complete and prepare it for broadcast
*/
async waitForXtzTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/xtz/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a XTZ transaction on Fireblocks (combines createXtzTx and waitForXtzTxCompletion)
*/
async signXtzTx(integration, tx, note) {
const fbTx = await this.createXtzTx(integration, tx, note);
return await this.waitForXtzTxCompletion(integration, tx, fbTx);
}
/**
* Create a NEAR transaction in Fireblocks without waiting for completion
*/
async createNearTx(integration, tx, assetId, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'NEAR tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, assetId, fbNote);
}
/**
* Wait for a NEAR transaction to complete and prepare it for broadcast
*/
async waitForNearTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/near/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: fbTx,
};
}
/**
* Sign a NEAR transaction on Fireblocks (combines createNearTx and waitForNearTxCompletion)
*/
async signNearTx(integration, tx, assetId, note) {
const fbTx = await this.createNearTx(integration, tx, assetId, note);
return await this.waitForNearTxCompletion(integration, tx, fbTx);
}
/**
* Sign a Trx transaction on Fireblocks
*/
async createTrxTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_id,
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'TRX tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, 'TRX', fbNote);
}
async waitForTrxTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
if (!completedTx.signedMessages?.[0]?.signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const signature = `${completedTx.signedMessages[0].signature.fullSig}0${completedTx.signedMessages[0].signature.v}`;
const preparedTx = await this.client.POST('/trx/transaction/prepare', {
body: {
unsigned_tx_serialized: tx.unsigned_tx_serialized,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
async signTrxTx(integration, tx, note) {
const fbTx = await this.createTrxTx(integration, tx, note);
return await this.waitForTrxTxCompletion(integration, tx, fbTx);
}
/**
* Sign a SEI transaction on Fireblocks
*/
/**
* Create a SEI transaction in Fireblocks without waiting for completion
*/
async createSeiTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash,
derivationPath: [44, 60, Number(integration.vaultId), 0, 0],
preHash: {
content: tx.unsigned_tx_serialized,
hashAlgorithm: 'SHA256',
},
},
],
algorithm: SignedMessageAlgorithmEnum.EcdsaSecp256K1,
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'SEI tx from @kilnfi/sdk';
return await fbSigner.createTransaction(payload, undefined, fbNote);
}
/**
* Wait for a SEI transaction to complete and prepare it for broadcast
*/
async waitForSeiTxCompletion(integration, tx, fbTx) {
const fbSigner = this.getSigner(integration);
const completedTx = await fbSigner.waitForTxCompletion(fbTx);
const signature = completedTx.signedMessages?.[0]?.signature?.fullSig;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
const preparedTx = await this.client.POST('/sei/transaction/prepare', {
body: {
pubkey: tx.pubkey,
tx_body: tx.tx_body,
tx_auth_info: tx.tx_auth_info,
signature: signature,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: completedTx,
};
}
/**
* Sign a SEI transaction on Fireblocks (combines createSeiTx and waitForSeiTxCompletion)
*/
async signSeiTx(integration, tx, note) {
const fbTx = await this.createSeiTx(integration, tx, note);
return await this.waitForSeiTxCompletion(integration, tx, fbTx);
}
async signSuiTx(integration, tx, note) {
const payload = {
rawMessageData: {
messages: [
{
content: tx.unsigned_tx_hash.substring(2),
},
],
},
};
const fbSigner = this.getSigner(integration);
const fbNote = note ? note : 'SUI tx from @kilnfi/sdk';
const fbTx = await fbSigner.sign(payload, 'SUI', fbNote);
const signature = fbTx.signedMessages?.[0]?.signature?.fullSig;
const fbPubkey = fbTx.signedMessages?.[0]?.publicKey;
if (!signature) {
throw new Error(ERRORS.MISSING_SIGNATURE);
}
if (!fbPubkey) {
throw new Error(ERRORS.MISSING_PUBLIC_KEY);
}
const preparedTx = await this.client.POST('/sui/transaction/prepare', {
body: {
pubkey: fbPubkey,
signature: signature,
tx_serialized: tx.unsigned_tx_serialized,
},
});
if (preparedTx.error || !preparedTx.data) {
throw new Error(ERRORS.FAILED_TO_PREPARE);
}
return {
signed_tx: preparedTx.data,
fireblocks_tx: fbTx,
};
}
}
//# sourceMappingURL=fireblocks.js.map