tests: example rust contracts moved from warp-wasm-templates

This commit is contained in:
robal
2023-03-17 17:55:17 +01:00
parent c1d8fb7a52
commit dbe52e82cd
75 changed files with 17993 additions and 1 deletions

View File

@@ -0,0 +1,19 @@
[package]
name = "warp_pst_implementation"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
console_error_panic_hook = "0.1.7"
warp_pst = { path = "../definition" }
warp-contracts = { version = "0.1.2", features = ["debug"], path = "../../../warp-contracts" }
wasm-bindgen = "=0.2.84"
wasm-bindgen-futures = "=0.4.34"
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "=0.5.0"
async-recursion = "1.0.0"
async-trait = "0.1.56"
tokio-test = "0.4.2"

View File

@@ -0,0 +1,20 @@
use super::ViewActionable;
use warp_pst::{
action::{Balance, PstBalanceResult, PstViewResponse::BalanceResult, PstViewResult},
error::PstError::*,
state::PstState,
};
impl ViewActionable for Balance {
fn action(self, _caller: String, state: &PstState) -> PstViewResult {
if !state.balances.contains_key(&self.target) {
return PstViewResult::ContractError(WalletHasNoBalanceDefined(self.target));
}
let balance_response = PstBalanceResult {
balance: *state.balances.get(&self.target).unwrap(),
ticker: state.ticker.clone(),
target: self.target,
};
PstViewResult::Success(BalanceResult(balance_response))
}
}

View File

@@ -0,0 +1,23 @@
use super::WriteActionable;
use warp_contracts::js_imports::Transaction;
use warp_pst::{
action::{Evolve, PstWriteResult},
error::PstError::*,
state::PstState,
};
impl WriteActionable for Evolve {
fn action(self, _caller: String, mut state: PstState) -> PstWriteResult {
match state.can_evolve {
Some(true) => {
if state.owner == Transaction::owner() {
state.evolve = Option::from(self.value);
PstWriteResult::Success(state)
} else {
PstWriteResult::ContractError(OnlyOwnerCanEvolve)
}
}
_ => PstWriteResult::ContractError(EvolveNotAllowed),
}
}
}

View File

@@ -0,0 +1,31 @@
use super::AsyncWriteActionable;
use async_trait::async_trait;
use warp_contracts::{foreign_call::read_foreign_contract_state, js_imports::log};
use warp_pst::{
action::{ForeignRead, PstWriteResult},
error::PstError::*,
state::PstState,
};
#[async_trait(?Send)]
impl AsyncWriteActionable for ForeignRead {
async fn action(self, _caller: String, mut state: PstState) -> PstWriteResult {
if self.contract_tx_id == "bad_contract" {
return PstWriteResult::ContractError(IDontLikeThisContract);
}
let foreign_contract_state: PstState =
match read_foreign_contract_state(&self.contract_tx_id).await {
Ok(s) => s,
Err(e) => return PstWriteResult::RuntimeError(e),
};
// Some dummy logic - just for the sake of the integration test
if foreign_contract_state.ticker == "FOREIGN_PST" {
log("Adding to tokens");
for val in state.balances.values_mut() {
*val += 1000;
}
}
PstWriteResult::Success(state)
}
}

View File

@@ -0,0 +1,43 @@
use super::AsyncViewActionable;
use async_trait::async_trait;
use serde::Serialize;
use warp_contracts::{foreign_call::view_foreign_contract_state, handler_result::ViewResult::*};
use warp_pst::{
action::{
ForeignView, PstBalanceResult, PstForeignViewResult, PstViewResponse::*, PstViewResult,
},
state::PstState,
};
#[derive(Serialize, Debug)]
struct BalanceInput {
function: String,
target: String,
}
#[async_trait(?Send)]
impl AsyncViewActionable for ForeignView {
async fn action(self, _caller: String, _state: &PstState) -> PstViewResult {
let foreign_contract_state = view_foreign_contract_state(
&self.contract_tx_id,
BalanceInput {
target: self.target,
function: "balance".to_string(),
},
)
.await;
match foreign_contract_state {
Success(PstBalanceResult {
balance,
ticker,
target,
}) => Success(ForeignViewResult(PstForeignViewResult {
balance,
ticker,
target,
})),
ContractError(e) => ContractError(e),
RuntimeError(e) => RuntimeError(e),
}
}
}

View File

@@ -0,0 +1,36 @@
use super::AsyncWriteActionable;
use async_trait::async_trait;
use serde::Serialize;
use warp_contracts::{foreign_call::write_foreign_contract, handler_result::WriteResult::*};
use warp_pst::{
action::{ForeignWrite, PstWriteResult},
error::PstError,
state::PstState,
};
#[derive(Serialize)]
struct Input {
function: String,
qty: u64,
target: String,
}
#[async_trait(?Send)]
impl AsyncWriteActionable for ForeignWrite {
async fn action(self, _caller: String, state: PstState) -> PstWriteResult {
match write_foreign_contract::<Input, PstError>(
&self.contract_tx_id,
Input {
function: "transfer".to_string(),
qty: self.qty,
target: self.target,
},
)
.await
{
Success(_) => Success(state),
ContractError(e) => ContractError(e),
RuntimeError(e) => RuntimeError(e),
}
}
}

View File

@@ -0,0 +1,28 @@
use super::AsyncViewActionable;
use async_trait::async_trait;
use warp_contracts::{handler_result::ViewResult::*, kv_operations::kv_get};
use warp_pst::{
action::{KvGet, PstKvGetResult, PstViewResponse, PstViewResult},
state::PstState,
};
#[async_trait(?Send)]
impl AsyncViewActionable for KvGet {
async fn action(self, _caller: String, _state: &PstState) -> PstViewResult {
match kv_get(&self.key).await {
Success(a) => {
PstViewResult::Success(PstViewResponse::KvGetResult(PstKvGetResult {
key: self.key,
value: a,
}))
}
ContractError(_) => {
PstViewResult::Success(PstViewResponse::KvGetResult(PstKvGetResult {
key: self.key,
value: "".to_owned(),
}))
},
RuntimeError(e) => RuntimeError(e),
}
}
}

