use crate::chain::Chain;
use crate::sign_schema::SignatureSchema;
use crate::{AssetAmount, AssetId};
use ex3_serde::bincode;
use ex3_timestamp::TimeInNs;
use ic_stable_structures::storable::Bound;
use ic_stable_structures::Storable;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct Withdrawal {
pub chain: Chain,
pub sign_schema: SignatureSchema,
pub to: String,
pub asset_id: AssetId,
pub amount: AssetAmount,
pub fee: AssetAmount,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct ForceWithdrawal {
pub chain: Chain,
pub sign_schema: SignatureSchema,
pub to: String,
pub asset_id: AssetId,
pub amount: AssetAmount,
pub fee: AssetAmount,
pub timestamp: TimeInNs,
}
impl Storable for Withdrawal {
fn to_bytes(&self) -> std::borrow::Cow<[u8]> {
bincode::serialize(&self).unwrap().into()
}
fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self {
bincode::deserialize(&bytes).unwrap()
}
const BOUND: Bound = Bound::Bounded {
max_size: 289,
is_fixed_size: false,
};
}
impl Storable for ForceWithdrawal {
fn to_bytes(&self) -> std::borrow::Cow<[u8]> {
bincode::serialize(&self).unwrap().into()
}
fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self {
bincode::deserialize(&bytes).unwrap()
}
const BOUND: Bound = Bound::Bounded {
max_size: 297,
is_fixed_size: false,
};
}
#[cfg(test)]
mod tests {
use crate::chain::ChainType;
use ex3_serde::{bincode, cbor};
use super::*;
#[test]
fn test_serde() {
let withdrawal = Withdrawal {
chain: Chain {
r#type: ChainType::Ethereum,
network: 1u8.into(),
},
sign_schema: SignatureSchema::EvmEcdsa,
to: "0x0000001312312321313213".to_string(),
asset_id: AssetId::from(2000u32),
amount: AssetAmount::from(10000u64),
fee: AssetAmount::from(100u64),
};
let encoded = bincode::serialize(&withdrawal).unwrap();
let decoded: Withdrawal = bincode::deserialize(&encoded).unwrap();
assert_eq!(withdrawal, decoded);
let encoded = cbor::serialize(&withdrawal).unwrap();
let decoded: Withdrawal = cbor::deserialize(&encoded).unwrap();
assert_eq!(withdrawal, decoded);
}
#[test]
fn test_storable_for_withdrawal() {
let withdrawal = Withdrawal {
chain: Chain {
r#type: ChainType::Ethereum,
network: 1u8.into(),
},
sign_schema: SignatureSchema::EvmEcdsa,
to: "0x3f349bBaFEc1551819B8be1EfEA2fC46cA749aA1".to_string(),
asset_id: AssetId::from(u128::MAX),
amount: AssetAmount::from(u128::MAX),
fee: AssetAmount::from(u128::MAX),
};
let bytes = withdrawal.to_bytes();
assert!(bytes.len() <= 289, "bytes.len() = {}", bytes.len());
let decoded = Withdrawal::from_bytes(bytes);
assert_eq!(withdrawal, decoded);
}
#[test]
fn test_storable_for_force_withdrawal() {
let force_withdrawal = ForceWithdrawal {
chain: Chain {
r#type: ChainType::Ethereum,
network: 1u8.into(),
},
sign_schema: SignatureSchema::EvmEcdsa,
to: "0x3f349bBaFEc1551819B8be1EfEA2fC46cA749aA1".to_string(),
asset_id: AssetId::from(u128::MAX),
amount: AssetAmount::from(u128::MAX),
fee: AssetAmount::from(u128::MAX),
timestamp: TimeInNs(u64::MAX),
};
let bytes = force_withdrawal.to_bytes();
assert!(bytes.len() <= 297, "bytes.len() = {}", bytes.len());
let decoded = ForceWithdrawal::from_bytes(bytes);
assert_eq!(force_withdrawal, decoded);
}
}