@@ -100,6 +100,61 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
100
100
);
101
101
}
102
102
103
+ // This method divides messages into a couple of batches and creates
104
+ // twap updateData for them. It returns the updateData and the updateFee
105
+ function createBatchedTwapUpdateDataFromMessagesWithConfig (
106
+ PriceFeedMessage[] memory messages ,
107
+ MerkleUpdateConfig memory config
108
+ ) public returns (bytes [][] memory updateData , uint updateFee ) {
109
+ require (messages.length >= 2 , "At least 2 messages required for TWAP " );
110
+
111
+ // Select first two messages for TWAP calculation
112
+ PriceFeedMessage[] memory startMessages = new PriceFeedMessage [](1 );
113
+ startMessages[0 ] = messages[0 ];
114
+
115
+ PriceFeedMessage[] memory endMessages = new PriceFeedMessage [](1 );
116
+ endMessages[0 ] = messages[1 ];
117
+
118
+ // Generate the update data for start and end
119
+ bytes [] memory startUpdateData = new bytes [](1 );
120
+ startUpdateData[0 ] = generateWhMerkleUpdateWithSource (
121
+ startMessages,
122
+ config
123
+ );
124
+
125
+ bytes [] memory endUpdateData = new bytes [](1 );
126
+ endUpdateData[0 ] = generateWhMerkleUpdateWithSource (
127
+ endMessages,
128
+ config
129
+ );
130
+
131
+ // Create the updateData array with exactly 2 elements as required by parseTwapPriceFeedUpdates
132
+ updateData = new bytes [][](2 );
133
+ updateData[0 ] = startUpdateData;
134
+ updateData[1 ] = endUpdateData;
135
+
136
+ // Calculate the update fee
137
+ updateFee = pyth.getUpdateFee (updateData[0 ]);
138
+ }
139
+
140
+ function createBatchedTwapUpdateDataFromMessages (
141
+ PriceFeedMessage[] memory messages
142
+ ) internal returns (bytes [][] memory updateData , uint updateFee ) {
143
+ (
144
+ updateData,
145
+ updateFee
146
+ ) = createBatchedTwapUpdateDataFromMessagesWithConfig (
147
+ messages,
148
+ MerkleUpdateConfig (
149
+ MERKLE_TREE_DEPTH,
150
+ NUM_GUARDIAN_SIGNERS,
151
+ SOURCE_EMITTER_CHAIN_ID,
152
+ SOURCE_EMITTER_ADDRESS,
153
+ false
154
+ )
155
+ );
156
+ }
157
+
103
158
/// Testing parsePriceFeedUpdates method.
104
159
function testParsePriceFeedUpdatesWorks (uint seed ) public {
105
160
setRandSeed (seed);
@@ -309,4 +364,63 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
309
364
MAX_UINT64
310
365
);
311
366
}
367
+
368
+ function testParseTwapPriceFeedUpdates () public {
369
+ // Define a single price ID we'll use for the test
370
+ uint numMessages = 1 ;
371
+ bytes32 [] memory priceIds = new bytes32 [](numMessages);
372
+ priceIds[0 ] = bytes32 (uint256 (1 ));
373
+
374
+ // Create two PriceFeedMessage instances for the start and end points
375
+ PriceFeedMessage[] memory messages = new PriceFeedMessage [](2 );
376
+
377
+ // Start message
378
+ messages[0 ].priceId = priceIds[0 ];
379
+ messages[0 ].price = 100 ;
380
+ messages[0 ].conf = 10 ;
381
+ messages[0 ].expo = - 8 ;
382
+ messages[0 ].publishTime = 1000 ;
383
+ messages[0 ].prevPublishTime = 900 ;
384
+ messages[0 ].emaPrice = 100 ;
385
+ messages[0 ].emaConf = 10 ;
386
+
387
+ // End message
388
+ messages[1 ].priceId = priceIds[0 ];
389
+ messages[1 ].price = 110 ;
390
+ messages[1 ].conf = 8 ;
391
+ messages[1 ].expo = - 8 ;
392
+ messages[1 ].publishTime = 1100 ;
393
+ messages[1 ].prevPublishTime = 1000 ;
394
+ messages[1 ].emaPrice = 110 ;
395
+ messages[1 ].emaConf = 8 ;
396
+
397
+ // Create update data for TWAP calculation
398
+ (
399
+ bytes [][] memory updateData ,
400
+ uint updateFee
401
+ ) = createBatchedTwapUpdateDataFromMessages (messages);
402
+
403
+ // log the updateData
404
+ console.logBytes (updateData[0 ][0 ]);
405
+ console.logBytes (updateData[1 ][0 ]);
406
+
407
+ // Parse the TWAP updates
408
+ PythStructs.TwapPriceFeed[] memory twapPriceFeeds = pyth
409
+ .parseTwapPriceFeedUpdates {value: updateFee}(updateData, priceIds);
410
+
411
+ // Validate basic properties
412
+ assertEq (twapPriceFeeds[0 ].id, priceIds[0 ]);
413
+ assertEq (twapPriceFeeds[0 ].startTime, uint64 (1000 )); // publishTime start
414
+ assertEq (twapPriceFeeds[0 ].endTime, uint64 (1100 )); // publishTime end
415
+ assertEq (twapPriceFeeds[0 ].twap.expo, int32 (- 8 )); // expo
416
+
417
+ // The TWAP price should be the difference in cumulative price divided by the slot difference
418
+ assertEq (twapPriceFeeds[0 ].twap.price, int64 (105 ));
419
+
420
+ // The TWAP conf should be the difference in cumulative conf divided by the slot difference
421
+ assertEq (twapPriceFeeds[0 ].twap.conf, uint64 (9 ));
422
+
423
+ // Validate the downSlotsRatio is 0 in our test implementation
424
+ assertEq (twapPriceFeeds[0 ].downSlotsRatio, uint32 (0 ));
425
+ }
312
426
}
0 commit comments