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

Phase 2 #129

Merged
merged 23 commits into from
Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
11ae4d8
Added new chapters.
manangouhari Oct 26, 2020
96ddeae
Upated useChapter to filter module-wise. Need to figure out overview …
manangouhari Oct 27, 2020
4991eb3
Refactored useChapter to use a more explicit parameter.
manangouhari Oct 27, 2020
0f0f29f
Added module-1 to slug for chapters.:
manangouhari Oct 27, 2020
6a907a7
Cleaned up frontmatter for inter-contract section.
manangouhari Oct 27, 2020
1003e09
Cleaned up frontmatter for FA2 section.
manangouhari Oct 27, 2020
65be4e5
Pushing the code for Bhaskar.
manangouhari Oct 27, 2020
c003ada
Indentation error fixed in 02.mdx
manangouhari Oct 27, 2020
c5af004
Re: fixed indentation error in 02.mdx
manangouhari Oct 27, 2020
1bd9224
Pages for module overview are now being dynamically generated.
manangouhari Oct 27, 2020
ed64b09
Added links to module 2&3 on the homepage. Only for test right now.
manangouhari Oct 27, 2020
fc011d2
Fixed logic for continuation link on overview page.
manangouhari Oct 27, 2020
de9efd5
Replaced 'lesson-v1' with filterBy to make localStorage logic dynamic.
manangouhari Oct 27, 2020
68ae683
Fixed backLinks on chapter header to dynamically navigate to overview…
manangouhari Oct 27, 2020
d90e707
MenuSlider works dynamically :)
manangouhari Oct 27, 2020
c98f795
Removed chapter-new.js
manangouhari Oct 28, 2020
0950d94
New overview page implemented.
manangouhari Oct 28, 2020
ad8a400
Updated copy for module specific overview pages. Still not finalized …
manangouhari Oct 28, 2020
e51446b
Fixed the user flow(partially). Rest will be done once last module is…
manangouhari Oct 29, 2020
a8b15a6
Added TODO to buggy code.
manangouhari Oct 29, 2020
1a85e7a
Dynamic header added.
manangouhari Oct 29, 2020
0bf8c4e
Wrote copy for general overview.
manangouhari Oct 29, 2020
a95a2f5
Fixed the chapters a bit
manangouhari Oct 29, 2020
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
32 changes: 23 additions & 9 deletions gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
nodes {
frontmatter {
slug
type
}
}
}
Expand All @@ -15,15 +16,28 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
reporter.panic('failed to create chapter', result.errors);
}

const chapters = result.data.allMdx.nodes;
const mdxFiles = result.data.allMdx.nodes;

