Skip to content
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

Builders - adding a custom made module #26

Merged
merged 25 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9cd7a2f
add article
augustocollado Sep 4, 2023
3fb2324
Add calls snippet
augustocollado Sep 4, 2023
e7ff6a1
Add cargo toml snippet
augustocollado Sep 4, 2023
a837a5e
add index.md
augustocollado Sep 4, 2023
5918387
Added all the files and navegability
augustocollado Sep 5, 2023
962fa25
fix newline
augustocollado Sep 5, 2023
15128f0
Apply suggestions from code review
augustocollado Sep 5, 2023
2ef9648
guard for not production ready code as snippet
augustocollado Sep 6, 2023
9231fb0
Merge branch 'main' into augustocollado/adding-custom-made-module
augustocollado Sep 6, 2023
d1d5c42
prerequisites section
augustocollado Sep 6, 2023
ccf85fb
connector between sections
augustocollado Sep 6, 2023
e393e18
deleted unused traits for currency
augustocollado Sep 6, 2023
be2e9c9
clarifying randomness
augustocollado Sep 6, 2023
b9d91df
calls reordering
augustocollado Sep 6, 2023
164ffec
errors intro line
augustocollado Sep 6, 2023
f7aa79b
Storage suggestion
augustocollado Sep 6, 2023
55c7a42
evm template option
augustocollado Sep 6, 2023
d642305
Apply suggestions from code review
augustocollado Sep 6, 2023
6c22b23
Changed numbered list and other observations
augustocollado Sep 6, 2023
a35f6da
Merge branch 'main' into augustocollado/adding-custom-made-module
augustocollado Sep 6, 2023
e694500
added link to tanssi repo
augustocollado Sep 8, 2023
849c451
Apply suggestions from code review
augustocollado Sep 8, 2023
d496f37
code snippet for repeated text
augustocollado Sep 8, 2023
921c86e
Actualizar adding-custom-made-module.md
augustocollado Sep 8, 2023
63e583f
merge
albertov19 Sep 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .snippets/code/basic-substrate/lottery-example-calls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#[pallet::call]
impl<T: Config> Pallet<T> {

#[pallet::call_index(0)]
#[pallet::weight(0)]
pub fn buy_ticket(origin: OriginFor<T>) -> DispatchResult {

// 1. Validates the origin signature
let buyer = ensure_signed(origin)?;

// 2. Checks that the user has enough balance to afford the ticket price
ensure!(
T::Currency::free_balance(&buyer) >= T::TicketCost::get(),
Error::<T>::NotEnoughCurrency
);

// 3. Checks that the user is not already participating
if let Some(participants) = Self::get_participants() {
ensure!(
!participants.contains(&buyer),
Error::<T>::AccountAlreadyParticipating
);
}

// 4. Adds the user as a new participant for the prize
match Self::get_participants() {
Some(mut participants) => {
ensure!(
participants.try_push(buyer.clone()).is_ok(),
Error::<T>::CanNotAddParticipant
);
Participants::<T>::set(Some(participants));
},
None => {
let mut participants = BoundedVec::new();
ensure!(
participants.try_push(buyer.clone()).is_ok(),
Error::<T>::CanNotAddParticipant
);
Participants::<T>::set(Some(participants));
}
};

// 5. Transfers the ticket cost to the module's account
// to be hold until transferred to the winner
T::Currency::transfer(
&buyer,
&Self::get_pallet_account(),
T::TicketCost::get(),
ExistenceRequirement::KeepAlive)?;

// 6. Notify the event
Self::deposit_event(Event::TicketBought { who: buyer });
Ok(())
}

#[pallet::call_index(1)]
#[pallet::weight(0)]
pub fn award_prize(origin: OriginFor<T>) -> DispatchResult {

// 1. Validates the origin signature
let _who = ensure_root(origin)?;

match Self::get_participants() {
Some(participants) => {

// 2. Gets a random number from the randomness module
let nonce = Self::get_and_increment_nonce();
let (random_seed, _) = T::MyRandomness::random(&nonce);
let random_number = <u32>::decode(&mut random_seed.as_ref())
.expect("secure hashes should always be bigger than u32; qed");

// 3. Selects the winner from the participants lit
let winner_index = random_number as usize % participants.len();
let winner = participants.as_slice().get(winner_index).unwrap();

// 4. Transfers the total prize to the winner's account
let prize = T::Currency::free_balance(&Self::get_pallet_account());
T::Currency::transfer(
&Self::get_pallet_account(),
&winner,
prize,
ExistenceRequirement::AllowDeath)?;

// 5. Resets the participants list, and gets ready for another lottery round
Participants::<T>::kill();

// 6. Notify the event
Self::deposit_event(Event::PrizeAwarded { winner: winner.clone() } );
},
None => {
// Notify the event (No participants)
Self::deposit_event(Event::ThereAreNoParticipants);
}
};

Ok(())
}
}
53 changes: 53 additions & 0 deletions .snippets/code/basic-substrate/lottery-example-cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[package]
name = "module-lottery-example"
version = "4.0.0-dev"
description = "Simple module example"
authors = [""]
homepage = ""
edition = "2021"
publish = false

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [
"derive",
] }
scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
frame-benchmarking = {
version = "4.0.0-dev",
default-features = false,
optional = true,
git = "https://github.com/paritytech/substrate.git",
branch = "polkadot-v1.0.0"
}
frame-support = {
version = "4.0.0-dev",
default-features = false,
git = "https://github.com/paritytech/substrate.git",
branch = "polkadot-v1.0.0"
}
frame-system = {
version = "4.0.0-dev",
default-features = false,
git = "https://github.com/paritytech/substrate.git",
branch = "polkadot-v1.0.0"
}

