├── .gitignore ├── .prettierignore ├── 00-connect-to-blockchain.html ├── 01-read-address-data.html ├── 02-connect-to-contracts.html ├── 03-using-ens.html ├── 04-ercs.html ├── 05-example-app.html ├── 06-public-and-private-keys.html ├── 07-externally-owned-accounts.html ├── 08-crypto-wallet-setup.html ├── 09-test-networks.html ├── README.md ├── boilerplate ├── editor.js └── style.css ├── example_app.html ├── images ├── blockchain-connection-ethersjs.png ├── blockchain-connection.png ├── ecc-keys.png ├── encryption.png ├── ethereum-ecosystem.png ├── externally-owned-account.png └── signature.png ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.html -------------------------------------------------------------------------------- /00-connect-to-blockchain.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
11 | This course will start from zero, so you don't have to install any software for the first lessons. 12 | You don't need a crypto-wallet or crypto dev tools; all you need is your browser and basic 13 | JavaScript know-how. 14 |
15 | 16 |17 | Note: If you don't know JavaScript yet, because you just started learning how to program, 18 | or you only know other programming languages, you can try 19 | FreeCodeCamp, which offers good JavaScript 20 | courses for free! 21 |22 | 23 |
26 | In Web2, you know how to load your data from a server into a frontend. You connect to a backend 27 | with an HTTP API, which gets data from a database. 28 |
29 | 30 |31 | The same is true for Web3. If you don't have a crypto-wallet, you need an HTTP API to connect 32 | to a blockchain network because these networks use a protocol your browser doesn't understand. 33 | This API is called an remote procedure call endpoint, or RPC for short. This RPC accepts 34 | requests from a browser over HTTP and leads them to a blockchain network. You can only read data 35 | from the blockchain with this connection method. 36 |
37 | 38 |
39 | If you have a crypto-wallet, you can use it in JavaScript with a browser extension. In the case of
40 | Ethereum, the extension will add a global ethereum
object into the frontend. With
41 | this object you can use your wallet in your frontend. You can use this connection method to read
42 | and write data to the blockchain, like sending transactions.
43 |
46 | If you installed a crypto-wallet browser extension, it will connect to the blockchain network over 47 | an RPC, so the browser doesn't have to use the RPC directly. It will also take care of tasks like 48 | signing, and key management. 49 |
50 | 51 |52 | In Figure 1, you can see the different types of connections—Web2 and Web3 with and without a 53 | crypto-wallet. 54 |
55 | 56 |64 | In this course, you will start with the read-only connection methods. 65 |
66 | 67 |70 | Ethers.js is software that helps with connecting to the 71 | Ethereum network. You don't have to care if you connect directly over a RPC or use a browser 72 | extension when using Ethers.js. After you start any connection, the functions you call are the same. 73 |
74 | 75 |76 | Figure 2 shows how Ethers.js fits between your frontend and the Ethereum network. (The image is 77 | not 100% true, because Ethers.js comes with an integrated crypto-wallet, but we won't use it in 78 | the first part of this course.) 79 |
80 | 81 |
89 | Ethers.js is an ECMAScript module on the NPM package registry. This means, you can
90 | import
it directly in the browser with the unpkg CDN.
91 |
94 | import {ethers} from "//unpkg.com/ethers@5.5.1/dist/ethers.esm.min.js 95 |96 | 97 |
100 | You have to create a provider object to connect to the Ethereum network. Providers are the 101 | abstraction Ethers.js uses to normalize RPC use. 102 |
103 | 104 |
105 | You can create such an provider by calling the getDefaultProvider
method of the
106 | ethers
object you imported before.
107 |
110 | Note: This tutorial features a code editor. Here you can write JavaScript code and run it 111 | with the press of a button. The Ethers.js library is imported for you and you can use 112 |115 | 116 |await
for asynchronous requests. It also has a
117 | The first example is already written to show you how the editor works. Just press the 118 | Execute-button and check the output. 119 |
120 | 121 |127 | Try it yourself! 128 |
129 | 130 |
131 | To read data from the Etherum network, you can call the getBlock
method of the
132 | ethers
object. It returns a promise that resolves to an object that has the block's
133 | data, so you need to await
it. After you got the block, you can look at its data with
134 | the print
function.
135 |
141 | const block = await provider.getBlock() 142 | print(block) 143 |
144 |147 | If it worked, you see the block data in the output. This data is all blockchain-specific and 148 | doesn't tell us anything interesting yet. At least, you see that the connection worked, and you 149 | read data from it! 150 |
151 | 152 |153 | Ethers.js comes pre-configured with a shared RPC you can use for free to read data from the 154 | blockchain. This RPC has a request limit, so it can happen that you don't get a response if you 155 | send too many requests. But for this course, it should be enough. 156 |
157 | 158 |161 | In this lesson, you learned how Web2 and Web3 backends are different, while both use HTTP APIs. 162 | We call these APIs RPCs in Web3 because they allow us to remotely call procedures of a blockchain 163 | network. 164 |
165 | 166 |167 | You also learned how to use a blockchain network with the help of Ethers.js. You didn't have to 168 | install anything, just call a few methods and see what happens. 169 |
170 | 171 |172 | In the next lesson you will learn how to read address data. 173 |
174 | -------------------------------------------------------------------------------- /01-read-address-data.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |10 | Addresses are the bread and butter of blockchain networks. What IPs are for the Internet, 11 | addresses are for the blockchain. Addresses point to smart contracts and externally owned 12 | accounts (EOAs). 13 |
14 | 15 |
16 | An address number of the length of 20 bytes build from a public key and is usually shown as 40 hex
17 | digits. They look something like this 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
.
18 |
21 | Note: An address is used to send and receive data or money, in the form of tokens. Your 22 | money is gone when you send tokens to the wrong address because of a fault. Always check you have 23 | the correct address. No one can help you to get your money back! 24 |25 | 26 |
27 | An EOA is an address controlled by a private/public key pair owner from outside the Ethereum 28 | network; thus, the name externally owned account. Usually, you use a crypto-wallet to 29 | manage keys and addresses. 30 |
31 | 32 |33 | A smart contract is software running on the nodes (computers) that make up the blockchain network. 34 | The owner of a smart contract can be another smart contract or an EOA. That's why a smart contract 35 | isn't externally owned. 36 |
37 | 38 |39 | These addresses, both smart contracts and EOAs, have data tied to them. The Ethereum blockchain 40 | stores this data, and you can read and write it if you have the right permissions. In this lesson, 41 | you will just read data. As you can see in Figure 1, you can't write on the blockchain without a 42 | crypto-wallet. 43 |
44 | 45 |56 | To read data, you need an Ethers.js provider but also an address. Let's start with the transaction 57 | (TX) count. It's a simple number stored on the blockchain for every address that was part of such 58 | a TX. Ethereum adds 1 to the number if another TX with that address happens. 59 |
60 | 61 |
62 | Ethers.js providers offer a getTransactionCount
method that returns a promise that
63 | resolves to a TX count, so you have to await
it.
64 |
67 | Try it out in the editor! Call the method and print
its output. The method expects an
68 | address as string
argument, so here a few you can use:
69 |
0xdd00Cc906B93419814443Bb913949d503B3DF3c4
75 | 0xde21f729137c5af1b01d73af1dc21effa2b8a0d6
79 | 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
83 | 91 | const transactionCount = await provider.getTransactionCount(address) 92 | print(transactionCount) 93 |
94 |99 | Reading the balance of an address is a bit harder than reading the TX count. 100 |
101 | 102 |103 | Smart contracts and EOAs, have an Ether balance, the native money or the native token of 104 | the Ethereum network. Ether is what you have to pay to do TXs on the Ethereum network. 105 |
106 | 107 |
108 | Using a provider's getBalance
method, you can read the Ether balance of an address.
109 | Again, this method returns a promise, so you have to await
it.
110 |
113 | Try it out in the editor! Call the method and print
its output. The method expects an
114 | address as string
argument, so here a few you can use:
115 |
0xdd00Cc906B93419814443Bb913949d503B3DF3c4
121 | 0xde21f729137c5af1b01d73af1dc21effa2b8a0d6
125 | 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
129 | 136 | const balance = await provider.getBalance( 137 | "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" 138 | ) 139 | print(balance) 140 |
141 |144 | We got the balance, but why does it look like that? 145 |
146 | 147 |
150 | Ethers.js wrapped the balance in its own BigNumber
type, because the number can be
151 | too big for JavaScript's Number
type to store. You have to change the balance to a
152 | string
with the right number of decimal points to display it in a clear way.
153 |
156 | One of the biggest things that make Ethereum different from JavaScript are number types. For a
157 | long time, every number was of type Number
in JavaScript, which is a double-precision
158 | (64bit) floating-point . Every number was stored like that, because some time ago it got a
159 | new number type called
160 |
161 | BigInt
for very large integer numbers.
162 |
165 | Everything is an integer number in Solidity, the language used to make smart contracts for
166 | Ethereum. Solidity is concerned with money, and floating-point has problems that can cost you
167 | money, so they went for integer numbers only. Solidity always stores numbers as integers, and the
168 | most used type is uint256
(also known as uint
) which can store 78
169 | decimal digits. JavaScript's Number
type can only store 16 digits.
170 |
173 | Tokens can have more than 16 digits, so they're too big for Number
. Addresses are
174 | also stored as integers and are 20 byte big (40 hex digits). 20 byte are 160 bit, so they don't
175 | fit into the 64 bit Number
type either. That's why you use a String
to
176 | store addresses in JavaScript.
177 |
180 | Since Ethers.js wants to keep working with older browsers that don't support BigInt
,
181 | they made their own integer type called BigNumber
. It comes with
182 |
183 | methods for basic arithmetics, but can also be converted to String
or
184 | BigInt
when needed.
185 |
190 | The last exercise gave you a BigNumber
object that isn't easy to understand. While
191 | it's enough to work with the value inside of our code, you should change it to a
192 | String
before you show it to a user.
193 |
196 | To do so, you can use
197 | utility
198 | functions Ethers.js includes. The formatUnits
function will automatically convert
199 | a BigNumber
to a string
with the right decimal points. Which is handy to
200 | display a balance to a user.
201 |
204 | Try to convert the BigNumber
to a string
and print
it!
205 |
208 | The formatUnits
function can be found in the ethers.utils
object. This
209 | time it returns the output right away, so no await
needed.
210 |
218 | const readableBalance = ethers.utils.formatUnits(balance) + " ETH" 219 | print(readableBalance) 220 |
221 |226 | In this lesson, you learned that addresses are the heart of the Ethereum blockchain and point to 227 | externally owned accounts and smart contracts. 228 |
229 | 230 |
231 | Addresses are 160 bits or 20 bytes integer numbers usually shown as 40 hex digits, and JavaScript
232 | can't store them in its Number
type because it's only 8 bytes big. The same is true
233 | for token balances, which can have more than the 16 digits a Number
could store.
234 |
237 | In the next lesson, you will learn how to use smart 238 | contracts from the frontend. 239 |
-------------------------------------------------------------------------------- /02-connect-to-contracts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |10 | Smart contracts are the main feature that distinguishes Ethereum from Bitcoin. A smart contract is 11 | a program running on the Ethereum network, and it can access the blockchain data. 12 |
13 | 14 |15 | You write smart contracts in the Solidity programming language. Like Java, Solidity gets compiled 16 | to a bytecode that runs in a virtual machine. In this case, it's called the Ethereum Virtual 17 | Machine, or EVM for short. 18 |
19 | 20 |To interact with a smart contract from JavaScript, you need three things:
23 | 24 |31 | In the last lesson, you learned, every EOA and smart contract has an address; this is how you find 32 | the contract on the blockchain. 33 |
34 | 35 |36 | const address = "0x25ed58c027921E14D86380eA2646E3a1B5C55A8b" 37 |38 |
41 | To figure out what functions a contract has to offer, you need an Application Binary Interface, or short ABI, a list 42 | of function signatures of functions you want to call later. Ethers.js uses the ABI to determine what arguments a 43 | function expects and what values it returned when it finished its work. 44 |
45 | 46 |47 | When using Ethers.js, you can define the ABI as an array of strings, where the strings are 48 | Solidity function signatures, just like you would write them in the Solidity programming language. 49 |
50 | 51 |Here is an example of an ABI for one function:
52 | 53 |54 | const abi = [ 55 | "function ownerOf(uint256 tokenId) external view returns (address owner)", 56 | ] 57 |58 |
61 | Functions get defined with the function
keyword followed by a name and then the
62 | arguments in paratheses. Solidity is statically typed and doesn't support floating points but
63 | integer types of different sizes.
64 |
67 | In the example above the function takes one argument of type uint256
and it's named
68 | tokenId
.
69 |
72 | The external
keyword is an access modifier that marks the function as callable from
73 | outside of the contract.
74 |
77 | The view
keyword is crucial too because it tells the EVM that the function won't
78 | modify any on-chain state; it will just read it. view
enables you to call the
79 | function without having a wallet because the Ethereum RPC you use can read all data from its local
80 | copy of the blockchain.
81 |
83 | The returns
keyword tells you what you get back when you call the function. In this
84 | case, it's the owner's address of a token.
85 |
88 | The next step is to create a new contract instance and call the ownerOf
function
89 | defined by the ABI!
90 |
Try it yourself in the editor!
93 | 94 |102 | const smartContract = new ethers.Contract( 103 | contractAddress, 104 | contractAbi, 105 | provider, 106 | ) 107 | const owner = await smartContract.ownerOf(2) 108 | print(owner) 109 |
110 |113 | The owner of the contract, like everything on the blockchain, is located at an address, and this 114 | is just what the function returned. The address could point to another contract that created our 115 | contract, as so called factory contract. The address could also point to an EOA, which is the case 116 | in this example. 117 |
118 | 119 |122 | This lesson taught you about smart contract interaction. How to find them on the blockchain with 123 | the help of a provider and an address and how to call its functions with an ABI. 124 |
125 | 126 |127 | An ABI is just an array of strings, these strings are function signatures like you would write 128 | them in Solidity, the programming language powering Ethereum. 129 |
130 | 131 |132 | If you found these addresses a bit cumbersome to work with, I have good news for you. 133 | The next lesson is about the blockchain equivalent of DNS: 134 | The Etherum Name Service. 135 |
-------------------------------------------------------------------------------- /03-using-ens.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |11 | In the previous lesson, you learned about smart contracts and how to connect to them. The next 12 | step is to make this work easier with ENS. 13 |
14 | 15 |16 | You learned that addresses are to the blockchain what IPs are to the internet. The same goes for 17 | the Ethereum Name Service, short ENS. It's the blockchain equivalent of the Domain Name Service, 18 | or DNS. 19 |
20 | 21 |22 | ENS can be used to make addresses more accessible for humans. This way you can connect to EOAs and 23 | smart contracts with a human readable string. 24 |
25 | 26 |27 | You can register ENS domains just like regular domains at the ENS 28 | service website. 29 |
30 | 31 |
34 | Ethers.js works transparently with ENS, so we can simply replace the address from the last lesson
35 | with an ENS domain that resolves to that address. In case of that address a corresponding domain
36 | is devdao.eth
.
37 |
40 | Try it in the editor. Fetch the balance of the Developer DAO NFT contract and print it. But use
41 | the devdao.eth
ENS domain instead of the address!
42 |
48 | const balance = await provider.getBalance("devdao.eth") 49 | print(ethers.utils.formatUnits(balance) + " ETH") 50 |
51 |54 | Note: Keep in mind, the target blockchain address of a ENS domain can change. So if 55 | you want to make sure that the same address is called every time, use the 56 | address directly. 57 |58 | 59 |
62 | ENS domains are a usability imporvement for the blockchain. Just like DNS domains were for the
63 | internet in general. Remembering devdao.eth
is much easier than a big hex number.
64 |
67 | Ethers.js works transparently with ENS domains, so you can usually drop-in a domain in places 68 | where you need an address. 69 |
70 | 71 |72 | In the next lesson, we will learn about Ethereum Request for Comments, or short ERCs. 73 |
-------------------------------------------------------------------------------- /04-ercs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |11 | When building decentralized systems, one of the most crucial parts is how they interact. You 12 | learned that a smart contract has public functions, but you also need an ABI to 13 | call them. 14 |
15 | 16 |17 | You might be able to reverse engineer the ABI in some way, for example, by reading the 18 | source code. But sadly, not all smart contracts are open source. This makes the task quite 19 | cumbersome. 20 |
21 | 22 |25 | Luckily the creators of Ethereum saw this problem early on and focused on interopt between smart 26 | contracts. The result is the Ethereum request for comments or short ERCs. They can contain specs 27 | for interfaces a smart contract has to implement. 28 |
29 | 30 |31 | The process goes as follows: Things aren't going smoothly for some reason or another, and users 32 | want to solve it. They write an Ethereum Improvement Proposal (EIP) and layout what could be 33 | better. Next, the Ethereum Committee will approve the EIP if it's okay and create an ERC based on 34 | the EIP. 35 |
36 | 37 |38 | This process leads to new ways for smart contract interopt and makes it easier to mix and match 39 | smart contracts in Web3 applications. 40 |
41 | 42 |45 | The most prominent ERCs are ERC-20 for 46 | fungible tokens, commonly known as cryptocurrencies or simply tokens, and 47 | ERC-721 for non-fungible tokens, known as 48 | NFTs. 49 |
50 | 51 |52 | While critical functions of smart contracts are usually bound to specific addresses, many are 53 | external without any permissions so that you can call them via Ethers.js. 54 |
55 | 56 |59 | If you know the address of a smart contract that mints NFTs, you can go and search for an ERC-721 60 | ABI and use it together with the address to call it. 61 |
62 | 63 |
64 | The standardized Solidity interface
for an ERC-721 contract looks like this:
65 |
68 | interface ERC721 { 69 | event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); 70 | event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); 71 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 72 | 73 | function balanceOf(address _owner) external view returns (uint256); 74 | function ownerOf(uint256 _tokenId) external view returns (address); 75 | function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable; 76 | function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; 77 | function transferFrom(address _from, address _to, uint256 _tokenId) external payable; 78 | function approve(address _approved, uint256 _tokenId) external payable; 79 | function setApprovalForAll(address _operator, bool _approved) external; 80 | function getApproved(uint256 _tokenId) external view returns (address); 81 | function isApprovedForAll(address _owner, address _operator) external view returns (bool); 82 | } 83 |84 |
87 | We learned in lesson 2 that we can convert this to an ABI for Ethers.js by simply copying the 88 | function signatures as strings into a JavaScript array. 89 |
90 | 91 |92 | const erc721Abi = [ 93 | "function balanceOf(address _owner) external view returns (uint256)", 94 | "function ownerOf(uint256 _tokenId) external view returns (address)", 95 | "function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable", 96 | "function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable", 97 | "function transferFrom(address _from, address _to, uint256 _tokenId) external payable", 98 | "function approve(address _approved, uint256 _tokenId) external payable", 99 | "function setApprovalForAll(address _operator, bool _approved) external", 100 | "function getApproved(uint256 _tokenId) external view returns (address)", 101 | "function isApprovedForAll(address _owner, address _operator) external view returns (bool)", 102 | ] 103 |104 |
107 | Now, since we don't have covered wallets yet, we are only able to call the view
108 | functions, so let's throw the rest out.
109 |
112 | const erc721ReadOnlyAbi = [ 113 | "function balanceOf(address _owner) external view returns (uint256)", 114 | "function ownerOf(uint256 _tokenId) external view returns (address)", 115 | "function getApproved(uint256 _tokenId) external view returns (address)", 116 | "function isApprovedForAll(address _owner, address _operator) external view returns (bool)", 117 | ] 118 |119 |
122 | Try to get the owner of tokenId
5666
for the NFT contract located at
123 | 0x25ed58c027921E14D86380eA2646E3a1B5C55A8b
, using the ABI we defined above and
124 | print
the result!
125 |
128 | You can use the lookupAddress
method of the provider to get the ENS domain that points to an address.
129 | Try that for the owner address of the token.
130 |
136 | const erc721ReadOnlyAbi = [ 137 | "function balanceOf(address _owner) external view returns (uint256)", 138 | "function ownerOf(uint256 _tokenId) external view returns (address)", 139 | "function getApproved(uint256 _tokenId) external view returns (address)", 140 | "function isApprovedForAll(address _owner, address _operator) external view returns (bool)", 141 | ] 142 | 143 | const contractAddress = "0x25ed58c027921E14D86380eA2646E3a1B5C55A8b" 144 | 145 | const smartContract = new ethers.Contract( 146 | contractAddress, 147 | erc721ReadOnlyAbi, 148 | provider 149 | ) 150 | 151 | const ownerAddress = await smartContract.ownerOf(5666) 152 | 153 | const ownerDomain = await provider.lookupAddress(ownerAddress) 154 | 155 | print(ownerDomain) 156 |
157 |162 | In this lesson you learned about ERCs. How they standardize interfaces and behavior to help you 163 | using these contracts and also allow other contrats to interact with them. 164 |
165 | 166 |167 | We also converted a Solitidy interface defined in the ERC-721 to a ABI you can use with Ethers.js. 168 |
169 | 170 |171 | In the next lesson, you will build your very first Web3 app! 172 |
-------------------------------------------------------------------------------- /05-example-app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |10 | Now that you know how to connect to the Ethereum network with its smart contracts and find 11 | out which functions a smart contract provides, you can finally implement our first small app! 12 |
13 | 14 |This lesson is more hands-on, which means you have to build your app on your own!
17 | 18 |19 | Since you didn't learn about wallets, you can't change anything on the blockchain, but 20 | you can read what's already been written on it by other people around the world. But you get some 21 | pointers, so you know how to start. Also, I've already written the app so that you can check out a 22 | working example. 23 |
24 | 25 |28 | The app is an NFT owner finder. A frontend (a simple HTML page is 29 | enough) for the ERC271 specification. You already used this spec in the previous lesson. 30 |
31 | 32 |33 | The idea is a user can enter a contract address and token ID, and the app will ask the 34 | Ethereum network for the address of the token owner. 35 |
36 | 37 |38 | Bonus points for additional information you display in that app: 39 |
40 | 41 |57 | This lesson concludes the first part of this course. You learned most of the things you can do 58 | without your wallet. 59 |
60 | 61 |62 | You learned about the basic architecture of the Ethereum network how to connect to it via public 63 | RPCs and Ethers.js and how to do fundamental interactions with smart contracts on the chain. 64 |
65 | 66 |67 | You also got introduced to the Ethereum Name Service, which makes interactions with addresses 68 | easier. 69 |
70 | 71 |72 | In this final lesson, you even build your first app! 73 |
74 | 75 |78 | The next part of this course will introduce you to wallets and transactions, so you can finally 79 | make a change! You will do all this with test networks, so you don't have to pay the enormous gas 80 | fees currently hampering the Ethereum network. 81 |
-------------------------------------------------------------------------------- /06-public-and-private-keys.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |10 | I wanted to start part two of this course with crypto-wallets. Because they will be the software, 11 | you need to install and set up for part II. But I thought the keys are only a part of the things a 12 | crypto-wallet manages for you and the most important part. So, I think keys should have their own 13 | lesson. 14 |
15 | 16 |17 | This lesson won't go into the details of elliptic curve cryptography (ECC). There are better 18 | resources to understand this topic. If you want to learn the technical details, I recommend 19 | the free ebook Practical Cryptography for Developers that has 20 | 21 | a part that explains ECC 22 | . 23 |24 | 25 |
28 | If I learned one thing about cryptography, it's that you should never ever give away your 29 | private key or seed phrase. If you don't understand anything from the book I linked before 30 | or written in this lesson, at least keep that small piece of know-how in mind. 31 |
32 | 33 |34 | This rule means you should only ever type your private key in a secure crypto-wallet app and never 35 | in a text file on your PC or smartphone. It's too long for the usual human to remember without 36 | much work, so for backup write it down on paper. This way no one who uses your computers 37 | can read it from your hard drive. 38 |
39 | 40 |41 | In some countries, you might fear that the government will be after your keys, but the more likely 42 | threat is your house burning down or water damage. So, make sure you have copies at different safe 43 | locations. 44 |
45 | 46 |47 | If you need a private key for development and tests that you will hard-code in a source file, make 48 | sure you don't use this development key for your everyday crypto dealings. This way, it's not so 49 | bad when your key ends up on GitHub, S3, etc. 50 |
51 | 52 |53 | The same goes for your seed phrase, which is a way to write down a private key as a list of short 54 | words. As a developer, you work directly with private keys, but end-users use their private key in 55 | the form of a seed phrase when they move it around between crypto-wallets and paper. 56 |
57 | 58 |59 | It's also good to know that you shouldn't show people your addresses and public keys without a 60 | good reason. While no one can directly steal your tokens without your private key, an attacker 61 | can send tokens to your address for phishing. These could lead you to some web apps that try to 62 | scam you into using your private key to do something dumb. 63 |
64 | 65 |
68 | A key, private or public, is just some kind of data. In the specific case of ECC, these two keys
69 | are very big numbers. So big that you will store them as string
or
70 | BigInteger
in JavaScript.
71 |
83 | A private key for ECC is a randomly generated integer that can look something like this in hexadecimal:
84 | 57cfa2d774eab59998a0b87d641b504aaefeae12f244db08d77e019e6d90afb9
85 |
88 | In Ethereum and many other blockchain networks, this key must be smaller than a special prime 89 | number. 90 |
91 | 92 |
93 | This big prime number looks like this in hexadecimal:
94 | fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
95 |
98 | The reason why this exact prime number is used is out of the scope of this course (you can 99 | read about it in the book I linked above). But the limit set by that prime number is important! 100 | Not every random integer is a valid private key, and if you want to generate your own, it has to 101 | be smaller than that prime number. 102 |
103 | 104 |105 | let privateKey 106 | 107 | do { 108 | privateKey = generateRandomInteger() 109 | } while(privateKey > 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn) 110 |111 | 112 |
115 | A public key for ECC is two integers that are concatenated together. Both of these integers can 116 | have the private key length, but they aren't random. These two numbers are calculated from the 117 | private key. 118 |
119 | 120 |
121 | A public key can look like this:
122 | 0453a07319d6d7a34d1bf3363415a316c0f5cd4cb5fe49f414b1c9d7b420169b652cf466ed56ec01733a9726ee27017ad66e384eefc2d6897aa61d3157cc1273eb
123 |
126 | The function used to calculate a public key from a private key is based on a specific algorithm 127 | and some predefined parameters. All systems interacting with the Ethereum network have to use the 128 | same algorithm and parameters to get the same results. 129 |
130 | 131 |132 | let privateKey 133 | 134 | do { 135 | privateKey = generateRandomInteger() 136 | } while(privateKey > 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn) 137 | 138 | const publicKey = generatePublicKey(privateKey) 139 |140 | 141 |
144 | A seed phrase, also known as a secret recovery phrase, is a list of 12-24 short random words used 145 | to generate one or more private keys and, in turn, public keys and addresses in the end. 146 |
147 | 148 |
149 | A seed phrase could look like this:
150 | forget wing follow flip swallow achieve correct view dinner witness hybrid proud
151 |
154 | While you can generate a private key directly, many crypto-wallet apps use a seed phrase to 155 | generate them for you. Many people use multiple addresses, and if you're developing with Ethereum 156 | and using it for day-to-day things, you will at least need two addresses and two private keys. 157 |
158 | 159 |160 | The idea of a seed phrase is that it's a random list of words, but the algorithm to generate 161 | multiple private keys from that phrase is deterministic. This allows to generate multiple keys 162 | from one phrase and recover all these keys from one seed phrase. Otherwise, you would have to 163 | write down every single private key on its own. 164 |
165 | 166 |167 | const seedPhrase = [ 168 | "forget", "wing", "follow", 169 | "flip", "swallow", "achieve", 170 | "correct", "view", "dinner", 171 | "witness", "hybrid", "proud" 172 | ] 173 | 174 | const keyGenerator = initKeyGenerator(seedPhrase) 175 | 176 | const keys = [] 177 | for(let i = 0; i < 10; ++i) { 178 | const privateKey = keyGenerator(i) 179 | const publicKey = generatePublicKey(privateKey) 180 | const address = keccak256(publicKey).toString().slice(0,20) 181 | keys.push({ privateKey, publicKey, address}) 182 | } 183 |184 |
187 | The downside of this is that if your seed phrase gets stolen, all private keys generated from it 188 | are stolen too. This means everything true for your private key is also true ten-fold for your 189 | seed phrase because it's the same as multiple private keys. 190 |
191 | 192 |193 | Never write your seed phrase down on your PC or smartphone outside of a crypto-wallet app, 194 | never store it in an S3 bucket, or GitHub, etc. To recover your keys when you lose your 195 | smartphone or laptop, or they break, you can write the seed phrase on a piece of paper and store 196 | it in a safe location. 197 |
198 | 199 |202 | So, you know what the keys are and how you should handle them, but what exactly is their purpose? 203 |
204 | 205 |206 | Private and public keys are used for different tasks. Their usage follows from the fact that 207 | everyone can have your public keys, and no one should ever have your private keys. 208 |
209 | 210 |213 | The private key is used mainly to sign data. Signing means you attach a signature to the data. 214 | A signature is created with a signature algorithm that uses your private key and the data that 215 | needs to be signed. 216 |
217 | 218 |219 | The idea is that the signature data can't be generated without having the private key. 220 |
221 | 222 |
223 | A signature could look like this in its Base64 version:
224 | MEQCIEamErEp0wjW2nBCwPJyMWB1UEb8UHaEFeUDko88MOs/AiB5daIS5j1stXRetBsEWbvd0TeoYsfucmADmxFUxbE2oQ==
225 |
229 | The public key is used to verify that signature. If you sign something with a private key, the 230 | related public key, in combination with a signing algorithm, the signature, and the signed data, 231 | will either lead to a "yes, this signature is from the correct private key" or not. 232 |
233 | 234 |235 | Since you are the only one who has your private keys, you are the only one who can create these 236 | signatures. If your keys get stolen, other people can pretend they are the original owners (i. e. 237 | you). If you lose your private key, you can't create correct signatures anymore, and systems with 238 | your public key won't believe that you are indeed who you pretend to be. 239 |
240 | 241 |242 | In Figure 2, you see how the three parts interact with each other. 243 |
244 | 245 |255 | You learned you can use the public key to verify a signature, but that's not all it can do. The 256 | public key can also encrypt a message that only the corresponding private key can decrypt. 257 |
258 | 259 |260 | If you want to use asymetric encryption to communicate privately, you have to exchange public keys. 261 | Everyone with your public key can then send you messages that only you can read. 262 |
263 | 264 |265 | Figure 3 shows the simplified process. For performance reasons, the message in that picture is 266 | usually not the actual data you want to send, but a symmetric encryption key that will be 267 | exchanged with the private key holder and then used to encrypt/decrypt all messages flowing 268 | between the two parties. 269 |
270 | 271 |281 | In this lesson, you learned that keys are just numbers. Very big numbers, that have specific 282 | properties. They are often displayed in hexadecimal, which makes things a bit confusing for 283 | beginners. 284 |
285 | 286 |287 | These keys are used together with ECC-based algorithms and in the case of Ethereum, with a 288 | specific set of parameters that are the same in the whole Ethereum network to ensure, all 289 | participants have the same results when signing and verifying data. 290 |
291 | 292 |293 | In the next lesson, you will learn more about 294 | externally owned accounts, and how they relate to the keys we discussed here. 295 |
-------------------------------------------------------------------------------- /07-externally-owned-accounts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |11 | In the last lesson we talked about keys, what they are, how they are used, and how they relate to 12 | each other. 13 |
14 | 15 |16 | In this lesson, you will learn how keys are related to addresses and how they together form the 17 | basis for externally owned accounts (EOAs). 18 |
19 | 20 |23 | In Part I, you learned that addresses are to a blockchain are like IPs are to the internet, but 24 | how are addresses related to keys? 25 |
26 | 27 |
28 | An address is a 20 byte (160 bit) long integer that gets calculated from the public key and it can
29 | look like this:
30 | 0xdd00Cc906B93419814443Bb913949d503B3DF3c4
31 |
41 | The 0x usually indicates a hex number, and the length was chosen to allow for enough addresses in 42 | the future while still being short enough for everyday usage. 43 |
44 | 45 |46 | The public key gets hashed with 47 | 48 | Keccak-256 49 | , and the first 20 bytes of this hash become the address for an EOA controlled by the related 50 | key pair. 51 |
52 | 53 |56 | Ethers comes with a few utility functions that allow you to create an address from a public key 57 | step by step. 58 |
59 | 60 |
61 | The example comes with a random pair of keys, and you have to create the address yourself. Keep in
62 | mind that the public key comes with a 0x04
prefix that indicates its in the
63 | uncompressed version and is not part of the key.
64 |
67 | The functions you need are: 68 |
69 | 70 |ethers.utils.hexDataSlice()
to cut parts of the key and hash.ethers.utils.keccak256()
to create the hash that includes the address.
76 | You can look at wallet.address
to check if the key is correct.
77 |
85 | const keyWithoutPrefix = hexDataSlice(publicKey, 1) // remove 0x04 86 | const hashedKey = keccak256(keyWithoutPrefix) 87 | const myAddress = hexDataSlice(hashedKey, 12) 88 | print(address) 89 | print(myAddress) 90 |
91 |94 | Ethereum uses letter casing in the address as a checksum. While the addresses work independently 95 | of casing, it is sometimes used to check the integrity of an address. 96 |
97 | 98 |101 | As the name implies, an EOA is an account that is controlled from outside the blockchain network. 102 | The private key that was used to create the address isn't on chain and the person owning it is 103 | also external to the blockchain network. 104 |
105 | 106 |107 | The arrows in figure 2 show who controls which address and where, in relation to the blockchain 108 | network, each controller is located. 109 |
110 | 111 |119 | The address controlled by an external private key is an EOA, the other addresses are controlled by 120 | smart contracts, and thus, not EOA. 121 |
122 | 123 |126 | Now, that we know how keys relate to addresses and what EOAs are, let's look at an example. Say 127 | you want to send tokens from one address to another. 128 |
129 | 130 |131 | You have to send your address, the target address, and the amount of tokens you want to spend, to 132 | the Ethereum network. You have to send your public key too, so the nodes on the network can verify 133 | that it's a legit transaction. 134 |
135 | 136 |137 | The transaction is checked for two facts. 138 |
139 | 140 |146 | Since your address is generated from your public key, the Ethereum nodes know if you send a key 147 | that doesn't belong to your address. They can run the hash algorithm on the public key, look at 148 | the first 20 bytes, and compare them to your address. 149 |
150 | 151 |152 | The next step is to verify that you also have the correct private key. Only private key owners can 153 | spend money of an address. 154 |
155 | 156 |157 | To check this, the nodes will send you a random message and you will sign it with the private key 158 | you used to generate the public key. Since they already have your public key, they can use it to 159 | check if your signature is correct. If you used the wrong private key to sign, this check will 160 | fail and your trasaction will be rejected. 161 |
162 | 163 |164 | There is still risk here. The Ethereum network will take any vaild address as a target for your 165 | transaction. If you make a typo, your funds may end up at an address that no one has a private key 166 | for and they are lost. 167 |
168 | 169 |172 | Receiving tokens is more easy, but doesn't come without risk either. 173 |
174 | 175 |176 | Anyone can send funds to any valid address. So, if someone knows your address, they can send you 177 | tokens, wether you like it or not. 178 |
179 | 180 |181 | The usual case is that you sold a good or service, and someone will pay you by sending tokens to 182 | your address. You have to make sure your address doesn't have any typos, but that's it. 183 |
184 | 185 |186 | Special cases are airdrops. When a project or person does an airdrop, it means they send tokens to 187 | addresses that have specific criteria. Like, used a service, or held a special NFT before some 188 | date. 189 |
190 | 191 |192 | Usually an airdrop is a good thing, because you get free tokens. But scammers use airdrops to 193 | phish you. They randomly send you some token which might lead you to investigate. You can end up 194 | on a suspicious site that asks you for your private key or to sign a scam transaction. 195 |
196 | 197 |200 | EOAs are addresses controlled by an external private key instead of a on-chain smart contract. 201 |
202 | 203 |204 | The relation between private key, public key, and address allows the blockchain network to verify 205 | all transactions can only come from controllers of the correct private keys. 206 |
207 | 208 |209 | Sending tokens around still bears the risk of typos. Also, when you lose your private key or it 210 | gets stolen, all tokens on that address are lost. This is especially crucial for developers! Make 211 | sure you always use private keys dedicated to development only, so if you accidentally upload them 212 | to a public code repository, nothing of value is stolen. 213 |
214 | 215 |216 | In the next lesson, you will learn about wallets and 217 | how to set up your own via Ethers.js. 218 |
-------------------------------------------------------------------------------- /08-crypto-wallet-setup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |11 | We know how public key cryptography works, even if just in essence. We know that a EOA is a 12 | blockchain address that is controlled by the holder of a related public/private key pair. But how 13 | come crypto wallets into play? 14 |
15 | 16 |19 | A crypto wallet, or simply wallet, is a mechanism to manage your keys, some are even able to 20 | manage your blockchain connections. 21 |
22 | 23 |24 | There are different types of wallets, so let's get a small overview on the essentials. 25 |
26 | 27 |30 | A wallet app is a dedicated application that manages your keys and blockchain connections. Some 31 | can connect to different types of blockchains, some only understand one specific blockchain 32 | network. 33 |
34 | 35 |36 | Since a wallet app is software, it comes with the danger of being hacked if it's installed on a 37 | device that has an internet connection. 38 |
39 | 40 |41 | MetaMask is probably the most popular wallet app for the Ethereum network. You can enter your keys 42 | into it, or even let it generate keys for your with a seed phrase. It allows you to add and remove 43 | RPCs for different chains, and comes preconfigured with Ethereum mainnet and it's test networks. 44 |
45 | 46 |47 | To connect a wallet app with a Web3 app, you either need a browser extension that links the wallet 48 | you installed on your PC or Mac with the browser or, if you're using the mobile version, you need 49 | to scan a QR code displayed on the Web3 app. 50 |
51 | 52 |55 | A paper wallet is simply a piece of paper with all your keys, addresses, or your seed phrase 56 | written down. It can't do much, since it's not software, but at least you don't have to remember 57 | all this information on your own. 58 |
59 | 60 |61 | With a paper wallet you can't send any tokens, but if you tell people one of the addresses you 62 | written on it, you can at least receive them. 63 |
64 | 65 |66 | Also, it can't get hacked online, because it can't be connected to the internet. This makes 67 | paper wallet quite safe. Depending on the material of the wallet and the risk of burglaries in 68 | your location, it can be susceptible to other problems. Also, like everything else, you can simply 69 | lose it. 70 |
71 | 72 |75 | Hardware wallets are devices that store your keys, addresses, and seed phrases. They keep your 76 | private keys always on the device and never make them public. If you need to sign a message with a 77 | private key, you have to send the message to the wallet and it will respond with the signature. 78 |
79 | 80 |81 | Hardware wallets have standardized interfaces and work in tandem with wallet apps. So, you can see 82 | them as an extension of a wallet app that makes it more secure. 83 |
84 | 85 |88 | Since all these digital wallets talk to each other and DApps via standardized interfaces, it might 89 | not come as a surprise that there is an API for this. 90 |
91 | 92 |93 | What a software library is to an app, is a programmatic wallet to an wallet app. It's just a piece 94 | of software that is controlled with code; no UI, no CLI, just code. 95 |
96 | 97 |
98 | Ethers.js offers such a programmatic wallet with its concepts of Singers, which are an abstraction
99 | over different account types. One of them is Wallet
.
100 |
103 | Wallet
is a class you can create an object from that works directly with an RPC. This
104 | way you can actually write something on the blockchain without installing additional software!
105 |
110 | In Part 1 of this course, we talked about how crypto wallets form a layer between your browser and 111 | the blockchain network of your choice. Figure 1 shows where a wallet is usually located in the 112 | stack. 113 |
114 | 115 |116 | The blockchain connection with wallet part of the image shows that the wallet handles the 117 | connection to the RPC, and the browser doesn't know anything about it. 118 |
119 | 120 |128 | As you just learned, Ethers.js can work as a wallet too! So, we can connect to a RPC with 129 | Ethers.js and also use it to sign transactions, which are the mechanism to write on the 130 | blockchain. 131 |
132 | 133 |136 | If you're developing with a blockchain, never use private keys that control addresses with your 137 | personal assets on it! Create one or more development keys, via a seed phrase or the random key 138 | generator of Ethers.js. 139 |
140 | 141 |
142 | If you have to do transactions in development that require tokens, be it for deployments or simply
143 | to test your code, you need to save the keys somewhere for later use. If you don't need any tokens
144 | for an action, you can just take a new random Wallet
every time.
145 |
148 | The following example creates a random Wallet
every time you run it. Copy one of the
149 | private keys and use it as your development key.
150 |
158 | Note: You shouldn't copy your private keys around and save them in an insecure way, but 159 | since a development key doesn't have any tokens, it's not a problem if it gets stolen. Just create 160 | a new one and delete the old one if that happens. 161 |162 | 163 |
166 | Let's use that key! Try to construct a new Wallet
object, pass it your copied private
167 | key from above, and print the public key and address it generates.
168 |
171 | Also, copy the address, so you have it handy for the later lessons. 172 |
173 | 174 |177 | const wallet = new ethers.Wallet( 178 | "0x350690562a6c31051d2c9f085e0b91be0a4ac0a3c206998c89ff3cfedf3524d0" 179 | ) 180 | 181 | print(wallet.publicKey) 182 | print(wallet.address) 183 |
184 |189 | Now, that you can create wallets from an existing private key, let's try to connect a wallet to a 190 | provider. 191 |
192 | 193 |
194 | To establish a connection the wallet object offers a connect
method which will create
195 | a new wallet that is connected to the provider.
196 |
199 | Try to create a connected wallet and use it's getGasPrice
method to check if the
200 | connection works. Keep in mind that this method is asynchronous, and the price will be a
201 | BigNum
object.
202 |
207 | const wallet = new ethers.Wallet( 208 | "0x350690562a6c31051d2c9f085e0b91be0a4ac0a3c206998c89ff3cfedf3524d0" 209 | ) 210 | 211 | const connectedWallet = wallet.connect(ethers.getDefaultProvider()) 212 | 213 | const gasPrice = await connectedWallet.getGasPrice() 214 | 215 | print(ethers.utils.formatEther(gasPrice) + " ETH") 216 |
217 |222 | In this lesson, you learned about different types of wallets, and that you can use a programmatic 223 | wallet for development. This way, you don't have to install any additional software. 224 |
225 | 226 |227 | You also learned how to connect a wallet with a provider, which will be important for the 228 | following lessons. As I said before, you need a wallet to send transactions to a blockchain 229 | network. 230 |
231 | 232 |233 | In the next lesson, you will learn about test networks and how 234 | to request test tokens from token faucets. 235 |
-------------------------------------------------------------------------------- /09-test-networks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |11 | Building software requires you to test before you release. The usual development process goes from 12 | running things on your local computer, to running it on a test system, to running it on the 13 | production system. 14 |
15 | 16 |17 | This process also holds true for Web3 development. You install a local blockchain network on your 18 | own machine to test the basic functionality of your smart contracts and later you deploy the 19 | system onto a test network, to make sure it still works togeher with many other smart contracts 20 | you might use in your application. 21 |
22 | 23 |24 | Test networks enable testing on real infrastructure without spending real tokens, and in turn, 25 | real money. A TX on the Ethereum network can easily cost $10, so when you're just testing and 26 | sending hundreds of TXS a day, this can get costly quick! With free test tokens that's not an 27 | issue anymore. 28 |
29 | 30 |31 | Also, if you accidentally push a development key to a public repository, you won't lose anything 32 | but the worthless test tokens you put on that address. 33 |
34 | 35 |36 | This is why you had to copy a private key in the previous lesson. You need an address you can 37 | reuse so you can get tokens on it and spend them for gas or to do transactions that require 38 | payment. 39 |
40 | 41 |42 | Note: We will go into the details of gas costs later. This lesson is just about connecting 43 | to a test network and getting our first tokens! 44 |45 | 46 |
49 | In Part I of this course, you learned how to use providers to connect to a blockchain network. You
50 | simply called the ethers.getDefaultProvider
method and got a provider to read data
51 | from the chain.
52 |
55 | The default provider connects, by default, to the Ethereum main network. Which is the production
56 | environment of Ethereum. If you want to connect to a test network, you have to use the first
57 | parameter of that method. In our case it will be "goerli"
.
58 |
61 | Note: Görli is one of Ethereum test networks, Ethers.js knows about it, so we can simply 62 | use the name. For other networks that are compatible with Ethers.js, you need more configuration. 63 |64 | 65 |
66 | The code is similar to the last lesson, but this time, I want you to call getChainId
67 | to ensure you're connected to the test network. The correct ID is 5
.
68 |
74 | const wallet = new ethers.Wallet( 75 | "0x350690562a6c31051d2c9f085e0b91be0a4ac0a3c206998c89ff3cfedf3524d0" 76 | ) 77 | 78 | const provider = ethers.getDefaultProvider("goerli") 79 | 80 | const connectedWallet = wallet.connect(provider) 81 | 82 | const chainId = await connectedWallet.getChainId() 83 | 84 | print(chainId) 85 |
86 |91 | Now that you know how to connect to a test network, we will go back to the question why I asked 92 | you to copy a private key and address. 93 |
94 | 95 |96 | On blockchain networks you have to pay for writing actions, which means sending transactions. If 97 | you send an TX from an address that doesn't own enough of the networks native token, your TX won't 98 | get executed. So, if you create random private keys for development all the time, they will never 99 | have any tokens to pay for anything. 100 |
101 | 102 |103 | To fix this, you create one or more private key for development, load them up with tokens, and 104 | use them to pay for your TXS. While you have to buy tokens on the main network, you can get them 105 | for free from a token faucet. 106 |
107 | 108 |109 | A faucet is a website, where you enter the address of your development account, and it will send 110 | you test network tokens for free. 111 |
112 | 113 |114 | Choose one of the following faucets to request test tokens for the address that belongs to the 115 | private key you copied in the last lesson. 116 |
117 | 118 |130 | If your choosen faucet accepted your request, you want to check out if it worked and you got your 131 | tokens. You can do this in multiple ways. One is to go on 132 | Etherscan, a blockchain explorer, 133 | enter the address you used in the faucet and search for it. 134 |
135 | 136 |137 | Note: Etherscan is a search engine for addresses. Everything on-chain is public and you can 138 | browse it freely. 139 |140 | 141 |
142 | The second way is to check the balance programmatically with Ethers.js. So, try it yourself.
143 | Connect to the Görli testnet, and call the getBalance
method on your wallet. It is
144 | asynchronous and returns a BigNum
.
145 |
150 | const wallet = new ethers.Wallet( 151 | "0x350690562a6c31051d2c9f085e0b91be0a4ac0a3c206998c89ff3cfedf3524d0" 152 | ) 153 | 154 | const provider = ethers.getDefaultProvider("goerli") 155 | 156 | const connectedWallet = wallet.connect(provider) 157 | 158 | const balance = await connectedWallet.getBalance() 159 | 160 | print(`${connectedWallet.address} owns ${ethers.utils.formatEther(balance)} ETH`) 161 |
162 |
165 | If everything went correctly, the balance of your address should be higher than 0
.
166 |
171 | In this lesson you learned what tests networks are and how they fit inside your development 172 | processes. Main networks are the production environment of blockchain networks, and test networks 173 | are, well, the test environments. 174 |
175 | 176 |177 | You also learned that these test networks come with their own test tokens and how to request them 178 | from one of the multiple faucets out there. 179 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A basic introduction to Web3 and its concepts. 2 | 3 | The target audience is **frontend developers**, who have at least an average grasp of JavaScript and 4 | Web2 technology. 5 | 6 | > If you don't know much about Web development, because you come from another industry or you're 7 | > just beginning your programmer journey, I strongly recommend checking out 8 | > [FreeCodeCamp](https://www.freecodecamp.org/learn/). After finishing the Web design, JavaScript 9 | > algorithms, and front end development courses, you should be up to speed to take this Web3 course. 10 | 11 | **This course is in progress and help is appreciated!** 12 | 13 | ## Lessons 14 | 15 | This course goes step by step through the Web3 concepts from a Web apps point of view. So, (almost) 16 | **no Solidity or dev-tools are required** for the first two parts. 17 | 18 | You are **just writing JavaScript for the browser**. 19 | 20 | There is even a small code editor that lets you **try out code right on the page**. 21 | 22 | Every part finishes with an example app where you can apply your new knowledge right away. 23 | 24 | ### Part I: Reading Data from a Blockchain Network 25 | 26 | The first part is about the basics, connecting to a blockchain network, reading data, etc. 27 | You only need a modern browser and that's it. 28 | 29 | - [00 Connecting to a Blockchain Network](https://kay-is.github.io/web3-from-zero/00-connect-to-blockchain.html) 30 | - [01 Reading an Address Data](https://kay-is.github.io/web3-from-zero/01-read-address-data.html) 31 | - [02 Connecting to Smart Contracts](https://kay-is.github.io/web3-from-zero/02-connect-to-contracts.html) 32 | - [03 Using the Ethereum Name Service](https://kay-is.github.io/web3-from-zero/03-using-ens.html) 33 | - [04 Ethereum Request for Comment](https://kay-is.github.io/web3-from-zero/04-ercs.html) 34 | - [05 First Example App](https://kay-is.github.io/web3-from-zero/05-example-app.html) 35 | 36 | ### Part II: Writing Data to a Blockchain Network (WIP) 37 | 38 | The second part is about getting more interactive, you will need to install a wallet extension to 39 | your browser and create your first accounts. 40 | 41 | - [06 Public & Private Keys](https://kay-is.github.io/web3-from-zero/06-public-and-private-keys.html) 42 | - [07 Externally Owned Accounts](https://kay-is.github.io/web3-from-zero/07-externally-owned-accounts.html) 43 | - [08 Crypto Wallet Setup](https://kay-is.github.io/web3-from-zero/08-crypto-wallet-setup.html) 44 | - [09 Test Networks](https://kay-is.github.io/web3-from-zero/09-test-networks.html) 45 | - 10 Sending Transactions 46 | - 11 Second Example App 47 | 48 | ## Ethereum Edition 49 | 50 | This is the Ethereum edition, which uses the Ethereum network as an example. 51 | 52 | The Ethereum ecosystem is a vast landscape if you're just starting out, you might be dazzled by all the networks, dev environments, wallets, and whatnot. 53 | 54 |  55 | 56 | This introduction will help you to make sense of this all, talking about one concept per lesson. 57 | -------------------------------------------------------------------------------- /boilerplate/editor.js: -------------------------------------------------------------------------------- 1 | import { ethers } from "//unpkg.com/ethers@5.5.1/dist/ethers.esm.min.js" 2 | 3 | window.ethers = ethers 4 | 5 | document.addEventListener("copy", (e) => { 6 | const text_only = document.getSelection().toString() 7 | const clipdata = e.clipboardData || window.clipboardData 8 | clipdata.setData("text/plain", text_only) 9 | clipdata.setData("text/html", text_only) 10 | e.preventDefault() 11 | }) 12 | 13 | const clearHtmlCode = (code) => 14 | code 15 | .trim() 16 | .split("\n") 17 | .map((line) => line.trim()) 18 | .join("\n") 19 | 20 | customElements.define( 21 | "code-editor", 22 | class CodeEditor extends HTMLElement { 23 | connectedCallback() { 24 | const hintElement = this.querySelector("p") 25 | let codeHint = null 26 | if (hintElement) { 27 | codeHint = clearHtmlCode(hintElement.innerHTML) 28 | this.removeChild(hintElement) 29 | } 30 | 31 | const code = clearHtmlCode(this.innerHTML) 32 | 33 | this.innerHTML = ` 34 |${code}
35 | 16 | Please enter the address of a smart contract that implements the ERC271 specification. 17 |
18 | 19 |