-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: battlepass #120
feat: battlepass #120
Conversation
battlepass/src/lib.rs
Outdated
#[pallet::getter(fn get_battlepass)] | ||
pub(super) type Battlepasses<T: Config> = StorageMap<_, Blake2_128Concat, T::Hash, Battlepass<T::Hash, T::AccountId, T::BlockNumber, String<T>>, OptionQuery>; | ||
|
||
/// Number of battlepasses per organization. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it the number of claimed passes ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's the total number of created battlepasses per org.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so created not claimed? what is the difference? i think the pass is minted
when you claim, so claimed==created
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean what @vayesy wrote? or do you reference something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, yes, I meant @vayesy.
#[pallet::call] | ||
impl<T: Config> Pallet<T> { | ||
#[pallet::weight(0)] | ||
pub fn create_battlepass( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you put the transactional part into the extrinsic fn, you may need to double the code unneccessarily as we need a way to add a battlepass via oracle, therefore who, pass, account
where who is permitted oracle and account is the user to add. also we need to store respective discord id somewhere otherwise we cannot map it,.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is slight confusion in terminology.
We name two entities the same way: a)
general entity, which is created by organization and represents event to participate for the users; b)
entity, which users purchase to gain access to participate in the event.
Particularly this extrinsic is used to create a)
entity type. So we don't need to store discord id here and extend functionality for the oracle. Those will be applied for working with b)
entity type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
battlepass is the general seasonal wrapper for achievements which result in scores and which unlock claiming rewards. i have written a doc for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add the proper names for those entities and structs and show where they are stored? @vayesy
battlepass/src/types.rs
Outdated
pub org_id: Hash, | ||
pub name: BoundedString, | ||
pub cid: BoundedString, | ||
pub state: BattlepassState, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually, we have separate storage for the state (ex. MemberStates
, OrgStates
). I'm not sure what ActiveBattlepassByOrg
is, but storing the state in the struct and storing it in the separate storage is suboptimal since you need to update both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will create storage for states, like battlepass_id -> BattlepassState
ActiveBattlepassByOrg - is to check which is a currently active battlepass for the Org (org_id -> active battlepass_id
). So the Active state will be stored in two places, but it will bring more benefits in terms of storage and usability, I suppose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can query the active battlepass either via the graph as a client or by filtering for active pass as a first class citizen (the pallet), what is the usecase for the pallet? it would only operate per id on a specific battlepass and reject if the operation is not allowed, e.g. not active, not owner
e.g. org
-> vec<battlepass>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example of use case: upon creation of new Battlepass for the Org, we need to check if there is an Active Battlepass (current season) already. Org may have multiple Battlepasses, but only one can be Active. So having a mapping org
-> active battlepass
is more convenient and faster than working with vec.
ensure!(T::Control::is_org_active(&org_id), Error::<T>::OrgUnknown); | ||
// check if user is a member of organization | ||
ensure!(T::Control::is_org_member_active(&org_id, &claimer), Error::<T>::NotMember); | ||
// check if Org has active battlepass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you look to the two checks above maybe we should introduce the same for battlepass, like T::Battlepass::is_battlepass_active
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we need to get the active battlepass, not just check if it's active.
pub enum BattlepassState { | ||
Draft = 0, | ||
Active = 1, | ||
Closed = 2, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Closed
=> Ended
|| 'Inactive' ?
also need Locked
I also tend to capitalize state, like DRAFT
ACTIVE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe Closed
-> Finished
? And the extrinsic accordingly finish_battlepass
?
Why do we need Locked
? @2075
None, // royalty_amount | ||
BoundedVec::truncate_from(b"NFT meta".to_vec()), // metadata TODO: what should be here? | ||
false, // transferable | ||
None // resources |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like these inline comments.
Here are some standards for documentation of the Rust project.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't find any info about inline comments in the standards.
Did you mean it's better to describe struct fields on the top of the struct? Like:
/// Battlepass struct
///
/// `collection_id`: Collection that will store all claimed Battlepass-NFTs
pub struct Battlepass...
|
||
#[derive(Encode, Decode, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen)] | ||
pub struct BattlepassNft { | ||
pub collection_id: u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I don't know the details here, but there should be a collection identifier in the rmrk NFT object. For me, this struct looks redundant, but feel free to ignore my comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, should be stored maybe in battlepass metadata as hash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
Added battlepass_id (hash) to metadata field of minted NFT.
Storage ClaimedBattlepasses: (AccountId, BattlepassId) -> NftId
will be used to quickly validate if Battlepass NFT was claimed by user.
#[pallet::generate_deposit(pub(super) fn deposit_event)] | ||
pub enum Event<T: Config> { | ||
/// New BattlePass created | ||
BattlepassCreated { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest using "Created", "Claimed", "Closed" instead. Like we have for Flow. Since the subject is always the same - Battlepass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// ActiveBattlepassByOrg: map Hash => Hash | ||
#[pallet::storage] | ||
#[pallet::getter(fn get_active_battlepass)] | ||
pub type ActiveBattlepassByOrg<T: Config> = StorageMap<_, Blake2_128Concat, T::Hash, T::Hash, OptionQuery>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is only one usage of this storage and it's avoiding duplicates. And it's possible to achieve this with the existing Battlepass
storage if you do the next steps:
- remove
created
andupdated
from theBattlepass
struct, since indexer nows this information it's redundant here - this way you'll have a unique hash of the Battlepass without any variables like BlockNumber
- check if Battlepass doesn't contain a hash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. But in this case, we need to keep in mind to recreate all Battlepasses if something changed in Battlepass struct.
And with this approach, we can only check if the same Battlepass exists, but we need to check if there is an active
battlepass.
/// | ||
/// BattlepassStates: map Hash => BattlepassState | ||
#[pallet::storage] | ||
#[pallet::getter(fn get_battlepass_state)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided not to use getters. But maybe it's not actual anymore. WDYT? @vayesy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thumbs up mean not use getters
(why not then?) or not actual anymore
? :)
#[pallet::weight(0)] | ||
pub fn close_battlepass( | ||
origin: OriginFor<T>, | ||
org_id: T::Hash, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use org_id
here instead of battlepass_id
.
pub fn claim_battlepass( | ||
origin: OriginFor<T>, | ||
org_id: T::Hash, | ||
) -> DispatchResult { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use org_id
here instead of battlepass_id
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would work though
- claim the active battlepass for an org would require this
- or param is optional org or battlepass id
- agree it is cleaner to use battlepass id
ensure!(T::Control::is_org_member_active(&org_id, &claimer), Error::<T>::NotMember); | ||
// check if Org has active battlepass | ||
let battlepass_id = Self::get_active_battlepass(org_id).ok_or(Error::<T>::BattlepassUnknown)?; | ||
// check if Battlepass already claimed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you'd use battlepass_id
as an extrinsic param, you can remove this line.
would recommend to use |
* Remove unused migration. (#111) * Remove unused migration. * Remove empty migration.rs files * Fix tests. * Add M2 review comments * USE ORML dependencies from github instead of local version * fix: rm warnings * M2 review fixes (#115) * feat: update member state (#119) * feat: update orml references to git * feat: add update member ext * feat: update missing member state * feat: update event, api * Updated extrinsic. Added benchmarks Co-authored-by: vasylenko-yevhen <[email protected]> * feat: battlepass (#120) * Create Battlepass pallete * docs: add readme * Update extrinsics. * Add RMRK integration, mint Battlepass NFTs. Co-authored-by: 2075 <[email protected]> * Allow users to join to prime type org (#121) * Create Battlepass pallete * Add Battlepass activation, refactor. * Update lib.rs (#123) * add levels and rewards to battlepass. (#124) * Unit tests for Battlepass (#125) * Add wallet for battlepass Bot * feat: change root_or_governance for approval * feat: benchmarks for battlepass * feat: bump substrate version from 0.9.28 to 0.9.36 * Add extrinsic descriptions for Battlepass. * feat: Update Battlepass and Reward (#130) * feat:tests for update_battlepass and update_reward * feat: new benchmarks for battlepass. * feat: extend bot privileges * feat: claim battlepass by bot * feat: add, remove levels by bot * update benchmarks * feat: use unique NFT IDs * feat: remove ability to claim battlepass for self * allows non org members to participate in battlepass * finish tests, update weights * allows root account to add bot account to the battlepass * Correctly validate `add_bot` caller * fix: update_battlepass should update any number of fields * Remove RMRK * fix: should create battlepass if there is active one * feat: add option for name and cid (#142) * feat: add option for name and cid * feat: update tests * feat: add mock, update test * feat: fix types * feat: rm unused * feat: update readme, benchmarking * Fix type --------- Co-authored-by: vasylenko-yevhen <[email protected]> * feat: bump substrate version from 0.9.36 to 0.9.38 (#141) * feat: bump substrate version from 0.9.36 to 0.9.38 * bump protocol to 1.3.0 * use CID as collection metadata * Revert "feat: bump substrate version from 0.9.36 to 0.9.38 (#141)" (#144) This reverts commit d084aca. * Update substrate v36 to v38 (#145) * feat: bump substrate version from 0.9.36 to 0.9.38 * bump protocol to 1.3.0 * use CID as collection metadata --------- Co-authored-by: FiberMan <[email protected]> * fix: update_reward should update any number of fields (#146) * feat: allow bot to update the battlepass * feat: use provided CID as a metadata for NFT. * address comments from SBP3 review * Substrate upgrade 0.9.38 to 0.9.39 * Substrate upgrade 0.9.39 to 0.9.40 * remove deprecated macros * replace pallet_uniques with pallet_nfts (#152) * fix(battlepass): update permissions (#153) --------- Co-authored-by: Yura <[email protected]> Co-authored-by: Daniel Bigos <[email protected]> Co-authored-by: vasylenko-yevhen <[email protected]> Co-authored-by: 2075 <[email protected]>
No description provided.