dice_contract
Spiral.Kino.eval!(
~S"""
///- --package ../dice
open rust
open rust.rust_operators
open sm'_operators
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test static
open testing
""",
timeout: 300_000
)
dice_contract
state
Spiral.Kino.eval!(
~S"""
type state =
{
version : u32
seeds : near.vector u8
}
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
()
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
trace Verbose (fun () => "") id
""",
timeout: 300_000
)
new
Spiral.Kino.eval!(
~S"""
inl new () : state =
{
version = 2
seeds = "seeds" |> sm'.byte_slice |> near.new_vector
}
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
inl state = new ()
trace Verbose (fun () => "dice_contract") fun () => { state = #?*state }
trace Verbose (fun () => "") id
""",
timeout: 300_000
)
max_seeds
Spiral.Kino.eval!(
~S"""
inl max_seeds () : convert.unativeint =
100i32 |> convert.convert
""",
timeout: 300_000
)
contribute_seed
Spiral.Kino.eval!(
~S"""
inl contribute_seed (seeds : rust.ref (rust.mut' (near.vector u8))) (seed : am'.vec u8) : () =
seeds |> near.vector_extend seed
inl seed_excess_len =
(seeds |> rust.len |> fun x => x : u32 |> convert.i32) - (max_seeds () |> convert.i32)
if seed_excess_len > 0 then
inl seed_excess : am'.vec u8 =
!\\(seed_excess_len, $'"!seeds.drain(0..$0 as u32).collect::<Vec<_>>()"')
trace Debug
fun () => "dice_contract.contribute_seed"
fun () => { seed_excess_len seed_excess = #?*seed_excess }
trace Debug (fun () => "") (join id)
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
inl replicate n =
let rec 루프 i acc =
if i > n
then acc
else
inl i' = i % 10
inl i' =
if i' = 0
then i % limit.max
else i'
루프 (i + 1) (i' :: acc)
루프 1 []
|> listm.rev
|> listm'.box
|> listm'.to_array'
inl max_seeds : u32 = max_seeds () |> convert.convert
inl seeds = "" |> sm'.byte_slice |> near.new_vector |> rust.to_ref_mut
conv max_seeds * 1.2f64
|> replicate
|> am'.map_base convert.u8
|> am'.to_vec
|> contribute_seed seeds
seeds
|> rust.len
|> _assert_eq max_seeds
""",
timeout: 300_000
)
generate_random_number
Spiral.Kino.eval!(
~S"""
inl generate_random_number
(seeds : rust.ref (rust.mut' (near.vector u8)))
(key : sm'.std_string)
(proof : sm'.std_string)
(max : u64)
: u64
=
inl seed = near.random_seed ()
inl epoch_height = near.epoch_height ()
inl block_height = near.block_height ()
inl block_timestamp = near.block_timestamp ()
inl account_balance = near.account_balance ()
inl signer_account_id = near.signer_account_id ()
inl predecessor_account_id = near.predecessor_account_id ()
inl entropy =
;[
seed
seeds |> rust.reref |> near.vector_to_vec
epoch_height |> am'.to_le_bytes |> am'.to_vec'
block_height |> am'.to_le_bytes |> am'.to_vec'
block_timestamp |> am'.to_le_bytes |> am'.to_vec'
account_balance |> near.as_yoctonear |> am'.to_le_bytes |> am'.to_vec'
signer_account_id |> am'.as_bytes |> am'.to_vec''
predecessor_account_id |> am'.as_bytes |> am'.to_vec''
proof |> sm'.into_bytes
key |> sm'.into_bytes
]
|> am'.to_vec
|> rust.concat
inl hash_u8 = entropy |> near.keccak512
hash_u8 |> contribute_seed seeds
inl rolls_list =
hash_u8
|> am'.from_vec_base
|> am'.to_list_base'
|> listm'.unbox
|> stream.from_list
|> lib.dice.rotate_numbers 6
|> stream.to_list
trace Debug
fun () => "dice_contract.generate_random_number"
fun () => {
max
key
proof
block_timestamp
block_height
epoch_height
account_balance = #?*account_balance
signer_account_id = signer_account_id |> sm'.to_string'
predecessor_account_id = predecessor_account_id |> sm'.to_string'
seed = #?*seed
seeds = #?*seeds
entropy_len = entropy |> am'.vec_len
entropy = #?*entropy
hash_u8 = #?*hash_u8
rolls = rolls_list |> listm'.box |> listm'.to_array' |> am'.to_vec |> sm'.format_debug
}
inl sequential_roll = rolls_list |> lib.dice.create_sequential_roller
inl result = lib.dice.roll_progressively sequential_roll true max
trace Debug (fun () => "") (join id)
result
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -cd near-token
2000
|> generate_random_number
("" |> sm'.byte_slice |> near.new_vector |> rust.to_ref_mut)
("" |> sm'.to_std_string)
("" |> sm'.to_std_string)
|> _assert_gt 0
""",
timeout: 300_000
)
roll_within_bounds
Spiral.Kino.eval!(
~S"""
inl roll_within_bounds (max : u64) (rolls : am'.vec u8) : optionm'.option' u64 =
inl result =
rolls
|> am'.from_vec_base
|> am'.to_list_base'
|> listm'.unbox
|> lib.dice.roll_within_bounds max
|> optionm'.box
trace Debug
fun () => "dice_contract.roll_within_bounds"
fun () => { max rolls = #?*rolls; result = #?*result }
trace Debug (fun () => "") (join id)
result
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
inl rolls = ;[ 1; 5; 4; 4; 5 ] |> am'.to_vec
rolls
|> roll_within_bounds 2000
|> _assert_eq' (optionm'.some' 995)
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
inl rolls = ;[ 2; 2; 6; 4; 5 ] |> am'.to_vec
rolls
|> roll_within_bounds 2000
|> _assert_eq' (optionm'.some' 1715)
""",
timeout: 300_000
)
main
Spiral.Kino.eval!(
~S"""
///> _
inl main_native () : () =
global "#[derive(near_sdk::PanicOnDefault, borsh::BorshDeserialize, borsh::BorshSerialize)]\npub struct OldState {\n version: u32,\n seeds: near_sdk::store::vec::Vector<u8>,\n}"
global "#[near_sdk::near_bindgen]\n#[derive(near_sdk::PanicOnDefault, borsh::BorshDeserialize, borsh::BorshSerialize)]\npub struct State((u32, near_sdk::store::vec::Vector<u8>));"
global "impl From<OldState> for State {\n fn from(old_state: OldState) -> Self {\n Self((old_state.version + 1, old_state.seeds))\n }\n}"
global "#[near_sdk::near_bindgen]\nimpl State {\n #[init]\n pub fn new() -> Self {\n Self(dice_contract_new())\n }\n pub fn contribute_seed(&mut self, seed: Vec<u8>) {\n dice_contract_contribute_seed(&mut self.0.1, seed)\n }\n pub fn contribute_seed_borsh(&mut self, #[serializer(borsh)] seed: Vec<u8>) {\n self.contribute_seed(seed)\n }\n pub fn generate_random_number(&mut self, key: String, proof: String, max: u64) -> u64 {\n dice_contract_generate_random_number(&mut self.0.1, key, proof, max)\n }\n pub fn roll_within_bounds(&self, max: u64, rolls: Vec<u8>) -> Option<u64> {\n dice_contract_roll_within_bounds(max, rolls)\n }\n #[result_serializer(borsh)]\n pub fn roll_within_bounds_borsh(\n &self,\n #[serializer(borsh)] max: u64,\n #[serializer(borsh)] rolls: Vec<u8>,\n ) -> Option<u64> {\n self.roll_within_bounds(max, rolls)\n }\n}"
inl quiet () : () = set_trace_level Info
!!!!Export("dice_contract_new", ((fun () => inl () = quiet () in inl x = new () in x.version, x.seeds) : () -> u32 * near.vector u8))
!!!!Export("dice_contract_contribute_seed", ((fun (seeds, seed) => inl () = quiet () in contribute_seed seeds seed) : rust.ref (rust.mut' (near.vector u8)) * am'.vec u8 -> ()))
!!!!Export("dice_contract_generate_random_number", ((fun (seeds, key, proof, max) => inl () = quiet () in generate_random_number seeds key proof max) : rust.ref (rust.mut' (near.vector u8)) * sm'.std_string * sm'.std_string * u64 -> u64))
!!!!Export("dice_contract_roll_within_bounds", ((fun (max, rolls) => inl () = quiet () in roll_within_bounds max rolls) : u64 * am'.vec u8 -> optionm'.option' u64))
inl main () =
if is_rust ()
then main_native ()
else ()
""",
timeout: 300_000
)