1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::{PayloadDecoder, Result};
use ex3_node_error::OtherError;
use ex3_timestamp::TimeInNs;
use num_bigint::BigUint;
use num_traits::Num;
use serde_bytes::ByteBuf;
use std::str::FromStr;

use crate::tx_type_dto::{AssetAccountBinding, AssetAccountUnbinding};

impl PayloadDecoder {
    /// Decode asset account binding
    ///
    /// Payload plain text:
    /// ```text
    ///      subject: asset account binding
    ///      wallet_id: 0x1234
    ///      nonce: : 0x1234
    ///      sign_schema: 0x12
    ///      data.main: 0x12
    ///      data.asset: 0x1
    ///      data.initiator: 0x1234
    ///      data.sign_schema_initiator: 0x12
    ///      data.sig_initiator: 0x1234
    ///      data.timestamp: 17239321323
    /// ```
    /// The payload should be in the following format:
    /// `{sign_schema}|{data.initiator}|{data.main}|{data.asset}|{data.timestamp}|{data.sig_initiator}|{data.sig_initiator}`
    ///
    /// Used for the following transactions:
    /// - [TransactionType::AssetAccountBinding]
    pub fn decode_to_asset_account_binding(
        payload: &[u8],
    ) -> Result<ex3_node_types::transaction::AssetAccountBinding> {
        let payload_str = String::from_utf8(payload.as_ref().to_vec()).expect("should success");

        let hexes = payload_str.split('|').collect::<Vec<&str>>();

        let err = OtherError::new("Invalid payload");

        if hexes.len() != 7 {
            return Err(err.clone().into());
        }

        let sign_schema = u8::from_str_radix(hexes[0], 16).map_err(|_| err.clone())?;
        let initiator = BigUint::from_str_radix(hexes[1], 16).map_err(|_| err.clone())?;
        let main_wallet_id = BigUint::from_str_radix(hexes[2], 16).map_err(|_| err.clone())?;
        let asset_wallet_id = BigUint::from_str_radix(hexes[3], 16).map_err(|_| err.clone())?;
        let timestamp = u64::from_str(hexes[4]).map_err(|_| err.clone())?;
        let sign_schema_initiator = u8::from_str_radix(hexes[5], 16).map_err(|_| err.clone())?;
        let sig_initiator = hex::decode(hexes[6]).map_err(|_| err.clone())?;

        let tx = AssetAccountBinding {
            sign_schema,
            main: main_wallet_id,
            asset: asset_wallet_id,
            initiator,
            sign_schema_initiator,
            sig_initiator: ByteBuf::from(sig_initiator),
            timestamp: TimeInNs(timestamp),
        };

        Ok(tx.into())
    }

    /// Decode asset account unbinding
    ///
    /// Payload plain text:
    /// ```text
    ///     subject: asset account unbinding
    ///     wallet_id: 0x1234
    ///     nonce: 0x1234
    ///     sign_schema: 0x1
    ///     data.main: 0x12213
    ///     data.asset: 0x112344
    /// ```
    /// The payload should be in the following format:
    /// ``{data.main}|{data.asset}``
    pub fn decode_to_asset_account_unbinding(
        payload: &[u8],
    ) -> Result<ex3_node_types::transaction::AssetAccountUnbinding> {
        let payload_str = String::from_utf8(payload.as_ref().to_vec()).expect("should success");

        let hexes = payload_str.split('|').collect::<Vec<&str>>();

        let err = OtherError::new("Invalid payload");

        if hexes.len() != 3 {
            return Err(err.clone().into());
        }

        let sign_schema = u8::from_str_radix(hexes[0], 16).map_err(|_| err.clone())?;
        let main_wallet_id = BigUint::from_str_radix(hexes[1], 16).map_err(|_| err.clone())?;
        let asset_wallet_id = BigUint::from_str_radix(hexes[2], 16).map_err(|_| err.clone())?;

        let tx = AssetAccountUnbinding {
            sign_schema,
            main: main_wallet_id,
            asset: asset_wallet_id,
        };

        Ok(tx.into())
    }
}