diff --git a/.github/actions/generate-resources/.gitignore b/.github/actions/generate-resources/.gitignore new file mode 100644 index 0000000..c3a2b5f --- /dev/null +++ b/.github/actions/generate-resources/.gitignore @@ -0,0 +1,2 @@ +node_modules +*.lock \ No newline at end of file diff --git a/.github/actions/generate-resources/.prettierrc b/.github/actions/generate-resources/.prettierrc new file mode 100644 index 0000000..97dcd75 --- /dev/null +++ b/.github/actions/generate-resources/.prettierrc @@ -0,0 +1,9 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "proseWrap": "always" +} diff --git a/.github/actions/generate-resources/README.md b/.github/actions/generate-resources/README.md new file mode 100644 index 0000000..e00544a --- /dev/null +++ b/.github/actions/generate-resources/README.md @@ -0,0 +1,78 @@ +# Generate RESOURCES.md Action + +This action reads data from the Developer DAO Airtable and puts its content into RESOURCES.md. + +## Authors + +- [@gjsyme](https://github.com/gjsyme) +- [@codingwithmanny](https://github.com/codingwithmanny) + +## Requirements + +- NVM or Node `v16.13.0` + +## Setup + +```bash +yarn install; +``` + +## Tests + +```bash +yarn test; +``` + +## How To Run Locally + +**NOTE:** `DO NOT` run this from within the `actions/generate-resources` folder, it will overwrite this `RESOURCES.md`. + +**NOTE:** You need to have the [nektos/act](https://github.com/nektos/act) cli on your system for this to work as it has been developed +Once installed, you can call the below command. + +**NOTE:** You need to create the github token for yourself in order to test on your local machine. As it is your github token, you will only be able to push to repos you have write access to. + +```bash +act -v -s GITHUB_TOKEN=YOUR_USER_TOKEN -j refresh +``` + +## Example GitHub Action Usage + +```yaml +jobs: + refresh: + name: Scheduling + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Enable node + uses: actions/setup-node@v2 + with: + node-version: 16.x + + - name: Install Yarn + run: npm i -g yarn + + # hack given that we don't have top-level dependencies + # go into the directory and install (resets dir before next command is run) + - name: Install dependencies + run: cd ./.github/actions/generate-resources && yarn install --frozen-lockfile + + - name: Run action + uses: ./.github/actions/generate-resources + + - name: Prettier clean up + run: ./.github/actions/generate-resources/node_modules/.bin/prettier RESOURCES.md --write + + # note the harcode of the repo name. this could be done better if we wanted to use this repeatedly, but seems like a one-off + # if you're testing, make sure that the repo organization and repo name (gjsyme and resources, respectively, here) are replaced by something + # that something needs to be writable by a user with your permissions (from your GH token) + - name: Commit changes + run: | + git add RESOURCES.md + git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/gjsyme/resources + git -c user.name="D_D RESOURCE BOT" -c user.email="resource_bot@users.noreply.github.com" commit -m 'Refresh RESOURCES.md from Airtable' || echo 'No changes to commit' + git push origin || echo 'No changes to commit' +``` \ No newline at end of file diff --git a/.github/actions/generate-resources/__tests__/main.test.js b/.github/actions/generate-resources/__tests__/main.test.js new file mode 100644 index 0000000..617ca00 --- /dev/null +++ b/.github/actions/generate-resources/__tests__/main.test.js @@ -0,0 +1,271 @@ +// Mocks +// **NOTE:** Mocks needs to be init before main is imported +// ex: ReferenceError: Cannot access 'mockAirtableBase' before initialization +// ======================================================== +// To suppress the console.error +global.console = { + ...jest.requireActual('console'), + error: jest.fn(), +}; + +/** + * + */ +const mockAirtableEachPageNextPage = jest.fn(); + +/** + * + */ +const mockAirtableEachPage = jest.fn(); + +/** + * + */ +const mockAirtableSelect = jest.fn(() => ({ + eachPage: mockAirtableEachPage, +})); + +/** + * + */ +const mockAirtableBase = jest.fn(() => { + return () => ({ + select: mockAirtableSelect, + }); +}); + +/** + * + */ +jest.mock('airtable', () => { + return jest.fn().mockImplementation(() => ({ + base: mockAirtableBase, + })); +}); + +/** + * + */ +const mockWriteFileSync = jest.fn(); + +/** + * + */ +jest.mock('fs', () => { + return { + writeFileSync: mockWriteFileSync, + }; +}); + +/** + * + */ +afterEach(() => { + jest.clearAllMocks(); +}); + +// Imports +// ======================================================== +const main = require('../main'); + +// Tests +// ======================================================== +/** + * Failure - fetchAirtableData + */ +test('[Failure]: fetchAirtableData handles errors and returns empty array', async () => { + // Setup + + // Pre Expectations + expect(mockAirtableBase).not.toHaveBeenCalled(); + + // Init + const result = await main.fetchAirtableData(); + + // Post Expectatations + expect(mockAirtableBase).not.toHaveBeenCalled(); + expect(result).toEqual([]); +}); + +/** + * Success - fetchAirtableData + */ +test('[Success]: fetchAirtableData returns array', async () => { + // Setup + mockAirtableEachPage.mockImplementation((callback) => { + callback( + [ + { + _rawJson: 'entry1', + }, + { + _rawJson: 'entry2', + }, + ], + mockAirtableEachPageNextPage, + ); + }); + + // Pre Expectations + expect(mockAirtableBase).not.toHaveBeenCalled(); + + // Init + const result = await main.fetchAirtableData('random'); + + // Post Expectatations + expect(mockAirtableBase).toHaveBeenCalledWith(main.AIRTABLE_RESOURCE_BASE); + expect(mockAirtableBase).toHaveBeenCalled(); + expect(mockAirtableSelect).toHaveBeenCalled(); + expect(mockAirtableEachPage).toHaveBeenCalled(); + expect(mockAirtableEachPageNextPage).toHaveBeenCalled(); + expect(result).toEqual(['entry1', 'entry2']); +}); + +/** + * Failure - init + */ +test('[Failure]: init returns a default README.md', async () => { + // Setup + const airTableResourceData = [ + { + _rawJson: { + fields: { + Title: 'Title1', + Source: 'Source1', + Author: ['unknownAuthorId1'], + Summary: 'Summary1', + }, + }, + }, + ]; + mockAirtableEachPage.mockImplementation((callback) => { + callback(airTableResourceData, mockAirtableEachPageNextPage); + }); + const README_RESOURCE_BODY = airTableResourceData.map( + (item) => + `- [${item?._rawJson?.fields?.Title}](${ + item?._rawJson?.fields?.Source + })\n\n Author${ + item?._rawJson?.fields?.Author?.length > 1 ? 's' : '' + }: ${item?._rawJson?.fields?.Author?.map(() => '')}${ + item?._rawJson?.fields?.Summary + ? '\n' + item?._rawJson?.fields?.Summary + : '' + }`, + ); + + // Pre Expectatations + expect(mockAirtableBase).not.toHaveBeenCalled(); + + // Init + await main.init(); + + // Post Expectatations + expect(mockAirtableBase).toHaveBeenCalled(); + expect(mockWriteFileSync).toHaveBeenCalled(); + expect(mockWriteFileSync).toHaveBeenCalledWith( + './README.md', + `${main.README_RESOURCE_HEADER}${README_RESOURCE_BODY}`, + ); +}); + +/** + * Success - init + */ +test('[Success]: init returns full README.md', async () => { + // Setup + const airTableAuthorData = [ + { + _rawJson: { + id: 'unknownAuthorId1', + fields: { + Name: 'AuthorName1', + }, + }, + }, + { + _rawJson: { + id: 'unknownAuthorId2', + fields: { + Name: 'AuthorName2', + }, + }, + }, + { + _rawJson: { + id: 'unknownAuthorId3', + fields: { + Name: '', + }, + }, + }, + ]; + const airTableResourceData = [ + { + _rawJson: { + fields: { + Title: 'Title1', + Source: 'Source1', + Author: ['unknownAuthorId1', 'unknownAuthorId2', 'unknownAuthorId3'], + Summary: 'Summary1', + }, + }, + }, + ]; + + mockAirtableBase.mockImplementation(() => { + return (tableName) => { + if (tableName === 'Author') { + return { + select: () => ({ + eachPage: (callback) => { + callback(airTableAuthorData, mockAirtableEachPageNextPage); + }, + }), + }; + } + return { + select: () => ({ + eachPage: (callback) => { + callback(airTableResourceData, mockAirtableEachPageNextPage); + }, + }), + }; + }; + }); + + const authorMap = {}; + airTableAuthorData.forEach((item) => { + if (item?._rawJson?.id && item?._rawJson?.fields) { + authorMap[item?._rawJson?.id] = item?._rawJson?.fields; + } + }); + + const README_RESOURCE_BODY = airTableResourceData.map( + (item) => + `- [${item?._rawJson?.fields?.Title}](${ + item?._rawJson?.fields?.Source + })\n\n Author${ + item?._rawJson?.fields?.Author?.length > 1 ? 's' : '' + }: ${item?._rawJson?.fields?.Author?.map( + (authorId) => authorMap[authorId]?.Name ?? '', + )}${ + item?._rawJson?.fields?.Summary + ? '\n' + item?._rawJson?.fields?.Summary + : '' + }`, + ); + + // Pre Expectatations + expect(mockAirtableBase).not.toHaveBeenCalled(); + + // Init + await main.init(); + + // Post Expectatations + expect(mockAirtableBase).toHaveBeenCalled(); + expect(mockWriteFileSync).toHaveBeenCalledWith( + './README.md', + `${main.README_RESOURCE_HEADER}${README_RESOURCE_BODY}`, + ); +}); diff --git a/.github/actions/generate-resources/action.yml b/.github/actions/generate-resources/action.yml new file mode 100644 index 0000000..bb43e0d --- /dev/null +++ b/.github/actions/generate-resources/action.yml @@ -0,0 +1,5 @@ +name: 'generate resources' +description: 'Read Developer DAO Airtable and generate README.md' +runs: + using: 'node12' + main: 'init.js' \ No newline at end of file diff --git a/.github/actions/generate-resources/init.js b/.github/actions/generate-resources/init.js new file mode 100644 index 0000000..9cb44c9 --- /dev/null +++ b/.github/actions/generate-resources/init.js @@ -0,0 +1,8 @@ +// Imports +// ======================================================== +const main = require('./main'); + +/** + * + */ +main.init(); \ No newline at end of file diff --git a/.github/actions/generate-resources/main.js b/.github/actions/generate-resources/main.js new file mode 100644 index 0000000..2acd65b --- /dev/null +++ b/.github/actions/generate-resources/main.js @@ -0,0 +1,143 @@ +// Imports +// ======================================================== +const Airtable = require('airtable'); +const fs = require('fs'); + +// Constants +// ======================================================== +// airtable resources managed by @kempsterrrr +// these should be replaced by secrets other than these values +const AIRTABLE_READONLY_KEY = 'keyDaaDlZelNrerXQ'; +const AIRTABLE_RESOURCE_BASE = 'appPP6MpO5hrfQwqI'; +const RESOURCE_HEADER = `# Resources\n\n`; + +// Config +// ======================================================== +const airtable = new Airtable({ apiKey: AIRTABLE_READONLY_KEY }); + +// Functions +// ======================================================== +/** + * + * @param {*} tableName + * @returns + */ +const fetchAirtableData = async (tableName) => { + let DATA = []; + try { + if (!tableName) throw new Error('Invalid name.'); + + await airtable + .base(AIRTABLE_RESOURCE_BASE)(tableName) + .select() + .eachPage((records, fetchNextPage) => { + DATA = records + ? [...DATA, ...records.map((item) => item ? item._rawJson || '' : '')] + : DATA; + fetchNextPage(); + }); + } catch (error) { + console.error(`ERROR: Fetching '${tableName}''`, { error }); + } + + return DATA; +}; + +/** + * + * @param {*} authorTwitter a string containing the twitter handle possibly with other undesired content + * @returns the string twitter handler from the input + */ +const cleanTwitterString = (authorTwitter) => { + if (!authorTwitter) return; + // prevent casing weirdness and ensure lowercasae for checking + const compare = authorTwitter.toLowerCase(); + // lazy, ifs for the common distortions + // either the '.com/' construct or starting with @ + if (compare.indexOf('twitter.com') > -1) { + const comIndex = compare.indexOf('.com/') + 5; + return authorTwitter.substring(comIndex, authorTwitter.length); + } + if (compare.startsWith('@')) { + return authorTwitter.substring(1, authorTwitter.length); + } + return authorTwitter; +}; + +/** + * + */ +const init = async () => { + // Retrieve airtable data + const resourcesData = await fetchAirtableData('Resource'); + const authorsData = await fetchAirtableData('Author'); + console.log( + `received ${resourcesData.length} resources and ${authorsData.length} authors`, + ); + + // ids used with resources + const authorMap = {}; + authorsData.filter(item => item).forEach((item) => { + if (item.id && item.fields) { + authorMap[item.id] = { + ...item.fields, + Twitter: cleanTwitterString(item.fields.Twitter) + } + } + }); + + /** + * + * @param {Author} author the airtable author, notably included Name and optional Twitter value + * returns the string (markdown) value for the author + */ + const buildAuthorText = (author) => { + if(author.Twitter){ + return `[${author.Name ? author.Name : 'No name given'}](https://twitter.com/${author.Twitter})`; + } + return author.Name ? author.Name : ''; + } + + const buildSection = (title, resourceList) => { + let resource_string = `## ${title}\n\n`; + return resource_string.concat( + // filter to make up for old node not supporting attribute.?otherAttribute syntax + resourceList.filter(item => (item && item.fields && item.fields.Author)).map( + (item) => ( + `- [${item.fields.Title}](${item.fields.Source})\n\n Author${ + item.fields.Author.length > 1 ? 's' : '' + }: ${item.fields.Author.map((authorId) => buildAuthorText(authorMap[authorId]))}${ + item.fields.Summary ? '\n\n ' + item.fields.Summary : '' + }` + ) + ) + .join('\n\n') + ); + } + + const RESOURCE_BODY = + buildSection('Beginner', resourcesData.filter((item) => (item.fields && item.fields.Level==='Beginner')))+'\n\n' + + buildSection('Intermediate', resourcesData.filter((item) => (item.fields && item.fields.Level==='Intermediate')))+'\n\n' + + buildSection('Advanced', resourcesData.filter((item) => (item.fields && item.fields.Level==='Advanced')))+'\n\n'; + console.log( + 'writing to ./RESOURCES.md', + RESOURCE_HEADER, + RESOURCE_BODY, + ); + + // Write RESOURCES.md file + fs.writeFileSync( + './RESOURCES.md', + `${RESOURCE_HEADER}${RESOURCE_BODY}`, + ); +}; + +// Exports +// ======================================================== +module.exports = { + fetchAirtableData, + init, + AIRTABLE_READONLY_KEY, + AIRTABLE_RESOURCE_BASE, + RESOURCE_HEADER, +}; diff --git a/.github/actions/generate-resources/package.json b/.github/actions/generate-resources/package.json new file mode 100644 index 0000000..d316912 --- /dev/null +++ b/.github/actions/generate-resources/package.json @@ -0,0 +1,21 @@ +{ + "name": "generate-resources", + "version": "0.2.0", + "description": "An action to read Developer DAO Airtable and generate README.md", + "main": "main.js", + "author": "@gjsyme", + "license": "MIT", + "private": false, + "scripts": { + "start": "node main.js && ./node_modules/.bin/prettier README.md --write", + "test": "jest", + "prettier": "./node_modules/.bin/prettier . --write" + }, + "dependencies": { + "airtable": "^0.11.1", + "prettier": "^2.4.1" + }, + "devDependencies": { + "jest": "^27.3.1" + } +} \ No newline at end of file diff --git a/.github/workflows/refresh.yml b/.github/workflows/refresh.yml new file mode 100644 index 0000000..66266ef --- /dev/null +++ b/.github/workflows/refresh.yml @@ -0,0 +1,41 @@ +name: Populate Markdown + +on: + # actual valid github configuration that would get called + schedule: + - cron: '0 0 * * *' + +jobs: + refresh: + name: Scheduling + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Enable node + uses: actions/setup-node@v2 + with: + node-version: 16.x + + - name: Install Yarn + run: npm i -g yarn + + # hack given that we don't have top-level dependencies + # go into the directory and install (resets dir before next command is run) + - name: Install dependencies + run: cd ./.github/actions/generate-resources && yarn install --frozen-lockfile + + - name: Run action + uses: ./.github/actions/generate-resources + + - name: Prettier clean up + run: ./.github/actions/generate-resources/node_modules/.bin/prettier RESOURCES.md --write + + # note the harcode of the repo name. this could be done better if we wanted to use this repeatedly, but seems like a one-off + - name: Commit changes + run: | + git add RESOURCES.md + git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} + git -c user.name="D_D RESOURCE BOT" -c user.email="resource_bot@users.noreply.github.com" commit -m 'Refresh RESOURCES.md from Airtable' || echo 'No changes to commit' + git push origin || echo 'No changes to commit' \ No newline at end of file diff --git a/GLOSSARY.md b/GLOSSARY.md index 6e4314f..51848e1 100644 --- a/GLOSSARY.md +++ b/GLOSSARY.md @@ -17,6 +17,11 @@ [Learn more from Ethereum Docs](https://ethereum.org/en/developers/docs/dapps/) +- What is Defi? + > DeFi is a collective term for financial products and services that are accessible to anyone who can use Ethereum – anyone with an internet connection. With DeFi, the markets are always open and there are no centralized authorities who can block payments or deny you access to anything. Services that were previously slow and at risk of human error are automatic and safer now that they're handled by code that anyone can inspect and scrutinize. + + [Learn more about DeFi from here](https://ethereum.org/en/defi/) + ## E - What are ERC Tokens? > ERCs (Ethereum Request for Comments) are technical documents used by smart contract developers at Ethereum. They define a set of rules required to implement tokens for the Ethereum ecosystem. These documents are usually created by developers, and they include information about protocol specifications and contract descriptions. Before becoming an standard, an ERC must be revised, commented and accepted by the community through an EIP (Ethereum Improvement Proposal). @@ -43,6 +48,11 @@ [Learn more from Ethereum Docs](https://ethereum.org/en/developers/docs/intro-to-ethereum/) +- What is Ethereum Virtual Machine (EVM)? + > The Ethereum protocol itself exists solely for the purpose of keeping the continuous, uninterrupted, and immutable operation of this special state machine; It's the environment in which all Ethereum accounts and smart contracts live. At any given block in the chain, Ethereum has one and only one 'canonical' state, and the EVM is what defines the rules for computing a new valid state from block to block. + + [Learn more from EVM Docs](https://ethereum.org/en/developers/docs/evm/) + ## F - What is a Fungible Token? > The ERC-20 introduces a standard for Fungible Tokens, in other words, they have a property that makes each Token be exactly the same (in type and value) of another Token. For example, an ERC-20 Token acts just like the ETH, meaning that 1 Token is and will always be equal to all the other Tokens. @@ -65,12 +75,33 @@ [Learn more from Hardhat Docs](https://hardhat.org/getting-started/) +## L + +- What is Layer 2? + > Layer 2 is a collective term for solutions designed to help scale your application by handling transactions off the Ethereum Mainnet (Layer 1) while taking advantage of the robust decentralized security model of Mainnet. + + [Learn more from ethereum.org](https://ethereum.org/en/developers/docs/scaling/layer-2-rollups/) + +## M +- What is Metamask? + + > Metamask is a crypto wallet- it allows you to store and transact Ethereum or any other Ethereum-based (ERC- 20) tokens. + + [Learn more from Metamask Docs](https://docs.metamask.io/guide/) ## N - What is a Non-Fungible Token? > A Non-Fungible Token (NFT) is used to identify something or someone in a unique way. This type of Token is perfect to be used on platforms that offer collectible items, access keys, lottery tickets, numbered seats for concerts and sports matches, etc. This special type of Token has amazing possibilities so it deserves a proper Standard, the ERC-721 came to solve that! [Learn more from Ethereum Docs](https://ethereum.org/en/developers/docs/standards/tokens/erc-721/) +- What is Nonce? + > a counter that indicates the number of transactions sent from the account. This ensures transactions are only processed once. In a contract account, this number represents the number of contracts created by the ac + +## R + - What is Remix IDE? + > Remix IDE is an open source web and desktop application. It fosters a fast development cycle and has a rich set of plugins with intuitive GUIs. Remix is used for the entire journey of contract development with Solidity language in as well as being a playground for learning and teaching Ethereum. you can switch to remixid on your browser from here [here](https://remix.ethereum.org/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.7+commit.e28d00a7.js) + + [Learn more from Remix IDE docs](https://remix-ide.readthedocs.io/en/latest/#) ## S - What is a Smart Contract? > A "smart contract" is simply a program that runs on the Ethereum blockchain. It's a collection of code (its functions) and data (its state) that resides at a specific address on the Ethereum blockchain. @@ -88,3 +119,11 @@ > Solidity is a curly-bracket language. It is influenced by C++, Python and JavaScript, and is designed to target the Ethereum Virtual Machine (EVM). [Learn more from Solidity Docs](https://docs.soliditylang.org/en/v0.8.8/) +## T +- What is a Transaction? + >An Ethereum transaction refers to an action initiated by an externally-owned account, in other words an account managed by a human, not a contract. For example, if Bob sends Alice 1 ETH, Bob's account must be debited and Alice's must be credited. This state-changing action takes place within a transaction. + +- What is Truffle ? + > Truffle is a world-class development environment, testing framework and asset pipeline for blockchains using the Ethereum Virtual Machine (EVM), aiming to make life as a developer easier. + + [Learn more from Truffle Docs](https://www.trufflesuite.com/docs/truffle/overview) diff --git a/README.md b/README.md index 846a994..096105a 100644 --- a/README.md +++ b/README.md @@ -33,12 +33,17 @@ The community has created this knowledge base to help you **learn** and **grow** This guide by [Emanuele Ricci](https://twitter.com/StErMi) will cover how to configure Hardhat to compile, deploy test and debug a Solidity project. You will learn to create a smart contract, test it with Waffle, deploy it on Rinkeby and get it verified by Etherscan. +- [How to deploy your first NFT contract on Ethereum](https://docs.alchemy.com/alchemy/tutorials/how-to-create-an-nft) + + This guide could tell you how to write and deploy NFT contract, also it could help you to run front-end about minting your deployed contract. Could choose Truffle or Hardhat. And this tutorial could teach you how to mint NFT by script. + ### 📺 Content Creator Channels - [Nader Dabit on YouTube](https://www.youtube.com/c/naderdabit) - [Austin Griffith on YouTube](https://www.youtube.com/channel/UC_HI2i2peo1A-STdG22GFsA) - [Patrick Collins on YouTube](https://www.youtube.com/channel/UCn-3f8tw_E1jZvhuHatROwA) - [Whiteboard Crypto on YouTube](https://www.youtube.com/channel/UCsYYksPHiGqXHPoHI-fm5sg) +- [EatTheBlock on YouTube](https://www.youtube.com/c/EatTheBlocks) ### 📚 Docs @@ -46,6 +51,21 @@ The community has created this knowledge base to help you **learn** and **grow** - [Solidity Documentation](https://docs.soliditylang.org/en/v0.8.8/index.html) - [Solidity By Example](https://docs.soliditylang.org/en/v0.8.8/solidity-by-example.html) +### 📖 Books + +- [Mastering Ethereum](https://github.com/ethereumbook/ethereumbook), open source book by Andreas M. Antonopoulos and Gavin Wood +- [Hands-On Smart Contract Development with Solidity and Ethereum](https://www.oreilly.com/library/view/hands-on-smart-contract/9781492045250/), by Kevin Solorio, Randall Kanna, and David H. Hoover + +### 🤯 More Resource Lists + +- [Solidity cheatsheet and best practices](https://github.com/manojpramesh/solidity-cheatsheet) +- [Solidity gotchas, pitfalls, limitations, and idiosyncrasies](https://github.com/miguelmota/solidity-idiosyncrasies) +- [Awesome Solidity](https://github.com/bkrem/awesome-solidity) +- [Awesome Smart Contracts](https://github.com/transmute-industries/awesome-smart-contracts) +- [Not So Smart Contracts](https://github.com/crytic/not-so-smart-contracts) +- [useWeb3](https://www.useweb3.xyz/) +- [Open source web3 develop tutorial](https://github.com/ConsenSys-Academy/Blockchain-Developer-Bootcamp) + ### 🎮 Interactive Game Tutorials - [CryptoZombies](https://cryptozombies.io/en/solidity) @@ -59,6 +79,7 @@ The community has created this knowledge base to help you **learn** and **grow** - [scaffold-eth](https://github.com/scaffold-eth/scaffold-eth) - 🏗 forkable Ethereum dev stack focused on fast product iterations - [eth-hooks](https://github.com/scaffold-eth/eth-hooks) - Commonly used Ethereum hooks to create a web3 application - [eth-components](https://github.com/scaffold-eth/eth-components) - React library of commonly used Ethereum components to kickstart your next web3 react app +- [useDApp](https://usedapp.io/) - Framework for rapid Dapp development. Simple. Robust. Extendable. Testable ## Technologies @@ -69,10 +90,29 @@ The community has created this knowledge base to help you **learn** and **grow** - [Solidity Documentation](https://docs.soliditylang.org/en/v0.8.8/index.html) - [Truffle Suite Documentation](https://www.trufflesuite.com/docs) +## Dorage (Decentralized Storage) + +- [IPFS](https://ipfs.io/) +- [Arweave](https://www.arweave.org/) +- [Filecoin](https://filecoin.io/) + ### Solana - [Solana Developer Resources](https://github.com/CristinaSolana/solana-developer-resources) +### Layer 2 Rollups + +Layer 2 rollups provide a path to scaling Ethereum in a way that preserves the security guarantees of mainnet while increasing the transaction throughput and affordability of using Ethereum. Two main types of solutions exist, Optimistic Rollups and Zero-Knowledge Rollups. Below are some resources for learning more and getting started. + +- [Rollups Overview](https://ethereum.org/en/developers/docs/scaling/layer-2-rollups/) +- [Optimism Developer Documentation](https://community.optimism.io/docs/) +- [Truffle Optimism Box](https://github.com/truffle-box/optimism-box) +- [Arbitrum Developer Documentation](https://developer.offchainlabs.com/docs/developer_quickstart) +- [Truffle Arbitrum Box](https://github.com/truffle-box/arbitrum-box) +- [Starknet](https://starkware.co/starknet/) +- [Tutorial Using Starknet with Nile](https://medium.com/coinmonks/starknet-tutorial-for-beginners-using-nile-6af9c2270c15) +- [zkSync Developer Documentation](https://zksync.io/dev/) + ## Use Cases ### DeFi @@ -96,6 +136,7 @@ The community has created this knowledge base to help you **learn** and **grow** ## Courses ### Free Courses + - [Buildspace](https://buildspace.so) Action-oriented and community-driven course platform. Learn how to build a simple dApp or mint your own NFTs in just hours. (More courses later) @@ -104,10 +145,14 @@ The community has created this knowledge base to help you **learn** and **grow** Summary and examples of most common Solidity functions, use-cases, real smart contracts, and more. +- [ProtoSchool](https://proto.school/) + + Interactive tutorials on decentralized web protocols + - [Questbook](https://questbook.notion.site/Questbook-Learn-Web3-a5f4be8b107f4647a91fe84e6aa7e722) Questbook is a Decentralized University where learning web3 is always free - + - [FreeCodeCamp's Solidity Tutorial](https://www.youtube.com/embed/M576WGiDBdQ) Comprehensive introduction to main Solidity concepts (+blockchain/smart contracts) everyone needs to start writing their own ERC720 and ERC20 tokens, dApps, and more. @@ -116,6 +161,19 @@ The community has created this knowledge base to help you **learn** and **grow** - [Ethereum and Solidity: The Complete Developer's Guide](https://www.udemy.com/course/ethereum-and-solidity-the-complete-developers-guide/) (Udemy) - [Smart Contracts con Solidity de la A a la Z](https://www.udemy.com/course/solidity-a-z/learn/lecture/26791510?start=0#overview) (Udemy) (Spanish) +- [Smart Contract Engineer](https://www.smartcontract.engineer/) +- [SuperHi Crypto + Web 3 for Creatives](https://www.superhi.com/courses/crypto-and-web3-for-creatives) + +## 🔒 Security + +- [Awesome Ethereum Security](https://github.com/crytic/awesome-ethereum-security) contains curated resources to learn about Ethereum security, and also several useful tools +- [Not so Smart Contracts](https://github.com/crytic/not-so-smart-contracts) contains examples of common smart contract vulnerabilities, including code from real smart contracts +- [Smart Contract Security Audits](https://github.com/chainsulting/Smart-Contract-Security-Audits) performed and published by Chainsulting, with all audit reports included +- [Damn Vulnerable DeFi](https://www.damnvulnerabledefi.xyz/) is the wargame to learn offensive security of DeFi smart contracts + +## Meetups + +- [Blockchain 101](https://blockchain101.com/) is a meetup group from NYC that runs a lot of virtual meetups every month, open to everyone remotely! ## Other helpful resources diff --git a/RESOURCES.md b/RESOURCES.md new file mode 100644 index 0000000..4abaa35 --- /dev/null +++ b/RESOURCES.md @@ -0,0 +1,297 @@ +# Resources + +## Beginner + +- [Build an Ethereum Blockchain App](https://www.linkedin.com/learning/paths/build-an-ethereum-blockchain-app) + + Author: [Michael Solomon](https://twitter.com/LI_learning) + + 9 hour intro level course taught by a college professor that explains the elements involved in blockchain development as well a walkthrough of setting up a dev environment, creating a Hello World dApp, running some test code and deploying to the blockchain. This is a paid course on LinkedIn learning but is available for free by logging in using one of the many public library systems. (https://www.forbes.com/sites/tjmccue/2019/04/07/how-to-access-lynda-linkedin-learning-for-free/) + +- [What is Web3? The Decentralized Internet of the Future Explained](https://www.freecodecamp.org/news/what-is-web3/) + + Author: Nader Dabit + + The web we are experiencing today is much different than what it was just 10 years ago. How has the web evolved, and more importantly – where is it going next? Also, why do any of these things matter? + +- [Solana: How to send custom instructions via instruction data](https://dev.to/cogoo/solana-how-to-send-custom-instructions-via-instruction-data-4g9g) + + Author: [Colin Ogoo](https://twitter.com/C_Ogoo) + + Walk through the process of sending a custom instruction to a solana on-chain program. We'll modify the solana example helloworld to take two instructions, SayHello and SayGoodbye. + +- [How to write your first decentralized app - scaffold-eth Challenge 1: Staking dApp](https://dev.to/stermi/scaffold-eth-challenge-1-staking-dapp-4ofb) + + Author: [Emanuele Ricci](https://twitter.com/StErMi) + +- [Ethers.js Library](https://www.chainshot.com/learn/ethers) + + Author: [Chainshot](https://twitter.com/TeamChainShot) + + Learn how to interact with the Ethereum blockchain using the ethers.js library + +- [Solidity, Blockchain, and Smart Contract Course – Beginner to Expert Python Tutorial](https://www.youtube.com/watch?v=M576WGiDBdQ&ab_channel=freeCodeCamp.org) + + Author: [FreeCodeCamp](https://twitter.com/freeCodeCamp) + + This course will give you a full introduction into all of the core concepts in blockchain, smart contracts, solidity, NFTs/ERC721s, ERC20s, Coding Decentralized Finance (DeFi), python and solidity, Chainlink, Ethereum, upgradable smart contracts, and full stack blockchain development. + +- [How to create an ERC20 Token and a Solidity Vendor Contract to sell/buy your own token](https://dev.to/stermi/how-to-create-an-erc20-token-and-a-solidity-vendor-contract-to-sell-buy-your-own-token-4j1m) + + Author: [Emanuele Ricci](https://twitter.com/StErMi) + + A walkthrough of the Scaffold ETH challenge to create a Token Vendor contract. + +- [Building a Solana NFT](https://procgen.ai/update/solana/rust/2021/10/03/glitch-punks.html) + + Author: [Catherine David](https://twitter.com/miscatulated) + + Learn how to build an NFT program in Solana + +- [Build a Mini Buymeacoffee dApp Using Solidity + Ethereum Smart Contract + ReactJs + TailwindCSS](https://blog.idrisolubisi.com/build-a-mini-buymeacoffee-dapp-using-solidity-ethereum-smart-contract-reactjs-tailwindcss) + + Author: [Olubisi Ayinde](https://twitter.com/olanetsoft) + + Build a dapp to send some crypto to buy a coffee and a note with Solidity, React, and Tailwind.css. + +- [The Ultimate Guide To Getting Started With NFTs](https://www.tomhirst.com/getting-started-with-nfts) + + Author: [Tom Hirst](https://twitter.com/tom_hirst) + + Whether you’re interested in starting an NFT art collection, trading NFTs like stocks, developing smart contracts for NFT projects, involving yourself in the NFT community or want to understand more about the NFT space, this guide will offer you a valuable entry point. + +- [Solana Core Concepts (Community Video)](https://www.youtube.com/watch?v=4dNuMXBjpr0) + + Author: Solana + + An easy to digest overview of the core concepts of the Solana Blockchain. + +- [Ethereum and Solidity: The Complete Developer's Guide](https://www.udemy.com/course/ethereum-and-solidity-the-complete-developers-guide/) + + Author: [Stephen Grider](https://twitter.com/ste_grider) + + Use Ethereum, Solidity, and Smart Contracts to build production-ready apps based on the blockchain + +- [How to make your very own cryptocurrency (deploy your first smart contract!)](https://blog.mcgee.cat/how-to-make-your-very-own-cryptocurrency-deploy-your-first-smart-contract) + + Author: [Cat McGee](https://twitter.com/CatMcGeeCode) + + Walkthrough on how to create and deploy a ERC-20 token + +- [Going Full Time Web3](https://mirror.xyz/rahat.eth/tw60FNcgP1rorzIOfoQEEBix_NjDQS5_AbRr1YkTSEU) + + Author: [Rahat Chowdhury](https://twitter.com/Rahatcodes) + + Going fulltime in Web3. Talks about the author's journey and has a cool summary of his journey so far. + +- [Building a Blockchain in Go PT: I - The Hello World of Blockchains](https://dev.to/nheindev/build-the-hello-world-of-blockchain-in-go-bli) + + Author: [Noah Hein](https://twitter.com/NHeinDev) + + A tutorial on how to build a "Hello World" blockchain in Go + +- [Hello World! An Introduction To Solidity Smart Contracts](https://blog.paulmcaviney.ca/hello-world) + + Author: [Paul McAviney](https://twitter.com/paul_can_code) + + Write a hello world smart contract in Solidity + +- [Creating Tokens on Solana](https://www.brianfriel.xyz/how-to-create-a-token-on-solana/) + + Author: [Brian Friel](https://twitter.com/bfriel_) + + An introduction to the SPL Token Program and Solana's account model, complete with a guide on how to create a token on Solana. + +- [Peter's Solidity Recruitment Request](https://www.youtube.com/watch?v=80fA7foSi7c) + + Author: [Consensys](https://twitter.com/ConsenSys) + + Solidity recruitment test given for recruits for a Consensys job. Good job prep and interview practice. + +- [A DAO for Developers](https://devdao.mirror.xyz/Jl7_CZvMxkzFv-lJ29NXfEq9LXuZWkUjxOKoCF9CG_w) + + Author: Nader Dabit + + Whatever good things we build up end up building us. Talking about developer dao progress so far and the purpose of the DAO as a public good. + +- [Solana 101](https://2501babe.github.io/posts/solana101.html) + + Author: [hana](https://twitter.com/dumbcontract2) + +- [Learn to Code Blockchain DApps By Building Simple Games](https://cryptozombies.io/) + + Author: [Loom Network](https://twitter.com/loomnetwork) + + CryptoZombies is an interactive school that teaches you all things technical about blockchains. Learn to make smart contracts in Solidity or Libra by making your own crypto-collectibles game. + +- [Solana teardown: Walkthrough of the example helloworld program](https://dev.to/cogoo/solana-teardown-walkthrough-of-the-example-helloworld-program-18m4) + + Author: [Colin Ogoo](https://twitter.com/C_Ogoo) + + Walk through the helloworld Rust program line-by-line and begin to unpack how programs on Solana work. + +- [Solana’s Token Program, Explained](https://pencilflip.medium.com/solanas-token-program-explained-de0ddce29714) + + Author: [Matt Lim](https://twitter.com/pencilflip) + + Breaking down how fungible and non-fungible tokens work in Solana. + +- [The Complete Guide to Full Stack Solana Development with React, Anchor, Rust, and Phantom](https://dev.to/dabit3/the-complete-guide-to-full-stack-solana-development-with-react-anchor-rust-and-phantom-3291) + + Author: Nader Dabit + +- [Learning How to Build on Solana](https://www.brianfriel.xyz/learning-how-to-build-on-solana/) + + Author: [Brian Friel](https://twitter.com/bfriel_) + + An introductory tour to writing applications on Solana, built with the Anchor framework and React. + +- [The Complete Guide to Full Stack Ethereum Development](https://dev.to/dabit3/the-complete-guide-to-full-stack-ethereum-development-3j13) + + Author: Nader Dabit + + Tutorial from Nader Dabit on how to build Full Stack dApps with React, Ethers.js, and Hardhat. + +- [Discover Ethereum & Solidity Unleash the power of blockchain applications](https://www.ludu.co/course/ethereum) + + Author: [Tristan Edwards](https://twitter.com/t4t5) + + In this tutorial, beginners can create a complete DApp from start to finish, using common best practices from the Ethereum ecosystem with test cases for smart contracrts. + + +## Intermediate + +- [JSON RPC API](https://docs.solana.com/developing/clients/jsonrpc-api) + + Author: Solana + + The only way to get information from the Solana Blockchain, these docs lay out the JSON RPC API, which all of the SDKs wrap. + +- [A Guide to Private Ethereum Mining with Geth (Go-Ethereum)](https://dev.to/heydamali/a-guide-to-private-ethereum-mining-with-geth-go-ethereum-13ol) + + Author: [Arinze](https://twitter.com/heydamali) + + Walk through the process of setting up a single node, private Ethereum blockchain using the Geth client. The purpose of this guide is to help readers understand how the blockchain works from the miners' perspective and what goes into the mining process + +- [How To Get Front-Run on Ethereum mainnet](https://www.youtube.com/watch?v=UZ-NNd6yjFM) + + Author: [Scott Bigelow](https://twitter.com/epheph) + + An introduction and real time example of a frontrun on Ethereum Mainnet + +- [The Financialization of Fun: Crypto Gaming Thesis](https://www.mechanism.capital/crypto-gaming-thesis/) + + Author: [Eva Wu](https://twitter.com/wvaeu) + + Blockchain gaming is seeing a hurricane of action; while Steam bans crypto gaming, big game studios are exploring it and “Play to Earn (P2E)” is on every VC’s lips. + +- [Capture The Ether](https://capturetheether.com/) + + Author: [Steve Marx](https://twitter.com/smarx) + + Capture the Ether is a game in which you hack Ethereum smart contracts to learn about security. It's meant to be both fun and educational. + +- [Honeypots in Ethereum And How To Avoid Them With Tenderly.co Transaction Simulation](https://www.youtube.com/watch?v=DDn5mksOUCc) + + Author: [Scott Bigelow](https://twitter.com/epheph) + + Ethereum mainnet honeypot contracts try to trick you into sending it your own Ether, allowing the scammer to withdraw that Ether later. In this video, we explore the common "quiz" honeypot, explore how people fall for it, and how you can use transaction simulation and https://tenderly.co to check what your transaction does before broadcasting it. + +- [How To Dockerize Your Hardhat Solidity Contract On Localhost](https://codingwithmanny.medium.com/how-to-dockerize-your-hardhat-solidity-contract-on-localhost-a45424369896) + + Author: [Manny](https://twitter.com/codingwithmanny) + + How To Take Your Web3 Solidity Contract With Hardhat & Create A Docker Image With The Local Deployment + +- [5 Solidity Code Smells That Every Blockchain Developer Should Know](https://medium.com/coinmonks/5-solidity-code-smells-87bb2f259dde) + + Author: [Jackson Kelley](https://twitter.com/sjkelleyjr) + + Five issues to watch for when creating a Solidity smart contract. Each smell has links to related challenges for practice. + +- [Ethernaut](https://ethernaut.openzeppelin.com/) + + Author: [Open Zeppelin](https://twitter.com/OpenZeppelin) + + The Ethernaut is a Web3/Solidity based wargame inspired on overthewire.org, played in the Ethereum Virtual Machine. Each level is a smart contract that needs to be 'hacked'. + +- [Understanding Merkle Trees in 5 minutes](https://medium.com/coinmonks/understanding-merkle-trees-in-5-minutes-68e0f4406a72) + + Author: Charlie Rogers + + Hash trees (merkle trees), is a tree in which every node is labelled with a cryptographic hash of a data block. Hash trees can be used to verify any kind of data stored, handled and transferred in and between computers. They can help to ensure that data blocks received from other peers in a peer to peer network as received undamaged and unaltered + +- [How to Debug Pending Ethereum Transactions](https://blog.alchemy.com/blog/how-to-debug-pending-ethereum-transactions) + + Author: [Alchemy Team](https://twitter.com/AlchemyPlatform) + + A deep dive into the flow of a transaction on the Ethereum network, from the moment you hit “send” to the point when the transaction becomes fully mined. + +- [How to apply TDD when writing an Ethereum smart contract with Solidity](https://medium.com/@fabientownsend/how-to-apply-tdd-when-writing-an-ethereum-smart-contract-with-solidity-1e4b227a84aa) + + Author: [Fabien Townsend](https://twitter.com/FabienTownsend) + + Introduction on how to use TDD when writing an ETH smart contract + +- [Smart Contracts Risk Analysis and Flash Loan Exploits - Ethereum Security](https://www.youtube.com/watch?v=nLHCyEvszkc) + + Author: [Loom Network](https://twitter.com/loomnetwork) + + Mudit Gupta, an advisor to the SushiSwap protocol has a 90 minute video on smart contract security + +- [Secure Development Series](https://www.youtube.com/playlist?list=PLdJRkA9gCKOONBSlcifqLig_ZTyG_YLqz) + + Author: [tincho](https://twitter.com/tinchoabbate) + + Secure Development Workshop and best Practices by OpenZeppelin + +- [Understanding Program Derived Addresses](https://www.brianfriel.xyz/understanding-program-derived-addresses/) + + Author: [Brian Friel](https://twitter.com/bfriel_) + + A practical overview of how Solana programs read and write data. + +- [Tutorial: Building a web3 frontend with React](https://medium.com/scrappy-squirrels/tutorial-building-a-web3-frontend-with-react-e0a87ea3bad) + + Author: [Rounak Banik](https://twitter.com/Rounak_Banik) + + Tutorial on allowing users to connect a Metamask wallet to your website, and allow users to call a contract functions, make a payment, and mint an NFT from your collection. + +- [Secureum - Ethereum Security Concepts](https://secureum.substack.com/) + + Author: [0xRajeev](https://twitter.com/0xRajeev) + + Ethereum security focused substack developed as part of the Secureum Smart Contract Auditing bootcamp in partnership with the major auditing firms and the Ethereum foundation. Each chapter is formated as a list, each containing a description of 100 title related concepts. + +- [Crypto Design Challenges](https://paulstamatiou.com/crypto-design-challenges/) + + Author: [Paul Stamatiou](https://twitter.com/Stammy) + + It's still early days. Crypto exists today in a relatively wild west phase. There are some common deisgn challenges crypto projects share and the article articulates several ways we can tackle these design issues. + +- [Building GraphQL APIs on Ethereum](https://dabit3.medium.com/building-graphql-apis-on-ethereum-427ed363df17) + + Author: Nader Dabit + + How to use the Graph protocol to build GraphQL APIs on top of the blockchain. + +- [Serverless and blockchain: check NFT supply with AWS Lambda](https://dev.to/dashbird/serverless-and-blockchain-check-nft-supply-with-aws-lambda-5d0f) + + Author: [Kayis](https://twitter.com/K4y1s) + + Build a serverless system to query the Ethereum blockchain for NFT data + +## Advanced + +- [A Guide to Designing Effective NFT Launches](https://www.paradigm.xyz/2021/10/a-guide-to-designing-effective-nft-launches/) + + Authors: [Hasu](https://twitter.com/hasufl),[Anish Agnihotri](https://twitter.com/_anishagnihotri) + + Deconstruct bad launches to determine what a good launch needs, breaks down the steps of a launch, and provides a reference implementation of a well designed launch. + +- [Damn Vulnerable DeFi](https://www.damnvulnerabledefi.xyz/) + + Author: [tincho](https://twitter.com/tinchoabbate) + + The offensive security playground for decentralized finances. + Throughout numerous challenges you will build the skills to become a bug hunter or security auditor in the space.