iota_sdk/client/api/
types.rs

1// Copyright 2022 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use crypto::keys::bip44::Bip44;
5use serde::{Deserialize, Serialize};
6
7use crate::{
8    client::secret::types::{InputSigningData, InputSigningDataDto},
9    types::{
10        block::{
11            address::{dto::AddressDto, Address},
12            output::{dto::OutputDto, Output},
13            payload::{
14                transaction::{
15                    dto::{TransactionEssenceDto, TransactionPayloadDto},
16                    TransactionEssence,
17                },
18                TransactionPayload,
19            },
20            Error,
21        },
22        TryFromDto, ValidationParams,
23    },
24    utils::serde::bip44::option_bip44,
25};
26
27/// Helper struct for offline signing
28#[derive(Clone, Debug, Eq, PartialEq)]
29pub struct PreparedTransactionData {
30    /// Transaction essence
31    pub essence: TransactionEssence,
32    /// Required input information for signing. Inputs need to be ordered by address type
33    pub inputs_data: Vec<InputSigningData>,
34    /// Optional remainder output information
35    pub remainder: Option<RemainderData>,
36}
37
38/// PreparedTransactionData Dto
39#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct PreparedTransactionDataDto {
42    /// Transaction essence
43    pub essence: TransactionEssenceDto,
44    /// Required address information for signing
45    pub inputs_data: Vec<InputSigningDataDto>,
46    /// Optional remainder output information
47    pub remainder: Option<RemainderDataDto>,
48}
49
50impl From<&PreparedTransactionData> for PreparedTransactionDataDto {
51    fn from(value: &PreparedTransactionData) -> Self {
52        Self {
53            essence: TransactionEssenceDto::from(&value.essence),
54            inputs_data: value.inputs_data.iter().map(InputSigningDataDto::from).collect(),
55            remainder: value.remainder.as_ref().map(RemainderDataDto::from),
56        }
57    }
58}
59
60impl TryFromDto for PreparedTransactionData {
61    type Dto = PreparedTransactionDataDto;
62    type Error = Error;
63
64    fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result<Self, Self::Error> {
65        Ok(Self {
66            essence: TransactionEssence::try_from_dto_with_params(dto.essence, &params)
67                .map_err(|_| Error::InvalidField("essence"))?,
68            inputs_data: dto
69                .inputs_data
70                .into_iter()
71                .map(|i| InputSigningData::try_from_dto_with_params(i, &params))
72                .collect::<crate::client::Result<Vec<InputSigningData>>>()
73                .map_err(|_| Error::InvalidField("input_data"))?,
74            remainder: match dto.remainder {
75                Some(remainder) => Some(
76                    RemainderData::try_from_dto_with_params(remainder, &params)
77                        .map_err(|_| Error::InvalidField("remainder"))?,
78                ),
79                None => None,
80            },
81        })
82    }
83}
84
85/// Helper struct for offline signing
86#[derive(Clone, Debug, Eq, PartialEq)]
87pub struct SignedTransactionData {
88    /// Signed transaction payload
89    pub transaction_payload: TransactionPayload,
90    /// Required address information for signing
91    pub inputs_data: Vec<InputSigningData>,
92}
93
94/// SignedTransactionData Dto
95#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
96#[serde(rename_all = "camelCase")]
97pub struct SignedTransactionDataDto {
98    /// Transaction essence
99    pub transaction_payload: TransactionPayloadDto,
100    /// Required address information for signing
101    pub inputs_data: Vec<InputSigningDataDto>,
102}
103
104impl From<&SignedTransactionData> for SignedTransactionDataDto {
105    fn from(value: &SignedTransactionData) -> Self {
106        Self {
107            transaction_payload: TransactionPayloadDto::from(&value.transaction_payload),
108            inputs_data: value.inputs_data.iter().map(InputSigningDataDto::from).collect(),
109        }
110    }
111}
112
113impl TryFromDto for SignedTransactionData {
114    type Dto = SignedTransactionDataDto;
115    type Error = Error;
116
117    fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result<Self, Self::Error> {
118        Ok(Self {
119            transaction_payload: TransactionPayload::try_from_dto_with_params(dto.transaction_payload, &params)
120                .map_err(|_| Error::InvalidField("transaction_payload"))?,
121            inputs_data: dto
122                .inputs_data
123                .into_iter()
124                .map(|i| InputSigningData::try_from_dto_with_params(i, &params))
125                .collect::<crate::client::Result<Vec<InputSigningData>>>()
126                .map_err(|_| Error::InvalidField("inputs_data"))?,
127        })
128    }
129}
130
131/// Data for a remainder output, used for ledger nano
132#[derive(Clone, Debug, Eq, PartialEq)]
133pub struct RemainderData {
134    /// The remainder output
135    pub output: Output,
136    /// The chain derived from seed, for the remainder addresses
137    pub chain: Option<Bip44>,
138    /// The remainder address
139    pub address: Address,
140}
141
142/// Data for a remainder output, used for ledger nano
143#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
144pub struct RemainderDataDto {
145    /// The remainder output
146    pub output: OutputDto,
147    /// The chain derived from seed, for the remainder addresses
148    #[serde(with = "option_bip44", default)]
149    pub chain: Option<Bip44>,
150    /// The remainder address
151    pub address: AddressDto,
152}
153
154impl TryFromDto for RemainderData {
155    type Dto = RemainderDataDto;
156    type Error = Error;
157
158    fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result<Self, Self::Error> {
159        Ok(Self {
160            output: Output::try_from_dto_with_params_inner(dto.output, params)?,
161            chain: dto.chain,
162            address: Address::try_from(dto.address)?,
163        })
164    }
165}
166impl From<&RemainderData> for RemainderDataDto {
167    fn from(remainder: &RemainderData) -> Self {
168        Self {
169            output: OutputDto::from(&remainder.output),
170            chain: remainder.chain,
171            address: AddressDto::from(&remainder.address),
172        }
173    }
174}