• 【Substrate Collectables教程】【第2章Kitties】4 拥有多个 Kitties


    拥有多个 Kitties

    4.1 使用 Tuples 去模拟高阶数组

    我们需要引入一些更复杂的存储项来表示多个用户对多个项目的所有权。

    幸运的是,根据我们的需求,使用一个由 AccountId 和 Index 组成的 tuple 几乎就可以解决我们的问题了。

    以下是我们如何使用这样的结构构造每个人独有的 "friends list":

    MyFriendsArray get(my_friends_array): map (T::AccountId, u32) => T::AccountId;
    MyFriendsCount get(my_friends_count): map T::AccountId => u32;
    

    这模拟了一个标准的二维数组,如:

    MyFriendsArray[AccountId][Index] -> AccountId

    我们也可以获取用户的朋友数量:

    MyFriendsArray[AccountId].length()

     4.2 相对索引

    与以前一样,我们可以通过索引项目的位置来优化 runtime 需要执行的计算工作。一般的方法是反转 MyFriendsArray 的映射,并创建一个这样的存储项:

    MyFriendsIndex: map (T::AccountId, T::AccountId) => u32;

    如果 AccountId 代表用户和他们的朋友, 那么返回值将是 MyFriendsArray 的索引,即该朋友在该用户的朋友列表中的存储位置。

    但是,由于我们的 kitty 都具有唯一标识符作为 Hash,并且不能被多个用户所拥有,所以我们实际上可以简化此结构

    MyKittiesIndex: map T::Hash => u32;

    这个索引告诉了我们对于一个给定的 kitty,可以在哪里查看该项的 所有者 数组。

    4.3 示例

    use support::{decl_storage, decl_module, StorageValue, StorageMap,
        dispatch::Result, ensure, decl_event};
    use system::ensure_signed;
    use runtime_primitives::traits::{As, Hash};
    use parity_codec::{Encode, Decode};
    
    #[derive(Encode, Decode, Default, Clone, PartialEq)]
    #[cfg_attr(feature = "std", derive(Debug))]
    pub struct Kitty<Hash, Balance> {
        id: Hash,
        dna: Hash,
        price: Balance,
        gen: u64,
    }
    
    pub trait Trait: balances::Trait {
        type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
    }
    
    decl_event!(
        pub enum Event<T>
        where
            <T as system::Trait>::AccountId,
            <T as system::Trait>::Hash
        {
            Created(AccountId, Hash),
        }
    );
    
    decl_storage! {
        trait Store for Module<T: Trait> as KittyStorage {
            Kitties get(kitty): map T::Hash => Kitty<T::Hash, T::Balance>;
            KittyOwner get(owner_of): map T::Hash => Option<T::AccountId>;
    
            AllKittiesArray get(kitty_by_index): map u64 => T::Hash;
            AllKittiesCount get(all_kitties_count): u64;
            AllKittiesIndex: map T::Hash => u64;
    
            OwnedKittiesArray get(kitty_of_owner_by_index): map (T::AccountId, u64) => T::Hash;
            OwnedKittiesCount get(owned_kitty_count): map T::AccountId => u64;
            OwnedKittiesIndex: map T::Hash => u64;
            
            Nonce: u64;
        }
    }
    
    decl_module! {
        pub struct Module<T: Trait> for enum Call where origin: T::Origin {
    
            fn deposit_event<T>() = default;
    
            fn create_kitty(origin) -> Result {
                let sender = ensure_signed(origin)?;
    
                let owned_kitty_count = Self::owned_kitty_count(&sender);
    
                let new_owned_kitty_count = owned_kitty_count.checked_add(1)
                    .ok_or("Overflow adding a new kitty to account balance")?;
    
                let all_kitties_count = Self::all_kitties_count();
    
                let new_all_kitties_count = all_kitties_count.checked_add(1)
                    .ok_or("Overflow adding a new kitty to total supply")?;
    
                let nonce = <Nonce<T>>::get();
                let random_hash = (<system::Module<T>>::random_seed(), &sender, nonce)
                    .using_encoded(<T as system::Trait>::Hashing::hash);
    
                ensure!(!<KittyOwner<T>>::exists(random_hash), "Kitty already exists");
    
                let new_kitty = Kitty {
                    id: random_hash,
                    dna: random_hash,
                    price: <T::Balance as As<u64>>::sa(0),
                    gen: 0,
                };
    
                <Kitties<T>>::insert(random_hash, new_kitty);
                <KittyOwner<T>>::insert(random_hash, &sender);
    
                <AllKittiesArray<T>>::insert(all_kitties_count, random_hash);
                <AllKittiesCount<T>>::put(new_all_kitties_count);
                <AllKittiesIndex<T>>::insert(random_hash, all_kitties_count);
    
                <OwnedKittiesArray<T>>::insert((sender.clone(), owned_kitty_count), random_hash);
                <OwnedKittiesCount<T>>::insert(&sender, new_owned_kitty_count);
                <OwnedKittiesIndex<T>>::insert(random_hash, owned_kitty_count);
                
                <Nonce<T>>::mutate(|n| *n += 1);
    
                Self::deposit_event(RawEvent::Created(sender, random_hash));
    
                Ok(())
            }
        }
    }
  • 相关阅读:
    P1194 买礼物(建模)
    024 Android 对话框(AlertDialog)的应用(与Android黑马培训班的024相对照学习)
    023 Android 滚动视图(ScollView)
    022 Android 开源项目使用指南
    021 Android 日历视图(Calendarview)
    020 ProgressBar(进度条)、SeekBar(拖动条)与星级评分条(RatingBar)
    019 Android 程序调试技巧汇总
    018 Android 单选按钮(RadioButton)和复选框(CheckBox)的使用
    017 Android ToggleButton(开关函数)与switch (开关按钮)
    016 Android Toast语句应用
  • 原文地址:https://www.cnblogs.com/xiangshigang/p/16268443.html
Copyright © 2020-2023  润新知