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

Edits(?) & fixes #183

Merged
merged 35 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f0f8246
Update tests.rs
Yung-Beef Oct 28, 2024
08e5bba
Update README.md
Yung-Beef Oct 28, 2024
ee7cb24
Update README.md
Yung-Beef Oct 28, 2024
edfb8ab
Update README.md
Yung-Beef Oct 29, 2024
3d49eea
Update lib.rs
Yung-Beef Oct 29, 2024
f1bfdde
Update lib.rs
Yung-Beef Oct 29, 2024
2b2771d
Update impls.rs
Yung-Beef Oct 29, 2024
c0914b3
Update README.md
Yung-Beef Oct 29, 2024
4282876
Update tests.rs
Yung-Beef Oct 29, 2024
ecfe488
Update README.md
Yung-Beef Oct 29, 2024
ed6c010
Update impls.rs
Yung-Beef Oct 29, 2024
32e9804
Update impls.rs
Yung-Beef Oct 29, 2024
ed98ee5
Update impls.rs
Yung-Beef Oct 29, 2024
2189bf5
Update impls.rs
Yung-Beef Oct 29, 2024
13d6c68
Update impls.rs
Yung-Beef Oct 29, 2024
165550c
Update README.md
Yung-Beef Oct 29, 2024
d63f8ca
Update README.md
Yung-Beef Oct 29, 2024
86fffac
Update tests.rs
Yung-Beef Oct 29, 2024
8927f72
Update README.md
Yung-Beef Oct 30, 2024
7cf8074
Update README.md
Yung-Beef Oct 30, 2024
dedfaa7
Update README.md
Yung-Beef Oct 30, 2024
b2b1b28
Update README.md
Yung-Beef Oct 30, 2024
11401bd
Update impls.rs
Yung-Beef Oct 30, 2024
c0bdc12
Update README.md
Yung-Beef Oct 30, 2024
1bc0de2
remove "and sex"
shawntabrizi Nov 1, 2024
0938622
Merge branch 'master' into pr/183
shawntabrizi Nov 1, 2024
a506928
Merge branch 'master' into pr/183
shawntabrizi Nov 1, 2024
9e78b77
Update steps/20/README.md
shawntabrizi Nov 1, 2024
c58e0d4
Update steps/20/README.md
shawntabrizi Nov 1, 2024
2460e6a
Update steps/22/src/lib.rs
shawntabrizi Nov 1, 2024
2501315
Update steps/38/src/impls.rs
shawntabrizi Nov 1, 2024
84943e5
Update steps/38/src/impls.rs
shawntabrizi Nov 1, 2024
0784def
Update steps/52/README.md
shawntabrizi Nov 1, 2024
47eaafb
Update steps/52/src/impls.rs
shawntabrizi Nov 1, 2024
748563f
Update steps/6/README.md
shawntabrizi Nov 1, 2024
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
2 changes: 1 addition & 1 deletion steps/11/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ These properties make hash functions key for ensuring data integrity and uniquen

Due to the properties of a Hash, it is often referred to as a fingerprint.

For context, a 32-byte hash has 2^32 different possible outputs. This nearly as many atoms as there are in the whole universe!
For context, a 32-byte hash has 2^32 different possible outputs. This is nearly as many atoms as there are in the whole universe!

This uniqueness property helps blockchain nodes come to consensus with one another.

Expand Down
2 changes: 1 addition & 1 deletion steps/16/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

If you look into the history of "hacks" and "bugs" that happen in the blockchain world, a lot of it is associated with some kind of "unsafe" code.

Keeping our blockchain logic safe, and Rust is designed to handle it well.
We need to keep our blockchain logic safe, and Rust is designed to handle it well.

## Errors

Expand Down
2 changes: 2 additions & 0 deletions steps/20/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Each `Key` can store a separate `Value`, which makes maps super useful.

In this case `[u8; 32]` represents some unique identifier for each Kitty we will store, and `()` is simply a placeholder type for now.

Note that each storage instance needs its own `#[pallet::storage]` attribute.
shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved

## Conceptual

The key difference between a `StorageValue` and a `StorageMap` is:
Expand Down
4 changes: 2 additions & 2 deletions steps/22/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use super::*;
use frame::prelude::*;

