use candid::CandidType;
use ex3_serde::bincode;
use ic_stable_structures::{storable::Bound, Storable};
use serde::{Deserialize, Serialize};
use crate::chain::ChainType;
use crate::{BlockHeight, CandidBlockHeight, CandidWalletRegisterId, PublicKey, WalletRegisterId};
#[derive(
CandidType, Clone, Hash, Deserialize, Serialize, Debug, Eq, PartialEq, PartialOrd, Ord,
)]
pub struct WalletIdentifier {
pub pub_key: PublicKey,
pub chain_type: ChainType,
}
impl WalletIdentifier {
pub fn new(pub_key: PublicKey, chain_type: ChainType) -> Self {
Self {
pub_key,
chain_type,
}
}
}
impl Storable for WalletIdentifier {
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.as_ref()).unwrap()
}
const BOUND: Bound = Bound::Bounded {
max_size: 64,
is_fixed_size: false,
};
}
#[derive(Clone, Hash, Deserialize, Serialize, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct RegisteredWalletIdentifier {
pub wallet_id: WalletRegisterId,
pub wallet_identifier: WalletIdentifier,
pub registered_height: BlockHeight,
}
impl Storable for RegisteredWalletIdentifier {
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.as_ref()).unwrap()
}
const BOUND: Bound = Bound::Bounded {
max_size: 224,
is_fixed_size: false,
};
}
#[derive(CandidType, Clone, Hash, Deserialize, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct CandidRegisteredWalletIdentifier {
pub wallet_id: CandidWalletRegisterId,
pub wallet_identifier: WalletIdentifier,
pub registered_height: CandidBlockHeight,
}
impl From<RegisteredWalletIdentifier> for CandidRegisteredWalletIdentifier {
fn from(registered_wallet_identifier: RegisteredWalletIdentifier) -> Self {
Self {
wallet_id: registered_wallet_identifier.wallet_id.into(),
wallet_identifier: registered_wallet_identifier.wallet_identifier,
registered_height: registered_wallet_identifier.registered_height.into(),
}
}
}
impl From<CandidRegisteredWalletIdentifier> for RegisteredWalletIdentifier {
fn from(candid_registered_wallet_identifier: CandidRegisteredWalletIdentifier) -> Self {
Self {
wallet_id: candid_registered_wallet_identifier.wallet_id.into(),
wallet_identifier: candid_registered_wallet_identifier.wallet_identifier,
registered_height: candid_registered_wallet_identifier.registered_height.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use ic_stable_structures::storable::Storable;
#[test]
fn test_storable_for_wallet_identifier() {
let wallet_identifier =
WalletIdentifier::new(PublicKey::from([0u8; 32]), ChainType::Bitcoin);
let bytes = wallet_identifier.to_bytes();
assert!(bytes.len() <= 64);
let wallet_identifier2 = WalletIdentifier::from_bytes(bytes);
assert_eq!(wallet_identifier, wallet_identifier2);
}
#[test]
fn test_storable_for_registered_wallet_identifier() {
let registered_wallet_identifier = RegisteredWalletIdentifier {
wallet_id: WalletRegisterId::from(u128::MAX),
wallet_identifier: WalletIdentifier::new(
PublicKey::from([0u8; 32]),
ChainType::Bitcoin,
),
registered_height: BlockHeight::from(0u32),
};
let bytes = registered_wallet_identifier.to_bytes();
assert!(bytes.len() <= 224);
let registered_wallet_identifier2 = RegisteredWalletIdentifier::from_bytes(bytes);
assert_eq!(registered_wallet_identifier, registered_wallet_identifier2);
}
}