1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use snafu::ResultExt;

use cosmwasm::serde::{from_slice, to_vec};
use cosmwasm::traits::{Api, Storage};
use cosmwasm::types::{ContractResult, Env, QueryResult};

use crate::errors::{Error, ParseErr, RuntimeErr, SerializeErr};
use crate::instance::{Func, Instance};

pub fn call_init<S: Storage + 'static, A: Api + 'static>(
    instance: &mut Instance<S, A>,
    env: &Env,
    msg: &[u8],
) -> Result<ContractResult, Error> {
    let env = to_vec(env).context(SerializeErr {})?;
    let data = call_init_raw(instance, &env, msg)?;
    let res: ContractResult = from_slice(&data).context(ParseErr {})?;
    Ok(res)
}

pub fn call_handle<S: Storage + 'static, A: Api + 'static>(
    instance: &mut Instance<S, A>,
    env: &Env,
    msg: &[u8],
) -> Result<ContractResult, Error> {
    let env = to_vec(env).context(SerializeErr {})?;
    let data = call_handle_raw(instance, &env, msg)?;
    let res: ContractResult = from_slice(&data).context(ParseErr {})?;
    Ok(res)
}

pub fn call_query<S: Storage + 'static, A: Api + 'static>(
    instance: &mut Instance<S, A>,
    msg: &[u8],
) -> Result<QueryResult, Error> {
    let data = call_query_raw(instance, msg)?;
    let res: QueryResult = from_slice(&data).context(ParseErr {})?;
    Ok(res)
}

pub fn call_query_raw<S: Storage + 'static, A: Api + 'static>(
    instance: &mut Instance<S, A>,
    msg: &[u8],
) -> Result<Vec<u8>, Error> {
    // we cannot resuse the call_raw functionality as it assumes a param variable... just do it inline
    let msg_offset = instance.allocate(msg)?;
    let func: Func<u32, u32> = instance.func("query")?;
    let res_offset = func.call(msg_offset).context(RuntimeErr {})?;
    let data = instance.memory(res_offset);
    // free return value in wasm (arguments were freed in wasm code)
    instance.deallocate(res_offset)?;
    Ok(data)
}

pub fn call_init_raw<S: Storage + 'static, A: Api + 'static>(
    instance: &mut Instance<S, A>,
    env: &[u8],
    msg: &[u8],
) -> Result<Vec<u8>, Error> {
    call_raw(instance, "init", env, msg)
}

pub fn call_handle_raw<S: Storage + 'static, A: Api + 'static>(
    instance: &mut Instance<S, A>,
    env: &[u8],
    msg: &[u8],
) -> Result<Vec<u8>, Error> {
    call_raw(instance, "handle", env, msg)
}

fn call_raw<S: Storage + 'static, A: Api + 'static>(
    instance: &mut Instance<S, A>,
    name: &str,
    env: &[u8],
    msg: &[u8],
) -> Result<Vec<u8>, Error> {
    let param_offset = instance.allocate(env)?;
    let msg_offset = instance.allocate(msg)?;

    let func: Func<(u32, u32), u32> = instance.func(name)?;
    let res_offset = func.call(param_offset, msg_offset).context(RuntimeErr {})?;

    let data = instance.memory(res_offset);
    // free return value in wasm (arguments were freed in wasm code)
    instance.deallocate(res_offset)?;
    Ok(data)
}