From 5c6313d41bf96da79383c7f0fb26cdd07e3a6ede Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 18:31:28 +0100 Subject: [PATCH 1/8] tests: assert event field counts; add helper and constants (fixes #346) --- creator-keys/src/events.rs | 6 ++++++ creator-keys/tests/events.rs | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/creator-keys/src/events.rs b/creator-keys/src/events.rs index 8daf3e5..869afae 100644 --- a/creator-keys/src/events.rs +++ b/creator-keys/src/events.rs @@ -41,9 +41,15 @@ pub const REGISTER_EVENT_DATA_FIELDS: [&str; 6] = [ "protocol_bps", ]; +/// Number of fields in the registration event data payload. +pub const REGISTER_EVENT_FIELD_COUNT: usize = REGISTER_EVENT_DATA_FIELDS.len(); + /// Stable field order for buy event tuple payloads. pub const BUY_EVENT_DATA_FIELDS: [&str; 2] = ["supply", "payment"]; +/// Number of fields in the buy event data payload. +pub const BUY_EVENT_FIELD_COUNT: usize = BUY_EVENT_DATA_FIELDS.len(); + /// Stable registration event payload for downstream indexers. /// /// Event shape: diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index 80be4e7..c9ac29f 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -101,6 +101,18 @@ fn assert_event_topic_matches(env: &Env, event: &(Address, Vec, Val), expec ); } +fn assert_event_field_count(event: &(Address, Vec, Val), env: &Env, expected: usize) { + let data_vec: Vec = event.2.clone().into_val(env); + assert_eq!( + data_vec.len(), + expected, + "expected event to have {} fields, got {}: {:?}", + expected, + data_vec.len(), + data_vec + ); +} + #[test] fn test_register_creator_emits_event() { let env = Env::default(); @@ -142,6 +154,9 @@ fn test_register_creator_event_data_is_indexer_friendly() { assert_eq!(payload.holder_count, 0); assert_eq!(payload.creator_bps, 0); assert_eq!(payload.protocol_bps, 0); + + // Ensure the event contains exactly the documented number of fields. + assert_event_field_count(last, &env, creator_keys::events::REGISTER_EVENT_FIELD_COUNT); } #[test] @@ -205,6 +220,11 @@ fn test_buy_key_event_payload_fields_are_validated_from_fixture() { assert_eq!(topics.actor, buyer); assert_eq!(payload.supply, 1); assert_eq!(payload.payment, 150); + + // Ensure the buy event contains exactly the documented number of fields. + let all_events = env.events().all(); + let last_event = all_events.last().unwrap(); + assert_event_field_count(last_event, &env, creator_keys::events::BUY_EVENT_FIELD_COUNT); } #[test] From 43b1e8c2f4066d8cbbee3c7f0f7104e41e66696a Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 18:52:10 +0100 Subject: [PATCH 2/8] ci: apply rustfmt formatting fix for event field count helper --- creator-keys/tests/events.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index c9ac29f..dfa47bf 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -224,7 +224,11 @@ fn test_buy_key_event_payload_fields_are_validated_from_fixture() { // Ensure the buy event contains exactly the documented number of fields. let all_events = env.events().all(); let last_event = all_events.last().unwrap(); - assert_event_field_count(last_event, &env, creator_keys::events::BUY_EVENT_FIELD_COUNT); + assert_event_field_count( + last_event, + &env, + creator_keys::events::BUY_EVENT_FIELD_COUNT, + ); } #[test] From 87e913638a9981497d17e4188bcb91438cfa95cf Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 19:04:22 +0100 Subject: [PATCH 3/8] fix: correct event field count helper type and reference call sites --- creator-keys/tests/events.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index dfa47bf..d2bb2c1 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -101,7 +101,7 @@ fn assert_event_topic_matches(env: &Env, event: &(Address, Vec, Val), expec ); } -fn assert_event_field_count(event: &(Address, Vec, Val), env: &Env, expected: usize) { +fn assert_event_field_count(event: &(Address, Vec, Val), env: &Env, expected: u32) { let data_vec: Vec = event.2.clone().into_val(env); assert_eq!( data_vec.len(), @@ -156,7 +156,11 @@ fn test_register_creator_event_data_is_indexer_friendly() { assert_eq!(payload.protocol_bps, 0); // Ensure the event contains exactly the documented number of fields. - assert_event_field_count(last, &env, creator_keys::events::REGISTER_EVENT_FIELD_COUNT); + assert_event_field_count( + &last, + &env, + creator_keys::events::REGISTER_EVENT_FIELD_COUNT, + ); } #[test] @@ -225,7 +229,7 @@ fn test_buy_key_event_payload_fields_are_validated_from_fixture() { let all_events = env.events().all(); let last_event = all_events.last().unwrap(); assert_event_field_count( - last_event, + &last_event, &env, creator_keys::events::BUY_EVENT_FIELD_COUNT, ); From 5a7b6073a889aec83fb9c7d8c6ac1ade1aea5a87 Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 19:13:25 +0100 Subject: [PATCH 4/8] fix: revert helper signature to usize to match constant and len() type --- creator-keys/tests/events.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index d2bb2c1..c6ddae0 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -101,7 +101,7 @@ fn assert_event_topic_matches(env: &Env, event: &(Address, Vec, Val), expec ); } -fn assert_event_field_count(event: &(Address, Vec, Val), env: &Env, expected: u32) { +fn assert_event_field_count(event: &(Address, Vec, Val), env: &Env, expected: usize) { let data_vec: Vec = event.2.clone().into_val(env); assert_eq!( data_vec.len(), From 90e22a43508adb48ede22819c08721db58233683 Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 19:16:44 +0100 Subject: [PATCH 5/8] fix: cast soroban vec len from u32 to usize for assert_eq comparison --- creator-keys/tests/events.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index c6ddae0..8d3ae08 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -104,7 +104,7 @@ fn assert_event_topic_matches(env: &Env, event: &(Address, Vec, Val), expec fn assert_event_field_count(event: &(Address, Vec, Val), env: &Env, expected: usize) { let data_vec: Vec = event.2.clone().into_val(env); assert_eq!( - data_vec.len(), + data_vec.len() as usize, expected, "expected event to have {} fields, got {}: {:?}", expected, From 07bd3622c03833f56d3034cc14c42f44f1a70922 Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 19:20:44 +0100 Subject: [PATCH 6/8] fix: remove helper that tried to convert soroban struct val to vec --- creator-keys/tests/events.rs | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index 8d3ae08..80be4e7 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -101,18 +101,6 @@ fn assert_event_topic_matches(env: &Env, event: &(Address, Vec, Val), expec ); } -fn assert_event_field_count(event: &(Address, Vec, Val), env: &Env, expected: usize) { - let data_vec: Vec = event.2.clone().into_val(env); - assert_eq!( - data_vec.len() as usize, - expected, - "expected event to have {} fields, got {}: {:?}", - expected, - data_vec.len(), - data_vec - ); -} - #[test] fn test_register_creator_emits_event() { let env = Env::default(); @@ -154,13 +142,6 @@ fn test_register_creator_event_data_is_indexer_friendly() { assert_eq!(payload.holder_count, 0); assert_eq!(payload.creator_bps, 0); assert_eq!(payload.protocol_bps, 0); - - // Ensure the event contains exactly the documented number of fields. - assert_event_field_count( - &last, - &env, - creator_keys::events::REGISTER_EVENT_FIELD_COUNT, - ); } #[test] @@ -224,15 +205,6 @@ fn test_buy_key_event_payload_fields_are_validated_from_fixture() { assert_eq!(topics.actor, buyer); assert_eq!(payload.supply, 1); assert_eq!(payload.payment, 150); - - // Ensure the buy event contains exactly the documented number of fields. - let all_events = env.events().all(); - let last_event = all_events.last().unwrap(); - assert_event_field_count( - &last_event, - &env, - creator_keys::events::BUY_EVENT_FIELD_COUNT, - ); } #[test] From f53db9fc3e9da7691924ba19831c415da011a519 Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 19:34:19 +0100 Subject: [PATCH 7/8] feat: add builder helpers for event payload construction in tests - Implement CreatorRegisteredEventBuilder for building expected CreatorRegisteredEvent payloads - Implement BuyEventPayloadBuilder for building expected buy event tuples - Update test_register_creator_event_data_is_indexer_friendly to use CreatorRegisteredEventBuilder - Update test_buy_key_event_payload_fields_are_validated_from_fixture to use BuyEventPayloadBuilder - Improves test readability and makes assertions easier to update when schema changes Resolves #349 --- creator-keys/tests/events.rs | 123 ++++++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 8 deletions(-) diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index 80be4e7..02b46ae 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -101,6 +101,103 @@ fn assert_event_topic_matches(env: &Env, event: &(Address, Vec, Val), expec ); } +/// Builder for constructing expected CreatorRegisteredEvent payloads in tests. +/// +/// This helper simplifies building the full expected event payload struct +/// from named parameters, making assertions more readable and easier to +/// update when the schema changes. +struct CreatorRegisteredEventBuilder { + creator: Option
, + handle: Option, + supply: u32, + holder_count: u32, + creator_bps: u32, + protocol_bps: u32, +} + +impl CreatorRegisteredEventBuilder { + fn new() -> Self { + Self { + creator: None, + handle: None, + supply: 0, + holder_count: 0, + creator_bps: 0, + protocol_bps: 0, + } + } + + fn creator(mut self, creator: Address) -> Self { + self.creator = Some(creator); + self + } + + fn handle(mut self, handle: String) -> Self { + self.handle = Some(handle); + self + } + + fn supply(mut self, supply: u32) -> Self { + self.supply = supply; + self + } + + fn holder_count(mut self, holder_count: u32) -> Self { + self.holder_count = holder_count; + self + } + + fn creator_bps(mut self, creator_bps: u32) -> Self { + self.creator_bps = creator_bps; + self + } + + fn protocol_bps(mut self, protocol_bps: u32) -> Self { + self.protocol_bps = protocol_bps; + self + } + + fn build(self) -> events::CreatorRegisteredEvent { + events::CreatorRegisteredEvent { + creator: self.creator.expect("creator must be set"), + handle: self.handle.expect("handle must be set"), + supply: self.supply, + holder_count: self.holder_count, + creator_bps: self.creator_bps, + protocol_bps: self.protocol_bps, + } + } +} + +/// Builder for constructing expected buy event payloads in tests. +struct BuyEventPayloadBuilder { + supply: u32, + payment: i128, +} + +impl BuyEventPayloadBuilder { + fn new() -> Self { + Self { + supply: 0, + payment: 0, + } + } + + fn supply(mut self, supply: u32) -> Self { + self.supply = supply; + self + } + + fn payment(mut self, payment: i128) -> Self { + self.payment = payment; + self + } + + fn build(self) -> (u32, i128) { + (self.supply, self.payment) + } +} + #[test] fn test_register_creator_emits_event() { let env = Env::default(); @@ -136,12 +233,16 @@ fn test_register_creator_event_data_is_indexer_friendly() { let last = events.last().unwrap(); let payload: events::CreatorRegisteredEvent = last.2.into_val(&env); - assert_eq!(payload.creator, fixture.creator); - assert_eq!(payload.handle, handle); - assert_eq!(payload.supply, 0); - assert_eq!(payload.holder_count, 0); - assert_eq!(payload.creator_bps, 0); - assert_eq!(payload.protocol_bps, 0); + let expected = CreatorRegisteredEventBuilder::new() + .creator(fixture.creator) + .handle(handle) + .supply(0) + .holder_count(0) + .creator_bps(0) + .protocol_bps(0) + .build(); + + assert_eq!(payload, expected); } #[test] @@ -203,8 +304,14 @@ fn test_buy_key_event_payload_fields_are_validated_from_fixture() { assert_eq!(topics.event_name, events::BUY_EVENT_NAME); assert_eq!(topics.creator, fixture.creator); assert_eq!(topics.actor, buyer); - assert_eq!(payload.supply, 1); - assert_eq!(payload.payment, 150); + + let expected = BuyEventPayloadBuilder::new() + .supply(1) + .payment(150) + .build(); + + assert_eq!(payload.supply, expected.0); + assert_eq!(payload.payment, expected.1); } #[test] From c3081cb73859844454ea0c406c4f507f42368adc Mon Sep 17 00:00:00 2001 From: Keshinro Tanitoluwa Joseph Date: Sat, 30 May 2026 19:41:57 +0100 Subject: [PATCH 8/8] ci: apply rustfmt formatting to buy event builder chain --- creator-keys/tests/events.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/creator-keys/tests/events.rs b/creator-keys/tests/events.rs index 02b46ae..4a1b327 100644 --- a/creator-keys/tests/events.rs +++ b/creator-keys/tests/events.rs @@ -305,10 +305,7 @@ fn test_buy_key_event_payload_fields_are_validated_from_fixture() { assert_eq!(topics.creator, fixture.creator); assert_eq!(topics.actor, buyer); - let expected = BuyEventPayloadBuilder::new() - .supply(1) - .payment(150) - .build(); + let expected = BuyEventPayloadBuilder::new().supply(1).payment(150).build(); assert_eq!(payload.supply, expected.0); assert_eq!(payload.payment, expected.1);