pchain_sdk/
internal.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//! Internal functions that interacts within this transaction context. For example, setting data to receipts,
7//! calling other contracts, transfer to other account.
8
9use pchain_types::{cryptography::PublicAddress, serialization::{Serializable, Deserializable}, blockchain::Log, runtime::CallInput};
10
11use crate::imports;
12
13/// `return_value` places `value` in the receipt of a transaction.
14pub fn return_value(value: Vec<u8>) {    
15    let value_ptr = value.as_ptr();
16    let value_len = value.len() as u32;
17    unsafe {           
18        imports::return_value(value_ptr, value_len);
19    }
20}
21
22/// `log` saves message with a topic to receipt of a transaction.
23pub fn log(topic: &[u8], value: &[u8]) {
24    let event = Log { 
25        topic: topic.to_vec(), 
26        value: value.to_vec()
27    };
28    let serialized_event = Log::serialize(&event);
29
30    let log_ptr= serialized_event.as_ptr();
31    let log_len = serialized_event.len() as u32;
32
33    unsafe {
34        imports::_log(log_ptr, log_len);
35    }
36}
37
38/// A call to contract. The caller should already know the data type of return value from the function call.
39/// It returns Option of T where T is return value from the function. 
40/// If data type T is different from the actual return value type of the function, None is returned.
41pub fn call<T: borsh::BorshDeserialize>(address: PublicAddress, method_name: &str, arguments: Vec<u8>, value: u64) -> Option<T> {
42    let return_value = call_untyped(address, method_name, arguments, value)?;
43    T::deserialize(&mut return_value.as_slice()).map_or(None, |value| Some(value))
44}
45
46/// A call to contract, with vector of bytes as return type.
47/// It returns Option of Vec of bytes. Interpretation on the bytes depends on caller
48pub fn call_untyped(contract_address: PublicAddress, method_name: &str, arguments: Vec<u8>, value: u64) -> Option<Vec<u8>> {
49    let call_command = pchain_types::blockchain::Command::Call( CallInput{ 
50        target: contract_address, 
51        method: method_name.to_string(), 
52        arguments: <Vec<Vec<u8>>>::deserialize(&arguments).ok(), 
53        amount: if value > 0 { Some(value) } else { None }
54    }).serialize();
55
56    let call_ptr: *const u8 = call_command.as_ptr();
57    let call_len = call_command.len() as u32;
58
59    let mut return_val_ptr: u32 = 0;
60    let return_val_ptr_ptr = &mut return_val_ptr;
61
62    let return_value = unsafe {
63        let return_val_len = imports::call(call_ptr, call_len, return_val_ptr_ptr);
64        Vec::<u8>::from_raw_parts(return_val_ptr as *mut u8, return_val_len as usize, return_val_len as usize)
65    };
66
67    if return_value.is_empty() { 
68        None
69    } else {
70        Some(return_value)
71    }
72}
73
74/// transfer balance amount to another address. 
75pub fn transfer(recipient: PublicAddress, amount: u64) {
76    let mut transfer_bytes = Vec::new();
77    transfer_bytes.append(&mut recipient.to_vec());
78    transfer_bytes.append(&mut amount.to_le_bytes().to_vec());
79
80    let transfer_ptr = transfer_bytes.as_ptr();
81    unsafe { imports::transfer(transfer_ptr) }
82}