iota-sdk 0.3.0

The IOTA SDK provides developers with a seamless experience to develop on IOTA by providing account abstractions and clients to interact with node APIs.
Documentation
// Copyright 2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crypto::keys::slip10::Chain;

use crate::{
    client::secret::types::{InputSigningData, InputSigningDataDto},
    types::block::{
        address::{dto::AddressDto, Address},
        output::{dto::OutputDto, Output},
        payload::{
            transaction::{
                dto::{TransactionEssenceDto, TransactionPayloadDto},
                TransactionEssence,
            },
            TransactionPayload,
        },
        protocol::ProtocolParameters,
        Error,
    },
};

/// Helper struct for offline signing
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PreparedTransactionData {
    /// Transaction essence
    pub essence: TransactionEssence,
    /// Required input information for signing. Inputs need to be ordered by address type
    pub inputs_data: Vec<InputSigningData>,
    /// Optional remainder output information
    pub remainder: Option<RemainderData>,
}

/// PreparedTransactionData Dto
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PreparedTransactionDataDto {
    /// Transaction essence
    pub essence: TransactionEssenceDto,
    /// Required address information for signing
    pub inputs_data: Vec<InputSigningDataDto>,
    /// Optional remainder output information
    pub remainder: Option<RemainderDataDto>,
}

impl From<&PreparedTransactionData> for PreparedTransactionDataDto {
    fn from(value: &PreparedTransactionData) -> Self {
        Self {
            essence: TransactionEssenceDto::from(&value.essence),
            inputs_data: value.inputs_data.iter().map(InputSigningDataDto::from).collect(),
            remainder: value.remainder.as_ref().map(RemainderDataDto::from),
        }
    }
}

impl PreparedTransactionData {
    /// Conversion from [`PreparedTransactionDataDto`] to [`PreparedTransactionData`].
    pub fn try_from_dto(
        value: &PreparedTransactionDataDto,
        protocol_parameters: &ProtocolParameters,
    ) -> Result<Self, Error> {
        Ok(Self {
            essence: TransactionEssence::try_from_dto(&value.essence, protocol_parameters)
                .map_err(|_| Error::InvalidField("essence"))?,
            inputs_data: value
                .inputs_data
                .iter()
                .map(|i| InputSigningData::try_from_dto(i, protocol_parameters.token_supply()))
                .collect::<crate::client::Result<Vec<InputSigningData>>>()
                .map_err(|_| Error::InvalidField("input_data"))?,
            remainder: match &value.remainder {
                Some(remainder) => Some(
                    RemainderData::try_from_dto(remainder, protocol_parameters.token_supply())
                        .map_err(|_| Error::InvalidField("remainder"))?,
                ),
                None => None,
            },
        })
    }

    /// Unverified conversion from [`PreparedTransactionDataDto`] to [`PreparedTransactionData`].
    pub fn try_from_dto_unverified(value: &PreparedTransactionDataDto) -> Result<Self, Error> {
        Ok(Self {
            essence: TransactionEssence::try_from_dto_unverified(&value.essence)
                .map_err(|_| Error::InvalidField("essence"))?,
            inputs_data: value
                .inputs_data
                .iter()
                .map(InputSigningData::try_from_dto_unverified)
                .collect::<crate::client::Result<Vec<InputSigningData>>>()
                .map_err(|_| Error::InvalidField("inputs_data"))?,
            remainder: match &value.remainder {
                Some(remainder) => Some(
                    RemainderData::try_from_dto_unverified(remainder).map_err(|_| Error::InvalidField("remainder"))?,
                ),
                None => None,
            },
        })
    }
}

/// Helper struct for offline signing
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SignedTransactionData {
    /// Signed transaction payload
    pub transaction_payload: TransactionPayload,
    /// Required address information for signing
    pub inputs_data: Vec<InputSigningData>,
}

