@@ -243,7 +243,7 @@ export class SDKClient {
243243 async submitEthereumTransaction (
244244 transactionBuffer : Uint8Array ,
245245 callerName : string ,
246- requestId ? : string ,
246+ requestId : string ,
247247 ) : Promise < { txResponse : TransactionResponse ; fileId : FileId | null } > {
248248 const ethereumTransactionData : EthereumTransactionData = EthereumTransactionData . fromBytes ( transactionBuffer ) ;
249249 const ethereumTransaction = new EthereumTransaction ( ) ;
@@ -476,6 +476,7 @@ export class SDKClient {
476476
477477 this . logger . info ( `${ requestIdPrefix } Execute ${ transactionType } transaction` ) ;
478478 const resp = await transaction . execute ( this . clientMain ) ;
479+
479480 this . logger . info (
480481 `${ requestIdPrefix } ${ resp . transactionId } ${ callerName } ${ transactionType } status: ${ Status . Success } (${ Status . Success . _code } )` ,
481482 ) ;
@@ -643,60 +644,146 @@ export class SDKClient {
643644 private createFile = async (
644645 callData : Uint8Array ,
645646 client : Client ,
646- requestId ? : string ,
647- callerName ? : string ,
648- interactingEntity ? : string ,
647+ requestId : string ,
648+ callerName : string ,
649+ interactingEntity : string ,
649650 ) => {
650651 const requestIdPrefix = formatRequestIdMessage ( requestId ) ;
651652 const hexedCallData = Buffer . from ( callData ) . toString ( 'hex' ) ;
653+ const currentDateNow = Date . now ( ) ;
654+ let fileCreateTx , fileAppendTx ;
652655
653- const fileCreateTx = await new FileCreateTransaction ( )
654- . setContents ( hexedCallData . substring ( 0 , this . fileAppendChunkSize ) )
655- . setKeys ( client . operatorPublicKey ? [ client . operatorPublicKey ] : [ ] ) ;
656- const fileCreateTxResponse = await fileCreateTx . execute ( client ) ;
657- const { fileId } = await fileCreateTxResponse . getReceipt ( client ) ;
658-
659- const createFileRecord = await fileCreateTxResponse . getRecord ( this . clientMain ) ;
660- this . captureMetrics (
661- SDKClient . transactionMode ,
662- fileCreateTx . constructor . name ,
663- Status . Success ,
664- createFileRecord . transactionFee . toTinybars ( ) . toNumber ( ) ,
665- createFileRecord ?. contractFunctionResult ?. gasUsed ,
666- callerName ,
667- interactingEntity ,
668- ) ;
656+ try {
657+ const shouldLimit = this . hbarLimiter . shouldLimit ( currentDateNow , SDKClient . transactionMode , callerName ) ;
658+ if ( shouldLimit ) {
659+ throw predefined . HBAR_RATE_LIMIT_EXCEEDED ;
660+ }
669661
670- if ( fileId && callData . length > this . fileAppendChunkSize ) {
671- const fileAppendTx = await new FileAppendTransaction ( )
672- . setFileId ( fileId )
673- . setContents ( hexedCallData . substring ( this . fileAppendChunkSize , hexedCallData . length ) )
674- . setChunkSize ( this . fileAppendChunkSize )
675- . setMaxChunks ( this . maxChunks ) ;
676- await fileAppendTx . execute ( client ) ;
662+ fileCreateTx = await new FileCreateTransaction ( )
663+ . setContents ( hexedCallData . substring ( 0 , this . fileAppendChunkSize ) )
664+ . setKeys ( client . operatorPublicKey ? [ client . operatorPublicKey ] : [ ] ) ;
665+
666+ const fileCreateTxResponse = await fileCreateTx . execute ( client ) ;
667+ const { fileId } = await fileCreateTxResponse . getReceipt ( client ) ;
668+
669+ // get transaction fee and add expense to limiter
670+ const createFileRecord = await fileCreateTxResponse . getRecord ( this . clientMain ) ;
671+ let transactionFee = createFileRecord . transactionFee ;
672+ this . hbarLimiter . addExpense ( transactionFee . toTinybars ( ) . toNumber ( ) , currentDateNow ) ;
677673
678674 this . captureMetrics (
679675 SDKClient . transactionMode ,
680- fileAppendTx . constructor . name ,
676+ fileCreateTx . constructor . name ,
681677 Status . Success ,
682- await this . calculateFileAppendTxTotalTinybarsCost ( fileAppendTx ) ,
683- 0 ,
678+ createFileRecord . transactionFee . toTinybars ( ) . toNumber ( ) ,
679+ createFileRecord ?. contractFunctionResult ?. gasUsed ,
684680 callerName ,
685681 interactingEntity ,
686682 ) ;
687- }
688683
689- // Ensure that the calldata file is not empty
690- if ( fileId ) {
691- const fileSize = await ( await new FileInfoQuery ( ) . setFileId ( fileId ) . execute ( client ) ) . size ;
684+ if ( fileId && callData . length > this . fileAppendChunkSize ) {
685+ fileAppendTx = await new FileAppendTransaction ( )
686+ . setFileId ( fileId )
687+ . setContents ( hexedCallData . substring ( this . fileAppendChunkSize , hexedCallData . length ) )
688+ . setChunkSize ( this . fileAppendChunkSize )
689+ . setMaxChunks ( this . maxChunks ) ;
690+ const fileAppendTxResponse = await fileAppendTx . execute ( client ) ;
691+
692+ // get transaction fee and add expense to limiter
693+ const appendFileRecord = await fileAppendTxResponse . getRecord ( this . clientMain ) ;
694+ transactionFee = appendFileRecord . transactionFee ;
695+ this . hbarLimiter . addExpense ( transactionFee . toTinybars ( ) . toNumber ( ) , currentDateNow ) ;
696+
697+ this . captureMetrics (
698+ SDKClient . transactionMode ,
699+ fileAppendTx . constructor . name ,
700+ Status . Success ,
701+ await this . calculateFileAppendTxTotalTinybarsCost ( fileAppendTx ) ,
702+ 0 ,
703+ callerName ,
704+ interactingEntity ,
705+ ) ;
706+ }
707+
708+ // Ensure that the calldata file is not empty
709+ if ( fileId ) {
710+ const fileSize = await ( await new FileInfoQuery ( ) . setFileId ( fileId ) . execute ( client ) ) . size ;
692711
693- if ( callData . length > 0 && fileSize . isZero ( ) ) {
694- throw new SDKClientError ( { } , `${ requestIdPrefix } Created file is empty. ` ) ;
712+ if ( callData . length > 0 && fileSize . isZero ( ) ) {
713+ throw new SDKClientError ( { } , `${ requestIdPrefix } Created file is empty. ` ) ;
714+ }
715+ this . logger . trace ( `${ requestIdPrefix } Created file with fileId: ${ fileId } and file size ${ fileSize } ` ) ;
716+ }
717+
718+ return fileId ;
719+ } catch ( error : any ) {
720+ const sdkClientError = new SDKClientError ( error , error . message ) ;
721+ let transactionFee : number | Hbar = 0 ;
722+
723+ // if valid network error utilize transaction id
724+ if ( sdkClientError . isValidNetworkError ( ) ) {
725+ try {
726+ const transactionCreateRecord = await new TransactionRecordQuery ( )
727+ . setTransactionId ( fileCreateTx . transactionId ! )
728+ . setNodeAccountIds ( fileCreateTx . nodeAccountIds ! )
729+ . setValidateReceiptStatus ( false )
730+ . execute ( this . clientMain ) ;
731+ transactionFee = transactionCreateRecord . transactionFee ;
732+ this . hbarLimiter . addExpense ( transactionFee . toTinybars ( ) . toNumber ( ) , currentDateNow ) ;
733+
734+ this . captureMetrics (
735+ SDKClient . transactionMode ,
736+ fileCreateTx . constructor . name ,
737+ sdkClientError . status ,
738+ transactionFee . toTinybars ( ) . toNumber ( ) ,
739+ transactionCreateRecord ?. contractFunctionResult ?. gasUsed ,
740+ callerName ,
741+ interactingEntity ,
742+ ) ;
743+
744+ this . logger . info (
745+ `${ requestIdPrefix } ${ fileCreateTx . transactionId } ${ callerName } ${ fileCreateTx . constructor . name } status: ${ sdkClientError . status } (${ sdkClientError . status . _code } ), cost: ${ transactionFee } ` ,
746+ ) ;
747+
748+ if ( fileAppendTx ) {
749+ const transactionAppendRecord = await new TransactionRecordQuery ( )
750+ . setTransactionId ( fileAppendTx . transactionId ! )
751+ . setNodeAccountIds ( fileAppendTx . nodeAccountIds ! )
752+ . setValidateReceiptStatus ( false )
753+ . execute ( this . clientMain ) ;
754+ transactionFee = transactionAppendRecord . transactionFee ;
755+ this . hbarLimiter . addExpense ( transactionFee . toTinybars ( ) . toNumber ( ) , currentDateNow ) ;
756+
757+ this . captureMetrics (
758+ SDKClient . transactionMode ,
759+ fileCreateTx . constructor . name ,
760+ sdkClientError . status ,
761+ transactionFee . toTinybars ( ) . toNumber ( ) ,
762+ transactionCreateRecord ?. contractFunctionResult ?. gasUsed ,
763+ callerName ,
764+ interactingEntity ,
765+ ) ;
766+
767+ this . logger . info (
768+ `${ requestIdPrefix } ${ fileAppendTx . transactionId } ${ callerName } ${ fileCreateTx . constructor . name } status: ${ sdkClientError . status } (${ sdkClientError . status . _code } ), cost: ${ transactionFee } ` ,
769+ ) ;
770+ }
771+ } catch ( err : any ) {
772+ const recordQueryError = new SDKClientError ( err , err . message ) ;
773+ this . logger . error (
774+ recordQueryError ,
775+ `${ requestIdPrefix } Error raised during TransactionRecordQuery for ${ fileCreateTx . transactionId } ` ,
776+ ) ;
777+ }
695778 }
696- this . logger . trace ( `${ requestIdPrefix } Created file with fileId: ${ fileId } and file size ${ fileSize } ` ) ;
697- }
698779
699- return fileId ;
780+ this . logger . info ( `${ requestIdPrefix } HBAR_RATE_LIMIT_EXCEEDED cost: ${ transactionFee } ` ) ;
781+
782+ if ( error instanceof JsonRpcError ) {
783+ throw predefined . HBAR_RATE_LIMIT_EXCEEDED ;
784+ }
785+ throw sdkClientError ;
786+ }
700787 } ;
701788
702789 /**
0 commit comments