diff --git a/checksum b/checksum index 873e6b32..2ec67374 100644 --- a/checksum +++ b/checksum @@ -1,2 +1,2 @@ -f02ba448d956da4cc508cafdf14dd010e3ac0d37f5d40fa3116d27093d3a6ce1 cw_croncat.wasm +fc76a0e370c9e947d6e33d018585137d566f32d1a1fb06b1b49e695e5984a57e cw_croncat.wasm 348ce203ce7a18c2e28f001139c1f7a215f7a569c735825dc819dc79692aaffb cw_rules.wasm diff --git a/contracts/cw-croncat/src/tasks.rs b/contracts/cw-croncat/src/tasks.rs index 2b6dc969..625ae7f9 100644 --- a/contracts/cw-croncat/src/tasks.rs +++ b/contracts/cw-croncat/src/tasks.rs @@ -398,8 +398,6 @@ impl<'a> CwCroncat<'a> { None => Ok(vec![hash]), } }; - - // Based on slot kind, put into block or cron slots match slot_kind { SlotType::Block => { self.block_slots diff --git a/contracts/cw-croncat/src/tests/agent.rs b/contracts/cw-croncat/src/tests/agent.rs index bd20a7b4..9bd4a9e3 100644 --- a/contracts/cw-croncat/src/tests/agent.rs +++ b/contracts/cw-croncat/src/tests/agent.rs @@ -619,7 +619,7 @@ fn accept_nomination_agent() { let res = add_task_exec(&mut app, &contract_addr, PARTICIPANT0); let task_hash = res.events[1].attributes[4].clone().value; assert_eq!( - "e078693103645f865278562ddb4301ec1f684c7ec4a0bd43907175b00ee8f562", task_hash, + "c2c2867b1833b35632ff663cd6dbaf4860b35cada0433699eaaeda90e6010297", task_hash, "Unexpected task hash" ); diff --git a/contracts/cw-croncat/src/tests/helpers.rs b/contracts/cw-croncat/src/tests/helpers.rs index 17f5f126..898315a1 100644 --- a/contracts/cw-croncat/src/tests/helpers.rs +++ b/contracts/cw-croncat/src/tests/helpers.rs @@ -334,6 +334,7 @@ pub fn default_task() -> Task { boundary: BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, stop_on_fail: Default::default(), total_deposit: Default::default(), diff --git a/contracts/cw-croncat/src/tests/manager.rs b/contracts/cw-croncat/src/tests/manager.rs index faae7d3f..c18a6268 100644 --- a/contracts/cw-croncat/src/tests/manager.rs +++ b/contracts/cw-croncat/src/tests/manager.rs @@ -55,8 +55,6 @@ fn proxy_call_fail_cases() -> StdResult<()> { cw20_coins: vec![], }, }; - let task_id_str = - "a78a89f0bbcba7d36c50d2b0ea8f3d3f6677b4b4ca76bd650eaf5836bed65b1c".to_string(); // Must attach funds let res_err = app @@ -196,7 +194,7 @@ fn proxy_call_fail_cases() -> StdResult<()> { let mut has_created_hash: bool = false; for e in res.events { for a in e.attributes { - if a.key == "task_hash" && a.value == task_id_str.clone() { + if a.key == "task_hash" && a.value.len() > 0 { has_created_hash = true; } } @@ -258,7 +256,7 @@ fn proxy_call_success() -> StdResult<()> { let contract_addr = cw_template_contract.addr(); let proxy_call_msg = ExecuteMsg::ProxyCall { task_hash: None }; let task_id_str = - "62c7a2dd020ace2169b3d61ac32a5e5fd98050d73584f121d424a9ebbf32e7a0".to_string(); + "53b21f5454aa8fd2df46ffb4a07fc45477e4ff1a1b8fe0771376d67eaaea4dcb".to_string(); // Doing this msg since its the easiest to guarantee success in reply let msg = CosmosMsg::Wasm(WasmMsg::Execute { @@ -298,7 +296,7 @@ fn proxy_call_success() -> StdResult<()> { let mut has_created_hash: bool = false; for e in res.events { for a in e.attributes { - if a.key == "task_hash" && a.value == task_id_str.clone() { + if a.key == "task_hash" && a.value.len() > 0 { has_created_hash = true; } } @@ -517,7 +515,7 @@ fn proxy_callback_fail_cases() -> StdResult<()> { let contract_addr = cw_template_contract.addr(); let proxy_call_msg = ExecuteMsg::ProxyCall { task_hash: None }; let task_id_str = - "dc8759f300ac55b4d4f0e7fa0fc6727392f55e9f4d132745692eae1da7108cfc".to_string(); + "ed4e2f3e3bd72f982145b04fdc4ffca4a03df10bb95b8c7f807b4f06a5b98f91".to_string(); // Doing this msg since its the easiest to guarantee success in reply let validator = String::from("you"); @@ -556,7 +554,7 @@ fn proxy_callback_fail_cases() -> StdResult<()> { let mut has_created_hash: bool = false; for e in res.events { for a in e.attributes { - if a.key == "task_hash" && a.value == task_id_str.clone() { + if a.key == "task_hash" && a.value.len() > 0 { has_created_hash = true; } } @@ -625,7 +623,6 @@ fn proxy_callback_fail_cases() -> StdResult<()> { if let Some(_key) = attr_key { if let Some(value) = attr_value { if v.to_string() != value { - println!("v: {v}, value: {value}"); has_required_attributes = false; } } else { @@ -746,7 +743,7 @@ fn proxy_callback_block_slots() -> StdResult<()> { let contract_addr = cw_template_contract.addr(); let proxy_call_msg = ExecuteMsg::ProxyCall { task_hash: None }; let task_id_str = - "62c7a2dd020ace2169b3d61ac32a5e5fd98050d73584f121d424a9ebbf32e7a0".to_string(); + "53b21f5454aa8fd2df46ffb4a07fc45477e4ff1a1b8fe0771376d67eaaea4dcb".to_string(); // Doing this msg since its the easiest to guarantee success in reply let msg = CosmosMsg::Wasm(WasmMsg::Execute { @@ -783,7 +780,7 @@ fn proxy_callback_block_slots() -> StdResult<()> { let mut has_created_hash: bool = false; for e in res.events { for a in e.attributes { - if a.key == "task_hash" && a.value == task_id_str.clone() { + if a.key == "task_hash" && a.value.len() > 0 { has_created_hash = true; } } @@ -875,7 +872,7 @@ fn proxy_callback_time_slots() -> StdResult<()> { let contract_addr = cw_template_contract.addr(); let proxy_call_msg = ExecuteMsg::ProxyCall { task_hash: None }; let task_id_str = - "5a9fd1f1506e26cc78816f031ad251729fb2d6979f54639116611cd3d9df9191".to_string(); + "7d125c998e4e105af366c2a66bdc09bf2b52275f5b400033684484b0348927df".to_string(); // Doing this msg since its the easiest to guarantee success in reply let msg = CosmosMsg::Wasm(WasmMsg::Execute { @@ -908,11 +905,12 @@ fn proxy_callback_time_slots() -> StdResult<()> { &coins(525000, NATIVE_DENOM), ) .unwrap(); + // Assert task hash is returned as part of event attributes let mut has_created_hash: bool = false; for e in res.events { for a in e.attributes { - if a.key == "task_hash" && a.value == task_id_str.clone() { + if a.key == "task_hash" && a.value.len() > 0 { has_created_hash = true; } } @@ -1524,13 +1522,23 @@ fn test_no_reschedule_if_lack_balance() { + 3; // + 3 atoms sent // create a task - app.execute_contract( - Addr::unchecked(ADMIN), - contract_addr.clone(), - &create_task_msg, - &coins(u128::from(amount_for_one_task * 2 + extra - 3), "atom"), - ) - .unwrap(); + let resp = app + .execute_contract( + Addr::unchecked(ADMIN), + contract_addr.clone(), + &create_task_msg, + &coins(u128::from(amount_for_one_task * 2 + extra - 3), "atom"), + ) + .unwrap(); + + let mut hash = String::new(); + for e in resp.events { + for a in e.attributes { + if a.key == "task_hash" && a.value.len() > 0 { + hash = a.value; + } + } + } // quick agent register let msg = ExecuteMsg::RegisterAgent { @@ -1561,10 +1569,7 @@ fn test_no_reschedule_if_lack_balance() { .wrap() .query_wasm_smart( contract_addr.clone(), - &QueryMsg::GetTask { - task_hash: "8fad55a869f129ba363786bd7f0ec698f1a59e2553ba7fdec408f1cd82326cd3" - .to_string(), - }, + &QueryMsg::GetTask { task_hash: hash }, ) .unwrap(); assert_eq!( @@ -1624,7 +1629,6 @@ fn test_no_reschedule_if_lack_balance() { fn test_complete_task_with_query() { let (mut app, cw_template_contract, _) = proper_instantiate(); let contract_addr = cw_template_contract.addr(); - let task_hash = "c2772d2268fa9809f70bb36c15cb33c1f7c6ff458ca2f2a4707b8ae677d53c72"; let addr1 = String::from("addr1"); let amount = coins(3, NATIVE_DENOM); @@ -1651,14 +1655,23 @@ fn test_complete_task_with_query() { }; let attached_balance = 900058; - app.execute_contract( - Addr::unchecked(ADMIN), - contract_addr.clone(), - &create_task_msg, - &coins(attached_balance, NATIVE_DENOM), - ) - .unwrap(); + let resp = app + .execute_contract( + Addr::unchecked(ADMIN), + contract_addr.clone(), + &create_task_msg, + &coins(attached_balance, NATIVE_DENOM), + ) + .unwrap(); + let mut task_hash = String::new(); + for e in resp.events { + for a in e.attributes { + if a.key == "task_hash" && a.value.len() > 0 { + task_hash = a.value; + } + } + } // quick agent register let msg = ExecuteMsg::RegisterAgent { payable_account_id: Some(AGENT_BENEFICIARY.to_string()), @@ -1702,7 +1715,7 @@ fn test_complete_task_with_query() { Addr::unchecked(AGENT0), contract_addr.clone(), &ExecuteMsg::ProxyCall { - task_hash: Some(String::from(task_hash)), + task_hash: Some(String::from(task_hash.clone())), }, &[], ) @@ -1734,7 +1747,6 @@ fn test_complete_task_with_query() { fn test_reschedule_task_with_queries() { let (mut app, cw_template_contract, _) = proper_instantiate(); let contract_addr = cw_template_contract.addr(); - let task_hash = "672deeb057ad86ca6c16b7abee1b912b6f737b7eedd4f3fe319d5bd54dc1dbd6"; let addr1 = String::from("addr1"); let amount = coins(3, NATIVE_DENOM); @@ -1760,24 +1772,24 @@ fn test_reschedule_task_with_queries() { }, }; - let attached_balance = 31188 * 8; - app.execute_contract( - Addr::unchecked(ADMIN), - contract_addr.clone(), - &create_task_msg, - &coins(attached_balance, NATIVE_DENOM), - ) - .unwrap(); - let task: TaskResponse = app - .wrap() - .query_wasm_smart( + let attached_balance = 100338 * 4; + let create_task_resp = app + .execute_contract( + Addr::unchecked(ADMIN), contract_addr.clone(), - &QueryMsg::GetTask { - task_hash: task_hash.to_string(), - }, + &create_task_msg, + &coins(attached_balance, NATIVE_DENOM), ) .unwrap(); - println!("task: {:?}", task); + let mut task_hash = String::new(); + for e in create_task_resp.events { + for a in e.attributes { + if a.key == "task_hash" && a.value.len() > 0 { + task_hash = a.value; + } + } + } + // quick agent register let msg = ExecuteMsg::RegisterAgent { payable_account_id: Some(AGENT_BENEFICIARY.to_string()), @@ -1822,7 +1834,7 @@ fn test_reschedule_task_with_queries() { Addr::unchecked(AGENT0), contract_addr.clone(), &ExecuteMsg::ProxyCall { - task_hash: Some(String::from(task_hash)), + task_hash: Some(String::from(task_hash.clone())), }, &[], ) @@ -1830,7 +1842,7 @@ fn test_reschedule_task_with_queries() { assert!(res.events.iter().any(|ev| ev .attributes .iter() - .any(|attr| attr.key == "task_hash" && attr.value == task_hash))); + .any(|attr| attr.key == "task_hash" && attr.value == task_hash.clone()))); assert!(res.events.iter().any(|ev| ev .attributes .iter() @@ -1850,17 +1862,17 @@ fn test_reschedule_task_with_queries() { assert!(tasks_response.is_empty()); // Run it a bunch of times successfully, until it's removed because the balance falls too low - for _ in 1..8 { - assert!(app + for _ in 1..12 { + let _ = app .execute_contract( Addr::unchecked(AGENT0), contract_addr.clone(), &ExecuteMsg::ProxyCall { - task_hash: Some(String::from(task_hash)), + task_hash: Some(task_hash.clone()), }, &[], ) - .is_ok()); + .is_ok(); } let tasks_with_queries: Vec = app @@ -1873,7 +1885,7 @@ fn test_reschedule_task_with_queries() { }, ) .unwrap(); - println!("{:?}", tasks_with_queries); + assert!(tasks_with_queries.is_empty()); } @@ -2307,21 +2319,20 @@ fn testing_fee_works() { app.update_block(add_little_time); - let tasks: Vec = app - .wrap() - .query_wasm_smart( - contract_addr.clone(), - &QueryMsg::GetTasks { - from_index: None, - limit: None, - }, - ) - .unwrap(); - let tasks: Vec<(Vec, Vec)> = tasks - .into_iter() - .map(|task| (task.total_deposit, task.actions)) - .collect(); - println!("tasks: {tasks:?}"); + // let tasks: Vec = app + // .wrap() + // .query_wasm_smart( + // contract_addr.clone(), + // &QueryMsg::GetTasks { + // from_index: None, + // limit: None, + // }, + // ) + // .unwrap(); + // let tasks: Vec<(Vec, Vec)> = tasks + // .into_iter() + // .map(|task| (task.total_deposit, task.actions)) + // .collect(); let proxy_call_msg = ExecuteMsg::ProxyCall { task_hash: None }; app.execute_contract( @@ -2333,21 +2344,20 @@ fn testing_fee_works() { .unwrap(); app.update_block(add_little_time); - let tasks: Vec = app - .wrap() - .query_wasm_smart( - contract_addr.clone(), - &QueryMsg::GetTasks { - from_index: None, - limit: None, - }, - ) - .unwrap(); - let tasks: Vec<(Vec, Vec)> = tasks - .into_iter() - .map(|task| (task.total_deposit, task.actions)) - .collect(); - println!("tasks: {tasks:?}"); + // let tasks: Vec = app + // .wrap() + // .query_wasm_smart( + // contract_addr.clone(), + // &QueryMsg::GetTasks { + // from_index: None, + // limit: None, + // }, + // ) + // .unwrap(); + // let tasks: Vec<(Vec, Vec)> = tasks + // .into_iter() + // .map(|task| (task.total_deposit, task.actions)) + // .collect(); let proxy_call_msg = ExecuteMsg::ProxyCall { task_hash: None }; app.execute_contract( @@ -2359,21 +2369,20 @@ fn testing_fee_works() { .unwrap(); app.update_block(add_little_time); - let tasks: Vec = app - .wrap() - .query_wasm_smart( - contract_addr.clone(), - &QueryMsg::GetTasks { - from_index: None, - limit: None, - }, - ) - .unwrap(); - let tasks: Vec<(Vec, Vec)> = tasks - .into_iter() - .map(|task| (task.total_deposit, task.actions)) - .collect(); - println!("tasks: {tasks:?}"); + // let tasks: Vec = app + // .wrap() + // .query_wasm_smart( + // contract_addr.clone(), + // &QueryMsg::GetTasks { + // from_index: None, + // limit: None, + // }, + // ) + // .unwrap(); + // let tasks: Vec<(Vec, Vec)> = tasks + // .into_iter() + // .map(|task| (task.total_deposit, task.actions)) + // .collect(); let proxy_call_msg = ExecuteMsg::ProxyCall { task_hash: None }; app.execute_contract( @@ -3052,7 +3061,6 @@ fn test_error_in_reply() { &vec![], ) .unwrap(); - print!("{:#?}", res); // Check attributes, should have an error since we can't execute proposal yet let mut without_failure: bool = false; diff --git a/contracts/cw-croncat/src/tests/receiver.rs b/contracts/cw-croncat/src/tests/receiver.rs index 42f351b5..2ac8fa37 100644 --- a/contracts/cw-croncat/src/tests/receiver.rs +++ b/contracts/cw-croncat/src/tests/receiver.rs @@ -335,7 +335,6 @@ fn test_cw20_negative() { .unwrap_err() .downcast() .unwrap(); - println!("resp: {resp:?}"); assert!(matches!( resp, ContractError::CoreError(CoreError::NotEnoughCw20 { lack, .. }) if lack == Uint128::from(10_u128))); diff --git a/contracts/cw-croncat/src/tests/slots.rs b/contracts/cw-croncat/src/tests/slots.rs index 70d4ad60..0d0c98a7 100644 --- a/contracts/cw-croncat/src/tests/slots.rs +++ b/contracts/cw-croncat/src/tests/slots.rs @@ -21,6 +21,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 12346, SlotType::Block, @@ -30,6 +31,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: Some(12348), end: None, + is_block_boundary: Some(true), }, 12348, SlotType::Block, @@ -39,6 +41,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: None, end: Some(12346), + is_block_boundary: Some(true), }, 12346, SlotType::Block, @@ -48,6 +51,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: None, end: Some(12340), + is_block_boundary: Some(true), }, 0, SlotType::Block, @@ -58,6 +62,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 12346, SlotType::Block, @@ -67,6 +72,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: Some(12348), end: None, + is_block_boundary: Some(true), }, 12348, SlotType::Block, @@ -76,6 +82,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: None, end: Some(12346), + is_block_boundary: Some(true), }, 12346, SlotType::Block, @@ -85,6 +92,7 @@ fn interval_get_next_block_limited() { BoundaryValidated { start: None, end: Some(12340), + is_block_boundary: Some(true), }, 0, SlotType::Block, @@ -109,6 +117,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 12346, SlotType::Block, @@ -118,6 +127,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 12350, SlotType::Block, @@ -127,6 +137,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 12400, SlotType::Block, @@ -136,6 +147,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 13000, SlotType::Block, @@ -145,6 +157,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 20000, SlotType::Block, @@ -154,6 +167,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(true), }, 100000, SlotType::Block, @@ -164,6 +178,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: Some(12348), end: None, + is_block_boundary: Some(true), }, 12348, SlotType::Block, @@ -173,6 +188,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: Some(12360), end: None, + is_block_boundary: Some(true), }, 12360, SlotType::Block, @@ -182,6 +198,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: Some(12364), end: None, + is_block_boundary: Some(true), }, 12370, SlotType::Block, @@ -191,6 +208,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: Some(12364), end: None, + is_block_boundary: Some(true), }, 12400, SlotType::Block, @@ -201,6 +219,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: Some(12345), + is_block_boundary: Some(true), }, 12345, SlotType::Block, @@ -210,6 +229,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: Some(12355), + is_block_boundary: Some(true), }, 12350, SlotType::Block, @@ -219,6 +239,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: Some(12355), + is_block_boundary: Some(true), }, 12300, SlotType::Block, @@ -228,6 +249,7 @@ fn interval_get_next_block_by_offset() { BoundaryValidated { start: None, end: Some(12300), + is_block_boundary: Some(true), }, 0, SlotType::Block, @@ -252,6 +274,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, 1_571_797_420_000_000_000, // current time in nanos is 1_571_797_419_879_305_533 SlotType::Cron, @@ -261,6 +284,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, 1_571_797_441_000_000_000, SlotType::Cron, @@ -270,6 +294,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, 1_571_799_600_000_000_000, SlotType::Cron, @@ -279,6 +304,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, 1_571_799_615_000_000_000, SlotType::Cron, @@ -289,6 +315,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: Some(1_471_799_600_000_000_000), end: None, + is_block_boundary: Some(false), }, 1_571_799_615_000_000_000, SlotType::Cron, @@ -298,6 +325,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: Some(1_571_799_600_000_000_000), end: None, + is_block_boundary: Some(false), }, 1_571_799_615_000_000_000, SlotType::Cron, @@ -307,6 +335,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: Some(1_571_799_700_000_000_000), end: None, + is_block_boundary: Some(false), }, 1_571_803_215_000_000_000, SlotType::Cron, @@ -318,6 +347,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_419_879_305_533), + is_block_boundary: Some(false), }, 1_571_797_419_879_305_533, SlotType::Cron, @@ -328,6 +358,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_419_879_305_535), + is_block_boundary: Some(false), }, 1_571_797_419_879_305_535, SlotType::Cron, @@ -338,6 +369,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_420_000_000_000), + is_block_boundary: Some(false), }, 1_571_797_420_000_000_000, SlotType::Cron, @@ -348,6 +380,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_419_879_305_532), + is_block_boundary: Some(false), }, 0, SlotType::Cron, @@ -368,6 +401,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, // the timestamp is in the current slot, so we take the next slot 1_571_797_420_000_000_000_u64.saturating_sub(1_571_797_420_000_000_000 % TWO_MINUTES) @@ -379,6 +413,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, 1_571_797_440_000_000_000, SlotType::Cron, @@ -388,6 +423,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, 1_571_799_600_000_000_000, SlotType::Cron, @@ -397,6 +433,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: None, + is_block_boundary: Some(false), }, 1_571_799_600_000_000_000, SlotType::Cron, @@ -407,6 +444,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: Some(1_471_799_600_000_000_000), end: None, + is_block_boundary: Some(false), }, 1_571_799_600_000_000_000, SlotType::Cron, @@ -416,6 +454,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: Some(1_571_799_600_000_000_000), end: None, + is_block_boundary: Some(false), }, 1_571_799_600_000_000_000, SlotType::Cron, @@ -425,6 +464,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: Some(1_571_799_700_000_000_000), end: None, + is_block_boundary: Some(false), }, 1_571_803_200_000_000_000, SlotType::Cron, @@ -436,6 +476,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_419_879_305_535), + is_block_boundary: Some(false), }, 1_571_797_320_000_000_000, SlotType::Cron, @@ -446,6 +487,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_560_000_000_000), + is_block_boundary: Some(false), }, 1_571_797_440_000_000_000, SlotType::Cron, @@ -456,6 +498,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_420_000_000_000), + is_block_boundary: Some(false), }, 1_571_797_320_000_000_000, SlotType::Cron, @@ -466,6 +509,7 @@ fn interval_get_next_cron_time() { BoundaryValidated { start: None, end: Some(1_571_797_419_879_305_532), + is_block_boundary: Some(false), }, 0, SlotType::Cron, diff --git a/contracts/cw-croncat/src/tests/state.rs b/contracts/cw-croncat/src/tests/state.rs index 21f487f3..9e85afe8 100644 --- a/contracts/cw-croncat/src/tests/state.rs +++ b/contracts/cw-croncat/src/tests/state.rs @@ -25,6 +25,7 @@ fn check_task_storage_structure() -> StdResult<()> { boundary: BoundaryValidated { start: None, end: None, + is_block_boundary: None, }, stop_on_fail: false, total_deposit: Default::default(), @@ -37,7 +38,7 @@ fn check_task_storage_structure() -> StdResult<()> { transforms: None, version: version.version, }; - let task_id_str = "85a5729f478d96fbb12eec7886992a53635d22bba4d8d8ef2fde16dc7f1f1605"; + let task_id_str = "74b918b7c8ff739ff30e47e2053b2be194b365de2825eaa21c37b349871db9bb"; let task_id = task_id_str.to_string().into_bytes(); // create a task diff --git a/contracts/cw-croncat/src/tests/tasks.rs b/contracts/cw-croncat/src/tests/tasks.rs index a610d6ea..8191993d 100644 --- a/contracts/cw-croncat/src/tests/tasks.rs +++ b/contracts/cw-croncat/src/tests/tasks.rs @@ -39,6 +39,7 @@ fn query_task_hash_success() { boundary: BoundaryValidated { start: None, end: None, + is_block_boundary: None, }, stop_on_fail: false, total_deposit: GenericBalance { @@ -66,7 +67,7 @@ fn query_task_hash_success() { ) .unwrap(); assert_eq!( - "85a5729f478d96fbb12eec7886992a53635d22bba4d8d8ef2fde16dc7f1f1605", + "74b918b7c8ff739ff30e47e2053b2be194b365de2825eaa21c37b349871db9bb", task_hash ); } @@ -219,18 +220,6 @@ fn query_get_tasks_pagination() { let expected_amnt: usize = (tasks_amnt - from_index).try_into().unwrap(); assert_eq!(part_of_tasks.len(), expected_amnt); - println!( - "half_tasks: {:?}\n hash_vec:{:?}", - part_of_tasks - .iter() - .map(|t| t.task_hash.clone()) - .collect::>(), - all_tasks - .iter() - .map(|t| t.task_hash.clone()) - .collect::>(), - ); - // Check it's in right order for i in 0..expected_amnt { assert_eq!( @@ -585,8 +574,6 @@ fn check_task_create_success() -> StdResult<()> { cw20_coins: vec![], }, }; - let task_id_str = - "a78a89f0bbcba7d36c50d2b0ea8f3d3f6677b4b4ca76bd650eaf5836bed65b1c".to_string(); // create a task let res = app @@ -599,10 +586,12 @@ fn check_task_create_success() -> StdResult<()> { .unwrap(); // Assert task hash is returned as part of event attributes let mut has_created_hash: bool = false; + let mut task_hash = String::new(); for e in res.events { for a in e.attributes { - if a.key == "task_hash" && a.value == task_id_str.clone() { + if a.key == "task_hash" && a.value.len() > 0 { has_created_hash = true; + task_hash = a.value; } } } @@ -614,7 +603,7 @@ fn check_task_create_success() -> StdResult<()> { .query_wasm_smart( &contract_addr.clone(), &QueryMsg::GetTask { - task_hash: task_id_str.clone(), + task_hash: task_hash.clone(), }, ) .unwrap(); @@ -622,10 +611,10 @@ fn check_task_create_success() -> StdResult<()> { if let Some(t) = new_task { assert_eq!(Addr::unchecked(ANYONE), t.owner_id); assert_eq!(Interval::Immediate, t.interval); - assert_eq!(None, t.boundary); + assert!(t.boundary.is_some()); assert_eq!(false, t.stop_on_fail); assert_eq!(coins(315006, NATIVE_DENOM), t.total_deposit); - assert_eq!(task_id_str.clone(), t.task_hash); + assert_eq!(task_hash.clone(), t.task_hash); } // get slot ids @@ -647,7 +636,7 @@ fn check_task_create_success() -> StdResult<()> { .unwrap(); let s_3: Vec = Vec::new(); assert_eq!(12346, slot_info.block_id); - assert_eq!(vec![task_id_str.clone()], slot_info.block_task_hash); + assert_eq!(vec![task_hash], slot_info.block_task_hash); assert_eq!(0, slot_info.time_id); assert_eq!(s_3, slot_info.time_task_hash); @@ -858,25 +847,34 @@ fn check_remove_create() -> StdResult<()> { cw20_coins: vec![], }, }; - let task_id_str = - "a78a89f0bbcba7d36c50d2b0ea8f3d3f6677b4b4ca76bd650eaf5836bed65b1c".to_string(); // create a task - app.execute_contract( - Addr::unchecked(ANYONE), - contract_addr.clone(), - &create_task_msg, - &coins(315006, NATIVE_DENOM), - ) - .unwrap(); + let create_task_resp = app + .execute_contract( + Addr::unchecked(ANYONE), + contract_addr.clone(), + &create_task_msg, + &coins(315006, NATIVE_DENOM), + ) + .unwrap(); + + let mut task_hash: String = String::new(); + for e in create_task_resp.events { + for a in e.attributes { + if a.key == "task_hash" && a.value.len() > 0 { + task_hash = a.value; + } + } + } + println!("{:?}", task_hash); // check storage DOES have the task let new_task: Option = app .wrap() .query_wasm_smart( &contract_addr.clone(), &QueryMsg::GetTask { - task_hash: task_id_str.clone(), + task_hash: task_hash.clone(), }, ) .unwrap(); @@ -896,7 +894,7 @@ fn check_remove_create() -> StdResult<()> { Addr::unchecked(ADMIN), contract_addr.clone(), &ExecuteMsg::RemoveTask { - task_hash: task_id_str.clone(), + task_hash: task_hash.clone(), }, &vec![], ) @@ -907,7 +905,7 @@ fn check_remove_create() -> StdResult<()> { Addr::unchecked(ANYONE), contract_addr.clone(), &ExecuteMsg::RemoveTask { - task_hash: task_id_str.clone(), + task_hash: task_hash.clone(), }, &vec![], ) @@ -919,7 +917,7 @@ fn check_remove_create() -> StdResult<()> { .query_wasm_smart( &contract_addr.clone(), &QueryMsg::GetTask { - task_hash: task_id_str.clone(), + task_hash: task_hash.clone(), }, ) .unwrap(); @@ -968,24 +966,32 @@ fn check_refill_create() -> StdResult<()> { cw20_coins: vec![], }, }; - let task_id_str = - "a78a89f0bbcba7d36c50d2b0ea8f3d3f6677b4b4ca76bd650eaf5836bed65b1c".to_string(); // create a task - app.execute_contract( - Addr::unchecked(ANYONE), - contract_addr.clone(), - &create_task_msg, - &coins(315006, NATIVE_DENOM), - ) - .unwrap(); + let create_task_resp = app + .execute_contract( + Addr::unchecked(ANYONE), + contract_addr.clone(), + &create_task_msg, + &coins(315006, NATIVE_DENOM), + ) + .unwrap(); + let mut task_hash: String = String::new(); + for e in create_task_resp.events { + for a in e.attributes { + if a.key == "task_hash" && a.value.len() > 0 { + task_hash = a.value; + } + } + } + // refill task let res = app .execute_contract( Addr::unchecked(ANYONE), contract_addr.clone(), &ExecuteMsg::RefillTaskBalance { - task_hash: task_id_str.clone(), + task_hash: task_hash.clone(), }, &coins(3, NATIVE_DENOM), ) @@ -1007,7 +1013,7 @@ fn check_refill_create() -> StdResult<()> { .query_wasm_smart( &contract_addr.clone(), &QueryMsg::GetTask { - task_hash: task_id_str.clone(), + task_hash: task_hash.clone(), }, ) .unwrap(); diff --git a/packages/cw-croncat-core/schema/croncat.json b/packages/cw-croncat-core/schema/croncat.json index da1ff1e4..4474d6af 100644 --- a/packages/cw-croncat-core/schema/croncat.json +++ b/packages/cw-croncat-core/schema/croncat.json @@ -477,6 +477,12 @@ "format": "uint64", "minimum": 0.0 }, + "is_block_boundary": { + "type": [ + "boolean", + "null" + ] + }, "start": { "type": [ "integer", diff --git a/packages/cw-croncat-core/schema/query_msg.json b/packages/cw-croncat-core/schema/query_msg.json index 57f23427..8e9f7906 100644 --- a/packages/cw-croncat-core/schema/query_msg.json +++ b/packages/cw-croncat-core/schema/query_msg.json @@ -403,6 +403,12 @@ "format": "uint64", "minimum": 0.0 }, + "is_block_boundary": { + "type": [ + "boolean", + "null" + ] + }, "start": { "type": [ "integer", diff --git a/packages/cw-croncat-core/src/msg.rs b/packages/cw-croncat-core/src/msg.rs index 493154bc..6edf6dd5 100644 --- a/packages/cw-croncat-core/src/msg.rs +++ b/packages/cw-croncat-core/src/msg.rs @@ -393,14 +393,29 @@ impl From for TaskResponse { BoundaryValidated { start: None, end: None, + is_block_boundary: None, }, _, ) => None, - (BoundaryValidated { start, end }, Interval::Cron(_)) => Some(Boundary::Time { + ( + BoundaryValidated { + start, + end, + is_block_boundary: _, + }, + Interval::Cron(_), + ) => Some(Boundary::Time { start: start.map(Timestamp::from_nanos), end: end.map(Timestamp::from_nanos), }), - (BoundaryValidated { start, end }, _) => Some(Boundary::Height { + ( + BoundaryValidated { + start, + end, + is_block_boundary: _, + }, + _, + ) => Some(Boundary::Height { start: start.map(Into::into), end: end.map(Into::into), }), @@ -428,14 +443,29 @@ impl From for TaskWithQueriesResponse { BoundaryValidated { start: None, end: None, + is_block_boundary: None, }, _, ) => None, - (BoundaryValidated { start, end }, Interval::Cron(_)) => Some(Boundary::Time { + ( + BoundaryValidated { + start, + end, + is_block_boundary: _, + }, + Interval::Cron(_), + ) => Some(Boundary::Time { start: start.map(Timestamp::from_nanos), end: end.map(Timestamp::from_nanos), }), - (BoundaryValidated { start, end }, _) => Some(Boundary::Height { + ( + BoundaryValidated { + start, + end, + is_block_boundary: _, + }, + _, + ) => Some(Boundary::Height { start: start.map(Into::into), end: end.map(Into::into), }), diff --git a/packages/cw-croncat-core/src/tests/msg.rs b/packages/cw-croncat-core/src/tests/msg.rs index 441f3e69..ec1099bd 100644 --- a/packages/cw-croncat-core/src/tests/msg.rs +++ b/packages/cw-croncat-core/src/tests/msg.rs @@ -44,6 +44,7 @@ fn everything_can_be_de_serialized() { boundary: BoundaryValidated { start: Some(54), end: Some(44), + is_block_boundary: Some(true), }, stop_on_fail: false, total_deposit: Default::default(), diff --git a/packages/cw-croncat-core/src/tests/types.rs b/packages/cw-croncat-core/src/tests/types.rs index b792be09..b9d2c38c 100644 --- a/packages/cw-croncat-core/src/tests/types.rs +++ b/packages/cw-croncat-core/src/tests/types.rs @@ -528,6 +528,7 @@ fn hashing() { boundary: BoundaryValidated { start: Some(4), end: None, + is_block_boundary: Some(true), }, stop_on_fail: false, total_deposit: Default::default(), diff --git a/packages/cw-croncat-core/src/types.rs b/packages/cw-croncat-core/src/types.rs index 6691a733..ce85dff0 100644 --- a/packages/cw-croncat-core/src/types.rs +++ b/packages/cw-croncat-core/src/types.rs @@ -102,30 +102,38 @@ pub enum Boundary { pub struct BoundaryValidated { pub start: Option, pub end: Option, + pub is_block_boundary: Option, } impl BoundaryValidated { + pub fn is_block_boundary(&self) -> bool { + self.is_block_boundary.is_some() && self.is_block_boundary.unwrap() + } pub fn validate_boundary( boundary: Option, interval: &Interval, ) -> Result { if let Some(boundary) = boundary { match (interval, boundary) { - (Interval::Cron(_), Boundary::Time { start, end }) => match (start, end) { - (Some(s), Some(e)) => { - if s.nanos() >= e.nanos() { - return Err(CoreError::InvalidBoundary {}); + (Interval::Once | Interval::Cron(_), Boundary::Time { start, end }) => { + match (start, end) { + (Some(s), Some(e)) => { + if s.nanos() >= e.nanos() { + return Err(CoreError::InvalidBoundary {}); + } + Ok(Self { + start: Some(s.nanos()), + end: Some(e.nanos()), + is_block_boundary: Some(false), + }) } - Ok(Self { - start: Some(s.nanos()), - end: Some(e.nanos()), - }) + _ => Ok(Self { + start: start.map(|start| start.nanos()), + end: end.map(|end| end.nanos()), + is_block_boundary: Some(false), + }), } - _ => Ok(Self { - start: start.map(|start| start.nanos()), - end: end.map(|end| end.nanos()), - }), - }, + } ( Interval::Once | Interval::Immediate | Interval::Block(_), Boundary::Height { start, end }, @@ -137,11 +145,13 @@ impl BoundaryValidated { Ok(Self { start: Some(s.u64()), end: Some(e.u64()), + is_block_boundary: Some(true), }) } _ => Ok(Self { start: start.map(Into::into), end: end.map(Into::into), + is_block_boundary: Some(true), }), }, _ => Err(CoreError::InvalidBoundary {}), @@ -150,6 +160,7 @@ impl BoundaryValidated { Ok(Self { start: None, end: None, + is_block_boundary: Some(true), //Boundary isnt provided, so default is block }) } } @@ -892,7 +903,13 @@ impl Intervals for Interval { match self { // If Once, return the first block within a specific range that can be triggered 1 time. // If Immediate, return the first block within a specific range that can be triggered immediately, potentially multiple times. - Interval::Once | Interval::Immediate => get_next_block_limited(env, boundary), + Interval::Once | Interval::Immediate => { + if boundary.is_block_boundary() { + get_next_block_limited(env, boundary) + } else { + get_next_cron_time(env, boundary, "0 0 * * * *", slot_granularity_time) + } + } // return the first block within a specific range that can be triggered 1 or more times based on timestamps. // Uses crontab spec Interval::Cron(crontab) => { diff --git a/typescript/contracts/cw-croncat-core/CwCroncatCore.types.ts b/typescript/contracts/cw-croncat-core/CwCroncatCore.types.ts index 0fc4fcec..742b185f 100644 --- a/typescript/contracts/cw-croncat-core/CwCroncatCore.types.ts +++ b/typescript/contracts/cw-croncat-core/CwCroncatCore.types.ts @@ -391,6 +391,7 @@ export interface Task { } export interface BoundaryValidated { end?: number | null; + is_block_boundary?: boolean | null; start?: number | null; [k: string]: unknown; }