1use rand::Rng;
5use std::{cell::RefCell, time::Duration};
6
7use candid::Principal;
8use getrandom::register_custom_getrandom;
9use rand::{rngs::StdRng, RngCore, SeedableRng};
10
11thread_local! {
13 pub static RNG: RefCell<Option<StdRng>> = RefCell::new(None);
14}
15
16pub fn init_ic_rand() {
19 ic_cdk_timers::set_timer(Duration::from_secs(0), || ic_cdk::spawn(set_rand()));
20 register_custom_getrandom!(custom_getrandom);
21}
22
23pub fn get_random_number() -> u64 {
26 RNG.with(|rng| rng.borrow_mut().as_mut().unwrap().gen())
27}
28
29async fn set_rand() {
31 let (seed,) = ic_cdk::call(Principal::management_canister(), "raw_rand", ())
32 .await
33 .unwrap();
34 RNG.with(|rng| {
35 *rng.borrow_mut() = Some(StdRng::from_seed(seed));
36 ic_cdk::println!("rng: {:?}", *rng.borrow());
37 });
38}
39
40fn custom_getrandom(buf: &mut [u8]) -> Result<(), getrandom::Error> {
42 RNG.with(|rng| rng.borrow_mut().as_mut().unwrap().fill_bytes(buf));
43 Ok(())
44}