feat: introduce warp_contracts macro
gh-309
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
# Dependency directories
|
||||
|
||||
node_modules/
|
||||
crates/warp-contracts/target
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
214
crates/warp-contracts/Cargo.lock
generated
Normal file
214
crates/warp-contracts/Cargo.lock
generated
Normal file
@@ -0,0 +1,214 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "warp-contracts"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"warp-contracts-core",
|
||||
"warp-contracts-macro",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "warp-contracts-core"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "warp-contracts-macro"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"warp-contracts-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
34
crates/warp-contracts/Cargo.toml
Normal file
34
crates/warp-contracts/Cargo.toml
Normal file
@@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "warp-contracts"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
description = "Warp WASM contract utils for rust contracts"
|
||||
license = "MIT"
|
||||
documentation = "https://academy.warp.cc/docs/sdk/advanced/wasm"
|
||||
homepage = "https://warp.cc"
|
||||
repository = "https://github.com/warp-contracts/warp"
|
||||
keywords = ["warp", "smart-contract", "SmartWeave", "web3"]
|
||||
categories = ["api-bindings", "development-tools::ffi", "finance", "wasm"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = { workspace = true }
|
||||
wasm-bindgen-futures = { workspace = true }
|
||||
js-sys = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde-wasm-bindgen = { workspace = true }
|
||||
warp-contracts-macro = { version = "0.1.1", path = "warp-contracts-macro" }
|
||||
warp-contracts-core = { version = "0.1.1", path = "warp-contracts-core" }
|
||||
|
||||
[features]
|
||||
debug = ["warp-contracts-core/debug"]
|
||||
|
||||
[workspace]
|
||||
members = ["warp-contracts-macro", "warp-contracts-core"]
|
||||
|
||||
[workspace.dependencies]
|
||||
wasm-bindgen = "=0.2.84"
|
||||
wasm-bindgen-futures = { version = "=0.4.34" }
|
||||
js-sys = "=0.3.61"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde-wasm-bindgen = "=0.5.0"
|
||||
web-sys = { version = "=0.3.61" }
|
||||
23
crates/warp-contracts/README.md
Normal file
23
crates/warp-contracts/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Warp contracts
|
||||
|
||||
`warp-contracts` is an inherent part of [Warp SDK](https://github.com/warp-contracts/warp). This library allows for smooth integration with Warp implementation of SmartWeave protocol.
|
||||
|
||||
| Feature | Yes/No |
|
||||
| ---------------------- | ----------- |
|
||||
| Sandboxing | ✅ |
|
||||
| Foreign contract read | ✅ |
|
||||
| Foreign contract view | ✅ |
|
||||
| Foreign contract write | ✅ |
|
||||
| Arweave.utils | Soon |
|
||||
| Evolve | ✅ |
|
||||
| Logging from contract | ✅ |
|
||||
| Transaction data (1) | ✅ |
|
||||
| Block data (2) | ✅ |
|
||||
| Contract data (3) | ✅ |
|
||||
| Gas metering | ✅ |
|
||||
|
||||
Legend:
|
||||
- `Soon` - the technology is already there, we just need to find some time to add the missing features :-)
|
||||
- `(1)` - access current transaction data (id, owner, etc.)
|
||||
- `(2)` - access current block data (indep_hash, height, timestamp)
|
||||
- `(3)` - access current contract data (id, owner)
|
||||
4
crates/warp-contracts/src/README.md
Normal file
4
crates/warp-contracts/src/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# contract_utils module
|
||||
|
||||
This is a module with boilerplate code for each SmartWeave RUST contract.
|
||||
**Please don't modify it unless you 100% know what you are doing!**
|
||||
65
crates/warp-contracts/src/foreign_call.rs
Normal file
65
crates/warp-contracts/src/foreign_call.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
use super::js_imports::SmartWeave;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use serde_wasm_bindgen::from_value;
|
||||
use core::fmt::Debug;
|
||||
use warp_contracts_core::{
|
||||
handler_result::{ViewResult, WriteResult},
|
||||
methods::to_json_value,
|
||||
warp_result::{transmission::from_json, WarpResult},
|
||||
};
|
||||
|
||||
pub async fn read_foreign_contract_state<T: DeserializeOwned>(
|
||||
contract_address: &str,
|
||||
) -> Result<T, String> {
|
||||
match SmartWeave::read_contract_state(contract_address).await {
|
||||
Ok(s) => match from_value::<T>(s) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) => Err(format!("{e:?}")),
|
||||
},
|
||||
Err(e) => Err(format!("{e:?}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn view_foreign_contract_state<
|
||||
V: DeserializeOwned + Debug,
|
||||
I: Serialize,
|
||||
E: DeserializeOwned + Debug,
|
||||
>(
|
||||
contract_address: &str,
|
||||
input: I,
|
||||
) -> ViewResult<V, E> {
|
||||
let input = match to_json_value(&input) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return ViewResult::RuntimeError(format!("{e:?}")),
|
||||
};
|
||||
match SmartWeave::view_contract_state(contract_address, input).await {
|
||||
Ok(s) => match from_json::<V, E>(s) {
|
||||
WarpResult::WriteSuccess() => {
|
||||
ViewResult::RuntimeError("got WriteResponse for view call".to_owned())
|
||||
}
|
||||
v => v.into(),
|
||||
},
|
||||
Err(e) => ViewResult::RuntimeError(format!("{e:?}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn write_foreign_contract<I: Serialize, E: DeserializeOwned + Debug>(
|
||||
contract_address: &str,
|
||||
input: I,
|
||||
) -> WriteResult<(), E> {
|
||||
let input = match to_json_value(&input) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return WriteResult::RuntimeError(format!("{e:?}")),
|
||||
};
|
||||
let write_result = SmartWeave::write(contract_address, input).await;
|
||||
match write_result {
|
||||
Ok(s) => match from_json::<(), E>(s) {
|
||||
WarpResult::ViewSuccess(_) => {
|
||||
WriteResult::RuntimeError("got ViewResponse for write call".to_owned())
|
||||
}
|
||||
v => v.into(),
|
||||
},
|
||||
Err(e) => WriteResult::RuntimeError(format!("{e:?}")),
|
||||
}
|
||||
}
|
||||
96
crates/warp-contracts/src/js_imports.rs
Normal file
96
crates/warp-contracts/src/js_imports.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen]
|
||||
pub type Block;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Block, js_name = indep_hash)]
|
||||
pub fn indep_hash() -> String;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Block, js_name = height)]
|
||||
pub fn height() -> i32;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Block, js_name = timestamp)]
|
||||
pub fn timestamp() -> i32;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen]
|
||||
pub type Contract;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Contract, js_name = contractId)]
|
||||
pub fn id() -> String;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Contract, js_name = contractOwner)]
|
||||
pub fn owner() -> String;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen]
|
||||
pub type Transaction;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Transaction, js_name = id)]
|
||||
pub fn id() -> String;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Transaction, js_name = owner)]
|
||||
pub fn owner() -> String;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Transaction, js_name = target)]
|
||||
pub fn target() -> String;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen]
|
||||
pub type KV;
|
||||
|
||||
#[wasm_bindgen(catch, static_method_of = KV, js_name = kvGet)]
|
||||
pub async fn get(key: &str) -> Result<JsValue, JsValue>;
|
||||
|
||||
#[wasm_bindgen(catch, static_method_of = KV, js_name = kvPut)]
|
||||
pub async fn put(key: &str, value: JsValue) -> Result<(), JsValue>;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen]
|
||||
pub type SmartWeave;
|
||||
|
||||
#[wasm_bindgen(catch, static_method_of = SmartWeave, js_name = readContractState)]
|
||||
pub async fn read_contract_state(contract_id: &str) -> Result<JsValue, JsValue>;
|
||||
|
||||
#[wasm_bindgen(catch, static_method_of = SmartWeave, js_name = viewContractState)]
|
||||
pub async fn view_contract_state(contract_id: &str, input: JsValue)
|
||||
-> Result<JsValue, JsValue>;
|
||||
|
||||
#[wasm_bindgen(catch, static_method_of = SmartWeave, js_name = write)]
|
||||
pub async fn write(contract_id: &str, input: JsValue) -> Result<JsValue, JsValue>;
|
||||
|
||||
#[wasm_bindgen(static_method_of = SmartWeave, js_name = refreshState)]
|
||||
pub async fn refresh_state();
|
||||
|
||||
#[wasm_bindgen(static_method_of = SmartWeave, js_name = caller)]
|
||||
pub fn caller() -> String;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen]
|
||||
pub type Vrf;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Vrf, js_name = value)]
|
||||
pub fn value() -> String;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Vrf, js_name = randomInt)]
|
||||
pub fn randomInt(max_value: i32) -> i32;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
pub fn log(s: &str);
|
||||
}
|
||||
31
crates/warp-contracts/src/kv_operations.rs
Normal file
31
crates/warp-contracts/src/kv_operations.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use super::js_imports::KV;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use serde_wasm_bindgen::from_value;
|
||||
use warp_contracts_core::{handler_result::ViewResult, methods::to_json_value};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum KvError {
|
||||
NotFound,
|
||||
}
|
||||
|
||||
pub async fn kv_get<T: DeserializeOwned + Default>(key: &str) -> ViewResult<T, KvError> {
|
||||
match KV::get(key).await {
|
||||
Ok(a) if !a.is_null() => match from_value(a) {
|
||||
Ok(v) => ViewResult::Success(v),
|
||||
Err(e) => ViewResult::RuntimeError(format!("{e:?}")),
|
||||
},
|
||||
Ok(_) => ViewResult::ContractError(KvError::NotFound),
|
||||
Err(e) => ViewResult::RuntimeError(format!("{e:?}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn kv_put<T: Serialize>(key: &str, value: T) -> Result<(), String> {
|
||||
match to_json_value(&value) {
|
||||
Ok(v) => match KV::put(key, v).await {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(format!("{e:?}")),
|
||||
},
|
||||
Err(e) => Err(format!("{:?}", e)),
|
||||
}
|
||||
}
|
||||
8
crates/warp-contracts/src/lib.rs
Normal file
8
crates/warp-contracts/src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
pub mod foreign_call;
|
||||
pub mod js_imports;
|
||||
pub mod kv_operations;
|
||||
pub use warp_contracts_core::handler_result;
|
||||
pub use warp_contracts_core::methods;
|
||||
pub use warp_contracts_core::optional_cell;
|
||||
pub use warp_contracts_core::warp_result;
|
||||
pub use warp_contracts_macro::warp_contract;
|
||||
21
crates/warp-contracts/warp-contracts-core/Cargo.toml
Normal file
21
crates/warp-contracts/warp-contracts-core/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "warp-contracts-core"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
description = "warp-contracts helper crate"
|
||||
license = "MIT"
|
||||
documentation = "https://academy.warp.cc/docs/sdk/advanced/wasm"
|
||||
homepage = "https://warp.cc"
|
||||
repository = "https://github.com/warp-contracts/warp"
|
||||
keywords = ["warp", "smart-contract", "SmartWeave", "web3"]
|
||||
categories = ["api-bindings", "development-tools::ffi", "finance", "wasm"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = { workspace = true }
|
||||
wasm-bindgen-futures = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde-wasm-bindgen = { workspace = true }
|
||||
web-sys = { workspace = true, optional = true }
|
||||
|
||||
[features]
|
||||
debug = ["web-sys/console"]
|
||||
4
crates/warp-contracts/warp-contracts-core/README.md
Normal file
4
crates/warp-contracts/warp-contracts-core/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# warp-contract-core
|
||||
|
||||
Helper library for warp-contracts and warp-contracts-macro. See the `warp-contracts` documentation for more details.
|
||||
|
||||
20
crates/warp-contracts/warp-contracts-core/src/detail.rs
Normal file
20
crates/warp-contracts/warp-contracts-core/src/detail.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
// What we try to achieve here is setting common lifetime for State and Future objects
|
||||
// but using higher-ranked trait bounds (https://doc.rust-lang.org/reference/trait-bounds.html#higher-ranked-trait-bounds),
|
||||
// i.e. impossible to specify on the call side (see use of this trait).
|
||||
// The effect is somewhat opposite to 'static lifetime, the lifetime shorter than anything passed by the user.
|
||||
// Inspired by https://stackoverflow.com/a/63558160/3021277
|
||||
pub trait BorrowingFn<'a, S, A, V> {
|
||||
type Fut: core::future::Future<Output = V> + 'a;
|
||||
fn call(self, state: &'a S, action: A) -> Self::Fut;
|
||||
}
|
||||
|
||||
impl<'a, Fu: 'a, F, S: 'a, A, V> BorrowingFn<'a, S, A, V> for F
|
||||
where
|
||||
F: FnOnce(&'a S, A) -> Fu,
|
||||
Fu: core::future::Future<Output = V> + 'a,
|
||||
{
|
||||
type Fut = Fu;
|
||||
fn call(self, state: &'a S, action: A) -> Fu {
|
||||
self(state, action)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#[derive(Debug)]
|
||||
pub enum ViewResult<View, Error> {
|
||||
Success(View),
|
||||
ContractError(Error),
|
||||
RuntimeError(String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WriteResult<State, Error> {
|
||||
Success(State),
|
||||
ContractError(Error),
|
||||
RuntimeError(String),
|
||||
}
|
||||
5
crates/warp-contracts/warp-contracts-core/src/lib.rs
Normal file
5
crates/warp-contracts/warp-contracts-core/src/lib.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod detail;
|
||||
pub mod handler_result;
|
||||
pub mod methods;
|
||||
pub mod optional_cell;
|
||||
pub mod warp_result;
|
||||
185
crates/warp-contracts/warp-contracts-core/src/methods.rs
Normal file
185
crates/warp-contracts/warp-contracts-core/src/methods.rs
Normal file
@@ -0,0 +1,185 @@
|
||||
use crate::{
|
||||
detail::BorrowingFn,
|
||||
handler_result::{ViewResult, WriteResult},
|
||||
optional_cell::{CloneContents, OptionalCell},
|
||||
warp_result::transmission::Transmission,
|
||||
warp_result::WarpResult,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use core::future::Future;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_wasm_bindgen::from_value;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
pub async fn write_async<State, Action, Error, Fun, Fut>(
|
||||
state: &OptionalCell<State>,
|
||||
interaction: JsValue,
|
||||
write_contract_method: Fun,
|
||||
) -> JsValue
|
||||
where
|
||||
State: Clone + Debug + Serialize,
|
||||
Action: DeserializeOwned + Debug,
|
||||
Error: Serialize,
|
||||
Fun: FnOnce(State, Action) -> Fut,
|
||||
Fut: Future<Output = WriteResult<State, Error>>,
|
||||
{
|
||||
let result = match parse_input(state, interaction) {
|
||||
Err(value) => return value,
|
||||
Ok(action) => write_contract_method(state.clone_contents(), action).await,
|
||||
};
|
||||
|
||||
map_write_result(result, state)
|
||||
}
|
||||
|
||||
pub fn write_sync<State, Action, Error, Fun>(
|
||||
s: &OptionalCell<State>,
|
||||
interaction: JsValue,
|
||||
write_contract_method: Fun,
|
||||
) -> JsValue
|
||||
where
|
||||
State: Clone + Debug + Serialize,
|
||||
Action: DeserializeOwned + Debug,
|
||||
Error: Serialize,
|
||||
Fun: FnOnce(State, Action) -> WriteResult<State, Error>,
|
||||
{
|
||||
let result = match parse_input(s, interaction) {
|
||||
Err(value) => return value,
|
||||
Ok(action) => write_contract_method(s.clone_contents(), action),
|
||||
};
|
||||
|
||||
map_write_result(result, s)
|
||||
}
|
||||
|
||||
// We need a dedicated trait BorrowingFn to attach the same lifetime
|
||||
// that is not possible to specify by the caller of the view_async to both &State and Future
|
||||
pub async fn view_async<State, Action, View, Error, Fun>(
|
||||
s: &OptionalCell<State>,
|
||||
interaction: JsValue,
|
||||
view_contract_method: Fun,
|
||||
) -> JsValue
|
||||
where
|
||||
State: Clone,
|
||||
Action: DeserializeOwned + core::fmt::Debug,
|
||||
View: Serialize + Debug,
|
||||
Error: Serialize + Debug,
|
||||
Fun: for<'a> BorrowingFn<'a, State, Action, ViewResult<View, Error>>,
|
||||
{
|
||||
let result = match parse_input(s, interaction) {
|
||||
Err(value) => return value,
|
||||
Ok(action) => {
|
||||
view_contract_method
|
||||
.call(s.cell.borrow().as_ref().unwrap(), action)
|
||||
.await
|
||||
}
|
||||
};
|
||||
|
||||
to_json_value::<Transmission<View, Error>>(&WarpResult::from(result).into()).unwrap()
|
||||
}
|
||||
|
||||
pub fn view_sync<State, Action, View, Error, Fun>(
|
||||
s: &OptionalCell<State>,
|
||||
interaction: JsValue,
|
||||
view_contract_method: Fun,
|
||||
) -> JsValue
|
||||
where
|
||||
State: Clone,
|
||||
Action: DeserializeOwned + Debug,
|
||||
View: Serialize,
|
||||
Error: Serialize,
|
||||
Fun: FnOnce(&State, Action) -> ViewResult<View, Error>,
|
||||
{
|
||||
let result = match parse_input(s, interaction) {
|
||||
Err(value) => return value,
|
||||
Ok(action) => view_contract_method(s.cell.borrow().as_ref().unwrap(), action),
|
||||
};
|
||||
|
||||
to_json_value::<Transmission<View, Error>>(&WarpResult::from(result).into()).unwrap()
|
||||
}
|
||||
|
||||
fn map_write_result<State, Error>(
|
||||
result: WriteResult<State, Error>,
|
||||
state: &OptionalCell<State>,
|
||||
) -> JsValue
|
||||
where
|
||||
State: Clone + Debug + Serialize,
|
||||
Error: Serialize,
|
||||
{
|
||||
if let WriteResult::Success(new_state) = result {
|
||||
state.cell.replace(Some(new_state));
|
||||
to_json_value::<Transmission<(), Error>>(&WarpResult::WriteSuccess().into()).unwrap()
|
||||
} else {
|
||||
to_json_value::<Transmission<(), Error>>(&WarpResult::from(result).into()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_input<State, Action>(
|
||||
state: &OptionalCell<State>,
|
||||
interaction: JsValue,
|
||||
) -> Result<Action, JsValue>
|
||||
where
|
||||
Action: DeserializeOwned + core::fmt::Debug,
|
||||
State: Clone,
|
||||
{
|
||||
let action = from_value(interaction);
|
||||
if action.is_err() {
|
||||
return Err(runtime_error(format!(
|
||||
"Error while parsing input {}",
|
||||
action.unwrap_err()
|
||||
)));
|
||||
}
|
||||
if state.is_empty() {
|
||||
return Err(runtime_error(format!(
|
||||
"initState MUST be called before interaction can take place"
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(action.unwrap())
|
||||
}
|
||||
|
||||
pub fn init_state<S: DeserializeOwned>(
|
||||
state: &OptionalCell<S>,
|
||||
init_state: &JsValue,
|
||||
) -> Option<String> {
|
||||
match from_value(init_state.clone()) {
|
||||
Ok(parsed_state) => {
|
||||
state.cell.replace(Some(parsed_state));
|
||||
None
|
||||
}
|
||||
Err(e) => {
|
||||
let ret = format!("failed to parse init state {:?}", e);
|
||||
#[cfg(feature = "debug")]
|
||||
{
|
||||
web_sys::console::debug_1(&JsValue::from_str(&ret));
|
||||
}
|
||||
Option::from(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_state<State: Serialize + Debug>(state: &OptionalCell<State>) -> JsValue {
|
||||
// not sure if that's deterministic - which is very important for the execution network.
|
||||
// TODO: perf - according to docs:
|
||||
// "This is unlikely to be super speedy so it's not recommended for large payload"
|
||||
// - we should minimize calls to serde_wasm_bindgen::to_json_value
|
||||
if state.is_empty() {
|
||||
runtime_error(
|
||||
"contract state not initialized. please run initState method first".to_owned(),
|
||||
)
|
||||
} else {
|
||||
match to_json_value(state.cell.borrow().as_ref().unwrap()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => runtime_error(format!("failed to serialize return value {:?}", e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_json_value<T: serde::ser::Serialize + ?Sized>(
|
||||
value: &T,
|
||||
) -> core::result::Result<JsValue, serde_wasm_bindgen::Error> {
|
||||
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
||||
value.serialize(&serializer)
|
||||
}
|
||||
|
||||
pub fn runtime_error(error_message: String) -> JsValue {
|
||||
to_json_value::<Transmission<(), ()>>(&WarpResult::RuntimeError(error_message).into()).unwrap()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
use core::cell::RefCell;
|
||||
|
||||
/// Tiny wrapper over RefCell that:
|
||||
/// - allow for uninitialized values (by storing Option)
|
||||
/// - allow static usage (by implementing Sync and providing const constructor)
|
||||
///
|
||||
/// Because WASM is single threaded, we don't need to worry much about inter-thread communication
|
||||
pub struct OptionalCell<T> {
|
||||
pub cell: RefCell<Option<T>>,
|
||||
}
|
||||
|
||||
impl<T> OptionalCell<T> {
|
||||
pub const fn empty() -> OptionalCell<T> {
|
||||
OptionalCell {
|
||||
cell: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.cell.borrow().is_none()
|
||||
}
|
||||
}
|
||||
|
||||
// Add clone_content to OptionalCell only if T is known to implement Clone.
|
||||
// In particular to to use is_empty on OptionalCell trait Clone is not required on T.
|
||||
pub trait CloneContents<T: Clone> {
|
||||
fn clone_contents(&self) -> T;
|
||||
}
|
||||
|
||||
impl<T: Clone> CloneContents<T> for OptionalCell<T> {
|
||||
fn clone_contents(&self) -> T {
|
||||
self.cell.borrow().as_ref().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for OptionalCell<T> {}
|
||||
130
crates/warp-contracts/warp-contracts-core/src/warp_result.rs
Normal file
130
crates/warp-contracts/warp-contracts-core/src/warp_result.rs
Normal file
@@ -0,0 +1,130 @@
|
||||
use crate::handler_result::{ViewResult, WriteResult};
|
||||
|
||||
pub enum WarpResult<View, Error> {
|
||||
WriteSuccess(),
|
||||
ViewSuccess(View),
|
||||
ContractError(Error),
|
||||
RuntimeError(String),
|
||||
}
|
||||
|
||||
impl<V, E> From<ViewResult<V, E>> for WarpResult<V, E> {
|
||||
fn from(value: ViewResult<V, E>) -> Self {
|
||||
match value {
|
||||
ViewResult::Success(v) => WarpResult::ViewSuccess(v),
|
||||
ViewResult::ContractError(e) => WarpResult::ContractError(e),
|
||||
ViewResult::RuntimeError(e) => WarpResult::RuntimeError(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, V, E> From<WriteResult<S, E>> for WarpResult<V, E> {
|
||||
fn from(value: WriteResult<S, E>) -> Self {
|
||||
match value {
|
||||
WriteResult::Success(_) => WarpResult::WriteSuccess(),
|
||||
WriteResult::ContractError(e) => WarpResult::ContractError(e),
|
||||
WriteResult::RuntimeError(e) => WarpResult::RuntimeError(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, E> From<WarpResult<V, E>> for ViewResult<V, E> {
|
||||
fn from(value: WarpResult<V, E>) -> Self {
|
||||
match value {
|
||||
WarpResult::WriteSuccess() => unreachable!(),
|
||||
WarpResult::ViewSuccess(v) => ViewResult::Success(v),
|
||||
WarpResult::ContractError(e) => ViewResult::ContractError(e),
|
||||
WarpResult::RuntimeError(e) => ViewResult::RuntimeError(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, E> From<WarpResult<V, E>> for WriteResult<(), E> {
|
||||
fn from(value: WarpResult<V, E>) -> Self {
|
||||
match value {
|
||||
WarpResult::WriteSuccess() => WriteResult::Success(()),
|
||||
WarpResult::ViewSuccess(_) => unreachable!(),
|
||||
WarpResult::ContractError(e) => WriteResult::ContractError(e),
|
||||
WarpResult::RuntimeError(e) => WriteResult::RuntimeError(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Module defining format as expected by SDK, covers (de)serialization.
|
||||
// We have this separated from WarpResult above (visible to contract code) to
|
||||
// keep WarpResult interface clean
|
||||
pub mod transmission {
|
||||
use super::WarpResult;
|
||||
use core::fmt::Debug;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ErrorResult {
|
||||
#[serde(rename = "errorMessage")]
|
||||
error_message: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Transmission<View, Error> {
|
||||
#[serde(rename = "type")]
|
||||
result_type: String,
|
||||
result: Option<View>,
|
||||
error: Option<Error>,
|
||||
#[serde(rename = "errorMessage")]
|
||||
error_message: Option<String>,
|
||||
}
|
||||
|
||||
impl<V: Debug, E: Debug> From<Transmission<V, E>> for WarpResult<V, E> {
|
||||
fn from(value: Transmission<V, E>) -> Self {
|
||||
match value.result_type.as_str() {
|
||||
"ok" if value.result.is_none() => WarpResult::WriteSuccess(),
|
||||
"ok" => WarpResult::ViewSuccess(value.result.unwrap()),
|
||||
"error" if value.error.is_some() => WarpResult::ContractError(value.error.unwrap()),
|
||||
"exception" if value.error_message.is_some() => {
|
||||
WarpResult::RuntimeError(value.error_message.unwrap())
|
||||
}
|
||||
_ => WarpResult::RuntimeError(format!("failed to parse response {:?}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, E> From<WarpResult<V, E>> for Transmission<V, E> {
|
||||
fn from(value: WarpResult<V, E>) -> Self {
|
||||
let mut res = Transmission {
|
||||
result_type: "".to_owned(),
|
||||
result: None,
|
||||
error: None,
|
||||
error_message: None,
|
||||
};
|
||||
match value {
|
||||
WarpResult::WriteSuccess() => {
|
||||
res.result_type = "ok".to_owned();
|
||||
}
|
||||
WarpResult::ViewSuccess(v) => {
|
||||
res.result_type = "ok".to_owned();
|
||||
res.result = Some(v);
|
||||
}
|
||||
WarpResult::ContractError(e) => {
|
||||
res.result_type = "error".to_owned();
|
||||
res.error = Some(e);
|
||||
}
|
||||
WarpResult::RuntimeError(e) => {
|
||||
res.result_type = "exception".to_owned();
|
||||
res.error_message = Some(e);
|
||||
}
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_json<V: Debug, E: Debug>(warp_result: JsValue) -> WarpResult<V, E>
|
||||
where
|
||||
V: DeserializeOwned,
|
||||
E: DeserializeOwned,
|
||||
{
|
||||
match serde_wasm_bindgen::from_value::<Transmission<V, E>>(warp_result) {
|
||||
Ok(t) => t.into(),
|
||||
Err(e) => WarpResult::RuntimeError(format!("{e:?}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
19
crates/warp-contracts/warp-contracts-macro/Cargo.toml
Normal file
19
crates/warp-contracts/warp-contracts-macro/Cargo.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "warp-contracts-macro"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
description = "warp_contract macro definition"
|
||||
license = "MIT"
|
||||
documentation = "https://academy.warp.cc/docs/sdk/advanced/wasm"
|
||||
homepage = "https://warp.cc"
|
||||
repository = "https://github.com/warp-contracts/warp"
|
||||
keywords = ["warp", "smart-contract", "SmartWeave", "web3"]
|
||||
categories = ["api-bindings", "development-tools::ffi", "finance", "wasm"]
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0"
|
||||
syn = { version = "1.0", features = ["extra-traits"] }
|
||||
warp-contracts-core = { version = "0.1.1", path = "../warp-contracts-core" }
|
||||
3
crates/warp-contracts/warp-contracts-macro/README.md
Normal file
3
crates/warp-contracts/warp-contracts-macro/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# warp-contracts-macro
|
||||
|
||||
Implementation of the #[warp_contract] attribute. See the `warp-contracts` documentation for more information.
|
||||
8
crates/warp-contracts/warp-contracts-macro/src/lib.rs
Normal file
8
crates/warp-contracts/warp-contracts-macro/src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
mod warp_contract_macro;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn warp_contract(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
warp_contract_macro::warp_contract(attr, input)
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, FnArg, ItemFn};
|
||||
|
||||
pub(crate) fn warp_contract(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let is_write = match attr.to_string().as_str() {
|
||||
"write" => true,
|
||||
"view" => false,
|
||||
_ => panic!(
|
||||
"warp_contract macro requires exactly one attribute: \
|
||||
'write' for method changing state or 'view' for view state method \
|
||||
e.g. #[warp_contract(write)], #[warp_contract(view)]"
|
||||
),
|
||||
};
|
||||
let ast = parse_macro_input!(input as ItemFn);
|
||||
let ast_clone = ast.clone();
|
||||
let fun_name = ast.sig.ident;
|
||||
let is_async = ast.sig.asyncness.is_some();
|
||||
let (await_spec, write_core_method, view_core_method) = if is_async {
|
||||
(
|
||||
quote! { .await },
|
||||
quote! { ::warp_contracts::methods::write_async },
|
||||
quote! { ::warp_contracts::methods::view_async },
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote! {},
|
||||
quote! { ::warp_contracts::methods::write_sync },
|
||||
quote! { ::warp_contracts::methods::view_sync },
|
||||
)
|
||||
};
|
||||
|
||||
let inputs = ast.sig.inputs;
|
||||
if inputs.len() != 2 {
|
||||
panic!("two arguments expected for warp contract handle method, the first one representing state object and the second representing interaction description");
|
||||
}
|
||||
let state_type = match inputs.first().unwrap() {
|
||||
FnArg::Receiver(_) => panic!("self not allowed in warp contract handle function"),
|
||||
FnArg::Typed(t) => &t.ty,
|
||||
};
|
||||
if is_write {
|
||||
quote! {
|
||||
/*
|
||||
Note: in order do optimize communication between host and the WASM module,
|
||||
we're storing the state inside the WASM module (for the time of state evaluation).
|
||||
This allows to reduce the overhead of passing the state back and forth
|
||||
between the host and module with each contract interaction.
|
||||
In case of bigger states this overhead can be huge.
|
||||
Same approach has been implemented for the AssemblyScript version.
|
||||
|
||||
So the flow (from the SDK perspective) is:
|
||||
1. SDK calls exported WASM module function "initState" (with lastly cached state or initial state,
|
||||
if cache is empty) - which initializes the state in the WASM module.
|
||||
2. SDK calls "handle" function for each of the interaction.
|
||||
If given interaction was modifying the state - it is updated inside the WASM module
|
||||
- but not returned to host.
|
||||
3. Whenever SDK needs to know the current state (eg. in order to perform
|
||||
caching or to simply get its value after evaluating all of the interactions)
|
||||
- it calls WASM's module "currentState" function.
|
||||
|
||||
The handle function by default does not return the new state -
|
||||
it only updates it in the WASM module.
|
||||
The handle function returns a value only in case of error
|
||||
or calling a "view" function.
|
||||
|
||||
In the future this might also allow to enhance the inner-contracts communication
|
||||
- e.g. if the execution network will store the state of the contracts - as the WASM contract module memory
|
||||
- it would allow to read other contract's state "directly" from WASM module memory.
|
||||
*/
|
||||
static __WARP_CONTRACT_STATE: ::warp_contracts::optional_cell::OptionalCell<#state_type> =
|
||||
::warp_contracts::optional_cell::OptionalCell::empty();
|
||||
|
||||
const _: () = {
|
||||
use ::core::{cell::RefCell, option::Option};
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use ::serde_wasm_bindgen::from_value;
|
||||
use ::warp_contracts::{
|
||||
optional_cell::OptionalCell,
|
||||
warp_result::{transmission::Transmission, WarpResult},
|
||||
js_imports::log,
|
||||
methods::*
|
||||
};
|
||||
use ::wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(js_name = warpContractWrite)]
|
||||
pub async fn __warp_contracts_generated_write(interaction: JsValue) -> JsValue {
|
||||
#write_core_method(&__WARP_CONTRACT_STATE, interaction, #fun_name)#await_spec
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = initState)]
|
||||
pub fn __warp_contracts_generated_init_state(state: &JsValue) -> Option<String> {
|
||||
init_state(&__WARP_CONTRACT_STATE, state)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = currentState)]
|
||||
pub fn __warp_contracts_generated_current_state() -> JsValue {
|
||||
current_state(&__WARP_CONTRACT_STATE)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = version)]
|
||||
pub fn __warp_contracts_generated_version() -> i32 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Workaround for now to simplify type reading without as/loader or wasm-bindgen
|
||||
// 1 = assemblyscript
|
||||
// 2 = rust
|
||||
// 3 = go
|
||||
// 4 = swift
|
||||
// 5 = c
|
||||
#[wasm_bindgen(js_name = lang)]
|
||||
pub fn __warp_contracts_generated_lang() -> i32 {
|
||||
return 2;
|
||||
}
|
||||
()
|
||||
};
|
||||
#ast_clone
|
||||
}
|
||||
.into()
|
||||
} else {
|
||||
quote! {
|
||||
const _: () = {
|
||||
use ::wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(js_name = warpContractView)]
|
||||
pub async fn __warp_contracts_generated_view(interaction: JsValue) -> JsValue {
|
||||
#view_core_method(&__WARP_CONTRACT_STATE, interaction, #fun_name)#await_spec
|
||||
}
|
||||
};
|
||||
#ast_clone
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
@@ -720,7 +720,7 @@ export const rustWasmImports = (swGlobal, wbindgenImports, wasmInstance, dtorVal
|
||||
},
|
||||
|
||||
|
||||
__wbg_log_3: function () {
|
||||
__wbg_log: function () {
|
||||
return logError(function (arg0, arg1) {
|
||||
rawImports.console.log(getStringFromWasm0(arg0, arg1));
|
||||
}, arguments)
|
||||
@@ -737,14 +737,12 @@ export const rustWasmImports = (swGlobal, wbindgenImports, wasmInstance, dtorVal
|
||||
return ret;
|
||||
},
|
||||
|
||||
__wbg_log_7: function () {
|
||||
__wbg_debug: function () {
|
||||
return logError(function (arg0) {
|
||||
console.log(getObject(arg0));
|
||||
}, arguments)
|
||||
},
|
||||
|
||||
|
||||
|
||||
__wbg_String: function () {
|
||||
return logError(function (arg0, arg1) {
|
||||
const ret = String(getObject(arg1));
|
||||
|
||||
Reference in New Issue
Block a user