use super::ser::{EpeeRead, EpeeWrite, Reader, write_optional, write_var_bytes, write_vec};
use super::types::Value256;
use super::variant::tag;
use super::varint::append_varint;
use crate::error::Result;
pub const ASSET_DESCRIPTOR_OPERATION_UNDEFINED: u8 = 0;
pub const ASSET_DESCRIPTOR_OPERATION_REGISTER: u8 = 1;
pub const ASSET_DESCRIPTOR_OPERATION_EMIT: u8 = 2;
pub const ASSET_DESCRIPTOR_OPERATION_UPDATE: u8 = 3;
pub const ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN: u8 = 4;
pub const ASSET_DESCRIPTOR_OPERATION_HF4_VER: u64 = 1;
pub const ASSET_DESCRIPTOR_OPERATION_HF5_VER: u64 = 2;
#[derive(Clone, Copy, Debug, Default)]
pub struct AssetEtcField;
impl EpeeWrite for AssetEtcField {
fn write_epee(&self, out: &mut Vec<u8>) {
out.push(tag::DUMMY);
}
}
impl EpeeRead for AssetEtcField {
fn read_epee(r: &mut Reader<'_>) -> Result<Self> {
match r.read_byte()? {
tag::DUMMY => Ok(AssetEtcField),
other => Err(crate::err!("unsupported asset etc field tag {other}")),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct AssetDescriptorBase {
pub version: u64,
pub total_max_supply: u64,
pub current_supply: u64,
pub decimal_point: u8,
pub ticker: Vec<u8>,
pub full_name: Vec<u8>,
pub meta_info: Vec<u8>,
pub owner: Value256,
pub hidden_supply: bool,
pub owner_eth_pub_key: Option<[u8; 33]>,
pub etc: Vec<AssetEtcField>,
}
impl EpeeWrite for AssetDescriptorBase {
fn write_epee(&self, out: &mut Vec<u8>) {
append_varint(out, self.version);
self.total_max_supply.write_epee(out);
self.current_supply.write_epee(out);
out.push(self.decimal_point);
write_var_bytes(&self.ticker, out);
write_var_bytes(&self.full_name, out);
write_var_bytes(&self.meta_info, out);
self.owner.write_epee(out);
out.push(self.hidden_supply as u8);
if self.version < 1 {
return;
}
match &self.owner_eth_pub_key {
Some(k) => {
out.push(0);
out.extend_from_slice(k);
}
None => out.push(1),
}
if self.version < 2 {
return;
}
write_vec(&self.etc, out);
}
}
impl EpeeRead for AssetDescriptorBase {
fn read_epee(r: &mut Reader<'_>) -> Result<Self> {
let version = r.read_varint()?;
if version > 2 {
return Err(crate::err!(
"unsupported asset_descriptor_base version {version}"
));
}
let mut adb = AssetDescriptorBase {
version,
total_max_supply: u64::read_epee(r)?,
current_supply: u64::read_epee(r)?,
decimal_point: r.read_byte()?,
ticker: r.read_var_bytes()?,
full_name: r.read_var_bytes()?,
meta_info: r.read_var_bytes()?,
owner: Value256::read_epee(r)?,
hidden_supply: bool::read_epee(r)?,
owner_eth_pub_key: None,
etc: Vec::new(),
};
if version < 1 {
return Ok(adb);
}
adb.owner_eth_pub_key = match r.read_byte()? {
0 => {
let mut k = [0u8; 33];
k.copy_from_slice(r.read_exact(33)?);
Some(k)
}
1 => None,
other => return Err(crate::err!("invalid optional flag {other}")),
};
if version < 2 {
return Ok(adb);
}
adb.etc = r.read_vec()?;
Ok(adb)
}
}
#[derive(Clone, Debug, Default)]
pub struct AssetDescriptorOperation {
pub version: u64,
pub operation_type: u8,
pub descriptor: Option<AssetDescriptorBase>,
pub amount_commitment: Option<Value256>,
pub asset_id: Option<Value256>,
pub amount: Option<u64>,
pub asset_id_salt: Option<u32>,
pub etc: Vec<AssetEtcField>,
}
impl EpeeWrite for AssetDescriptorOperation {
fn write_epee(&self, out: &mut Vec<u8>) {
append_varint(out, self.version);
out.push(self.operation_type);
if self.version < ASSET_DESCRIPTOR_OPERATION_HF5_VER {
self.descriptor.clone().unwrap_or_default().write_epee(out);
self.amount_commitment
.unwrap_or(Value256::ZERO)
.write_epee(out);
write_optional(&self.asset_id, out);
return;
}
write_optional(&self.amount_commitment, out);
write_optional(&self.asset_id, out);
write_optional(&self.descriptor, out);
write_optional(&self.amount, out);
write_optional(&self.asset_id_salt, out);
write_vec(&self.etc, out);
}
}
impl EpeeRead for AssetDescriptorOperation {
fn read_epee(r: &mut Reader<'_>) -> Result<Self> {
let version = r.read_varint()?;
if version > ASSET_DESCRIPTOR_OPERATION_HF5_VER {
return Err(crate::err!(
"unsupported asset_descriptor_operation version {version}"
));
}
let operation_type = r.read_byte()?;
if version < ASSET_DESCRIPTOR_OPERATION_HF5_VER {
return Ok(AssetDescriptorOperation {
version,
operation_type,
descriptor: Some(AssetDescriptorBase::read_epee(r)?),
amount_commitment: Some(Value256::read_epee(r)?),
asset_id: r.read_optional()?,
amount: None,
asset_id_salt: None,
etc: Vec::new(),
});
}
Ok(AssetDescriptorOperation {
version,
operation_type,
amount_commitment: r.read_optional()?,
asset_id: r.read_optional()?,
descriptor: r.read_optional()?,
amount: r.read_optional()?,
asset_id_salt: r.read_optional()?,
etc: r.read_vec()?,
})
}
}