mdxFiles.forEach(file => {

chapters.forEach(chapter => {
actions.createPage({
path: `/lesson/${chapter.frontmatter.slug}`,
component: require.resolve('./src/templates/chapter.js'),
context: {
slug: chapter.frontmatter.slug,
},
});
if(file.frontmatter.type === "module"){
actions.createPage({
path: `/tezos/overview/${file.frontmatter.slug}`,
component: require.resolve('./src/templates/overview.js'),
context: {
slug: file.frontmatter.slug,
},

});
}else{

actions.createPage({
path: `/tezos/lesson/${file.frontmatter.slug}`,
component: require.resolve('./src/templates/chapter.js'),
context: {
slug: file.frontmatter.slug,
},
});
}
});
};
172 changes: 172 additions & 0 deletions lessons/inter-contract-calling/01/01.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: Intro to Mutez
chapter: Chapter 1
slug: module-02/chapter-01
filterBy: lesson-2
editor:
language: python
startingCode: |
import smartpy as sp
class Cryptobot(sp.Contract):

def __init__(self, manager_address, life_state):

self.init(
bot_manager = manager_address,
name = "terminator",
is_alive = life_state,
plasma_bullet_count = 5,

record_alien_kills = {
"simple_alien": sp.nat(0),
"boss_alien": sp.nat(0),
}
# add mutez_points here


)


@sp.entry_point
def shoot_alien(self, alien_type):

sp.verify(
self.data.bot_manager == sp.sender,
message = "Error: non manager call"
)

sp.if self.data.plasma_bullet_count >= 1:
self.data.plasma_bullet_count -= 1
self.data.record_alien_kills[alien_type] += 1
sp.else:
sp.failwith("Error: you ran out of bullets! Please buy more!")


@sp.add_test(name = "mutez")
def test():
scenario = sp.test_scenario()

## Class Invokation
my_address = sp.address("tz1Syu3KacZ8cy4286a4vaCeoMtwqVKHkaoj")

test_bot = Cryptobot(manager_address = my_address, life_state = True)

## Testing contract
scenario += test_bot

#scenario.verify over here.

answer: |
import smartpy as sp

class Cryptobot(sp.Contract):

def __init__(self, manager_address, life_state):

self.init(
bot_manager = manager_address,
name = "terminator",
is_alive = life_state,
plasma_bullet_count = 5,

record_alien_kills = {
"simple_alien": sp.nat(0),
"boss_alien": sp.nat(0),
},
# add mutez_points here
mutez_points = sp.mutez(5000)

)


@sp.entry_point
def shoot_alien(self, alien_type):

sp.verify(
self.data.bot_manager == sp.sender,
message = "Error: non manager call"
)

sp.if self.data.plasma_bullet_count >= 1:
self.data.plasma_bullet_count -= 1
self.data.record_alien_kills[alien_type] += 1
sp.else:
sp.failwith("Error: you ran out of bullets! Please buy more!")


@sp.add_test(name = "mutez")
def test():
scenario = sp.test_scenario()

## Class Invokation
my_address = sp.address("tz1Syu3KacZ8cy4286a4vaCeoMtwqVKHkaoj")

test_bot = Cryptobot(manager_address = my_address, life_state = True)

## Testing contract
scenario += test_bot

#scenario.verify over here
scenario.verify(test_bot.data.mutez_points == sp.mutez(5000))
---

### Intro
Awesome work defeating those nasty aliens :rocket:
But, beware that was only the **first wave**, there's a greater challenge that lies ahead of you.
At least one good thing came out of the first battle, you managed to collect some **mutez** 💵 when you defeated the first wave.

Confused what good is this **mutez** thingy?
It's a **smaller unit of XTZ**.
Simply a way to represent smaller amounts of Tezos.

This will come in handy to defeat the new challenge coming your way.
You'll can use these `mutez_points` to buy power-ups from the `Market`(we'll implement the market in the coming chapters).


### Study time
Mutez is to XTZ(Currency of Tezos) what a cent is to dollar or what gram is to kg.
To be more accurate -
`1,000,000 mutez = 1 XTZ`(1 million Mutez = 1 Tez(or XTZ))

