From 54114b185154d82a7c4e43f01085f7eb78680aa2 Mon Sep 17 00:00:00 2001 From: menefrego15 Date: Wed, 1 Oct 2025 17:02:08 +0200 Subject: [PATCH 1/2] improve signature flow fireblocks (split create and wait) --- src/fireblocks.ts | 534 ++++++++++++++++++++++++++++++++------- src/fireblocks_signer.ts | 22 +- 2 files changed, 465 insertions(+), 91 deletions(-) diff --git a/src/fireblocks.ts b/src/fireblocks.ts index 433eb85..76adf75 100644 --- a/src/fireblocks.ts +++ b/src/fireblocks.ts @@ -186,14 +186,14 @@ export class FireblocksService { /** * Sign a ATOM transaction on Fireblocks */ - async signAtomTx( + /** + * Create an ATOM transaction in Fireblocks without waiting for completion + */ + async createAtomTx( integration: FireblocksIntegration, tx: components['schemas']['ATOMUnsignedTx'] | components['schemas']['ATOMStakeUnsignedTx'], note?: string, - ): Promise<{ - signed_tx: { data: components['schemas']['ATOMSignedTx'] }; - fireblocks_tx: TransactionResponse; - }> { + ): Promise { const payload = { rawMessageData: { messages: [ @@ -210,8 +210,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'ATOM tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, 'ATOM_COS', fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, 'ATOM_COS', fbNote); + } + + /** + * Wait for an ATOM transaction to complete and prepare it for broadcast + */ + async waitForAtomTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['ATOMUnsignedTx'] | components['schemas']['ATOMStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['ATOMSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -232,21 +247,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a DYDX transaction on Fireblocks + * Sign an ATOM transaction on Fireblocks (combines createAtomTx and waitForAtomTxCompletion) */ - async signDydxTx( + async signAtomTx( integration: FireblocksIntegration, - tx: components['schemas']['DYDXUnsignedTx'] | components['schemas']['DYDXStakeUnsignedTx'], + tx: components['schemas']['ATOMUnsignedTx'] | components['schemas']['ATOMStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['DYDXSignedTx'] }; + signed_tx: { data: components['schemas']['ATOMSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + 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: FireblocksIntegration, + tx: components['schemas']['DYDXUnsignedTx'] | components['schemas']['DYDXStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -263,8 +293,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'DYDX tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, 'DYDX_DYDX', fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, 'DYDX_DYDX', fbNote); + } + + /** + * Wait for a DYDX transaction to complete and prepare it for broadcast + */ + async waitForDydxTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['DYDXUnsignedTx'] | components['schemas']['DYDXStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['DYDXSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -285,21 +330,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a FET transaction on Fireblocks + * Sign a DYDX transaction on Fireblocks (combines createDydxTx and waitForDydxTxCompletion) */ - async signFetTx( + async signDydxTx( integration: FireblocksIntegration, - tx: components['schemas']['FETUnsignedTx'] | components['schemas']['FETStakeUnsignedTx'], + tx: components['schemas']['DYDXUnsignedTx'] | components['schemas']['DYDXStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['FETSignedTx'] }; + signed_tx: { data: components['schemas']['DYDXSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + 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: FireblocksIntegration, + tx: components['schemas']['FETUnsignedTx'] | components['schemas']['FETStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -318,8 +378,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'FET tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, undefined, fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, undefined, fbNote); + } + + /** + * Wait for a FET transaction to complete and prepare it for broadcast + */ + async waitForFetTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['FETUnsignedTx'] | components['schemas']['FETStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['FETSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -340,21 +415,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a OM transaction on Fireblocks + * Sign a FET transaction on Fireblocks (combines createFetTx and waitForFetTxCompletion) */ - async signOmTx( + async signFetTx( integration: FireblocksIntegration, - tx: components['schemas']['OMUnsignedTx'] | components['schemas']['OMStakeUnsignedTx'], + tx: components['schemas']['FETUnsignedTx'] | components['schemas']['FETStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['OMSignedTx'] }; + signed_tx: { data: components['schemas']['FETSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + const fbTx = await this.createFetTx(integration, tx, note); + return await this.waitForFetTxCompletion(integration, tx, fbTx); + } + + /** + * Sign a OM transaction on Fireblocks + */ + /** + * Create a OM transaction in Fireblocks without waiting for completion + */ + async createOmTx( + integration: FireblocksIntegration, + tx: components['schemas']['OMUnsignedTx'] | components['schemas']['OMStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -373,8 +463,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'OM tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, undefined, fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, undefined, fbNote); + } + + /** + * Wait for a OM transaction to complete and prepare it for broadcast + */ + async waitForOmTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['OMUnsignedTx'] | components['schemas']['OMStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['OMSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -395,21 +500,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a INJ transaction on Fireblocks + * Sign a OM transaction on Fireblocks (combines createOmTx and waitForOmTxCompletion) */ - async signInjTx( + async signOmTx( integration: FireblocksIntegration, - tx: components['schemas']['INJUnsignedTx'] | components['schemas']['INJStakeUnsignedTx'], + tx: components['schemas']['OMUnsignedTx'] | components['schemas']['OMStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['INJSignedTx'] }; + signed_tx: { data: components['schemas']['OMSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + const fbTx = await this.createOmTx(integration, tx, note); + return await this.waitForOmTxCompletion(integration, tx, fbTx); + } + + /** + * Sign a INJ transaction on Fireblocks + */ + /** + * Create a INJ transaction in Fireblocks without waiting for completion + */ + async createInjTx( + integration: FireblocksIntegration, + tx: components['schemas']['INJUnsignedTx'] | components['schemas']['INJStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -426,8 +546,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'INJ tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, 'INJ_INJ', fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, 'INJ_INJ', fbNote); + } + + /** + * Wait for a INJ transaction to complete and prepare it for broadcast + */ + async waitForInjTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['INJUnsignedTx'] | components['schemas']['INJStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['INJSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -448,21 +583,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a KAVA transaction on Fireblocks + * Sign a INJ transaction on Fireblocks (combines createInjTx and waitForInjTxCompletion) */ - async signKavaTx( + async signInjTx( integration: FireblocksIntegration, - tx: components['schemas']['KAVAUnsignedTx'] | components['schemas']['KAVAStakeUnsignedTx'], + tx: components['schemas']['INJUnsignedTx'] | components['schemas']['INJStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['KAVASignedTx'] }; + signed_tx: { data: components['schemas']['INJSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + const fbTx = await this.createInjTx(integration, tx, note); + return await this.waitForInjTxCompletion(integration, tx, fbTx); + } + + /** + * Sign a KAVA transaction on Fireblocks + */ + /** + * Create a KAVA transaction in Fireblocks without waiting for completion + */ + async createKavaTx( + integration: FireblocksIntegration, + tx: components['schemas']['KAVAUnsignedTx'] | components['schemas']['KAVAStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -481,8 +631,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'KAVA tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, undefined, fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, undefined, fbNote); + } + + /** + * Wait for a KAVA transaction to complete and prepare it for broadcast + */ + async waitForKavaTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['KAVAUnsignedTx'] | components['schemas']['KAVAStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['KAVASignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -503,21 +668,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a CRO transaction on Fireblocks + * Sign a KAVA transaction on Fireblocks (combines createKavaTx and waitForKavaTxCompletion) */ - async signCroTx( + async signKavaTx( integration: FireblocksIntegration, - tx: components['schemas']['CROUnsignedTx'] | components['schemas']['CROStakeUnsignedTx'], + tx: components['schemas']['KAVAUnsignedTx'] | components['schemas']['KAVAStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['CROSignedTx'] }; + signed_tx: { data: components['schemas']['KAVASignedTx'] }; fireblocks_tx: TransactionResponse; }> { + const fbTx = await this.createKavaTx(integration, tx, note); + return await this.waitForKavaTxCompletion(integration, tx, fbTx); + } + + /** + * Sign a CRO transaction on Fireblocks + */ + /** + * Create a CRO transaction in Fireblocks without waiting for completion + */ + async createCroTx( + integration: FireblocksIntegration, + tx: components['schemas']['CROUnsignedTx'] | components['schemas']['CROStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -536,8 +716,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'CRO tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, undefined, fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, undefined, fbNote); + } + + /** + * Wait for a CRO transaction to complete and prepare it for broadcast + */ + async waitForCroTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['CROUnsignedTx'] | components['schemas']['CROStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['CROSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -558,21 +753,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a NOBLE transaction on Fireblocks + * Sign a CRO transaction on Fireblocks (combines createCroTx and waitForCroTxCompletion) */ - async signNobleTx( + async signCroTx( integration: FireblocksIntegration, - tx: components['schemas']['DYDXUnsignedTx'], + tx: components['schemas']['CROUnsignedTx'] | components['schemas']['CROStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['DYDXSignedTx'] }; + signed_tx: { data: components['schemas']['CROSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + 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: FireblocksIntegration, + tx: components['schemas']['DYDXUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -591,8 +801,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'NOBLE tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, undefined, fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, undefined, fbNote); + } + + /** + * Wait for a NOBLE transaction to complete and prepare it for broadcast + */ + async waitForNobleTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['DYDXUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['DYDXSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -613,21 +838,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a OSMO transaction on Fireblocks + * Sign a NOBLE transaction on Fireblocks (combines createNobleTx and waitForNobleTxCompletion) */ - async signOsmoTx( + async signNobleTx( integration: FireblocksIntegration, - tx: components['schemas']['OSMOUnsignedTx'] | components['schemas']['OSMOStakeUnsignedTx'], + tx: components['schemas']['DYDXUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['OSMOSignedTx'] }; + signed_tx: { data: components['schemas']['DYDXSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + 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: FireblocksIntegration, + tx: components['schemas']['OSMOUnsignedTx'] | components['schemas']['OSMOStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -644,8 +884,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'OSMO tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, 'OSMO', fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, 'OSMO', fbNote); + } + + /** + * Wait for a OSMO transaction to complete and prepare it for broadcast + */ + async waitForOsmoTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['OSMOUnsignedTx'] | components['schemas']['OSMOStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['OSMOSignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -666,21 +921,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a TIA transaction on Fireblocks + * Sign a OSMO transaction on Fireblocks (combines createOsmoTx and waitForOsmoTxCompletion) */ - async signTiaTx( + async signOsmoTx( integration: FireblocksIntegration, - tx: components['schemas']['TIAUnsignedTx'] | components['schemas']['TIAStakeUnsignedTx'], + tx: components['schemas']['OSMOUnsignedTx'] | components['schemas']['OSMOStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['TIASignedTx'] }; + signed_tx: { data: components['schemas']['OSMOSignedTx'] }; fireblocks_tx: TransactionResponse; }> { + 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: FireblocksIntegration, + tx: components['schemas']['TIAUnsignedTx'] | components['schemas']['TIAStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -697,8 +967,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'TIA tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, 'CELESTIA', fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, 'CELESTIA', fbNote); + } + + /** + * Wait for a TIA transaction to complete and prepare it for broadcast + */ + async waitForTiaTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['TIAUnsignedTx'] | components['schemas']['TIAStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['TIASignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -719,21 +1004,36 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } /** - * Sign a ZETA transaction on Fireblocks + * Sign a TIA transaction on Fireblocks (combines createTiaTx and waitForTiaTxCompletion) */ - async signZetaTx( + async signTiaTx( integration: FireblocksIntegration, - tx: components['schemas']['ZETAUnsignedTx'] | components['schemas']['ZETAStakeUnsignedTx'], + tx: components['schemas']['TIAUnsignedTx'] | components['schemas']['TIAStakeUnsignedTx'], note?: string, ): Promise<{ - signed_tx: { data: components['schemas']['ZETASignedTx'] }; + signed_tx: { data: components['schemas']['TIASignedTx'] }; fireblocks_tx: TransactionResponse; }> { + const fbTx = await this.createTiaTx(integration, tx, note); + return await this.waitForTiaTxCompletion(integration, tx, fbTx); + } + + /** + * Sign a ZETA transaction on Fireblocks + */ + /** + * Create a ZETA transaction in Fireblocks without waiting for completion + */ + async createZetaTx( + integration: FireblocksIntegration, + tx: components['schemas']['ZETAUnsignedTx'] | components['schemas']['ZETAStakeUnsignedTx'], + note?: string, + ): Promise { const payload = { rawMessageData: { messages: [ @@ -752,8 +1052,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'ZETA tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, undefined, fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, undefined, fbNote); + } + + /** + * Wait for a ZETA transaction to complete and prepare it for broadcast + */ + async waitForZetaTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['ZETAUnsignedTx'] | components['schemas']['ZETAStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['ZETASignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -774,10 +1089,25 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } + /** + * Sign a ZETA transaction on Fireblocks (combines createZetaTx and waitForZetaTxCompletion) + */ + async signZetaTx( + integration: FireblocksIntegration, + tx: components['schemas']['ZETAUnsignedTx'] | components['schemas']['ZETAStakeUnsignedTx'], + note?: string, + ): Promise<{ + signed_tx: { data: components['schemas']['ZETASignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + const fbTx = await this.createZetaTx(integration, tx, note); + return await this.waitForZetaTxCompletion(integration, tx, fbTx); + } + /** * Sign a DOT transaction on Fireblocks */ @@ -1221,20 +1551,20 @@ export class FireblocksService { /** * Sign a SEI transaction on Fireblocks */ - async signSeiTx( + /** + * Create a SEI transaction in Fireblocks without waiting for completion + */ + async createSeiTx( integration: FireblocksIntegration, tx: components['schemas']['SEIUnsignedTx'] | components['schemas']['SEIStakeUnsignedTx'], note?: string, - ): Promise<{ - signed_tx: { data: components['schemas']['SEISignedTx'] }; - fireblocks_tx: TransactionResponse; - }> { + ): Promise { const payload = { rawMessageData: { messages: [ { content: tx.unsigned_tx_hash, - derivationPath: [44, 118, Number(integration.vaultId), 0, 0], + derivationPath: [44, 60, Number(integration.vaultId), 0, 0], preHash: { content: tx.unsigned_tx_serialized, hashAlgorithm: 'SHA256', @@ -1247,8 +1577,23 @@ export class FireblocksService { const fbSigner = this.getSigner(integration); const fbNote = note ? note : 'SEI tx from @kilnfi/sdk'; - const fbTx = await fbSigner.sign(payload, undefined, fbNote); - const signature = fbTx.signedMessages?.[0]?.signature?.fullSig; + return await fbSigner.createTransaction(payload, undefined, fbNote); + } + + /** + * Wait for a SEI transaction to complete and prepare it for broadcast + */ + async waitForSeiTxCompletion( + integration: FireblocksIntegration, + tx: components['schemas']['SEIUnsignedTx'] | components['schemas']['SEIStakeUnsignedTx'], + fbTx: TransactionResponse, + ): Promise<{ + signed_tx: { data: components['schemas']['SEISignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + 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); @@ -1269,10 +1614,25 @@ export class FireblocksService { return { signed_tx: preparedTx.data, - fireblocks_tx: fbTx, + fireblocks_tx: completedTx, }; } + /** + * Sign a SEI transaction on Fireblocks (combines createSeiTx and waitForSeiTxCompletion) + */ + async signSeiTx( + integration: FireblocksIntegration, + tx: components['schemas']['SEIUnsignedTx'] | components['schemas']['SEIStakeUnsignedTx'], + note?: string, + ): Promise<{ + signed_tx: { data: components['schemas']['SEISignedTx'] }; + fireblocks_tx: TransactionResponse; + }> { + const fbTx = await this.createSeiTx(integration, tx, note); + return await this.waitForSeiTxCompletion(integration, tx, fbTx); + } + async signSuiTx( integration: FireblocksIntegration, tx: components['schemas']['SUITx'], diff --git a/src/fireblocks_signer.ts b/src/fireblocks_signer.ts index a91c7a2..2be6927 100644 --- a/src/fireblocks_signer.ts +++ b/src/fireblocks_signer.ts @@ -49,7 +49,7 @@ export class FireblocksSigner { * Wait for given transaction to be completed * @param fbTx fireblocks transaction */ - protected async waitForTxCompletion(fbTx: CreateTransactionResponse): Promise { + public async waitForTxCompletion(fbTx: CreateTransactionResponse): Promise { let tx = fbTx; while (tx.status !== 'COMPLETED') { // see https://developers.fireblocks.com/reference/transaction-substatuses#failed-substatuses @@ -72,12 +72,16 @@ export class FireblocksSigner { } /** - * Sign a transaction with fireblocks using Fireblocks raw message signing feature + * Create a transaction in Fireblocks without waiting for completion * @param payloadToSign transaction data in hexadecimal * @param assetId fireblocks asset id * @param note optional fireblocks custom note */ - public async sign(payloadToSign: object, assetId?: FireblocksAssetId, note = ''): Promise { + public async createTransaction( + payloadToSign: object, + assetId?: FireblocksAssetId, + note = '', + ): Promise { const assetArgs = assetId ? ({ assetId, @@ -94,7 +98,17 @@ export class FireblocksSigner { note, extraParameters: payloadToSign, }; - const fbTx = (await this.fireblocks.transactions.createTransaction({ transactionRequest: tx })).data; + return (await this.fireblocks.transactions.createTransaction({ transactionRequest: tx })).data; + } + + /** + * Sign a transaction with fireblocks using Fireblocks raw message signing feature + * @param payloadToSign transaction data in hexadecimal + * @param assetId fireblocks asset id + * @param note optional fireblocks custom note + */ + public async sign(payloadToSign: object, assetId?: FireblocksAssetId, note = ''): Promise { + const fbTx = await this.createTransaction(payloadToSign, assetId, note); return await this.waitForTxCompletion(fbTx); } From e9f7b4a47257e0557850668b80a3376d6fe0815d Mon Sep 17 00:00:00 2001 From: menefrego15 Date: Wed, 1 Oct 2025 17:15:21 +0200 Subject: [PATCH 2/2] bump version 4.2.20 --- bun.lockb | Bin 22997 -> 23477 bytes examples/sei.ts | 2 +- package.json | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bun.lockb b/bun.lockb index bc7f01a3cb83d87572ed402ac0a214795f62c1e2..0dc9e1841a4b9905e3e111ca41a4446df42c48a7 100755 GIT binary patch delta 937 zcmY+Bzi-n(6vyM#j?cfH)JPFh8K|H@BZycM38%GaXv{`|0jX1m2qCqh3KjC`(PQk# zAHW~L0J0FP#|SYb5=cx4F*7hSa(C}SbT^#+{oZ?@ckkV|Qu+8vncY%0^4;zFwd4HJ z_4>QPhlHr`UL}yKfm5UF65Ht7f+pF4N)416EY&+SMlG~9_}Y*fM;bRE)dKjcbvU5X z+ALHX(Y@I?fTs@nX#>Fua%%>H8w@Nsg)WEaJS5U7+!GM`KhwMH7EtMJSm@`xXhZ^) zabe;0AtN?#VO8l0Rw4+uMSYjKg%KD`UuGM<#x6ugK$y^&G1EJc8kpxYmoB_iWkjrS zVd9~VXQHV{xSr&uChbEEqcSnwk{jN}hAlo5OU%|{^UST6yq+EWA82F;?2@$&I_w@~ zw!Knz59YQHiR!~oyU(7%VUKad_uLsl((M*5qc+_Gc(ZyR7jX(K9SU#}r*lO-RCQQV zc)V6LGV^RPdZ!O_&!^a>$7?|3uaG$l^bykFkoj79Js?dyGkCdJQkkUYk|HfBPg0qr z=8__t>pVW@a=4k@X#E-Bi*@$!YliUa-d*s+(0nGW;XX_TS0M?1o9Fu&^)@OegU5=w zh)`#7`FZb$zVkgs-F}E)Gki5Zdp(}sevn*@r<0S@Cl}Kfljrc|@Fx5{jLcZXZ5@~Q HN6`8QUn$19 delta 774 zcmYk2PiWIn9LMvryyo9a^O|*1gv!{4)Jj1ufKMPE&4dAjA9d`3~ODawBKI{WLwGDM4A#3!hjP`*)vmeGNc zQ6&Vv8nLK7Co*j_bM2ZjJ&QefJ?_H~)20*^6As^Ev|N0nX9Z%Q5mFtgyqsY(;zHey zu|FHRZzsa_-IgOPilzo*tw#?4$J3GoGO`tdrnMoLPZs^6Nkgl@nOD< zJ1i$KC^ba+5$eyVPhH%ei`#QU%>Li_*p;6qqNBzc(cu!0sao_7k*V+jnTAaIf(nQC zy6oS_=RqaRR#u5=smQfGCX_9jU!XFJ{He!?34gtKiuGnQ_H1^V8P$x{tJ7>C*sFr! zB (https://kiln.fi)", "license": "BUSL-1.1", "description": "JavaScript sdk for Kiln API",