@@ -26,6 +26,8 @@ import { Histogram, Registry } from 'prom-client';
2626import { formatRequestIdMessage } from '../../formatters' ;
2727import axiosRetry from 'axios-retry' ;
2828
29+ type REQUEST_METHODS = 'GET' | 'POST' ;
30+
2931export interface ILimitOrderParams {
3032 limit ?: number ;
3133 order ?: string ;
@@ -70,6 +72,7 @@ export class MirrorNodeClient {
7072 private static GET_NETWORK_FEES_ENDPOINT = 'network/fees' ;
7173 private static GET_TOKENS_ENDPOINT = 'tokens' ;
7274 private static GET_TRANSACTIONS_ENDPOINT = 'transactions' ;
75+ private static CONTRACT_CALL_ENDPOINT = 'contracts/call' ;
7376
7477 private static CONTRACT_RESULT_LOGS_PROPERTY = 'logs' ;
7578 private static CONTRACT_STATE_PROPERTY = 'state' ;
@@ -87,9 +90,11 @@ export class MirrorNodeClient {
8790 */
8891 private readonly logger : Logger ;
8992
90- private readonly client : AxiosInstance ;
93+ private readonly restClient : AxiosInstance ;
94+ private readonly web3Client : AxiosInstance ;
9195
92- public readonly baseUrl : string ;
96+ public readonly restUrl : string ;
97+ public readonly web3Url : string ;
9398
9499 /**
95100 * The metrics register used for metrics tracking.
@@ -130,23 +135,23 @@ export class MirrorNodeClient {
130135 return axiosClient ;
131136 }
132137
133- constructor ( baseUrl : string , logger : Logger , register : Registry , axiosClient ?: AxiosInstance ) {
134- if ( axiosClient !== undefined ) {
135- this . baseUrl = '' ;
136- this . client = axiosClient ;
137- } else {
138- if ( ! baseUrl . match ( / ^ h t t p s ? : \/ \/ / ) ) {
139- baseUrl = `https://${ baseUrl } ` ;
140- }
138+ constructor ( restUrl : string , logger : Logger , register : Registry , restClient ?: AxiosInstance , web3Url ?: string , web3Client ?: AxiosInstance ) {
139+ if ( ! web3Url ) {
140+ web3Url = restUrl ;
141+ }
141142
142- if ( ! baseUrl . match ( / \/ $ / ) ) {
143- baseUrl = ` ${ baseUrl } /` ;
144- }
143+ if ( restClient !== undefined ) {
144+ this . restUrl = '' ;
145+ this . web3Url = '' ;
145146
146- baseUrl = `${ baseUrl } api/v1/` ;
147+ this . restClient = restClient ;
148+ this . web3Client = ! ! web3Client ? web3Client : restClient ;
149+ } else {
150+ this . restUrl = this . buildUrl ( restUrl ) ;
151+ this . web3Url = this . buildUrl ( web3Url ) ;
147152
148- this . baseUrl = baseUrl ;
149- this . client = axiosClient ? axiosClient : this . createAxiosClient ( baseUrl ) ;
153+ this . restClient = restClient ? restClient : this . createAxiosClient ( this . restUrl ) ;
154+ this . web3Client = web3Client ? web3Client : this . createAxiosClient ( this . web3Url ) ;
150155 }
151156
152157 this . logger = logger ;
@@ -162,47 +167,77 @@ export class MirrorNodeClient {
162167 registers : [ register ]
163168 } ) ;
164169
165- this . logger . info ( `Mirror Node client successfully configured to ${ this . baseUrl } ` ) ;
170+ this . logger . info ( `Mirror Node client successfully configured to REST url: ${ this . restUrl } and Web3 url: ${ this . web3Url } ` ) ;
166171 }
172+
173+ private buildUrl ( baseUrl : string ) {
174+ if ( ! baseUrl . match ( / ^ h t t p s ? : \/ \/ / ) ) {
175+ baseUrl = `https://${ baseUrl } ` ;
176+ }
167177
168- async request ( path : string , pathLabel : string , allowedErrorStatuses ?: number [ ] , requestId ?: string ) : Promise < any > {
178+ if ( ! baseUrl . match ( / \/ $ / ) ) {
179+ baseUrl = `${ baseUrl } /` ;
180+ }
181+
182+ return `${ baseUrl } api/v1/` ;
183+ }
184+
185+ private async request ( path : string , pathLabel : string , method : REQUEST_METHODS , data ?: any , allowedErrorStatuses ?: number [ ] , requestId ?: string ) : Promise < any > {
169186 const start = Date . now ( ) ;
170187 const requestIdPrefix = formatRequestIdMessage ( requestId ) ;
171188 let ms ;
172189 try {
173- const response = await this . client . get ( path , {
190+ let response ;
191+ const headers = {
174192 headers :{
175193 'requestId' : requestId || ''
176194 }
177- } ) ;
178- ms = Date . now ( ) - start ;
179- this . logger . debug ( `${ requestIdPrefix } [GET] ${ path } ${ response . status } ${ ms } ms` ) ;
195+ } ;
196+
197+ if ( method === 'GET' ) {
198+ response = await this . restClient . get ( path , headers ) ;
199+ }
200+ else {
201+ response = await this . web3Client . post ( path , data , headers ) ;
202+ }
203+
204+ const ms = Date . now ( ) - start ;
205+ this . logger . debug ( `${ requestIdPrefix } [${ method } ] ${ path } ${ response . status } ${ ms } ms` ) ;
180206 this . mirrorResponseHistogram . labels ( pathLabel , response . status ) . observe ( ms ) ;
181207 return response . data ;
182208 } catch ( error : any ) {
183209 ms = Date . now ( ) - start ;
184210 const effectiveStatusCode = error . response ?. status || MirrorNodeClientError . ErrorCodes [ error . code ] || MirrorNodeClient . unknownServerErrorHttpStatusCode ;
185211 this . mirrorResponseHistogram . labels ( pathLabel , effectiveStatusCode ) . observe ( ms ) ;
186- this . handleError ( error , path , effectiveStatusCode , allowedErrorStatuses , requestId ) ;
212+ this . handleError ( error , path , effectiveStatusCode , method , allowedErrorStatuses , requestId ) ;
187213 }
188214 return null ;
189215 }
190216
191- handleError ( error : any , path : string , effectiveStatusCode : number , allowedErrorStatuses ?: number [ ] , requestId ?: string ) {
217+ async get ( path : string , pathLabel : string , allowedErrorStatuses ?: number [ ] , requestId ?: string ) : Promise < any > {
218+ return this . request ( path , pathLabel , 'GET' , null , allowedErrorStatuses , requestId ) ;
219+ }
220+
221+ async post ( path : string , data : any , pathLabel : string , allowedErrorStatuses ?: number [ ] , requestId ?: string ) : Promise < any > {
222+ if ( ! data ) data = { } ;
223+ return this . request ( path , pathLabel , 'POST' , data , allowedErrorStatuses , requestId ) ;
224+ }
225+
226+ handleError ( error : any , path : string , effectiveStatusCode : number , method : REQUEST_METHODS , allowedErrorStatuses ?: number [ ] , requestId ?: string ) {
192227 const requestIdPrefix = formatRequestIdMessage ( requestId ) ;
193228 if ( allowedErrorStatuses && allowedErrorStatuses . length ) {
194229 if ( error . response && allowedErrorStatuses . indexOf ( effectiveStatusCode ) !== - 1 ) {
195- this . logger . debug ( `${ requestIdPrefix } [GET ] ${ path } ${ effectiveStatusCode } status` ) ;
230+ this . logger . debug ( `${ requestIdPrefix } [${ method } ] ${ path } ${ effectiveStatusCode } status` ) ;
196231 return null ;
197232 }
198233 }
199234
200- this . logger . error ( new Error ( error . message ) , `${ requestIdPrefix } [GET ] ${ path } ${ effectiveStatusCode } status` ) ;
235+ this . logger . error ( new Error ( error . message ) , `${ requestIdPrefix } [${ method } ] ${ path } ${ effectiveStatusCode } status` ) ;
201236 throw new MirrorNodeClientError ( error . message , effectiveStatusCode ) ;
202237 }
203238
204239 async getPaginatedResults ( url : string , pathLabel : string , resultProperty : string , allowedErrorStatuses ?: number [ ] , requestId ?: string , results = [ ] , page = 1 ) {
205- const result = await this . request ( url , pathLabel , allowedErrorStatuses , requestId ) ;
240+ const result = await this . get ( url , pathLabel , allowedErrorStatuses , requestId ) ;
206241
207242 if ( result && result [ resultProperty ] ) {
208243 results = results . concat ( result [ resultProperty ] ) ;
@@ -219,14 +254,14 @@ export class MirrorNodeClient {
219254 }
220255
221256 public async getAccountLatestTransactionByAddress ( idOrAliasOrEvmAddress : string , requestId ?: string ) : Promise < object > {
222- return this . request ( `${ MirrorNodeClient . GET_ACCOUNTS_ENDPOINT } ${ idOrAliasOrEvmAddress } ?order=desc&limit=1` ,
257+ return this . get ( `${ MirrorNodeClient . GET_ACCOUNTS_ENDPOINT } ${ idOrAliasOrEvmAddress } ?order=desc&limit=1` ,
223258 MirrorNodeClient . GET_ACCOUNTS_ENDPOINT ,
224259 [ 400 ] ,
225260 requestId ) ;
226261 }
227262
228263 public async getAccount ( idOrAliasOrEvmAddress : string , requestId ?: string ) {
229- return this . request ( `${ MirrorNodeClient . GET_ACCOUNTS_ENDPOINT } ${ idOrAliasOrEvmAddress } ` ,
264+ return this . get ( `${ MirrorNodeClient . GET_ACCOUNTS_ENDPOINT } ${ idOrAliasOrEvmAddress } ` ,
230265 MirrorNodeClient . GET_ACCOUNTS_ENDPOINT ,
231266 [ 400 , 404 ] ,
232267 requestId ) ;
@@ -253,14 +288,14 @@ export class MirrorNodeClient {
253288 this . setQueryParam ( queryParamObject , 'account.id' , accountId ) ;
254289 this . setQueryParam ( queryParamObject , 'timestamp' , timestamp ) ;
255290 const queryParams = this . getQueryParams ( queryParamObject ) ;
256- return this . request ( `${ MirrorNodeClient . GET_BALANCE_ENDPOINT } ${ queryParams } ` ,
291+ return this . get ( `${ MirrorNodeClient . GET_BALANCE_ENDPOINT } ${ queryParams } ` ,
257292 MirrorNodeClient . GET_BALANCE_ENDPOINT ,
258293 [ 400 , 404 ] ,
259294 requestId ) ;
260295 }
261296
262297 public async getBlock ( hashOrBlockNumber : string | number , requestId ?: string ) {
263- return this . request ( `${ MirrorNodeClient . GET_BLOCK_ENDPOINT } ${ hashOrBlockNumber } ` ,
298+ return this . get ( `${ MirrorNodeClient . GET_BLOCK_ENDPOINT } ${ hashOrBlockNumber } ` ,
264299 MirrorNodeClient . GET_BLOCK_ENDPOINT ,
265300 [ 400 , 404 ] ,
266301 requestId ) ;
@@ -272,21 +307,21 @@ export class MirrorNodeClient {
272307 this . setQueryParam ( queryParamObject , 'timestamp' , timestamp ) ;
273308 this . setLimitOrderParams ( queryParamObject , limitOrderParams ) ;
274309 const queryParams = this . getQueryParams ( queryParamObject ) ;
275- return this . request ( `${ MirrorNodeClient . GET_BLOCKS_ENDPOINT } ${ queryParams } ` ,
310+ return this . get ( `${ MirrorNodeClient . GET_BLOCKS_ENDPOINT } ${ queryParams } ` ,
276311 MirrorNodeClient . GET_BLOCKS_ENDPOINT ,
277312 [ 400 , 404 ] ,
278313 requestId ) ;
279314 }
280315
281316 public async getContract ( contractIdOrAddress : string , requestId ?: string ) {
282- return this . request ( `${ MirrorNodeClient . GET_CONTRACT_ENDPOINT } ${ contractIdOrAddress } ` ,
317+ return this . get ( `${ MirrorNodeClient . GET_CONTRACT_ENDPOINT } ${ contractIdOrAddress } ` ,
283318 MirrorNodeClient . GET_CONTRACT_ENDPOINT ,
284319 [ 400 , 404 ] ,
285320 requestId ) ;
286321 }
287322
288323 public async getContractResult ( transactionIdOrHash : string , requestId ?: string ) {
289- return this . request ( `${ MirrorNodeClient . GET_CONTRACT_RESULT_ENDPOINT } ${ transactionIdOrHash } ` ,
324+ return this . get ( `${ MirrorNodeClient . GET_CONTRACT_RESULT_ENDPOINT } ${ transactionIdOrHash } ` ,
290325 MirrorNodeClient . GET_CONTRACT_RESULT_ENDPOINT ,
291326 [ 400 , 404 ] ,
292327 requestId ) ;
@@ -297,14 +332,14 @@ export class MirrorNodeClient {
297332 this . setContractResultsParams ( queryParamObject , contractResultsParams ) ;
298333 this . setLimitOrderParams ( queryParamObject , limitOrderParams ) ;
299334 const queryParams = this . getQueryParams ( queryParamObject ) ;
300- return this . request ( `${ MirrorNodeClient . GET_CONTRACT_RESULTS_ENDPOINT } ${ queryParams } ` ,
335+ return this . get ( `${ MirrorNodeClient . GET_CONTRACT_RESULTS_ENDPOINT } ${ queryParams } ` ,
301336 MirrorNodeClient . GET_CONTRACT_RESULTS_ENDPOINT ,
302337 [ 400 , 404 ] ,
303338 requestId ) ;
304339 }
305340
306341 public async getContractResultsDetails ( contractId : string , timestamp : string , requestId ?: string ) {
307- return this . request ( `${ this . getContractResultsDetailsByContractIdAndTimestamp ( contractId , timestamp ) } ` ,
342+ return this . get ( `${ this . getContractResultsDetailsByContractIdAndTimestamp ( contractId , timestamp ) } ` ,
308343 MirrorNodeClient . GET_CONTRACT_RESULTS_DETAILS_BY_CONTRACT_ID_ENDPOINT ,
309344 [ 400 , 404 ] ,
310345 requestId ) ;
@@ -319,14 +354,14 @@ export class MirrorNodeClient {
319354 this . setContractResultsParams ( queryParamObject , contractResultsParams ) ;
320355 this . setLimitOrderParams ( queryParamObject , limitOrderParams ) ;
321356 const queryParams = this . getQueryParams ( queryParamObject ) ;
322- return this . request ( `${ MirrorNodeClient . getContractResultsByAddressPath ( contractIdOrAddress ) } ${ queryParams } ` ,
357+ return this . get ( `${ MirrorNodeClient . getContractResultsByAddressPath ( contractIdOrAddress ) } ${ queryParams } ` ,
323358 MirrorNodeClient . GET_CONTRACT_RESULTS_BY_ADDRESS_ENDPOINT ,
324359 [ 400 ] ,
325360 requestId ) ;
326361 }
327362
328363 public async getContractResultsByAddressAndTimestamp ( contractIdOrAddress : string , timestamp : string , requestId ?: string ) {
329- return this . request ( `${ MirrorNodeClient . getContractResultsByAddressPath ( contractIdOrAddress ) } /${ timestamp } ` ,
364+ return this . get ( `${ MirrorNodeClient . getContractResultsByAddressPath ( contractIdOrAddress ) } /${ timestamp } ` ,
330365 MirrorNodeClient . GET_CONTRACT_RESULTS_BY_ADDRESS_ENDPOINT ,
331366 [ 206 , 400 , 404 ] ,
332367 requestId ) ;
@@ -398,7 +433,7 @@ export class MirrorNodeClient {
398433 const queryParamObject = { } ;
399434 this . setQueryParam ( queryParamObject , 'timestamp' , timestamp ) ;
400435 const queryParams = this . getQueryParams ( queryParamObject ) ;
401- return this . request ( `${ MirrorNodeClient . GET_NETWORK_EXCHANGERATE_ENDPOINT } ${ queryParams } ` ,
436+ return this . get ( `${ MirrorNodeClient . GET_NETWORK_EXCHANGERATE_ENDPOINT } ${ queryParams } ` ,
402437 MirrorNodeClient . GET_NETWORK_EXCHANGERATE_ENDPOINT ,
403438 [ 400 , 404 ] ,
404439 requestId ) ;
@@ -409,7 +444,7 @@ export class MirrorNodeClient {
409444 this . setQueryParam ( queryParamObject , 'timestamp' , timestamp ) ;
410445 this . setQueryParam ( queryParamObject , 'order' , order ) ;
411446 const queryParams = this . getQueryParams ( queryParamObject ) ;
412- return this . request ( `${ MirrorNodeClient . GET_NETWORK_FEES_ENDPOINT } ${ queryParams } ` ,
447+ return this . get ( `${ MirrorNodeClient . GET_NETWORK_FEES_ENDPOINT } ${ queryParams } ` ,
413448 MirrorNodeClient . GET_NETWORK_FEES_ENDPOINT ,
414449 [ 400 , 404 ] ,
415450 requestId ) ;
@@ -426,7 +461,7 @@ export class MirrorNodeClient {
426461 }
427462
428463 public async getTokenById ( tokenId : string , requestId ?: string ) {
429- return this . request ( `${ MirrorNodeClient . GET_TOKENS_ENDPOINT } /${ tokenId } ` ,
464+ return this . get ( `${ MirrorNodeClient . GET_TOKENS_ENDPOINT } /${ tokenId } ` ,
430465 MirrorNodeClient . GET_TOKENS_ENDPOINT ,
431466 [ 400 , 404 ] ,
432467 requestId ) ;
@@ -449,12 +484,16 @@ export class MirrorNodeClient {
449484 this . setLimitOrderParams ( queryParamObject , limitOrderParams ) ;
450485 const queryParams = this . getQueryParams ( queryParamObject ) ;
451486
452- return this . request ( `${ MirrorNodeClient . GET_CONTRACT_ENDPOINT } ${ address } ${ MirrorNodeClient . GET_STATE_ENDPOINT } ${ queryParams } ` ,
487+ return this . get ( `${ MirrorNodeClient . GET_CONTRACT_ENDPOINT } ${ address } ${ MirrorNodeClient . GET_STATE_ENDPOINT } ${ queryParams } ` ,
453488 MirrorNodeClient . GET_STATE_ENDPOINT ,
454489 [ 400 , 404 ] ,
455490 requestId ) ;
456491 }
457492
493+ public async postContractCall ( callData : string , requestId ?: string ) {
494+ return this . post ( MirrorNodeClient . CONTRACT_CALL_ENDPOINT , callData , MirrorNodeClient . CONTRACT_CALL_ENDPOINT , [ 400 ] , requestId ) ;
495+ }
496+
458497 getQueryParams ( params : object ) {
459498 let paramString = '' ;
460499 for ( const [ key , value ] of Object . entries ( params ) ) {
@@ -557,7 +596,11 @@ export class MirrorNodeClient {
557596 }
558597
559598 //exposing mirror node instance for tests
560- public getMirrorNodeInstance ( ) {
561- return this . client ;
599+ public getMirrorNodeRestInstance ( ) {
600+ return this . restClient ;
601+ }
602+
603+ public getMirrorNodeWeb3Instance ( ) {
604+ return this . web3Client ;
562605 }
563606}
0 commit comments