View File

@@ -0,0 +1,24 @@
use super::AsyncWriteActionable;
use async_trait::async_trait;
use warp_contracts::{
js_imports::{log, Transaction},
kv_operations::kv_put,
};
use warp_pst::{
action::{KvPut, PstWriteResult},
state::PstState,
};
#[async_trait(?Send)]
impl AsyncWriteActionable for KvPut {
async fn action(self, caller: String, state: PstState) -> PstWriteResult {
let owner = Transaction::owner();
log(&format!("caller {caller}"));
log(&format!("Transaction owner {owner}"));
match kv_put(&self.key, &self.value).await {
Err(e) => PstWriteResult::RuntimeError(e),
Ok(_) => PstWriteResult::Success(state),
}
}
}

View File

@@ -0,0 +1,36 @@
use async_trait::async_trait;
use warp_pst::{action::{PstViewResult, PstWriteResult}, state::PstState};
pub mod balance;
pub mod evolve;
pub mod foreign_read;
pub mod foreign_view;
pub mod foreign_write;
pub mod kv_get;
pub mod kv_put;
pub mod transfer;
pub use balance::*;
pub use evolve::*;
pub use foreign_read::*;
pub use foreign_view::*;
pub use foreign_write::*;
pub use transfer::*;
pub trait ViewActionable {
fn action(self, caller: String, state: &PstState) -> PstViewResult;
}
#[async_trait(?Send)]
pub trait AsyncViewActionable {
async fn action(self, caller: String, state: &PstState) -> PstViewResult;
}
pub trait WriteActionable {
fn action(self, caller: String, state: PstState) -> PstWriteResult;
}
#[async_trait(?Send)]
pub trait AsyncWriteActionable {
async fn action(self, caller: String, state: PstState) -> PstWriteResult;
}

View File

@@ -0,0 +1,36 @@
use super::WriteActionable;
use warp_contracts::js_imports::{log, SmartWeave, Transaction};
use warp_pst::{
action::{PstWriteResult, Transfer},
error::PstError::*,
state::PstState,
};
impl WriteActionable for Transfer {
fn action(self, _caller: String, mut state: PstState) -> PstWriteResult {
log(("caller ".to_owned() + &SmartWeave::caller()).as_str());
log(("Transaction owner ".to_owned() + &Transaction::owner()).as_str());
if self.qty == 0 {
return PstWriteResult::ContractError(TransferAmountMustBeHigherThanZero);
}
let caller = Transaction::owner();
let balances = &mut state.balances;
// Checking if caller has enough funds
let caller_balance = *balances.get(&caller).unwrap_or(&0);
if caller_balance < self.qty {
return PstWriteResult::ContractError(CallerBalanceNotEnough(caller_balance));
}
// Update caller balance
balances.insert(caller, caller_balance - self.qty);
// Update target balance
let target_balance = *balances.get(&self.target).unwrap_or(&0);
balances.insert(self.target, target_balance + self.qty);
PstWriteResult::Success(state)
}
}

View File

@@ -0,0 +1,55 @@
use warp_pst::{
action::{Action, PstWriteResult, PstViewResult},
state::PstState,
};
use wasm_bindgen::prelude::wasm_bindgen;
use crate::actions::*;
use warp_contracts::{js_imports::*, warp_contract};
#[warp_contract(write)]
pub async fn handle_write(state: PstState, action: Action) -> PstWriteResult {
console_error_panic_hook::set_once();
let effective_caller = SmartWeave::caller();
//Example of accessing functions imported from js:
log("log from contract");
log(&("Transaction::id()".to_owned() + &Transaction::id()));
log(&("Transaction::owner()".to_owned() + &Transaction::owner()));
log(&("Transaction::target()".to_owned() + &Transaction::target()));
log(&("Block::height()".to_owned() + &Block::height().to_string()));
log(&("Block::indep_hash()".to_owned() + &Block::indep_hash()));
log(&("Block::timestamp()".to_owned() + &Block::timestamp().to_string()));
log(&("Contract::id()".to_owned() + &Contract::id()));
log(&("Contract::owner()".to_owned() + &Contract::owner()));
log(&("SmartWeave::caller()".to_owned() + &SmartWeave::caller()));
// for vrf-compatible interactions
log(&("Vrf::value()".to_owned() + &Vrf::value()));
log(&("Vrf::randomInt(7)".to_owned() + &Vrf::randomInt(7).to_string()));
match action {
Action::Transfer(action) => action.action(effective_caller, state),
Action::Evolve(action) => action.action(effective_caller, state),
Action::ForeignRead(action) => action.action(effective_caller, state).await,
Action::ForeignWrite(action) => action.action(effective_caller, state).await,
Action::KvPut(action) => action.action(effective_caller, state).await,
_ => PstWriteResult::RuntimeError("invalid method for write".to_owned()),
}
}
#[warp_contract(view)]
pub async fn handle_view(state: &PstState, action: Action) -> PstViewResult {
console_error_panic_hook::set_once();
let effective_caller = SmartWeave::caller();
match action {
Action::Balance(action) => action.action(effective_caller, state),
Action::ForeignView(action) => action.action(effective_caller, state).await,
Action::KvGet(action) => action.action(effective_caller, state).await,
_ => PstViewResult::RuntimeError("invalid method for view".to_owned()),
}
}

View File

@@ -0,0 +1,2 @@
mod actions;
mod contract;