@@ -61,14 +61,14 @@ import {
6161 getAminoStdSignDoc ,
6262 getEip712TypedData ,
6363 createWeb3Extension ,
64+ CosmosTxV1Beta1TxPb ,
6465 getEip712TypedDataV2 ,
6566 createTxRawFromSigResponse ,
6667 createTransactionWithSigners ,
6768} from '@injectivelabs/sdk-ts/core/tx'
6869import { checkIfTxRunOutOfGas } from '../utils/index.js'
6970import type { NetworkEndpoints } from '@injectivelabs/networks'
7071import type { ThrownException } from '@injectivelabs/exceptions'
71- import type { CosmosTxV1Beta1TxPb } from '@injectivelabs/sdk-ts'
7272import type { DirectSignResponse } from '@injectivelabs/sdk-ts/types'
7373import type { Wallet as WalletType } from '@injectivelabs/wallet-base'
7474import type {
@@ -348,6 +348,108 @@ export class MsgBroadcaster {
348348 }
349349 }
350350
351+ /**
352+ * Sign and broadcast a pre-built transaction that already includes
353+ * a fee payer's signature, directly to chain (bypassing web3gw).
354+ */
355+ async broadcastWithFeePayerSig ( {
356+ tx,
357+ feePayerSig,
358+ accountNumber,
359+ injectiveAddress,
360+ } : {
361+ feePayerSig : string
362+ accountNumber : number
363+ tx : Uint8Array | string
364+ injectiveAddress : string
365+ } ) : Promise < TxResponse > {
366+ const {
367+ chainId,
368+ endpoints,
369+ walletStrategy,
370+ txTimeout : txTimeoutInBlocks ,
371+ } = this
372+
373+ if ( ! isCosmosWallet ( walletStrategy . wallet ) ) {
374+ throw new GeneralException (
375+ new Error (
376+ 'broadcastWithFeePayerSig only supports Cosmos wallets (Keplr, Leap, etc.). EVM wallets are not supported for SIGN_MODE_DIRECT.' ,
377+ ) ,
378+ )
379+ }
380+
381+ const txBytes = typeof tx === 'string' ? base64ToUint8Array ( tx ) : tx
382+ const txRaw = CosmosTxV1Beta1TxPb . TxRaw . fromBinary ( txBytes )
383+
384+ const cosmosWallet = walletStrategy . getCosmosWallet ( chainId )
385+ const canDisableCosmosGasCheck = (
386+ [ Wallet . Keplr , Wallet . OWallet ] as WalletType [ ]
387+ ) . includes ( walletStrategy . wallet )
388+
389+ if ( canDisableCosmosGasCheck && cosmosWallet . disableGasCheck ) {
390+ cosmosWallet . disableGasCheck ( chainId )
391+ }
392+
393+ try {
394+ walletStrategy . emit (
395+ WalletStrategyEmitterEventType . TransactionPreparationStart ,
396+ )
397+
398+ const directSignResponse = ( await walletStrategy . signCosmosTransaction ( {
399+ txRaw,
400+ chainId,
401+ accountNumber,
402+ address : injectiveAddress ,
403+ } ) ) as DirectSignResponse
404+
405+ walletStrategy . emit (
406+ WalletStrategyEmitterEventType . TransactionPreparationEnd ,
407+ )
408+
409+ const signedTxRaw = CosmosTxV1Beta1TxPb . TxRaw . create ( )
410+ signedTxRaw . bodyBytes = directSignResponse . signed . bodyBytes
411+ signedTxRaw . authInfoBytes = directSignResponse . signed . authInfoBytes
412+
413+ const takerSig = base64ToUint8Array (
414+ directSignResponse . signature . signature ,
415+ )
416+ const feePayerSigBytes = feePayerSig . startsWith ( '0x' )
417+ ? hexToUint8Array ( feePayerSig . slice ( 2 ) )
418+ : base64ToUint8Array ( feePayerSig )
419+
420+ signedTxRaw . signatures = [ takerSig , feePayerSigBytes ]
421+
422+ walletStrategy . emit (
423+ WalletStrategyEmitterEventType . TransactionBroadcastStart ,
424+ )
425+
426+ const txResponse = await new TxGrpcApi ( endpoints . grpc ) . broadcast (
427+ signedTxRaw ,
428+ { txTimeout : txTimeoutInBlocks } ,
429+ )
430+
431+ walletStrategy . emit (
432+ WalletStrategyEmitterEventType . TransactionBroadcastEnd ,
433+ )
434+
435+ return txResponse
436+ } catch ( e ) {
437+ const error = e as any
438+
439+ walletStrategy . emit ( WalletStrategyEmitterEventType . TransactionFail )
440+
441+ if ( isThrownException ( error ) ) {
442+ throw error
443+ }
444+
445+ throw new TransactionException ( new Error ( error ) )
446+ } finally {
447+ if ( canDisableCosmosGasCheck && cosmosWallet . enableGasCheck ) {
448+ cosmosWallet . enableGasCheck ( chainId )
449+ }
450+ }
451+ }
452+
351453 /**
352454 * Prepare/sign/broadcast transaction using
353455 * Ethereum native wallets on the client side.
0 commit comments