pchain_sdk/
method.rs

1/*
2    Copyright © 2023, ParallelChain Lab 
3    Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
4*/
5
6//! Defines the abstract level of inputs and outputs of a contract method.
7//! Contracts written use the `#[contract]` macro to unpack those Transaction Command `Call` 
8//! that contain a serialized `arguments`. This structure selects the Method 
9//! that a call should enter, as well as provides the arguments for the function call. 
10//! 
11//! The structure of output of a contract method wraps the return value in Internal Calls.
12//!
13//! Developers typically do not need to care about the contents of this module. The `#[contract]` macro handles
14//! the creation and consumption of ContractMethodInput in expanded code. 
15
16use borsh::{BorshSerialize, BorshDeserialize};
17
18use crate::transaction;
19
20/// Input of a contract method in a call, which consists of method name and its borsh-serialized arguments.
21pub struct ContractMethodInput {
22    pub method_name: String,
23    pub arguments: Vec<u8>,
24}
25
26impl ContractMethodInput {
27    /// Convert the fields in the transaction Call command
28    pub fn from_transaction() -> Self {
29        Self{
30            method_name: transaction::method(),
31            arguments: transaction::arguments()
32        }
33    }
34    /// Get method_name as &str from Call command.
35    pub fn method_name(&self) -> &str {
36        self.method_name.as_str()
37    }
38
39    /// Converts `arguments` in Call command  to `Vec<Vec<u8>>` so that it can be parsed to specific data type for the entrypoint function.
40    pub fn get_multiple_arguments(&self) -> Vec<Vec<u8>> {
41        let mut args = self.arguments.as_slice();
42        BorshDeserialize::deserialize(&mut args).unwrap()
43    }
44
45    /// Parser function to deserialize indexed argument into defined data type
46    pub fn parse_multiple_arguments<T: BorshDeserialize>(args: &[Vec<u8>], idx: usize) -> T {
47        let bs = args[idx].clone();
48        BorshDeserialize::deserialize(&mut bs.as_ref()).unwrap()
49    }
50}
51
52
53
54/// Builder to contruct arguments in Call command so that it can be passed to entrypoint
55/// 
56/// 
57/// # Basic example 
58/// ```no_run
59/// let args_builder = pchain_sdk::ContractMethodInputBuilder::new();
60/// args_builder
61/// .add("i am string".to_string())
62/// .add(0_i32)
63/// .add(vec![0u8; 8]);
64/// 
65/// // construct Vec<u8> data to pass to call arguments 
66/// let args :Vec<u8> = args_builder.to_call_arguments();
67/// ...
68/// ```
69pub struct ContractMethodInputBuilder {
70    pub args :Vec<Vec<u8>>
71}
72impl ContractMethodInputBuilder {
73    pub fn new() -> Self {
74        Self { args: vec![] }
75    }
76    pub fn add<T: BorshSerialize>(&mut self,  arg :T) -> &mut Self{
77        self.args.push(arg.try_to_vec().unwrap());
78        self
79    }
80    pub fn to_call_arguments(&self) -> Vec<u8> {
81        // use pchain_types for serialization for consistency with runtime
82        <Vec<Vec<u8>> as pchain_types::serialization::Serializable>::serialize(&self.args)
83    }
84}
85
86
87/// Encapsulates the return value as serialized bytes from contract method. 
88/// None if the contract method does not specify return value.
89#[derive(BorshSerialize, BorshDeserialize, Default)]
90pub struct ContractMethodOutput(Option<Vec<u8>>);
91
92impl ContractMethodOutput {
93    pub fn set<T: BorshSerialize>(result :&T) -> Self {
94        Self(Some(T::try_to_vec(result).unwrap()))
95    }
96
97    pub fn get(self) -> Option<Vec<u8>> {
98        self.0
99    }
100}