tonlib_core/wallet/
version_helper.rs

1use super::wallet_code::WALLET_VERSION_BY_CODE;
2use crate::cell::{ArcCell, Cell, CellBuilder, TonCellError};
3use crate::tlb_types::tlb::TLB;
4use crate::wallet::mnemonic::KeyPair;
5use crate::wallet::versioned::highload_v2::WalletDataHighloadV2R2;
6use crate::wallet::versioned::v1_v2::{WalletDataV1V2, WalletExtMsgBodyV2};
7use crate::wallet::versioned::v3::{WalletDataV3, WalletExtMsgBodyV3};
8use crate::wallet::versioned::v4::{WalletDataV4, WalletExtMsgBodyV4};
9use crate::wallet::versioned::v5::{WalletDataV5, WalletExtMsgBodyV5};
10use crate::wallet::wallet_code::WALLET_CODE_BY_VERSION;
11use crate::wallet::wallet_version::WalletVersion;
12use crate::TonHash;
13
14pub struct VersionHelper;
15
16impl VersionHelper {
17    pub fn get_data(
18        version: WalletVersion,
19        key_pair: &KeyPair,
20        wallet_id: i32,
21    ) -> Result<Cell, TonCellError> {
22        let public_key = TonHash::try_from(key_pair.public_key.as_slice())?;
23        let data_cell = match version {
24            WalletVersion::V1R1
25            | WalletVersion::V1R2
26            | WalletVersion::V1R3
27            | WalletVersion::V2R1
28            | WalletVersion::V2R2 => WalletDataV1V2::new(public_key).to_cell()?,
29            WalletVersion::V3R1 | WalletVersion::V3R2 => {
30                WalletDataV3::new(wallet_id, public_key).to_cell()?
31            }
32            WalletVersion::V4R1 | WalletVersion::V4R2 => {
33                WalletDataV4::new(wallet_id, public_key).to_cell()?
34            }
35            WalletVersion::V5R1 => WalletDataV5::new(wallet_id, public_key).to_cell()?,
36            WalletVersion::HighloadV2R2 => {
37                WalletDataHighloadV2R2::new(wallet_id, public_key).to_cell()?
38            }
39            WalletVersion::HighloadV1R1
40            | WalletVersion::HighloadV1R2
41            | WalletVersion::HighloadV2
42            | WalletVersion::HighloadV2R1 => {
43                let err_str = format!("initial_data for {version:?} is unsupported");
44                return Err(TonCellError::InternalError(err_str));
45            }
46        };
47        Ok(data_cell)
48    }
49
50    pub fn get_code(version: WalletVersion) -> Result<&'static ArcCell, TonCellError> {
51        WALLET_CODE_BY_VERSION.get(&version).ok_or_else(|| {
52            let err_str = format!("No code found for {version:?}");
53            TonCellError::InternalError(err_str)
54        })
55    }
56
57    pub fn get_version(code_hash: &TonHash) -> Result<&WalletVersion, TonCellError> {
58        WALLET_VERSION_BY_CODE
59            .get(code_hash)
60            .ok_or_else(|| TonCellError::InternalError("No wallet version found".to_string()))
61    }
62
63    pub fn build_ext_msg<T: AsRef<[ArcCell]>>(
64        version: WalletVersion,
65        valid_until: u32,
66        msg_seqno: u32,
67        wallet_id: i32,
68        msgs_refs: T,
69    ) -> Result<Cell, TonCellError> {
70        let msgs: Vec<ArcCell> = msgs_refs.as_ref().to_vec();
71
72        match version {
73            WalletVersion::V2R1 | WalletVersion::V2R2 => WalletExtMsgBodyV2 {
74                msg_seqno,
75                valid_until,
76                msgs_modes: vec![3u8; msgs.len()],
77                msgs,
78            }
79            .to_cell(),
80            WalletVersion::V3R1 | WalletVersion::V3R2 => WalletExtMsgBodyV3 {
81                subwallet_id: wallet_id,
82                msg_seqno,
83                valid_until,
84                msgs_modes: vec![3u8; msgs.len()],
85                msgs,
86            }
87            .to_cell(),
88            WalletVersion::V4R1 | WalletVersion::V4R2 => WalletExtMsgBodyV4 {
89                subwallet_id: wallet_id,
90                valid_until,
91                msg_seqno,
92                opcode: 0,
93                msgs_modes: vec![3u8; msgs.len()],
94                msgs,
95            }
96            .to_cell(),
97            WalletVersion::V5R1 => WalletExtMsgBodyV5 {
98                wallet_id,
99                valid_until,
100                msg_seqno,
101                msgs_modes: vec![3u8; msgs.len()],
102                msgs,
103            }
104            .to_cell(),
105            _ => {
106                let err_str = format!("build_ext_msg for {version:?} is unsupported");
107                Err(TonCellError::InternalError(err_str))
108            }
109        }
110    }
111
112    pub fn sign_msg(
113        version: WalletVersion,
114        msg_cell: &Cell,
115        sign: &[u8],
116    ) -> Result<Cell, TonCellError> {
117        let signed_cell = match version {
118            // different order
119            WalletVersion::V5R1 => {
120                let mut builder = CellBuilder::new();
121                builder.store_cell(msg_cell)?;
122                builder.store_slice(sign)?;
123                builder.build()?
124            }
125            _ => {
126                let mut builder = CellBuilder::new();
127                builder.store_slice(sign)?;
128                builder.store_cell(msg_cell)?;
129                builder.build()?
130            }
131        };
132        Ok(signed_cell)
133    }
134}