[dev-dependencies]
sp-core = { version = "21.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" }
sp-io = { version = "23.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" }
sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" }

[features]
default = ["std"]
std = [
"codec/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
]
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]
54 changes: 37 additions & 17 deletions .snippets/code/modules/lottery-example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ pub mod pallet {
PalletId,
};

type BalanceOf<T> = <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;

#[pallet::pallet]
pub struct Pallet<T>(_);
Expand All @@ -30,23 +31,27 @@ pub mod pallet {
#[pallet::config]
pub trait Config: frame_system::Config {

/// Because this pallet emits events, it depends on the runtime's definition of an event.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
// 1. Event definition
type RuntimeEvent: From<Event<Self>>
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;

/// This module depends on other modules, such as balances and randomness
// 2. Currency
type Currency: Currency<Self::AccountId>
+ ReservableCurrency<Self::AccountId>
+ LockableCurrency<Self::AccountId>;

// 3. Randomness
type MyRandomness: Randomness<Self::Hash, BlockNumberFor<Self>>;

/// Some values that must be configured when adding the module to the runtime
// 4. Ticket cost
#[pallet::constant]
type TicketCost: Get<BalanceOf<Self>>;

// 5. Maximum number of participants
#[pallet::constant]
type MaxParticipants: Get<u32>;

// 6. Module Id
#[pallet::constant]
type PalletId: Get<PalletId>;
}
Expand Down Expand Up @@ -91,27 +96,29 @@ pub mod pallet {

#[pallet::call]
impl<T: Config> Pallet<T> {

#[pallet::call_index(0)]
#[pallet::weight(0)]
pub fn buy_ticket(origin: OriginFor<T>) -> DispatchResult {

// 1. Validates the origin signature
let buyer = ensure_signed(origin)?;

// Checks that the user has enough balance to afford the ticket price
// 2. Checks that the user has enough balance to afford the ticket price
ensure!(
T::Currency::free_balance(&buyer) >= T::TicketCost::get(),
Error::<T>::NotEnoughCurrency
);

// Checks that the user do not have a ticket yet
// 3. Checks that the user is not already participating
if let Some(participants) = Self::get_participants() {
ensure!(
!participants.contains(&buyer),
Error::<T>::AccountAlreadyParticipating
);
}

// Stores the user to participate in the lottery
// 4. Adds the user as a new participant for the prize
match Self::get_participants() {
Some(mut participants) => {
ensure!(
Expand All @@ -130,42 +137,55 @@ pub mod pallet {
}
};

// Transfer the ticket cost to the module's account
T::Currency::transfer(&buyer, &Self::get_pallet_account(), T::TicketCost::get(), ExistenceRequirement::KeepAlive)?;
// 5. Transfers the ticket cost to the module's account
// to be hold until transferred to the winner
T::Currency::transfer(
&buyer,
&Self::get_pallet_account(),
T::TicketCost::get(),
ExistenceRequirement::KeepAlive)?;

// Notify the event
// 6. Notify the event
Self::deposit_event(Event::TicketBought { who: buyer });
Ok(())
}

#[pallet::call_index(1)]
#[pallet::weight(0)]
pub fn award_prize(origin: OriginFor<T>) -> DispatchResult {

// 1. Validates the origin signature
let _who = ensure_root(origin)?;

match Self::get_participants() {
Some(participants) => {

// Gets a random number, using randomness module
// 2. Gets a random number from the randomness module
let nonce = Self::get_and_increment_nonce();
let (random_seed, _) = T::MyRandomness::random(&nonce);
let random_number = <u32>::decode(&mut random_seed.as_ref())
.expect("secure hashes should always be bigger than u32; qed");

// Selects the winner
// 3. Selects the winner from the participants lit
let winner_index = random_number as usize % participants.len();
let winner = participants.as_slice().get(winner_index).unwrap();

// Transfers the total prize to the winner's account
// 4. Transfers the total prize to the winner's account
let prize = T::Currency::free_balance(&Self::get_pallet_account());
T::Currency::transfer(&Self::get_pallet_account(), &winner, prize, ExistenceRequirement::AllowDeath)?;
T::Currency::transfer(
&Self::get_pallet_account(),
&winner,
prize,
ExistenceRequirement::AllowDeath)?;

// Resets the storage, and gets ready for another lottery round
// 5. Resets the participants list, and gets ready for another lottery round
Participants::<T>::kill();

// 6. Notify the event
Self::deposit_event(Event::PrizeAwarded { winner: winner.clone() } );
},
None => {
// Notify the event (No participants)
Self::deposit_event(Event::ThereAreNoParticipants);
}
};
Expand Down
2 changes: 1 addition & 1 deletion builders/build/.pages
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ hide: false
nav:
- index.md
- 'Prerequisites': 'prerequisites.md'
# - 'Basic Substrate': 'substrate.md'
- 'substrate'
# - 'Templates': 'templates.md'
# - 'Modifying your ContainerChain': 'modifying.md'
# - 'Test Locally': 'test.md'
Expand Down
5 changes: 5 additions & 0 deletions builders/build/substrate/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
title: Basic Substrate
hide: false
nav:
- index.md
- 'Adding a Custom-Made Module': 'adding-custom-made-module.md'
Loading
Loading