Powered by AppSignal & Oban Pro

spiral_wasm

apps/wasm/spiral_wasm.livemd

spiral_wasm

Spiral.Kino.eval!(
  ~S"""
  open rust.rust_operators
  open rust
  open sm'_operators
  """,
  timeout: 300_000
)

spiral_wasm

get_args

Spiral.Kino.eval!(
  ~S"""
  inl get_args () =
      {
          exception = "exception", 'e'
          trace_level = "trace_level", 't'
          wasm = "wasm", 'w'
      }
  """,
  timeout: 300_000
)

get_command

Spiral.Kino.eval!(
  ~S"""
  let get_command () =
      ###"command"
      |> runtime.new_command
      |> runtime.command_args_override_self true
      |> runtime.command_init_arg (get_args () .exception) (
          runtime.arg_num_args_range (
              runtime.new_value_range
                  true
                  (am'.End eval)
                  (am'.End fun _ => (1i32 |> convert.convert : convert.unativeint))
          )
          >> runtime.arg_require_equals true
          >> runtime.arg_default_missing_value ""
      )
      |> runtime.command_init_arg (get_args () .trace_level) (
          real runtime.arg_union `trace_level ignore
      )
      |> runtime.command_init_arg (get_args () .wasm) (
          runtime.arg_required true
      )
  """,
  timeout: 300_000
)

run

Spiral.Kino.eval!(
  ~S"""
  let rec run
      (matches : runtime.arg_matches)
      : async.future_pin (
          resultm.result'
              u8
              resultm.anyhow_error
      )
      =
      fun () =>
          inl wasm_path =
              matches
              |> runtime.matches_get_one (get_args () .wasm |> fst)
              |> optionm'.unbox
              |> optionm.value
              |> sm'.from_std_string

          trace Verbose (fun () => "spiral_wasm.run") fun () => { wasm_path }

          inl wasm = wasm_path |> file_system.read |> resultm.try'

          let fn (retry : u8) =
              fun () =>
                  inl worker = near_workspaces.sandbox_worker () |> resultm.try'
                  inl contract = worker |> near_workspaces.dev_deploy wasm |> async.await |> resultm.try'

                  trace Verbose (fun () => "spiral_wasm.run") fun () => { retry worker contract }

                  inl result =
                      contract
                      |> near_workspaces.call "state_main"
                      |> near_workspaces.gas (near_workspaces.from_tgas 300)
                      |> near_workspaces.transact
                      |> async.await
                      |> resultm.try'

                  trace Verbose (fun () => "spiral_wasm.run") fun () => { retry result }

                  result
                  |> near_workspaces.logs
                  |> am'.vec_map sm'.ref_to_std_string
                  |> am'.vec_for_each console.write_line

                  trace_raw Info (fun () => " ")
                  result |> near_workspaces.print_usd retry

                  inl result2 = result |> near_workspaces.into_result

                  trace Verbose (fun () => "spiral_wasm.run") fun () => { result2 }

                  inl receipt_failures = result |> near_workspaces.receipt_failures
                  inl receipt_failures_len = receipt_failures |> am'.vec_len |> convert.i32

                  trace Verbose
                      fun () => "spiral_wasm.run"
                      fun () => { receipt_failures_len receipt_failures }

                  inl receipt_outcomes = result |> near_workspaces.receipt_outcomes
                  inl receipt_outcomes_len = receipt_outcomes |> am'.vec_len |> convert.i32

                  trace Verbose
                      fun () => "spiral_wasm.run"
                      fun () => { receipt_outcomes_len receipt_outcomes }

                  inl json = result |> near_workspaces.json

                  trace Verbose (fun () => "spiral_wasm.run") fun () => { json }

                  inl borsh = result |> near_workspaces.borsh

                  trace Verbose (fun () => "spiral_wasm.run") fun () => { borsh }

                  inl error = #?{ receipt_outcomes_len retry receipt_failures }
                  if receipt_failures_len > 0
                  then (Ok (Some error) : _ _ resultm.anyhow_error) |> resultm.box
                  elif receipt_outcomes_len > 1
                  then (Ok None : _ _ resultm.anyhow_error) |> resultm.box
                  else error |> resultm.anyhow_error |> resultm.err
              |> async.new_future_move

          let rec 루프 (retry : u8) =
              inl max = 15
              inl init (error : _ string) =
                  fun () =>
                      { retry error }
                  |> async.new_future_move
              fun () =>
                  inl result =
                      fn retry
                      |> async.await
                      |> resultm.map_error' sm'.format'
                      |> resultm.unbox
                  match result with
                  | Ok (None) =>
                      init None
                      |> async.await
                      |> Ok
                  | Ok (Some error) =>
                      trace Critical (fun () => "spiral_wasm.run / Ok (Some error)") fun () => { retry error }
                      init (Some error)
                      |> async.await
                      |> Error
                  | Error error when retry >= max =>
                      trace Warning (fun () => "spiral_wasm.run / Error error") fun () => { retry error }
                      trace_raw Warning (fun () => "\n")
                      init None
                      |> async.await
                      |> Ok
                  | Error error =>
                      trace Warning (fun () => "spiral_wasm.run / Error error") fun () => { retry error }
                      trace_raw Warning (fun () => "\n")
                      루프 (retry + 1) |> async.await
              |> async.new_future_move
          inl retries = 루프 1 |> async.await

          trace Verbose (fun () => "spiral_wasm.run") fun () => { retries }

          match retries with
          | Ok { retry } => Ok retry |> resultm.box
          | Error { retry error } => #?{ retries error } |> resultm.anyhow_error |> resultm.err

      |> async.new_future_move
  """,
  timeout: 300_000
)

