# How to run wasm applications with ssvm-napi-storage (Wasm-Bindgen and interpreter mode) ## Environment Setup for Rust, Nodejs, and ssvmup ```bash $ sudo apt-get update $ sudo apt-get -y upgrade $ sudo apt install build-essential curl wget git vim libboost-all-dev $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh $ source $HOME/.cargo/env $ cargo install cargo-wasi $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash $ export NVM_DIR="$HOME/.nvm" $ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" $ [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" $ nvm install v14.2.0 $ nvm use v14.2.0 $ npm i -g ssvmup ``` ## Example 1. Hello Application ### Create a new rust library project ```bash cargo new --lib hello cd hello ``` ### Modify the cargo config file Add the following to the `Cargo.toml` file. ```toml [lib] name = "hello" path = "src/lib.rs" crate-type =["cdylib"] [dependencies] wasm-bindgen = "=0.2.61" ``` ### Write Rust code Below is the entire content of the `src/lib.rs` file. ```rust use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn say(s: String) -> String { let r = String::from("hello "); return r + &s; } #[wasm_bindgen] pub fn add(a: i32, b: i32) -> i32 { return a + b; } #[wasm_bindgen] pub fn reverse(v: Vec) -> Vec { let mut r = v.clone(); r.reverse(); return r; } ``` In addition to the above code, functions like the example below can deliberately parse incoming JSON string data. This is an additional say example that uses valid JSON instead of just plain string. Please note, in addition to the dependencies above, you will now also need to add `serde_json = "1.0.53"` to your Cargo.toml file for the following `say_with_json` demonstration to work. ```rust use serde_json::json; use wasm_bindgen::prelude::*; use serde_json::{Result, Value}; #[wasm_bindgen] pub fn say_with_json(s: String) -> String { let json_as_value: Value = serde_json::from_str(&s).unwrap(); let first_word = String::from("Hello "); let concatenation = first_word + &serde_json::to_string(&json_as_value["name"]).unwrap(); let response_object = json!({ "result": concatenation }); return serde_json::to_string(&response_object).unwrap(); } ``` When given `{"name": "Tim"}` this `say_with_json` function returns `Hello Tim` wrapped in a response object (as valid JSON) like this `{"ssvm_response": ["{\"result\": \"Hello Tim\"}"]}` ### Build the WASM bytecode with ssvmup ```bash ssvmup build ``` After building, our target wasm file is located at `pkg/hello_bg.wasm`. ### Install SSVM addon for your application ```bash npm install ssvm-storage ``` or if you want to build from source: ```bash export CXX=g++-9 npm install --build-from-source https://github.com/second-state/ssvm-napi-storage ``` ### Use SSVM-storage addon After installing SSVM addon, we could now interact with `hello_bg.wasm` generated by wasm-pack in Node.js. Make sure you use the corresponding VM method to the rust return type. - Create a new folder at any path you want. (e.g. `mkdir application`) - Copy `hello_bg.wasm` into your application directory. (e.g. `cp hello_gb.wasm `) - Create js file `main.js` (or whatever you like) with the following content: ```javascript var ssvm = require('ssvm-storage'); var vm = new ssvm.VM("hello_bg.wasm"); var ret = vm.RunString("say", "world"); console.log(ret); ret = vm.RunInt("add", 3, 4); console.log(ret); ret = vm.RunUint8Array("reverse", Uint8Array.from([1, 2, 3, 4, 5, 6])); console.log(ret); ret = vm.RunInt("add", 999, -111); console.log(ret); ret = vm.RunUint8Array("reverse", Uint8Array.from([60, 50, 40, 30, 20, 10])); console.log(ret); ``` ### Execute and check results ```bash $ node main.js hello world 7 Uint8Array [ 6, 5, 4, 3, 2, 1 ] 888 Uint8Array [ 10, 20, 30, 40, 50, 60 ] ```