use alloc::{
string::{String, ToString},
vec::Vec,
};
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{
de::{self, Visitor},
Deserialize, Serialize,
};
#[cfg(feature = "full")]
use sha3::Digest;
use crate::*;
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub struct RewardsClaim {
block_heights: Vec<BlockHeight>,
}
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub enum StakingAction {
Stake {
amount: u128,
},
Delegate {
validator: ValidatorPublicKey,
},
Distribute {
claim: RewardsClaim,
},
DepositForFees {
holder: ValidatorPublicKey,
amount: u128,
},
}
impl ContractAction for StakingAction {
fn as_blob(
&self,
contract_name: ContractName,
caller: Option<BlobIndex>,
callees: Option<Vec<BlobIndex>>,
) -> Blob {
Blob {
contract_name,
data: BlobData::from(StructuredBlobData {
caller,
callees,
parameters: self.clone(),
}),
}
}
}
#[derive(
Clone, BorshSerialize, BorshDeserialize, Default, Eq, PartialEq, Hash, PartialOrd, Ord,
)]
pub struct ValidatorPublicKey(pub Vec<u8>);
impl ValidatorPublicKey {
pub fn new_for_tests(str: &str) -> Self {
Self(str.as_bytes().to_vec())
}
}
#[cfg(feature = "full")]
impl utoipa::PartialSchema for ValidatorPublicKey {
fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
String::schema()
}
}
#[cfg(feature = "full")]
impl utoipa::ToSchema for ValidatorPublicKey {}
impl Serialize for ValidatorPublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(hex::encode(&self.0).as_str())
}
}
impl<'de> Deserialize<'de> for ValidatorPublicKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct ValidatorPublicKeyVisitor;
impl Visitor<'_> for ValidatorPublicKeyVisitor {
type Value = ValidatorPublicKey;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("a hex string representing a ValidatorPublicKey")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let bytes = hex::decode(value).map_err(de::Error::custom)?;
Ok(ValidatorPublicKey(bytes))
}
}
deserializer.deserialize_str(ValidatorPublicKeyVisitor)
}
}
impl core::fmt::Debug for ValidatorPublicKey {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("ValidatorPubK")
.field(&hex::encode(
self.0.get(..HASH_DISPLAY_SIZE).unwrap_or(&self.0),
))
.finish()
}
}
impl core::fmt::Display for ValidatorPublicKey {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"{}",
&hex::encode(self.0.get(..HASH_DISPLAY_SIZE).unwrap_or(&self.0),)
)
}
}
#[derive(
Clone,
Debug,
BorshSerialize,
BorshDeserialize,
Serialize,
Deserialize,
PartialEq,
Eq,
Hash,
Ord,
PartialOrd,
)]
#[serde(try_from = "String", into = "String")]
pub struct LaneId {
pub operator: ValidatorPublicKey,
pub suffix: String,
}
pub type LaneSuffix = String;
#[cfg(feature = "full")]
impl utoipa::PartialSchema for LaneId {
fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
String::schema()
}
}
#[cfg(feature = "full")]
impl utoipa::ToSchema for LaneId {}
impl Default for LaneId {
fn default() -> Self {
LaneId::with_suffix(ValidatorPublicKey::default(), LaneId::DEFAULT_SUFFIX)
}
}
impl LaneId {
pub const DEFAULT_SUFFIX: &'static str = "default";
pub fn new(operator: ValidatorPublicKey) -> Self {
Self::with_suffix(operator, Self::DEFAULT_SUFFIX)
}
pub fn with_suffix(operator: ValidatorPublicKey, suffix: impl Into<String>) -> Self {
Self {
operator,
suffix: suffix.into(),
}
}
pub fn operator(&self) -> &ValidatorPublicKey {
&self.operator
}
pub fn suffix(&self) -> &str {
&self.suffix
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(self.operator.0.len() + 1 + self.suffix.len());
bytes.extend_from_slice(&self.operator.0);
bytes.push(b'-');
bytes.extend_from_slice(self.suffix.as_bytes());
bytes
}
#[cfg(feature = "full")]
pub fn update_hasher<D: Digest>(&self, hasher: &mut D) {
hasher.update(&self.operator.0);
hasher.update(b"-");
hasher.update(self.suffix.as_bytes());
}
pub fn parse(value: &str) -> Result<Self, String> {
if let Some((hex_part, suffix)) = value.split_once('-') {
if suffix.is_empty() {
return Err("LaneId suffix cannot be empty".to_string());
}
let bytes = hex::decode(hex_part).map_err(|e| e.to_string())?;
Ok(LaneId::with_suffix(ValidatorPublicKey(bytes), suffix))
} else {
let bytes = hex::decode(value).map_err(|e| e.to_string())?;
Ok(LaneId::with_suffix(
ValidatorPublicKey(bytes),
LaneId::DEFAULT_SUFFIX,
))
}
}
}
impl From<ValidatorPublicKey> for LaneId {
fn from(value: ValidatorPublicKey) -> Self {
LaneId::new(value)
}
}
impl core::str::FromStr for LaneId {
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Self::parse(value)
}
}
impl TryFrom<String> for LaneId {
type Error = String;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::parse(&value)
}
}
impl From<LaneId> for String {
fn from(value: LaneId) -> Self {
value.to_string()
}
}
impl core::fmt::Display for LaneId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}-{}", hex::encode(&self.operator.0), self.suffix)
}
}
#[derive(
Debug,
Clone,
Copy,
Default,
BorshSerialize,
BorshDeserialize,
Eq,
PartialEq,
Serialize,
Deserialize,
PartialOrd,
Ord,
)]
#[cfg_attr(feature = "full", derive(utoipa::ToSchema))]
pub struct LaneBytesSize(pub u64);
impl core::ops::Add<usize> for LaneBytesSize {
type Output = Self;
fn add(self, other: usize) -> Self {
LaneBytesSize(self.0 + other as u64)
}
}
impl core::fmt::Display for LaneBytesSize {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.0 < 1024 {
write!(f, "{} B", self.0)
} else if self.0 < 1024 * 1024 {
write!(f, "{} KB", self.0 / 1024)
} else if self.0 < 1024 * 1024 * 1024 {
write!(f, "{} MB", self.0 / (1024 * 1024))
} else if self.0 < 1024 * 1024 * 1024 * 1024 {
write!(f, "{} GB", self.0 / (1024 * 1024 * 1024))
} else {
write!(f, "{} TB", self.0 / (1024 * 1024 * 1024 * 1024))
}
}
}