@@ -69,6 +69,10 @@ export class EthImpl implements Eth {
6969 static ethGetTransactionCount = 'eth_getTransactionCount' ;
7070 static ethSendRawTransaction = 'eth_sendRawTransaction' ;
7171
72+ // block constants
73+ static blockLatest = 'latest' ;
74+ static blockEarliest = 'earliest' ;
75+ static blockPending = 'pending' ;
7276
7377 /**
7478 * The sdk client use for connecting to both the consensus nodes and mirror node. The account
@@ -139,7 +143,7 @@ export class EthImpl implements Eth {
139143 const requestIdPrefix = formatRequestIdMessage ( requestId ) ;
140144 this . logger . trace ( `${ requestIdPrefix } feeHistory(blockCount=${ blockCount } , newestBlock=${ newestBlock } , rewardPercentiles=${ rewardPercentiles } )` ) ;
141145 try {
142- const latestBlockNumber = await this . translateBlockTag ( 'latest' , requestId ) ;
146+ const latestBlockNumber = await this . translateBlockTag ( EthImpl . blockLatest , requestId ) ;
143147 const newestBlockNumber = await this . translateBlockTag ( newestBlock , requestId ) ;
144148
145149 if ( newestBlockNumber > latestBlockNumber ) {
@@ -441,10 +445,43 @@ export class EthImpl implements Eth {
441445 return predefined . UNSUPPORTED_METHOD ;
442446 }
443447
444- getStorageAt ( address : string , slot : string , blockNumber : string | null , requestId ?: string ) : JsonRpcError {
448+ /**
449+ * Gets the value from a storage position at the given Ethereum address.
450+ *
451+ * @param address
452+ * @param slot
453+ * @param blockNumberOrTag
454+ */
455+ async getStorageAt ( address : string , slot : string , blockNumberOrTag ?: string | null , requestId ?: string ) : Promise < string > {
445456 const requestIdPrefix = formatRequestIdMessage ( requestId ) ;
446- this . logger . trace ( `${ requestIdPrefix } getStorageAt(address=${ address } , slot=${ slot } , blockNumber=${ blockNumber } )` , address , slot , blockNumber ) ;
447- return predefined . UNSUPPORTED_METHOD ;
457+ let result = EthImpl . zeroHex32Byte ; // if contract or slot not found then return 32 byte 0
458+ const blockResponse = await this . getHistoricalBlockResponse ( blockNumberOrTag , false ) ;
459+ const blockEndTimestamp = blockResponse ?. timestamp ?. to ;
460+ const contractResult = await this . mirrorNodeClient . getLatestContractResultsByAddress ( address , blockEndTimestamp , 1 ) ;
461+
462+ if ( contractResult ?. results ?. length > 0 ) {
463+ // retrieve the contract result details
464+ await this . mirrorNodeClient . getContractResultsDetails ( address , contractResult . results [ 0 ] . timestamp )
465+ . then ( contractResultDetails => {
466+ if ( contractResultDetails && contractResultDetails . state_changes ) {
467+ // loop through the state changes to match slot and return value
468+ for ( const stateChange of contractResultDetails . state_changes ) {
469+ if ( stateChange . slot === slot ) {
470+ result = stateChange . value_written ;
471+ }
472+ }
473+ }
474+ } )
475+ . catch ( ( e : any ) => {
476+ this . logger . error (
477+ e ,
478+ `${ requestIdPrefix } Failed to retrieve contract result details for contract address ${ address } at timestamp=${ contractResult . results [ 0 ] . timestamp } ` ,
479+ ) ;
480+ throw e ;
481+ } ) ;
482+ }
483+
484+ return result ;
448485 }
449486
450487 /**
@@ -913,9 +950,9 @@ export class EthImpl implements Eth {
913950 * @private
914951 */
915952 private async translateBlockTag ( tag : string | null , requestId ?: string ) : Promise < number > {
916- if ( tag === null || tag === 'latest' || tag === 'pending' ) {
953+ if ( tag === null || tag === EthImpl . blockLatest || tag === EthImpl . blockPending ) {
917954 return Number ( await this . blockNumber ( requestId ) ) ;
918- } else if ( tag === 'earliest' ) {
955+ } else if ( tag === EthImpl . blockEarliest ) {
919956 return 0 ;
920957 } else {
921958 return Number ( tag ) ;
@@ -932,25 +969,8 @@ export class EthImpl implements Eth {
932969 * @param blockHashOrNumber
933970 * @param showDetails
934971 */
935- private async getBlock ( blockHashOrNumber : string , showDetails : boolean , requestId ?: string ) : Promise < Block | null > {
936- let blockResponse : any ;
937- if ( blockHashOrNumber == null || blockHashOrNumber == 'latest' || blockHashOrNumber == 'pending' ) {
938- const blockPromise = this . mirrorNodeClient . getLatestBlock ( requestId ) ;
939- const blockAnswer = await blockPromise ;
940- blockResponse = blockAnswer . blocks [ 0 ] ;
941- } else if ( blockHashOrNumber == 'earliest' ) {
942- blockResponse = await this . mirrorNodeClient . getBlock ( 0 , requestId ) ;
943- } else if ( blockHashOrNumber . length < 32 ) {
944- // anything less than 32 characters is treated as a number
945- blockResponse = await this . mirrorNodeClient . getBlock ( Number ( blockHashOrNumber ) , requestId ) ;
946- } else {
947- blockResponse = await this . mirrorNodeClient . getBlock ( blockHashOrNumber , requestId ) ;
948- }
949-
950- if ( _ . isNil ( blockResponse ) || blockResponse . hash === undefined ) {
951- // block not found
952- return null ;
953- }
972+ private async getBlock ( blockHashOrNumber : string , showDetails : boolean , requestId ?: string ) : Promise < Block | null > {
973+ const blockResponse = await this . getHistoricalBlockResponse ( blockHashOrNumber , true ) ;
954974
955975 const timestampRange = blockResponse . timestamp ;
956976 const timestampRangeParams = [ `gte:${ timestampRange . from } ` , `lte:${ timestampRange . to } ` ] ;
@@ -1016,6 +1036,41 @@ export class EthImpl implements Eth {
10161036 } ) ;
10171037 }
10181038
1039+ /**
1040+ * returns the block response
1041+ * otherwise return undefined.
1042+ *
1043+ * @param blockNumberOrTag
1044+ * @param returnLatest
1045+ */
1046+ private async getHistoricalBlockResponse ( blockNumberOrTag ?: string | null , returnLatest ?: boolean ) : Promise < any | null > {
1047+ let blockResponse : any ;
1048+ // Determine if the latest block should be returned and if not then just return null
1049+ if ( ! returnLatest &&
1050+ ( blockNumberOrTag == null || blockNumberOrTag === EthImpl . blockLatest || blockNumberOrTag === EthImpl . blockPending ) ) {
1051+ return null ;
1052+ }
1053+
1054+ if ( blockNumberOrTag == null || blockNumberOrTag === EthImpl . blockLatest || blockNumberOrTag === EthImpl . blockPending ) {
1055+ const blockPromise = this . mirrorNodeClient . getLatestBlock ( ) ;
1056+ const blockAnswer = await blockPromise ;
1057+ blockResponse = blockAnswer . blocks [ 0 ] ;
1058+ } else if ( blockNumberOrTag == EthImpl . blockEarliest ) {
1059+ blockResponse = await this . mirrorNodeClient . getBlock ( 0 ) ;
1060+ } else if ( blockNumberOrTag . length < 32 ) {
1061+ // anything less than 32 characters is treated as a number
1062+ blockResponse = await this . mirrorNodeClient . getBlock ( Number ( blockNumberOrTag ) ) ;
1063+ } else {
1064+ blockResponse = await this . mirrorNodeClient . getBlock ( blockNumberOrTag ) ;
1065+ }
1066+ if ( _ . isNil ( blockResponse ) || blockResponse . hash === undefined ) {
1067+ // block not found.
1068+ throw predefined . RESOURCE_NOT_FOUND ;
1069+ }
1070+
1071+ return blockResponse ;
1072+ }
1073+
10191074 private static getTransactionCountFromBlockResponse ( block : any ) {
10201075 if ( block === null || block . count === undefined ) {
10211076 // block not found
0 commit comments