Skip to content

Commit c2a48b5

Browse files
committed
test(integration-tests): add rav v2 test support
1 parent 35a27c0 commit c2a48b5

File tree

4 files changed

+238
-2
lines changed

4 files changed

+238
-2
lines changed

integration-tests/src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use anyhow::Result;
1111
use clap::Parser;
1212
use load_test::receipt_handler_load_test;
1313
use metrics::MetricsChecker;
14-
pub(crate) use rav_tests::{test_invalid_chain_id, test_tap_rav_v1};
14+
pub(crate) use rav_tests::{test_invalid_chain_id, test_tap_rav_v1, test_tap_rav_v2};
1515

1616
/// Main CLI parser structure
1717
#[derive(Parser, Debug)]
@@ -24,6 +24,7 @@ struct Cli {
2424
#[derive(clap::Subcommand, Debug)]
2525
enum Commands {
2626
Rav1,
27+
Rav2,
2728

2829
#[clap(name = "load")]
2930
LoadService {
@@ -43,6 +44,10 @@ async fn main() -> Result<()> {
4344
test_invalid_chain_id().await?;
4445
test_tap_rav_v1().await?;
4546
}
47+
// cargo run -- rav2
48+
Commands::Rav2 => {
49+
test_tap_rav_v2().await?;
50+
}
4651
// cargo run -- load --num-receipts 1000
4752
Commands::LoadService { num_receipts } => {
4853
let concurrency = num_cpus::get();

integration-tests/src/rav_tests.rs

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::{
1313
ACCOUNT0_SECRET, CHAIN_ID, GATEWAY_API_KEY, GATEWAY_URL, GRAPH_URL, INDEXER_URL,
1414
MAX_RECEIPT_VALUE, SUBGRAPH_ID, TAP_AGENT_METRICS_URL, TAP_VERIFIER_CONTRACT,
1515
},
16-
utils::{create_request, create_tap_receipt, find_allocation},
16+
utils::{create_request, create_tap_receipt, create_tap_receipt_v2, find_allocation},
1717
MetricsChecker,
1818
};
1919

@@ -211,3 +211,186 @@ pub async fn test_invalid_chain_id() -> Result<()> {
211211

212212
Ok(())
213213
}
214+
215+
// Function to test the TAP RAV generation with V2 receipts
216+
pub async fn test_tap_rav_v2() -> Result<()> {
217+
// Setup HTTP client
218+
let http_client = Arc::new(Client::new());
219+
let wallet: PrivateKeySigner = ACCOUNT0_SECRET.parse().unwrap();
220+
221+
// Query the network subgraph to find active allocations
222+
let allocation_id = find_allocation(http_client.clone(), GRAPH_URL).await?;
223+
let allocation_id = Address::from_str(&allocation_id)?;
224+
225+
// For V2, we need payer and service provider addresses
226+
let payer = wallet.address();
227+
let service_provider = allocation_id; // Using allocation_id as service provider for simplicity
228+
229+
// Create a metrics checker
230+
let metrics_checker =
231+
MetricsChecker::new(http_client.clone(), TAP_AGENT_METRICS_URL.to_string());
232+
233+
// First check initial metrics
234+
let initial_metrics = metrics_checker.get_current_metrics().await?;
235+
let initial_ravs_created =
236+
initial_metrics.ravs_created_by_allocation(&allocation_id.to_string());
237+
let initial_unaggregated =
238+
initial_metrics.unaggregated_fees_by_allocation(&allocation_id.to_string());
239+
240+
println!(
241+
"\n=== V2 Initial metrics: RAVs created: {}, Unaggregated fees: {} ===",
242+
initial_ravs_created, initial_unaggregated
243+
);
244+
245+
println!("\n=== V2 STAGE 1: Sending large receipt batches with small pauses ===");
246+
247+
// Send multiple V2 receipts in two batches with a gap between them
248+
let mut total_successful = 0;
249+
250+
for batch in 0..BATCHES {
251+
println!(
252+
"Sending V2 batch {} of 2 with {} receipts each...",
253+
batch + 1,
254+
NUM_RECEIPTS
255+
);
256+
257+
for i in 0..NUM_RECEIPTS {
258+
// Create V2 receipt
259+
let receipt = create_tap_receipt_v2(
260+
MAX_RECEIPT_VALUE,
261+
&allocation_id,
262+
TAP_VERIFIER_CONTRACT,
263+
CHAIN_ID,
264+
&wallet,
265+
&payer,
266+
&service_provider,
267+
)?;
268+
269+
let receipt_json = serde_json::to_string(&receipt)?;
270+
271+
let response = create_request(
272+
&http_client,
273+
&format!("{}/subgraphs/id/{}", INDEXER_URL, SUBGRAPH_ID),
274+
&receipt_json,
275+
&json!({
276+
"query": "{ _meta { block { number } } }"
277+
}),
278+
)
279+
.send()
280+
.await?;
281+
282+
if response.status().is_success() {
283+
total_successful += 1;
284+
println!(
285+
"V2 Query {} of batch {} sent successfully",
286+
i + 1,
287+
batch + 1
288+
);
289+
} else {
290+
return Err(anyhow::anyhow!(
291+
"Failed to send V2 query: {}",
292+
response.status()
293+
));
294+
}
295+
296+
// Small pause between queries within batch
297+
tokio::time::sleep(Duration::from_millis(100)).await;
298+
}
299+
300+
// Check metrics after batch
301+
let batch_metrics = metrics_checker.get_current_metrics().await?;
302+
println!(
303+
"After V2 batch {}: RAVs created: {}, Unaggregated fees: {}",
304+
batch + 1,
305+
batch_metrics.ravs_created_by_allocation(&allocation_id.to_string()),
306+
batch_metrics.unaggregated_fees_by_allocation(&allocation_id.to_string())
307+
);
308+
309+
// Wait between batches - long enough for first batch to exit buffer
310+
if batch < 1 {
311+
println!("Waiting for buffer period + 5s...");
312+
tokio::time::sleep(Duration::from_secs(WAIT_TIME_BATCHES)).await;
313+
}
314+
}
315+
316+
println!("\n=== V2 STAGE 2: Sending continuous trigger receipts ===");
317+
318+
// Now send a series of regular V2 queries with short intervals until RAV is detected
319+
for i in 0..MAX_TRIGGERS {
320+
println!("Sending V2 trigger query {}/{}...", i + 1, MAX_TRIGGERS);
321+
322+
// Create V2 receipt
323+
let receipt = create_tap_receipt_v2(
324+
MAX_RECEIPT_VALUE / 10, // Smaller value for trigger receipts
325+
&allocation_id,
326+
TAP_VERIFIER_CONTRACT,
327+
CHAIN_ID,
328+
&wallet,
329+
&payer,
330+
&service_provider,
331+
)?;
332+
333+
let receipt_json = serde_json::to_string(&receipt)?;
334+
335+
let response = create_request(
336+
&http_client,
337+
&format!("{}/subgraphs/id/{}", INDEXER_URL, SUBGRAPH_ID),
338+
&receipt_json,
339+
&json!({
340+
"query": "{ _meta { block { number } } }"
341+
}),
342+
)
343+
.send()
344+
.await?;
345+
346+
if response.status().is_success() {
347+
total_successful += 1;
348+
println!("V2 Trigger receipt {} sent successfully", i + 1);
349+
} else {
350+
return Err(anyhow::anyhow!(
351+
"Failed to send V2 trigger query: {}",
352+
response.status()
353+
));
354+
}
355+
356+
// Check after each trigger
357+
tokio::time::sleep(Duration::from_secs(1)).await;
358+
359+
let current_metrics = metrics_checker.get_current_metrics().await?;
360+
let current_ravs_created =
361+
current_metrics.ravs_created_by_allocation(&allocation_id.to_string());
362+
let current_unaggregated =
363+
current_metrics.unaggregated_fees_by_allocation(&allocation_id.to_string());
364+
365+
println!(
366+
"After V2 trigger {}: RAVs created: {}, Unaggregated fees: {}",
367+
i + 1,
368+
current_ravs_created,
369+
current_unaggregated
370+
);
371+
372+
// If we've succeeded, exit early
373+
if current_ravs_created > initial_ravs_created {
374+
println!(
375+
"✅ V2 TEST PASSED: RAVs created increased from {} to {}!",
376+
initial_ravs_created, current_ravs_created
377+
);
378+
return Ok(());
379+
}
380+
381+
if current_unaggregated < initial_unaggregated * 0.9 {
382+
println!(
383+
"✅ V2 TEST PASSED: Unaggregated fees decreased significantly from {} to {}!",
384+
initial_unaggregated, current_unaggregated
385+
);
386+
return Ok(());
387+
}
388+
}
389+
390+
println!("\n=== V2 Summary ===");
391+
println!("Total V2 queries sent successfully: {}", total_successful);
392+
393+
// If we got here, test failed
394+
println!("❌ V2 TEST FAILED: No RAV generation detected");
395+
Err(anyhow::anyhow!("Failed to detect V2 RAV generation"))
396+
}

integration-tests/src/utils.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use serde_json::json;
1414
use tap_core::{signed_message::Eip712SignedMessage, tap_eip712_domain};
1515
use tap_graph::Receipt;
1616
use thegraph_core::alloy::{primitives::Address, signers::local::PrivateKeySigner};
17+
use thegraph_core::CollectionId;
1718

1819
pub fn create_tap_receipt(
1920
value: u128,
@@ -50,6 +51,49 @@ pub fn create_tap_receipt(
5051
Ok(receipt)
5152
}
5253

54+
pub fn create_tap_receipt_v2(
55+
value: u128,
56+
allocation_id: &Address,
57+
verifier_contract: &str,
58+
chain_id: u64,
59+
wallet: &PrivateKeySigner,
60+
payer: &Address,
61+
service_provider: &Address,
62+
) -> Result<Eip712SignedMessage<tap_graph::v2::Receipt>> {
63+
let nonce = rng().random::<u64>();
64+
65+
// Get timestamp in nanoseconds
66+
let timestamp = SystemTime::now()
67+
.duration_since(SystemTime::UNIX_EPOCH)?
68+
.as_nanos();
69+
let timestamp_ns = timestamp as u64;
70+
71+
// Convert allocation_id to collection_id (as per V2 design)
72+
let collection_id = *CollectionId::from(*allocation_id);
73+
74+
// Create domain separator
75+
let eip712_domain_separator =
76+
tap_eip712_domain(chain_id, Address::from_str(verifier_contract)?);
77+
78+
// Create and sign V2 receipt
79+
println!("Creating and signing V2 receipt...");
80+
let receipt = Eip712SignedMessage::new(
81+
&eip712_domain_separator,
82+
tap_graph::v2::Receipt {
83+
collection_id,
84+
payer: *payer,
85+
service_provider: *service_provider,
86+
data_service: Address::ZERO, // Using zero address for data service
87+
nonce,
88+
timestamp_ns,
89+
value,
90+
},
91+
wallet,
92+
)?;
93+
94+
Ok(receipt)
95+
}
96+
5397
// Function to create a configured request
5498
pub fn create_request(
5599
client: &reqwest::Client,

justfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,7 @@ profile-restore:
109109
test-local:
110110
@cd integration-tests && ./fund_escrow.sh
111111
@cd integration-tests && cargo run -- rav1
112+
113+
test-local-v2:
114+
@cd integration-tests && ./fund_escrow.sh
115+
@cd integration-tests && cargo run -- rav2

0 commit comments

Comments
 (0)