xpx_chain_sdk/models/transaction/
transaction_modify_multisig_account.rs

1/*
2 * Copyright 2018 ProximaX Limited. All rights reserved.
3 * Use of this source code is governed by the Apache 2.0
4 * license that can be found in the LICENSE file.
5 */
6
7use std::any::Any;
8use std::fmt;
9
10use anyhow::Result;
11use serde_json::Value;
12
13use crate::{
14    errors_const,
15    multisig::CosignatoryModification,
16    network::NetworkType,
17};
18use crate::account::PublicAccount;
19use crate::models::consts::{KEY_SIZE, MODIFY_MULTISIG_HEADER_SIZE};
20use crate::transaction::buffers;
21use crate::transaction::internal::cosignatory_modification_array_to_buffer;
22use crate::transaction::schema::modify_multisig_account_transaction_schema;
23
24use super::{
25    CommonTransaction, Deadline, Transaction,
26    TransactionType, TransactionVersion,
27};
28
29#[derive(Clone, Debug, Serialize, Builder, Deserialize)]
30#[builder(
31    create_empty = "empty",
32    build_fn(validate = "Self::validate", error = "crate::api::error::Error")
33)]
34#[serde(rename_all = "camelCase")]
35pub struct ModifyMultisigAccountTransaction {
36    /// Represents common transaction information..
37    #[builder(private, pattern = "mutable")]
38    pub common: CommonTransaction,
39    pub min_removal_delta: i8,
40    pub min_approval_delta: i8,
41    pub modifications: Vec<CosignatoryModification>,
42}
43
44impl ModifyMultisigAccountTransactionBuilder {
45    fn validate(&self) -> Result<()> {
46        if let Some(ref modifications) = self.modifications {
47            ensure!(!modifications.is_empty(), errors_const::ERR_EMPTY_MODIFICATIONS);
48        }
49
50        if let Some(min_approval_delta) = self.min_approval_delta {
51            ensure!(min_approval_delta != 0, errors_const::ERR_EMPTY_MODIFICATIONS);
52        }
53
54        if let Some(min_removal_delta) = self.min_removal_delta {
55            ensure!(min_removal_delta != 0, errors_const::ERR_EMPTY_MODIFICATIONS);
56        }
57
58        Ok(())
59    }
60
61    /// The deadline method sets the deadline field.
62    pub fn deadline(&mut self, value: Deadline) -> &mut ModifyMultisigAccountTransactionBuilder {
63        self.common.as_mut().map(|item| item.deadline = Some(value));
64        self
65    }
66
67    /// The max_fee method sets the max_fee field.
68    pub fn max_fee(&mut self, value: u64) -> &mut ModifyMultisigAccountTransactionBuilder {
69        self.common.as_mut().map(|item| item.max_fee = Some(value));
70        self
71    }
72}
73
74impl ModifyMultisigAccountTransaction {
75    /// Build a transfer transaction object.
76    pub fn builder(network_type: NetworkType) -> ModifyMultisigAccountTransactionBuilder {
77        let common = CommonTransaction::create_from_type(
78            TransactionType::MultisigAccountModify,
79            network_type,
80            TransactionVersion::MULTISIG_ACCOUNT_MODIFICATION,
81            Some(Default::default()),
82            None,
83        );
84        ModifyMultisigAccountTransactionBuilder { common: Some(common), ..Default::default() }
85    }
86}
87
88#[typetag::serde]
89impl Transaction for ModifyMultisigAccountTransaction {
90    fn size(&self) -> usize {
91        MODIFY_MULTISIG_HEADER_SIZE + ((KEY_SIZE + 1) * self.modifications.len())
92    }
93
94    fn as_value(&self) -> Value {
95        serde_json::to_value(self).unwrap_or_default()
96    }
97
98    fn get_common_transaction(&self) -> CommonTransaction {
99        self.common.to_owned()
100    }
101
102    fn to_serializer<'a>(&self) -> Vec<u8> {
103        // Build up a serialized buffer algorithmically.
104        // Initialize it with a capacity of 0 bytes.
105        let mut _builder = fb::FlatBufferBuilder::new();
106
107        let modifications = self.clone().modifications;
108
109        let modification_vector =
110            cosignatory_modification_array_to_buffer(&mut _builder, modifications);
111
112        let abs_vector = self.common.build_vector(&mut _builder, self.size());
113
114        let mut txn_builder =
115            buffers::ModifyMultisigAccountTransactionBufferBuilder::new(&mut _builder);
116        txn_builder.add_size_(self.size() as u32);
117        txn_builder.add_signature(abs_vector.signature_vec);
118        txn_builder.add_signer(abs_vector.signer_vec);
119        txn_builder.add_version(abs_vector.version_vec);
120        txn_builder.add_type_(abs_vector.type_vec);
121        txn_builder.add_max_fee(abs_vector.max_fee_vec);
122        txn_builder.add_deadline(abs_vector.deadline_vec);
123
124        txn_builder.add_min_removal_delta(self.min_removal_delta);
125        txn_builder.add_min_approval_delta(self.min_approval_delta);
126        txn_builder.add_num_modifications(self.modifications.len() as u8);
127        txn_builder.add_modifications(fb::WIPOffset::new(modification_vector));
128
129        let t = txn_builder.finish();
130        _builder.finish(t, None);
131
132        let buf = _builder.finished_data();
133
134        modify_multisig_account_transaction_schema().serialize(&mut buf.to_vec())
135    }
136
137    fn set_aggregate(&mut self, signer: PublicAccount) {
138        self.common.set_aggregate(signer)
139    }
140
141    fn as_any(&self) -> &dyn Any {
142        self
143    }
144
145    fn into_any(self: Box<Self>) -> Box<dyn Any> {
146        self
147    }
148
149    fn box_clone(&self) -> Box<dyn Transaction + 'static> {
150        Box::new((*self).clone())
151    }
152}
153
154impl fmt::Display for ModifyMultisigAccountTransaction {
155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156        write!(f, "{}", serde_json::to_string_pretty(&self).unwrap_or_default())
157    }
158}