1use core::char::{decode_utf16, REPLACEMENT_CHARACTER};2use evm_coder::{3 abi::{AbiWriter, StringError},4 types::*,5};6use core::convert::TryInto;7use alloc::format;8use crate::{Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList};9use frame_support::storage::StorageDoubleMap;10use pallet_evm::AddressMapping;11use super::erc::*;12use super::account::CrossAccountId;1314type Result<T> = core::result::Result<T, StringError>;1516impl<T: Config> InlineNameSymbol for CollectionHandle<T> {17 type Error = StringError;1819 fn name(&self) -> Result<string> {20 Ok(decode_utf16(self.name.iter().copied())21 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))22 .collect::<string>())23 }2425 fn symbol(&self) -> Result<string> {26 Ok(string::from_utf8_lossy(&self.token_prefix).into())27 }28}2930impl<T: Config> InlineTotalSupply for CollectionHandle<T> {31 type Error = StringError;3233 fn total_supply(&self) -> Result<uint256> {34 35 Ok(0.into())36 }37}3839impl<T: Config> ERC721Metadata for CollectionHandle<T> {40 type Error = StringError;4142 fn token_uri(&self, token_id: uint256) -> Result<string> {43 44 Ok(format!("unique.network/{}/{}", self.id, token_id))45 }4647 fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {48 <Self as InlineNameSymbol>::call(self, c)49 }50}5152impl<T: Config> ERC721Enumerable for CollectionHandle<T> {53 type Error = StringError;5455 fn token_by_index(&self, index: uint256) -> Result<uint256> {56 Ok(index)57 }5859 fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {60 61 Err("not implemented".into())62 }6364 fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {65 <Self as InlineTotalSupply>::call(self, c)66 }67}6869impl<T: Config> ERC721 for CollectionHandle<T> {70 type Error = StringError;7172 fn balance_of(&self, owner: address) -> Result<uint256> {73 let owner = T::EvmAddressMapping::into_account_id(owner);74 let balance = <Balance<T>>::get(self.id, owner);75 Ok(balance.into())76 }77 fn owner_of(&self, token_id: uint256) -> Result<address> {78 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;79 let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;80 Ok(*token.owner.as_eth())81 }82 fn safe_transfer_from_with_data(83 &mut self,84 _from: address,85 _to: address,86 _token_id: uint256,87 _data: bytes,88 _value: value,89 ) -> Result<void> {90 91 Err("not implemented".into())92 }93 fn safe_transfer_from(94 &mut self,95 _from: address,96 _to: address,97 _token_id: uint256,98 _value: value,99 ) -> Result<void> {100 101 Err("not implemented".into())102 }103104 fn transfer_from(105 &mut self,106 caller: caller,107 from: address,108 to: address,109 token_id: uint256,110 _value: value,111 ) -> Result<void> {112 let caller = T::CrossAccountId::from_eth(caller);113 let from = T::CrossAccountId::from_eth(from);114 let to = T::CrossAccountId::from_eth(to);115 let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;116117 <Module<T>>::transfer_from_internal(&caller, &from, &to, &self, token_id, 1)118 .map_err(|_| "transferFrom error")?;119 Ok(())120 }121122 fn approve(123 &mut self,124 caller: caller,125 approved: address,126 token_id: uint256,127 _value: value,128 ) -> Result<void> {129 let caller = T::CrossAccountId::from_eth(caller);130 let approved = T::CrossAccountId::from_eth(approved);131 let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;132133 <Module<T>>::approve_internal(&caller, &approved, &self, token_id, 1)134 .map_err(|_| "approve internal")?;135 Ok(())136 }137138 fn set_approval_for_all(139 &mut self,140 _caller: caller,141 _operator: address,142 _approved: bool,143 ) -> Result<void> {144 145 Err("not implemented".into())146 }147148 fn get_approved(&self, _token_id: uint256) -> Result<address> {149 150 Err("not implemented".into())151 }152153 fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {154 155 Err("not implemented".into())156 }157158 fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {159 let ERC165Call::SupportsInterface { interface_id } = c.call;160 Ok(evm_coder::abi_encode!(bool(161 &ERC721Call::supports_interface(interface_id)162 )))163 }164}165166impl<T: Config> ERC721UniqueExtensions for CollectionHandle<T> {167 type Error = StringError;168 fn transfer(169 &mut self,170 caller: caller,171 to: address,172 token_id: uint256,173 _value: value,174 ) -> Result<void> {175 let caller = T::CrossAccountId::from_eth(caller);176 let to = T::CrossAccountId::from_eth(to);177 let token_id = token_id.try_into().map_err(|_| "amount overflow")?;178179 <Module<T>>::transfer_internal(&caller, &to, &self, token_id, 1)180 .map_err(|_| "transfer error")?;181 Ok(())182 }183}184185impl<T: Config> UniqueNFT for CollectionHandle<T> {186 type Error = StringError;187 fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {188 let ERC165Call::SupportsInterface { interface_id } = c.call;189 Ok(evm_coder::abi_encode!(bool(190 &UniqueNFTCall::supports_interface(interface_id)191 )))192 }193 fn call_erc721(&mut self, c: Msg<ERC721Call>) -> Result<AbiWriter> {194 <Self as ERC721>::call(self, c)195 }196 fn call_erc721_metadata(&mut self, c: Msg<ERC721MetadataCall>) -> Result<AbiWriter> {197 <Self as ERC721Metadata>::call(self, c)198 }199 fn call_erc721_enumerable(&mut self, c: Msg<ERC721EnumerableCall>) -> Result<AbiWriter> {200 <Self as ERC721Enumerable>::call(self, c)201 }202 fn call_erc721_unique_extensions(203 &mut self,204 c: Msg<ERC721UniqueExtensionsCall>,205 ) -> Result<AbiWriter> {206 <Self as ERC721UniqueExtensions>::call(self, c)207 }208}209210impl<T: Config> ERC20 for CollectionHandle<T> {211 type Error = StringError;212 fn decimals(&self) -> Result<uint8> {213 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {214 *decimals215 } else {216 unreachable!()217 })218 }219 fn balance_of(&self, owner: address) -> Result<uint256> {220 let owner = T::EvmAddressMapping::into_account_id(owner);221 let balance = <Balance<T>>::get(self.id, owner);222 Ok(balance.into())223 }224 fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {225 let caller = T::CrossAccountId::from_eth(caller);226 let to = T::CrossAccountId::from_eth(to);227 let amount = amount.try_into().map_err(|_| "amount overflow")?;228229 <Module<T>>::transfer_internal(&caller, &to, &self, 1, amount)230 .map_err(|_| "transfer error")?;231 Ok(true)232 }233 fn transfer_from(234 &mut self,235 caller: caller,236 from: address,237 to: address,238 amount: uint256,239 ) -> Result<bool> {240 let caller = T::CrossAccountId::from_eth(caller);241 let from = T::CrossAccountId::from_eth(from);242 let to = T::CrossAccountId::from_eth(to);243 let amount = amount.try_into().map_err(|_| "amount overflow")?;244245 <Module<T>>::transfer_from_internal(&caller, &from, &to, &self, 1, amount)246 .map_err(|_| "transferFrom error")?;247 Ok(true)248 }249 fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {250 let caller = T::CrossAccountId::from_eth(caller);251 let spender = T::CrossAccountId::from_eth(spender);252 let amount = amount.try_into().map_err(|_| "amount overflow")?;253254 <Module<T>>::approve_internal(&caller, &spender, &self, 1, amount)255 .map_err(|_| "approve internal")?;256 Ok(true)257 }258 fn allowance(&self, owner: address, spender: address) -> Result<uint256> {259 let owner = T::CrossAccountId::from_eth(owner);260 let spender = T::CrossAccountId::from_eth(spender);261262 Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())263 }264 fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {265 <Self as InlineNameSymbol>::call(self, c)266 }267 fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {268 <Self as InlineTotalSupply>::call(self, c)269 }270}271272impl<T: Config> UniqueFungible for CollectionHandle<T> {273 type Error = StringError;274 fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {275 let ERC165Call::SupportsInterface { interface_id } = c.call;276 Ok(evm_coder::abi_encode!(bool(277 &UniqueNFTCall::supports_interface(interface_id)278 )))279 }280 fn call_erc20(&mut self, c: Msg<ERC20Call>) -> Result<AbiWriter> {281 <Self as ERC20>::call(self, c)282 }283}