git.delta.rocks / unique-network / refs/commits / 87253dd2aec5

difftreelog

refunfible transfer

str-mv2020-08-04parent: #49a2388.patch.diff
in: master

1 file changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
42 Invalid,42 Invalid,
43 // custom data size43 // custom data size
44 NFT(u32),44 NFT(u32),
45 // amount45 // decimal points
46 Fungible(u32),46 Fungible(u32),
47 // custom data size
47 ReFungible,48 ReFungible(u32),
48}49}
4950
50impl Into<u8> for CollectionMode {51impl Into<u8> for CollectionMode {
53 CollectionMode::Invalid => 0,54 CollectionMode::Invalid => 0,
54 CollectionMode::NFT(_) => 1,55 CollectionMode::NFT(_) => 1,
55 CollectionMode::Fungible(_) => 2,56 CollectionMode::Fungible(_) => 2,
56 CollectionMode::ReFungible => 3,57 CollectionMode::ReFungible(_) => 3,
57 }58 }
58 }59 }
59}60}
110#[cfg_attr(feature = "std", derive(Debug))]111#[cfg_attr(feature = "std", derive(Debug))]
111pub struct FungibleItemType<AccountId> {112pub struct FungibleItemType<AccountId> {
112 pub collection: u64,113 pub collection: u64,
113 pub owner: Vec<AccountId>,114 pub owner: AccountId,
114 pub data: Vec<u64>,115 pub value: u128,
115}116}
116117
117#[derive(Encode, Decode, Default, Clone, PartialEq)]118#[derive(Encode, Decode, Default, Clone, PartialEq)]
118#[cfg_attr(feature = "std", derive(Debug))]119#[cfg_attr(feature = "std", derive(Debug))]
119pub struct ReFungibleItemType<AccountId> {120pub struct ReFungibleItemType<AccountId> {
120 pub collection: u64,121 pub collection: u64,
121 pub owner: Vec<Ownership<AccountId>>,122 pub owner: Vec<Ownership<AccountId>>,
123 pub data: Vec<u8>,
122}124}
123125
124pub trait Trait: system::Trait {126pub trait Trait: system::Trait {
181 let who = ensure_signed(origin)?;183 let who = ensure_signed(origin)?;
182 let custom_data_size = match mode {184 let custom_data_size = match mode {
183 CollectionMode::NFT(size) => size,185 CollectionMode::NFT(size) => size,
186 CollectionMode::ReFungible(size) => size,
184 _ => 0187 _ => 0
185 };188 };
186189
190 };193 };
191194
192 // check params195 // check params
193 ensure!(decimal_points < 100, "decimal_points parameter must be lower than 100"); 196 ensure!(decimal_points <= 4, "decimal_points parameter must be lower than 4");
194197
195 let mut name = collection_name.to_vec();198 let mut name = collection_name.to_vec();
196 name.push(0);199 name.push(0);
357360
358 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;361 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
359362
360 let new_balance = <Balance<T>>::get(collection_id, owner.clone()) + 1;363 let new_balance = <Balance<T>>::get(collection_id, owner.clone()).checked_add(1).unwrap();
361 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);364 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);
362365
363 // TODO: implement other modes366 // TODO: implement other modes
374 Self::add_nft_item(item)?;377 Self::add_nft_item(item)?;
375 378
376 },379 },
380 CollectionMode::ReFungible(_) => {
381 let mut owner_list = Vec::new();
382 let value = (10 as u128).pow(target_collection.decimal_points);
383 owner_list.push(Ownership {owner: owner, fraction: value});
384
385 let item = ReFungibleItemType {
386 collection: collection_id,
387 owner: owner_list,
388 data: properties
389 };
390
391 Self::add_refungible_item(item)?;
392 },
377 _ => ()393 _ => ()
378 };394 };
379395
392 {408 {
393 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;409 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
394 }410 }
395 411 let target_collection = <Collection<T>>::get(collection_id);
412
413 match target_collection.mode
414 {
396 Self::burn_nft_item(collection_id, item_id)?;415 CollectionMode::NFT(_) => Self::burn_nft_item(collection_id, item_id)?,
416 CollectionMode::ReFungible(_) => Self::burn_refungible_item(collection_id, item_id, sender.clone())?,
417 _ => ()
418 };
397419
398 // call event420 // call event
399 Self::deposit_event(RawEvent::ItemDestroyed(collection_id, item_id));421 Self::deposit_event(RawEvent::ItemDestroyed(collection_id, item_id));
417 match target_collection.mode 439 match target_collection.mode
418 {440 {
419 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, recipient)?,441 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, recipient)?,
442 CollectionMode::ReFungible(_) => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?,
420 _ => ()443 _ => ()
421 };444 };
422445
556579
557 match target_collection.mode {580 match target_collection.mode {
558 CollectionMode::NFT(_) => <NftItemList<T>>::get(collection_id, item_id).owner == subject,581 CollectionMode::NFT(_) => <NftItemList<T>>::get(collection_id, item_id).owner == subject,
559 CollectionMode::Fungible(_) => <FungibleItemList<T>>::get(collection_id, item_id).owner.contains(&subject),582 CollectionMode::Fungible(_) => <FungibleItemList<T>>::get(collection_id, item_id).owner == subject,
560 CollectionMode::ReFungible => <ReFungibleItemList<T>>::get(collection_id, item_id).owner.iter().any(|i| i.owner == subject),583 CollectionMode::ReFungible(_) => <ReFungibleItemList<T>>::get(collection_id, item_id).owner.iter().any(|i| i.owner == subject),
561 CollectionMode::Invalid => false584 CollectionMode::Invalid => false
562 }585 }
563 }586 }
564587
588 fn add_refungible_item(item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
589
590 let current_index = <ItemListIndex>::get(item.collection)
591 .checked_add(1)
592 .expect("Item list index id error");
593
594 Self::add_token_index(item.collection, current_index, item.owner.first().unwrap().owner.clone())?;
595
596 <ItemListIndex>::insert(item.collection, current_index);
597 <ReFungibleItemList<T>>::insert(item.collection, current_index, item);
598
599 Ok(())
600 }
601
602 fn burn_refungible_item(collection_id: u64, item_id: u64, owner: T::AccountId) -> DispatchResult {
603
604 let collection = <ReFungibleItemList<T>>::get(collection_id, item_id);
605 let item = collection.owner.iter().filter(|&i| i.owner == owner).next().unwrap();
606 Self::remove_token_index(collection_id, item_id, owner)?;
607
608 // update balance
609 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(item.fraction as u64).unwrap();
610 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
611
612 // TODO
613 <ReFungibleItemList<T>>::remove(collection_id, item_id);
614
615 Ok(())
616 }
617
618 fn transfer_refungible(collection_id: u64, item_id: u64, value: u64, owner: T::AccountId, new_owner: T::AccountId) -> DispatchResult {
619
620 let full_item = <ReFungibleItemList<T>>::get(collection_id, item_id);
621 let item = full_item.owner.iter().filter(|i| i.owner == owner).next().unwrap();
622 let amount = item.fraction;
623
624 ensure!(amount < value.into(),"Item balance not enouth");
625
626 // update balance
627 let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(value).unwrap();
628 <Balance<T>>::insert(collection_id, item.owner.clone(), balance_old_owner);
629
630 let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone()).checked_add(value).unwrap();
631 <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
632
633 let old_owner = item.owner.clone();
634 let new_owner_has_account = full_item.owner.iter().any(|i| i.owner == new_owner);
635
636 // transfer
637 if amount == value.into() && !new_owner_has_account
638 {
639 // change owner
640 // new owner do not have account
641 let mut new_full_item = full_item.clone();
642 new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().owner = new_owner.clone();
643 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
644
645 // update index collection
646 Self::move_token_index(collection_id, item_id, old_owner.clone(), new_owner.clone())?;
647 }
648 else
649 {
650 let mut new_full_item = full_item.clone();
651 new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().fraction -= amount;
652
653 // separate amount
654 if new_owner_has_account {
655 // new owner has account
656 new_full_item.owner.iter_mut().find(|i| i.owner == new_owner).unwrap().fraction += amount;
657 }
658 else
659 {
660 // new owner do not have account
661 new_full_item.owner.push(Ownership { owner: new_owner.clone(), fraction: amount});
662 Self::add_token_index(collection_id, item_id, new_owner.clone())?;
663 }
664
665 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
666 }
667
668 Ok(())
669 }
670
565 fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {671 fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
566672