git.delta.rocks / unique-network / refs/commits / 749341e77d24

difftreelog

feat(refungible-pallet) ERC-721 EVM API

Grigoriy Simonov2022-07-25parent: #2232fc1.patch.diff
in: master

12 files changed

modifiedMakefilediffbeforeafterboth
15NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs15NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs
16NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json16NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json
1717
18REFUNGIBLE_EVM_STUBS=./pallets/refungible/src/stubs
18RENFUNGIBLE_EVM_ABI=./tests/src/eth/reFungibleAbi.json19REFUNGIBLE_EVM_ABI=./tests/src/eth/reFungibleAbi.json
19RENFUNGIBLE_TOKEN_EVM_ABI=./tests/src/eth/reFungibleTokenAbi.json20REFUNGIBLE_TOKEN_EVM_ABI=./tests/src/eth/reFungibleTokenAbi.json
2021
21CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/22CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/
22CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json23CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json
36UniqueNFT.sol:37UniqueNFT.sol:
37 PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh38 PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
38 PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh39 PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
39 40
41UniqueRefungible.sol:
42 PACKAGE=pallet-refungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
43 PACKAGE=pallet-refungible NAME=erc::gen_impl OUTPUT=$(REFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
44
40UniqueRefungible.sol:45UniqueRefungible.sol:
41 PACKAGE=pallet-refungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh46 PACKAGE=pallet-refungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
42 PACKAGE=pallet-refungible NAME=erc::gen_impl OUTPUT=$(REFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh47 PACKAGE=pallet-refungible NAME=erc::gen_impl OUTPUT=$(REFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
61 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.raw ./.maintain/scripts/compile_stub.sh66 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.raw ./.maintain/scripts/compile_stub.sh
62 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh67 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh
68
69UniqueRefungible: UniqueRefungible.sol
70 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungible.raw ./.maintain/scripts/compile_stub.sh
71 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh
6372
64UniqueRefungibleToken: UniqueRefungibleToken.sol73UniqueRefungibleToken: UniqueRefungibleToken.sol
65 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungibleToken.raw ./.maintain/scripts/compile_stub.sh74 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungibleToken.raw ./.maintain/scripts/compile_stub.sh
66 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(RENFUNGIBLE_TOKEN_EVM_ABI) ./.maintain/scripts/generate_abi.sh75 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_TOKEN_EVM_ABI) ./.maintain/scripts/generate_abi.sh
6776
68UniqueRefungible: UniqueRefungible.sol77UniqueRefungible: UniqueRefungible.sol
69 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungible.raw ./.maintain/scripts/compile_stub.sh78 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungible.raw ./.maintain/scripts/compile_stub.sh
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
1616
17extern crate alloc;17extern crate alloc;
18
19use alloc::string::ToString;
20use core::{
21 char::{REPLACEMENT_CHARACTER, decode_utf16},
22 convert::TryInto,
23};
18use evm_coder::{generate_stubgen, solidity_interface, types::*};24use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};
1925use frame_support::{BoundedBTreeMap, BoundedVec};
20use pallet_common::{CollectionHandle, erc::CollectionCall, erc::CommonEvmHandler};26use pallet_common::{
2127 CollectionHandle, CollectionPropertyPermissions,
28 erc::{
29 CommonEvmHandler, CollectionCall,
30 static_property::{key, value as property_value},
31 },
32};
22use pallet_evm::PrecompileHandle;33use pallet_evm::{account::CrossAccountId, PrecompileHandle};
23use pallet_evm_coder_substrate::call;34use pallet_evm_coder_substrate::{call, dispatch_to_evm};
35use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
36use sp_core::H160;
37use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec};
38use up_data_structs::{
39 CollectionId, CollectionPropertiesVec, Property, PropertyKey, PropertyKeyPermission,
40 PropertyPermission, TokenId,
41};
2442
25use crate::{Config, RefungibleHandle};43use crate::{
44 AccountBalance, Config, CreateItemData, Pallet, RefungibleHandle, SelfWeightOf,
45 TokenProperties, TokensMinted, weights::WeightInfo,
46};
47
48#[solidity_interface(name = "TokenProperties")]
49impl<T: Config> RefungibleHandle<T> {
50 fn set_token_property_permission(
51 &mut self,
52 caller: caller,
53 key: string,
54 is_mutable: bool,
55 collection_admin: bool,
56 token_owner: bool,
57 ) -> Result<()> {
58 let caller = T::CrossAccountId::from_eth(caller);
59 <Pallet<T>>::set_token_property_permissions(
60 self,
61 &caller,
62 vec![PropertyKeyPermission {
63 key: <Vec<u8>>::from(key)
64 .try_into()
65 .map_err(|_| "too long key")?,
66 permission: PropertyPermission {
67 mutable: is_mutable,
68 collection_admin,
69 token_owner,
70 },
71 }],
72 )
73 .map_err(dispatch_to_evm::<T>)
74 }
75
76 fn set_property(
77 &mut self,
78 caller: caller,
79 token_id: uint256,
80 key: string,
81 value: bytes,
82 ) -> Result<()> {
83 let caller = T::CrossAccountId::from_eth(caller);
84 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
85 let key = <Vec<u8>>::from(key)
86 .try_into()
87 .map_err(|_| "key too long")?;
88 let value = value.try_into().map_err(|_| "value too long")?;
89
90 let nesting_budget = self
91 .recorder
92 .weight_calls_budget(<StructureWeight<T>>::find_parent());
93
94 <Pallet<T>>::set_token_property(
95 self,
96 &caller,
97 TokenId(token_id),
98 Property { key, value },
99 &nesting_budget,
100 )
101 .map_err(dispatch_to_evm::<T>)
102 }
103
104 fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {
105 let caller = T::CrossAccountId::from_eth(caller);
106 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
107 let key = <Vec<u8>>::from(key)
108 .try_into()
109 .map_err(|_| "key too long")?;
110
111 let nesting_budget = self
112 .recorder
113 .weight_calls_budget(<StructureWeight<T>>::find_parent());
114
115 <Pallet<T>>::delete_token_property(self, &caller, TokenId(token_id), key, &nesting_budget)
116 .map_err(dispatch_to_evm::<T>)
117 }
118
119 /// Throws error if key not found
120 fn property(&self, token_id: uint256, key: string) -> Result<bytes> {
121 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
122 let key = <Vec<u8>>::from(key)
123 .try_into()
124 .map_err(|_| "key too long")?;
125
126 let props = <TokenProperties<T>>::get((self.id, token_id));
127 let prop = props.get(&key).ok_or("key not found")?;
128
129 Ok(prop.to_vec())
130 }
131}
132
133#[derive(ToLog)]
134pub enum ERC721Events {
135 Transfer {
136 #[indexed]
137 from: address,
138 #[indexed]
139 to: address,
140 #[indexed]
141 token_id: uint256,
142 },
143 /// @dev Not supported
144 Approval {
145 #[indexed]
146 owner: address,
147 #[indexed]
148 approved: address,
149 #[indexed]
150 token_id: uint256,
151 },
152 /// @dev Not supported
153 #[allow(dead_code)]
154 ApprovalForAll {
155 #[indexed]
156 owner: address,
157 #[indexed]
158 operator: address,
159 approved: bool,
160 },
161}
162
163#[derive(ToLog)]
164pub enum ERC721MintableEvents {
165 /// @dev Not supported
166 #[allow(dead_code)]
167 MintingFinished {},
168}
169
170#[solidity_interface(name = "ERC721Metadata")]
171impl<T: Config> RefungibleHandle<T> {
172 fn name(&self) -> Result<string> {
173 Ok(decode_utf16(self.name.iter().copied())
174 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
175 .collect::<string>())
176 }
177
178 fn symbol(&self) -> Result<string> {
179 Ok(string::from_utf8_lossy(&self.token_prefix).into())
180 }
181
182 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
183 ///
184 /// @dev If the token has a `url` property and it is not empty, it is returned.
185 /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
186 /// If the collection property `baseURI` is empty or absent, return "" (empty string)
187 /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
188 /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
189 ///
190 /// @return token's const_metadata
191 #[solidity(rename_selector = "tokenURI")]
192 fn token_uri(&self, token_id: uint256) -> Result<string> {
193 let token_id_u32: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
194
195 if let Ok(url) = get_token_property(self, token_id_u32, &key::url()) {
196 if !url.is_empty() {
197 return Ok(url);
198 }
199 } else if !is_erc721_metadata_compatible::<T>(self.id) {
200 return Err("tokenURI not set".into());
201 }
202
203 if let Some(base_uri) =
204 pallet_common::Pallet::<T>::get_collection_property(self.id, &key::base_uri())
205 {
206 if !base_uri.is_empty() {
207 let base_uri = string::from_utf8(base_uri.into_inner()).map_err(|e| {
208 Error::Revert(alloc::format!(
209 "Can not convert value \"baseURI\" to string with error \"{}\"",
210 e
211 ))
212 })?;
213 if let Ok(suffix) = get_token_property(self, token_id_u32, &key::suffix()) {
214 if !suffix.is_empty() {
215 return Ok(base_uri + suffix.as_str());
216 }
217 }
218
219 return Ok(base_uri + token_id.to_string().as_str());
220 }
221 }
222
223 Ok("".into())
224 }
225}
226
227#[solidity_interface(name = "ERC721Enumerable")]
228impl<T: Config> RefungibleHandle<T> {
229 fn token_by_index(&self, index: uint256) -> Result<uint256> {
230 Ok(index)
231 }
232
233 /// Not implemented
234 fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {
235 // TODO: Not implemetable
236 Err("not implemented".into())
237 }
238
239 fn total_supply(&self) -> Result<uint256> {
240 self.consume_store_reads(1)?;
241 Ok(<Pallet<T>>::total_supply(self).into())
242 }
243}
244
245#[solidity_interface(name = "ERC721", events(ERC721Events))]
246impl<T: Config> RefungibleHandle<T> {
247 fn balance_of(&self, owner: address) -> Result<uint256> {
248 self.consume_store_reads(1)?;
249 let owner = T::CrossAccountId::from_eth(owner);
250 let balance = <AccountBalance<T>>::get((self.id, owner));
251 Ok(balance.into())
252 }
253
254 fn owner_of(&self, token_id: uint256) -> Result<address> {
255 self.consume_store_reads(2)?;
256 let token = token_id.try_into()?;
257 let owner = <Pallet<T>>::token_owner(self.id, token);
258 Ok(owner
259 .map(|address| *address.as_eth())
260 .unwrap_or_else(|| H160::default()))
261 }
262
263 /// @dev Not implemented
264 fn safe_transfer_from_with_data(
265 &mut self,
266 _from: address,
267 _to: address,
268 _token_id: uint256,
269 _data: bytes,
270 _value: value,
271 ) -> Result<void> {
272 // TODO: Not implemetable
273 Err("not implemented".into())
274 }
275
276 /// @dev Not implemented
277 fn safe_transfer_from(
278 &mut self,
279 _from: address,
280 _to: address,
281 _token_id: uint256,
282 _value: value,
283 ) -> Result<void> {
284 // TODO: Not implemetable
285 Err("not implemented".into())
286 }
287
288 /// @dev Not implemented
289 fn transfer_from(
290 &mut self,
291 _caller: caller,
292 _from: address,
293 _to: address,
294 _token_id: uint256,
295 _value: value,
296 ) -> Result<void> {
297 Err("not implemented".into())
298 }
299
300 /// @dev Not implemented
301 fn approve(
302 &mut self,
303 _caller: caller,
304 _approved: address,
305 _token_id: uint256,
306 _value: value,
307 ) -> Result<void> {
308 Err("not implemented".into())
309 }
310
311 /// @dev Not implemented
312 fn set_approval_for_all(
313 &mut self,
314 _caller: caller,
315 _operator: address,
316 _approved: bool,
317 ) -> Result<void> {
318 // TODO: Not implemetable
319 Err("not implemented".into())
320 }
321
322 /// @dev Not implemented
323 fn get_approved(&self, _token_id: uint256) -> Result<address> {
324 // TODO: Not implemetable
325 Err("not implemented".into())
326 }
327
328 /// @dev Not implemented
329 fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {
330 // TODO: Not implemetable
331 Err("not implemented".into())
332 }
333}
334
335#[solidity_interface(name = "ERC721Burnable")]
336impl<T: Config> RefungibleHandle<T> {
337 /// @dev Not implemented
338 fn burn(&mut self, _caller: caller, _token_id: uint256, _value: value) -> Result<void> {
339 Err("not implemented".into())
340 }
341}
342
343#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]
344impl<T: Config> RefungibleHandle<T> {
345 fn minting_finished(&self) -> Result<bool> {
346 Ok(false)
347 }
348
349 /// `token_id` should be obtained with `next_token_id` method,
350 /// unlike standard, you can't specify it manually
351 #[weight(<SelfWeightOf<T>>::create_item())]
352 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {
353 let caller = T::CrossAccountId::from_eth(caller);
354 let to = T::CrossAccountId::from_eth(to);
355 let token_id: u32 = token_id.try_into()?;
356 let budget = self
357 .recorder
358 .weight_calls_budget(<StructureWeight<T>>::find_parent());
359
360 if <TokensMinted<T>>::get(self.id)
361 .checked_add(1)
362 .ok_or("item id overflow")?
363 != token_id
364 {
365 return Err("item id should be next".into());
366 }
367
368 let const_data = BoundedVec::default();
369 let users = [(to.clone(), 1)]
370 .into_iter()
371 .collect::<BTreeMap<_, _>>()
372 .try_into()
373 .unwrap();
374 <Pallet<T>>::create_item(
375 self,
376 &caller,
377 CreateItemData::<T> {
378 const_data,
379 users,
380 properties: CollectionPropertiesVec::default(),
381 },
382 &budget,
383 )
384 .map_err(dispatch_to_evm::<T>)?;
385
386 Ok(true)
387 }
388
389 /// `token_id` should be obtained with `next_token_id` method,
390 /// unlike standard, you can't specify it manually
391 #[solidity(rename_selector = "mintWithTokenURI")]
392 #[weight(<SelfWeightOf<T>>::create_item())]
393 fn mint_with_token_uri(
394 &mut self,
395 caller: caller,
396 to: address,
397 token_id: uint256,
398 token_uri: string,
399 ) -> Result<bool> {
400 let key = key::url();
401 let permission = get_token_permission::<T>(self.id, &key)?;
402 if !permission.collection_admin {
403 return Err("Operation is not allowed".into());
404 }
405
406 let caller = T::CrossAccountId::from_eth(caller);
407 let to = T::CrossAccountId::from_eth(to);
408 let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;
409 let budget = self
410 .recorder
411 .weight_calls_budget(<StructureWeight<T>>::find_parent());
412
413 if <TokensMinted<T>>::get(self.id)
414 .checked_add(1)
415 .ok_or("item id overflow")?
416 != token_id
417 {
418 return Err("item id should be next".into());
419 }
420
421 let mut properties = CollectionPropertiesVec::default();
422 properties
423 .try_push(Property {
424 key,
425 value: token_uri
426 .into_bytes()
427 .try_into()
428 .map_err(|_| "token uri is too long")?,
429 })
430 .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
431
432 let const_data = BoundedVec::default();
433 let users = [(to.clone(), 1)]
434 .into_iter()
435 .collect::<BTreeMap<_, _>>()
436 .try_into()
437 .unwrap();
438 <Pallet<T>>::create_item(
439 self,
440 &caller,
441 CreateItemData::<T> {
442 const_data,
443 users,
444 properties,
445 },
446 &budget,
447 )
448 .map_err(dispatch_to_evm::<T>)?;
449 Ok(true)
450 }
451
452 /// @dev Not implemented
453 fn finish_minting(&mut self, _caller: caller) -> Result<bool> {
454 Err("not implementable".into())
455 }
456}
457
458fn get_token_property<T: Config>(
459 collection: &CollectionHandle<T>,
460 token_id: u32,
461 key: &up_data_structs::PropertyKey,
462) -> Result<string> {
463 collection.consume_store_reads(1)?;
464 let properties = <TokenProperties<T>>::try_get((collection.id, token_id))
465 .map_err(|_| Error::Revert("Token properties not found".into()))?;
466 if let Some(property) = properties.get(key) {
467 return Ok(string::from_utf8_lossy(property).into());
468 }
469
470 Err("Property tokenURI not found".into())
471}
472
473fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {
474 if let Some(shema_name) =
475 pallet_common::Pallet::<T>::get_collection_property(collection_id, &key::schema_name())
476 {
477 let shema_name = shema_name.into_inner();
478 shema_name == property_value::ERC721_METADATA
479 } else {
480 false
481 }
482}
483
484fn get_token_permission<T: Config>(
485 collection_id: CollectionId,
486 key: &PropertyKey,
487) -> Result<PropertyPermission> {
488 let token_property_permissions = CollectionPropertyPermissions::<T>::try_get(collection_id)
489 .map_err(|_| Error::Revert("No permissions for collection".into()))?;
490 let a = token_property_permissions
491 .get(key)
492 .map(Clone::clone)
493 .ok_or_else(|| {
494 let key = string::from_utf8(key.clone().into_inner()).unwrap_or_default();
495 Error::Revert(alloc::format!("No permission for key {}", key))
496 })?;
497 Ok(a)
498}
499
500#[solidity_interface(name = "ERC721UniqueExtensions")]
501impl<T: Config> RefungibleHandle<T> {
502 /// @notice Returns next free RFT ID.
503 fn next_token_id(&self) -> Result<uint256> {
504 self.consume_store_reads(1)?;
505 Ok(<TokensMinted<T>>::get(self.id)
506 .checked_add(1)
507 .ok_or("item id overflow")?
508 .into())
509 }
510
511 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]
512 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
513 let caller = T::CrossAccountId::from_eth(caller);
514 let to = T::CrossAccountId::from_eth(to);
515 let mut expected_index = <TokensMinted<T>>::get(self.id)
516 .checked_add(1)
517 .ok_or("item id overflow")?;
518 let budget = self
519 .recorder
520 .weight_calls_budget(<StructureWeight<T>>::find_parent());
521
522 let total_tokens = token_ids.len();
523 for id in token_ids.into_iter() {
524 let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
525 if id != expected_index {
526 return Err("item id should be next".into());
527 }
528 expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;
529 }
530 let const_data = BoundedVec::default();
531 let users = [(to.clone(), 1)]
532 .into_iter()
533 .collect::<BTreeMap<_, _>>()
534 .try_into()
535 .unwrap();
536 let create_item_data = CreateItemData::<T> {
537 const_data,
538 users,
539 properties: CollectionPropertiesVec::default(),
540 };
541 let data = (0..total_tokens)
542 .map(|_| create_item_data.clone())
543 .collect();
544
545 <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)
546 .map_err(dispatch_to_evm::<T>)?;
547 Ok(true)
548 }
549
550 #[solidity(rename_selector = "mintBulkWithTokenURI")]
551 #[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]
552 fn mint_bulk_with_token_uri(
553 &mut self,
554 caller: caller,
555 to: address,
556 tokens: Vec<(uint256, string)>,
557 ) -> Result<bool> {
558 let key = key::url();
559 let caller = T::CrossAccountId::from_eth(caller);
560 let to = T::CrossAccountId::from_eth(to);
561 let mut expected_index = <TokensMinted<T>>::get(self.id)
562 .checked_add(1)
563 .ok_or("item id overflow")?;
564 let budget = self
565 .recorder
566 .weight_calls_budget(<StructureWeight<T>>::find_parent());
567
568 let mut data = Vec::with_capacity(tokens.len());
569 let const_data = BoundedVec::default();
570 let users: BoundedBTreeMap<_, _, _> = [(to.clone(), 1)]
571 .into_iter()
572 .collect::<BTreeMap<_, _>>()
573 .try_into()
574 .unwrap();
575 for (id, token_uri) in tokens {
576 let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
577 if id != expected_index {
578 return Err("item id should be next".into());
579 }
580 expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;
581
582 let mut properties = CollectionPropertiesVec::default();
583 properties
584 .try_push(Property {
585 key: key.clone(),
586 value: token_uri
587 .into_bytes()
588 .try_into()
589 .map_err(|_| "token uri is too long")?,
590 })
591 .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
592
593 let create_item_data = CreateItemData::<T> {
594 const_data: const_data.clone(),
595 users: users.clone(),
596 properties,
597 };
598 data.push(create_item_data);
599 }
600
601 <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)
602 .map_err(dispatch_to_evm::<T>)?;
603 Ok(true)
604 }
605}
26606
27#[solidity_interface(607#[solidity_interface(
28 name = "UniqueRefungible",608 name = "UniqueRefungible",
29 is(via("CollectionHandle<T>", common_mut, Collection),)609 is(
610 ERC721,
611 ERC721Metadata,
612 ERC721Enumerable,
613 ERC721UniqueExtensions,
614 ERC721Mintable,
615 ERC721Burnable,
616 via("CollectionHandle<T>", common_mut, Collection),
617 TokenProperties,
618 )
30)]619)]
31impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> {}620impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> {}
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
88#![cfg_attr(not(feature = "std"), no_std)]88#![cfg_attr(not(feature = "std"), no_std)]
8989
90use crate::erc_token::ERC20Events;90use crate::erc_token::ERC20Events;
91use crate::erc::ERC721Events;
9192
92use codec::{Encode, Decode, MaxEncodedLen};93use codec::{Encode, Decode, MaxEncodedLen};
93use core::ops::Deref;94use core::ops::Deref;
97use pallet_evm_coder_substrate::WithRecorder;98use pallet_evm_coder_substrate::WithRecorder;
98use pallet_common::{99use pallet_common::{
99 CommonCollectionOperations, Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,100 CommonCollectionOperations, Error as CommonError, Event as CommonEvent,
101 eth::collection_id_to_address, Pallet as PalletCommon,
100};102};
101use pallet_structure::Pallet as PalletStructure;103use pallet_structure::Pallet as PalletStructure;
102use scale_info::TypeInfo;104use scale_info::TypeInfo;
118pub mod erc_token;120pub mod erc_token;
119pub mod weights;121pub mod weights;
122
123pub type CreateItemData<T> =
124 CreateRefungibleExData<<T as pallet_evm::account::Config>::CrossAccountId>;
120pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;125pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
121126
122/// Token data, stored independently from other data used to describe it127/// Token data, stored independently from other data used to describe it
797 pub fn create_multiple_items(803 pub fn create_multiple_items(
798 collection: &RefungibleHandle<T>,804 collection: &RefungibleHandle<T>,
799 sender: &T::CrossAccountId,805 sender: &T::CrossAccountId,
800 data: Vec<CreateRefungibleExData<T::CrossAccountId>>,806 data: Vec<CreateItemData<T>>,
801 nesting_budget: &dyn Budget,807 nesting_budget: &dyn Budget,
802 ) -> DispatchResult {808 ) -> DispatchResult {
803 if !collection.is_owner_or_admin(sender) {809 if !collection.is_owner_or_admin(sender) {
942 TokenId(token_id),948 TokenId(token_id),
943 )),949 )),
944 );950 );
951 <PalletEvm<T>>::deposit_log(
952 ERC721Events::Transfer {
953 from: H160::default(),
954 to: *user.as_eth(),
955 token_id: token_id.into(),
956 }
957 .to_log(collection_id_to_address(collection.id)),
958 );
945 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(959 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(
946 collection.id,960 collection.id,
947 TokenId(token_id),961 TokenId(token_id),
1120 pub fn create_item(1134 pub fn create_item(
1121 collection: &RefungibleHandle<T>,1135 collection: &RefungibleHandle<T>,
1122 sender: &T::CrossAccountId,1136 sender: &T::CrossAccountId,
1123 data: CreateRefungibleExData<T::CrossAccountId>,1137 data: CreateItemData<T>,
1124 nesting_budget: &dyn Budget,1138 nesting_budget: &dyn Budget,
1125 ) -> DispatchResult {1139 ) -> DispatchResult {
1126 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)1140 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)
modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
33
4pragma solidity >=0.8.0 <0.9.0;4pragma solidity >=0.8.0 <0.9.0;
5
6// Anonymous struct
7struct Tuple0 {
8 uint256 field_0;
9 string field_1;
10}
511
6// Common stubs holder12// Common stubs holder
7contract Dummy {13contract Dummy {
21 }27 }
22}28}
29
30// Inline
31contract ERC721Events {
32 event Transfer(
33 address indexed from,
34 address indexed to,
35 uint256 indexed tokenId
36 );
37 event Approval(
38 address indexed owner,
39 address indexed approved,
40 uint256 indexed tokenId
41 );
42 event ApprovalForAll(
43 address indexed owner,
44 address indexed operator,
45 bool approved
46 );
47}
48
49// Inline
50contract ERC721MintableEvents {
51 event MintingFinished();
52}
53
54// Selector: 0784ee64
55contract ERC721UniqueExtensions is Dummy, ERC165 {
56 // @notice Returns next free RFT ID.
57 //
58 // Selector: nextTokenId() 75794a3c
59 function nextTokenId() public view returns (uint256) {
60 require(false, stub_error);
61 dummy;
62 return 0;
63 }
64
65 // Selector: mintBulk(address,uint256[]) 44a9945e
66 function mintBulk(address to, uint256[] memory tokenIds)
67 public
68 returns (bool)
69 {
70 require(false, stub_error);
71 to;
72 tokenIds;
73 dummy = 0;
74 return false;
75 }
76
77 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
78 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
79 public
80 returns (bool)
81 {
82 require(false, stub_error);
83 to;
84 tokens;
85 dummy = 0;
86 return false;
87 }
88}
89
90// Selector: 41369377
91contract TokenProperties is Dummy, ERC165 {
92 // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
93 function setTokenPropertyPermission(
94 string memory key,
95 bool isMutable,
96 bool collectionAdmin,
97 bool tokenOwner
98 ) public {
99 require(false, stub_error);
100 key;
101 isMutable;
102 collectionAdmin;
103 tokenOwner;
104 dummy = 0;
105 }
106
107 // Selector: setProperty(uint256,string,bytes) 1752d67b
108 function setProperty(
109 uint256 tokenId,
110 string memory key,
111 bytes memory value
112 ) public {
113 require(false, stub_error);
114 tokenId;
115 key;
116 value;
117 dummy = 0;
118 }
119
120 // Selector: deleteProperty(uint256,string) 066111d1
121 function deleteProperty(uint256 tokenId, string memory key) public {
122 require(false, stub_error);
123 tokenId;
124 key;
125 dummy = 0;
126 }
127
128 // Throws error if key not found
129 //
130 // Selector: property(uint256,string) 7228c327
131 function property(uint256 tokenId, string memory key)
132 public
133 view
134 returns (bytes memory)
135 {
136 require(false, stub_error);
137 tokenId;
138 key;
139 dummy;
140 return hex"";
141 }
142}
143
144// Selector: 42966c68
145contract ERC721Burnable is Dummy, ERC165 {
146 // @dev Not implemented
147 //
148 // Selector: burn(uint256) 42966c68
149 function burn(uint256 tokenId) public {
150 require(false, stub_error);
151 tokenId;
152 dummy = 0;
153 }
154}
155
156// Selector: 58800161
157contract ERC721 is Dummy, ERC165, ERC721Events {
158 // Selector: balanceOf(address) 70a08231
159 function balanceOf(address owner) public view returns (uint256) {
160 require(false, stub_error);
161 owner;
162 dummy;
163 return 0;
164 }
165
166 // Selector: ownerOf(uint256) 6352211e
167 function ownerOf(uint256 tokenId) public view returns (address) {
168 require(false, stub_error);
169 tokenId;
170 dummy;
171 return 0x0000000000000000000000000000000000000000;
172 }
173
174 // @dev Not implemented
175 //
176 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672
177 function safeTransferFromWithData(
178 address from,
179 address to,
180 uint256 tokenId,
181 bytes memory data
182 ) public {
183 require(false, stub_error);
184 from;
185 to;
186 tokenId;
187 data;
188 dummy = 0;
189 }
190
191 // @dev Not implemented
192 //
193 // Selector: safeTransferFrom(address,address,uint256) 42842e0e
194 function safeTransferFrom(
195 address from,
196 address to,
197 uint256 tokenId
198 ) public {
199 require(false, stub_error);
200 from;
201 to;
202 tokenId;
203 dummy = 0;
204 }
205
206 // @dev Not implemented
207 //
208 // Selector: transferFrom(address,address,uint256) 23b872dd
209 function transferFrom(
210 address from,
211 address to,
212 uint256 tokenId
213 ) public {
214 require(false, stub_error);
215 from;
216 to;
217 tokenId;
218 dummy = 0;
219 }
220
221 // @dev Not implemented
222 //
223 // Selector: approve(address,uint256) 095ea7b3
224 function approve(address approved, uint256 tokenId) public {
225 require(false, stub_error);
226 approved;
227 tokenId;
228 dummy = 0;
229 }
230
231 // @dev Not implemented
232 //
233 // Selector: setApprovalForAll(address,bool) a22cb465
234 function setApprovalForAll(address operator, bool approved) public {
235 require(false, stub_error);
236 operator;
237 approved;
238 dummy = 0;
239 }
240
241 // @dev Not implemented
242 //
243 // Selector: getApproved(uint256) 081812fc
244 function getApproved(uint256 tokenId) public view returns (address) {
245 require(false, stub_error);
246 tokenId;
247 dummy;
248 return 0x0000000000000000000000000000000000000000;
249 }
250
251 // @dev Not implemented
252 //
253 // Selector: isApprovedForAll(address,address) e985e9c5
254 function isApprovedForAll(address owner, address operator)
255 public
256 view
257 returns (address)
258 {
259 require(false, stub_error);
260 owner;
261 operator;
262 dummy;
263 return 0x0000000000000000000000000000000000000000;
264 }
265}
266
267// Selector: 5b5e139f
268contract ERC721Metadata is Dummy, ERC165 {
269 // Selector: name() 06fdde03
270 function name() public view returns (string memory) {
271 require(false, stub_error);
272 dummy;
273 return "";
274 }
275
276 // Selector: symbol() 95d89b41
277 function symbol() public view returns (string memory) {
278 require(false, stub_error);
279 dummy;
280 return "";
281 }
282
283 // Returns token's const_metadata
284 //
285 // Selector: tokenURI(uint256) c87b56dd
286 function tokenURI(uint256 tokenId) public view returns (string memory) {
287 require(false, stub_error);
288 tokenId;
289 dummy;
290 return "";
291 }
292}
293
294// Selector: 68ccfe89
295contract ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {
296 // Selector: mintingFinished() 05d2035b
297 function mintingFinished() public view returns (bool) {
298 require(false, stub_error);
299 dummy;
300 return false;
301 }
302
303 // `token_id` should be obtained with `next_token_id` method,
304 // unlike standard, you can't specify it manually
305 //
306 // Selector: mint(address,uint256) 40c10f19
307 function mint(address to, uint256 tokenId) public returns (bool) {
308 require(false, stub_error);
309 to;
310 tokenId;
311 dummy = 0;
312 return false;
313 }
314
315 // `token_id` should be obtained with `next_token_id` method,
316 // unlike standard, you can't specify it manually
317 //
318 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f
319 function mintWithTokenURI(
320 address to,
321 uint256 tokenId,
322 string memory tokenUri
323 ) public returns (bool) {
324 require(false, stub_error);
325 to;
326 tokenId;
327 tokenUri;
328 dummy = 0;
329 return false;
330 }
331
332 // @dev Not implemented
333 //
334 // Selector: finishMinting() 7d64bcb4
335 function finishMinting() public returns (bool) {
336 require(false, stub_error);
337 dummy = 0;
338 return false;
339 }
340}
341
342// Selector: 780e9d63
343contract ERC721Enumerable is Dummy, ERC165 {
344 // Selector: tokenByIndex(uint256) 4f6ccce7
345 function tokenByIndex(uint256 index) public view returns (uint256) {
346 require(false, stub_error);
347 index;
348 dummy;
349 return 0;
350 }
351
352 // Not implemented
353 //
354 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
355 function tokenOfOwnerByIndex(address owner, uint256 index)
356 public
357 view
358 returns (uint256)
359 {
360 require(false, stub_error);
361 owner;
362 index;
363 dummy;
364 return 0;
365 }
366
367 // Selector: totalSupply() 18160ddd
368 function totalSupply() public view returns (uint256) {
369 require(false, stub_error);
370 dummy;
371 return 0;
372 }
373}
23374
24// Selector: 7d9262e6375// Selector: 7d9262e6
25contract Collection is Dummy, ERC165 {376contract Collection is Dummy, ERC165 {
251contract UniqueRefungible is Dummy, ERC165, Collection {}602contract UniqueRefungible is
603 Dummy,
604 ERC165,
605 ERC721,
606 ERC721Metadata,
607 ERC721Enumerable,
608 ERC721UniqueExtensions,
609 ERC721Mintable,
610 ERC721Burnable,
611 Collection,
612 TokenProperties
613{}
252614
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
33
4pragma solidity >=0.8.0 <0.9.0;4pragma solidity >=0.8.0 <0.9.0;
5
6// Anonymous struct
7struct Tuple0 {
8 uint256 field_0;
9 string field_1;
10}
511
6// Common stubs holder12// Common stubs holder
7interface Dummy {13interface Dummy {
12 function supportsInterface(bytes4 interfaceID) external view returns (bool);18 function supportsInterface(bytes4 interfaceID) external view returns (bool);
13}19}
20
21// Inline
22interface ERC721Events {
23 event Transfer(
24 address indexed from,
25 address indexed to,
26 uint256 indexed tokenId
27 );
28 event Approval(
29 address indexed owner,
30 address indexed approved,
31 uint256 indexed tokenId
32 );
33 event ApprovalForAll(
34 address indexed owner,
35 address indexed operator,
36 bool approved
37 );
38}
39
40// Inline
41interface ERC721MintableEvents {
42 event MintingFinished();
43}
44
45// Selector: 0784ee64
46interface ERC721UniqueExtensions is Dummy, ERC165 {
47 // @notice Returns next free RFT ID.
48 //
49 // Selector: nextTokenId() 75794a3c
50 function nextTokenId() external view returns (uint256);
51
52 // Selector: mintBulk(address,uint256[]) 44a9945e
53 function mintBulk(address to, uint256[] memory tokenIds)
54 external
55 returns (bool);
56
57 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
58 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
59 external
60 returns (bool);
61}
62
63// Selector: 41369377
64interface TokenProperties is Dummy, ERC165 {
65 // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
66 function setTokenPropertyPermission(
67 string memory key,
68 bool isMutable,
69 bool collectionAdmin,
70 bool tokenOwner
71 ) external;
72
73 // Selector: setProperty(uint256,string,bytes) 1752d67b
74 function setProperty(
75 uint256 tokenId,
76 string memory key,
77 bytes memory value
78 ) external;
79
80 // Selector: deleteProperty(uint256,string) 066111d1
81 function deleteProperty(uint256 tokenId, string memory key) external;
82
83 // Throws error if key not found
84 //
85 // Selector: property(uint256,string) 7228c327
86 function property(uint256 tokenId, string memory key)
87 external
88 view
89 returns (bytes memory);
90}
91
92// Selector: 42966c68
93interface ERC721Burnable is Dummy, ERC165 {
94 // @dev Not implemented
95 //
96 // Selector: burn(uint256) 42966c68
97 function burn(uint256 tokenId) external;
98}
99
100// Selector: 58800161
101interface ERC721 is Dummy, ERC165, ERC721Events {
102 // Selector: balanceOf(address) 70a08231
103 function balanceOf(address owner) external view returns (uint256);
104
105 // Selector: ownerOf(uint256) 6352211e
106 function ownerOf(uint256 tokenId) external view returns (address);
107
108 // @dev Not implemented
109 //
110 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672
111 function safeTransferFromWithData(
112 address from,
113 address to,
114 uint256 tokenId,
115 bytes memory data
116 ) external;
117
118 // @dev Not implemented
119 //
120 // Selector: safeTransferFrom(address,address,uint256) 42842e0e
121 function safeTransferFrom(
122 address from,
123 address to,
124 uint256 tokenId
125 ) external;
126
127 // @dev Not implemented
128 //
129 // Selector: transferFrom(address,address,uint256) 23b872dd
130 function transferFrom(
131 address from,
132 address to,
133 uint256 tokenId
134 ) external;
135
136 // @dev Not implemented
137 //
138 // Selector: approve(address,uint256) 095ea7b3
139 function approve(address approved, uint256 tokenId) external;
140
141 // @dev Not implemented
142 //
143 // Selector: setApprovalForAll(address,bool) a22cb465
144 function setApprovalForAll(address operator, bool approved) external;
145
146 // @dev Not implemented
147 //
148 // Selector: getApproved(uint256) 081812fc
149 function getApproved(uint256 tokenId) external view returns (address);
150
151 // @dev Not implemented
152 //
153 // Selector: isApprovedForAll(address,address) e985e9c5
154 function isApprovedForAll(address owner, address operator)
155 external
156 view
157 returns (address);
158}
159
160// Selector: 5b5e139f
161interface ERC721Metadata is Dummy, ERC165 {
162 // Selector: name() 06fdde03
163 function name() external view returns (string memory);
164
165 // Selector: symbol() 95d89b41
166 function symbol() external view returns (string memory);
167
168 // Returns token's const_metadata
169 //
170 // Selector: tokenURI(uint256) c87b56dd
171 function tokenURI(uint256 tokenId) external view returns (string memory);
172}
173
174// Selector: 68ccfe89
175interface ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {
176 // Selector: mintingFinished() 05d2035b
177 function mintingFinished() external view returns (bool);
178
179 // `token_id` should be obtained with `next_token_id` method,
180 // unlike standard, you can't specify it manually
181 //
182 // Selector: mint(address,uint256) 40c10f19
183 function mint(address to, uint256 tokenId) external returns (bool);
184
185 // `token_id` should be obtained with `next_token_id` method,
186 // unlike standard, you can't specify it manually
187 //
188 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f
189 function mintWithTokenURI(
190 address to,
191 uint256 tokenId,
192 string memory tokenUri
193 ) external returns (bool);
194
195 // @dev Not implemented
196 //
197 // Selector: finishMinting() 7d64bcb4
198 function finishMinting() external returns (bool);
199}
200
201// Selector: 780e9d63
202interface ERC721Enumerable is Dummy, ERC165 {
203 // Selector: tokenByIndex(uint256) 4f6ccce7
204 function tokenByIndex(uint256 index) external view returns (uint256);
205
206 // Not implemented
207 //
208 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
209 function tokenOfOwnerByIndex(address owner, uint256 index)
210 external
211 view
212 returns (uint256);
213
214 // Selector: totalSupply() 18160ddd
215 function totalSupply() external view returns (uint256);
216}
14217
15// Selector: 7d9262e6218// Selector: 7d9262e6
16interface Collection is Dummy, ERC165 {219interface Collection is Dummy, ERC165 {
163interface UniqueRefungible is Dummy, ERC165, Collection {}366interface UniqueRefungible is
367 Dummy,
368 ERC165,
369 ERC721,
370 ERC721Metadata,
371 ERC721Enumerable,
372 ERC721UniqueExtensions,
373 ERC721Mintable,
374 ERC721Burnable,
375 Collection,
376 TokenProperties
377{}
164378
addedtests/src/eth/reFungibleAbi.jsondiffbeforeafterboth

no changes

modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
446 [key: string]: AugmentedError<ApiType>;446 [key: string]: AugmentedError<ApiType>;
447 };447 };
448 rmrkCore: {448 rmrkCore: {
449 /**
450 * Not the target owner of the sent NFT.
451 **/
449 CannotAcceptNonOwnedNft: AugmentedError<ApiType>;452 CannotAcceptNonOwnedNft: AugmentedError<ApiType>;
453 /**
454 * Not the target owner of the sent NFT.
455 **/
450 CannotRejectNonOwnedNft: AugmentedError<ApiType>;456 CannotRejectNonOwnedNft: AugmentedError<ApiType>;
457 /**
458 * NFT was not sent and is not pending.
459 **/
451 CannotRejectNonPendingNft: AugmentedError<ApiType>;460 CannotRejectNonPendingNft: AugmentedError<ApiType>;
461 /**
462 * If an NFT is sent to a descendant, that would form a nesting loop, an ouroboros.
463 * Sending to self is redundant.
464 **/
452 CannotSendToDescendentOrSelf: AugmentedError<ApiType>;465 CannotSendToDescendentOrSelf: AugmentedError<ApiType>;
466 /**
467 * Too many tokens created in the collection, no new ones are allowed.
468 **/
453 CollectionFullOrLocked: AugmentedError<ApiType>;469 CollectionFullOrLocked: AugmentedError<ApiType>;
470 /**
471 * Only destroying collections without tokens is allowed.
472 **/
454 CollectionNotEmpty: AugmentedError<ApiType>;473 CollectionNotEmpty: AugmentedError<ApiType>;
474 /**
475 * Collection does not exist, has a wrong type, or does not map to a Unique ID.
476 **/
455 CollectionUnknown: AugmentedError<ApiType>;477 CollectionUnknown: AugmentedError<ApiType>;
478 /**
479 * Property of the type of RMRK collection could not be read successfully.
480 **/
456 CorruptedCollectionType: AugmentedError<ApiType>;481 CorruptedCollectionType: AugmentedError<ApiType>;
457 NftTypeEncodeError: AugmentedError<ApiType>;482 /**
483 * Could not find an ID for a collection. It is likely there were too many collections created on the chain, causing an overflow.
484 **/
458 NoAvailableCollectionId: AugmentedError<ApiType>;485 NoAvailableCollectionId: AugmentedError<ApiType>;
486 /**
487 * Token does not exist, or there is no suitable ID for it, likely too many tokens were created in a collection, causing an overflow.
488 **/
459 NoAvailableNftId: AugmentedError<ApiType>;489 NoAvailableNftId: AugmentedError<ApiType>;
490 /**
491 * Could not find an ID for the resource. It is likely there were too many resources created on an NFT, causing an overflow.
492 **/
460 NoAvailableResourceId: AugmentedError<ApiType>;493 NoAvailableResourceId: AugmentedError<ApiType>;
494 /**
495 * Token is marked as non-transferable, and thus cannot be transferred.
496 **/
461 NonTransferable: AugmentedError<ApiType>;497 NonTransferable: AugmentedError<ApiType>;
498 /**
499 * No permission to perform action.
500 **/
462 NoPermission: AugmentedError<ApiType>;501 NoPermission: AugmentedError<ApiType>;
502 /**
503 * No such resource found.
504 **/
463 ResourceDoesntExist: AugmentedError<ApiType>;505 ResourceDoesntExist: AugmentedError<ApiType>;
506 /**
507 * Resource is not pending for the operation.
508 **/
464 ResourceNotPending: AugmentedError<ApiType>;509 ResourceNotPending: AugmentedError<ApiType>;
510 /**
511 * Could not find a property by the supplied key.
512 **/
465 RmrkPropertyIsNotFound: AugmentedError<ApiType>;513 RmrkPropertyIsNotFound: AugmentedError<ApiType>;
514 /**
515 * Too many symbols supplied as the property key. The maximum is [256](up_data_structs::MAX_PROPERTY_KEY_LENGTH).
516 **/
466 RmrkPropertyKeyIsTooLong: AugmentedError<ApiType>;517 RmrkPropertyKeyIsTooLong: AugmentedError<ApiType>;
518 /**
519 * Too many bytes supplied as the property value. The maximum is [32768](up_data_structs::MAX_PROPERTY_VALUE_LENGTH).
520 **/
467 RmrkPropertyValueIsTooLong: AugmentedError<ApiType>;521 RmrkPropertyValueIsTooLong: AugmentedError<ApiType>;
522 /**
523 * Something went wrong when decoding encoded data from the storage.
524 * Perhaps, there was a wrong key supplied for the type, or the data was improperly stored.
525 **/
468 UnableToDecodeRmrkData: AugmentedError<ApiType>;526 UnableToDecodeRmrkData: AugmentedError<ApiType>;
469 /**527 /**
470 * Generic error528 * Generic error
471 **/529 **/
472 [key: string]: AugmentedError<ApiType>;530 [key: string]: AugmentedError<ApiType>;
473 };531 };
474 rmrkEquip: {532 rmrkEquip: {
533 /**
534 * Base collection linked to this ID does not exist.
535 **/
475 BaseDoesntExist: AugmentedError<ApiType>;536 BaseDoesntExist: AugmentedError<ApiType>;
537 /**
538 * No Theme named "default" is associated with the Base.
539 **/
476 NeedsDefaultThemeFirst: AugmentedError<ApiType>;540 NeedsDefaultThemeFirst: AugmentedError<ApiType>;
541 /**
542 * Could not find an ID for a Base collection. It is likely there were too many collections created on the chain, causing an overflow.
543 **/
477 NoAvailableBaseId: AugmentedError<ApiType>;544 NoAvailableBaseId: AugmentedError<ApiType>;
545 /**
546 * Could not find a suitable ID for a Part, likely too many Part tokens were created in the Base, causing an overflow
547 **/
478 NoAvailablePartId: AugmentedError<ApiType>;548 NoAvailablePartId: AugmentedError<ApiType>;
549 /**
550 * Cannot assign equippables to a fixed Part.
551 **/
479 NoEquippableOnFixedPart: AugmentedError<ApiType>;552 NoEquippableOnFixedPart: AugmentedError<ApiType>;
553 /**
554 * Part linked to this ID does not exist.
555 **/
480 PartDoesntExist: AugmentedError<ApiType>;556 PartDoesntExist: AugmentedError<ApiType>;
557 /**
558 * No permission to perform action.
559 **/
481 PermissionError: AugmentedError<ApiType>;560 PermissionError: AugmentedError<ApiType>;
482 /**561 /**
483 * Generic error562 * Generic error
507 [key: string]: AugmentedError<ApiType>;586 [key: string]: AugmentedError<ApiType>;
508 };587 };
509 structure: {588 structure: {
510 /**589 /**
511 * While iterating over children, reached the breadth limit.590 * While nesting, reached the breadth limit of nesting, exceeding the provided budget.
512 **/591 **/
513 BreadthLimit: AugmentedError<ApiType>;592 BreadthLimit: AugmentedError<ApiType>;
514 /**593 /**
515 * While searching for the owner, reached the depth limit.594 * While nesting, reached the depth limit of nesting, exceeding the provided budget.
516 **/595 **/
517 DepthLimit: AugmentedError<ApiType>;596 DepthLimit: AugmentedError<ApiType>;
518 /**597 /**
519 * While searching for the owner, encountered an already checked account, detecting a loop.598 * While nesting, encountered an already checked account, detecting a loop.
520 **/599 **/
521 OuroborosDetected: AugmentedError<ApiType>;600 OuroborosDetected: AugmentedError<ApiType>;
522 /**601 /**
523 * Couldn't find the token owner that is itself a token.602 * Couldn't find the token owner that is itself a token.
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
492 [key: string]: QueryableStorageEntry<ApiType>;492 [key: string]: QueryableStorageEntry<ApiType>;
493 };493 };
494 rmrkCore: {494 rmrkCore: {
495 /**
496 * Latest yet-unused collection ID.
497 **/
495 collectionIndex: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;498 collectionIndex: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
499 /**
500 * Mapping from RMRK collection ID to Unique's.
501 **/
496 uniqueCollectionId: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;502 uniqueCollectionId: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
497 /**503 /**
498 * Generic query504 * Generic query
499 **/505 **/
500 [key: string]: QueryableStorageEntry<ApiType>;506 [key: string]: QueryableStorageEntry<ApiType>;
501 };507 };
502 rmrkEquip: {508 rmrkEquip: {
509 /**
510 * Checkmark that a Base has a Theme NFT named "default".
511 **/
503 baseHasDefaultTheme: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;512 baseHasDefaultTheme: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
513 /**
514 * Map of a Base ID and a Part ID to an NFT in the Base collection serving as the Part.
515 **/
504 inernalPartId: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;516 inernalPartId: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
505 /**517 /**
506 * Generic query518 * Generic query
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
347 [key: string]: SubmittableExtrinsicFunction<ApiType>;347 [key: string]: SubmittableExtrinsicFunction<ApiType>;
348 };348 };
349 rmrkCore: {349 rmrkCore: {
350 /**350 /**
351 * Accepts an NFT sent from another account to self or owned NFT351 * Accept an NFT sent from another account to self or an owned NFT.
352 * 352 *
353 * Parameters:353 * The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.
354 * - `origin`: sender of the transaction354 *
355 * # Permissions:
356 * - Token-owner-to-be
355 * - `rmrk_collection_id`: collection id of the nft to be accepted357 *
358 * # Arguments:
359 * - `rmrk_collection_id`: RMRK collection ID of the NFT to be accepted.
356 * - `rmrk_nft_id`: nft id of the nft to be accepted360 * - `rmrk_nft_id`: ID of the NFT to be accepted.
357 * - `new_owner`: either origin's account ID or origin-owned NFT, whichever the NFT was361 * - `new_owner`: Either the sender's account ID or a sender-owned NFT,
358 * sent to362 * whichever the accepted NFT was sent to.
359 **/363 **/
360 acceptNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;364 acceptNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;
361 /**365 /**
362 * accept the addition of a new resource to an existing NFT366 * Accept the addition of a newly created pending resource to an existing NFT.
363 **/367 *
368 * This transaction is needed when a resource is created and assigned to an NFT
369 * by a non-owner, i.e. the collection issuer, with one of the
370 * [`add_...` transactions](Pallet::add_basic_resource).
371 *
372 * # Permissions:
373 * - Token owner
374 *
375 * # Arguments:
376 * - `rmrk_collection_id`: RMRK collection ID of the NFT.
377 * - `rmrk_nft_id`: ID of the NFT with a pending resource to be accepted.
378 * - `resource_id`: ID of the newly created pending resource.
379 **/
364 acceptResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;380 acceptResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
365 /**381 /**
366 * accept the removal of a resource of an existing NFT382 * Accept the removal of a removal-pending resource from an NFT.
367 **/383 *
384 * This transaction is needed when a non-owner, i.e. the collection issuer,
385 * requests a [removal](`Pallet::remove_resource`) of a resource from an NFT.
386 *
387 * # Permissions:
388 * - Token owner
389 *
390 * # Arguments:
391 * - `rmrk_collection_id`: RMRK collection ID of the NFT.
392 * - `rmrk_nft_id`: ID of the NFT with a resource to be removed.
393 * - `resource_id`: ID of the removal-pending resource.
394 **/
368 acceptResourceRemoval: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;395 acceptResourceRemoval: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
369 /**396 /**
370 * Create basic resource397 * Create and set/propose a basic resource for an NFT.
371 **/398 *
399 * A basic resource is the simplest, lacking a Base and anything that comes with it.
400 * See RMRK docs for more information and examples.
401 *
402 * # Permissions:
403 * - Collection issuer - if not the token owner, adding the resource will warrant
404 * the owner's [acceptance](Pallet::accept_resource).
405 *
406 * # Arguments:
407 * - `rmrk_collection_id`: RMRK collection ID of the NFT.
408 * - `nft_id`: ID of the NFT to assign a resource to.
409 * - `resource`: Data of the resource to be created.
410 **/
372 addBasicResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceBasicResource | { src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceBasicResource]>;411 addBasicResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceBasicResource | { src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceBasicResource]>;
373 /**412 /**
374 * Create composable resource413 * Create and set/propose a composable resource for an NFT.
375 **/414 *
415 * A composable resource links to a Base and has a subset of its Parts it is composed of.
416 * See RMRK docs for more information and examples.
417 *
418 * # Permissions:
419 * - Collection issuer - if not the token owner, adding the resource will warrant
420 * the owner's [acceptance](Pallet::accept_resource).
421 *
422 * # Arguments:
423 * - `rmrk_collection_id`: RMRK collection ID of the NFT.
424 * - `nft_id`: ID of the NFT to assign a resource to.
425 * - `resource`: Data of the resource to be created.
426 **/
376 addComposableResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceComposableResource | { parts?: any; base?: any; src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceComposableResource]>;427 addComposableResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceComposableResource | { parts?: any; base?: any; src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceComposableResource]>;
377 /**428 /**
378 * Create slot resource429 * Create and set/propose a slot resource for an NFT.
379 **/430 *
431 * A slot resource links to a Base and a slot ID in it which it can fit into.
432 * See RMRK docs for more information and examples.
433 *
434 * # Permissions:
435 * - Collection issuer - if not the token owner, adding the resource will warrant
436 * the owner's [acceptance](Pallet::accept_resource).
437 *
438 * # Arguments:
439 * - `rmrk_collection_id`: RMRK collection ID of the NFT.
440 * - `nft_id`: ID of the NFT to assign a resource to.
441 * - `resource`: Data of the resource to be created.
442 **/
380 addSlotResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceSlotResource | { base?: any; src?: any; metadata?: any; slot?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceSlotResource]>;443 addSlotResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceSlotResource | { base?: any; src?: any; metadata?: any; slot?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceSlotResource]>;
381 /**444 /**
382 * burn nft445 * Burn an NFT, destroying it and its nested tokens up to the specified limit.
383 **/446 * If the burning budget is exceeded, the transaction is reverted.
447 *
448 * This is the way to burn a nested token as well.
449 *
450 * For more information, see [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively).
451 *
452 * # Permissions:
453 * * Token owner
454 *
455 * # Arguments:
456 * - `collection_id`: RMRK ID of the collection in which the NFT to burn belongs to.
457 * - `nft_id`: ID of the NFT to be destroyed.
458 * - `max_burns`: Maximum number of tokens to burn, assuming nesting. The transaction
459 * is reverted if there are more tokens to burn in the nesting tree than this number.
460 * This is primarily a mechanism of transaction weight control.
461 **/
384 burnNft: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, maxBurns: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;462 burnNft: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, maxBurns: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
385 /**463 /**
386 * Change the issuer of a collection464 * Change the issuer of a collection. Analogous to Unique's collection's [`owner`](up_data_structs::Collection).
387 * 465 *
388 * Parameters:466 * # Permissions:
389 * - `origin`: sender of the transaction467 * * Collection issuer
468 *
390 * - `collection_id`: collection id of the nft to change issuer of469 * # Arguments:
470 * - `collection_id`: RMRK collection ID to change the issuer of.
391 * - `new_issuer`: Collection's new issuer471 * - `new_issuer`: Collection's new issuer.
392 **/472 **/
393 changeCollectionIssuer: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newIssuer: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, MultiAddress]>;473 changeCollectionIssuer: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newIssuer: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, MultiAddress]>;
394 /**474 /**
395 * Create a collection475 * Create a new collection of NFTs.
396 **/476 *
477 * # Permissions:
478 * * Anyone - will be assigned as the issuer of the collection.
479 *
480 * # Arguments:
481 * - `metadata`: Metadata describing the collection, e.g. IPFS hash. Cannot be changed.
482 * - `max`: Optional maximum number of tokens.
483 * - `symbol`: UTF-8 string with token prefix, by which to represent the token in wallets and UIs.
484 * Analogous to Unique's [`token_prefix`](up_data_structs::Collection). Cannot be changed.
485 **/
397 createCollection: AugmentedSubmittable<(metadata: Bytes | string | Uint8Array, max: Option<u32> | null | object | string | Uint8Array, symbol: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Bytes, Option<u32>, Bytes]>;486 createCollection: AugmentedSubmittable<(metadata: Bytes | string | Uint8Array, max: Option<u32> | null | object | string | Uint8Array, symbol: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Bytes, Option<u32>, Bytes]>;
398 /**487 /**
399 * destroy collection488 * Destroy a collection.
400 **/489 *
490 * Only empty collections can be destroyed. If it has any tokens, they must be burned first.
491 *
492 * # Permissions:
493 * * Collection issuer
494 *
495 * # Arguments:
496 * - `collection_id`: RMRK ID of the collection to destroy.
497 **/
401 destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;498 destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
402 /**499 /**
403 * lock collection500 * "Lock" the collection and prevent new token creation. Cannot be undone.
404 **/501 *
502 * # Permissions:
503 * * Collection issuer
504 *
505 * # Arguments:
506 * - `collection_id`: RMRK ID of the collection to lock.
507 **/
405 lockCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;508 lockCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
406 /**509 /**
407 * Mints an NFT in the specified collection510 * Mint an NFT in a specified collection.
408 * Sets metadata and the royalty attribute511 *
409 * 512 * # Permissions:
410 * Parameters:513 * * Collection issuer
411 * - `collection_id`: The class of the asset to be minted.514 *
412 * - `nft_id`: The nft value of the asset to be minted.515 * # Arguments:
413 * - `recipient`: Receiver of the royalty516 * - `owner`: Owner account of the NFT. If set to None, defaults to the sender (collection issuer).
414 * - `royalty`: Permillage reward from each trade for the Recipient517 * - `collection_id`: RMRK collection ID for the NFT to be minted within. Cannot be changed.
415 * - `metadata`: Arbitrary data about an nft, e.g. IPFS hash518 * - `recipient`: Receiver account of the royalty. Has no effect if the `royalty_amount` is not set. Cannot be changed.
416 * - `transferable`: Ability to transfer this NFT519 * - `royalty_amount`: Optional permillage reward from each trade for the `recipient`. Cannot be changed.
417 **/520 * - `metadata`: Arbitrary data about an NFT, e.g. IPFS hash. Cannot be changed.
521 * - `transferable`: Can this NFT be transferred? Cannot be changed.
522 * - `resources`: Resource data to be added to the NFT immediately after minting.
523 **/
418 mintNft: AugmentedSubmittable<(owner: Option<AccountId32> | null | object | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, recipient: Option<AccountId32> | null | object | string | Uint8Array, royaltyAmount: Option<Permill> | null | object | string | Uint8Array, metadata: Bytes | string | Uint8Array, transferable: bool | boolean | Uint8Array, resources: Option<Vec<RmrkTraitsResourceResourceTypes>> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Option<AccountId32>, u32, Option<AccountId32>, Option<Permill>, Bytes, bool, Option<Vec<RmrkTraitsResourceResourceTypes>>]>;524 mintNft: AugmentedSubmittable<(owner: Option<AccountId32> | null | object | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, recipient: Option<AccountId32> | null | object | string | Uint8Array, royaltyAmount: Option<Permill> | null | object | string | Uint8Array, metadata: Bytes | string | Uint8Array, transferable: bool | boolean | Uint8Array, resources: Option<Vec<RmrkTraitsResourceResourceTypes>> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Option<AccountId32>, u32, Option<AccountId32>, Option<Permill>, Bytes, bool, Option<Vec<RmrkTraitsResourceResourceTypes>>]>;
419 /**525 /**
420 * Rejects an NFT sent from another account to self or owned NFT526 * Reject an NFT sent from another account to self or owned NFT.
421 * 527 * The NFT in question will not be sent back and burnt instead.
422 * Parameters:528 *
423 * - `origin`: sender of the transaction529 * The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.
424 * - `rmrk_collection_id`: collection id of the nft to be accepted530 *
425 * - `rmrk_nft_id`: nft id of the nft to be accepted531 * # Permissions:
426 **/532 * - Token-owner-to-be-not
533 *
534 * # Arguments:
535 * - `rmrk_collection_id`: RMRK ID of the NFT to be rejected.
536 * - `rmrk_nft_id`: ID of the NFT to be rejected.
537 **/
427 rejectNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;538 rejectNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
428 /**539 /**
429 * remove resource540 * Remove and erase a resource from an NFT.
430 **/541 *
542 * If the sender does not own the NFT, then it will be pending confirmation,
543 * and will have to be [accepted](Pallet::accept_resource_removal) by the token owner.
544 *
545 * # Permissions
546 * - Collection issuer
547 *
548 * # Arguments
549 * - `collection_id`: RMRK ID of a collection to which the NFT making use of the resource belongs to.
550 * - `nft_id`: ID of the NFT with a resource to be removed.
551 * - `resource_id`: ID of the resource to be removed.
552 **/
431 removeResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;553 removeResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
432 /**554 /**
433 * Transfers a NFT from an Account or NFT A to another Account or NFT B555 * Transfer an NFT from an account/NFT A to another account/NFT B.
434 * 556 * The token must be transferable. Nesting cannot occur deeper than the [`NESTING_BUDGET`].
435 * Parameters:557 *
436 * - `origin`: sender of the transaction558 * If the target owner is an NFT owned by another account, then the NFT will enter
437 * - `rmrk_collection_id`: collection id of the nft to be transferred559 * the pending state and will have to be accepted by the other account.
438 * - `rmrk_nft_id`: nft id of the nft to be transferred560 *
439 * - `new_owner`: new owner of the nft which can be either an account or a NFT561 * # Permissions:
440 **/562 * - Token owner
563 *
564 * # Arguments:
565 * - `collection_id`: RMRK ID of the collection of the NFT to be transferred.
566 * - `nft_id`: ID of the NFT to be transferred.
567 * - `new_owner`: New owner of the nft which can be either an account or a NFT.
568 **/
441 send: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;569 send: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;
442 /**570 /**
443 * set a different order of resource priority571 * Set a different order of resource priorities for an NFT. Priorities can be used,
444 **/572 * for example, for order of rendering.
573 *
574 * Note that the priorities are not updated automatically, and are an empty vector
575 * by default. There is no pre-set definition for the order to be particular,
576 * it can be interpreted arbitrarily use-case by use-case.
577 *
578 * # Permissions:
579 * - Token owner
580 *
581 * # Arguments:
582 * - `rmrk_collection_id`: RMRK collection ID of the NFT.
583 * - `rmrk_nft_id`: ID of the NFT to rearrange resource priorities for.
584 * - `priorities`: Ordered vector of resource IDs.
585 **/
445 setPriority: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, priorities: Vec<u32> | (u32 | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<u32>]>;586 setPriority: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, priorities: Vec<u32> | (u32 | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<u32>]>;
446 /**587 /**
447 * set a custom value on an NFT588 * Add or edit a custom user property, a key-value pair, describing the metadata
448 **/589 * of a token or a collection, on either one of these.
590 *
591 * Note that in this proxy implementation many details regarding RMRK are stored
592 * as scoped properties prefixed with "rmrk:", normally inaccessible
593 * to external transactions and RPCs.
594 *
595 * # Permissions:
596 * - Collection issuer - in case of collection property
597 * - Token owner - in case of NFT property
598 *
599 * # Arguments:
600 * - `rmrk_collection_id`: RMRK collection ID.
601 * - `maybe_nft_id`: Optional ID of the NFT. If left empty, then the property is set for the collection.
602 * - `key`: Key of the custom property to be referenced by.
603 * - `value`: Value of the custom property to be stored.
604 **/
449 setProperty: AugmentedSubmittable<(rmrkCollectionId: Compact<u32> | AnyNumber | Uint8Array, maybeNftId: Option<u32> | null | object | string | Uint8Array, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, Option<u32>, Bytes, Bytes]>;605 setProperty: AugmentedSubmittable<(rmrkCollectionId: Compact<u32> | AnyNumber | Uint8Array, maybeNftId: Option<u32> | null | object | string | Uint8Array, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, Option<u32>, Bytes, Bytes]>;
450 /**606 /**
451 * Generic tx607 * Generic tx
452 **/608 **/
453 [key: string]: SubmittableExtrinsicFunction<ApiType>;609 [key: string]: SubmittableExtrinsicFunction<ApiType>;
454 };610 };
455 rmrkEquip: {611 rmrkEquip: {
456 /**612 /**
457 * Creates a new Base.613 * Create a new Base.
458 * Modeled after [base interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/base.md)614 *
615 * Modeled after the [Base interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/base.md)
459 * 616 *
460 * Parameters:617 * # Permissions
461 * - origin: Caller, will be assigned as the issuer of the Base618 * - Anyone - will be assigned as the issuer of the Base.
462 * - base_type: media type, e.g. "svg"619 *
620 * # Arguments:
621 * - `base_type`: Arbitrary media type, e.g. "svg".
463 * - symbol: arbitrary client-chosen symbol622 * - `symbol`: Arbitrary client-chosen symbol.
464 * - parts: array of Fixed and Slot parts composing the base, confined in length by623 * - `parts`: Array of Fixed and Slot Parts composing the Base,
465 * RmrkPartsLimit624 * confined in length by [`RmrkPartsLimit`](up_data_structs::RmrkPartsLimit).
466 **/625 **/
467 createBase: AugmentedSubmittable<(baseType: Bytes | string | Uint8Array, symbol: Bytes | string | Uint8Array, parts: Vec<RmrkTraitsPartPartType> | (RmrkTraitsPartPartType | { FixedPart: any } | { SlotPart: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Bytes, Bytes, Vec<RmrkTraitsPartPartType>]>;626 createBase: AugmentedSubmittable<(baseType: Bytes | string | Uint8Array, symbol: Bytes | string | Uint8Array, parts: Vec<RmrkTraitsPartPartType> | (RmrkTraitsPartPartType | { FixedPart: any } | { SlotPart: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Bytes, Bytes, Vec<RmrkTraitsPartPartType>]>;
627 /**
628 * Update the array of Collections allowed to be equipped to a Base's specified Slot Part.
629 *
630 * Modeled after [equippable interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/equippable.md).
631 *
632 * # Permissions:
633 * - Base issuer
634 *
635 * # Arguments:
636 * - `base_id`: Base containing the Slot Part to be updated.
637 * - `part_id`: Slot Part whose Equippable List is being updated.
638 * - `equippables`: List of equippables that will override the current Equippables list.
639 **/
468 equippable: AugmentedSubmittable<(baseId: u32 | AnyNumber | Uint8Array, slotId: u32 | AnyNumber | Uint8Array, equippables: RmrkTraitsPartEquippableList | { All: any } | { Empty: any } | { Custom: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsPartEquippableList]>;640 equippable: AugmentedSubmittable<(baseId: u32 | AnyNumber | Uint8Array, slotId: u32 | AnyNumber | Uint8Array, equippables: RmrkTraitsPartEquippableList | { All: any } | { Empty: any } | { Custom: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsPartEquippableList]>;
469 /**641 /**
470 * Adds a Theme to a Base.642 * Add a Theme to a Base.
471 * Modeled after [themeadd interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/themeadd.md)643 * A Theme named "default" is required prior to adding other Themes.
644 *
645 * Modeled after [Themeadd interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/themeadd.md).
472 * Themes are stored in the Themes storage646 *
473 * A Theme named "default" is required prior to adding other Themes.647 * # Permissions:
474 * 648 * - Base issuer
475 * Parameters:649 *
476 * - origin: The caller of the function, must be issuer of the base650 * # Arguments:
477 * - base_id: The Base containing the Theme to be updated651 * - `base_id`: Base ID containing the Theme to be updated.
478 * - theme: The Theme to add to the Base. A Theme has a name and properties, which are an652 * - `theme`: Theme to add to the Base. A Theme has a name and properties, which are an
479 * array of [key, value, inherit].653 * array of [key, value, inherit].
480 * - key: arbitrary BoundedString, defined by client654 * - `key`: Arbitrary BoundedString, defined by client.
481 * - value: arbitrary BoundedString, defined by client655 * - `value`: Arbitrary BoundedString, defined by client.
482 * - inherit: optional bool656 * - `inherit`: Optional bool.
483 **/657 **/
484 themeAdd: AugmentedSubmittable<(baseId: u32 | AnyNumber | Uint8Array, theme: RmrkTraitsTheme | { name?: any; properties?: any; inherit?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, RmrkTraitsTheme]>;658 themeAdd: AugmentedSubmittable<(baseId: u32 | AnyNumber | Uint8Array, theme: RmrkTraitsTheme | { name?: any; properties?: any; inherit?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, RmrkTraitsTheme]>;
485 /**659 /**
486 * Generic tx660 * Generic tx
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
1314/** @name PalletRmrkCoreError */1314/** @name PalletRmrkCoreError */
1315export interface PalletRmrkCoreError extends Enum {1315export interface PalletRmrkCoreError extends Enum {
1316 readonly isCorruptedCollectionType: boolean;1316 readonly isCorruptedCollectionType: boolean;
1317 readonly isNftTypeEncodeError: boolean;
1318 readonly isRmrkPropertyKeyIsTooLong: boolean;1317 readonly isRmrkPropertyKeyIsTooLong: boolean;
1319 readonly isRmrkPropertyValueIsTooLong: boolean;1318 readonly isRmrkPropertyValueIsTooLong: boolean;
1320 readonly isRmrkPropertyIsNotFound: boolean;1319 readonly isRmrkPropertyIsNotFound: boolean;
1333 readonly isCannotRejectNonPendingNft: boolean;1332 readonly isCannotRejectNonPendingNft: boolean;
1334 readonly isResourceNotPending: boolean;1333 readonly isResourceNotPending: boolean;
1335 readonly isNoAvailableResourceId: boolean;1334 readonly isNoAvailableResourceId: boolean;
1336 readonly type: 'CorruptedCollectionType' | 'NftTypeEncodeError' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';1335 readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
1337}1336}
13381337
1339/** @name PalletRmrkCoreEvent */1338/** @name PalletRmrkCoreEvent */
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
2990 * Lookup400: pallet_rmrk_core::pallet::Error<T>2990 * Lookup400: pallet_rmrk_core::pallet::Error<T>
2991 **/2991 **/
2992 PalletRmrkCoreError: {2992 PalletRmrkCoreError: {
2993 _enum: ['CorruptedCollectionType', 'NftTypeEncodeError', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']2993 _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']
2994 },2994 },
2995 /**2995 /**
2996 * Lookup402: pallet_rmrk_equip::pallet::Error<T>2996 * Lookup402: pallet_rmrk_equip::pallet::Error<T>
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
3144 /** @name PalletRmrkCoreError (400) */3144 /** @name PalletRmrkCoreError (400) */
3145 export interface PalletRmrkCoreError extends Enum {3145 export interface PalletRmrkCoreError extends Enum {
3146 readonly isCorruptedCollectionType: boolean;3146 readonly isCorruptedCollectionType: boolean;
3147 readonly isNftTypeEncodeError: boolean;
3148 readonly isRmrkPropertyKeyIsTooLong: boolean;3147 readonly isRmrkPropertyKeyIsTooLong: boolean;
3149 readonly isRmrkPropertyValueIsTooLong: boolean;3148 readonly isRmrkPropertyValueIsTooLong: boolean;
3150 readonly isRmrkPropertyIsNotFound: boolean;3149 readonly isRmrkPropertyIsNotFound: boolean;
3163 readonly isCannotRejectNonPendingNft: boolean;3162 readonly isCannotRejectNonPendingNft: boolean;
3164 readonly isResourceNotPending: boolean;3163 readonly isResourceNotPending: boolean;
3165 readonly isNoAvailableResourceId: boolean;3164 readonly isNoAvailableResourceId: boolean;
3166 readonly type: 'CorruptedCollectionType' | 'NftTypeEncodeError' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';3165 readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
3167 }3166 }
31683167
3169 /** @name PalletRmrkEquipError (402) */3168 /** @name PalletRmrkEquipError (402) */