1pub mod structs;
2
3use crate::api::client::{APIClient, Provider};
4use crate::api::system::structs::{
5 CreateAccountParams, DelegateBandwidthAction, NewAccountAction, SetAbiAction, SetCodeAction,
6 TransferAction,
7};
8use crate::api::v1::structs::{ClientError, SendTransactionResponse, SendTransactionResponseError};
9use crate::chain::abi::ABI;
10use crate::chain::action::{Action, PermissionLevel};
11use crate::chain::binary_extension::BinaryExtension;
12use crate::chain::name::Name;
13use crate::chain::private_key::PrivateKey;
14use crate::name;
15use crate::serializer::Encoder;
16use sha2::{Digest, Sha256};
17
18#[derive(Debug, Default, Clone)]
19pub struct SystemAPI<T: Provider> {
20 api_client: APIClient<T>,
21}
22
23impl<T: Provider> SystemAPI<T> {
24 pub fn new(api_client: APIClient<T>) -> Self {
25 SystemAPI { api_client }
26 }
27
28 pub async fn create_account(
29 &self,
30 create_params: CreateAccountParams,
31 creator_private_key: PrivateKey,
32 ) -> Result<SendTransactionResponse, ClientError<SendTransactionResponseError>> {
33 let CreateAccountParams {
34 name,
35 creator,
36 owner,
37 active,
38 ram_bytes,
39 stake_net,
40 stake_cpu,
41 transfer,
42 } = create_params;
43 let new_account_action = Action::new(
44 name!("eosio"),
45 name!("newaccount"),
46 PermissionLevel::new(creator, name!("active")),
47 NewAccountAction {
48 creator,
49 name,
50 owner,
51 active,
52 },
53 );
54 let buy_ram_action = Action::new(
55 name!("eosio"),
56 name!("buyrambytes"),
57 PermissionLevel::new(creator, name!("active")),
58 structs::BuyRamBytesAction {
59 payer: creator,
60 receiver: name,
61 bytes: ram_bytes,
62 },
63 );
64 let delegate_bw_action = Action::new(
65 name!("eosio"),
66 name!("delegatebw"),
67 PermissionLevel::new(creator, name!("active")),
68 DelegateBandwidthAction {
69 from: creator,
70 receiver: name,
71 stake_net_quantity: stake_net,
72 stake_cpu_quantity: stake_cpu,
73 transfer,
74 },
75 );
76 let actions = vec![new_account_action, buy_ram_action, delegate_bw_action];
77 self.api_client.transact(actions, creator_private_key).await
78 }
79
80 pub async fn transfer(
81 &self,
82 transfer_action: TransferAction,
83 sender_private_key: PrivateKey,
84 token_contract: Option<Name>,
85 ) -> Result<SendTransactionResponse, ClientError<SendTransactionResponseError>> {
86 self.api_client
87 .transact(
88 vec![Action::new(
89 token_contract.unwrap_or(name!("eosio.token")),
90 name!("transfer"),
91 PermissionLevel::new(transfer_action.from, name!("active")),
92 transfer_action,
93 )],
94 sender_private_key,
95 )
96 .await
97 }
98
99 pub async fn set_contract_from_files(
100 &self,
101 account: Name,
102 wasm_path: &str,
103 abi_path: &str,
104 memo: Option<String>,
105 private_key: PrivateKey,
106 ) -> Result<SendTransactionResponse, ClientError<SendTransactionResponseError>> {
107 let wasm = std::fs::read(wasm_path).unwrap();
108 let abi_json_bytes = std::fs::read(abi_path).unwrap();
109 let abi: ABI = serde_json::from_slice(&abi_json_bytes).unwrap();
110 let abi_bytes = Encoder::pack(&abi);
111 self.set_contract(account, wasm, abi_bytes, memo, private_key)
112 .await
113 }
114
115 pub async fn set_contract(
116 &self,
117 account: Name,
118 wasm: Vec<u8>,
119 abi: Vec<u8>,
120 memo: Option<String>,
121 private_key: PrivateKey,
122 ) -> Result<SendTransactionResponse, ClientError<SendTransactionResponseError>> {
123 let mut hasher = Sha256::new();
124 hasher.update(&wasm);
125 let wasm_hash = hasher.finalize();
126 println!(
127 "Setting contract for account: {:?}, with hash: {:?}",
128 account.as_string(),
129 wasm_hash
130 );
131 self.api_client
132 .transact(
133 vec![
134 Action::new(
135 name!("eosio"),
136 name!("setcode"),
137 PermissionLevel::new(account, name!("active")),
138 SetCodeAction {
139 vmtype: 0,
140 vmversion: 0,
141 account,
142 code: wasm,
143 memo: BinaryExtension::new(memo.clone()),
144 },
145 ),
146 Action::new(
147 name!("eosio"),
148 name!("setabi"),
149 PermissionLevel::new(account, name!("active")),
150 SetAbiAction {
151 account,
152 abi,
153 memo: BinaryExtension::new(memo),
154 },
155 ),
156 ],
157 private_key,
158 )
159 .await
160 }
161}