9
9
import com .algorand .algosdk .util .Digester ;
10
10
import com .algorand .algosdk .util .Encoder ;
11
11
import com .algorand .algosdk .v2 .client .Utils ;
12
+ import com .algorand .algosdk .v2 .client .common .AlgodClient ;
12
13
import com .algorand .algosdk .v2 .client .common .Response ;
13
14
import com .algorand .algosdk .v2 .client .model .*;
14
15
import io .cucumber .java .en .Given ;
@@ -290,23 +291,25 @@ private static void assertSetOfByteArraysEqual(Set<byte[]> expected, Set<byte[]>
290
291
291
292
@ Then ("according to {string}, the current application should have the following boxes {string}." )
292
293
public void checkAppBoxes (String fromClient , String encodedBoxesRaw ) throws Exception {
294
+ final Set <byte []> expectedNames = new HashSet <>();
295
+ if (!encodedBoxesRaw .isEmpty ()) {
296
+ for (String s : encodedBoxesRaw .split (":" )) {
297
+ expectedNames .add (Encoder .decodeFromBase64 (s ));
298
+ }
299
+ }
300
+
293
301
Response <BoxesResponse > r ;
294
- if (fromClient .equals ("algod" ))
302
+ if (fromClient .equals ("algod" )) {
303
+ advanceChainAndWaitForBoxes (base .aclv2 , this .appId , this .transientAccount ,
304
+ expectedNames .size ());
295
305
r = base .aclv2 .GetApplicationBoxes (this .appId ).execute ();
296
- else if (fromClient .equals ("indexer" ))
306
+ } else if (fromClient .equals ("indexer" ))
297
307
r = base .v2IndexerClient .searchForApplicationBoxes (this .appId ).execute ();
298
308
else
299
309
throw new IllegalArgumentException ("expecting algod or indexer, got " + fromClient );
300
310
301
311
Assert .assertTrue (r .isSuccessful ());
302
312
303
- final Set <byte []> expectedNames = new HashSet <>();
304
- if (!encodedBoxesRaw .isEmpty ()) {
305
- for (String s : encodedBoxesRaw .split (":" )) {
306
- expectedNames .add (Encoder .decodeFromBase64 (s ));
307
- }
308
- }
309
-
310
313
final Set <byte []> actualNames = new HashSet <>();
311
314
for (BoxDescriptor b : r .body ().boxes ) {
312
315
actualNames .add (b .name );
@@ -315,6 +318,69 @@ else if (fromClient.equals("indexer"))
315
318
assertSetOfByteArraysEqual (expectedNames , actualNames );
316
319
}
317
320
321
+ /**
322
+ * Advance the blockchain and wait for the expected number of application boxes to persist.
323
+ *
324
+ * @param algodClient Algod client for interacting with the blockchain.
325
+ * @param appId Application ID to check for boxes.
326
+ * @param sender Account sending dummy transactions.
327
+ * @param expectedNumBoxes The expected number of boxes.
328
+ * @throws Exception if the boxes do not persist within the specified attempts.
329
+ */
330
+ public static void advanceChainAndWaitForBoxes (
331
+ AlgodClient algodClient ,
332
+ long appId ,
333
+ TransientAccount sender ,
334
+ int expectedNumBoxes ) throws Exception {
335
+
336
+ int waitRounds = 5 ;
337
+ int maxAttempts = 50 ;
338
+ // Get the current round
339
+ long currentRound = algodClient .GetStatus ().execute ().body ().lastRound ;
340
+ long targetRound = currentRound + waitRounds ;
341
+
342
+ System .out .println ("Current round: " + currentRound + ", waiting for round: " + targetRound );
343
+
344
+ int attempts = 0 ;
345
+ while (attempts < maxAttempts ) {
346
+ // Send a dummy 0-Algo payment transaction to advance the blockchain
347
+ TransactionParametersResponse params = algodClient .TransactionParams ().execute ().body ();
348
+
349
+ Transaction txn = Transaction .PaymentTransactionBuilder ()
350
+ .sender (sender .transientAccount .getAddress ())
351
+ .amount (0 )
352
+ .receiver (sender .transientAccount .getAddress ())
353
+ .suggestedParams (params )
354
+ .noteUTF8 ("Advance round for box persistence" )
355
+ .build ();
356
+
357
+ SignedTransaction stxn = sender .transientAccount .signTransaction (txn );
358
+ String txId = algodClient .RawTransaction ().rawtxn (Encoder .encodeToMsgPack (stxn )).execute ().body ().txId ;
359
+
360
+ // Use Utils.waitForConfirmation to wait for the transaction to be confirmed
361
+ Utils .waitForConfirmation (algodClient , txId , waitRounds );
362
+ System .out .println ("Dummy transaction confirmed. TxID: " + txId );
363
+
364
+ // Check the number of boxes
365
+ Response <BoxesResponse > boxResponse = algodClient .GetApplicationBoxes (appId ).execute ();
366
+ List <BoxDescriptor > boxes = boxResponse .body ().boxes ;
367
+
368
+ int actualNumBoxes = boxes != null ? boxes .size () : 0 ;
369
+ System .out .println ("Actual number of boxes: " + actualNumBoxes + ", Expected: " + expectedNumBoxes );
370
+
371
+ if (actualNumBoxes == expectedNumBoxes ) {
372
+ System .out .println ("The expected number of boxes is now available." );
373
+ return ; // Exit once the condition is met
374
+ }
375
+
376
+ // Wait for a second before the next attempt
377
+ Thread .sleep (1000 );
378
+ attempts ++;
379
+ }
380
+
381
+ throw new Exception ("Timeout waiting for " + expectedNumBoxes + " boxes to persist for application " + appId );
382
+ }
383
+
318
384
@ Then ("according to {string}, with {long} being the parameter that limits results, the current application should have {int} boxes." )
319
385
public void checkAppBoxesNum (String fromClient , Long limit , int expected_num ) throws Exception {
320
386
Response <BoxesResponse > r ;
0 commit comments