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}