main

Spiral.Kino.eval!(
  ~S"""
  ///> _

  inl run_main (args : array_base string) : i32 =
      inl command = get_command ()
      inl arg_matches = command |> runtime.command_get_matches

      inl trace_level =
          arg_matches
          |> runtime.matches_get_one (get_args () .trace_level |> fst)
          |> optionm'.unbox
          |> optionm.map (
              sm'.from_std_string
              >> reflection.union_try_pick
          )
          |> optionm'.flatten
          |> optionm'.default_value Verbose

      inl trace_state = get_trace_state_or_init (Some trace_level)

      trace Verbose
          fun () => "spiral_wasm.main"
          fun () => { args }

      inl exception =
          arg_matches
          |> runtime.matches_get_one (get_args () .exception |> fst)
          |> optionm'.map (sm'.from_std_string >> sm'.trim_start [ '\\' ] >> sm'.trim_end [ '\\' ])
          |> optionm'.unbox

      inl result =
          arg_matches
          |> run
          |> async.block_on_tokio
          |> resultm.map_error' sm'.format'

      match result |> rust.clone_rust |> resultm.unbox, exception with
      | Ok retries, Some exception =>
          ($'$"spiral_wasm.main / retries: {!retries} / exception: \'{!exception}\'"' : string)
          |> resultm.err |> resultm.unwrap'
      | Error _error, Some ("") =>
          ()
      | Error error, Some exception when error |> sm'.from_std_string |> sm'.contains exception =>
          ()
      | Error error, Some exception =>
          ($'$"spiral_wasm.main / exception: \'{!exception}\' / error: {!error}"' : string)
          |> resultm.err |> resultm.unwrap'
      | Ok _retries, _ =>
          ()
      | Error _error, _ =>
          result |> resultm.unwrap' |> ignore

      0i32

  /// F#: `main` for the Fable build. Native Rust (`--backend Rust`, see build.ps1): runs `run_main` with the process args.
  inl main () =
      backend_switch {
          Fsharp = fun () => $'let main args = !run_main args' : ()
          Rust = fun () =>
              inl args =
                  $'Rc::new(RefCell::new(std::env::args().skip(1).map(|x| Rc::<str>::from(x)).collect::<Vec<Rc<str>>>()))'
                  : array_base string
              run_main args |> ignore
      } : ()
  """,
  timeout: 300_000
)