impl<T: Config> Pallet<T> {
/* 🚧 TODO 🚧: Update this function signature to include `id` which is type `[u8; 32]`. */
/* 🚧 TODO 🚧: Update this function signature to include `dna` which is type `[u8; 32]`. */
pub fn mint(owner: T::AccountId) -> DispatchResult {
let current_count: u32 = CountForKitties::<T>::get();
let new_count = current_count.checked_add(1).ok_or(Error::<T>::TooManyKitties)?;
/* 🚧 TODO 🚧: In the `Kitties` map, under the key `id`, insert `()`. */
/* 🚧 TODO 🚧: In the `Kitties` map, under the key `dna`, insert `()`. */
CountForKitties::<T>::set(new_count);
Self::deposit_event(Event::<T>::Created { owner });
Ok(())
Expand Down
4 changes: 2 additions & 2 deletions steps/22/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ pub mod pallet {
pub fn create_kitty(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;
/* 🚧 TODO 🚧:
- Create `const default_id`, which type `[u8; 32]` and has value `[0u8; 32]`.
- Pass `default_id` to the `mint` function as a second parameter.
- Create a `dna` variable that this kitty will have, which has a value of `[0u8; 32]`.
- Pass `dna` to the `mint` function as a second parameter.
shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved
*/
Self::mint(who)?;
Ok(())
Expand Down
18 changes: 9 additions & 9 deletions steps/27/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Creating a new struct in Rust is pretty straight forward.

```rust
pub struct Kitty {
dna: [u8; 32],
owner: u32,
pub dna: [u8; 32],
pub owner: u32,
}
```

Expand Down Expand Up @@ -38,18 +38,18 @@ The first, and most verbose option in our situation is to make the struct generi

```rust
pub struct Kitty<AccountId> {
dna: [u8; 32],
owner: AccountId,
pub dna: [u8; 32],
pub owner: AccountId,
}
```

If we want to use multiple generic types, we could just keep extending this pattern:

```rust
pub struct Kitty<AccountId, BlockNumber> {
dna: [u8; 32],
owner: AccountId,
created: BlockNumber,
pub dna: [u8; 32],
pub owner: AccountId,
pub created: BlockNumber,
}
```

Expand All @@ -69,8 +69,8 @@ Let's look how that might look like:

```rust
pub struct Kitty<T: Config> {
dna: [u8; 32],
owner: T::AccountId,
pub dna: [u8; 32],
pub owner: T::AccountId,
}
```

Expand Down
3 changes: 3 additions & 0 deletions steps/27/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type Block = frame_system::mocking::MockBlock<TestRuntime>;
// We create the constants `ALICE` and `BOB` to make it clear when we are representing users below.
const ALICE: u64 = 1;
const BOB: u64 = 2;
/* 🚧 TODO 🚧:
- Create `const DEFAULT_KITTY` with a `dna` of [0u8; 32] and an `owner` of 0 };.
*/

// Our blockchain tests only need 3 Pallets:
// 1. System: Which is included with every FRAME runtime.
Expand Down
2 changes: 1 addition & 1 deletion steps/31/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ let unique_payload = (item1, item2, item3);
// To use the `hash_of` API, we need to bring the `Hash` trait into scope.
use frame::traits::Hash;
// Hash that object to get a unique identifier.
let hash: [u8; 32] = BlakeTwo256::hash_of(&unique_payload).into().
let hash: [u8; 32] = BlakeTwo256::hash_of(&unique_payload).into();
```

The `hash_of` API comes from the `Hash` trait and takes any `encode`-able object, and returns a `H256`, which is a 256-bit hash. As you can see in the code above, it is easy to convert that to a `[u8; 32]` by just calling `.into()`, since these two types are equivalent.
Expand Down
2 changes: 1 addition & 1 deletion steps/38/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<T: Config> Pallet<T> {
- `kitty_id` which is `[u8; 32]`.
- It returns a `DispatchResult`
- The inner logic for now is:
- Call `Self::dispatch_event` on and emit `Event::<T>:Transferred` with params.
- Call `Self::ddeposit_event` on and emit `Event::<T>:Transferred` with params.
shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved
- Return `Ok(())`.
*/
}
2 changes: 1 addition & 1 deletion steps/42/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ T::NativeBalance::mint_into(alice, amount)?;
T::NativeBalance::transfer(alice, bob, amount, Preserve)?;
```

The key difference here is that we do NOT assume that these APIs must from from specifically `pallet_balances`. If you wanted to use another pallet in the `polkadot-sdk` ecosystem which provides these same functions, you can use it! Our pallet is NOT tightly coupled to which pallet provides access to the `NativeBalance`, it only requires that there is something implementing the `Inspect` and `Mutate` traits.
The key difference here is that we do NOT assume that these APIs must come from specifically `pallet_balances`. If you wanted to use another pallet in the `polkadot-sdk` ecosystem which provides these same functions, you can use it! Our pallet is NOT tightly coupled to which pallet provides access to the `NativeBalance`, it only requires that there is something implementing the `Inspect` and `Mutate` traits.

The power of loose coupling may not be immediately obvious, but as you get deeper into developing in the Polkadot ecosystem, you will start to realize how powerful this approach can be.

Expand Down
1 change: 1 addition & 0 deletions steps/42/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ impl pallet_balances::Config for TestRuntime {
// will also need to update this configuration to represent that.
impl pallet_kitties::Config for TestRuntime {
type RuntimeEvent = RuntimeEvent;
/* 🚧 TODO 🚧: Add type `NativeBalance` as the `Balances` pallet. */
}

// We need to run most of our tests using this function: `new_test_ext().execute_with(|| { ... });`
Expand Down
2 changes: 1 addition & 1 deletion steps/44/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Let's look at how we would interact with this generic type, and solve many of th

The `Balance` type is ultimately configured inside `pallet_balances`, and remember, we don't have direct access to that pallet because we used loose coupling.

The way we can access the `Balance` type is through the `Inspect` trait of the `NativeBalance` associated type. Accessing it kind of funny, which is why we commonly introduce a `BalanceOf<T>` alias type like so:
The way we can access the `Balance` type is through the `Inspect` trait of the `NativeBalance` associated type. Accessing it is kind of funny, which is why we commonly introduce a `BalanceOf<T>` alias type like so:

```rust
// Allows easy access our Pallet's `Balance` type. Comes from `Fungible` interface.
Expand Down
2 changes: 1 addition & 1 deletion steps/46/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Set Price Extrinsic

Now that we our Pallet set up to handle balances, let's actually use them.
Now that we have our Pallet set up to handle balances, let's actually use them.

In this step, we will create an extrinsic which allows the owner of a kitty to set a price for the kitty.

Expand Down
2 changes: 1 addition & 1 deletion steps/50/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Buy Kitty Extrinsic

Now that kitties can have a price, we want to enable them to be purchaseable.
Now that kitties can have a price, we want to enable them to be purchasable.

For that, we will create the `buy_kitty` extrinsic.

Expand Down
8 changes: 7 additions & 1 deletion steps/52/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ That is all beyond the scope of this tutorial, but the high level idea is that w

In this context, we don't want someone to kill their account to buy a kitty, so we want to use `Preservation::Preserve` for our `transfer`.

> NOTE: To access this enum, you will need import the trait to bring it in scope, so don't forget to include:
shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved
>
> ```rust
> use frame::traits::tokens::Preservation;
> ```

So the final syntax should look like:

```rust
Expand All @@ -85,7 +91,7 @@ Both transfer functions need to succeed for the sale to complete successfully.

If either one of them would fail, the whole purchase should fail.

Thankfully, both of our transfer functions return a result, and to handle things correctly here, we just ned to propagate up those errors. For that, we simply include `?` at the end of the function.
Thankfully, both of our transfer functions return a result, and to handle things correctly here, we just need to propagate up those errors. For that, we simply include `?` at the end of the function.

If at any point our extrinsic or the logic inside the extrinsic returns an error, the whole extrinsic will fail and all changes to storage will be undone. This is exactly the same behavior you would expect from a smart contract, and keeps our state transition function functioning smoothly.

Expand Down
1 change: 1 addition & 0 deletions steps/52/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::*;
use frame::prelude::*;
use frame::primitives::BlakeTwo256;
/* 🚧 TODO 🚧: Import `frame::traits::tokens::Preservation`. */
/* 🚧 TODO 🚧: Import `frame::traits::fungible::Mutate`. */
Copy link
Owner

@shawntabrizi shawntabrizi Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed since you have super::*, and lib.rs imports this already

shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved
use frame::traits::Hash;

// Learn about internal functions.
Expand Down
2 changes: 2 additions & 0 deletions steps/6/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ If you are familiar with smart contracts or any kind of blockchain application,

Those transactions are processed, and then dispatched to callable functions within the blockchain.

*Internal functions are generally implemented in a separate `impl.rs` file for ergonomic purposes, while the callable functions are located in `lib.rs`.*
shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved

### Pallet Call Macro

Pallet development allows you to create callable functions by introducing the `#[pallet::call]` macro on top of a normal function implementation code block.
Expand Down
Loading