@@ -4,33 +4,74 @@ import retry from 'async-retry';
44import { formatTransactionId , getNetworkEnv } from './util.js' ;
55import { AccountInfo , AccountsResponse } from '../../front-end/src/shared/interfaces/index.js' ;
66
7- const getBaseURL = ( ) => {
8- const network = getNetworkEnv ( ) . toUpperCase ( ) ;
9- switch ( network ) {
10- case 'TESTNET' :
11- return 'https://testnet.mirrornode.hedera.com/api/v1' ;
12- case 'PREVIEWNET' :
13- return 'https://previewnet.mirrornode.hedera.com/api/v1' ;
14- case 'LOCALNET' :
15- default :
16- return 'http://localhost:8081/api/v1' ;
17- }
18- } ;
19-
20- const apiCall = async ( endpoint : string , params : Object ) => {
21- const baseURL = getBaseURL ( ) ;
22- const fullURL = `${ baseURL } /${ endpoint } ` ;
23- console . log ( `Executing API Call: ${ fullURL } with params:` , params ) ;
24- try {
25- const response = await axios . get ( fullURL , { params } ) ;
26- console . log ( `API Call successful: ${ fullURL } ` ) ;
27- return response . data ;
28- } catch ( error : unknown ) {
29- throw new Error (
30- error instanceof Error ? `API call failed: ${ error . message } ` : 'API call failed' ,
31- ) ;
32- }
33- } ;
7+ const getBaseURL = ( ) => {
8+ const network = getNetworkEnv ( ) . toUpperCase ( ) ;
9+ switch ( network ) {
10+ case 'TESTNET' :
11+ return 'https://testnet.mirrornode.hedera.com/api/v1' ;
12+ case 'PREVIEWNET' :
13+ return 'https://previewnet.mirrornode.hedera.com/api/v1' ;
14+ case 'LOCALNET' :
15+ default :
16+ return 'http://localhost:8081/api/v1' ;
17+ }
18+ } ;
19+
20+ const apiCall = async ( endpoint : string , params : Object ) => {
21+ const baseURL = getBaseURL ( ) ;
22+ const fullURL = `${ baseURL } /${ endpoint } ` ;
23+ console . log ( `Executing API Call: ${ fullURL } with params:` , params ) ;
24+ try {
25+ const response = await axios . get ( fullURL , { params } ) ;
26+ console . log ( `API Call successful: ${ fullURL } ` ) ;
27+ return response . data ;
28+ } catch ( error : unknown ) {
29+ throw new Error (
30+ error instanceof Error ? `API call failed: ${ error . message } ` : 'API call failed' ,
31+ ) ;
32+ }
33+ } ;
34+
35+ const summarizeTransactions = ( response : any ) => {
36+ return ( response ?. transactions ?? [ ] ) . map ( ( transaction : any ) => ( {
37+ transaction_id : transaction . transaction_id ,
38+ consensus_timestamp : transaction . consensus_timestamp ,
39+ name : transaction . name ,
40+ result : transaction . result ,
41+ } ) ) ;
42+ } ;
43+
44+ const logRecentTransactionsForDebug = async ( payerAccountId : string ) => {
45+ try {
46+ const allTransactions = await apiCall ( 'transactions' , { limit : 10 , order : 'desc' } ) ;
47+ console . log (
48+ '[mirror-node-debug] Recent transactions from /transactions:' ,
49+ summarizeTransactions ( allTransactions ) ,
50+ ) ;
51+ } catch ( listError ) {
52+ console . log (
53+ '[mirror-node-debug] Failed to fetch recent transactions from /transactions:' ,
54+ listError instanceof Error ? listError . message : listError ,
55+ ) ;
56+ }
57+
58+ try {
59+ const payerTransactions = await apiCall ( 'transactions' , {
60+ 'account.id' : payerAccountId ,
61+ limit : 10 ,
62+ order : 'desc' ,
63+ } ) ;
64+ console . log (
65+ `[mirror-node-debug] Recent transactions from /transactions for payer ${ payerAccountId } :` ,
66+ summarizeTransactions ( payerTransactions ) ,
67+ ) ;
68+ } catch ( listError ) {
69+ console . log (
70+ `[mirror-node-debug] Failed to fetch payer transactions from /transactions for ${ payerAccountId } :` ,
71+ listError instanceof Error ? listError . message : listError ,
72+ ) ;
73+ }
74+ } ;
3475
3576/**
3677 * Performs a polling with retry mechanism on the mirror node API endpoint until a condition is met.
@@ -44,8 +85,8 @@ import { AccountInfo, AccountsResponse } from '../../front-end/src/shared/interf
4485 * @param {Object } params - The parameters to pass with the API call, usually query parameters.
4586 * @param {Function } validateResult - A function to validate the result of the API call.
4687 * Should return `true` if the result meets the expected conditions, `false` otherwise.
47- * @param {number } [timeout=15000 ] - The maximum time in milliseconds to keep retrying the API call.
48- * @param {number } [interval=2500 ] - The interval in milliseconds between retries.
88+ * @param {number } [timeout=30000 ] - The maximum time in milliseconds to keep retrying the API call.
89+ * @param {number } [interval=2000 ] - The interval in milliseconds between retries.
4990 * @returns {Promise<Object> } - A promise that resolves with the data from the API once the validation condition is met.
5091 * If the timeout is reached without successful validation, the promise rejects.
5192 *
@@ -56,52 +97,79 @@ import { AccountInfo, AccountsResponse } from '../../front-end/src/shared/interf
5697 * .catch(error => console.error('Failed to fetch account details:', error));
5798 * ```
5899 */
59- const pollWithRetry = async (
60- endpoint : string ,
61- params : Object ,
62- validateResult : ( result : any ) => boolean ,
63- timeout : number = 20000 ,
64- interval : number = 2500 ,
65- ) : Promise < any > => {
66- return retry (
67- async ( ) => {
68- console . log ( `Fetching data from ${ endpoint } ` ) ;
69- const result = await apiCall ( endpoint , params ) ;
70- if ( validateResult ( result ) ) {
71- console . log ( `Validation successful for data from ${ endpoint } ` ) ;
72- return result ;
73- }
74- throw new Error ( 'Data not ready or condition not met' ) ;
75- } ,
76- {
77- retries : Math . floor ( timeout / interval ) ,
78- minTimeout : interval ,
79- maxTimeout : interval ,
80- onRetry : ( error : any ) => {
81- console . log ( `Retrying due to: ${ error . message } ` ) ;
82- } ,
83- } ,
84- ) ;
85- } ;
86-
87- export const getAccountDetails = async ( accountId : string ) => {
100+ const pollWithRetry = async (
101+ endpoint : string ,
102+ params : Object ,
103+ validateResult : ( result : any ) => boolean ,
104+ timeout : number = 30000 ,
105+ interval : number = 2000 ,
106+ ) : Promise < any > => {
107+ return retry (
108+ async ( ) => {
109+ console . log ( `Fetching data from ${ endpoint } ` ) ;
110+ const result = await apiCall ( endpoint , params ) ;
111+ if ( validateResult ( result ) ) {
112+ console . log ( `Validation successful for data from ${ endpoint } ` ) ;
113+ return result ;
114+ }
115+ throw new Error ( 'Data not ready or condition not met' ) ;
116+ } ,
117+ {
118+ retries : Math . floor ( timeout / interval ) ,
119+ minTimeout : interval ,
120+ maxTimeout : interval ,
121+ onRetry : ( error : any ) => {
122+ console . log ( `Retrying due to: ${ error . message } ` ) ;
123+ } ,
124+ } ,
125+ ) ;
126+ } ;
127+
128+ export const getAccountDetails = async (
129+ accountId : string ,
130+ timeout : number = 180000 ,
131+ interval : number = 3000 ,
132+ ) => {
88133 return pollWithRetry (
89134 'accounts' ,
90135 { 'account.id' : accountId } ,
91136 result => result && result . accounts && result . accounts . length > 0 ,
137+ timeout ,
138+ interval ,
92139 ) ;
93140} ;
94141
95- export const getTransactionDetails = async ( transactionId : string ) => {
142+ export const getTransactionDetails = async (
143+ transactionId : string ,
144+ timeout : number = 180000 ,
145+ interval : number = 3000 ,
146+ ) => {
96147 const formatedTransactionId = formatTransactionId ( transactionId ) ;
97- return pollWithRetry (
98- `transactions/${ formatedTransactionId } ` ,
99- { } ,
100- result => result && result . transactions && result . transactions . length > 0 ,
101- ) ;
148+ const payerAccountId = transactionId . split ( '@' ) [ 0 ] ;
149+
150+ try {
151+ return await pollWithRetry (
152+ `transactions/${ formatedTransactionId } ` ,
153+ { } ,
154+ result => result && result . transactions && result . transactions . length > 0 ,
155+ timeout ,
156+ interval ,
157+ ) ;
158+ } catch ( error ) {
159+ console . log (
160+ `[mirror-node-debug] Exact transaction lookup failed for ${ formatedTransactionId } . Fetching transaction lists for comparison.` ,
161+ ) ;
162+ await logRecentTransactionsForDebug ( payerAccountId ) ;
163+
164+ throw error ;
165+ }
102166} ;
103167
104- export const getAssociatedAccounts = async ( publicKey : string ) => {
168+ export const getAssociatedAccounts = async (
169+ publicKey : string ,
170+ timeout : number = 90000 ,
171+ interval : number = 3000 ,
172+ ) => {
105173 let allAccounts : string [ ] = [ ] ;
106174 let params : Object | null = { 'account.publickey' : publicKey , order : 'asc' } ;
107175 let endpoint = 'accounts' ;
@@ -112,6 +180,8 @@ export const getAssociatedAccounts = async (publicKey: string) => {
112180 endpoint ,
113181 params ,
114182 result => result && result . accounts && result . accounts . length > 0 ,
183+ timeout ,
184+ interval ,
115185 ) ;
116186
117187 // Extract the account IDs from the response
0 commit comments