4

I am working on creating a custom map which takes T::AccountId as a perimeter:

#[pallet::storage]
#[pallet::getter(fn declaration_map)]
pub(super) type Declarations<T: Config> = StorageMap
<
_,
Blake2_128Concat,
T::AccountId,
Amendment<T::AccountId>,
OptionQuery
>;

I pass it as an OptionQuery since AccountId does not have a default value implemented and therefore could be None value. However in my calls: (Example)

#[pallet::weight(100_000)]
pub fn add_amendment(origin: OriginFor<T>, statement: Vec<u8>, owners: Vec<T::AccountId>) -> DispatchResult {
    use crate::pallet::Event::AmendmentAdded;
    ensure_root(origin)?;
    let amendment = Amendment {
                  statement: statement.clone(), 
                  owners: owners
                };
    let next_id = Self::next_amendment();
    Declarations::<T>::insert(next_id, amendment);
    Self::deposit_event(AmendmentAdded(next_id.unwrap(), statement));
    NextAmendmentID::<T>::put(&next_id.unwrap() + 1);
    Ok(())
}

When I get a value from the map there is a potential that the value will be None and can not be used as a key. The simplest way to fix this in my mind is to implement a default value to AccountId. My question is how do I implement that? There is an this article: Why is there no `Default` implementation for `T::AccountId`? The OP however doesn't go into detail about how they implemented a default value. If anyone has any insight on this it would be very helpful.

1
  • Sounds like you should return an error if the value is none instead of trying to implement default. In the case there is no account id, probably your logic is invalid, and should not be executed. Otherwise, please improve your code samples to be something which is complete, and can be edited to be correct. As is, you are leaving so many questions about other types and storage.
    – Shawn Tabrizi
    Commented Jun 16, 2022 at 23:43

1 Answer 1

0

The rule in the Rust programming language is:

If you implement trait U for type T, either T or U must live in your crate. In this case, neither do, so you cannot do that.

The standard fix for this, called the "newtype patter" is to create a new type that is a mere wrapper around T and therefore the above statement then holds.

struct MyAccountId(AccountId);

impl Default for MyAccountId { .. }

// this will allow you to use `MyAccountId` and `AccountId` often interchange-ably. 
impl Deref for MyAccountId {
  type Target = AccountId
} 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.