Powered by AppSignal & Oban Pro

chat_contract

apps/chat/contract/chat_contract.livemd

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
)