neo3/neo_contract/
contract_management.rs1use async_trait::async_trait;
2use futures::{FutureExt, TryFutureExt};
3use primitive_types::H160;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 builder::TransactionBuilder,
8 neo_clients::{APITrait, JsonRpcProvider, RpcClient},
9 neo_contract::{ContractError, SmartContractTrait},
10 ContractIdentifiers,
11};
12use neo3::prelude::*;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct ContractManagement<'a, P: JsonRpcProvider> {
17 #[serde(deserialize_with = "deserialize_script_hash")]
18 #[serde(serialize_with = "serialize_script_hash")]
19 script_hash: ScriptHash,
20 #[serde(skip)]
21 provider: Option<&'a RpcClient<P>>,
22}
23
24impl<'a, P: JsonRpcProvider + 'static> ContractManagement<'a, P> {
25 pub fn new(script_hash: H160, provider: Option<&'a RpcClient<P>>) -> Self {
26 Self { script_hash, provider }
27 }
28
29 pub async fn get_minimum_deployment_fee(&self) -> Result<u64, ContractError> {
30 Ok(self
31 .provider
32 .unwrap()
33 .invoke_function(&self.script_hash, "getMinimumDeploymentFee".to_string(), vec![], None)
34 .await?
35 .stack[0]
36 .as_int()
37 .unwrap() as u64)
38 }
39
40 pub async fn set_minimum_deployment_fee(&self, fee: u64) -> Result<u64, ContractError> {
41 Ok(self
42 .provider
43 .unwrap()
44 .invoke_function(
45 &self.script_hash,
46 "setMinimumDeploymentFee".to_string(),
47 vec![fee.into()],
48 None,
49 )
50 .await?
51 .stack[0]
52 .as_int()
53 .unwrap() as u64)
54 }
55
56 pub async fn get_contract(&self, hash: H160) -> Result<ContractState, ContractError> {
57 self.provider
58 .unwrap()
59 .get_contract_state(hash)
60 .await
61 .map_err(|e| ContractError::RuntimeError(e.to_string()))
62 }
63
64 pub async fn get_contract_by_id(&self, id: u32) -> Result<ContractState, ContractError> {
65 let hash = self.get_contract_hash_by_id(id).await.unwrap();
66 self.get_contract(hash).await
67 }
68
69 pub async fn get_contract_hash_by_id(&self, id: u32) -> Result<ScriptHash, ContractError> {
70 let result = self
71 .provider
72 .unwrap()
73 .invoke_function(
74 &self.script_hash,
75 "getContractById".to_string(),
76 vec![id.into()],
77 None,
78 )
79 .await
80 .unwrap()
81 .stack;
82
83 let item = &result[0];
84 Ok(ScriptHash::from_slice(&item.as_bytes().unwrap()))
85 }
86
87 pub async fn get_contract_hashes(&self) -> Result<ContractIdentifiers, ContractError> {
88 self.provider
89 .unwrap()
90 .invoke_function(&self.script_hash, "getContractHashes".to_string(), vec![], None)
91 .await
92 .map(|item| ContractIdentifiers::from_invocation_result(item).unwrap())
93 .map_err(|e| {
94 ContractError::from(e)
97 })
98 }
99
100 pub async fn has_method(
101 &self,
102 hash: H160,
103 method: &str,
104 params: usize,
105 ) -> Result<bool, ContractError> {
106 self.provider
107 .unwrap()
108 .invoke_function(
109 &self.script_hash,
110 "hasMethod".to_string(),
111 vec![hash.into(), method.into(), params.into()],
112 None,
113 )
114 .await
115 .map(|item| item.stack[0].as_bool().unwrap())
116 .map_err(|e| ContractError::RuntimeError(e.to_string()))
117 }
118
119 pub async fn deploy(
120 &self,
121 nef: &NefFile,
122 manifest: &[u8],
123 data: Option<ContractParameter>,
124 ) -> Result<TransactionBuilder<P>, ContractError> {
125 let params = vec![nef.into(), manifest.into(), data.unwrap()];
126 let tx = self.invoke_function("deploy", params).await;
127 tx
128 }
129}
130
131#[async_trait]
132impl<'a, P: JsonRpcProvider> SmartContractTrait<'a> for ContractManagement<'a, P> {
133 type P = P;
134
135 fn script_hash(&self) -> H160 {
136 self.script_hash.clone()
137 }
138
139 fn set_script_hash(&mut self, script_hash: H160) {
140 self.script_hash = script_hash;
141 }
142
143 fn provider(&self) -> Option<&RpcClient<P>> {
144 self.provider
145 }
146}