use std::io; use scale::{Encode, Decode, IoReader}; use borsh::{BorshSerialize, BorshDeserialize}; use serai_primitives::{Balance, Data}; use serai_coins_primitives::OutInstructionWithBalance; use crate::Address; /// A payment to fulfill. #[derive(Clone, BorshSerialize, BorshDeserialize)] pub struct Payment<A: Address> { address: A, balance: Balance, data: Option<Vec<u8>>, } impl<A: Address> TryFrom<OutInstructionWithBalance> for Payment<A> { type Error = (); fn try_from(out_instruction_with_balance: OutInstructionWithBalance) -> Result<Self, ()> { Ok(Payment { address: out_instruction_with_balance.instruction.address.try_into().map_err(|_| ())?, balance: out_instruction_with_balance.balance, data: out_instruction_with_balance.instruction.data.map(Data::consume), }) } } impl<A: Address> Payment<A> { /// Create a new Payment. pub fn new(address: A, balance: Balance, data: Option<Vec<u8>>) -> Self { Payment { address, balance, data } } /// The address to pay. pub fn address(&self) -> &A { &self.address } /// The balance to transfer. pub fn balance(&self) -> Balance { self.balance } /// The data to associate with this payment. pub fn data(&self) -> &Option<Vec<u8>> { &self.data } /// Read a Payment. pub fn read(reader: &mut impl io::Read) -> io::Result<Self> { let address = A::deserialize_reader(reader)?; let reader = &mut IoReader(reader); let balance = Balance::decode(reader).map_err(io::Error::other)?; let data = Option::<Vec<u8>>::decode(reader).map_err(io::Error::other)?; Ok(Self { address, balance, data }) } /// Write the Payment. pub fn write(&self, writer: &mut impl io::Write) -> io::Result<()> { self.address.serialize(writer)?; self.balance.encode_to(writer); self.data.encode_to(writer); Ok(()) } }