How to Debug Anything VideoInstallation & SetupMac & Linux SetupWindows SetupGitpodLocal Development IntroductionOptional Javascript Crash CoursesTiny Javascript RefresherAsynchronous Programming in JavascriptCompiling our SolidityGanache & NetworksIntroduction to Ethers.jsA Note on the await KeywordAdding Transaction OverridesTransaction ReceiptsSending a "raw" Transaction in Ethers.jsInteracting with Contracts in Ethers.jsEnvironment VariablesBetter Private Key ManagementOptional Prettier FormattingDeploying to a Testnet or a MainnetVerifying on Block Explorers from the UIAlchemy Dashboard & The Mempool
How to Debug Anything Video
- Patrick's Original Video
- Tinker and Experiement
- Check the Docs
- Do a web search
- Ask Questions on Forums & Q&A Sites
- Join & Strengthen the community and tool
5 steps to solve any coding problem:
there are four different types of forms and QA sites where the best place to ask:
how to format your question:
(1). Search
(2). Summarizing Title
(3). Introduce the problem first
(4). Add minimalistic code
(5). Learn Markdown(Use backticks)
(6). Use Tags
(7). Read forum rules
Installation & Setup
Mac & Linux Setup
Windows Setup
- WSL
- When working in WSL, use Linux commands instead of Windows commands
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
⚠️ Please use Gitpod as an absolute last resort
Gitpod
- Gitpod
- If using this, NEVER share a private key with real money on Gitpod
- Ideally you figure out the MacOS, Linux, or Windows install though
Local Development Introduction
CMD + K
orCTRL + K
clears the terminal
mkdir ethers-simple-storage-fcc
code .
to open VSCode in a new VSCode window
Optional Javascript Crash Courses
- Import your
SimpleStorage.sol
- Format your solidity code with:
"[solidity]": { "editor.defaultFormatter": "NomicFoundation.hardhat-solidity" }, "[javascript]":{ "editor.defaultFormatter": "esbenp.prettier-vscode" }
In your
.vscode/settings.json
file.Tiny Javascript Refresher
Asynchronous Programming in Javascript
- Asynchronous Programming
synchronous means it just goes one line after another.
// Synchronous // 1. Put popcorn in mic rowave // 2. Wait for popcorn to finish // 3. Pour drinks for eve ryone // Asynchronous // 1. Put popcorn in the mirc rowave // 2. Pour drinks for everyone I // 3. Wait for popcorn to finish
- await keyword
async and await make promises easier to write.
async makes a function return a Promise.
await makes a function wait for a Promise.
async function setupMovieNight() { await cookPopcorn() await pourDrinks() startMovie() } function cookPopcorn() { return Promise(/* some coe here */); }
- Promise in Javascript
- pending: initial state, neither fulfilled nor rejected.
- fulfilled: meaning that the operation was completed successfully.
- rejected: meaning that the operation failed.
A
Promise
is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason.A
Promise
is in one of these states:async function main() { console.log("hi"); let variable = 5; console.log(variable); } main().then(() => process.exit(0)).catch((error) => { console.error(error); process.exit(1); })
Compiling our Solidity
- solc-js
yarn add solc@0.8.7-fixed
Ganache & Networks
- Networks in Metamask
- RPC URL
Introduction to Ethers.js
- Ethers.js
Intalling
npm install --save ethers // or yarn add ethers
Importing
const { ethers } = require("ethers");
Usage
const provider = new ethers.providers.JsonRpcProvider("http://0.0.0. Ø:8545"); const wallet = new ethers.Wallet( "7dbe329dbf45741d3c5f1928e8e301c8358886bf4525e5f69dc2330aØbbe4f63" , provider );
- fs
read file
Installing
yarn add fs-extra
Import
const fs = require("fs-extra");
Usage
const abi = fs.readFileSync("./SimpleStorage_solSimpleStorage.abi", "utf8"); const binary = fs.readFileSync( "./SimpleStorage_sol_SimpleStorage.bin", "utf8" ); const contractFactory = new ethers.ContractFactory(abi, binary, wallet); console.log("Deploying, please wait..."); const contract = await contractFactory.deploy(); console.log(contract);
A Note on the await Keyword
Adding Transaction Overrides
const contractFactory = new ethers.ContractFactory(abi, binary, wallet); console.log("Deploying, please wait..."); const contract = await contractFactory.deploy({ gasPrice: 1000000000000 });
Transaction Receipts
const contractFactory = new ethers.ContractFactory(abi, binary, wallet); console.log("Deploying, please wait..."); const contract = await contractFactory.deploy(); // wait(1) means that you only get a transaction receipt when you wait for a block confirmation. const transactionReceipt = await contract.deployTransaction wait(1) ; console.log("Here is the dep loyment transaction (transaction response): "); console.log(contract.deployTransaction); console.log("Here is the transaction receipt: "); console.log(transactionReceipt);
Sending a "raw" Transaction in Ethers.js
const nonce = await wallet.getTransactionCount() ; const tx = [ nonce: nonce , gasPrice: 20000000000, gasLimit: 1000000, to: null, value: 0, data: "0x608060405234801561001057600080fd5b50610771806100206000396000f3fe608060405234", chainId: 1337, ]; const sentTxResponse = await wallet.sendTransaction(tx); await sentTxResponse.wait(1); console.log(sentTxResponse);
Interacting with Contracts in Ethers.js
Environment Variables
- dotenv
Instailling
yarn add dotenv
Usage
- create file named ”.env“
- code
require("dotenv").config(); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
Better Private Key Management
- wallet.encrypt
Encrypt
const ethers = require("ethers"); const fs = require("fs-extra"); require ("dotenv").config(); async function main() { const wallet = new ethers.Wallet(process.env.PRIVATE_ KEY); const encryptedJsonKey = await wallet.encrypt( process.env.PRIVATE_KEY_PASSWORD, process.env.PRIVATE_KEY ); console.log(encryptedJsonKey); fs.writeFileSync("./.encryptedKey.json", encryptedJsonKey); /* log {' address" : "b1e94f2b209e4f433d994986efc5ca , " id" :"1c04c5f3- d869- -4c3e- 986d- -8c84c1a262f2" "version : 3 , "Crypto'" {"cipherl :"aes-128-ctrl , "cipherparams" :{" iv" :"0b27385c3a7d3d25 f5ab7888cde85aa9} , "ciphertext" :"03 e7a9ba1b29f5577c537dca7b7de714 , "kdf" :"scrypt" , "kdfparams" : {"salt" :"e964335f aa8db2bb65f2b3e6adadc47edf2d9f89b4cb5 , "n" 131072, "dklen" 32, "p'":1," r":8}, "mac" :"68fba984 53703bd5c4437320436391cc529d84300544263bdc599c68e327"}} */ }
Decrypt
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL); // const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider) ; const encryptedJson = fs.readFileSync("./.encryptedKey.json", "utf8"); let wallet = new ethers.Wallet.fromEncryptedJsonSync( encryptedJson, process.env.PRIVATE_KEY_PASSWORD ); wallet = await wallet.connect(provider);
The Pledge I solemnly swear, that I will never place a private key or secret phrase or mnemonic in a .env file that is associated with real funds. I will only place private keys in a .env file that have ONLY testnet ETH, LINK, or other cryptocurrencies. When I'm testing and developing, I will use a different wallet than the one associated with my real funds. I am aware that if I forget a .gitignore and push my key/phrase up to GitHub even for a split-second, or show my key/phrase to the internet for a split second, it should be considered compromised and I should move all my funds immediately. If I am unsure if my account has real funds in it, I will assume it has real funds in it. If I assume it has real funds in it, I will not use it for developing purposes. I am aware that even if I hit add account on my metamask (or other ETH wallet) I will get a new private key, but it will share the same secret phrase/mnemonic of the other accounts generated in that metamask (or other ETH wallet). Pledge Additions For this course, I will only use funds associated with a brand new never-before-used metamask (or other ETH wallet). I am aware that my account associated with my private key is the same on testnets that it is on mainnets. If I must use a private key associated with real funds in the future, until I am 100% sure what I am doing I will always either: Use the encryption methods Patrick showed (ideally) Use some better encryption stuff Patrick didn't show Use the command line way to pass private keys, and delete my command line history right after If I never actually deploy anything to mainnet myself or work with a private key with real funds, I do not need to be concerned. EDIT Look at all you safe people! I'd like all your comments if I could, but love how you're all being safe!! Keep it up!
Optional Prettier Formatting
- Prettier
- install prettier
- create file named ”.prettierrc“.(this file will take precedent over the default configuration)
npm install --save-dev --save-exact prettier
Deploying to a Testnet or a Mainnet
- Alchemy
alchemy has a node as a service, and allows us to connect to any blockchain that they support for.
CTRL + C
stops any terminal command