/// # chat_contract open rust open rust.rust_operators /// ## chat_contract /// ### state type state = { version : u32 account_set : near.iterable_set near.account_id alias_set : near.iterable_set sm'.std_string account_map : near.lookup_map near.account_id sm'.std_string alias_map : near.lookup_map sm'.std_string (mapm.hash_map near.account_id (u64 * u32)) } /// ### new inl new () : state = { version = 2 account_set = "account_set" |> sm'.byte_slice |> near.new_iterable_set alias_set = "alias_set" |> sm'.byte_slice |> near.new_iterable_set account_map = "account_map" |> sm'.byte_slice |> near.new_lookup_map alias_map = "alias_map" |> sm'.byte_slice |> near.new_lookup_map } /// ### is_valid_alias inl is_valid_alias (alias : sm'.std_string) : bool = inl alias' = alias |> sm'.from_std_string inl alias_len = alias' |> sm'.length alias_len > 0i32 && alias_len < 64 && (alias' |> sm'.starts_with "-" |> not) && (alias' |> sm'.ends_with "-" |> not) && (alias' |> sm'.as_str |> sm'.chars |> iter.all (fun c => (c |> sm'.char_is_alphanumeric) || c = '-')) /// ### generate_cid inl generate_cid (content : am'.vec u8) : sm'.std_string = !\($'" fn encode_u64(value: u64) -> Vec { //"') : () !\($'" let mut buffer = unsigned_varint::encode::u64_buffer(); //"') : () !\($'" unsigned_varint::encode::u64(value, &mut buffer).to_vec() //"') : () !\($'" } //"') : () !\($'" fn sha256_hash(content: &[u8]) -> Vec { //"') : () !\($'" let mut hasher: sha2::Sha256 = sha2::Digest::new(); //"') : () !\($'" sha2::Digest::update(&mut hasher, content); //"') : () !\($'" sha2::Digest::finalize(hasher).to_vec() //"') : () !\($'" } //"') : () !\($'" let version: u8 = 1; //"') : () !\($'" let codec_raw: u64 = 0x55; //"') : () !\($'" let codec_bytes = encode_u64(codec_raw); //"') : () !\($'" let hash_result = sha256_hash(&!content); //"') : () !\($'" let multihash = std::iter::once(0x12) //"') : () !\($'" .chain(std::iter::once(32)) //"') : () !\($'" .chain(hash_result.into_iter()) //"') : () !\($'" .collect(); //"') : () !\($'" let cid_bytes = [vec\![version], codec_bytes, multihash].concat(); //"') : () !\($'" let result = multibase::encode(multibase::Base::Base32Lower, &cid_bytes); //"') : () !\($'"result"') /// ### claim_alias inl claim_alias (state : rust.ref (rust.mut' state)) (alias : sm'.std_string) : () = inl account_set : rust.ref (rust.mut' (near.iterable_set near.account_id)) = !\($'$"&mut !state.1"') inl alias_set : rust.ref (rust.mut' (near.iterable_set sm'.std_string)) = !\($'$"&mut !state.2"') inl account_map : rust.ref (rust.mut' (near.lookup_map near.account_id sm'.std_string)) = !\($'$"&mut !state.3"') inl alias_map : rust.ref (rust.mut' (near.lookup_map sm'.std_string (mapm.hash_map near.account_id (u64 * u32)))) = !\($'$"&mut !state.4"') inl signer_account_id = near.signer_account_id () inl predecessor_account_id = near.predecessor_account_id () inl block_timestamp = near.block_timestamp () trace Debug fun () => "chat_contract.claim_alias" fun () => { alias block_timestamp signer_account_id = signer_account_id |> sm'.to_string' predecessor_account_id = predecessor_account_id |> sm'.to_string' } if alias |> is_valid_alias |> not then near.panic_str "chat_contract.claim_alias / invalid alias" . true else false |> ignore inl account_alias = account_map |> near.lookup_get signer_account_id |> optionm'.cloned match account_alias |> optionm'.unbox with | Some account_alias when account_alias =. alias => trace Warning fun () => "chat_contract.claim_alias / alias already claimed" fun () => { account_alias = account_alias |> sm'.format_debug } | account_alias' => trace Debug fun () => "chat_contract.claim_alias" fun () => { account_alias = account_alias |> sm'.format_debug } match account_alias' with | Some account_alias => !\($'" !alias_map //"') : () !\($'" .get_mut(&!account_alias) //"') : () !\($'" .unwrap() //"') : () !\\(signer_account_id, $'" .remove(&$0); //"') : () | None => () !\\((signer_account_id, alias), $'" !account_map.insert($0.clone(), $1.clone()); //"') : () account_set |> near.iterable_set_insert signer_account_id |> ignore alias_set |> near.iterable_set_insert alias |> ignore !\\(alias, $'" let new_alias_account_map = match !alias_map.get(&$0) { //"') : () !\($'" None => { //"') : () !\($'" let mut new_map = std::collections::HashMap::new(); //"') : () !\\((signer_account_id, block_timestamp), $'" new_map.insert($0, ($1, 0u32)); //"') : () !\($'" new_map //"') : () !\($'" } //"') : () !\($'" Some(accounts) => { //"') : () !\($'" let mut accounts_vec = accounts.iter().collect::>(); //"') : () !\($'" accounts_vec.sort_unstable_by_key(|(_, (_, index))| index); //"') : () !\($'" let mut new_map = accounts_vec //"') : () !\($'" .iter() //"') : () !\($'" .enumerate() //"') : () !\($'" .map(|(i, (signer_account_id, (timestamp, _)))| { //"') : () !\($'" ((*signer_account_id).clone(), (*timestamp, i as u32)) //"') : () !\($'" }) //"') : () !\($'" .collect::>(); //"') : () !\\(signer_account_id, $'" new_map.insert($0, (!block_timestamp, accounts_vec.len() as u32)); //"') : () !\($'" new_map //"') : () !\($'" } //"') : () !\($'" }; //"') : () !\\(alias, $'" !alias_map.insert($0, new_alias_account_map); //"') : () /// ### get_account_info inl get_account_info (state : rust.ref state) (account_id : near.account_id) : optionm'.option' (sm'.std_string * (u64 * u32)) = inl account_map : rust.ref (near.lookup_map near.account_id sm'.std_string) = !\($'$"&!state.3"') inl alias_map : rust.ref (near.lookup_map sm'.std_string (mapm.hash_map near.account_id (u64 * u32))) = !\($'$"&!state.4"') (!\\(account_id, $'"true; let result = !account_map.get(&$0).and_then(|alias| { //"') : bool) |> ignore (!\($'"true; !alias_map.get(alias).map(|accounts| { //"') : bool) |> ignore (!\($'"true; let result = (alias.clone(), *accounts.get(&!account_id).unwrap()); //"') : bool) |> ignore (!\($'"true; (result.0, result.1.0, result.1.1) }) }); //"') : bool) |> ignore inl result = !\($'"result"') trace Debug fun () => "chat_contract.get_account_info" fun () => { account_id result } trace Debug (fun () => "") id result /// ### main ///! _ inl main () = !\($'"} //"') : () !\($'"\#[near_sdk::near_bindgen] //"') : () !\($'"\#[derive( //"') : () !\($'" near_sdk::PanicOnDefault, //"') : () !\($'" borsh::BorshDeserialize, //"') : () !\($'" borsh::BorshSerialize, //"') : () !\($'")] //"') : () !\($'"pub struct State ( //"') : () !\($'"/*"') : () (null () : rust.type_emit state) |> ignore !\($'"*/ )"') : () inl new_ () = !\($'"\#[init] //"') : () !\($'"pub fn new() -> Self { // 1"') : () (!\($'"true; /*"') : bool) |> ignore (null () : rust.type_emit ()) |> ignore (!\($'"true; */"') : bool) |> ignore inl result = new () $'let _result = !result in _result |> (fun x -> Fable.Core.RustInterop.emitRustExpr x $"Self($0) // x") // 2' : () !\($'"} // 2."') : () !\($'"} // 1."') : () 2 inl is_valid_alias () = !\($'"fn is_valid_alias(alias: String) -> bool { //"') : () inl alias = !\($'$"alias"') inl result = alias |> is_valid_alias $'let _result = !result in _result |> (fun x -> Fable.Core.RustInterop.emitRustExpr x "$0 }") // 2' : () !\($'"} //"') : () 1 inl generate_cid () = !\($'"pub fn generate_cid( //"') : () !\($'" &self, //"') : () !\($'" content: Vec, //"') : () !\($'") -> String { //"') : () inl content = !\($'$"content"') inl result = generate_cid content $'let _result = !result in _result |> (fun x -> Fable.Core.RustInterop.emitRustExpr x "$0 }") // 2' : () !\($'"} //"') : () 2 inl generate_cid_borsh () = !\($'"\#[result_serializer(borsh)] //"') : () !\($'"pub fn generate_cid_borsh( //"') : () !\($'" &self, //"') : () !\($'" \#[serializer(borsh)] content: Vec, //"') : () !\($'") -> String { //"') : () !\($'" self.generate_cid(content) //"') : () !\($'"} //"') : () 1 inl claim_alias () = !\($'"pub fn claim_alias( //"') : () !\($'" &mut self, //"') : () !\($'" alias: String, //"') : () !\($'") { //"') : () inl state = !\($'$"&mut self.0"') inl alias = !\($'$"alias"') inl result = claim_alias state alias trace Debug (fun () => "") (join id) !\($'"} //"') : () !\($'"} //"') : () !\($'"} //"') : () 3 inl get_account_info () = !\($'"pub fn get_account_info( //"') : () !\($'" &self, //"') : () !\($'" account_id: near_sdk::AccountId, //"') : () !\($'") -> Option<(String, u64, u32)> { //"') : () inl state = !\($'$"&self.0"') inl account_id : near.account_id = !\($'$"account_id"') inl result = account_id |> get_account_info state $'let _result = !result in _result |> (fun x -> Fable.Core.RustInterop.emitRustExpr x "$0 } // 4") // 3' : () !\($'"} // 1"') : () 1 inl get_alias_map () = !\($'"pub fn get_alias_map( //"') : () !\($'" &self, //"') : () !\($'" alias: String, //"') : () !\($'") -> Option> { //"') : () inl alias_map : rust.ref (near.lookup_map sm'.std_string (mapm.hash_map near.account_id (u64 * u32))) = !\($'$"&self.0.4"') inl alias : sm'.std_string = !\($'$"alias"') trace Debug fun () => "chat_contract.get_alias_map" fun () => { alias } trace Debug (fun () => "") (join id) !\\(alias, $'" !alias_map.get(&$0).cloned() //"') : () !\($'"} //"') : () !\($'"} //"') : () 2 inl get_alias_map_borsh () = !\($'"\#[result_serializer(borsh)] //"') : () !\($'"pub fn get_alias_map_borsh( //"') : () !\($'" &self, //"') : () !\($'" \#[serializer(borsh)] alias: String, //"') : () !\($'") -> Option> { //"') : () !\($'" self.get_alias_map(alias) //"') : () !\($'"} //"') : () 1 inl fns = [ new_ is_valid_alias generate_cid generate_cid_borsh claim_alias get_account_info get_alias_map get_alias_map_borsh ] // inl rec loop acc fns i = inl rec loop forall i {number} j {number}. (acc : i) (fns : list (() -> i)) (i : j) : i = match fns with | [] => acc | x :: xs => !\($'"\#[near_sdk::near_bindgen] //"') : () !\($'"impl State { //"') : () inl n = x () !\($'"} /* c"') : () // inl rec loop' i' = inl rec loop' forall t {number}. (i' : t) : () = if i' <> 1 // <= n then (!\($'"true; */ // ???? / i: !i / i\': !i' / acc: !acc / n: !n"') : bool) |> ignore else (!\($'"true; // ??? / i: !i / i\': !i' / acc: !acc / n: !n"') : bool) |> ignore loop' (i' + 1) loop' 1u8 loop (acc + n) xs (i + 1) inl n = loop 0u8 fns 1u8 // !\($'"/* a"') : () // !\($'"} // b"') : () !\($'"fn _main() //"') : () !\($'"{ { //"') : () inl rec loop' i' = if i' <= n then (!\($'"true; { (); // ?? / i\': !i' / n: !n"') : bool) |> ignore loop' (i' + 1) else (!\($'"true; { { (); // ? / i\': !i' / n: !n"') : bool) |> ignore // (!\($'"true; */ // ?? / i\': !i' / n: !n"') : bool) |> ignore loop' 1u8 inl main () = $'!main |> ignore' : ()