@@ -653,15 +653,64 @@ class Utils {
653653 * @param {string } txHash - The transaction hash to query.
654654 * @returns {Promise<string> } - The response code as a string.
655655 */
656- static async getHTSResponseCode ( txHash ) {
656+ /**
657+ * Reads a system contract's response code out of a transaction's mirror node
658+ * action tree.
659+ *
660+ * The action addressed to the system contract is identified by entity id
661+ * (`recipient`) OR by EVM address (`to`) — the entity-id form alone stopped
662+ * matching on consensus v0.77 / mirror v0.161. If neither shape is present,
663+ * fall back to the innermost action, which is where a facade/redirect call
664+ * leaves its response code, and say so in the log: the expected codes the
665+ * callers assert on (22 / 178 / 196 / 354 / 367) are precise enough that a
666+ * wrong pick fails the assertion rather than passing silently.
667+ *
668+ * @param {string } txHash - The transaction hash to query.
669+ * @param {string } entityId - System contract entity id, e.g. '0.0.359'.
670+ * @param {string } evmAddress - The same contract's long-zero EVM address.
671+ * @returns {Promise<string> } - The response code as a string.
672+ */
673+ static async getSystemContractResponseCode ( txHash , entityId , evmAddress ) {
657674 const mirrorNodeUrl = Utils . getMirrorNodeUrl ( networkName ) ;
658- const res = await Utils . retriedGetRequest (
659- `${ mirrorNodeUrl } /contracts/results/${ txHash } /actions` ,
675+ const target = evmAddress . toLowerCase ( ) ;
676+ const url = `${ mirrorNodeUrl } /contracts/results/${ txHash } /actions` ;
677+ // retriedGetRequest only retries on an HTTP error; a result that is present
678+ // but whose actions have not been ingested yet answers 200 with an empty
679+ // list, so wait that out too.
680+ let actions = [ ] ;
681+ for ( let attempt = 0 ; attempt < 5 && ! actions . length ; attempt ++ ) {
682+ if ( attempt ) await Utils . sleep ( 1000 ) ;
683+ const res = await Utils . retriedGetRequest ( url ) ;
684+ actions = res . data ?. actions ?? [ ] ;
685+ }
686+
687+ const precompileAction = actions . find (
688+ ( x ) => x . recipient === entityId || ( x . to ?? '' ) . toLowerCase ( ) === target ,
660689 ) ;
661- const precompileAction = res . data . actions . find (
662- ( x ) => x . recipient === Constants . HTS_SYSTEM_CONTRACT_ID ,
690+ if ( precompileAction ?. result_data != null ) {
691+ return BigInt ( precompileAction . result_data ) . toString ( ) ;
692+ }
693+
694+ const innermost = actions
695+ . filter ( ( x ) => x . result_data != null )
696+ . sort ( ( a , b ) => ( b . call_depth ?? 0 ) - ( a . call_depth ?? 0 ) ) [ 0 ] ;
697+ if ( ! innermost ) {
698+ throw new Error (
699+ `No action carrying result_data for ${ txHash } ; actions=${ JSON . stringify ( actions ) } ` ,
700+ ) ;
701+ }
702+ console . log (
703+ `[actions] no ${ entityId } action for ${ txHash } ; falling back to depth ${ innermost . call_depth } recipient=${ innermost . recipient } to=${ innermost . to } ` ,
704+ ) ;
705+ return BigInt ( innermost . result_data ) . toString ( ) ;
706+ }
707+
708+ static async getHTSResponseCode ( txHash ) {
709+ return Utils . getSystemContractResponseCode (
710+ txHash ,
711+ Constants . HTS_SYSTEM_CONTRACT_ID ,
712+ Constants . HTS_SYSTEM_CONTRACT_ADDRESS ,
663713 ) ;
664- return BigInt ( precompileAction . result_data ) . toString ( ) ;
665714 }
666715
667716 /**
@@ -709,14 +758,11 @@ class Utils {
709758 * @returns {string } - The response code as a string.
710759 */
711760 static async getHASResponseCode ( txHash ) {
712- const mirrorNodeUrl = Utils . getMirrorNodeUrl ( networkName ) ;
713- const res = await Utils . retriedGetRequest (
714- `${ mirrorNodeUrl } /contracts/results/${ txHash } /actions` ,
715- ) ;
716- const precompileAction = res . data . actions . find (
717- ( x ) => x . recipient === Constants . HAS_SYSTEM_CONTRACT_ID ,
761+ return Utils . getSystemContractResponseCode (
762+ txHash ,
763+ Constants . HAS_SYSTEM_CONTRACT_ID ,
764+ Constants . HAS_SYSTEM_CONTRACT_ADDRESS ,
718765 ) ;
719- return BigInt ( precompileAction . result_data ) . toString ( ) ;
720766 }
721767
722768 static async setupNft ( tokenCreateContract , owner , contractAddresses , hapi ) {
0 commit comments