UNPKG

@kilnfi/sdk

Version:

JavaScript sdk for Kiln API

1,013 lines 37.8 kB
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