-
-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #278 from Cyfrin/dev
dev --> main
- Loading branch information
Showing
343 changed files
with
7,118 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
...dvanced-python-vyper-smart-contract-development/1-moccasin-nft/1-intro/+page.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
## Moccasin NFTs | ||
|
||
This section is about Moccasin NFTs, and will continue to help us build our skills as we begin to work more independently with AI tools. | ||
|
||
We'll be working with NFTs, building a decentralized stablecoin, understanding signatures and upgrades, and learning some amazing new things as we explore the industry and develop our own skills. | ||
|
||
Remember to do all of the workshops associated with each of these sections. They are the heart of the course and how we will truly drill in all of the skills we're learning here. | ||
|
||
Our first section is on Moccasin NFTs. | ||
|
||
Here is the link to the full code we will be working with. | ||
|
||
``` | ||
https://github.com/Cyfrin/mox-nft-cu | ||
``` | ||
|
||
It's a classic Moccasin project and has a moccasin.toml file, which we will be diving into more in later sections. | ||
|
||
The code we're working with here is pretty simple; just a basic NFT. | ||
```python | ||
from moccasin.boa_tools import VyperContract | ||
from src import basic_nft | ||
|
||
def deploy_basic_nft() -> VyperContract: | ||
basic_nft_contract = basic_nft.deploy() | ||
print(f"Deployed basic NFT to {basic_nft_contract.address}") | ||
PUG_URI = "Qm1i6J98JYHB9Y36rUu0tDDm6LdEeNdAAgmrrx3s1tMa" | ||
print(f"Minted Pug NFT with URI {PUG_URI}") | ||
basic_nft_contract.mint(PUG_URI) | ||
return basic_nft_contract | ||
|
||
def moccasin_main(): | ||
return deploy_basic_nft() | ||
``` | ||
|
||
This will deploy our basic NFT and give us a link to our IPFS file that will point to a JSON file that represents our NFT. | ||
|
||
We can then import this into our MetaMask wallet and actually see our NFT. | ||
|
||
We can then import this into our MetaMask wallet and actually see our NFT. | ||
|
||
We'll also be going over some low-level encoding and some low-level raw calls. | ||
|
||
Now, we will go over a slightly more advanced NFT. It's the Mood NFT. Let's go over it in the terminal. | ||
|
||
```bash | ||
mox run deploy_mood_nft --network anvil --account Vyper-cour | ||
``` | ||
|
||
And this will get us a base 64 encoded URL where we can take this entire URL and then stick it into our browser to see our NFT which looks like this. | ||
|
||
Now, we're going to go over the advanced, Sub-Lesson, where we learn how to call anything, we learn about encoding, we learn about raw calls, and a lot of the low-level functionality that we have been skipping over. | ||
|
||
The final thing we will be showing you in this section, is this more advanced Sub-Lesson, where we learn how to call anything and we learn about encoding. | ||
|
||
```python | ||
from moccasin.boa_tools import VyperContract | ||
from src import mood_nft | ||
|
||
def deploy_mood_nft() -> VyperContract: | ||
mood_nft_contract = mood_nft.deploy() | ||
print(f"Deployed mood NFT to {mood_nft_contract.address}") | ||
PUG_URI = "Qm1i6J98JYHB9Y36rUu0tDDm6LdEeNdAAgmrrx3s1tMa" | ||
print(f"Minted Pug NFT with URI {PUG_URI}") | ||
mood_nft_contract.mint(PUG_URI) | ||
return mood_nft_contract | ||
|
||
def moccasin_main(): | ||
return deploy_mood_nft() | ||
``` | ||
|
||
Now, we will go over this more advanced sub-lesson where we learn how to call anything, we learn about encoding. | ||
|
||
```python | ||
from moccasin.boa_tools import VyperContract | ||
from src import mood_nft | ||
|
||
def deploy_mood_nft() -> VyperContract: | ||
mood_nft_contract = mood_nft.deploy() | ||
print(f"Deployed mood NFT to {mood_nft_contract.address}") | ||
PUG_URI = "Qm1i6J98JYHB9Y36rUu0tDDm6LdEeNdAAgmrrx3s1tMa" | ||
print(f"Minted Pug NFT with URI {PUG_URI}") | ||
mood_nft_contract.mint(PUG_URI) | ||
return mood_nft_contract | ||
|
||
def moccasin_main(): | ||
return deploy_mood_nft() | ||
``` | ||
|
||
We'll also be going over some low-level encoding and some low-level raw calls. | ||
|
||
Stay tuned for more amazing things as we move forward in this course! |
7 changes: 7 additions & 0 deletions
7
...act-development/1-moccasin-nft/10-note-what-happens-when-we-stop-anvil/+page.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
## What happens when we stop our Anvil and Era Test Node? | ||
|
||
When we stop our Era test node or Anvil node, our NFTs might still show up in our network, and they may go away. | ||
|
||
If we start getting some weird errors, we can click on the account in the top right corner of MetaMask, click on Settings, Advanced, and then click on Clear activity tab data. This will do a kind of reset. | ||
|
||
Obviously, right now, if we tried to send money because our Era test node is down, it would just gray out, which is really annoying. So, just know that we could even do a little refresh list, and it's going to just nothing's going to happen. So, just know that if our networks are down, if we're locally running networks are down, we might get some weird stuff showing up in our MetaMask. So, just be sure to keep that in mind. |
34 changes: 34 additions & 0 deletions
34
...d-python-vyper-smart-contract-development/1-moccasin-nft/11-workshop-1/+page.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
### Workshop 1: Mocksen NFTs | ||
|
||
We are going to be working with a centralized gateway. The centralized option we are using is: | ||
|
||
```text | ||
https://gateway.pinata.cloud/ipfs/QmAnOFS6q43HRTW32wVSv6ITTFv3aKqFTf8qKFfTmciJMK | ||
``` | ||
|
||
The first workshop involves completing two prompts: | ||
|
||
1. **Upload your own dog image to IPFS, mint it as an NFT, and then see it in your Metamask!** | ||
2. **Write tests to get at least 80% coverage!** | ||
|
||
If we are using our own IPFS, our IPFS node must be running. Our desktop app has a node option in the top right. If we want to stop it, we can turn it off. | ||
|
||
Alternatively, we can use a centralized service like Pinata Cloud. Pinata Cloud allows us to upload directly to the service. | ||
|
||
We need to ensure that our token URI returns a JSON object. The JSON object must include the image and image attributes. | ||
|
||
If we want to use the dog images provided in the Github repo for this course, we can find them under the /images/static directory. | ||
|
||
### Workshop 2: Mocksen DeFi | Algorithmic Trading | ||
|
||
The second workshop prompt is: | ||
|
||
**Spend at most 25 minutes on all of these prompts without the aide of AI. If you�re unable to solve them after 25 minutes, stop, take a break, and then work with an AI or the discussions to help you solve them. Good luck!** | ||
|
||
We can test our code in the terminal: | ||
|
||
```bash | ||
mox test --coverage | ||
``` | ||
|
||
This completes our introduction to the Mocksen NFTs and testing workshops. Pause the video, complete these workshops, and we'll see you in a bit! |
34 changes: 34 additions & 0 deletions
34
...thon-vyper-smart-contract-development/1-moccasin-nft/12-what-is-an-svg/+page.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
## NFTs: What is an SVG? | ||
|
||
We're going to use something called an SVG. | ||
|
||
Now, an SVG is something that we can store all on chain, but the issue is that we have to be able to encode our image as an SVG. We can also encode our JSON on chain as a base 64 encoded URI. | ||
|
||
What the heck do both of those mean? Well, first, let's go start with what is an SVG. | ||
|
||
SVG stands for Scalable Vector Graphics. SVG defines vector-based graphics in XML format. | ||
|
||
We can actually scroll down, and we can see an example right in this SVG example, right? So, this is it. So, it looks it's just kind of this tag where it has very specific parameters for defining what an image looks like. | ||
|
||
And, the reason that SVGs are so cool is because no matter how big or small you make them, they're always going to have the exact same quality because they're scalable. You know how, like, if you take an image like this one, let me view this, you know, if we take this image, right, and I make it super super big, and I make it super big. The bigger I make it, the worse the quality gets. With an SVG, you don't ever have to deal with that because you define exactly what it will look like, no matter what size. | ||
|
||
And what we can do is we can actually make our own SVG sort of like this, right? And if you're in the W3Schools, if you try for yourself, you can see my first SVG over here, and I can change this. I can say the fill is now blue. We'll run, and now it turns blue. I can say the stroke is black, right, and it turns black. | ||
|
||
So, there's a ton of different parameters and functions that we can do to make an SVG look a certain way. Right, so if we're back in our VS Code, we can even go up to IMG, new file, example.svg. We can code some SVG in here, so we'll do SVG xml ns equals, and this is just version stuff, http. | ||
```bash | ||
cd img/ | ||
base64 -i example.svg | ||
``` | ||
We can actually base 64 encode the output, everything in here, and what I can say is, I could do base 64 - i, which means we're going to input a file and we're going to pass in this example.svg. We'll see we get this weird thing as an output. | ||
|
||
So, now if we take this weird thing, and I'm going to actually create a little little README to make some notes here. | ||
|
||
So, this weird output is the base 64 encoded example.svg we just created. | ||
|
||
Now, at the start of this, we can add a beginning piece to tell our browser that this is an SVG. So, I'm going to say data colon image slash svg plus xml colon base 64 comma like this. And, if I copy this whole thing, oops, sorry, this is in this should be a semicolon here. If I copy this whole thing, and I paste it into any browser, we're going to get this Hi, your browser decoded this. So, basically what we did was we encoded this SVG file, and put this data image, SVG plus xml colon base 64, so our browser knew how to decode it, and then just passed the entire image through our browser URL. And boom. So, we can also do this with images. So, if I go back to the repo associated with this lesson, go to images, dynamic NFT, we go to happy.svg, we go down to code instead of preview, and see the exact code here, right? So we create this viewBox, oops, we create some circles, we create this path, which is how we just kind of draw lines, and I can copy this whole thing, paste it into my image, so I'm going to say, oops, image, I'm going to do happy.svg, happy.svg, paste it in here. If I pull up the preview, I see the preview is a happy. Now what I can do is I can do base 64 - i happy.svg, we get this output. I can copy this output. Let me go over to the README, paste it. I'm going to add this beginning piece to it, and then copy this whole thing. We go back to my browser, paste it in, and boom. We've passed all of this data to generate this SVG right in the URL. And, this is looks like Yes it does. a token URI, right? So, now, instead of using an IPFS hash for our token URI, we can actually 100% on-chain use this SVG thing. And, because this SVG is basically coded on chain, we can update it and interact with it to make it do whatever we want it, right? | ||
|
||
For example, if our has happy SVG, we could say, okay, if if somebody has 10 tokens, right, they get 10 circles or something like that, right? We could do whatever we want with this. | ||
```bash | ||
base64 -i happy.svg | ||
``` | ||
Welcome back. |
40 changes: 40 additions & 0 deletions
40
...ced-python-vyper-smart-contract-development/1-moccasin-nft/13-mood-nft/+page.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
Now that we know what an SVG is and how we can code it, we can use this coding to build an NFT where all the metadata is stored directly on chain. Let's go ahead and build this NFT. | ||
|
||
We'll call our new contract "mood_nft.vy" and inside we will code: | ||
|
||
```javascript | ||
pragma version 0.4.0 | ||
@license MIT | ||
@title Mood NFT | ||
``` | ||
|
||
We'll use a few imports here: | ||
|
||
```javascript | ||
from snekmate.tokens import erc721 | ||
from snekmate.auth import ownable as ow | ||
``` | ||
|
||
We will then define a constructor for our contract: | ||
|
||
```javascript | ||
initializes: | ||
ow | ||
erc721: ownable = ow | ||
|
||
def init(): | ||
ow._init() | ||
erc721.init_(NAME, SYMBOL, BASE_URI, NAME, EIP_712_VERSION) | ||
``` | ||
|
||
Finally, we'll need to define some state variables: | ||
|
||
```javascript | ||
# STATE VARIABLES | ||
NAME: constant(String[25]) = "Mood NFT" | ||
SYMBOL: constant(String[5]) = "MNFT" | ||
BASE_URI: public(constant(String[34])) = "https://gateway.pinata.cloud/ipfs/" | ||
EIP_712_VERSION: constant(String[1]) = "1" | ||
``` | ||
|
||
We are now ready to start deploying our dynamic NFT, which we'll do in the next video! |
81 changes: 81 additions & 0 deletions
81
...r-smart-contract-development/1-moccasin-nft/14-base-64-encoding-images/+page.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
## Base64 Encoding Images | ||
|
||
In this lesson, we will learn how to encode an image to Base64. | ||
|
||
First, we will create a new folder called "images" and save our two SVG files (happy.svg and sad.svg) in it. | ||
|
||
Next, we will import the base64 library and create a new function: | ||
|
||
```python | ||
import base64 | ||
|
||
def svg_to_base64_uri(svg): | ||
svg_bytes = svg.encode("utf-8") | ||
base64_bytes = base64.b64encode(svg_bytes).decode("utf-8") | ||
return f"data:image/svg+xml;base64,{base64_bytes}" | ||
``` | ||
|
||
Now, we can use the `svg_to_base64_uri()` function to encode our SVGs to Base64 and assign the results to the `happy_svg_uri` and `sad_svg_uri` variables. | ||
|
||
```python | ||
def deploy_mood(): | ||
happy_svg_uri = "" | ||
sad_svg_uri = "" | ||
with open("./images/happy.svg", "r") as f: | ||
happy_svg = f.read() | ||
happy_svg_uri = svg_to_base64_uri(happy_svg) | ||
print(happy_svg_uri) | ||
|
||
with open("./images/sad.svg", "r") as f: | ||
sad_svg = f.read() | ||
sad_svg_uri = svg_to_base64_uri(sad_svg) | ||
|
||
mood_nft = mood_nft.deploy(happy_svg_uri, sad_svg_uri) | ||
``` | ||
|
||
Finally, we will import the "mood_nft" contract and use it to pass our encoded image data. | ||
|
||
```python | ||
from src import mood_nft | ||
``` | ||
|
||
```python | ||
def deploy_mood(): | ||
happy_svg_uri = "" | ||
sad_svg_uri = "" | ||
with open("./images/happy.svg", "r") as f: | ||
happy_svg = f.read() | ||
happy_svg_uri = svg_to_base64_uri(happy_svg) | ||
print(happy_svg_uri) | ||
|
||
with open("./images/sad.svg", "r") as f: | ||
sad_svg = f.read() | ||
sad_svg_uri = svg_to_base64_uri(sad_svg) | ||
|
||
mood_nft = mood_nft.deploy(happy_svg_uri, sad_svg_uri) | ||
``` | ||
|
||
We can then run our script using the following terminal command: | ||
|
||
```bash | ||
mox run deploy_mood_nft | ||
``` | ||
|
||
This will return a Base64 encoded string that can be used to render our SVG image in a browser. We can copy and paste the string into our browser to verify that it works as expected. | ||
|
||
We will then make the `happy_svg_uri` and `sad_svg_uri` constant variables in our contract file. | ||
|
||
```python | ||
HAPPY_SVG_URI: immutable(String[800]) = "" | ||
SAD_SVG_URI: immutable(String[800]) = "" | ||
``` | ||
|
||
We will pass these into the constructor of the contract so the image data is stored there. | ||
|
||
```python | ||
def init(happy_svg_uri: String[800], sad_svg_uri: String[800]): | ||
ow.init() | ||
erc721.init(NAME, SYMBOL, BASE_URI, NAME, EIP_712_VERSION) | ||
HAPPY_SVG_URI = happy_svg_uri | ||
SAD_SVG_URI = sad_svg_uri | ||
``` |
Oops, something went wrong.