chat_contract
Spiral.Kino.eval!(
~S"""
open rust
open rust.rust_operators
open sm'_operators
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test static
open testing
""",
timeout: 300_000
)
chat_contract
state
Spiral.Kino.eval!(
~S"""
nominal alias_accounts = $'std::collections::HashMap<String, (u64, u32)>'
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 alias_accounts
}
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
()
""",
timeout: 300_000
)
new
Spiral.Kino.eval!(
~S"""
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
}
""",
timeout: 300_000
)
is_valid_alias
Spiral.Kino.eval!(
~S"""
inl is_valid_alias (alias : sm'.std_string) : bool =
$'{ let alias: &str = &(!alias); alias.len() > 0 && alias.len() < 64 && \!alias.starts_with(\'-\') && \!alias.ends_with(\'-\') && alias.chars().all(|c| c.is_alphanumeric() || c == \'-\') }' : bool
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
""
|> sm'.to_std_string
|> is_valid_alias
|> _assert_eq false
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
"a-"
|> sm'.to_std_string
|> is_valid_alias
|> _assert_eq false
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c
"a-a"
|> sm'.to_std_string
|> is_valid_alias
|> _assert_eq true
""",
timeout: 300_000
)
generate_cid
Spiral.Kino.eval!(
~S"""
inl generate_cid (content : am'.vec u8) : sm'.std_string =
$'{ let mut varint = unsigned_varint::encode::u64_buffer(); let codec_bytes = unsigned_varint::encode::u64(0x55, &mut varint).to_vec(); let mut hasher: sha2::Sha256 = sha2::Digest::new(); sha2::Digest::update(&mut hasher, &(!content)); let multihash: Vec<u8> = [0x12u8, 32].into_iter().chain(sha2::Digest::finalize(hasher).into_iter()).collect(); let cid_bytes = [vec\![1u8], codec_bytes, multihash].concat(); multibase::encode(multibase::Base::Base32Lower, &cid_bytes) }' : sm'.std_string
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust -c -d multibase='=0.9.1' sha2 unsigned-varint
;[]
|> am'.to_vec
|> generate_cid
|> sm'.from_std_string
|> _assert_eq "bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku"
""",
timeout: 300_000
)
claim_alias
Spiral.Kino.eval!(
~S"""
inl panic_str (text : string) : () =
$'near_sdk::env::panic_str(&*!text)' : ()
inl claim_alias
(account_set : rust.ref (rust.mut' (near.iterable_set near.account_id)))
(alias_set : rust.ref (rust.mut' (near.iterable_set sm'.std_string)))
(account_map : rust.ref (rust.mut' (near.lookup_map near.account_id sm'.std_string)))
(alias_map : rust.ref (rust.mut' (near.lookup_map sm'.std_string alias_accounts)))
(alias : sm'.std_string)
: ()
=
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
panic_str "chat_contract.claim_alias / invalid alias"
inl account_alias : optionm'.option' sm'.std_string =
$'(!account_map).get(&(!signer_account_id)).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' |> optionm'.box |> sm'.format_debug }
match account_alias' with
| Some account_alias =>
$'{ if let Some(accounts) = (!alias_map).get_mut(&(!account_alias)) { accounts.remove(&(!signer_account_id)); } }' : ()
| None => ()
$'{ (!account_map).insert((!signer_account_id).clone(), (!alias).clone()); }' : ()
account_set |> near.iterable_set_insert signer_account_id |> ignore
alias_set |> near.iterable_set_insert alias |> ignore
$'{ let accounts = match (!alias_map).get(&(!alias)) { None => { let mut accounts = std::collections::HashMap::new(); accounts.insert((!signer_account_id).clone(), (!block_timestamp, 0u32)); accounts } Some(previous) => { let mut ordered = previous.iter().collect::<Vec<_>>(); ordered.sort_unstable_by_key(|(_, (_, index))| *index); let mut accounts = ordered.iter().enumerate().map(|(i, (account_id, (timestamp, _)))| ((*account_id).clone(), (*timestamp, i as u32))).collect::<std::collections::HashMap<_, _>>(); accounts.insert((!signer_account_id).clone(), (!block_timestamp, ordered.len() as u32)); accounts } }; (!alias_map).insert((!alias).clone(), accounts); }' : ()
""",
timeout: 300_000
)
Spiral.Kino.eval!(
~S"""
///- --test
///> rust "-c=-e=\"chat_contract.claim_alias / invalid alias\""
inl state = new ()
""
|> sm'.to_std_string
|> claim_alias
(state.account_set |> rust.to_ref_mut)
(state.alias_set |> rust.to_ref_mut)
(state.account_map |> rust.to_ref_mut)
(state.alias_map |> rust.to_ref_mut)
""",
timeout: 300_000
)
get_account_info
Spiral.Kino.eval!(
~S"""
nominal account_info = $'Option<(String, u64, u32)>'
inl get_account_info
(account_map : rust.ref (near.lookup_map near.account_id sm'.std_string))
(alias_map : rust.ref (near.lookup_map sm'.std_string alias_accounts))
(account_id : near.account_id)
: account_info
=
inl result : account_info =
$'(!account_map).get(&(!account_id)).and_then(|alias| (!alias_map).get(alias).and_then(|accounts| accounts.get(&(!account_id)).map(|(timestamp, index)| (alias.clone(), *timestamp, *index))))'
trace Debug
fun () => "chat_contract.get_account_info"
fun () => { account_id result = #?*result }
result
""",
timeout: 300_000
)
get_alias_map
Spiral.Kino.eval!(
~S"""
nominal alias_accounts_option = $'Option<std::collections::HashMap<String, (u64, u32)>>'
inl get_alias_map
(alias_map : rust.ref (near.lookup_map sm'.std_string alias_accounts))
(alias : sm'.std_string)
: alias_accounts_option
=
trace Debug
fun () => "chat_contract.get_alias_map"
fun () => { alias }
$'(!alias_map).get(&(!alias)).cloned()' : alias_accounts_option
""",
timeout: 300_000
)
main
Spiral.Kino.eval!(
~S"""
///> _
inl main_native () : () =
global "#[near_sdk::near_bindgen]\n#[derive(near_sdk::PanicOnDefault, borsh::BorshDeserialize, borsh::BorshSerialize)]\npub struct State((u32, near_sdk::store::IterableSet<String>, near_sdk::store::IterableSet<String>, near_sdk::store::LookupMap<String, String>, near_sdk::store::LookupMap<String, std::collections::HashMap<String, (u64, u32)>>));"
global "#[near_sdk::near_bindgen]\nimpl State {\n #[init]\n pub fn new() -> Self {\n Self(chat_contract_new())\n }\n pub fn is_valid_alias(&self, alias: String) -> bool {\n chat_contract_is_valid_alias(alias)\n }\n pub fn generate_cid(&self, content: Vec<u8>) -> String {\n chat_contract_generate_cid(content)\n }\n #[result_serializer(borsh)]\n pub fn generate_cid_borsh(&self, #[serializer(borsh)] content: Vec<u8>) -> String {\n self.generate_cid(content)\n }\n pub fn claim_alias(&mut self, alias: String) {\n let state = &mut self.0;\n chat_contract_claim_alias(&mut state.1, &mut state.2, &mut state.3, &mut state.4, alias)\n }\n pub fn get_account_info(&self, account_id: near_sdk::AccountId) -> Option<(String, u64, u32)> {\n chat_contract_get_account_info(&self.0.3, &self.0.4, account_id.to_string())\n }\n pub fn get_alias_map(&self, alias: String) -> Option<std::collections::HashMap<String, (u64, u32)>> {\n chat_contract_get_alias_map(&self.0.4, alias)\n }\n #[result_serializer(borsh)]\n pub fn get_alias_map_borsh(&self, #[serializer(borsh)] alias: String) -> Option<std::collections::HashMap<String, (u64, u32)>> {\n self.get_alias_map(alias)\n }\n}"
inl quiet () : () = set_trace_level Info
!!!!Export("chat_contract_new", ((fun () => inl () = quiet () in inl x = new () in x.version, x.account_set, x.alias_set, x.account_map, x.alias_map) : () -> u32 * near.iterable_set near.account_id * near.iterable_set sm'.std_string * near.lookup_map near.account_id sm'.std_string * near.lookup_map sm'.std_string alias_accounts))
!!!!Export("chat_contract_is_valid_alias", ((fun alias => inl () = quiet () in is_valid_alias alias) : sm'.std_string -> bool))
!!!!Export("chat_contract_generate_cid", ((fun content => inl () = quiet () in generate_cid content) : am'.vec u8 -> sm'.std_string))
!!!!Export("chat_contract_claim_alias", ((fun (account_set, alias_set, account_map, alias_map, alias) => inl () = quiet () in claim_alias account_set alias_set account_map alias_map alias) : rust.ref (rust.mut' (near.iterable_set near.account_id)) * rust.ref (rust.mut' (near.iterable_set sm'.std_string)) * rust.ref (rust.mut' (near.lookup_map near.account_id sm'.std_string)) * rust.ref (rust.mut' (near.lookup_map sm'.std_string alias_accounts)) * sm'.std_string -> ()))
!!!!Export("chat_contract_get_account_info", ((fun (account_map, alias_map, account_id) => inl () = quiet () in get_account_info account_map alias_map account_id) : rust.ref (near.lookup_map near.account_id sm'.std_string) * rust.ref (near.lookup_map sm'.std_string alias_accounts) * near.account_id -> account_info))
!!!!Export("chat_contract_get_alias_map", ((fun (alias_map, alias) => inl () = quiet () in get_alias_map alias_map alias) : rust.ref (near.lookup_map sm'.std_string alias_accounts) * sm'.std_string -> alias_accounts_option))
inl main () =
if is_rust ()
then main_native ()
else ()
""",
timeout: 300_000
)