use core::ops::Deref;
use lnpbp::rgb::schema::{
constants::*,
script::{Procedure, StandardProcedure},
AssignmentAction, Bits, DataFormat, GenesisAction, GenesisSchema,
Occurences, Schema, StateFormat, StateSchema, TransitionAction,
TransitionSchema,
};
use crate::error::ServiceErrorDomain;
use crate::type_map;
#[derive(Debug, Display, Error, From)]
#[display(Debug)]
pub enum SchemaError {
NotAllFieldsPresent,
WrongSchemaId,
}
impl From<SchemaError> for ServiceErrorDomain {
fn from(err: SchemaError) -> Self {
ServiceErrorDomain::Schema(format!("{}", err))
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[display(Debug)]
#[repr(u16)]
pub enum FieldType {
Name,
Description,
Data,
DataFormat,
Timestamp,
LockDescriptor,
LockUtxo,
BurnUtxo,
Salt,
NftSource,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[display(Debug)]
#[repr(u16)]
pub enum OwnedRightsType {
Inflation,
Ownership,
Renomination,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[display(Debug)]
#[repr(u16)]
pub enum TransitionType {
Issue,
Transfer,
Engraving,
Renomination,
RightsSplit,
}
pub fn schema() -> Schema {
use Occurences::*;
Schema {
rgb_features: none!(),
root_id: none!(),
genesis: GenesisSchema {
metadata: type_map! {
FieldType::Name => Once,
FieldType::Description => NoneOrOnce,
FieldType::Data => NoneOrMore,
FieldType::DataFormat => NoneOrOnce,
FieldType::LockUtxo => NoneOrMore,
FieldType::LockDescriptor => NoneOrUpTo(32),
FieldType::Timestamp => Once,
FieldType::NftSource => NoneOrMore,
FieldType::Salt => Once
},
owned_rights: type_map! {
OwnedRightsType::Inflation => NoneOrOnce,
OwnedRightsType::Renomination => NoneOrOnce,
OwnedRightsType::Ownership => OnceOrMore
},
public_rights: none!(),
abi: bmap! {
GenesisAction::Validate => Procedure::Embedded(StandardProcedure::NonfungibleInflation)
},
},
extensions: bmap! {},
transitions: type_map! {
TransitionType::Issue => TransitionSchema {
metadata: type_map! {
FieldType::LockUtxo => NoneOrMore,
FieldType::LockDescriptor => NoneOrUpTo(32),
FieldType::NftSource => NoneOrMore,
FieldType::Salt => Once
},
closes: type_map! {
OwnedRightsType::Inflation => Once
},
owned_rights: type_map! {
OwnedRightsType::Inflation => NoneOrOnce,
OwnedRightsType::Ownership => OnceOrMore
},
public_rights: none!(),
abi: bmap! {
TransitionAction::Validate => Procedure::Embedded(StandardProcedure::NonfungibleInflation)
}
},
TransitionType::Transfer => TransitionSchema {
metadata: type_map! {
FieldType::Salt => Once
},
closes: type_map! {
OwnedRightsType::Ownership => OnceOrMore
},
owned_rights: type_map! {
OwnedRightsType::Ownership => OnceOrMore
},
public_rights: none!(),
abi: none!()
},
TransitionType::Engraving => TransitionSchema {
metadata: type_map! {
FieldType::Data => NoneOrMore,
FieldType::DataFormat => NoneOrOnce,
FieldType::Salt => Once
},
closes: type_map! {
OwnedRightsType::Ownership => OnceOrMore
},
owned_rights: type_map! {
OwnedRightsType::Ownership => OnceOrMore
},
public_rights: none!(),
abi: none!()
},
TransitionType::Renomination => TransitionSchema {
metadata: type_map! {
FieldType::Name => NoneOrOnce,
FieldType::Description => NoneOrOnce,
FieldType::Data => NoneOrMore,
FieldType::DataFormat => NoneOrOnce
},
closes: type_map! {
OwnedRightsType::Renomination => Once
},
owned_rights: type_map! {
OwnedRightsType::Renomination => NoneOrOnce
},
public_rights: none!(),
abi: none!()
},
TransitionType::RightsSplit => TransitionSchema {
metadata: type_map! {
FieldType::Salt => Once
},
closes: type_map! {
OwnedRightsType::Inflation => NoneOrMore,
OwnedRightsType::Ownership => NoneOrMore,
OwnedRightsType::Renomination => NoneOrOnce
},
owned_rights: type_map! {
OwnedRightsType::Inflation => NoneOrMore,
OwnedRightsType::Ownership => NoneOrMore,
OwnedRightsType::Renomination => NoneOrOnce
},
public_rights: none!(),
abi: bmap! {
TransitionAction::Validate => Procedure::Embedded(StandardProcedure::RightsSplit)
}
}
},
field_types: type_map! {
FieldType::Name => DataFormat::String(256),
FieldType::Description => DataFormat::String(core::u16::MAX),
FieldType::Data => DataFormat::Bytes(core::u16::MAX),
FieldType::DataFormat => DataFormat::Unsigned(Bits::Bit16, 0, core::u16::MAX as u128),
FieldType::Timestamp => DataFormat::Integer(Bits::Bit64, 1602340666, core::i64::MAX as i128),
FieldType::LockUtxo => DataFormat::TxOutPoint,
FieldType::LockDescriptor => DataFormat::String(core::u16::MAX),
FieldType::BurnUtxo => DataFormat::TxOutPoint,
FieldType::Salt => DataFormat::Unsigned(Bits::Bit32, 0, core::u32::MAX as u128),
FieldType::NftSource => DataFormat::Bytes(core::u16::MAX)
},
owned_right_types: type_map! {
OwnedRightsType::Inflation => StateSchema {
format: StateFormat::CustomData(DataFormat::Unsigned(Bits::Bit64, 0, core::u64::MAX as u128)),
abi: none!()
},
OwnedRightsType::Ownership => StateSchema {
format: StateFormat::CustomData(DataFormat::Unsigned(Bits::Bit32, 0, core::u32::MAX as u128)),
abi: bmap! {
AssignmentAction::Validate => Procedure::Embedded(StandardProcedure::IdentityTransfer)
}
},
OwnedRightsType::Renomination => StateSchema {
format: StateFormat::Declarative,
abi: none!()
}
},
public_right_types: none!(),
}
}
impl Deref for FieldType {
type Target = usize;
fn deref(&self) -> &Self::Target {
match self {
FieldType::Name => &1,
FieldType::Description => &2,
FieldType::Timestamp => &4,
FieldType::Data => &0x10,
FieldType::DataFormat => &0x11,
FieldType::Salt => &0x20,
FieldType::NftSource => &0x21,
FieldType::BurnUtxo => &FIELD_TYPE_BURN_UTXO,
FieldType::LockDescriptor => &FIELD_TYPE_LOCK_DESCRIPTOR,
FieldType::LockUtxo => &FIELD_TYPE_LOCK_UTXO,
}
}
}
impl Deref for OwnedRightsType {
type Target = usize;
fn deref(&self) -> &Self::Target {
match self {
OwnedRightsType::Renomination => &1,
OwnedRightsType::Inflation => &STATE_TYPE_NONFUNGIBLE_INFLATION,
OwnedRightsType::Ownership => &STATE_TYPE_NONFUNGIBLE_OWNERSHIP,
}
}
}
impl Deref for TransitionType {
type Target = usize;
fn deref(&self) -> &Self::Target {
match self {
TransitionType::Transfer => &0x00,
TransitionType::Engraving => &0x01,
TransitionType::Renomination => &0x10,
TransitionType::Issue => &TRANSITION_TYPE_FUNGIBLE_ISSUE,
TransitionType::RightsSplit => &0xF0,
}
}
}