pub use crate::{
psp34,
psp34::balances,
traits::psp34::*,
};
pub use psp34::{
Internal as _,
Transfer as _,
};
use crate::psp34::{
Operator,
Owner,
};
use ink::{
prelude::vec::Vec,
storage::traits::{
AutoStorableHint,
ManualKey,
Storable,
StorableHint,
},
};
use openbrush::{
storage::{
Mapping,
TypeGuard,
},
traits::{
AccountId,
Balance,
OccupiedStorage,
Storage,
},
};
pub const STORAGE_KEY: u32 = openbrush::storage_unique_key!(Data);
#[openbrush::upgradeable_storage(STORAGE_KEY)]
#[derive(Default, Debug)]
pub struct Data<B = balances::Balances>
where
B: Storable
+ AutoStorableHint<ManualKey<453953544, ManualKey<{ STORAGE_KEY }>>, Type = B>
+ StorableHint<ManualKey<{ STORAGE_KEY }>>,
{
pub token_owner: Mapping<Id, Owner>,
pub operator_approvals: Mapping<(Owner, Operator, Option<Id>), (), ApprovalsKey>,
pub balances: B,
pub _reserved: Option<()>,
}
pub struct ApprovalsKey;
impl<'a> TypeGuard<'a> for ApprovalsKey {
type Type = &'a (&'a Owner, &'a Operator, &'a Option<&'a Id>);
}
impl<B, T> PSP34 for T
where
B: balances::BalancesManager,
B: Storable
+ AutoStorableHint<ManualKey<453953544, ManualKey<{ STORAGE_KEY }>>, Type = B>
+ StorableHint<ManualKey<{ STORAGE_KEY }>>,
T: Storage<Data<B>>,
T: OccupiedStorage<{ STORAGE_KEY }, WithData = Data<B>>,
{
default fn collection_id(&self) -> Id {
let account_id = Self::env().account_id();
Id::Bytes(<_ as AsRef<[u8; 32]>>::as_ref(&account_id).to_vec())
}
default fn balance_of(&self, owner: AccountId) -> u32 {
self.data().balances.balance_of(&owner)
}
default fn owner_of(&self, id: Id) -> Option<AccountId> {
self._owner_of(&id)
}
default fn allowance(&self, owner: AccountId, operator: AccountId, id: Option<Id>) -> bool {
self._allowance(&owner, &operator, &id.as_ref())
}
default fn approve(&mut self, operator: AccountId, id: Option<Id>, approved: bool) -> Result<(), PSP34Error> {
let _a = &self.data().balances;
self._approve_for(operator, id, approved)
}
default fn transfer(&mut self, to: AccountId, id: Id, data: Vec<u8>) -> Result<(), PSP34Error> {
self._transfer_token(to, id, data)
}
default fn total_supply(&self) -> Balance {
self.data().balances.total_supply()
}
}
pub trait Internal {
fn _emit_transfer_event(&self, _from: Option<AccountId>, _to: Option<AccountId>, _id: Id);
fn _emit_approval_event(&self, _from: AccountId, _to: AccountId, _id: Option<Id>, _approved: bool);
fn _approve_for(&mut self, to: AccountId, id: Option<Id>, approved: bool) -> Result<(), PSP34Error>;
fn _owner_of(&self, id: &Id) -> Option<AccountId>;
fn _transfer_token(&mut self, to: AccountId, id: Id, data: Vec<u8>) -> Result<(), PSP34Error>;
fn _mint_to(&mut self, to: AccountId, id: Id) -> Result<(), PSP34Error>;
fn _burn_from(&mut self, from: AccountId, id: Id) -> Result<(), PSP34Error>;
fn _allowance(&self, owner: &Owner, operator: &Operator, id: &Option<&Id>) -> bool;
fn _check_token_exists(&self, id: &Id) -> Result<AccountId, PSP34Error>;
}
impl<B, T> Internal for T
where
B: balances::BalancesManager,
B: Storable
+ AutoStorableHint<ManualKey<453953544, ManualKey<{ STORAGE_KEY }>>, Type = B>
+ StorableHint<ManualKey<{ STORAGE_KEY }>>,
T: Storage<Data<B>>,
T: OccupiedStorage<{ STORAGE_KEY }, WithData = Data<B>>,
{
default fn _emit_transfer_event(&self, _from: Option<AccountId>, _to: Option<AccountId>, _id: Id) {}
default fn _emit_approval_event(&self, _from: AccountId, _to: AccountId, _id: Option<Id>, _approved: bool) {}
default fn _approve_for(&mut self, to: AccountId, id: Option<Id>, approved: bool) -> Result<(), PSP34Error> {
let mut caller = Self::env().caller();
if let Some(id) = &id {
let owner = self.data().token_owner.get(id).ok_or(PSP34Error::TokenNotExists)?;
if approved && owner == to {
return Err(PSP34Error::SelfApprove)
}
if owner != caller && !self._allowance(&owner, &caller, &None) {
return Err(PSP34Error::NotApproved)
};
caller = owner;
}
if approved {
self.data()
.operator_approvals
.insert(&(&caller, &to, &id.as_ref()), &());
} else {
self.data().operator_approvals.remove(&(&caller, &to, &id.as_ref()));
}
self._emit_approval_event(caller, to, id, approved);
Ok(())
}
default fn _owner_of(&self, id: &Id) -> Option<AccountId> {
self.data().token_owner.get(id)
}
default fn _transfer_token(&mut self, to: AccountId, id: Id, _data: Vec<u8>) -> Result<(), PSP34Error> {
let owner = self._check_token_exists(&id)?;
let caller = Self::env().caller();
if owner != caller && !self._allowance(&owner, &caller, &Some(&id)) {
return Err(PSP34Error::NotApproved)
}
self._before_token_transfer(Some(&owner), Some(&to), &id)?;
self.data().operator_approvals.remove(&(&owner, &caller, &Some(&id)));
self.data().balances.decrease_balance(&owner, &id, false);
self.data().token_owner.remove(&id);
self.data().balances.increase_balance(&to, &id, false);
self.data().token_owner.insert(&id, &to);
self._after_token_transfer(Some(&owner), Some(&to), &id)?;
self._emit_transfer_event(Some(owner), Some(to), id);
Ok(())
}
default fn _mint_to(&mut self, to: AccountId, id: Id) -> Result<(), PSP34Error> {
if self.data().token_owner.get(&id).is_some() {
return Err(PSP34Error::TokenExists)
}
self._before_token_transfer(None, Some(&to), &id)?;
self.data().balances.increase_balance(&to, &id, true);
self.data().token_owner.insert(&id, &to);
self._after_token_transfer(None, Some(&to), &id)?;
self._emit_transfer_event(None, Some(to), id);
Ok(())
}
default fn _burn_from(&mut self, from: AccountId, id: Id) -> Result<(), PSP34Error> {
self._check_token_exists(&id)?;
self._before_token_transfer(Some(&from), None, &id)?;
self.data().token_owner.remove(&id);
self.data().balances.decrease_balance(&from, &id, true);
self._after_token_transfer(Some(&from), None, &id)?;
self._emit_transfer_event(Some(from), None, id);
Ok(())
}
default fn _allowance(&self, owner: &Owner, operator: &Operator, id: &Option<&Id>) -> bool {
self.data().operator_approvals.get(&(owner, operator, &None)).is_some()
|| id != &None && self.data().operator_approvals.get(&(owner, operator, id)).is_some()
}
default fn _check_token_exists(&self, id: &Id) -> Result<AccountId, PSP34Error> {
self.data().token_owner.get(&id).ok_or(PSP34Error::TokenNotExists)
}
}
pub trait Transfer {
fn _before_token_transfer(
&mut self,
_from: Option<&AccountId>,
_to: Option<&AccountId>,
_id: &Id,
) -> Result<(), PSP34Error>;
fn _after_token_transfer(
&mut self,
_from: Option<&AccountId>,
_to: Option<&AccountId>,
_id: &Id,
) -> Result<(), PSP34Error>;
}
impl<B, T> Transfer for T
where
B: balances::BalancesManager,
B: Storable
+ AutoStorableHint<ManualKey<453953544, ManualKey<{ STORAGE_KEY }>>, Type = B>
+ StorableHint<ManualKey<{ STORAGE_KEY }>>,
T: Storage<Data<B>>,
T: OccupiedStorage<{ STORAGE_KEY }, WithData = Data<B>>,
{
default fn _before_token_transfer(
&mut self,
_from: Option<&AccountId>,
_to: Option<&AccountId>,
_id: &Id,
) -> Result<(), PSP34Error> {
Ok(())
}
default fn _after_token_transfer(
&mut self,
_from: Option<&AccountId>,
_to: Option<&AccountId>,
_id: &Id,
) -> Result<(), PSP34Error> {
Ok(())
}
}