Skip to main content

zera_sc/types/
txn.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Serialize, Deserialize, Debug, Clone)]
4pub enum TxnSender {
5    Delegate { sc_name: String, sc_instance: String },
6    Current,
7    ContractBefore,
8    OriginalContract,
9    User,
10}
11
12#[derive(Serialize, Deserialize, Debug, Clone)]
13pub(crate) struct NetworkTXN {
14    pub(crate) txn_type: TransactionType,
15    pub(crate) payload: String,
16    pub(crate) sender: TxnSender,
17}
18
19#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
20pub enum TransactionType {
21    #[default]
22    UnknownType,
23    CoinType,
24    MintType,
25    ItemMintType,
26    ContractTxnType,
27    VoteType,
28    ProposalType,
29    SmartContractType,
30    SmartContractExecuteType,
31    ExpenseRatioType,
32    NftType,
33    UpdateContractType,
34    ValidatorRegistrationType,
35    ValidatorHeartbeatType,
36    ProposalResultType,
37    DelegatedVotingType,
38    RevokeType,
39    QuashType,
40    FastQuorumType,
41    ComplianceType,
42    SbtBurnType,
43    RequiredVersion,
44    SmartContractInstantiateType,
45    AllowanceType,
46    ProposalCancelType,
47}
48
49#[derive(Serialize, Deserialize, Debug, Clone, Default)]
50pub struct ContractUpdateTXN {
51    pub contract_id: String,
52    pub contract_version: u64,
53    pub name: Option<String>,
54    pub governance: Option<Governance>,
55    pub restricted_keys: Vec<RestrictedKey>,
56    pub contract_fees: Option<ContractFees>,
57    pub custom_parameters: Vec<KeyValuePair>,
58    pub expense_ratio: Vec<ExpenseRatio>,
59    pub token_compliance: Vec<TokenCompliance>,
60    pub kyc_status: Option<bool>,
61    pub immutable_kyc_status: Option<bool>,
62    pub quash_threshold: Option<u32>,
63}
64
65#[derive(Serialize, Deserialize, Debug, Clone, Default)]
66pub struct InstrumentContractTXN {
67    pub contract_version: u64,
68    pub symbol: String,
69    pub name: String,
70    pub governance: Option<Governance>,
71    pub restricted_keys: Vec<RestrictedKey>,
72    pub max_supply: Option<String>,
73    pub contract_fees: Option<ContractFees>,
74    pub premint_wallets: Vec<PreMintWallet>,
75    pub coin_denomination: Option<CoinDenomination>,
76    pub custom_parameters: Vec<KeyValuePair>,
77    pub contract_id: String,
78    pub expense_ratio: Vec<ExpenseRatio>,
79    pub contract_type: ContractType,
80    pub update_contract_fees: bool,
81    pub update_expense_ratio: bool,
82    pub quash_threshold: Option<u32>,
83    pub token_compliance: Vec<TokenCompliance>,
84    pub kyc_status: bool,
85    pub immutable_kyc_status: bool,
86    pub max_supply_release: Vec<MaxSupplyRelease>,
87}
88
89#[derive(Serialize, Deserialize, Debug, Clone, Default)]
90pub struct PreMintWallet {
91    pub address: String,
92    pub amount: String,
93}
94
95#[derive(Serialize, Deserialize, Debug, Clone, Default)]
96pub struct CoinDenomination {
97    pub denomination_name: String,
98    pub amount: String,
99}
100
101#[derive(Serialize, Deserialize, Debug, Clone, Default)]
102pub struct MaxSupplyRelease {
103    pub release_date: ProtoTimestamp,
104    pub amount: String,
105}
106
107#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
108pub enum ContractType {
109    #[default]
110    Token,
111    Nft,
112    Sbt,
113}
114
115#[derive(Serialize, Deserialize, Debug, Clone, Default)]
116pub struct Governance {
117    pub governance_type: GovernanceType,
118    pub regular_quorum: u32,
119    pub fast_quorum: Option<u32>,
120    pub voting_instrument: Vec<String>,
121    pub threshold: u32,
122    pub chicken_dinner: Option<bool>,
123    pub allow_multi: bool,
124    pub voting_period: Option<u32>,
125    pub allowed_proposal_instrument: Vec<String>,
126    pub proposal_period: Option<ProposalPeriod>,
127    pub stage_length: Vec<Stage>,
128    pub start_timestamp: Option<ProtoTimestamp>,
129    pub max_approved: Option<u32>,
130}
131
132#[derive(Serialize, Deserialize, Debug, Clone, Default)]
133pub struct Stage {
134    pub length: u32,
135    pub period: ProposalPeriod,
136    pub break_stage: bool,
137    pub max_approved: u32,
138}
139
140#[derive(Serialize, Deserialize, Debug, Clone, Default)]
141pub struct RestrictedKey {
142    pub public_key: PublicKey,
143    pub time_delay: i64,
144    pub global: bool,
145    pub update_contract: bool,
146    pub transfer: bool,
147    pub quash: bool,
148    pub mint: bool,
149    pub vote: bool,
150    pub propose: bool,
151    pub compliance: bool,
152    pub expense_ratio: bool,
153    pub revoke: bool,
154    pub key_weight: u32,
155}
156
157#[derive(Serialize, Deserialize, Debug, Clone, Default)]
158pub struct PublicKey {
159    /// Base58-encoded single public key (e.g. `"A_c_7kdro2TE..."`).
160    pub single: String,
161    pub multi: Option<MultiKey>,
162    /// Smart-contract auth identifier in the form `"sc_<contract>_<instance>"`,
163    /// e.g. `"sc_sc_test_proxy_1"`. Used to identify a smart contract as a
164    /// restricted-key holder.
165    pub smart_contract_auth: Option<String>,
166    /// Governance auth identifier.
167    pub governance_auth: Option<String>,
168}
169
170impl PublicKey {
171    /// Build a `PublicKey` that authorizes a smart contract, identified by
172    /// its `name` and optional `instance` (defaults to `"1"`).
173    ///
174    /// Equivalent to populating `smart_contract_auth` with the string
175    /// returned by [`crate::wallet::sc_auth`] and leaving all other fields
176    /// at their defaults.
177    pub fn sc(contract: &str, instance: Option<&str>) -> Self {
178        let inst = instance.unwrap_or("1");
179        PublicKey {
180            smart_contract_auth: Some(format!("sc_{}_{}", contract, inst)),
181            ..Default::default()
182        }
183    }
184}
185
186#[derive(Serialize, Deserialize, Debug, Clone, Default)]
187pub struct MultiKey {
188    /// Base58-encoded public keys, with class prefix (e.g. `"c1_<key>"`).
189    pub public_keys: Vec<String>,
190    pub signatures: Vec<Vec<u8>>,
191    pub multi_patterns: Vec<MultiPatterns>,
192    pub hash_tokens: Vec<String>,
193}
194
195#[derive(Serialize, Deserialize, Debug, Clone, Default)]
196pub struct MultiPatterns {
197    pub class: Vec<u32>,
198    pub required: Vec<u32>,
199}
200
201#[derive(Serialize, Deserialize, Debug, Clone, Default)]
202pub struct ContractFees {
203    pub fee: String,
204    /// Base58-encoded fee recipient wallet address.
205    pub fee_address: Option<String>,
206    pub burn: String,
207    pub validator: String,
208    pub allowed_fee_instrument: Vec<String>,
209    pub contract_fee_type: ContractFeeType,
210}
211
212#[derive(Serialize, Deserialize, Debug, Clone, Default)]
213pub struct KeyValuePair {
214    pub key: String,
215    pub value: String,
216}
217
218#[derive(Serialize, Deserialize, Debug, Clone, Default)]
219pub struct ExpenseRatio {
220    pub day: u32,
221    pub month: u32,
222    pub percent: u32,
223}
224
225#[derive(Serialize, Deserialize, Debug, Clone, Default)]
226pub struct TokenCompliance {
227    pub compliance: Vec<Compliance>,
228}
229
230#[derive(Serialize, Deserialize, Debug, Clone, Default)]
231pub struct Compliance {
232    pub contract_id: String,
233    pub compliance_level: u32,
234}
235
236#[derive(Serialize, Deserialize, Debug, Clone, Default)]
237pub struct ProtoTimestamp {
238    pub seconds: i64,
239    pub nanos: i32,
240}
241
242#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
243pub enum ContractFeeType {
244    #[default]
245    None,
246    Fixed,
247    CurEquivalent,
248    Percentage,
249}
250
251#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
252pub enum GovernanceType {
253    #[default]
254    Adaptive,
255    Staged,
256    Cycle,
257    Staggered,
258    Remove,
259}
260
261#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
262pub enum ProposalPeriod {
263    #[default]
264    Days,
265    Months,
266}
267
268/// Full coin-transfer transaction, mirroring the network's `CoinTXN` proto
269/// (minus `base`, which the network fills in from the transaction context).
270///
271/// Use this when you need the full expressiveness of a coin transfer: multiple
272/// inputs, multiple outputs, explicit fee routing, etc. For the common
273/// "send X of Y to one recipient" case, prefer [`crate::transfer::send`] from
274/// the `transfer` module, which handles all of this internally.
275///
276/// # Address / key fields
277///
278/// Every wallet address or public key in this transaction — including
279/// `output_transfers[i].wallet_address` and `auth.public_key[i].single` — is
280/// passed as a base58 `String`. The network decodes it on its side. Raw
281/// binary fields (signatures, hashes) stay as `Vec<u8>`.
282#[derive(Serialize, Deserialize, Debug, Clone, Default)]
283pub struct CoinTXN {
284    pub contract_id: String,
285    /// Sender authorization. For smart-contract-originated transfers the
286    /// network populates `public_key`, `signature`, and `nonce` from the
287    /// `TxnSender` context — callers typically leave this at `Default`.
288    pub auth: TransferAuthentication,
289    pub input_transfers: Vec<InputTransfers>,
290    pub output_transfers: Vec<OutputTransfers>,
291    /// Contract used to pay this transfer's contract-level fee, if the
292    /// token being transferred has one configured. Leave as `None` when
293    /// transferring a token without contract fees (e.g. `$ZRA+0000`).
294    pub contract_fee_id: Option<String>,
295    pub contract_fee_amount: Option<String>,
296}
297
298/// Sender authentication for a `CoinTXN`. Mirrors the network's
299/// `TransferAuthentication` proto. Each position in `public_key`,
300/// `signature`, and `nonce` refers to the same signer.
301///
302/// For SC-originated transfers the network populates every field here from
303/// the `TxnSender` context; callers typically leave this at `Default`.
304#[derive(Serialize, Deserialize, Debug, Clone, Default)]
305pub struct TransferAuthentication {
306    pub public_key: Vec<PublicKey>,
307    pub signature: Vec<Vec<u8>>,
308    pub nonce: Vec<u64>,
309    /// Base58-encoded allowance wallet addresses.
310    pub allowance_address: Vec<String>,
311    pub allowance_nonce: Vec<u64>,
312}
313
314/// Describes which signer (by index into `TransferAuthentication.public_key`)
315/// is sending, how much, and how fees are split. Mirrors `InputTransfers`.
316///
317/// `fee_percent` and `contract_fee_percent` use a fixed-point scale where
318/// `100_000_000` = 100%.
319#[derive(Serialize, Deserialize, Debug, Clone, Default)]
320pub struct InputTransfers {
321    pub index: u64,
322    pub amount: String,
323    pub fee_percent: u32,
324    pub contract_fee_percent: Option<u32>,
325}
326
327/// A single coin-transfer output. Mirrors `OutputTransfers`.
328#[derive(Serialize, Deserialize, Debug, Clone, Default)]
329pub struct OutputTransfers {
330    /// Base58-encoded recipient wallet address.
331    pub wallet_address: String,
332    pub amount: String,
333    pub memo: Option<String>,
334}
335
336/// Full mint transaction, mirroring the network's `MintTXN` proto (minus
337/// `base`, which the network fills in).
338///
339/// For the common "mint X to Y" case, prefer [`crate::transfer::mint`] from
340/// the `transfer` module.
341#[derive(Serialize, Deserialize, Debug, Clone, Default)]
342pub struct MintTXN {
343    pub contract_id: String,
344    pub amount: String,
345    /// Base58-encoded recipient wallet address.
346    pub recipient_address: String,
347}
348