1515import com .google .protobuf .GeneratedMessageV3 ;
1616import java .io .Closeable ;
1717import java .io .IOException ;
18+ import java .util .ArrayList ;
1819import java .util .Arrays ;
1920import java .util .HashMap ;
2021import java .util .Iterator ;
3738import org .tron .api .GrpcAPI .Return ;
3839import org .tron .api .GrpcAPI .Return .response_code ;
3940import org .tron .api .GrpcAPI .TransactionExtention ;
41+ import org .tron .api .GrpcAPI .TransactionInfoList ;
4042import org .tron .common .crypto .Hash ;
4143import org .tron .common .es .ExecutorServiceManager ;
4244import org .tron .common .logsfilter .ContractEventParser ;
7577import org .tron .core .services .jsonrpc .types .BuildArguments ;
7678import org .tron .core .services .jsonrpc .types .CallArguments ;
7779import org .tron .core .services .jsonrpc .types .TransactionReceipt ;
80+ import org .tron .core .services .jsonrpc .types .TransactionReceipt .TransactionContext ;
7881import org .tron .core .services .jsonrpc .types .TransactionResult ;
7982import org .tron .core .store .StorageRowStore ;
8083import org .tron .core .vm .program .Storage ;
8184import org .tron .program .Version ;
8285import org .tron .protos .Protocol .Account ;
8386import org .tron .protos .Protocol .Block ;
87+ import org .tron .protos .Protocol .ResourceReceipt ;
8488import org .tron .protos .Protocol .Transaction ;
8589import org .tron .protos .Protocol .Transaction .Contract .ContractType ;
8690import org .tron .protos .Protocol .Transaction .Result .code ;
9397import org .tron .protos .contract .SmartContractOuterClass .SmartContractDataWrapper ;
9498import org .tron .protos .contract .SmartContractOuterClass .TriggerSmartContract ;
9599
100+
96101@ Slf4j (topic = "API" )
97102@ Component
98103public class TronJsonRpcImpl implements TronJsonRpc , Closeable {
@@ -767,6 +772,13 @@ public TransactionResult getTransactionByBlockNumberAndIndex(String blockNumOrTa
767772 return getTransactionByBlockAndIndex (block , index );
768773 }
769774
775+ /**
776+ * Get a transaction receipt by transaction hash
777+ *
778+ * @param txId the transaction hash in hex format (with or without 0x prefix)
779+ * @return TransactionReceipt object for the specified transaction, or null if not found
780+ * @throws JsonRpcInvalidParamsException if the transaction hash format is invalid
781+ */
770782 @ Override
771783 public TransactionReceipt getTransactionReceipt (String txId )
772784 throws JsonRpcInvalidParamsException {
@@ -781,7 +793,116 @@ public TransactionReceipt getTransactionReceipt(String txId)
781793 return null ;
782794 }
783795
784- return new TransactionReceipt (block , transactionInfo , wallet );
796+ BlockCapsule blockCapsule = new BlockCapsule (block );
797+ long blockNum = blockCapsule .getNum ();
798+ TransactionInfoList transactionInfoList = wallet .getTransactionInfoByBlockNum (blockNum );
799+ long energyFee = wallet .getEnergyFee (blockCapsule .getTimeStamp ());
800+
801+ // Find transaction context
802+ TransactionReceipt .TransactionContext context
803+ = findTransactionContext (transactionInfoList ,
804+ transactionInfo .getId ());
805+
806+ if (context == null ) {
807+ return null ; // Transaction not found in block
808+ }
809+
810+ return new TransactionReceipt (blockCapsule , transactionInfo , context , energyFee );
811+ }
812+
813+ /**
814+ * Finds transaction context for a specific transaction ID within the block
815+ * Calculates cumulative gas and log count up to the target transaction
816+ * @param infoList the transactionInfo list for the block
817+ * @param txId the transaction ID
818+ * @return TransactionContext containing index and cumulative values, or null if not found
819+ */
820+ private TransactionContext findTransactionContext (TransactionInfoList infoList ,
821+ ByteString txId ) {
822+
823+ long cumulativeGas = 0 ;
824+ long cumulativeLogCount = 0 ;
825+
826+ for (int index = 0 ; index < infoList .getTransactionInfoCount (); index ++) {
827+ TransactionInfo info = infoList .getTransactionInfo (index );
828+ ResourceReceipt resourceReceipt = info .getReceipt ();
829+
830+ if (info .getId ().equals (txId )) {
831+ return new TransactionContext (index , cumulativeGas , cumulativeLogCount );
832+ } else {
833+ cumulativeGas += resourceReceipt .getEnergyUsageTotal ();
834+ cumulativeLogCount += info .getLogCount ();
835+ }
836+ }
837+ return null ;
838+ }
839+
840+ /**
841+ * Get all transaction receipts for a specific block
842+ * @param blockNumOrTag the block number or tag (latest, earliest, pending, finalized)
843+ * @return List of TransactionReceipt objects for all transactions in the block,
844+ * null if block not found
845+ * @throws JsonRpcInvalidParamsException if the parameter format is invalid
846+ * @throws JsonRpcInternalException if there's an internal error
847+ */
848+ @ Override
849+ public List <TransactionReceipt > getBlockReceipts (String blockNumOrTag )
850+ throws JsonRpcInvalidParamsException , JsonRpcInternalException {
851+ Block block = wallet .getByJsonBlockId (blockNumOrTag );
852+ if (block == null ) {
853+ return null ;
854+ }
855+
856+ BlockCapsule blockCapsule = new BlockCapsule (block );
857+ long blockNum = blockCapsule .getNum ();
858+ TransactionInfoList transactionInfoList = wallet .getTransactionInfoByBlockNum (blockNum );
859+
860+ //energy price at the block timestamp
861+ long energyFee = wallet .getEnergyFee (blockCapsule .getTimeStamp ());
862+
863+ // Validate transaction list size consistency
864+ int transactionSizeInBlock = blockCapsule .getTransactions ().size ();
865+ if (transactionSizeInBlock != transactionInfoList .getTransactionInfoCount ()) {
866+ throw new JsonRpcInternalException (
867+ String .format ("TransactionList size mismatch: "
868+ + "block has %d transactions, but transactionInfoList has %d" ,
869+ transactionSizeInBlock , transactionInfoList .getTransactionInfoCount ()));
870+ }
871+
872+ return getTransactionReceiptsFromBlock (blockCapsule , transactionInfoList , energyFee );
873+ }
874+
875+ /**
876+ * Get all TransactionReceipts from a block
877+ * This method processes all transactions in the block
878+ * and creates receipts with cumulative gas calculations
879+ * @param blockCapsule the block containing transactions
880+ * @param transactionInfoList the transaction info list for the block
881+ * @param energyFee the energy price at the block timestamp
882+ * @return List of TransactionReceipt objects for all transactions in the block
883+ */
884+ private List <TransactionReceipt > getTransactionReceiptsFromBlock (BlockCapsule blockCapsule ,
885+ TransactionInfoList transactionInfoList , long energyFee ) {
886+
887+ List <TransactionReceipt > receipts = new ArrayList <>();
888+ long cumulativeGas = 0 ;
889+ long cumulativeLogCount = 0 ;
890+
891+ for (int index = 0 ; index < transactionInfoList .getTransactionInfoCount (); index ++) {
892+ TransactionInfo info = transactionInfoList .getTransactionInfo (index );
893+ ResourceReceipt resourceReceipt = info .getReceipt ();
894+
895+ TransactionReceipt .TransactionContext context = new TransactionContext (
896+ index , cumulativeGas , cumulativeLogCount );
897+
898+ // Use the constructor with pre-calculated context
899+ TransactionReceipt receipt = new TransactionReceipt (blockCapsule , info , context , energyFee );
900+ receipts .add (receipt );
901+
902+ cumulativeGas += resourceReceipt .getEnergyUsageTotal ();
903+ cumulativeLogCount += info .getLogCount ();
904+ }
905+ return receipts ;
785906 }
786907
787908 @ Override
0 commit comments