/// SignedTransactionData Dto
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SignedTransactionDataDto {
    /// Transaction essence
    pub transaction_payload: TransactionPayloadDto,
    /// Required address information for signing
    pub inputs_data: Vec<InputSigningDataDto>,
}

impl From<&SignedTransactionData> for SignedTransactionDataDto {
    fn from(value: &SignedTransactionData) -> Self {
        Self {
            transaction_payload: TransactionPayloadDto::from(&value.transaction_payload),
            inputs_data: value.inputs_data.iter().map(InputSigningDataDto::from).collect(),
        }
    }
}

impl SignedTransactionData {
    /// Conversion from [`SignedTransactionDataDto`] to [`SignedTransactionData`].
    pub fn try_from_dto(
        value: &SignedTransactionDataDto,
        protocol_parameters: &ProtocolParameters,
    ) -> Result<Self, Error> {
        Ok(Self {
            transaction_payload: TransactionPayload::try_from_dto(&value.transaction_payload, protocol_parameters)
                .map_err(|_| Error::InvalidField("transaction_payload"))?,
            inputs_data: value
                .inputs_data
                .iter()
                .map(|i| InputSigningData::try_from_dto(i, protocol_parameters.token_supply()))
                .collect::<crate::client::Result<Vec<InputSigningData>>>()
                .map_err(|_| Error::InvalidField("input_data"))?,
        })
    }

    /// Unverified conversion from [`SignedTransactionDataDto`] to [`SignedTransactionData`].
    pub fn try_from_dto_unverified(value: &SignedTransactionDataDto) -> Result<Self, Error> {
        Ok(Self {
            transaction_payload: TransactionPayload::try_from_dto_unverified(&value.transaction_payload)
                .map_err(|_| Error::InvalidField("transaction_payload"))?,
            inputs_data: value
                .inputs_data
                .iter()
                .map(InputSigningData::try_from_dto_unverified)
                .collect::<crate::client::Result<Vec<InputSigningData>>>()
                .map_err(|_| Error::InvalidField("inputs_data"))?,
        })
    }
}

/// Data for a remainder output, used for ledger nano
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct RemainderData {
    /// The remainder output
    pub output: Output,
    /// The chain derived from seed, for the remainder addresses
    pub chain: Option<Chain>,
    /// The remainder address
    pub address: Address,
}

/// Data for a remainder output, used for ledger nano
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct RemainderDataDto {
    /// The remainder output
    pub output: OutputDto,
    /// The chain derived from seed, for the remainder addresses
    pub chain: Option<Chain>,
    /// The remainder address
    pub address: AddressDto,
}

impl RemainderData {
    pub(crate) fn try_from_dto(remainder: &RemainderDataDto, token_supply: u64) -> crate::client::Result<Self> {
        Ok(Self {
            output: Output::try_from_dto(&remainder.output, token_supply)?,
            chain: remainder.chain.clone(),
            address: Address::try_from(&remainder.address)?,
        })
    }

    pub(crate) fn try_from_dto_unverified(remainder: &RemainderDataDto) -> crate::client::Result<Self> {
        Ok(Self {
            output: Output::try_from_dto_unverified(&remainder.output)?,
            chain: remainder.chain.clone(),
            address: Address::try_from(&remainder.address)?,
        })
    }
}

impl From<&RemainderData> for RemainderDataDto {
    fn from(remainder: &RemainderData) -> Self {
        Self {
            output: OutputDto::from(&remainder.output),
            chain: remainder.chain.clone(),
            address: AddressDto::from(&remainder.address),
        }
    }
}

/// Generated addresses
#[derive(Debug, Clone)]
pub struct RawAddresses {
    /// Public addresses
    pub public: Vec<Address>,
    /// Internal/change addresses <https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#change>
    pub internal: Vec<Address>,
}

/// Generated addresses bech32 encoded
#[derive(Debug, Clone)]
pub struct Bech32Addresses {
    /// Public addresses
    pub public: Vec<String>,
    /// Internal/change addresses <https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#change>
    pub internal: Vec<String>,
}