1use std::{
20 fmt::{self, Debug},
21 str::FromStr,
22};
23
24#[cfg(feature = "async")]
25use darkfi_serial::async_trait;
26use darkfi_serial::{SerialDecodable, SerialEncodable};
27
28use super::{
29 crypto::ContractId,
30 hex::{decode_hex_arr, AsHex},
31 ContractError, GenericResult,
32};
33use crate::crypto::{DAO_CONTRACT_ID, DEPLOYOOOR_CONTRACT_ID, MONEY_CONTRACT_ID};
34
35#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, SerialEncodable, SerialDecodable)]
36pub struct TransactionHash(pub [u8; 32]);
38
39impl TransactionHash {
40 pub fn new(data: [u8; 32]) -> Self {
41 Self(data)
42 }
43
44 pub fn none() -> Self {
45 Self([0; 32])
46 }
47
48 #[inline]
49 pub fn inner(&self) -> &[u8; 32] {
50 &self.0
51 }
52
53 pub fn as_string(&self) -> String {
54 self.0.hex().to_string()
55 }
56}
57
58impl FromStr for TransactionHash {
59 type Err = ContractError;
60
61 fn from_str(tx_hash_str: &str) -> GenericResult<Self> {
62 Ok(Self(decode_hex_arr(tx_hash_str)?))
63 }
64}
65
66impl fmt::Display for TransactionHash {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 write!(f, "{}", self.0.hex())
69 }
70}
71
72#[derive(Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
76pub struct ContractCall {
77 pub contract_id: ContractId,
79 pub data: Vec<u8>,
81}
82impl ContractCall {
85 pub fn is_money_fee(&self) -> bool {
87 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x00)
88 }
89
90 pub fn is_money_genesis_mint(&self) -> bool {
92 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x01)
93 }
94
95 pub fn is_money_pow_reward(&self) -> bool {
97 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x02)
98 }
99
100 pub fn is_money_transfer(&self) -> bool {
102 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x03)
103 }
104
105 pub fn is_money_otc_swap(&self) -> bool {
107 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x04)
108 }
109
110 pub fn is_money_auth_token_mint(&self) -> bool {
112 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x05)
113 }
114
115 pub fn is_money_auth_token_freeze(&self) -> bool {
117 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x06)
118 }
119
120 pub fn is_money_token_mint(&self) -> bool {
122 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x07)
123 }
124
125 pub fn is_dao_mint(&self) -> bool {
127 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x00)
128 }
129
130 pub fn is_dao_propose(&self) -> bool {
132 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x01)
133 }
134
135 pub fn is_dao_vote(&self) -> bool {
137 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x02)
138 }
139
140 pub fn is_dao_exec(&self) -> bool {
142 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x03)
143 }
144
145 pub fn is_dao_auth_money_transfer(&self) -> bool {
147 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x04)
148 }
149
150 pub fn is_deployment(&self) -> bool {
152 self.matches_contract_call_type(*DEPLOYOOOR_CONTRACT_ID, 0x00)
153 }
154
155 pub fn matches_contract_call_type(&self, contract_id: ContractId, func_code: u8) -> bool {
157 !self.data.is_empty() && self.contract_id == contract_id && self.data[0] == func_code
158 }
159}
160
161impl Debug for ContractCall {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 write!(f, "ContractCall(id={:?}", self.contract_id.inner())?;
165 let calldata = &self.data;
166 if !calldata.is_empty() {
167 write!(f, ", function_code={}", calldata[0])?;
168 }
169 write!(f, ")")
170 }
171}