Similar to all other data types in SmartPy(sp.TNat, sp.TMap, etc) there are Tezos specific data types as well and one of them is [`sp.TMutez`](https://smartpy.io/dev/reference.html#_mutez).

> #### Note -
> In SmartPy, when a type is being specified - it's referened with `sp.T<Type>`. But when it's being called with a value - it's called with `sp.<type>`.
> Example - `sp.TNat` and `sp.nat(5)`, `sp.TMutez` and `sp.mutez(500)`
> If you're not familiar with data types, go through this [chapter](https://cryptocodeschool.in/lesson/chapter-08)

#### Difference between sp.mutez and sp.tez -
When you write `sp.mutez(100000)` it's equated to `0.1 Tez(XTZ)`.
Hence, when you're specifying a large number of tokens, it's better to use `sp.tez`. Like - `sp.tez(0.1)`.
Whereas, `sp.mutez` helps you express smaller quantities with much better accuracy.

### Show me an example
```python=
class Wallet(sp.Contract):
def __init__(self, initial_amount):
self.init(
amount = sp.mutez(initial_amount)
)

@sp.add_test(name = "Wallet")
def test():
scenario = sp.test_scenario()
w = Wallet(1000)
scenario += w
scenario.verify(w.data.amount == sp.mutez(1000))
```
Here, `Wallet` is storing `amount` which is of type `sp.TMutez`
In the expression inside `scenario.verify`, `w.data.amount == sp.mutez(1000)`, we need to wrap `1000` with `sp.mutez()` because `amount` is holding data of type `sp.TMutez`.

Think about it - for two values to be equal, their type also needs to be the same because smartpy scripts get converted to **Michelson** which is the language that runs on the Tezos blockchain. **Michelson is stronly typed**, hence requires same types.

### #buidl-ing time

#### New feature request!
Now that you've collected some `mutez_points` in your previous battle, you need to have a place to keep track of them as well.

#### Step by step walkthrough
- Initialize `mutez_points` in your contract storage and set it equal to 5000 mutez.

#### Testing our code
- Use `scenario.verify` to confirm whether the `mutez_points` in `Cryptobot` is equal to `5000` or not.
151 changes: 151 additions & 0 deletions lessons/inter-contract-calling/02/02.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
title: Test Accounts
chapter: Chapter 2
slug: module-02/chapter-02
filterBy: lesson-2
editor:
language: python
startingCode: |
import smartpy as sp

class Cryptobot(sp.Contract):

def __init__(self, manager_address, life_state, initial_mutez):

self.init(
bot_manager = manager_address,
name = "terminator",
is_alive = life_state,
plasma_bullet_count = 5,

record_alien_kills = {
"simple_alien": sp.nat(0),
"boss_alien": sp.nat(0),
},
# add mutez_points here
mutez_points = sp.mutez(initial_mutez)

)


@sp.entry_point
def shoot_alien(self, alien_type):

sp.verify(
self.data.bot_manager == sp.sender,
message = "Error: non manager call"
)

sp.if self.data.plasma_bullet_count >= 1:
self.data.plasma_bullet_count -= 1
self.data.record_alien_kills[alien_type] += 1
sp.else:
sp.failwith("Error: you ran out of bullets! Please buy more!")


@sp.add_test(name = "test_account")
def test():
scenario = sp.test_scenario()

## Class Invokation
my_address = sp.address("tz1Syu3KacZ8cy4286a4vaCeoMtwqVKHkaoj")

test_bot = Cryptobot(manager_address = my_address, life_state = True, initial_mutez=5000)

## Testing contract
scenario += test_bot

answer: |
import smartpy as sp

class Cryptobot(sp.Contract):

def __init__(self, manager_address, life_state, initial_mutez):

self.init(
bot_manager = manager_address,
name = "terminator",
is_alive = life_state,
plasma_bullet_count = 5,

record_alien_kills = {
"simple_alien": sp.nat(0),
"boss_alien": sp.nat(0),
},
# add mutez_points here
mutez_points = sp.mutez(initial_mutez)

)


@sp.entry_point
def shoot_alien(self, alien_type):

sp.verify(
self.data.bot_manager == sp.sender,
message = "Error: non manager call"
)

sp.if self.data.plasma_bullet_count >= 1:
self.data.plasma_bullet_count -= 1
self.data.record_alien_kills[alien_type] += 1
sp.else:
sp.failwith("Error: you ran out of bullets! Please buy more!")


@sp.add_test(name = "test_account")
def test():
scenario = sp.test_scenario()

## Class Invokation
my_account = sp.test_account("Cryptobot Owner")

test_bot = Cryptobot(manager_address = my_account.address, life_state = True, initial_mutez=5000)

## Testing contract
scenario += test_bot
---

### Intro

Calibrating our plasma cannons for the next wave of aliens - what better way than to make your script a teeny bit better?
Right now, we're using `sp.address` to give a `bot_manager` address to our `Cryptobot`.
But, SmartPy has a special function called `sp.test_account(seed)` which we'll use to improve upon this.

### Study time
`sp.test_account(seed)` takes a random string as an argument and generates several properties based on this `seed` value.
A test accounts has the following fields -
- `address`
- `public_key_hash`
- `public_key`
- `secret_key`

Don't worry about what all the fields mean. We only need the `address` for our purpose :D

### Show me an example
```python=
class Wallet(sp.Contract):
def __init__(self, initial_amount, owner_address):
self.init(
amount = sp.mutez(initial_amount),
owner = owner_address
)

@sp.add_test(name = "Wallet")
def test():
scenario = sp.test_scenario()
account_owner = sp.test_account("Wallet Example Account")
w = Wallet(initial_amount = 1000, owner_address = account_owner.address)
scenario += w
```
Building on our example from the previous chapter, here a new field has been added in contract storage, `owner`.
Inside the test, we generated a test account using `sp.test_account("Wallet Example Account")` and passed in the address to wallet using `account_owner.address`.

### #buidl-ing time

#### Let's refactor!
Now you know about `sp.test_account`, use it instead of `sp.address` in our `Cryptobot`.

#### Step by step walkthrough
1. Replace `my_address` variable with `my_account` and assign and invoke it with `sp.test_account` with the `seed` of `"Cryptobot Owner"`.
2. Replace `my_address` in the Contract initialization with `my_account.address`.
Loading