├── .all-contributorsrc ├── Blockchain Cryptography ├── CRYPTOGRAPHIC HASHES │ └── 1-Find-Favourite-Color.js ├── PUBLIC KEY CRYPTOGRAPHY │ ├── hashMessage.js │ ├── keyToAddress.js │ ├── recoveryKey.js │ └── signMessage.js ├── blockchain-networks │ ├── 1-blocksAndHashes-block.js │ ├── 2-whatInAHash-block.js │ ├── 3-theGenesisBlock-blockchain.js │ ├── 4-addingBlocks-blockchain.js │ ├── 5-linkingTheBlock-blokchain.js │ └── validatingTheChain-blockchain.js └── proof-of-work │ ├── 1-mempool-index.js │ ├── 2-mineBlock-index.js │ ├── 3-blockHash-index.js │ ├── 4-mineTx-index.js │ ├── 5-difficulty-index.-Siddhesh.js │ └── 5-difficulty-index.js ├── CONTRIBUTION.md ├── LICENSE ├── README.md ├── blockchain-storage ├── Binary search tree │ ├── 1-Node.js │ ├── 2-Tree.js │ ├── 3-addRoot-Tree.js │ ├── 4-firstLayer-Tree.js │ ├── 5-manylayers-Tree.js │ └── 6-search-Tree.js ├── merkel-tree │ ├── 1-combineTwoLeaves-index.js │ ├── 2-multipleLayers-index.js │ ├── 3-oddLeaves-index.js │ ├── 4-buildTheProof-index.js │ └── 5-verifyYourProof-verify.js ├── tries │ ├── 1-constructor-TrieNode.js │ ├── 1-constructor-tries.js │ ├── 2-insert-tries.js │ ├── 3-insert-branching-trie.js │ └── 4-contains-trie.js └── utxo-model │ ├── 1-transaction-output-TXO.js │ ├── 2-spentTXOs.transaction.js │ ├── 3-sufficientAmount-transaction.js │ ├── 4-successfulExecute-transaction.js │ ├── 5-minerFee-transaction.js │ └── offTopic.tx-script.js ├── blockexplorer ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── assets │ │ └── logo.png │ ├── components │ │ ├── AccountBalance.jsx │ │ ├── AccountTxs.jsx │ │ ├── Block.jsx │ │ ├── Blocks.jsx │ │ ├── Header.jsx │ │ ├── Nft.jsx │ │ ├── Search.jsx │ │ ├── Transaction.jsx │ │ └── Transactions.jsx │ ├── helper.js │ ├── index.css │ ├── index.js │ └── services.js └── tailwind.config.js ├── ecdsa-node ├── client │ ├── .gitignore │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── vite.svg │ ├── src │ │ ├── Accounts.jsx │ │ ├── App.jsx │ │ ├── App.scss │ │ ├── Transfer.jsx │ │ ├── Wallet.jsx │ │ ├── helper.js │ │ ├── main.jsx │ │ └── server.js │ └── vite.config.js ├── readme.md └── server │ ├── .gitignore │ ├── index.js │ ├── package-lock.json │ ├── package.json │ ├── scripts │ └── generate.js │ └── vercel.json ├── ethereum ├── ethers │ ├── 1-makingWallets-wallet.js │ ├── 2-signATransactions-sign.js │ ├── 3-connectToEthereum-sendEther.js │ ├── 4-accountNonce-sendEther.js │ ├── 5-findBalance-findMyBalance.js │ ├── 6-charitableDonation-donation.js │ └── findEther.js └── json-rpc │ ├── 1-currentBlockNumber-getBlockNumber.js │ ├── 2-getBalance-getBalance.js │ ├── 3-getNonce-getNonce.js │ ├── 4-blockTransactions-getTotalTransactions.js │ └── 5-totalWei-getTotalBalance.js ├── smart-contracts-basics ├── data-types │ ├── 1-booleans-contract.sol │ ├── 2-unsigned-integers-contract.sol │ ├── 3-signed-integers-contract.sol │ ├── 4-string-literals-contract.sol │ └── 5-enum-contract.sol ├── event-emitter-project │ ├── .env.example │ ├── .gitignore │ ├── README.md │ ├── contracts │ │ └── EmitWinnerEvent.sol │ ├── hardhat.config.js │ ├── package-lock.json │ ├── package.json │ └── scripts │ │ ├── deploy.js │ │ └── emitWinnerEvent.js ├── functions │ ├── 1-argument-contract.sol │ ├── 2-increment-contract.sol │ ├── 3-viewAddition-contract.sol │ ├── 4-pureDouble-contract.sol │ └── 5-doubleOverload-contract.sol ├── learning-reverts │ ├── 1-contructorRevert.contract.sol │ ├── 2-onlyOwner-contract.sol │ └── 3-ownerModifier-contract.sol ├── practice-solidity │ ├── countdown-contract.sol │ └── sumAndAverage-contract.sol ├── sending-data │ ├── 1-callFunction-sideKick.sol │ ├── 2-signature-sideKick.sol │ ├── 3-withSignature-sideKick.sol │ ├── 4-arbitraryAlert-sideKick.sol │ └── 5-fallback-sideKick.sol ├── sending-ethers │ ├── 1-storing-owner-contract.sol │ ├── 2-recieve-ether-contract.sol │ ├── 3-tipOwner-contract.sol │ ├── 4-charity-contract.sol │ └── 5-selfDestruct-contract.sol └── smart-contract-communication │ ├── 1-getter-index.js │ ├── 2-setter-index.js │ ├── 3-transfer.index.js │ ├── 4-signer-index.js │ └── 5-deposit-index.js └── solidity-core ├── dead-man-switch └── Switch.sol ├── hackathon-ratings └── Hackathon.sol ├── multi-sigs ├── 1-constructor-multiSig.sol ├── 10-isConfirmed-multiSig.sol ├── 11-execute-multiSig.sol ├── 12-executeConfirmed-multiSig.sol ├── 13-sendingCalldata-multiSig.sol ├── 2-error-handling-multiSIg.sol ├── 3-transaction-setup-multiSig.sol ├── 4-addTransactions-multiSig.sol ├── 5-confirmations-multiSig.sol ├── 6-confirm-transactions-multiSig.sol ├── 7-confirm-security-multiSig.sol ├── 8-submit-transaction-multiSig.sol └── 9-receive-multiSig.sol └── party-split ├── 1-rsvp-Party.sol └── 2-rsvp-payBills.sol /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "commitConvention": "angular", 8 | "contributors": [ 9 | { 10 | "login": "SiddheshKukade", 11 | "name": "Siddhesh Bhupendra Kuakde", 12 | "avatar_url": "https://avatars.githubusercontent.com/u/65951872?v=4", 13 | "profile": "https://siddheshkukade.com", 14 | "contributions": [ 15 | "code" 16 | ] 17 | }, 18 | { 19 | "login": "pokhrelanmol", 20 | "name": "anmol pokhrel", 21 | "avatar_url": "https://avatars.githubusercontent.com/u/75737628?v=4", 22 | "profile": "https://github.com/pokhrelanmol", 23 | "contributions": [ 24 | "code", 25 | "doc" 26 | ] 27 | } 28 | ], 29 | "contributorsPerLine": 7, 30 | "skipCi": true, 31 | "repoType": "github", 32 | "repoHost": "https://github.com", 33 | "projectName": "AU_ETH_Bootcamp", 34 | "projectOwner": "SiddheshKukade" 35 | } 36 | -------------------------------------------------------------------------------- /Blockchain Cryptography/CRYPTOGRAPHIC HASHES/1-Find-Favourite-Color.js: -------------------------------------------------------------------------------- 1 | const { sha256 } = require("ethereum-cryptography/sha256"); 2 | const { toHex, utf8ToBytes } = require("ethereum-cryptography/utils"); 3 | 4 | // the possible colors that the hash could represent 5 | const COLORS = ["red", "green", "blue", "yellow", "pink", "orange"]; 6 | 7 | // given a hash, return the color that created the hash 8 | function findColor(hash) { 9 | let ans; 10 | COLORS.map((c) => { 11 | let temp = utf8ToBytes(c); 12 | temp = sha256(temp); 13 | if (toHex(hash) === toHex(temp)) { 14 | ans = c; 15 | } 16 | }); 17 | return ans; 18 | } 19 | 20 | module.exports = findColor; 21 | -------------------------------------------------------------------------------- /Blockchain Cryptography/PUBLIC KEY CRYPTOGRAPHY/hashMessage.js: -------------------------------------------------------------------------------- 1 | const { keccak256 } = require("ethereum-cryptography/keccak"); 2 | const { utf8ToBytes } = require("ethereum-cryptography/utils"); 3 | 4 | function hashMessage(message) { 5 | const bytes = utf8ToBytes(message); 6 | const hash = keccak256(bytes); 7 | return hash; 8 | } 9 | 10 | module.exports = hashMessage; 11 | -------------------------------------------------------------------------------- /Blockchain Cryptography/PUBLIC KEY CRYPTOGRAPHY/keyToAddress.js: -------------------------------------------------------------------------------- 1 | const secp = require("ethereum-cryptography/secp256k1"); 2 | const { keccak256 } = require("ethereum-cryptography/keccak"); 3 | 4 | function getAddress(publicKey) { 5 | const hash = keccak256(publicKey.slice(1, publicKey.length)); 6 | 7 | const address = hash.slice(-20); 8 | 9 | return address; 10 | } 11 | 12 | module.exports = getAddress; 13 | -------------------------------------------------------------------------------- /Blockchain Cryptography/PUBLIC KEY CRYPTOGRAPHY/recoveryKey.js: -------------------------------------------------------------------------------- 1 | const secp = require("ethereum-cryptography/secp256k1"); 2 | const hashMessage = require("./hashMessage"); 3 | 4 | async function recoverKey(message, signature, recoveryBit) { 5 | const hash = hashMessage(message); 6 | 7 | return secp.recoverPublicKey(hash, signature, recoveryBit); 8 | } 9 | 10 | module.exports = recoverKey; 11 | -------------------------------------------------------------------------------- /Blockchain Cryptography/PUBLIC KEY CRYPTOGRAPHY/signMessage.js: -------------------------------------------------------------------------------- 1 | const secp = require("ethereum-cryptography/secp256k1"); 2 | const hashMessage = require("./hashMessage"); 3 | 4 | const PRIVATE_KEY = 5 | "6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e"; 6 | 7 | async function signMessage(msg) { 8 | const hash = hashMessage(msg); 9 | return await secp.sign(hash, PRIVATE_KEY, { recovered: true }); 10 | } 11 | 12 | module.exports = signMessage; 13 | -------------------------------------------------------------------------------- /Blockchain Cryptography/blockchain-networks/1-blocksAndHashes-block.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | 3 | class Block { 4 | toHash() { 5 | return SHA256("Zibberish"); // a hash! 6 | } 7 | } 8 | 9 | module.exports = Block; 10 | -------------------------------------------------------------------------------- /Blockchain Cryptography/blockchain-networks/2-whatInAHash-block.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | 3 | class Block { 4 | constructor(data) { 5 | this.data = data; 6 | } 7 | toHash() { 8 | return SHA256(this.data); // a hash! 9 | } 10 | } 11 | const block = new Block("Alice sent Bob 1 BTC"); 12 | module.exports = Block; 13 | -------------------------------------------------------------------------------- /Blockchain Cryptography/blockchain-networks/3-theGenesisBlock-blockchain.js: -------------------------------------------------------------------------------- 1 | const Block = require("./Block"); 2 | const SHA256 = require("crypto-js/sha256"); 3 | 4 | class Blockchain { 5 | constructor() { 6 | const block = new Block("Zibberish"); 7 | this.chain = [block]; // genisis block 8 | } 9 | } 10 | const blockchain = new Blockchain(); 11 | 12 | module.exports = Blockchain; 13 | -------------------------------------------------------------------------------- /Blockchain Cryptography/blockchain-networks/4-addingBlocks-blockchain.js: -------------------------------------------------------------------------------- 1 | const Block = require("./Block"); 2 | const SHA256 = require("crypto-js/sha256"); 3 | 4 | class Blockchain { 5 | constructor() { 6 | const block = new Block("Zibberish"); 7 | this.chain = [block]; // genesis block 8 | } 9 | addBlock(newBlock) { 10 | this.chain.push(newBlock); 11 | } 12 | } 13 | const blockchain = new Blockchain(); 14 | const block = new Block("Charlie sent Dave 2 BTC"); 15 | 16 | blockchain.addBlock(block); 17 | module.exports = Blockchain; 18 | -------------------------------------------------------------------------------- /Blockchain Cryptography/blockchain-networks/5-linkingTheBlock-blokchain.js: -------------------------------------------------------------------------------- 1 | const Block = require("./Block"); 2 | const SHA256 = require("crypto-js/sha256"); 3 | 4 | class Blockchain { 5 | constructor() { 6 | const block = new Block("Zibberish"); 7 | this.chain = [block]; // genisis block 8 | } 9 | addBlock(newBlock) { 10 | newBlock.previousHash = this.chain[this.chain.length - 1].toHash(); 11 | newBlock.data = "Some More Data"; 12 | this.chain.push(newBlock); 13 | } 14 | } 15 | const blockchain = new Blockchain(); 16 | const block = new Block(); 17 | 18 | blockchain.addBlock(block); 19 | module.exports = Blockchain; 20 | -------------------------------------------------------------------------------- /Blockchain Cryptography/blockchain-networks/validatingTheChain-blockchain.js: -------------------------------------------------------------------------------- 1 | const Block = require("./Block"); 2 | const SHA256 = require("crypto-js/sha256"); 3 | 4 | class Blockchain { 5 | constructor() { 6 | const block = new Block("Zibberish"); 7 | this.chain = [block]; // genisis block 8 | } 9 | addBlock(newBlock) { 10 | newBlock.previousHash = this.chain[this.chain.length - 1].toHash(); 11 | newBlock.data = "Some More Data"; 12 | this.chain.push(newBlock); 13 | } 14 | isValid() { 15 | let isChainValid = true; 16 | const blockchain = this.chain; 17 | for (let i = 1; i < blockchain.length; i++) { 18 | const previousBlock = blockchain[i - 1]; 19 | const currentBlock = blockchain[i]; 20 | if ( 21 | previousBlock.toHash().toString() != 22 | currentBlock.previousHash.toString() 23 | ) { 24 | isChainValid = false; 25 | } 26 | } 27 | return isChainValid; 28 | } 29 | } 30 | const blockchain = new Blockchain(); 31 | const block = new Block(); 32 | 33 | blockchain.addBlock(block); 34 | module.exports = Blockchain; 35 | -------------------------------------------------------------------------------- /Blockchain Cryptography/proof-of-work/1-mempool-index.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | const TARGET_DIFFICULTY = 3 | BigInt(0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 4 | const MAX_TRANSACTIONS = 10; 5 | 6 | const mempool = []; 7 | const blocks = []; 8 | 9 | function addTransaction(transaction) { 10 | // TODO: add transaction to mempool 11 | mempool.push(transaction); 12 | } 13 | 14 | function mine() { 15 | // TODO: mine a block 16 | } 17 | 18 | module.exports = { 19 | TARGET_DIFFICULTY, 20 | MAX_TRANSACTIONS, 21 | addTransaction, 22 | mine, 23 | blocks, 24 | mempool, 25 | }; 26 | -------------------------------------------------------------------------------- /Blockchain Cryptography/proof-of-work/2-mineBlock-index.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | const TARGET_DIFFICULTY = 3 | BigInt(0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 4 | const MAX_TRANSACTIONS = 10; 5 | 6 | const mempool = []; 7 | const blocks = []; 8 | 9 | function addTransaction(transaction) { 10 | // TODO: add transaction to mempool 11 | mempool.push(transaction); 12 | } 13 | 14 | function mine() { 15 | // TODO: mine a block 16 | const blockHeight = blocks.length; 17 | blocks.push({ id: blockHeight }); 18 | } 19 | 20 | module.exports = { 21 | TARGET_DIFFICULTY, 22 | MAX_TRANSACTIONS, 23 | addTransaction, 24 | mine, 25 | blocks, 26 | mempool, 27 | }; 28 | -------------------------------------------------------------------------------- /Blockchain Cryptography/proof-of-work/3-blockHash-index.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | const TARGET_DIFFICULTY = 3 | BigInt(0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 4 | const MAX_TRANSACTIONS = 10; 5 | 6 | const mempool = []; 7 | const blocks = []; 8 | 9 | function addTransaction(transaction) { 10 | // TODO: add transaction to mempool 11 | mempool.push(transaction); 12 | } 13 | 14 | function mine() { 15 | // TODO: mine a block 16 | let blockHeight = blocks.length; 17 | const hash = SHA256(JSON.stringify({ id: blockHeight })); 18 | blocks.push({ hash: hash }); 19 | } 20 | 21 | module.exports = { 22 | TARGET_DIFFICULTY, 23 | MAX_TRANSACTIONS, 24 | addTransaction, 25 | mine, 26 | blocks, 27 | mempool, 28 | }; 29 | -------------------------------------------------------------------------------- /Blockchain Cryptography/proof-of-work/4-mineTx-index.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | const TARGET_DIFFICULTY = 3 | BigInt(0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 4 | const MAX_TRANSACTIONS = 10; 5 | 6 | const mempool = []; 7 | const blocks = []; 8 | 9 | function addTransaction(transaction) { 10 | // TODO: add transaction to mempool 11 | mempool.push(transaction); 12 | } 13 | 14 | function mine() { 15 | // TODO: mine a block 16 | let blockHeight = blocks.length; 17 | const transactions = mempool.splice(0, MAX_TRANSACTIONS); //this modifies original array i.e mempool 18 | 19 | let blockHash = SHA256(JSON.stringify({ id: blockHeight })); 20 | const block = { transactions, hash: blockHash }; 21 | blocks.push(block); 22 | } 23 | 24 | module.exports = { 25 | TARGET_DIFFICULTY, 26 | MAX_TRANSACTIONS, 27 | addTransaction, 28 | mine, 29 | blocks, 30 | mempool, 31 | }; 32 | -------------------------------------------------------------------------------- /Blockchain Cryptography/proof-of-work/5-difficulty-index.-Siddhesh.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require('crypto-js/sha256'); 2 | const TARGET_DIFFICULTY = BigInt(0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 3 | const MAX_TRANSACTIONS = 10; 4 | let id =0; 5 | let mempool = []; 6 | const blocks = []; 7 | 8 | function addTransaction(transaction) { 9 | mempool.push(transaction); 10 | } 11 | 12 | function mine() { 13 | let blockHeight = blocks.length; 14 | let transactions = mempool.splice(0,MAX_TRANSACTIONS) 15 | let nonceNo = 0; 16 | let obj = { id: blockHeight, transactions,nonce: nonceNo} 17 | let hash = SHA256(JSON.stringify(obj)) 18 | let int = BigInt(`0x${hash}`); 19 | while(int >TARGET_DIFFICULTY){ 20 | nonceNo++; 21 | obj = { id: blockHeight, transactions, nonce: nonceNo} 22 | hash = SHA256(JSON.stringify(obj)) 23 | int = BigInt(`0x${hash}`); 24 | } 25 | blocks.push({...obj, hash}) 26 | } 27 | 28 | module.exports = { 29 | TARGET_DIFFICULTY, 30 | MAX_TRANSACTIONS, 31 | addTransaction, 32 | mine, 33 | blocks, 34 | mempool 35 | }; 36 | -------------------------------------------------------------------------------- /Blockchain Cryptography/proof-of-work/5-difficulty-index.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | const TARGET_DIFFICULTY = 3 | BigInt(0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 4 | const MAX_TRANSACTIONS = 10; 5 | 6 | const mempool = []; 7 | const blocks = []; 8 | 9 | function addTransaction(transaction) { 10 | // TODO: add transaction to mempoo l 11 | mempool.push(transaction); 12 | } 13 | 14 | function mine() { 15 | // TODO: mine a block 16 | let blockHeight = blocks.length; 17 | const transactions = mempool.splice(0, MAX_TRANSACTIONS); //this modifies original array i.e mempool 18 | let nonce = 0; 19 | while (true) { 20 | let blockHash = SHA256( 21 | JSON.stringify({ nonce: nonce, id: blockHeight }) 22 | ); 23 | const int = BigInt(`0x${blockHash}`); 24 | if (int <= TARGET_DIFFICULTY) { 25 | const block = { transactions, hash: blockHash, nonce: nonce }; 26 | blocks.push(block); 27 | break; 28 | } 29 | nonce++; 30 | } 31 | } 32 | 33 | module.exports = { 34 | TARGET_DIFFICULTY, 35 | MAX_TRANSACTIONS, 36 | addTransaction, 37 | mine, 38 | blocks, 39 | mempool, 40 | }; 41 | -------------------------------------------------------------------------------- /CONTRIBUTION.md: -------------------------------------------------------------------------------- 1 | ## NOTE: Please check your answers twice before sending PR because we can't verify your answer. PLAY FAIR 2 | 3 | ## 👨‍💻 Prerequisites 4 | 5 | - [Alchemy University Bootcamp Student or Instructor](https://university.alchemy.com/) 6 | 7 | ## How to Contribute 8 | 9 | - Take a look at the existing [Issues](https://github.com/SiddheshKukade/AU_ETH_Bootcamp/issues) or [create a new issue](https://github.com/SiddheshKukade/AU_ETH_Bootcamp/issues/new/)! 10 | - [Fork the Repo](https://github.com/SiddheshKukade/AU_ETH_Bootcamp). Then, create a branch for any issue that you are working on. Finally, commit your work. 11 | - Create a **[Pull Request](https://github.com/SiddheshKukade/AU_ETH_Bootcamp)** (_PR_), which will be promptly reviewed and given suggestions for improvements by the community. 12 | 13 | ## ⭐ HOW TO MAKE A PULL REQUEST: 14 | 15 | **1.** Start by making a Fork of the [**AU_ETH_Bootcamp**](https://github.com/SiddheshKukade/AU_ETH_Bootcamp) repository. Click on the Fork symbol at the top right corner. 16 | 17 | **2.** Clone your new fork of the repository in the terminal/CLI on your computer with the following command: 18 | 19 | ```bash 20 | git clone https://github.com//AU_ETH_Bootcamp 21 | ``` 22 | 23 | **3.** Navigate to the newly created seeit project directory: 24 | 25 | ```bash 26 | cd AU_ETH_Bootcamp 27 | ``` 28 | 29 | **4.** Set upstream command: 30 | 31 | ```bash 32 | git remote add upstream https://github.com/SiddheshKukade/AU_ETH_Bootcamp 33 | ``` 34 | 35 | **5.** Create a new branch: 36 | 37 | ```bash 38 | git checkout -b YourBranchName 39 | ``` 40 | 41 | **6.** Sync your fork or your local repository with the origin repository: 42 | 43 | - In your forked repository, click on "Fetch upstream" 44 | - Click "Fetch and merge" 45 | 46 | ### Alternatively, Git CLI way to Sync forked repository with origin repository: 47 | 48 | ```bash 49 | git fetch upstream 50 | ``` 51 | 52 | ```bash 53 | git merge upstream/main 54 | ``` 55 | 56 | ### [Github Docs](https://docs.github.com/en/github/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-on-github) for Syncing 57 | 58 | **7.** Make your changes to the source code. 59 | 60 | **8.** Stage your changes: 61 | 62 | ⚠️ **Make sure** not to commit `package.json` or `package-lock.json` file 63 | 64 | ⚠️ **Make sure** not to run the commands `git add .` or `git add *` 65 | 66 | > Instead, stage your changes for each file/folder 67 | > 68 | > By using public path it means it will add all files and folders under that folder, it is better to be specific 69 | 70 | ```bash 71 | git add public 72 | ``` 73 | 74 | _or_ 75 | 76 | ```bash 77 | git add "" 78 | ``` 79 | 80 | **9.** Commit your changes: 81 | 82 | ```bash 83 | git commit -m "" 84 | ``` 85 | 86 | **10.** Push your local commits to the remote repository: 87 | 88 | ```bash 89 | git push origin YourBranchName 90 | ``` 91 | 92 | **11.** Create a [Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)! 93 | 94 | -- 95 | 96 | ## 💥 Issues 97 | 98 | In order to discuss changes, you are welcome to [open an issue](https://github.com/SiddheshKukade/AU_ETH_Bootcamp/issues/new/) about what you would like to contribute. Enhancements are always encouraged and appreciated. 99 | 100 | ## All the best! 🥇 101 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Siddhesh Bhupendra Kuakde 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | [![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors-) 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | # Alchemy University Ethereum Developer Bootcamp answers 14 | 15 | Contains answers for Ethereum Developer Bootcamp provided by [Alchemy University](https://university.alchemy.com/). Feel Free to contribute your answers here and help each other 16 | 17 | ## Want to Contribute? See [Contribution guidelines](https://github.com/pokhrelanmol/AU_ETH_Bootcamp/blob/anmol/CONTRIBUTION.md) 18 | 19 | ## Contributors 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
Siddhesh Bhupendra Kuakde
Siddhesh Bhupendra Kuakde

💻
Gabriel Isobara
Gabriel Isobara

💻 📖
anmol pokhrel
anmol pokhrel

💻
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-) 52 | 53 | 54 | -------------------------------------------------------------------------------- /blockchain-storage/Binary search tree/1-Node.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.left = null; 5 | this.right = null; 6 | } 7 | } 8 | 9 | module.exports = Node; 10 | -------------------------------------------------------------------------------- /blockchain-storage/Binary search tree/2-Tree.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiddheshKukade/AU_ETH_Bootcamp/fc99de609aaf0d33edf3ce7d85e7a3468ebf3235/blockchain-storage/Binary search tree/2-Tree.js -------------------------------------------------------------------------------- /blockchain-storage/Binary search tree/3-addRoot-Tree.js: -------------------------------------------------------------------------------- 1 | const Node = require("./Node.js"); 2 | class Tree { 3 | constructor() { 4 | this.root = null; 5 | } 6 | addNode(newNode) { 7 | this.root = newNode; 8 | } 9 | } 10 | // create a new tree and new node 11 | const tree = new Tree(); 12 | const node = new Node(5); 13 | 14 | // add the node to the tree using addNode 15 | tree.addNode(node); 16 | 17 | // the new node becomes the tree's root 18 | console.log(tree.root.data); // 5 19 | 20 | module.exports = Tree; 21 | -------------------------------------------------------------------------------- /blockchain-storage/Binary search tree/4-firstLayer-Tree.js: -------------------------------------------------------------------------------- 1 | const Node = require("./Node.js"); 2 | class Tree { 3 | constructor() { 4 | this.root = null; 5 | } 6 | addNode(newNode) { 7 | if (this.root) { 8 | if (newNode.data < this.root.data) { 9 | this.root.left = newNode; 10 | } else { 11 | this.root.right = newNode; 12 | } 13 | } else { 14 | this.root = newNode; 15 | } 16 | } 17 | } 18 | // create a new tree and new node 19 | const tree = new Tree(); 20 | const node = new Node(5); 21 | 22 | // add the node to the tree using addNode 23 | tree.addNode(node); 24 | 25 | // the new node becomes the tree's root 26 | console.log(tree.root.data); // 5 27 | 28 | module.exports = Tree; 29 | -------------------------------------------------------------------------------- /blockchain-storage/Binary search tree/5-manylayers-Tree.js: -------------------------------------------------------------------------------- 1 | const Node = require("./Node.js"); 2 | class Tree { 3 | constructor() { 4 | this.root = null; 5 | } 6 | insertNode(root, newNode) { 7 | if (newNode.data < root.data) { 8 | if (root.left) { 9 | this.insertNode(root.left, newNode); 10 | } else { 11 | root.left = newNode; 12 | return; 13 | } 14 | } else { 15 | if (root.right) { 16 | this.insertNode(root.right, newNode); 17 | } else { 18 | root.right = newNode; 19 | return; 20 | } 21 | } 22 | } 23 | addNode(newNode) { 24 | if (this.root) { 25 | this.insertNode(this.root, newNode); 26 | } else { 27 | this.root = newNode; 28 | } 29 | } 30 | } 31 | // create a new tree and new node 32 | const tree = new Tree(); 33 | const node = new Node(5); 34 | 35 | // add the node to the tree using addNode 36 | tree.addNode(node); 37 | 38 | // the new node becomes the tree's root 39 | console.log(tree.root.data); // 5 40 | 41 | module.exports = Tree; 42 | -------------------------------------------------------------------------------- /blockchain-storage/Binary search tree/6-search-Tree.js: -------------------------------------------------------------------------------- 1 | const Node = require("./Node.js"); 2 | class Tree { 3 | constructor() { 4 | this.root = null; 5 | } 6 | insertNode(root, newNode) { 7 | if (newNode.data < root.data) { 8 | if (root.left) { 9 | this.insertNode(root.left, newNode); 10 | } else { 11 | root.left = newNode; 12 | return; 13 | } 14 | } else { 15 | if (root.right) { 16 | this.insertNode(root.right, newNode); 17 | } else { 18 | root.right = newNode; 19 | return; 20 | } 21 | } 22 | } 23 | addNode(newNode) { 24 | if (this.root) { 25 | this.insertNode(this.root, newNode); 26 | } else { 27 | this.root = newNode; 28 | } 29 | } 30 | hasNode(data) { 31 | return this.findNode(this.root, data); 32 | } 33 | findNode(root, data) { 34 | if (!root) { 35 | return false; // if nothitng is found return false 36 | } else if (root.data === data) { 37 | // base case for recursion 38 | return true; 39 | } else if (root.data > data) { 40 | return this.findNode(root.left, data); // recursive call to the left 41 | } else if (root.data < data) { 42 | return this.findNode(root.right, data); // recursive call to the right 43 | } 44 | } 45 | } 46 | const tree = new Tree(); 47 | const node1 = new Node(4); 48 | 49 | tree.addNode(node1); 50 | 51 | console.log(tree.hasNode(4)); // true 52 | console.log(tree.hasNode(7)); // false 53 | module.exports = Tree; 54 | -------------------------------------------------------------------------------- /blockchain-storage/merkel-tree/1-combineTwoLeaves-index.js: -------------------------------------------------------------------------------- 1 | class MerkleTree { 2 | constructor(leaves, concat) { 3 | this.leaves = leaves; 4 | this.concat = concat; 5 | } 6 | getRoot() { 7 | this.root = this.concat(this.leaves[0], this.leaves[1]); 8 | return this.root; 9 | } 10 | } 11 | 12 | module.exports = MerkleTree; 13 | -------------------------------------------------------------------------------- /blockchain-storage/merkel-tree/2-multipleLayers-index.js: -------------------------------------------------------------------------------- 1 | class MerkleTree { 2 | constructor(leaves, concat) { 3 | this.leaves = leaves; 4 | this.concat = concat; 5 | } 6 | getRoot() { 7 | let currentLayer = this.leaves; 8 | while (currentLayer.length > 1) { 9 | let newLayer = []; 10 | let isOdd = currentLayer.length % 2 !== 0; 11 | let loopRange = isOdd 12 | ? currentLayer.length - 1 13 | : currentLayer.length; 14 | 15 | for (let i = 0; i < loopRange; i += 2) { 16 | newLayer.push( 17 | this.concat(currentLayer[i], currentLayer[i + 1]) 18 | ); 19 | } 20 | 21 | if (isOdd) { 22 | newLayer.push(currentLayer[currentLayer.length - 1]); 23 | } 24 | 25 | currentLayer = newLayer; 26 | } 27 | 28 | return currentLayer[0]; 29 | } 30 | } 31 | 32 | module.exports = MerkleTree; 33 | -------------------------------------------------------------------------------- /blockchain-storage/merkel-tree/3-oddLeaves-index.js: -------------------------------------------------------------------------------- 1 | // NOTE: We have same code for OddLeaves because we already handled in previous section 2 | class MerkleTree { 3 | constructor(leaves, concat) { 4 | this.leaves = leaves; 5 | this.concat = concat; 6 | } 7 | getRoot() { 8 | let currentLayer = this.leaves; 9 | while (currentLayer.length > 1) { 10 | let newLayer = []; 11 | let isOdd = currentLayer.length % 2 !== 0; 12 | let loopRange = isOdd 13 | ? currentLayer.length - 1 14 | : currentLayer.length; 15 | 16 | for (let i = 0; i < loopRange; i += 2) { 17 | newLayer.push( 18 | this.concat(currentLayer[i], currentLayer[i + 1]) 19 | ); 20 | } 21 | 22 | if (isOdd) { 23 | newLayer.push(currentLayer[currentLayer.length - 1]); 24 | } 25 | 26 | currentLayer = newLayer; 27 | } 28 | 29 | return currentLayer[0]; 30 | } 31 | } 32 | 33 | module.exports = MerkleTree; 34 | -------------------------------------------------------------------------------- /blockchain-storage/merkel-tree/4-buildTheProof-index.js: -------------------------------------------------------------------------------- 1 | class MerkleTree { 2 | constructor(leaves, concat) { 3 | this.leaves = leaves; 4 | this.concat = concat; 5 | } 6 | getRoot() { 7 | let currentLayer = this.leaves; 8 | while (currentLayer.leaves > 1) { 9 | let newLayer = []; 10 | const isOdd = currentLayer.length % 2 !== 0; 11 | const toRange = isOdd 12 | ? currentLayer.length - 1 13 | : currentLayer.length; //if element are odd i number then we don't need to loop to the end 14 | for (let i = 0; i < toRange; i += 2) { 15 | let left = currentLayer[i]; 16 | let right = currentLayer[i + 1]; 17 | newLayer.push(this.concat(left, right)); 18 | } 19 | if (isOdd) newLayer.push(currentLayer[currentLayer.length - 1]); 20 | currentLayer = newLayer; 21 | } 22 | return currentLayer[0]; 23 | } 24 | getProof(index) { 25 | let currentLayer = this.leaves; 26 | 27 | let proof = []; 28 | while (currentLayer.length > 1) { 29 | let newLayer = []; 30 | let isOdd = currentLayer.length % 2 !== 0; 31 | let toRange = isOdd ? currentLayer.length - 1 : currentLayer.length; 32 | 33 | for (let i = 0; i < toRange; i += 2) { 34 | newLayer.push( 35 | this.concat(currentLayer[i], currentLayer[i + 1]) 36 | ); 37 | if (i === index) { 38 | proof.push({ data: currentLayer[i + 1], left: false }); 39 | } 40 | if (i + 1 === index) { 41 | proof.push({ data: currentLayer[i], left: true }); 42 | } 43 | } 44 | 45 | if (isOdd) { 46 | newLayer.push(currentLayer[currentLayer.length - 1]); 47 | } 48 | 49 | index = Math.floor(index / 2); 50 | currentLayer = newLayer; 51 | } 52 | 53 | return proof; 54 | } 55 | } 56 | 57 | module.exports = MerkleTree; 58 | -------------------------------------------------------------------------------- /blockchain-storage/merkel-tree/5-verifyYourProof-verify.js: -------------------------------------------------------------------------------- 1 | function verifyProof(proof, node, root, concat) { 2 | for (let i = 0; i < proof.length; i++) { 3 | let proofNode = proof[i]; 4 | if (proofNode.left) { 5 | node = concat(proofNode.data, node); 6 | } else { 7 | node = concat(node, proofNode.data); 8 | } 9 | } 10 | return node === root; 11 | } 12 | 13 | module.exports = verifyProof; 14 | -------------------------------------------------------------------------------- /blockchain-storage/tries/1-constructor-TrieNode.js: -------------------------------------------------------------------------------- 1 | class TrieNode { 2 | constructor(key) { 3 | this.key = key; 4 | this.children = {}; 5 | this.isWord = false; 6 | } 7 | } 8 | 9 | module.exports = TrieNode; 10 | -------------------------------------------------------------------------------- /blockchain-storage/tries/1-constructor-tries.js: -------------------------------------------------------------------------------- 1 | const TrieNode = require("./TrieNode"); 2 | 3 | class Trie { 4 | constructor() { 5 | this.root = new TrieNode(); 6 | } 7 | } 8 | module.exports = Trie; 9 | -------------------------------------------------------------------------------- /blockchain-storage/tries/2-insert-tries.js: -------------------------------------------------------------------------------- 1 | const TrieNode = require("./1-constructor-TrieNode"); 2 | class Trie { 3 | constructor() { 4 | this.root = new TrieNode(); 5 | } 6 | insert(word) { 7 | let currentnode = this.root; 8 | const chararr = word.split(""); 9 | 10 | for (let i = 0; i < chararr.length; i++) { 11 | const alphabate = chararr[i]; 12 | if (!(alphabate in currentnode.children)) { 13 | currentnode.children[alphabate] = new TrieNode(alphabate); 14 | } 15 | currentnode = currentnode.children[alphabate]; 16 | } 17 | currentnode.isWord = true; 18 | } 19 | contains(word) { 20 | let currentNode = this.root; 21 | let charArr = word.split(""); 22 | 23 | for (let i = 0; i < charArr.length; i++) { 24 | const letter = charArr[i]; 25 | if (!(letter in currentNode.children)) { 26 | console.log("No word"); 27 | return false; 28 | } 29 | currentNode = currentNode.children[letter]; 30 | } 31 | if (currentNode.isWord) { 32 | console.log(true); 33 | return true; 34 | } else { 35 | console.log(false); 36 | return false; 37 | } 38 | } 39 | } 40 | const node = new TrieNode(); 41 | const trie = new Trie(); 42 | trie.insert("healthly"); 43 | trie.contains("health"); 44 | 45 | module.exports = Trie; 46 | -------------------------------------------------------------------------------- /blockchain-storage/tries/3-insert-branching-trie.js: -------------------------------------------------------------------------------- 1 | const TrieNode = require("./TrieNode"); 2 | 3 | class Trie { 4 | constructor() { 5 | this.root = new TrieNode(); 6 | } 7 | insert(string) { 8 | let currentNode = this.root; 9 | const charArr = string.split(""); 10 | 11 | for (let i = 0; i < charArr.length; i++) { 12 | const letter = charArr[i]; 13 | if (!(letter in currentNode.children)) { 14 | currentNode.children[letter] = new TrieNode(letter); 15 | } 16 | currentNode = currentNode.children[letter]; 17 | } 18 | currentNode.isWord = true; 19 | } 20 | } 21 | const trie = new Trie(); 22 | module.exports = Trie; 23 | -------------------------------------------------------------------------------- /blockchain-storage/tries/4-contains-trie.js: -------------------------------------------------------------------------------- 1 | const TrieNode = require("./TrieNode"); 2 | 3 | class Trie { 4 | constructor() { 5 | this.root = new TrieNode(); 6 | } 7 | insert(string) { 8 | let currentNode = this.root; 9 | const charArr = string.split(""); 10 | 11 | for (let i = 0; i < charArr.length; i++) { 12 | const letter = charArr[i]; 13 | if (!(letter in currentNode.children)) { 14 | currentNode.children[letter] = new TrieNode(letter); 15 | } 16 | currentNode = currentNode.children[letter]; 17 | } 18 | currentNode.isWord = true; 19 | } 20 | contains(word) { 21 | let currentNode = this.root; 22 | let charArr = word.split(""); 23 | 24 | for (let i = 0; i < charArr.length; i++) { 25 | const letter = charArr[i]; 26 | if (!(letter in currentNode.children)) { 27 | return false; 28 | } 29 | currentNode = currentNode.children[letter]; 30 | } 31 | if (currentNode.isWord) { 32 | return true; 33 | } else { 34 | return false; 35 | } 36 | } 37 | } 38 | const trie = new Trie(); 39 | 40 | module.exports = Trie; 41 | -------------------------------------------------------------------------------- /blockchain-storage/utxo-model/1-transaction-output-TXO.js: -------------------------------------------------------------------------------- 1 | class TXO { 2 | constructor(owner, amount) { 3 | this.owner = owner; 4 | this.amount = amount; 5 | this.spent = false; 6 | } 7 | spend() { 8 | this.spent = true; 9 | } 10 | } 11 | const txo = new TXO("1FNv3tXLkejPBYxDHDaZz6ENNz3zn3G4GM", 10); 12 | console.log("Owner address: ", txo.owner); //should be 1FNv3tXLkejPBYxDHDaZz6ENNz3zn3G4GM 13 | console.log("Amount: ", txo.amount); //should be 10 14 | console.log("IsSpent", txo.spent); //should be false 15 | txo.spend(); // this will spend the amount 16 | console.log("IsSpent", txo.spent); //should be true 17 | module.exports = TXO; 18 | -------------------------------------------------------------------------------- /blockchain-storage/utxo-model/2-spentTXOs.transaction.js: -------------------------------------------------------------------------------- 1 | class Transaction { 2 | constructor(inputUTXOs, outputUTXOs) { 3 | this.inputUTXOs = inputUTXOs; 4 | this.outputUTXOs = outputUTXOs; 5 | } 6 | execute() { 7 | for (let utxo of this.inputUTXOs) { 8 | if (utxo.spent) { 9 | throw "UTXO already spent"; 10 | } 11 | } 12 | } 13 | } 14 | 15 | module.exports = Transaction; 16 | -------------------------------------------------------------------------------- /blockchain-storage/utxo-model/3-sufficientAmount-transaction.js: -------------------------------------------------------------------------------- 1 | class Transaction { 2 | constructor(inputUTXOs, outputUTXOs) { 3 | this.inputUTXOs = inputUTXOs; 4 | this.outputUTXOs = outputUTXOs; 5 | } 6 | execute() { 7 | let totalInput = 0; 8 | let totalOutput = 0; 9 | for (let utxo of this.inputUTXOs) { 10 | if (utxo.spent) { 11 | throw "UTXO already spent"; 12 | } 13 | totalInput += utxo.amount; 14 | } 15 | for (let utxo of this.outputUTXOs) { 16 | totalOutput += utxo.amount; 17 | } 18 | 19 | if (totalInput < totalOutput) { 20 | throw new Error("You Don't Have Enough to Spend"); 21 | } 22 | } 23 | } 24 | 25 | module.exports = Transaction; 26 | -------------------------------------------------------------------------------- /blockchain-storage/utxo-model/4-successfulExecute-transaction.js: -------------------------------------------------------------------------------- 1 | class Transaction { 2 | constructor(inputUTXOs, outputUTXOs) { 3 | this.inputUTXOs = inputUTXOs; 4 | this.outputUTXOs = outputUTXOs; 5 | } 6 | execute() { 7 | let totalInput = 0; 8 | let totalOutput = 0; 9 | for (let utxo of this.inputUTXOs) { 10 | if (utxo.spent) { 11 | throw "UTXOs already spent"; 12 | } 13 | totalInput += utxo.amount; 14 | } 15 | for (let utxo of this.outputUTXOs) { 16 | totalOutput += utxo.amount; 17 | } 18 | 19 | if (totalOutput > totalInput) { 20 | throw new Error("You Don't Have Enough to Spend"); 21 | } 22 | 23 | // NOTE: sequence of code is important.Below code will executed only if no error is thrown above. 24 | for (let utxo of this.inputUTXOs) { 25 | utxo.spent = true; 26 | } 27 | } 28 | } 29 | 30 | module.exports = Transaction; 31 | -------------------------------------------------------------------------------- /blockchain-storage/utxo-model/5-minerFee-transaction.js: -------------------------------------------------------------------------------- 1 | class Transaction { 2 | constructor(inputUTXOs, outputUTXOs) { 3 | this.inputUTXOs = inputUTXOs; 4 | this.outputUTXOs = outputUTXOs; 5 | } 6 | execute() { 7 | let totalInput = 0; 8 | let totalOutput = 0; 9 | for (let utxo of this.inputUTXOs) { 10 | if (utxo.spent) { 11 | throw "UTXOs already spent"; 12 | } 13 | totalInput += utxo.amount; 14 | } 15 | for (let utxo of this.outputUTXOs) { 16 | totalOutput += utxo.amount; 17 | } 18 | 19 | if (totalInput < totalOutput) { 20 | throw new Error("You Don't Have Enough to Spend"); 21 | } 22 | 23 | for (let utxo of this.inputUTXOs) { 24 | utxo.spent = true; 25 | } 26 | 27 | const minerFee = totalInput - totalOutput; 28 | if (minerFee < 0) { 29 | throw "Miner fee less then 0.Miner can't loose money for you"; 30 | } 31 | this.fee = minerFee; 32 | } 33 | } 34 | 35 | module.exports = Transaction; 36 | -------------------------------------------------------------------------------- /blockchain-storage/utxo-model/offTopic.tx-script.js: -------------------------------------------------------------------------------- 1 | // NOTE: This code is only for Brainstroming and It is not tested or executed yet. I may be completely wrong here. 2 | class Tx { 3 | // lets set the tx data 4 | constructor(to, amount) { 5 | this.to = to; 6 | this.amount = amount; 7 | } 8 | // Let's create locking script also called scriptSig 9 | sign(privateKey, inputUtxos) { 10 | return privateKey + inputUtxos; // example signing 11 | } 12 | scriptSig() { 13 | this.privateKey = "1FNv3tXLkejPBYxDHDaZz6ENNz3zn3G4GM"; //random zibberish 14 | const sender = "1FNv3tXLkejPBYxDHDaZz6ENNz3zn3G4GM"; //random zibberish 15 | const recepient = this.to; 16 | const signature = this.sign(this.privateKey, inputUtxos); 17 | const conditionToSpendUtxos = "wait for 30 days"; 18 | return { 19 | sign: signature, 20 | sender: sender, 21 | conditionToSpendUtxos: conditionToSpendUtxos, 22 | recepient, 23 | inputUtxos, // some utxos 24 | amount: this.amount, 25 | }; 26 | } 27 | // Let's create unlocking script also called scriptPubKey 28 | scriptPubKey(scriptSig) { 29 | const { 30 | sign, 31 | sender, 32 | conditionToSpendUtxos, 33 | recepient, 34 | inputUtxos, 35 | amount, 36 | } = scriptSig; 37 | if (conditionToSpendUtxos === true) { 38 | return "GO AHEAD AND SPEND THE UTXOS"; 39 | } 40 | } 41 | } 42 | /********************* 43 | * WHAT IS SCRIPT * 44 | *********************/ 45 | /*********************************************************************************************************************** 46 | * A SCRIPT IN THE BITCOIN TRANSACTION UNLOCKS THE INPUT UTXOS BY VERIFYING THEIR DIGITAL SIGNATURES. A LOCKING SCRIPT SETS THE CONDITIONS FOR HOW THE UTXO OUTPUTS CAN BE SPENT; FOR EXAMPLE, POST DATING THE PAYMENT FOR 30 DAYS * 47 | ***********************************************************************************************************************/ 48 | 49 | /*********************************************************************************************************************** 50 | * WHAT IS TX INPUT? * * 51 | * => TX INPUT ARE THE UTXOS THAT ARE USED TO FUND THE TRANSACTION. * 52 | * WHAT IS TX OUTPUT? * 53 | * => TX OUTPUT ARE THE UTXOS THAT ARE CREATED BY THE TRANSACTION.IN SIMPLE TERM OUTPUT ARE THE AMOUNT THAT ARE SENT TO THE RECEIVER * 54 | ***********************************************************************************************************************/ 55 | -------------------------------------------------------------------------------- /blockexplorer/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /blockexplorer/README.md: -------------------------------------------------------------------------------- 1 | # Minimalistic Ethereum Block Explorer 2 | 3 | ## [Live Url](https://chainscan-seven.vercel.app/) 4 | 5 | ![alt text](https://github.com/pokhrelanmol/chainscan/blob/c5c7ade45146a8b325e040c862c058ae7e7365c9/src/assets/logo.png) 6 | 7 | ## Features 8 | 9 | - ✅ Display ten recent blocks and transactions on homepage 10 | - ✅ Allow users to click on a block number in the webpage to get the block's details including its list of transactions 11 | - ✅ From the list of transactions allow users to click on specific transactions to get the details of the transaction 12 | - ✅ Make an accounts page where a user can look up their balance or someone else's balance 13 | - ✅ Given a contract address and token id, can you get the NFT's metadata? 14 | - ✅ What is the floor price of an NFT right now? 15 | 16 | ## More Todo 17 | 18 | - Did a pending transaction get mined? 19 | - What transfers did an address receive this year? 20 | -------------------------------------------------------------------------------- /blockexplorer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blockexplorer", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^12.0.0", 8 | "@testing-library/user-event": "^12.0.0", 9 | "alchemy-sdk": "^2.2.3", 10 | "react": "^17.0.2", 11 | "react-dom": "^17.0.2", 12 | "react-router-dom": "^6.0.2", 13 | "react-scripts": "5.0.1", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": [ 24 | "react-app", 25 | "react-app/jest" 26 | ] 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | }, 40 | "devDependencies": { 41 | "autoprefixer": "^10.4.13", 42 | "postcss": "^8.4.19", 43 | "tailwindcss": "^3.2.4" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /blockexplorer/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /blockexplorer/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiddheshKukade/AU_ETH_Bootcamp/fc99de609aaf0d33edf3ce7d85e7a3468ebf3235/blockexplorer/public/favicon.ico -------------------------------------------------------------------------------- /blockexplorer/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /blockexplorer/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiddheshKukade/AU_ETH_Bootcamp/fc99de609aaf0d33edf3ce7d85e7a3468ebf3235/blockexplorer/public/logo192.png -------------------------------------------------------------------------------- /blockexplorer/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiddheshKukade/AU_ETH_Bootcamp/fc99de609aaf0d33edf3ce7d85e7a3468ebf3235/blockexplorer/public/logo512.png -------------------------------------------------------------------------------- /blockexplorer/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /blockexplorer/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /blockexplorer/src/App.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiddheshKukade/AU_ETH_Bootcamp/fc99de609aaf0d33edf3ce7d85e7a3468ebf3235/blockexplorer/src/App.css -------------------------------------------------------------------------------- /blockexplorer/src/App.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import Blocks from "./components/Blocks"; 3 | import Header from "./components/Header"; 4 | import Search from "./components/Search"; 5 | import Transactions from "./components/Transactions"; 6 | import { Route, Routes } from "react-router-dom"; 7 | import { getLastTenBlocks } from "./services"; 8 | import Block from "./components/Block"; 9 | import Transaction from "./components/Transaction"; 10 | import AccountInfo from "./components/AccountTxs"; 11 | import AccountTxs from "./components/AccountTxs"; 12 | import AccountBalance from "./components/AccountBalance"; 13 | import Nft from "./components/Nft"; 14 | 15 | function App() { 16 | return ( 17 |
18 |
19 | 20 | 24 |
25 | 26 | 27 |
28 |
29 | } 30 | /> 31 | } /> 32 | } /> 33 | } /> 34 | } /> 35 | } /> 36 | 37 | 38 | ); 39 | } 40 | 41 | export default App; 42 | -------------------------------------------------------------------------------- /blockexplorer/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiddheshKukade/AU_ETH_Bootcamp/fc99de609aaf0d33edf3ce7d85e7a3468ebf3235/blockexplorer/src/assets/logo.png -------------------------------------------------------------------------------- /blockexplorer/src/components/AccountBalance.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { useEffect } from "react"; 3 | import { formatEther } from "../helper"; 4 | import { getAccountBalance } from "../services"; 5 | import Search from "./Search"; 6 | 7 | const AccountBalance = () => { 8 | const [accountBalance, setAccountBalance] = useState(null); 9 | 10 | const handleSearch = async (inputValues) => { 11 | if (!inputValues) { 12 | alert("Please enter an address"); 13 | return; 14 | } 15 | const balance = await getAccountBalance(inputValues); 16 | setAccountBalance(balance.toString()); 17 | return () => { 18 | setAccountBalance(null); 19 | }; 20 | }; 21 | return ( 22 |
23 | 28 | {accountBalance === null ? ( 29 |
30 | Please Search Balance for some Address{" "} 31 |
32 | ) : ( 33 |
34 |
35 | Your Account Balance:{" "} 36 | 37 | {formatEther(accountBalance)} ETH 38 | 39 |
40 |
41 | )} 42 |
43 | ); 44 | }; 45 | 46 | export default AccountBalance; 47 | -------------------------------------------------------------------------------- /blockexplorer/src/components/AccountTxs.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { useNavigate, useParams } from "react-router-dom"; 3 | import { formatAddress, formatEther, joinClasses } from "../helper"; 4 | import { getAccountTxs } from "../services"; 5 | 6 | const Transaction = ({ 7 | blockNumber, 8 | from, 9 | to, 10 | amount, 11 | txHash, 12 | timeStamp, 13 | nonce, 14 | }) => { 15 | const navigate = useNavigate(); 16 | return ( 17 |
31 |
32 | Block Number:{" "} 33 | {blockNumber} 34 |
35 |
36 | From:{" "} 37 | navigate(`/transactions/${from}`)} 39 | className="text-blue-600 cursor-pointer" 40 | > 41 | {" "} 42 | {formatAddress(from)} 43 | 44 |
45 |
46 | To:{" "} 47 | navigate(`/transactions/${to}`)} 49 | className="text-blue-600 cursor-pointer" 50 | > 51 | {" "} 52 | {formatAddress(to)} 53 | 54 |
55 |
56 | Amount:{" "} 57 | 58 | {" "} 59 | {formatEther(amount.toString())} 60 | ETH 61 | 62 |
63 |
64 | Transaction Hash:{" "} 65 | navigate(`/transaction/${txHash}`)} 68 | > 69 | {formatAddress(txHash)} 70 | 71 |
72 |
73 | TimeStamp: {timeStamp} 74 |
75 |
76 | Nonce: {nonce} 77 |
78 |
79 | ); 80 | }; 81 | const AccountTxs = () => { 82 | const { address } = useParams(); 83 | const [accountTxs, setAccountTxs] = useState(); 84 | (async () => { 85 | const data = await getAccountTxs(address); 86 | setAccountTxs(data); 87 | })(); 88 | 89 | return ( 90 |
91 |

92 | {" "} 93 | Account Transaction Details 94 |

95 |
96 | {!accountTxs 97 | ? "Loading..." 98 | : accountTxs.map((tx) => { 99 | return ( 100 | 109 | ); 110 | })} 111 |
112 |
113 | ); 114 | }; 115 | 116 | export default AccountTxs; 117 | -------------------------------------------------------------------------------- /blockexplorer/src/components/Block.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useState } from "react"; 3 | import { useNavigate, useParams } from "react-router-dom"; 4 | import { formatAddress, formatEther, joinClasses } from "../helper"; 5 | import { getIndividualBlock } from "../services"; 6 | const Block = () => { 7 | const navigate = useNavigate(); 8 | const { blockNumber } = useParams(); 9 | const [blockData, setBlockData] = useState(); 10 | (async () => { 11 | const data = await getIndividualBlock(blockNumber); 12 | setBlockData(data); 13 | })(); 14 | 15 | // console.log(formatEther(baseFeePerGas.toString())); 16 | return ( 17 |
18 |

Block Details

19 |
31 | {!blockData ? ( 32 | "Loading..." 33 | ) : ( 34 | <> 35 |
36 | Base Fee :{" "} 37 | 38 | {" "} 39 | {formatEther( 40 | blockData.baseFeePerGas.toString() || "" 41 | )}{" "} 42 | ETH 43 | 44 |
45 |
46 | Gas Limit:{" "} 47 | 48 | {" "} 49 | {formatEther( 50 | blockData.gasLimit.toString() || "" 51 | )}{" "} 52 | ETH 53 | 54 |
55 |
56 | Gas Used:{" "} 57 | 58 | {" "} 59 | {formatEther( 60 | blockData.gasUsed.toString() || "" 61 | )}{" "} 62 | ETH 63 | 64 |
65 |
66 | Block Hash:{" "} 67 | 68 | {" "} 69 | {formatAddress(blockData.hash || "")}{" "} 70 | 71 |
72 |
73 | Validator:{" "} 74 | 75 | {" "} 76 | {formatAddress(blockData.miner || "")}{" "} 77 | 78 |
79 |
80 | Parent Hash:{" "} 81 | 82 | {" "} 83 | {formatAddress(blockData.parentHash || "")}{" "} 84 | 85 |
86 |
87 | {/* TODO: Install dayjs and format time */} 88 | Timestamp:{" "} 89 | 90 | {" "} 91 | {blockData.timestamp || ""}{" "} 92 | 93 |
94 |
95 | Transactions Count:{" "} 96 | 97 | {blockData.transactions.length}{" "} 98 | 99 |
100 |
101 | Transactions 102 | {blockData.transactions.map((tx) => ( 103 |
    104 |
  • 107 | navigate(`/transaction/${tx}`) 108 | } 109 | > 110 | {tx} 111 |
  • 112 |
113 | ))} 114 |
115 | 116 | )} 117 |
118 |
119 | ); 120 | }; 121 | 122 | export default Block; 123 | -------------------------------------------------------------------------------- /blockexplorer/src/components/Blocks.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useState } from "react"; 3 | import { formatAddress, joinClasses } from "../helper"; 4 | import { getLastTenBlocks } from "../services"; 5 | import { useNavigate } from "react-router-dom"; 6 | const BlockMinimal = ({ blockNumber, txCount, validator }) => { 7 | const navigate = useNavigate(); 8 | const handleBlockDetails = async (blockNumber) => { 9 | navigate(`/block/${blockNumber}`); 10 | }; 11 | return ( 12 |
22 |
23 | Block:{" "} 24 | handleBlockDetails(blockNumber)} 27 | > 28 | {blockNumber} 29 | 30 |
31 |
32 | No of Txs {txCount} 33 |
34 |
35 | Validator : 36 | 38 | navigate(`/transavalidatorctions/${validator}`) 39 | } 40 | className="text-blue-600 cursor-pointer" 41 | > 42 | {formatAddress(validator)} 43 | 44 |
45 |
46 | ); 47 | }; 48 | const Blocks = () => { 49 | const [blocks, setBlocks] = useState([]); 50 | (async () => { 51 | const _blocks = await getLastTenBlocks(); 52 | setBlocks(_blocks); 53 | })(); 54 | return ( 55 |
56 |

Latest Blocks

57 | {blocks.length ? ( 58 | blocks.map(({ miner, number, transactions }) => ( 59 | 65 | )) 66 | ) : ( 67 |
Loading...
68 | )} 69 |
70 | ); 71 | }; 72 | 73 | export default Blocks; 74 | -------------------------------------------------------------------------------- /blockexplorer/src/components/Header.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Navigate, useNavigate } from "react-router-dom"; 3 | import { joinClasses } from "../helper"; 4 | import logo from "../assets/logo.png"; 5 | const Header = () => { 6 | const navigate = useNavigate(); 7 | return ( 8 |
17 | {/* logo */} 18 |
19 | navigate("/")} 21 | className={joinClasses("w-24", "h-24")} 22 | src={logo} 23 | alt="logo" 24 | /> 25 |
26 | 48 |
49 | ); 50 | }; 51 | 52 | export default Header; 53 | -------------------------------------------------------------------------------- /blockexplorer/src/components/Nft.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { joinClasses } from "../helper"; 3 | import { getNftMetadata } from "../services"; 4 | import Search from "./Search"; 5 | const Nft = () => { 6 | const [nftMetadata, setNftMetadata] = useState(); 7 | const [inputValues, setInputValues] = useState({}); 8 | const handleChange = (e) => { 9 | setInputValues({ ...inputValues, [e.target.name]: e.target.value }); 10 | }; 11 | const handleSearch = async (e) => { 12 | e.preventDefault(); 13 | if (!inputValues.nftAddress || !inputValues.tokenId) { 14 | alert("Both fields are required "); 15 | return; 16 | } 17 | const _nftMetadata = await getNftMetadata( 18 | inputValues.nftAddress.toString(), 19 | inputValues.tokenId.toString() 20 | ); 21 | console.log(_nftMetadata); 22 | setNftMetadata(_nftMetadata); 23 | }; 24 | return ( 25 |
26 |
Search Nft
27 |

28 | Note: Only NFT listed on openSea is supported 29 |

30 |
34 | 47 | 60 | 70 |
71 | {/* Display Nft */} 72 | {nftMetadata && ( 73 |
82 | Nft 87 |
88 | Nft Address:{" "} 89 | 90 | {nftMetadata.address} 91 | 92 |
93 |
94 | Collection Name:{" "} 95 | 96 | {nftMetadata.name} 97 | 98 |
99 |
100 | Floor Price:{" "} 101 | 102 | {nftMetadata.openSea.floorPrice} ETH 103 | 104 |
105 |
106 | Description:{" "} 107 | 108 | {nftMetadata.openSea.description} 109 | 110 |
111 |
112 | )} 113 |
114 | ); 115 | }; 116 | 117 | export default Nft; 118 | -------------------------------------------------------------------------------- /blockexplorer/src/components/Search.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { joinClasses } from "../helper"; 3 | 4 | const Search = ({ handleSearch, placeholder, name }) => { 5 | const [inputValue, setInputValue] = useState(); 6 | const handleChange = (e) => { 7 | setInputValue(e.target.value); 8 | }; 9 | return ( 10 |
11 | 24 | 37 |
38 | ); 39 | }; 40 | 41 | export default Search; 42 | -------------------------------------------------------------------------------- /blockexplorer/src/components/Transaction.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { useNavigate, useParams } from "react-router-dom"; 3 | import { formatEther, joinClasses } from "../helper"; 4 | import { getIndividualTransaction } from "../services"; 5 | 6 | const Transaction = () => { 7 | const { txHash } = useParams(); 8 | const [txData, setTxData] = useState(); 9 | const navigate = useNavigate(); 10 | (async () => { 11 | const data = await getIndividualTransaction(txHash); 12 | setTxData(data); 13 | })(); 14 | return ( 15 |
16 |

Transaction Details

17 |
30 | {!txData ? ( 31 | "Loading..." 32 | ) : ( 33 | <> 34 |
35 | Block Hash:{" "} 36 | 37 | {" "} 38 | {txData.blockHash}{" "} 39 | 40 |
41 |
42 | Block Number:{" "} 43 | 44 | {" "} 45 | {txData.blockNumber} 46 | 47 |
48 |
49 | Nonce:{" "} 50 | 51 | {" "} 52 | {txData.nonce}{" "} 53 | 54 |
55 |
56 | Transaction Hash:{" "} 57 | 58 | {" "} 59 | {txData.hash}{" "} 60 | 61 |
62 |
63 | From:{" "} 64 | 66 | navigate(`/transactions/${txData.from}`) 67 | } 68 | className="text-blue-600 cursor-pointer" 69 | > 70 | {" "} 71 | {txData.from}{" "} 72 | 73 |
74 |
75 | To:{" "} 76 | 78 | navigate(`/transactions/${txData.to}`) 79 | } 80 | className="text-blue-600 cursor-pointer" 81 | > 82 | {" "} 83 | {txData.to}{" "} 84 | 85 |
86 |
87 | Value:{" "} 88 | 89 | {" "} 90 | {formatEther(txData.value.toString())} ETH 91 | 92 |
93 |
94 | Gas Limit :{" "} 95 | 96 | {" "} 97 | {formatEther(txData.gasLimit.toString())} ETH 98 | 99 |
100 |
101 | {/* TODO: Install dayjs and format time */} 102 | Gas Price:{" "} 103 | 104 | {" "} 105 | {formatEther(txData.gasPrice.toString())} ETH 106 | 107 |
108 | 109 |
110 | v:{" "} 111 | {txData.v} 112 |
113 |
114 | r:{" "} 115 | {txData.r} 116 |
117 |
118 | s:{" "} 119 | 120 | {txData.s} 121 | {""} 122 | 123 |
124 | 125 | )} 126 |
127 |
128 | ); 129 | }; 130 | 131 | export default Transaction; 132 | -------------------------------------------------------------------------------- /blockexplorer/src/components/Transactions.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { formatAddress, formatEther, joinClasses } from "../helper"; 4 | import { getLastTenTxs } from "../services"; 5 | const TransactionMinimal = ({ from, to, txhash, amount }) => { 6 | const navigate = useNavigate(); 7 | const handleTransactionDetails = async (txHash) => { 8 | navigate(`/transaction/${txHash}`); 9 | }; 10 | return ( 11 |
22 |
23 | Tx Hash:{" "} 24 | handleTransactionDetails(txhash)} 27 | > 28 | {formatAddress(txhash)} 29 | 30 |
{" "} 31 |
navigate(`/transactions/${from}`)}> 32 | From:{" "} 33 | 34 | {formatAddress(from)} 35 | 36 |
37 |
navigate(`/transations/${to}`)}> 38 | To:{" "} 39 | 40 | {formatAddress(to)} 41 | 42 |
43 |
44 | Amount:{" "} 45 | {formatEther(amount)} ETH 46 |
47 |
48 | ); 49 | }; 50 | const Transactions = () => { 51 | const [transactions, setTransactions] = useState([]); 52 | (async () => { 53 | const txs = await getLastTenTxs(); 54 | setTransactions(txs); 55 | })(); 56 | return ( 57 |
58 |

Latest Transactions

59 | {transactions.length ? ( 60 | transactions.map(({ hash, to, from, value }) => ( 61 | 68 | )) 69 | ) : ( 70 |
Loading...
71 | )} 72 |
73 | ); 74 | }; 75 | 76 | export default Transactions; 77 | -------------------------------------------------------------------------------- /blockexplorer/src/helper.js: -------------------------------------------------------------------------------- 1 | import { Utils } from "alchemy-sdk"; 2 | 3 | export const joinClasses = (...classes) => { 4 | return classes.join(" "); 5 | }; 6 | export const formatAddress = (address) => { 7 | return `${address.slice(0, 5)}...${address.slice(-5)}`; 8 | }; 9 | export const formatEther = (wei) => { 10 | return Utils.formatEther(wei); 11 | }; 12 | -------------------------------------------------------------------------------- /blockexplorer/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .block-data { 6 | @apply flex gap-20 border-b justify-between; 7 | } 8 | -------------------------------------------------------------------------------- /blockexplorer/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | 6 | import { BrowserRouter } from "react-router-dom"; 7 | ReactDOM.render( 8 | 9 | 10 | 11 | 12 | , 13 | document.getElementById("root") 14 | ); 15 | -------------------------------------------------------------------------------- /blockexplorer/src/services.js: -------------------------------------------------------------------------------- 1 | import { Alchemy, Network } from "alchemy-sdk"; 2 | import { formatEther } from "./helper"; 3 | const ETHERSCAN_API_KEY = process.env.REACT_APP_ETHERSCAN_API_KEY; 4 | const settings = { 5 | apiKey: process.env.REACT_APP_ALCHEMY_API_KEY, 6 | network: Network.ETH_MAINNET, 7 | }; 8 | 9 | export const alchemy = new Alchemy(settings); 10 | 11 | /******************************************************************* 12 | * MAKE ALL API CALL HERE AND CALL THESE FUNCTIONS ON FIRST RENDER * 13 | *******************************************************************/ 14 | export const getLastTenBlocks = async () => { 15 | const lastTenBlocks = []; 16 | const latestBlock = await alchemy.core.getBlockNumber(); 17 | let block = latestBlock; 18 | while (block > latestBlock - 10) { 19 | const _block = await alchemy.core.getBlock(block); 20 | lastTenBlocks.push(_block); 21 | block--; 22 | } 23 | return lastTenBlocks; 24 | }; 25 | 26 | export const getLastTenTxs = async () => { 27 | const _transactions = []; 28 | const latestBlockNumber = await alchemy.core.getBlockNumber(); 29 | const latestBlock = await alchemy.core.getBlock(latestBlockNumber); 30 | 31 | for (let txHash of latestBlock.transactions.slice(0, 10)) { 32 | const tx = await alchemy.transact.getTransaction(txHash); 33 | _transactions.push(tx); 34 | } 35 | return _transactions; 36 | }; 37 | export const getIndividualBlock = async (blockNumber) => { 38 | const block = await alchemy.core.getBlock(parseInt(blockNumber)); 39 | // console.log(formatEther(block.baseFeePerGas.toString())); 40 | return block; 41 | }; 42 | export const getIndividualTransaction = async (txhash) => { 43 | const tx = await alchemy.transact.getTransaction(txhash); 44 | return tx; 45 | }; 46 | export const getAccountBalance = async (address) => { 47 | const balance = await alchemy.core.getBalance(address, "latest"); 48 | return balance; 49 | }; 50 | /*********************** 51 | * ETHERSCAN API CALLS * 52 | ***********************/ 53 | export const getAccountTxs = async (address) => { 54 | const API_ENDPOINT = `https://api.etherscan.io/api?module=account&action=txlist&address=${address}&startblock=0&endblock=99999999&page=1&offset=20&sort=asc&apikey=${ETHERSCAN_API_KEY}`; 55 | 56 | const response = await fetch(API_ENDPOINT); 57 | const data = await response.json(); 58 | return data.result; 59 | }; 60 | 61 | /*********** 62 | * NFT API * 63 | ***********/ 64 | 65 | export const getNftMetadata = async (nftAddress, tokenId) => { 66 | const metadata = await alchemy.nft.getContractMetadata(nftAddress, tokenId); 67 | return metadata; 68 | }; 69 | -------------------------------------------------------------------------------- /blockexplorer/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /ecdsa-node/client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /ecdsa-node/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ECDSA Node 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ecdsa-node/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ecdsa-node", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "axios": "^0.27.2", 13 | "ethereum-cryptography": "^1.1.2", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0" 16 | }, 17 | "devDependencies": { 18 | "@types/react": "^18.0.17", 19 | "@types/react-dom": "^18.0.6", 20 | "@vitejs/plugin-react": "^2.1.0", 21 | "sass": "^1.54.9", 22 | "vite": "^3.1.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ecdsa-node/client/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ecdsa-node/client/src/Accounts.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useEffect, useState } from "react"; 3 | import server from "./server"; 4 | 5 | const Accounts = () => { 6 | const [accounts, setAccounts] = useState([]); 7 | useEffect(() => { 8 | (async () => { 9 | const { data: _accounts } = await server.get("accounts"); 10 | setAccounts(_accounts); 11 | })(); 12 | }, []); 13 | 14 | return ( 15 |
16 |

Try Playing Around With These Accounts

17 | {accounts.map((account, index) => ( 18 |
19 |
Private Key : {account.privateKey}
20 |
Address : {account.address}
21 |
Balance : {account.balance}
22 |
23 |
24 | ))} 25 |
26 | ); 27 | }; 28 | 29 | export default Accounts; 30 | -------------------------------------------------------------------------------- /ecdsa-node/client/src/App.jsx: -------------------------------------------------------------------------------- 1 | import Wallet from "./Wallet"; 2 | import Transfer from "./Transfer"; 3 | import "./App.scss"; 4 | import { useState } from "react"; 5 | import Accounts from "./Accounts"; 6 | 7 | function App() { 8 | const [balance, setBalance] = useState(0); 9 | const [address, setAddress] = useState(""); 10 | const [privateKey, setPrivateKey] = useState(""); 11 | 12 | return ( 13 |
14 | 22 | 29 | 30 |
31 | ); 32 | } 33 | 34 | export default App; 35 | -------------------------------------------------------------------------------- /ecdsa-node/client/src/App.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Muli", sans-serif; 3 | font-weight: 300; 4 | background-color: #e2e8f0; 5 | padding: 40px; 6 | } 7 | 8 | label { 9 | display: flex; 10 | flex-direction: column; 11 | letter-spacing: 0.05rem; 12 | font-size: 0.8em; 13 | font-weight: 400; 14 | color: #222; 15 | } 16 | 17 | .app { 18 | display: flex; 19 | max-width: 1400px; 20 | flex-wrap: wrap; 21 | gap: 12px; 22 | margin: 0 auto; 23 | } 24 | 25 | .container { 26 | flex-grow: 1; 27 | margin: 0 20px; 28 | background-color: #fff; 29 | border: 1px solid #cbd5e0; 30 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); 31 | border-radius: 0.375rem; 32 | padding: 40px; 33 | 34 | label { 35 | margin: 10px 0; 36 | } 37 | 38 | .button { 39 | margin-top: 10px; 40 | } 41 | } 42 | 43 | input { 44 | padding: 10px 0; 45 | border-radius: 0.125rem; 46 | border: 1px solid rgb(226, 232, 240); 47 | background-color: #fdfdfe; 48 | padding-inline-start: 0.75rem; 49 | font-size: 0.875rem; 50 | } 51 | 52 | .button { 53 | background-color: #319795; 54 | border-radius: 0.125rem; 55 | padding: 10px 20px; 56 | color: white; 57 | display: inline-flex; 58 | text-transform: uppercase; 59 | letter-spacing: 1px; 60 | font-weight: 400; 61 | font-size: 0.9em; 62 | &:hover { 63 | cursor: pointer; 64 | } 65 | } 66 | 67 | .wallet { 68 | display: flex; 69 | flex-direction: column; 70 | 71 | .balance { 72 | text-transform: uppercase; 73 | letter-spacing: 1px; 74 | font-weight: 400; 75 | font-size: 0.9em; 76 | display: inline-flex; 77 | margin-top: 10px; 78 | padding: 0.75rem; 79 | background-color: #f4f6f8; 80 | } 81 | } 82 | 83 | .transfer { 84 | display: flex; 85 | flex-direction: column; 86 | } 87 | .note-title { 88 | color: red; 89 | } 90 | .note-body { 91 | color: gray; 92 | font-size: small; 93 | } 94 | -------------------------------------------------------------------------------- /ecdsa-node/client/src/Transfer.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import server from "./server"; 3 | import { generateSignature } from "./helper"; 4 | import { useEffect } from "react"; 5 | function Transfer({ 6 | fromAddress, 7 | setBalance, 8 | privateKey, 9 | setPrivateKey, 10 | setAddress, 11 | }) { 12 | const [sendAmount, setSendAmount] = useState(""); 13 | const [recipient, setRecipient] = useState(""); 14 | const [addressToNonce, setAddressToNonce] = useState({}); //address => nonce 15 | const [nextNonce, setNextNonce] = useState(1); //nonce is 0 so next nonce is 1 16 | 17 | async function transfer(evt) { 18 | try { 19 | evt.preventDefault(); 20 | const { signatureHex, recoveryBit } = await generateSignature( 21 | sendAmount, 22 | recipient, 23 | privateKey 24 | ); 25 | const doesAddressExists = !fromAddress in addressToNonce; 26 | if (!doesAddressExists) { 27 | setAddressToNonce({ ...addressToNonce, [fromAddress]: 0 }); 28 | } 29 | const { 30 | data: { balance, sender, nonceFromServer }, 31 | } = await server.post(`send`, { 32 | signature: signatureHex, 33 | recoveryBit, 34 | amount: parseInt(sendAmount), 35 | recipient, 36 | nextNonce: !doesAddressExists ? 1 : nextNonce, 37 | }); 38 | setBalance(balance); 39 | setAddressToNonce({ 40 | ...addressToNonce, 41 | [sender]: nonceFromServer, 42 | }); 43 | setNextNonce(nonceFromServer + 1); 44 | setSendAmount(""); 45 | setRecipient(""); 46 | setPrivateKey(""); 47 | setAddress(""); 48 | setBalance(0); 49 | alert("Transfer successful"); 50 | console.log(addressToNonce); 51 | } catch (error) { 52 | console.log(error); 53 | } 54 | } 55 | useEffect(() => {}, [addressToNonce[fromAddress]]); 56 | 57 | return ( 58 |
59 |

Send Transaction

60 | 61 | 69 | 70 | 78 | 79 | 80 |
81 | ); 82 | } 83 | 84 | export default Transfer; 85 | -------------------------------------------------------------------------------- /ecdsa-node/client/src/Wallet.jsx: -------------------------------------------------------------------------------- 1 | import server from "./server"; 2 | import * as secp from "ethereum-cryptography/secp256k1"; 3 | import { toHex } from "ethereum-cryptography/utils"; 4 | import { keccak256 } from "ethereum-cryptography/keccak"; 5 | 6 | function Wallet({ 7 | address, 8 | setAddress, 9 | balance, 10 | setBalance, 11 | privateKey, 12 | setPrivateKey, 13 | }) { 14 | async function onChange(evt) { 15 | // generate public key and address from private key 16 | const _privateKey = evt.target.value; 17 | setPrivateKey(_privateKey); 18 | 19 | const publicKey = secp.getPublicKey(_privateKey); 20 | const publicKeyHash = toHex(keccak256(publicKey)); 21 | // console.log("Public key Hash wallet", publicKeyHash); 22 | const address = `0x${publicKeyHash.slice(-20)}`; // 20 bytes address 23 | setAddress(address); 24 | if (address) { 25 | const { 26 | data: { balance }, 27 | } = await server.get(`balance/${address}`); 28 | setBalance(balance); 29 | } else { 30 | setBalance(0); 31 | } 32 | } 33 | 34 | return ( 35 |
36 |

Your Wallet

37 |

38 | NOTE: You will never ever 39 | will input your Private like this. 40 |
41 | But for the purpose of understanding how public key cryptography 42 | works we are doing it here, 43 |
44 | Generally your wallet will store your private key and sign 45 | message when needed. 46 |

47 | 55 |
Address: {address}
{" "} 56 |
Balance: {balance}
57 |
58 | ); 59 | } 60 | 61 | export default Wallet; 62 | -------------------------------------------------------------------------------- /ecdsa-node/client/src/helper.js: -------------------------------------------------------------------------------- 1 | import * as secp from "ethereum-cryptography/secp256k1"; 2 | import { keccak256 } from "ethereum-cryptography/keccak.js"; 3 | import { toHex } from "ethereum-cryptography/utils.js"; 4 | 5 | export const generateSignature = async (amount, recipient, privateKey) => { 6 | const uint8Array = Uint8Array.from([amount, recipient]); 7 | const messageHash = toHex(uint8Array); 8 | // console.log("Message Hash = ", messageHash); 9 | const [signature, recovery] = await secp.sign(messageHash, privateKey, { 10 | recovered: true, 11 | }); 12 | 13 | const signatureHex = toHex(signature); 14 | 15 | const recoveryBit = recovery; 16 | 17 | return { signatureHex, recoveryBit }; 18 | }; 19 | -------------------------------------------------------------------------------- /ecdsa-node/client/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App"; 4 | 5 | ReactDOM.createRoot(document.getElementById("root")).render( 6 | 7 | 8 | 9 | ); -------------------------------------------------------------------------------- /ecdsa-node/client/src/server.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | const server = axios.create({ 4 | baseURL: "https://ecdsa-node-week1-git-main-pokhrelanmol.vercel.app", 5 | // baseURL: "http://localhost:3042", 6 | }); 7 | 8 | export default server; 9 | -------------------------------------------------------------------------------- /ecdsa-node/client/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()] 7 | }) 8 | -------------------------------------------------------------------------------- /ecdsa-node/readme.md: -------------------------------------------------------------------------------- 1 | ## [Live Url](https://ecdsa-node-week1-p31j.vercel.app/) 2 | 3 | ## ECDSA Node 4 | 5 | This project is an example of using a client and server to facilitate transfers between different addresses. Since there is just a single server on the back-end handling transfers, this is clearly very centralized. We won't worry about distributed consensus for this project. 6 | 7 | However, something that we would like to incoporate is Public Key Cryptography. By using Elliptic Curve Digital Signatures we can make it so the server only allows transfers that have been signed for by the person who owns the associated address. 8 | 9 | ### Client 10 | 11 | The client folder contains a [react app](https://reactjs.org/) using [vite](https://vitejs.dev/). To get started, follow these steps: 12 | 13 | 1. Open up a terminal in the `/client` folder 14 | 2. Run `npm install` to install all the depedencies 15 | 3. Run `npm run dev` to start the application 16 | 4. Now you should be able to visit the app at http://127.0.0.1:5173/ 17 | 18 | ### Server 19 | 20 | The server folder contains a node.js server using [express](https://expressjs.com/). To run the server, follow these steps: 21 | 22 | 1. Open a terminal within the `/server` folder 23 | 2. Run `npm install` to install all the depedencies 24 | 3. Run `node index` to start the server 25 | 26 | The application should connect to the default server port (3042) automatically! 27 | 28 | _Hint_ - Use [nodemon](https://www.npmjs.com/package/nodemon) instead of `node` to automatically restart the server on any changes. 29 | -------------------------------------------------------------------------------- /ecdsa-node/server/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | node_modules -------------------------------------------------------------------------------- /ecdsa-node/server/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const cors = require("cors"); 4 | const port = 3042; 5 | 6 | const secp = require("ethereum-cryptography/secp256k1"); 7 | const { keccak256 } = require("ethereum-cryptography/keccak"); 8 | const { toHex } = require("ethereum-cryptography/utils"); 9 | let addressToNonceServer = {}; 10 | app.use(cors()); 11 | app.use(express.json()); 12 | 13 | const balances = { 14 | // Private Key 98d3f3014d9fb99a4e9a6ec97072e0fa211a875703ccdf17f886d5e8a07a4147 15 | "0x7c726484d25ed94c388a": 100, 16 | // Private Key a3b6421c70f73fa5487af7c72f9cdb44c9e6873f6d2dc90936a509b8c2850aaa 17 | "0xaaa8fb541540f7d954ec": 50, 18 | // Private Key 37ebdf26165f916f3916e59290b38565cb91aebda633476891944a8673a1aa0f 19 | "0x187de361f645dfa21739": 75, 20 | }; 21 | 22 | app.get("/balance/:address", (req, res) => { 23 | const { address } = req.params; 24 | const balance = balances[address] || 0; 25 | res.send({ balance }); 26 | }); 27 | 28 | app.get("/accounts", (req, res) => { 29 | const accounts = [ 30 | { 31 | privateKey: 32 | "98d3f3014d9fb99a4e9a6ec97072e0fa211a875703ccdf17f886d5e8a07a4147", 33 | }, 34 | { 35 | privateKey: 36 | " a3b6421c70f73fa5487af7c72f9cdb44c9e6873f6d2dc90936a509b8c2850aaa", 37 | }, 38 | { 39 | privateKey: 40 | " 37ebdf26165f916f3916e59290b38565cb91aebda633476891944a8673a1aa0f", 41 | }, 42 | ]; 43 | Object.entries(balances).forEach(([address, balance], index) => { 44 | accounts[index] = { 45 | ...accounts[index], 46 | address: address, 47 | balance: balance, 48 | }; 49 | }); 50 | res.json(accounts); 51 | }); 52 | 53 | app.post("/send", (req, res) => { 54 | const { signature, recoveryBit, amount, recipient, nextNonce } = req.body; 55 | const uint8ArrayMsg = Uint8Array.from([amount, recipient]); 56 | const messageHash = toHex(uint8ArrayMsg); 57 | 58 | // recover public key from signature 59 | 60 | const publicKey = secp.recoverPublicKey( 61 | messageHash, 62 | signature, 63 | recoveryBit 64 | ); 65 | 66 | // hash public key to get address 67 | const publicKeyHash = toHex(keccak256(publicKey)); 68 | // console.log("Public key", publicKeyHash); 69 | const sender = `0x${publicKeyHash.slice(-20)}`; // 20 bytes address 70 | // console.log("Sender = ", sender); 71 | //Verification 72 | const isValidSign = secp.verify(signature, messageHash, toHex(publicKey)); 73 | const doesAddressExists = !sender in addressToNonceServer; 74 | if (!doesAddressExists) { 75 | addressToNonceServer = { ...addressToNonceServer, [sender]: 0 }; 76 | } 77 | let isNonceValid = nextNonce === addressToNonceServer[sender] + 1; 78 | setInitialBalance(sender); 79 | setInitialBalance(recipient); 80 | if (balances[sender] < amount) { 81 | res.status(400).send({ message: "Not enough funds!" }); 82 | } else if (!isValidSign) { 83 | res.status(400).send({ message: "Invalid Signature" }); 84 | } else if (!isNonceValid) { 85 | res.status(400).send({ message: "Invalid Nonce" }); 86 | } else { 87 | balances[sender] -= amount; 88 | balances[recipient] += amount; 89 | addressToNonceServer = { 90 | ...addressToNonceServer, 91 | [sender]: addressToNonceServer[sender] + 1, 92 | }; 93 | res.send({ 94 | balance: balances[sender], 95 | sender: sender, 96 | nonceFromServer: addressToNonceServer[sender], 97 | }); 98 | } 99 | }); 100 | 101 | app.listen(port, () => { 102 | console.log(`Listening on port ${port}!`); 103 | }); 104 | 105 | function setInitialBalance(address) { 106 | if (!balances[address]) { 107 | balances[address] = 0; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ecdsa-node/server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "server", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "ethereum-cryptography": "^1.1.2", 14 | "express": "^4.18.1" 15 | } 16 | }, 17 | "node_modules/@noble/hashes": { 18 | "version": "1.1.2", 19 | "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", 20 | "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==", 21 | "funding": [ 22 | { 23 | "type": "individual", 24 | "url": "https://paulmillr.com/funding/" 25 | } 26 | ] 27 | }, 28 | "node_modules/@noble/secp256k1": { 29 | "version": "1.6.3", 30 | "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", 31 | "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==", 32 | "funding": [ 33 | { 34 | "type": "individual", 35 | "url": "https://paulmillr.com/funding/" 36 | } 37 | ] 38 | }, 39 | "node_modules/@scure/base": { 40 | "version": "1.1.1", 41 | "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", 42 | "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", 43 | "funding": [ 44 | { 45 | "type": "individual", 46 | "url": "https://paulmillr.com/funding/" 47 | } 48 | ] 49 | }, 50 | "node_modules/@scure/bip32": { 51 | "version": "1.1.0", 52 | "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.0.tgz", 53 | "integrity": "sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q==", 54 | "funding": [ 55 | { 56 | "type": "individual", 57 | "url": "https://paulmillr.com/funding/" 58 | } 59 | ], 60 | "dependencies": { 61 | "@noble/hashes": "~1.1.1", 62 | "@noble/secp256k1": "~1.6.0", 63 | "@scure/base": "~1.1.0" 64 | } 65 | }, 66 | "node_modules/@scure/bip39": { 67 | "version": "1.1.0", 68 | "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", 69 | "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", 70 | "funding": [ 71 | { 72 | "type": "individual", 73 | "url": "https://paulmillr.com/funding/" 74 | } 75 | ], 76 | "dependencies": { 77 | "@noble/hashes": "~1.1.1", 78 | "@scure/base": "~1.1.0" 79 | } 80 | }, 81 | "node_modules/accepts": { 82 | "version": "1.3.8", 83 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 84 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 85 | "dependencies": { 86 | "mime-types": "~2.1.34", 87 | "negotiator": "0.6.3" 88 | }, 89 | "engines": { 90 | "node": ">= 0.6" 91 | } 92 | }, 93 | "node_modules/array-flatten": { 94 | "version": "1.1.1", 95 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 96 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 97 | }, 98 | "node_modules/body-parser": { 99 | "version": "1.20.0", 100 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", 101 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", 102 | "dependencies": { 103 | "bytes": "3.1.2", 104 | "content-type": "~1.0.4", 105 | "debug": "2.6.9", 106 | "depd": "2.0.0", 107 | "destroy": "1.2.0", 108 | "http-errors": "2.0.0", 109 | "iconv-lite": "0.4.24", 110 | "on-finished": "2.4.1", 111 | "qs": "6.10.3", 112 | "raw-body": "2.5.1", 113 | "type-is": "~1.6.18", 114 | "unpipe": "1.0.0" 115 | }, 116 | "engines": { 117 | "node": ">= 0.8", 118 | "npm": "1.2.8000 || >= 1.4.16" 119 | } 120 | }, 121 | "node_modules/bytes": { 122 | "version": "3.1.2", 123 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 124 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 125 | "engines": { 126 | "node": ">= 0.8" 127 | } 128 | }, 129 | "node_modules/call-bind": { 130 | "version": "1.0.2", 131 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 132 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 133 | "dependencies": { 134 | "function-bind": "^1.1.1", 135 | "get-intrinsic": "^1.0.2" 136 | }, 137 | "funding": { 138 | "url": "https://github.com/sponsors/ljharb" 139 | } 140 | }, 141 | "node_modules/content-disposition": { 142 | "version": "0.5.4", 143 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 144 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 145 | "dependencies": { 146 | "safe-buffer": "5.2.1" 147 | }, 148 | "engines": { 149 | "node": ">= 0.6" 150 | } 151 | }, 152 | "node_modules/content-type": { 153 | "version": "1.0.4", 154 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 155 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 156 | "engines": { 157 | "node": ">= 0.6" 158 | } 159 | }, 160 | "node_modules/cookie": { 161 | "version": "0.5.0", 162 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 163 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 164 | "engines": { 165 | "node": ">= 0.6" 166 | } 167 | }, 168 | "node_modules/cookie-signature": { 169 | "version": "1.0.6", 170 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 171 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 172 | }, 173 | "node_modules/cors": { 174 | "version": "2.8.5", 175 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 176 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 177 | "dependencies": { 178 | "object-assign": "^4", 179 | "vary": "^1" 180 | }, 181 | "engines": { 182 | "node": ">= 0.10" 183 | } 184 | }, 185 | "node_modules/debug": { 186 | "version": "2.6.9", 187 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 188 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 189 | "dependencies": { 190 | "ms": "2.0.0" 191 | } 192 | }, 193 | "node_modules/depd": { 194 | "version": "2.0.0", 195 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 196 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 197 | "engines": { 198 | "node": ">= 0.8" 199 | } 200 | }, 201 | "node_modules/destroy": { 202 | "version": "1.2.0", 203 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 204 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 205 | "engines": { 206 | "node": ">= 0.8", 207 | "npm": "1.2.8000 || >= 1.4.16" 208 | } 209 | }, 210 | "node_modules/ee-first": { 211 | "version": "1.1.1", 212 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 213 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 214 | }, 215 | "node_modules/encodeurl": { 216 | "version": "1.0.2", 217 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 218 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 219 | "engines": { 220 | "node": ">= 0.8" 221 | } 222 | }, 223 | "node_modules/escape-html": { 224 | "version": "1.0.3", 225 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 226 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 227 | }, 228 | "node_modules/etag": { 229 | "version": "1.8.1", 230 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 231 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 232 | "engines": { 233 | "node": ">= 0.6" 234 | } 235 | }, 236 | "node_modules/ethereum-cryptography": { 237 | "version": "1.1.2", 238 | "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz", 239 | "integrity": "sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==", 240 | "dependencies": { 241 | "@noble/hashes": "1.1.2", 242 | "@noble/secp256k1": "1.6.3", 243 | "@scure/bip32": "1.1.0", 244 | "@scure/bip39": "1.1.0" 245 | } 246 | }, 247 | "node_modules/express": { 248 | "version": "4.18.1", 249 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", 250 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", 251 | "dependencies": { 252 | "accepts": "~1.3.8", 253 | "array-flatten": "1.1.1", 254 | "body-parser": "1.20.0", 255 | "content-disposition": "0.5.4", 256 | "content-type": "~1.0.4", 257 | "cookie": "0.5.0", 258 | "cookie-signature": "1.0.6", 259 | "debug": "2.6.9", 260 | "depd": "2.0.0", 261 | "encodeurl": "~1.0.2", 262 | "escape-html": "~1.0.3", 263 | "etag": "~1.8.1", 264 | "finalhandler": "1.2.0", 265 | "fresh": "0.5.2", 266 | "http-errors": "2.0.0", 267 | "merge-descriptors": "1.0.1", 268 | "methods": "~1.1.2", 269 | "on-finished": "2.4.1", 270 | "parseurl": "~1.3.3", 271 | "path-to-regexp": "0.1.7", 272 | "proxy-addr": "~2.0.7", 273 | "qs": "6.10.3", 274 | "range-parser": "~1.2.1", 275 | "safe-buffer": "5.2.1", 276 | "send": "0.18.0", 277 | "serve-static": "1.15.0", 278 | "setprototypeof": "1.2.0", 279 | "statuses": "2.0.1", 280 | "type-is": "~1.6.18", 281 | "utils-merge": "1.0.1", 282 | "vary": "~1.1.2" 283 | }, 284 | "engines": { 285 | "node": ">= 0.10.0" 286 | } 287 | }, 288 | "node_modules/finalhandler": { 289 | "version": "1.2.0", 290 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 291 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 292 | "dependencies": { 293 | "debug": "2.6.9", 294 | "encodeurl": "~1.0.2", 295 | "escape-html": "~1.0.3", 296 | "on-finished": "2.4.1", 297 | "parseurl": "~1.3.3", 298 | "statuses": "2.0.1", 299 | "unpipe": "~1.0.0" 300 | }, 301 | "engines": { 302 | "node": ">= 0.8" 303 | } 304 | }, 305 | "node_modules/forwarded": { 306 | "version": "0.2.0", 307 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 308 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 309 | "engines": { 310 | "node": ">= 0.6" 311 | } 312 | }, 313 | "node_modules/fresh": { 314 | "version": "0.5.2", 315 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 316 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 317 | "engines": { 318 | "node": ">= 0.6" 319 | } 320 | }, 321 | "node_modules/function-bind": { 322 | "version": "1.1.1", 323 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 324 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 325 | }, 326 | "node_modules/get-intrinsic": { 327 | "version": "1.1.3", 328 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 329 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 330 | "dependencies": { 331 | "function-bind": "^1.1.1", 332 | "has": "^1.0.3", 333 | "has-symbols": "^1.0.3" 334 | }, 335 | "funding": { 336 | "url": "https://github.com/sponsors/ljharb" 337 | } 338 | }, 339 | "node_modules/has": { 340 | "version": "1.0.3", 341 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 342 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 343 | "dependencies": { 344 | "function-bind": "^1.1.1" 345 | }, 346 | "engines": { 347 | "node": ">= 0.4.0" 348 | } 349 | }, 350 | "node_modules/has-symbols": { 351 | "version": "1.0.3", 352 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 353 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 354 | "engines": { 355 | "node": ">= 0.4" 356 | }, 357 | "funding": { 358 | "url": "https://github.com/sponsors/ljharb" 359 | } 360 | }, 361 | "node_modules/http-errors": { 362 | "version": "2.0.0", 363 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 364 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 365 | "dependencies": { 366 | "depd": "2.0.0", 367 | "inherits": "2.0.4", 368 | "setprototypeof": "1.2.0", 369 | "statuses": "2.0.1", 370 | "toidentifier": "1.0.1" 371 | }, 372 | "engines": { 373 | "node": ">= 0.8" 374 | } 375 | }, 376 | "node_modules/iconv-lite": { 377 | "version": "0.4.24", 378 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 379 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 380 | "dependencies": { 381 | "safer-buffer": ">= 2.1.2 < 3" 382 | }, 383 | "engines": { 384 | "node": ">=0.10.0" 385 | } 386 | }, 387 | "node_modules/inherits": { 388 | "version": "2.0.4", 389 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 390 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 391 | }, 392 | "node_modules/ipaddr.js": { 393 | "version": "1.9.1", 394 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 395 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 396 | "engines": { 397 | "node": ">= 0.10" 398 | } 399 | }, 400 | "node_modules/media-typer": { 401 | "version": "0.3.0", 402 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 403 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 404 | "engines": { 405 | "node": ">= 0.6" 406 | } 407 | }, 408 | "node_modules/merge-descriptors": { 409 | "version": "1.0.1", 410 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 411 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 412 | }, 413 | "node_modules/methods": { 414 | "version": "1.1.2", 415 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 416 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 417 | "engines": { 418 | "node": ">= 0.6" 419 | } 420 | }, 421 | "node_modules/mime": { 422 | "version": "1.6.0", 423 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 424 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 425 | "bin": { 426 | "mime": "cli.js" 427 | }, 428 | "engines": { 429 | "node": ">=4" 430 | } 431 | }, 432 | "node_modules/mime-db": { 433 | "version": "1.52.0", 434 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 435 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 436 | "engines": { 437 | "node": ">= 0.6" 438 | } 439 | }, 440 | "node_modules/mime-types": { 441 | "version": "2.1.35", 442 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 443 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 444 | "dependencies": { 445 | "mime-db": "1.52.0" 446 | }, 447 | "engines": { 448 | "node": ">= 0.6" 449 | } 450 | }, 451 | "node_modules/ms": { 452 | "version": "2.0.0", 453 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 454 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 455 | }, 456 | "node_modules/negotiator": { 457 | "version": "0.6.3", 458 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 459 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 460 | "engines": { 461 | "node": ">= 0.6" 462 | } 463 | }, 464 | "node_modules/object-assign": { 465 | "version": "4.1.1", 466 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 467 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 468 | "engines": { 469 | "node": ">=0.10.0" 470 | } 471 | }, 472 | "node_modules/object-inspect": { 473 | "version": "1.12.2", 474 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 475 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", 476 | "funding": { 477 | "url": "https://github.com/sponsors/ljharb" 478 | } 479 | }, 480 | "node_modules/on-finished": { 481 | "version": "2.4.1", 482 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 483 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 484 | "dependencies": { 485 | "ee-first": "1.1.1" 486 | }, 487 | "engines": { 488 | "node": ">= 0.8" 489 | } 490 | }, 491 | "node_modules/parseurl": { 492 | "version": "1.3.3", 493 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 494 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 495 | "engines": { 496 | "node": ">= 0.8" 497 | } 498 | }, 499 | "node_modules/path-to-regexp": { 500 | "version": "0.1.7", 501 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 502 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 503 | }, 504 | "node_modules/proxy-addr": { 505 | "version": "2.0.7", 506 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 507 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 508 | "dependencies": { 509 | "forwarded": "0.2.0", 510 | "ipaddr.js": "1.9.1" 511 | }, 512 | "engines": { 513 | "node": ">= 0.10" 514 | } 515 | }, 516 | "node_modules/qs": { 517 | "version": "6.10.3", 518 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 519 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 520 | "dependencies": { 521 | "side-channel": "^1.0.4" 522 | }, 523 | "engines": { 524 | "node": ">=0.6" 525 | }, 526 | "funding": { 527 | "url": "https://github.com/sponsors/ljharb" 528 | } 529 | }, 530 | "node_modules/range-parser": { 531 | "version": "1.2.1", 532 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 533 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 534 | "engines": { 535 | "node": ">= 0.6" 536 | } 537 | }, 538 | "node_modules/raw-body": { 539 | "version": "2.5.1", 540 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 541 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 542 | "dependencies": { 543 | "bytes": "3.1.2", 544 | "http-errors": "2.0.0", 545 | "iconv-lite": "0.4.24", 546 | "unpipe": "1.0.0" 547 | }, 548 | "engines": { 549 | "node": ">= 0.8" 550 | } 551 | }, 552 | "node_modules/safe-buffer": { 553 | "version": "5.2.1", 554 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 555 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 556 | "funding": [ 557 | { 558 | "type": "github", 559 | "url": "https://github.com/sponsors/feross" 560 | }, 561 | { 562 | "type": "patreon", 563 | "url": "https://www.patreon.com/feross" 564 | }, 565 | { 566 | "type": "consulting", 567 | "url": "https://feross.org/support" 568 | } 569 | ] 570 | }, 571 | "node_modules/safer-buffer": { 572 | "version": "2.1.2", 573 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 574 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 575 | }, 576 | "node_modules/send": { 577 | "version": "0.18.0", 578 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 579 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 580 | "dependencies": { 581 | "debug": "2.6.9", 582 | "depd": "2.0.0", 583 | "destroy": "1.2.0", 584 | "encodeurl": "~1.0.2", 585 | "escape-html": "~1.0.3", 586 | "etag": "~1.8.1", 587 | "fresh": "0.5.2", 588 | "http-errors": "2.0.0", 589 | "mime": "1.6.0", 590 | "ms": "2.1.3", 591 | "on-finished": "2.4.1", 592 | "range-parser": "~1.2.1", 593 | "statuses": "2.0.1" 594 | }, 595 | "engines": { 596 | "node": ">= 0.8.0" 597 | } 598 | }, 599 | "node_modules/send/node_modules/ms": { 600 | "version": "2.1.3", 601 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 602 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 603 | }, 604 | "node_modules/serve-static": { 605 | "version": "1.15.0", 606 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 607 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 608 | "dependencies": { 609 | "encodeurl": "~1.0.2", 610 | "escape-html": "~1.0.3", 611 | "parseurl": "~1.3.3", 612 | "send": "0.18.0" 613 | }, 614 | "engines": { 615 | "node": ">= 0.8.0" 616 | } 617 | }, 618 | "node_modules/setprototypeof": { 619 | "version": "1.2.0", 620 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 621 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 622 | }, 623 | "node_modules/side-channel": { 624 | "version": "1.0.4", 625 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 626 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 627 | "dependencies": { 628 | "call-bind": "^1.0.0", 629 | "get-intrinsic": "^1.0.2", 630 | "object-inspect": "^1.9.0" 631 | }, 632 | "funding": { 633 | "url": "https://github.com/sponsors/ljharb" 634 | } 635 | }, 636 | "node_modules/statuses": { 637 | "version": "2.0.1", 638 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 639 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 640 | "engines": { 641 | "node": ">= 0.8" 642 | } 643 | }, 644 | "node_modules/toidentifier": { 645 | "version": "1.0.1", 646 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 647 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 648 | "engines": { 649 | "node": ">=0.6" 650 | } 651 | }, 652 | "node_modules/type-is": { 653 | "version": "1.6.18", 654 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 655 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 656 | "dependencies": { 657 | "media-typer": "0.3.0", 658 | "mime-types": "~2.1.24" 659 | }, 660 | "engines": { 661 | "node": ">= 0.6" 662 | } 663 | }, 664 | "node_modules/unpipe": { 665 | "version": "1.0.0", 666 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 667 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 668 | "engines": { 669 | "node": ">= 0.8" 670 | } 671 | }, 672 | "node_modules/utils-merge": { 673 | "version": "1.0.1", 674 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 675 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 676 | "engines": { 677 | "node": ">= 0.4.0" 678 | } 679 | }, 680 | "node_modules/vary": { 681 | "version": "1.1.2", 682 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 683 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 684 | "engines": { 685 | "node": ">= 0.8" 686 | } 687 | } 688 | }, 689 | "dependencies": { 690 | "@noble/hashes": { 691 | "version": "1.1.2", 692 | "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", 693 | "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==" 694 | }, 695 | "@noble/secp256k1": { 696 | "version": "1.6.3", 697 | "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", 698 | "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==" 699 | }, 700 | "@scure/base": { 701 | "version": "1.1.1", 702 | "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", 703 | "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==" 704 | }, 705 | "@scure/bip32": { 706 | "version": "1.1.0", 707 | "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.0.tgz", 708 | "integrity": "sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q==", 709 | "requires": { 710 | "@noble/hashes": "~1.1.1", 711 | "@noble/secp256k1": "~1.6.0", 712 | "@scure/base": "~1.1.0" 713 | } 714 | }, 715 | "@scure/bip39": { 716 | "version": "1.1.0", 717 | "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", 718 | "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", 719 | "requires": { 720 | "@noble/hashes": "~1.1.1", 721 | "@scure/base": "~1.1.0" 722 | } 723 | }, 724 | "accepts": { 725 | "version": "1.3.8", 726 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 727 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 728 | "requires": { 729 | "mime-types": "~2.1.34", 730 | "negotiator": "0.6.3" 731 | } 732 | }, 733 | "array-flatten": { 734 | "version": "1.1.1", 735 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 736 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 737 | }, 738 | "body-parser": { 739 | "version": "1.20.0", 740 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", 741 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", 742 | "requires": { 743 | "bytes": "3.1.2", 744 | "content-type": "~1.0.4", 745 | "debug": "2.6.9", 746 | "depd": "2.0.0", 747 | "destroy": "1.2.0", 748 | "http-errors": "2.0.0", 749 | "iconv-lite": "0.4.24", 750 | "on-finished": "2.4.1", 751 | "qs": "6.10.3", 752 | "raw-body": "2.5.1", 753 | "type-is": "~1.6.18", 754 | "unpipe": "1.0.0" 755 | } 756 | }, 757 | "bytes": { 758 | "version": "3.1.2", 759 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 760 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 761 | }, 762 | "call-bind": { 763 | "version": "1.0.2", 764 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 765 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 766 | "requires": { 767 | "function-bind": "^1.1.1", 768 | "get-intrinsic": "^1.0.2" 769 | } 770 | }, 771 | "content-disposition": { 772 | "version": "0.5.4", 773 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 774 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 775 | "requires": { 776 | "safe-buffer": "5.2.1" 777 | } 778 | }, 779 | "content-type": { 780 | "version": "1.0.4", 781 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 782 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 783 | }, 784 | "cookie": { 785 | "version": "0.5.0", 786 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 787 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" 788 | }, 789 | "cookie-signature": { 790 | "version": "1.0.6", 791 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 792 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 793 | }, 794 | "cors": { 795 | "version": "2.8.5", 796 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 797 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 798 | "requires": { 799 | "object-assign": "^4", 800 | "vary": "^1" 801 | } 802 | }, 803 | "debug": { 804 | "version": "2.6.9", 805 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 806 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 807 | "requires": { 808 | "ms": "2.0.0" 809 | } 810 | }, 811 | "depd": { 812 | "version": "2.0.0", 813 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 814 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 815 | }, 816 | "destroy": { 817 | "version": "1.2.0", 818 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 819 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 820 | }, 821 | "ee-first": { 822 | "version": "1.1.1", 823 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 824 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 825 | }, 826 | "encodeurl": { 827 | "version": "1.0.2", 828 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 829 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 830 | }, 831 | "escape-html": { 832 | "version": "1.0.3", 833 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 834 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 835 | }, 836 | "etag": { 837 | "version": "1.8.1", 838 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 839 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 840 | }, 841 | "ethereum-cryptography": { 842 | "version": "1.1.2", 843 | "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz", 844 | "integrity": "sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==", 845 | "requires": { 846 | "@noble/hashes": "1.1.2", 847 | "@noble/secp256k1": "1.6.3", 848 | "@scure/bip32": "1.1.0", 849 | "@scure/bip39": "1.1.0" 850 | } 851 | }, 852 | "express": { 853 | "version": "4.18.1", 854 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", 855 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", 856 | "requires": { 857 | "accepts": "~1.3.8", 858 | "array-flatten": "1.1.1", 859 | "body-parser": "1.20.0", 860 | "content-disposition": "0.5.4", 861 | "content-type": "~1.0.4", 862 | "cookie": "0.5.0", 863 | "cookie-signature": "1.0.6", 864 | "debug": "2.6.9", 865 | "depd": "2.0.0", 866 | "encodeurl": "~1.0.2", 867 | "escape-html": "~1.0.3", 868 | "etag": "~1.8.1", 869 | "finalhandler": "1.2.0", 870 | "fresh": "0.5.2", 871 | "http-errors": "2.0.0", 872 | "merge-descriptors": "1.0.1", 873 | "methods": "~1.1.2", 874 | "on-finished": "2.4.1", 875 | "parseurl": "~1.3.3", 876 | "path-to-regexp": "0.1.7", 877 | "proxy-addr": "~2.0.7", 878 | "qs": "6.10.3", 879 | "range-parser": "~1.2.1", 880 | "safe-buffer": "5.2.1", 881 | "send": "0.18.0", 882 | "serve-static": "1.15.0", 883 | "setprototypeof": "1.2.0", 884 | "statuses": "2.0.1", 885 | "type-is": "~1.6.18", 886 | "utils-merge": "1.0.1", 887 | "vary": "~1.1.2" 888 | } 889 | }, 890 | "finalhandler": { 891 | "version": "1.2.0", 892 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 893 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 894 | "requires": { 895 | "debug": "2.6.9", 896 | "encodeurl": "~1.0.2", 897 | "escape-html": "~1.0.3", 898 | "on-finished": "2.4.1", 899 | "parseurl": "~1.3.3", 900 | "statuses": "2.0.1", 901 | "unpipe": "~1.0.0" 902 | } 903 | }, 904 | "forwarded": { 905 | "version": "0.2.0", 906 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 907 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 908 | }, 909 | "fresh": { 910 | "version": "0.5.2", 911 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 912 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 913 | }, 914 | "function-bind": { 915 | "version": "1.1.1", 916 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 917 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 918 | }, 919 | "get-intrinsic": { 920 | "version": "1.1.3", 921 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 922 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 923 | "requires": { 924 | "function-bind": "^1.1.1", 925 | "has": "^1.0.3", 926 | "has-symbols": "^1.0.3" 927 | } 928 | }, 929 | "has": { 930 | "version": "1.0.3", 931 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 932 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 933 | "requires": { 934 | "function-bind": "^1.1.1" 935 | } 936 | }, 937 | "has-symbols": { 938 | "version": "1.0.3", 939 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 940 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 941 | }, 942 | "http-errors": { 943 | "version": "2.0.0", 944 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 945 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 946 | "requires": { 947 | "depd": "2.0.0", 948 | "inherits": "2.0.4", 949 | "setprototypeof": "1.2.0", 950 | "statuses": "2.0.1", 951 | "toidentifier": "1.0.1" 952 | } 953 | }, 954 | "iconv-lite": { 955 | "version": "0.4.24", 956 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 957 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 958 | "requires": { 959 | "safer-buffer": ">= 2.1.2 < 3" 960 | } 961 | }, 962 | "inherits": { 963 | "version": "2.0.4", 964 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 965 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 966 | }, 967 | "ipaddr.js": { 968 | "version": "1.9.1", 969 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 970 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 971 | }, 972 | "media-typer": { 973 | "version": "0.3.0", 974 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 975 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 976 | }, 977 | "merge-descriptors": { 978 | "version": "1.0.1", 979 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 980 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 981 | }, 982 | "methods": { 983 | "version": "1.1.2", 984 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 985 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 986 | }, 987 | "mime": { 988 | "version": "1.6.0", 989 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 990 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 991 | }, 992 | "mime-db": { 993 | "version": "1.52.0", 994 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 995 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 996 | }, 997 | "mime-types": { 998 | "version": "2.1.35", 999 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1000 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1001 | "requires": { 1002 | "mime-db": "1.52.0" 1003 | } 1004 | }, 1005 | "ms": { 1006 | "version": "2.0.0", 1007 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1008 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1009 | }, 1010 | "negotiator": { 1011 | "version": "0.6.3", 1012 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1013 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 1014 | }, 1015 | "object-assign": { 1016 | "version": "4.1.1", 1017 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1018 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" 1019 | }, 1020 | "object-inspect": { 1021 | "version": "1.12.2", 1022 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 1023 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" 1024 | }, 1025 | "on-finished": { 1026 | "version": "2.4.1", 1027 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1028 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1029 | "requires": { 1030 | "ee-first": "1.1.1" 1031 | } 1032 | }, 1033 | "parseurl": { 1034 | "version": "1.3.3", 1035 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1036 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1037 | }, 1038 | "path-to-regexp": { 1039 | "version": "0.1.7", 1040 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1041 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 1042 | }, 1043 | "proxy-addr": { 1044 | "version": "2.0.7", 1045 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1046 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1047 | "requires": { 1048 | "forwarded": "0.2.0", 1049 | "ipaddr.js": "1.9.1" 1050 | } 1051 | }, 1052 | "qs": { 1053 | "version": "6.10.3", 1054 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 1055 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 1056 | "requires": { 1057 | "side-channel": "^1.0.4" 1058 | } 1059 | }, 1060 | "range-parser": { 1061 | "version": "1.2.1", 1062 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1063 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1064 | }, 1065 | "raw-body": { 1066 | "version": "2.5.1", 1067 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1068 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1069 | "requires": { 1070 | "bytes": "3.1.2", 1071 | "http-errors": "2.0.0", 1072 | "iconv-lite": "0.4.24", 1073 | "unpipe": "1.0.0" 1074 | } 1075 | }, 1076 | "safe-buffer": { 1077 | "version": "5.2.1", 1078 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1079 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1080 | }, 1081 | "safer-buffer": { 1082 | "version": "2.1.2", 1083 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1084 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1085 | }, 1086 | "send": { 1087 | "version": "0.18.0", 1088 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1089 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1090 | "requires": { 1091 | "debug": "2.6.9", 1092 | "depd": "2.0.0", 1093 | "destroy": "1.2.0", 1094 | "encodeurl": "~1.0.2", 1095 | "escape-html": "~1.0.3", 1096 | "etag": "~1.8.1", 1097 | "fresh": "0.5.2", 1098 | "http-errors": "2.0.0", 1099 | "mime": "1.6.0", 1100 | "ms": "2.1.3", 1101 | "on-finished": "2.4.1", 1102 | "range-parser": "~1.2.1", 1103 | "statuses": "2.0.1" 1104 | }, 1105 | "dependencies": { 1106 | "ms": { 1107 | "version": "2.1.3", 1108 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1109 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1110 | } 1111 | } 1112 | }, 1113 | "serve-static": { 1114 | "version": "1.15.0", 1115 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1116 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1117 | "requires": { 1118 | "encodeurl": "~1.0.2", 1119 | "escape-html": "~1.0.3", 1120 | "parseurl": "~1.3.3", 1121 | "send": "0.18.0" 1122 | } 1123 | }, 1124 | "setprototypeof": { 1125 | "version": "1.2.0", 1126 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1127 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1128 | }, 1129 | "side-channel": { 1130 | "version": "1.0.4", 1131 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1132 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1133 | "requires": { 1134 | "call-bind": "^1.0.0", 1135 | "get-intrinsic": "^1.0.2", 1136 | "object-inspect": "^1.9.0" 1137 | } 1138 | }, 1139 | "statuses": { 1140 | "version": "2.0.1", 1141 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1142 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 1143 | }, 1144 | "toidentifier": { 1145 | "version": "1.0.1", 1146 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1147 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1148 | }, 1149 | "type-is": { 1150 | "version": "1.6.18", 1151 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1152 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1153 | "requires": { 1154 | "media-typer": "0.3.0", 1155 | "mime-types": "~2.1.24" 1156 | } 1157 | }, 1158 | "unpipe": { 1159 | "version": "1.0.0", 1160 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1161 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 1162 | }, 1163 | "utils-merge": { 1164 | "version": "1.0.1", 1165 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1166 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 1167 | }, 1168 | "vary": { 1169 | "version": "1.1.2", 1170 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1171 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" 1172 | } 1173 | } 1174 | } 1175 | -------------------------------------------------------------------------------- /ecdsa-node/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cors": "^2.8.5", 14 | "ethereum-cryptography": "^1.1.2", 15 | "express": "^4.18.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ecdsa-node/server/scripts/generate.js: -------------------------------------------------------------------------------- 1 | const secp = require("ethereum-cryptography/secp256k1"); 2 | const { keccak256 } = require("ethereum-cryptography/keccak"); 3 | const { toHex } = require("ethereum-cryptography/utils"); 4 | 5 | const privateKey = secp.utils.randomPrivateKey(); 6 | console.log("Private Key", toHex(privateKey)); 7 | const publicKey = secp.getPublicKey(privateKey); 8 | console.log("Public Key Raw", toHex(publicKey)); 9 | const publicKeyHash = toHex(keccak256(publicKey)); 10 | console.log("Hashed Public key", publicKeyHash); 11 | console.log("Address", publicKeyHash.slice(-20)); 12 | 13 | // Signing 14 | const uint8Array = Uint8Array.from([ 15 | "25", 16 | "54f6993a7f362ad2145698f08bb8db46785fe69a", 17 | ]); 18 | const signature = secp.signSync( 19 | keccak256(uint8Array), 20 | toHex(keccak256(privateKey)) 21 | ); 22 | console.log("Signature using uint8Array", toHex(signature)); 23 | 24 | // Signing using bytes 25 | const hashMsg = toHex(keccak256(uint8Array)); 26 | console.log("Hashed Message", hashMsg); 27 | const signature1 = secp.signSync(hashMsg, privateKey); 28 | console.log("Signature using hex", toHex(signature1)); 29 | // conclusion = No matter what you use uint8Array or hex signature is gonna be a same 30 | -------------------------------------------------------------------------------- /ecdsa-node/server/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "index.js", 6 | "use": "@vercel/node" 7 | } 8 | ], 9 | "routes": [ 10 | { 11 | "src": "/(.*)", 12 | "dest": "index.js" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /ethereum/ethers/1-makingWallets-wallet.js: -------------------------------------------------------------------------------- 1 | const ethers = require("ethers"); 2 | const { Wallet } = ethers; 3 | 4 | // create a wallet with a private key 5 | const wallet1 = new Wallet( 6 | "0xf2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d" 7 | ); 8 | 9 | // create a wallet from mnemonic 10 | const wallet2 = Wallet.fromMnemonic( 11 | "plate lawn minor crouch bubble evidence palace fringe bamboo laptop dutch ice" 12 | ); 13 | 14 | module.exports = { 15 | wallet1, 16 | wallet2, 17 | }; 18 | -------------------------------------------------------------------------------- /ethereum/ethers/2-signATransactions-sign.js: -------------------------------------------------------------------------------- 1 | const ethers = require("ethers"); 2 | const { Wallet, utils } = ethers; 3 | const { wallet1 } = require("./wallets"); 4 | 5 | const signaturePromise = wallet1.signTransaction({ 6 | value: ethers.utils.parseEther("1"), 7 | to: "0xdD0DC6FB59E100ee4fA9900c2088053bBe14DE92", 8 | gasLimit: 21000, 9 | gasPrice: 2000000000, 10 | }); 11 | 12 | module.exports = signaturePromise; 13 | -------------------------------------------------------------------------------- /ethereum/ethers/3-connectToEthereum-sendEther.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiddheshKukade/AU_ETH_Bootcamp/fc99de609aaf0d33edf3ce7d85e7a3468ebf3235/ethereum/ethers/3-connectToEthereum-sendEther.js -------------------------------------------------------------------------------- /ethereum/ethers/4-accountNonce-sendEther.js: -------------------------------------------------------------------------------- 1 | const { Wallet, utils, providers } = require("ethers"); 2 | const { ganacheProvider, PRIVATE_KEY } = require("./config"); 3 | 4 | const provider = new providers.Web3Provider(ganacheProvider); 5 | 6 | const wallet = new Wallet(PRIVATE_KEY, provider); 7 | 8 | async function sendEther({ value, to }) { 9 | const txRes = await wallet.sendTransaction({ 10 | value, 11 | to, 12 | gasLimit: 0x5208, 13 | gasPrice: 0x3b9aca00, 14 | }); 15 | 16 | return txRes; 17 | } 18 | 19 | module.exports = sendEther; 20 | -------------------------------------------------------------------------------- /ethereum/ethers/5-findBalance-findMyBalance.js: -------------------------------------------------------------------------------- 1 | const { Wallet, providers } = require("ethers"); 2 | const { ganacheProvider } = require("./config"); 3 | 4 | const provider = new providers.Web3Provider(ganacheProvider); 5 | function findMyBalance(privateKey) { 6 | const wallet = new Wallet(privateKey, provider); 7 | const txRes = wallet.getBalance(); 8 | return txRes; 9 | // retrieve the balance, given a private key 10 | } 11 | 12 | module.exports = findMyBalance; 13 | -------------------------------------------------------------------------------- /ethereum/ethers/6-charitableDonation-donation.js: -------------------------------------------------------------------------------- 1 | const { utils, providers, Wallet } = require("ethers"); 2 | const { ganacheProvider } = require("./config"); 3 | 4 | const provider = new providers.Web3Provider(ganacheProvider); 5 | 6 | /** 7 | * Donate at least 1 ether from the wallet to each charity 8 | * @param {string} a hex string private key for a wallet with 10 ETH 9 | * @param {array} an array of ethereum charity addresses 10 | * 11 | * @returns {Promise} a promise that resolves after all donations have been sent 12 | */ 13 | async function donate(privateKey, charities) { 14 | // TODO: donate to charity! 15 | const wallet = new Wallet(privateKey, provider); 16 | for (let charityAddr of charities) { 17 | await wallet.sendTransaction({ 18 | to: charityAddr, 19 | value: utils.parseEther("1"), 20 | gasLimit: 0x5208, 21 | gasPrice: 0x3b9aca00, 22 | }); 23 | } 24 | } 25 | 26 | module.exports = donate; 27 | -------------------------------------------------------------------------------- /ethereum/ethers/findEther.js: -------------------------------------------------------------------------------- 1 | const { providers } = require("ethers"); 2 | const { ganacheProvider } = require("./config"); 3 | 4 | const provider = new providers.Web3Provider(ganacheProvider); 5 | 6 | /** 7 | * Given an ethereum address find all the addresses 8 | * that were sent ether from that address 9 | * @param {string} address - The hexidecimal address for the sender 10 | * @async 11 | * @returns {Array} all the addresses that receieved ether 12 | */ 13 | async function findEther(address) { 14 | const blockNumber = await provider.getBlockNumber(); 15 | 16 | const recepients = []; 17 | let i = 0; 18 | while (i <= blockNumber) { 19 | const response = await provider.getBlockWithTransactions(i); 20 | response.transactions.forEach((tx) => { 21 | if (tx.from === address) { 22 | recepients.push(tx.to); 23 | } 24 | }); 25 | i++; 26 | } 27 | return recepients; 28 | } 29 | 30 | module.exports = findEther; 31 | -------------------------------------------------------------------------------- /ethereum/json-rpc/1-currentBlockNumber-getBlockNumber.js: -------------------------------------------------------------------------------- 1 | const provider = require("./provider"); 2 | 3 | async function getBlockNumber() { 4 | const response = await provider.send({ 5 | jsonrpc: "2.0", 6 | id: 1, 7 | method: "eth_blockNumber", 8 | }); 9 | 10 | return response.result; 11 | } 12 | 13 | module.exports = getBlockNumber; 14 | -------------------------------------------------------------------------------- /ethereum/json-rpc/2-getBalance-getBalance.js: -------------------------------------------------------------------------------- 1 | const provider = require("./provider"); 2 | 3 | async function getBalance(address) { 4 | const response = await provider.send({ 5 | jsonrpc: "2.0", 6 | id: 1, 7 | method: "eth_getBalance", // <-- fill in the method 8 | params: [address, "latest"], // <-- fill in the params 9 | }); 10 | return response.result; 11 | // return the balance of the address 12 | } 13 | 14 | module.exports = getBalance; 15 | -------------------------------------------------------------------------------- /ethereum/json-rpc/3-getNonce-getNonce.js: -------------------------------------------------------------------------------- 1 | const provider = require("./provider"); 2 | 3 | async function getNonce(address) { 4 | const response = await provider.send({ 5 | jsonrpc: "2.0", 6 | id: 1, 7 | method: "eth_getTransactionCount", //Note: nonce means transaction count 8 | params: [address, "latest"], 9 | }); 10 | 11 | return response.result; 12 | } 13 | 14 | module.exports = getNonce; 15 | -------------------------------------------------------------------------------- /ethereum/json-rpc/4-blockTransactions-getTotalTransactions.js: -------------------------------------------------------------------------------- 1 | const provider = require("./provider"); 2 | 3 | async function getTotalTransactions(blockNumber) { 4 | const response = await provider.send({ 5 | jsonrpc: "2.0", 6 | id: 1, 7 | method: "eth_getBlockTransactionCountByNumber", 8 | params: [blockNumber], 9 | }); 10 | return response.result; 11 | // return the total number of transactions in the block 12 | } 13 | 14 | module.exports = getTotalTransactions; 15 | -------------------------------------------------------------------------------- /ethereum/json-rpc/5-totalWei-getTotalBalance.js: -------------------------------------------------------------------------------- 1 | const provider = require("./provider"); 2 | 3 | async function getTotalBalance(addresses) { 4 | const queries = []; 5 | addresses.forEach((address, index) => { 6 | queries.push({ 7 | jsonrpc: "2.0", 8 | id: index, 9 | method: "eth_getBalance", 10 | params: [address, "latest"], 11 | }); 12 | }); 13 | const responses = await provider.send(queries); 14 | 15 | let totalBalance = 0; 16 | for (let data of responses) { 17 | console.log(data); 18 | totalBalance += parseInt(data.result); 19 | } 20 | return totalBalance; 21 | 22 | // return the total balance of all the addresses 23 | } 24 | 25 | module.exports = getTotalBalance; 26 | -------------------------------------------------------------------------------- /smart-contracts-basics/data-types/1-booleans-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | bool public a = true; 6 | bool public b = false; 7 | } 8 | -------------------------------------------------------------------------------- /smart-contracts-basics/data-types/2-unsigned-integers-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | // Found some gotchas here have a look at it 6 | // https://discord.com/channels/1039895401832128532/1047627160812277761/1053513309820813342 7 | uint8 public a = 1; 8 | uint16 public b = 65533; 9 | uint256 public sum = a + b; 10 | } 11 | -------------------------------------------------------------------------------- /smart-contracts-basics/data-types/3-signed-integers-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | int8 public a = 10; 6 | int8 public b = -10; 7 | int16 public difference = a - b; 8 | } 9 | -------------------------------------------------------------------------------- /smart-contracts-basics/data-types/4-string-literals-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | bytes32 public msg1 = "Hello World"; 6 | string public msg2 = 7 | "Hello World this is Anmol and i'm on the way to become a web 3 develper"; 8 | } 9 | -------------------------------------------------------------------------------- /smart-contracts-basics/data-types/5-enum-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | enum Foods { 6 | Apple, 7 | Pizza, 8 | Bagel, 9 | Banana 10 | } 11 | 12 | Foods public food1 = Foods.Pizza; 13 | Foods public food2 = Foods.Apple; 14 | Foods public food3 = Foods.Bagel; 15 | Foods public food4 = Foods.Banana; 16 | } 17 | -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY= YOUR_WALLET_PRIVATE_KEY 2 | GOERLI_URL=ALCHEMY_RPC_URL -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | 12 | -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/README.md: -------------------------------------------------------------------------------- 1 | # Emit Winner Event 2 | 3 | External Contract 4 | 5 | ```solidity 6 | //SPDX-License-Identifier: Unlicense 7 | pragma solidity ^0.8.0; 8 | 9 | contract Contract { 10 | event Winner(address); 11 | 12 | function attempt() external { 13 | require(msg.sender != tx.origin, "msg.sender is equal to tx.origin"); 14 | emit Winner(msg.sender); 15 | } 16 | } 17 | ``` 18 | 19 | deployed to = "https://goerli.etherscan.io/address/0xcF469d3BEB3Fc24cEe979eFf83BE33ed50988502" 20 | 21 | Project setup: 22 | 23 | ```shell 24 | npm i -D hardhat 25 | npm i dotenv 26 | npx hardhat init 27 | ``` 28 | 29 | Deploy contract 30 | 31 | 'hh' is equivalent to npx hardhat to use hh, install 32 | 33 | ```shell 34 | npm install --global hardhat-shorthand 35 | ``` 36 | 37 | ```shell 38 | hh run scripts/deploy --network goerli 39 | ``` 40 | 41 | after deployement copy the deployed address and go to open scripts/emitWinnerEvent.js 42 | paste that address in `getContractAt(YOUR_DEPLOYED_ADDRESS)` 43 | 44 | then copy paste this address "0xcF469d3BEB3Fc24cEe979eFf83BE33ed50988502" into 45 | contract.deploy() like this `contract.deploy("0xcF469d3BEB3Fc24cEe979eFf83BE33ed50988502")` 46 | Last step! 47 | 48 | run 49 | 50 | ```shell 51 | hh run scripts/emitWinnerEvent --network goerli 52 | ``` 53 | 54 | Woooohooo! You just emit event in the external contract 55 | 56 | see how this executed 57 | 58 | - Your EOA account(wallet) initialize the transaction 59 | - You call emitWinnerEvent on EmitWinnerEvent contract that you created 60 | - Till here msg.sender is EOA and also tx.origin is EOA i.e You 61 | - Now here is gotcha. EmitWinnerEvent calls attempt() in external contract 62 | - Now msg.sender is EmitWinnerEvent contract address and tx.orgin is still EOA i.e You 63 | - So it passes the require condition of the external contract and event is emmited 64 | -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/contracts/EmitWinnerEvent.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.9; 3 | interface ContractToCall{ 4 | function attempt() external; 5 | } 6 | contract EmitWinnerEvent{ 7 | // address constant CONTRACT_ADDRESS = 0xcF469d3BEB3Fc24cEe979eFf83BE33ed50988502; 8 | function emitWinnerEvent(address contractAddress) public { 9 | ContractToCall(contractAddress).attempt(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | require("@nomicfoundation/hardhat-toolbox"); 3 | /** @type import('hardhat/config').HardhatUserConfig */ 4 | module.exports = { 5 | solidity: "0.8.9", 6 | networks: { 7 | hardhat: {}, 8 | goerli: { 9 | url: process.env.GOERLI_URL, 10 | accounts: [process.env.PRIVATE_KEY], 11 | }, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "event-emitter-week4", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@ethersproject/abi": "^5.7.0", 14 | "@ethersproject/providers": "^5.7.2", 15 | "@nomicfoundation/hardhat-chai-matchers": "^1.0.5", 16 | "@nomicfoundation/hardhat-network-helpers": "^1.0.7", 17 | "@nomicfoundation/hardhat-toolbox": "^2.0.0", 18 | "@nomiclabs/hardhat-ethers": "^2.2.1", 19 | "@nomiclabs/hardhat-etherscan": "^3.1.3", 20 | "@typechain/ethers-v5": "^10.2.0", 21 | "@typechain/hardhat": "^6.1.5", 22 | "chai": "^4.3.7", 23 | "ethers": "^5.7.2", 24 | "hardhat": "^2.12.4", 25 | "hardhat-gas-reporter": "^1.0.9", 26 | "solidity-coverage": "^0.8.2", 27 | "typechain": "^8.1.1" 28 | }, 29 | "dependencies": { 30 | "dotenv": "^16.0.3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/scripts/deploy.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | 3 | async function main() { 4 | const contractFactory = await hre.ethers.getContractFactory( 5 | "EmitWinnerEvent" 6 | ); 7 | const contract = await contractFactory.deploy(); 8 | await contract.deployed(); 9 | console.log("Contract deployed to:", contract.address); 10 | } 11 | 12 | // We recommend this pattern to be able to use async/await everywhere 13 | // and properly handle errors. 14 | main().catch((error) => { 15 | console.error(error); 16 | process.exitCode = 1; 17 | }); 18 | -------------------------------------------------------------------------------- /smart-contracts-basics/event-emitter-project/scripts/emitWinnerEvent.js: -------------------------------------------------------------------------------- 1 | async function main() { 2 | const EMIT_WINNER_EVENT_CONTRACTj = 3 | "0x8272b09F90a55983cceC1954C1bC171A09243C25"; 4 | const TARGET_CONTRACT = "0xcF469d3BEB3Fc24cEe979eFf83BE33ed50988502"; 5 | const contract = await ethers.getContractAt( 6 | "EmitWinnerEvent", 7 | EMIT_WINNER_EVENT_CONTRACTj 8 | ); 9 | 10 | const tx = await contract.emitWinnerEvent(TARGET_CONTRACT); 11 | await tx.wait(); 12 | console.log("Winner event emitted"); 13 | } 14 | main() 15 | .then(() => process.exit(0)) 16 | .catch((error) => { 17 | console.error(error); 18 | process.exit(1); 19 | }); 20 | -------------------------------------------------------------------------------- /smart-contracts-basics/functions/1-argument-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | uint public x; 6 | 7 | constructor(uint _x) { 8 | x = _x; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smart-contracts-basics/functions/2-increment-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | uint public x; 6 | 7 | constructor(uint _x) { 8 | x = _x; 9 | } 10 | 11 | function increment() external { 12 | x++; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /smart-contracts-basics/functions/3-viewAddition-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | uint public x; 6 | 7 | constructor(uint _x) { 8 | x = _x; 9 | } 10 | 11 | function increment() external { 12 | x++; 13 | } 14 | 15 | function add(uint y) external view returns (uint sum) { 16 | sum = x + y; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /smart-contracts-basics/functions/4-pureDouble-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | function double(uint x) external pure returns (uint _double) { 6 | _double = x * 2; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /smart-contracts-basics/functions/5-doubleOverload-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | function double(uint x) external pure returns (uint _double) { 6 | _double = x * 2; 7 | } 8 | 9 | function double(uint x, uint y) external pure returns (uint, uint) { 10 | return (x * 2, y * 2); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /smart-contracts-basics/learning-reverts/1-contructorRevert.contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | error NotOwner(); 4 | 5 | contract Contract { 6 | constructor() payable { 7 | require(msg.value >= 1 ether, "Want More Ether!"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /smart-contracts-basics/learning-reverts/2-onlyOwner-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | error NotOwner(); 4 | 5 | contract Contract { 6 | address public owner; 7 | 8 | constructor() payable { 9 | require(msg.value >= 1 ether, "Want More Ether!"); 10 | owner = msg.sender; 11 | } 12 | 13 | function withdraw() public { 14 | if (msg.sender != owner) { 15 | revert NotOwner(); 16 | } 17 | (bool success, ) = owner.call{value: address(this).balance}(""); 18 | require(success, "Transfer Failed"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /smart-contracts-basics/learning-reverts/3-ownerModifier-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | address owner; 6 | uint configA; 7 | uint configB; 8 | uint configC; 9 | 10 | constructor() { 11 | owner = msg.sender; 12 | } 13 | 14 | function setA(uint _configA) public onlyOwner { 15 | configA = _configA; 16 | } 17 | 18 | function setB(uint _configB) public onlyOwner { 19 | configB = _configB; 20 | } 21 | 22 | function setC(uint _configC) public onlyOwner { 23 | configC = _configC; 24 | } 25 | 26 | modifier onlyOwner() { 27 | require(msg.sender == owner, "not an owner!"); 28 | _; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /smart-contracts-basics/practice-solidity/countdown-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | uint tickCount = 1; 6 | 7 | function tick() external { 8 | if (tickCount == 10) { 9 | selfdestruct(payable(msg.sender)); 10 | } else { 11 | tickCount++; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /smart-contracts-basics/practice-solidity/sumAndAverage-contract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.4; 2 | 3 | contract Contract { 4 | function sumAndAverage( 5 | uint a, 6 | uint b, 7 | uint c, 8 | uint d 9 | ) external pure returns (uint, uint) { 10 | uint sum = a + b + c + d; 11 | uint average = sum / 4; 12 | return (sum, average); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-data/1-callFunction-sideKick.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | interface IHero { 5 | function alert() external; 6 | } 7 | 8 | contract Sidekick { 9 | function sendAlert(address hero) external { 10 | IHero(hero).alert(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-data/2-signature-sideKick.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Sidekick { 5 | function sendAlert(address hero) external { 6 | // TODO: fill in the function signature 7 | bytes4 signature = bytes4(keccak256("alert()")); 8 | 9 | (bool success, ) = hero.call(abi.encodePacked(signature)); 10 | 11 | require(success); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-data/3-withSignature-sideKick.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Sidekick { 5 | function sendAlert(address hero, uint enemies, bool armed) external { 6 | (bool success, ) = hero.call( 7 | abi.encodeWithSignature("alert(uint256,bool)", enemies, armed) 8 | ); 9 | 10 | require(success); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-data/4-arbitraryAlert-sideKick.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Sidekick { 5 | function relay(address hero, bytes memory data) external { 6 | // send all of the data as calldata to the hero 7 | hero.call(data); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-data/5-fallback-sideKick.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Sidekick { 5 | function makeContact(address hero) external { 6 | hero.call("someZibbriesh"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-ethers/1-storing-owner-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | address public owner; 6 | 7 | constructor() { 8 | owner = msg.sender; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-ethers/2-recieve-ether-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | address public owner; 6 | 7 | constructor() { 8 | owner = msg.sender; 9 | } 10 | 11 | receive() external payable {} 12 | } 13 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-ethers/3-tipOwner-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | address public owner; 6 | 7 | constructor() { 8 | owner = msg.sender; 9 | } 10 | 11 | function tip() public payable { 12 | (bool success, ) = owner.call{value: msg.value}(""); 13 | require(success, "Transfer failed"); 14 | } 15 | 16 | receive() external payable {} 17 | } 18 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-ethers/4-charity-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | address public owner; 6 | address private charityAddr; 7 | 8 | constructor(address _charityAddr) { 9 | owner = msg.sender; 10 | charityAddr = _charityAddr; 11 | } 12 | 13 | function tip() public payable { 14 | (bool success, ) = owner.call{value: msg.value}(""); 15 | require(success, "Transfer failed"); 16 | } 17 | 18 | function donate() public { 19 | (bool success, ) = charityAddr.call{value: address(this).balance}(""); 20 | require(success, "Transfer failed"); 21 | } 22 | 23 | receive() external payable {} 24 | } 25 | -------------------------------------------------------------------------------- /smart-contracts-basics/sending-ethers/5-selfDestruct-contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Contract { 5 | address public owner; 6 | address private charityAddr; 7 | 8 | constructor(address _charityAddr) { 9 | owner = msg.sender; 10 | charityAddr = _charityAddr; 11 | } 12 | 13 | function tip() public payable { 14 | (bool success, ) = owner.call{value: msg.value}(""); 15 | require(success, "Transfer failed"); 16 | } 17 | 18 | function donate() public { 19 | selfdestruct(payable(charityAddr)); 20 | } 21 | 22 | receive() external payable {} 23 | } 24 | -------------------------------------------------------------------------------- /smart-contracts-basics/smart-contract-communication/1-getter-index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Find the `value` stored in the contract 3 | * 4 | * @param {ethers.Contract} contract - ethers.js contract instance 5 | * @return {promise} a promise which resolves with the `value` 6 | */ 7 | function getValue(contract) { 8 | return contract.value(); 9 | } 10 | 11 | module.exports = getValue; 12 | -------------------------------------------------------------------------------- /smart-contracts-basics/smart-contract-communication/2-setter-index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Modify the `value` stored in the contract 3 | * 4 | * @param {ethers.Contract} contract - ethers.js contract instance 5 | * @return {promise} a promise of transaction 6 | */ 7 | function setValue(contract) { 8 | contract.modify(4); 9 | } 10 | 11 | module.exports = setValue; 12 | -------------------------------------------------------------------------------- /smart-contracts-basics/smart-contract-communication/3-transfer.index.js: -------------------------------------------------------------------------------- 1 | i; 2 | /** 3 | * Transfer funds on the contract from the current signer 4 | * to the friends address 5 | * 6 | * @param {ethers.Contract} contract - ethers.js contract instance 7 | * @param {string} friend - a string containing a hexadecimal ethereum address 8 | * @return {promise} a promise of the transfer transaction 9 | */ 10 | function transfer(contract, friend) { 11 | contract.transfer(friend, 5); //we are not caring about decimal so chill 12 | } 13 | 14 | module.exports = transfer; 15 | -------------------------------------------------------------------------------- /smart-contracts-basics/smart-contract-communication/4-signer-index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Set the message on the contract using the signer passed in 3 | * 4 | * @param {ethers.Contract} contract - ethers.js contract instance 5 | * @param {ethers.types.Signer} signer - ethers.js signer instance 6 | * @return {promise} a promise of transaction modifying the `message` 7 | */ 8 | function setMessage(contract, signer) { 9 | return contract.connect(signer).modify("New Message"); 10 | } 11 | 12 | module.exports = setMessage; 13 | -------------------------------------------------------------------------------- /smart-contracts-basics/smart-contract-communication/5-deposit-index.js: -------------------------------------------------------------------------------- 1 | const ethers = require("ethers"); 2 | 3 | /** 4 | * Deposit at least 1 ether into the contract 5 | * 6 | * @param {ethers.Contract} contract - ethers.js contract instance 7 | * @return {promise} a promise of the deposit transaction 8 | */ 9 | function deposit(contract) { 10 | contract.deposit({ value: ethers.utils.parseEther("2") }); 11 | } 12 | 13 | module.exports = deposit; 14 | -------------------------------------------------------------------------------- /solidity-core/dead-man-switch/Switch.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.4; 3 | 4 | contract Switch { 5 | address public owner; 6 | address public recipient; 7 | uint256 totalBal; 8 | uint256 lastTimestamp; 9 | 10 | constructor(address _recipient) payable { 11 | owner = msg.sender; 12 | recipient = _recipient; 13 | totalBal = msg.value; 14 | lastTimestamp = block.timestamp + 52 weeks; 15 | } 16 | 17 | modifier onlyOwner() { 18 | require(msg.sender == owner, "Not Owner"); 19 | _; 20 | } 21 | 22 | modifier timeNotPassed() { 23 | require(lastTimestamp > block.timestamp, "Sorry! Time has passed"); 24 | _; 25 | } 26 | modifier timePassed() { 27 | require(lastTimestamp < block.timestamp, "Sorry! Time has not passed"); 28 | _; 29 | } 30 | 31 | function withdraw() external timePassed { 32 | (bool success, ) = recipient.call{value: totalBal}(""); 33 | require(success); 34 | } 35 | 36 | function ping() external onlyOwner timeNotPassed { 37 | lastTimestamp = block.timestamp + 52 weeks; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /solidity-core/hackathon-ratings/Hackathon.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Hackathon { 5 | struct Project { 6 | string title; 7 | uint256[] ratings; 8 | } 9 | 10 | Project[] projects; 11 | 12 | // Helper 13 | function getAverage(uint256[] memory _ratings) 14 | internal 15 | pure 16 | returns (uint256) 17 | { 18 | uint256 sum; 19 | for (uint256 i = 0; i < _ratings.length; i++) { 20 | sum += _ratings[i]; 21 | } 22 | return sum / _ratings.length; 23 | } 24 | 25 | function findWinner() external view returns (Project memory) { 26 | Project memory winner; 27 | uint256 winnerAverage = 0; 28 | for (uint256 i = 0; i < projects.length; i++) { 29 | uint256 average = getAverage(projects[i].ratings); 30 | if (average > winnerAverage) { 31 | winnerAverage = average; 32 | winner = projects[i]; 33 | } 34 | } 35 | return winner; 36 | } 37 | 38 | function newProject(string calldata _title) external { 39 | // creates a new project with a title and an empty ratings array 40 | projects.push(Project(_title, new uint256[](0))); 41 | } 42 | 43 | function rate(uint256 _idx, uint256 _rating) external { 44 | // rates a project by its index 45 | projects[_idx].ratings.push(_rating); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/1-constructor-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | constructor(address[] memory _owners, uint256 _required) { 9 | owners = _owners; 10 | required = _required; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/10-isConfirmed-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | modifier onlyOwners() { 30 | bool isOwner; 31 | for (uint256 i = 0; i < owners.length; i++) { 32 | if (msg.sender == owners[i]) { 33 | isOwner = true; 34 | } 35 | } 36 | require(isOwner, "Not an owner"); 37 | _; 38 | } 39 | 40 | function addTransaction(address to, uint256 value) 41 | internal 42 | returns (uint256) 43 | { 44 | require(to != address(0), "invalid recipient"); 45 | require(value > 0, "value is 0"); 46 | uint256 txCount = transactions.length; 47 | transactions.push(Transaction(to, value, false)); 48 | 49 | return txCount; 50 | } 51 | 52 | function confirmTransaction(uint256 txId) public onlyOwners { 53 | confirmations[txId][msg.sender] = true; 54 | } 55 | 56 | function submitTransaction(address to, uint256 value) external { 57 | uint256 txId = transactions.length; // No of tx as txId, this is zero-based so we are doing it before push 58 | addTransaction(to, value); 59 | confirmTransaction(txId); 60 | } 61 | 62 | function isConfirmed(uint256 txId) public view returns (bool) { 63 | uint256 confirmedTxs = getConfirmationsCount(txId); 64 | if (confirmedTxs == required) { 65 | return true; 66 | } else { 67 | return false; 68 | } 69 | } 70 | 71 | // view/pure function 72 | function transactionCount() public view returns (uint256) { 73 | return transactions.length; 74 | } 75 | 76 | function getConfirmationsCount(uint256 transactionId) 77 | public 78 | view 79 | returns (uint256) 80 | { 81 | uint256 count; 82 | for (uint256 i = 0; i < owners.length; i++) { 83 | if (confirmations[transactionId][owners[i]]) { 84 | count++; 85 | } 86 | } 87 | return count; 88 | } 89 | 90 | receive() external payable {} 91 | } 92 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/11-execute-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | modifier onlyOwners() { 30 | bool isOwner; 31 | for (uint256 i = 0; i < owners.length; i++) { 32 | if (msg.sender == owners[i]) { 33 | isOwner = true; 34 | } 35 | } 36 | require(isOwner, "Not an owner"); 37 | _; 38 | } 39 | 40 | function addTransaction(address to, uint256 value) 41 | internal 42 | returns (uint256) 43 | { 44 | require(to != address(0), "invalid recipient"); 45 | require(value > 0, "value is 0"); 46 | uint256 txCount = transactions.length; 47 | transactions.push(Transaction(to, value, false)); 48 | 49 | return txCount; 50 | } 51 | 52 | function confirmTransaction(uint256 txId) public onlyOwners { 53 | confirmations[txId][msg.sender] = true; 54 | } 55 | 56 | function submitTransaction(address to, uint256 value) external { 57 | uint256 txId = transactions.length; // No of tx as txId, this is zero-based so we are doing it before push 58 | addTransaction(to, value); 59 | confirmTransaction(txId); 60 | } 61 | 62 | function isConfirmed(uint256 txId) public view returns (bool) { 63 | uint256 confirmedTxs = getConfirmationsCount(txId); 64 | if (confirmedTxs == required) { 65 | return true; 66 | } else { 67 | return false; 68 | } 69 | } 70 | 71 | function executeTransaction(uint256 txId) public { 72 | bool _isConfirmed = isConfirmed(txId); 73 | require(_isConfirmed, "Sorry! Tx not confirmed"); 74 | Transaction memory _tx = transactions[txId]; // txId == index of transaction in transactions array 75 | transactions[txId].executed = true; // updating state before transfer to prevent possible re-entrency. refer https://www.youtube.com/watch?v=pYKI4ad3eV0&t=1018s 76 | (bool success, ) = _tx.to.call{value: _tx.value}(""); 77 | require(success, "Transfer failed in execute"); 78 | } 79 | 80 | // view/pure function 81 | function transactionCount() public view returns (uint256) { 82 | return transactions.length; 83 | } 84 | 85 | function getConfirmationsCount(uint256 transactionId) 86 | public 87 | view 88 | returns (uint256) 89 | { 90 | uint256 count; 91 | for (uint256 i = 0; i < owners.length; i++) { 92 | if (confirmations[transactionId][owners[i]]) { 93 | count++; 94 | } 95 | } 96 | return count; 97 | } 98 | 99 | receive() external payable {} 100 | } 101 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/12-executeConfirmed-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | modifier onlyOwners() { 30 | bool isOwner; 31 | for (uint256 i = 0; i < owners.length; i++) { 32 | if (msg.sender == owners[i]) { 33 | isOwner = true; 34 | } 35 | } 36 | require(isOwner, "Not an owner"); 37 | _; 38 | } 39 | 40 | function addTransaction(address to, uint256 value) 41 | internal 42 | returns (uint256) 43 | { 44 | require(to != address(0), "invalid recipient"); 45 | require(value > 0, "value is 0"); 46 | uint256 txCount = transactions.length; 47 | transactions.push(Transaction(to, value, false)); 48 | 49 | return txCount; 50 | } 51 | 52 | function confirmTransaction(uint256 txId) public onlyOwners { 53 | confirmations[txId][msg.sender] = true; 54 | bool _isConfirmed = isConfirmed(txId); 55 | if (_isConfirmed) { 56 | executeTransaction(txId); 57 | } 58 | } 59 | 60 | function submitTransaction(address to, uint256 value) external { 61 | uint256 txId = transactions.length; // No of tx as txId, this is zero-based so we are doing it before push 62 | addTransaction(to, value); 63 | confirmTransaction(txId); 64 | } 65 | 66 | function isConfirmed(uint256 txId) public view returns (bool) { 67 | uint256 confirmedTxs = getConfirmationsCount(txId); 68 | if (confirmedTxs == required) { 69 | return true; 70 | } else { 71 | return false; 72 | } 73 | } 74 | 75 | function executeTransaction(uint256 txId) public { 76 | bool _isConfirmed = isConfirmed(txId); 77 | require(_isConfirmed, "Sorry! Tx not confirmed"); 78 | Transaction memory _tx = transactions[txId]; // txId == index of transaction in transactions array 79 | transactions[txId].executed = true; // updating state before transfer to prevent possible re-entrency. refer https://www.youtube.com/watch?v=pYKI4ad3eV0&t=1018s 80 | (bool success, ) = _tx.to.call{value: _tx.value}(""); 81 | require(success, "Transfer failed in execute"); 82 | } 83 | 84 | // view/pure function 85 | function transactionCount() public view returns (uint256) { 86 | return transactions.length; 87 | } 88 | 89 | function getConfirmationsCount(uint256 transactiontxId) 90 | public 91 | view 92 | returns (uint256) 93 | { 94 | uint256 count; 95 | for (uint256 i = 0; i < owners.length; i++) { 96 | if (confirmations[transactiontxId][owners[i]]) { 97 | count++; 98 | } 99 | } 100 | return count; 101 | } 102 | 103 | receive() external payable {} 104 | } 105 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/13-sendingCalldata-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | bytes data; 17 | } 18 | 19 | constructor(address[] memory _owners, uint256 _required) { 20 | require(_owners.length >= 1, "No owners set"); 21 | require(_required >= 1, "Zero required confirmation set"); 22 | require( 23 | _required <= _owners.length, 24 | "cannot set confirmation more the owners" 25 | ); 26 | owners = _owners; 27 | required = _required; 28 | } 29 | 30 | modifier onlyOwners() { 31 | bool isOwner; 32 | for (uint256 i = 0; i < owners.length; i++) { 33 | if (msg.sender == owners[i]) { 34 | isOwner = true; 35 | } 36 | } 37 | require(isOwner, "Not an owner"); 38 | _; 39 | } 40 | 41 | function addTransaction( 42 | address to, 43 | uint256 value, 44 | bytes calldata data 45 | ) internal returns (uint256) { 46 | require(to != address(0), "invalid recipient"); 47 | uint256 txCount = transactions.length; 48 | transactions.push(Transaction(to, value, false, data)); 49 | 50 | return txCount; 51 | } 52 | 53 | function confirmTransaction(uint256 txId) public onlyOwners { 54 | confirmations[txId][msg.sender] = true; 55 | bool _isConfirmed = isConfirmed(txId); 56 | if (_isConfirmed) { 57 | executeTransaction(txId); 58 | } 59 | } 60 | 61 | function submitTransaction( 62 | address to, 63 | uint256 value, 64 | bytes calldata data 65 | ) external { 66 | uint256 txId = transactions.length; // No of tx as txId, this is zero-based so we are doing it before push 67 | addTransaction(to, value, data); 68 | confirmTransaction(txId); 69 | } 70 | 71 | function isConfirmed(uint256 txId) public view returns (bool) { 72 | uint256 confirmedTxs = getConfirmationsCount(txId); 73 | if (confirmedTxs == required) { 74 | return true; 75 | } else { 76 | return false; 77 | } 78 | } 79 | 80 | function executeTransaction(uint256 txId) public { 81 | bool _isConfirmed = isConfirmed(txId); 82 | require(_isConfirmed, "Sorry! Tx not confirmed"); 83 | Transaction memory _tx = transactions[txId]; // txId == index of transaction in transactions array 84 | transactions[txId].executed = true; // updating state before transfer to prevent possible re-entrency. refer https://www.youtube.com/watch?v=pYKI4ad3eV0&t=1018s 85 | (bool success, ) = _tx.to.call{value: _tx.value}(_tx.data); 86 | require(success, "Transfer failed in execute"); 87 | } 88 | 89 | // view/pure function 90 | function transactionCount() public view returns (uint256) { 91 | return transactions.length; 92 | } 93 | 94 | function getConfirmationsCount(uint256 transactiontxId) 95 | public 96 | view 97 | returns (uint256) 98 | { 99 | uint256 count; 100 | for (uint256 i = 0; i < owners.length; i++) { 101 | if (confirmations[transactiontxId][owners[i]]) { 102 | count++; 103 | } 104 | } 105 | return count; 106 | } 107 | 108 | receive() external payable {} 109 | } 110 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/2-error-handling-multiSIg.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | constructor(address[] memory _owners, uint256 _required) { 9 | require(_owners.length >= 1, "No owners set"); 10 | require(_required >= 1, "Zero required confirmation set"); 11 | require( 12 | _required <= _owners.length, 13 | "cannot set confirmation more the owners" 14 | ); 15 | owners = _owners; 16 | required = _required; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/3-transaction-setup-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | struct Transaction { 11 | address to; 12 | uint256 value; 13 | bool executed; 14 | } 15 | 16 | constructor(address[] memory _owners, uint256 _required) { 17 | require(_owners.length >= 1, "No owners set"); 18 | require(_required >= 1, "Zero required confirmation set"); 19 | require( 20 | _required <= _owners.length, 21 | "cannot set confirmation more the owners" 22 | ); 23 | owners = _owners; 24 | required = _required; 25 | } 26 | 27 | function transactionCount() public view returns (uint256) { 28 | return transactions.length; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/4-addTransactions-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | struct Transaction { 11 | address to; 12 | uint256 value; 13 | bool executed; 14 | } 15 | 16 | constructor(address[] memory _owners, uint256 _required) { 17 | require(_owners.length >= 1, "No owners set"); 18 | require(_required >= 1, "Zero required confirmation set"); 19 | require( 20 | _required <= _owners.length, 21 | "cannot set confirmation more the owners" 22 | ); 23 | owners = _owners; 24 | required = _required; 25 | } 26 | 27 | function addTransaction(address to, uint256 value) 28 | public 29 | returns (uint256) 30 | { 31 | require(to != address(0), "invalid recipient"); 32 | require(value > 0, "value is 0"); 33 | uint256 txCount = transactions.length; 34 | transactions.push(Transaction(to, value, false)); 35 | 36 | return txCount; 37 | } 38 | 39 | // view/pure function 40 | function transactionCount() public view returns (uint256) { 41 | return transactions.length; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/5-confirmations-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | function addTransaction(address to, uint256 value) 30 | public 31 | returns (uint256) 32 | { 33 | require(to != address(0), "invalid recipient"); 34 | require(value > 0, "value is 0"); 35 | uint256 txCount = transactions.length; 36 | transactions.push(Transaction(to, value, false)); 37 | 38 | return txCount; 39 | } 40 | 41 | // view/pure function 42 | function transactionCount() public view returns (uint256) { 43 | return transactions.length; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/6-confirm-transactions-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | function addTransaction(address to, uint256 value) 30 | public 31 | returns (uint256) 32 | { 33 | require(to != address(0), "invaltxId recipient"); 34 | require(value > 0, "value is 0"); 35 | uint256 txCount = transactions.length; 36 | transactions.push(Transaction(to, value, false)); 37 | 38 | return txCount; 39 | } 40 | 41 | function confirmTransaction(uint256 txId) public { 42 | confirmations[txId][msg.sender] = true; 43 | } 44 | 45 | // view/pure function 46 | function transactionCount() public view returns (uint256) { 47 | return transactions.length; 48 | } 49 | 50 | function getConfirmationsCount(uint256 transactiontxId) 51 | public 52 | view 53 | returns (uint256) 54 | { 55 | uint256 count; 56 | for (uint256 i = 0; i < owners.length; i++) { 57 | if (confirmations[transactiontxId][owners[i]]) { 58 | count++; 59 | } 60 | } 61 | return count; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/7-confirm-security-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | modifier onlyOwners() { 30 | bool isOwner; 31 | for (uint256 i = 0; i < owners.length; i++) { 32 | if (msg.sender == owners[i]) { 33 | isOwner = true; 34 | } 35 | } 36 | require(isOwner, "Not an owner"); 37 | _; 38 | } 39 | 40 | function addTransaction(address to, uint256 value) 41 | public 42 | returns (uint256) 43 | { 44 | require(to != address(0), "invaltxId recipient"); 45 | require(value > 0, "value is 0"); 46 | uint256 txCount = transactions.length; 47 | transactions.push(Transaction(to, value, false)); 48 | 49 | return txCount; 50 | } 51 | 52 | function confirmTransaction(uint256 txId) public onlyOwners { 53 | confirmations[txId][msg.sender] = true; 54 | } 55 | 56 | // view/pure function 57 | function transactionCount() public view returns (uint256) { 58 | return transactions.length; 59 | } 60 | 61 | function getConfirmationsCount(uint256 transactionId) 62 | public 63 | view 64 | returns (uint256) 65 | { 66 | uint256 count; 67 | for (uint256 i = 0; i < owners.length; i++) { 68 | if (confirmations[transactionId][owners[i]]) { 69 | count++; 70 | } 71 | } 72 | return count; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/8-submit-transaction-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | modifier onlyOwners() { 30 | bool isOwner; 31 | for (uint256 i = 0; i < owners.length; i++) { 32 | if (msg.sender == owners[i]) { 33 | isOwner = true; 34 | } 35 | } 36 | require(isOwner, "Not an owner"); 37 | _; 38 | } 39 | 40 | function addTransaction(address to, uint256 value) 41 | internal 42 | returns (uint256) 43 | { 44 | require(to != address(0), "invalid recipient"); 45 | require(value > 0, "value is 0"); 46 | uint256 txCount = transactions.length; 47 | transactions.push(Transaction(to, value, false)); 48 | 49 | return txCount; 50 | } 51 | 52 | function confirmTransaction(uint256 txId) public onlyOwners { 53 | confirmations[txId][msg.sender] = true; 54 | } 55 | 56 | function submitTransaction(address to, uint256 value) external { 57 | uint256 txId = transactions.length; // No of tx as txId, this is zero-based so we are doing it before push 58 | addTransaction(to, value); 59 | confirmTransaction(txId); 60 | } 61 | 62 | // view/pure function 63 | function transactionCount() public view returns (uint256) { 64 | return transactions.length; 65 | } 66 | 67 | function getConfirmationsCount(uint256 transactionId) 68 | public 69 | view 70 | returns (uint256) 71 | { 72 | uint256 count; 73 | for (uint256 i = 0; i < owners.length; i++) { 74 | if (confirmations[transactionId][owners[i]]) { 75 | count++; 76 | } 77 | } 78 | return count; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /solidity-core/multi-sigs/9-receive-multiSig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract MultiSig { 5 | address[] public owners; 6 | uint256 public required; 7 | 8 | Transaction[] public transactions; 9 | 10 | mapping(uint256 => mapping(address => bool)) public confirmations; 11 | 12 | struct Transaction { 13 | address to; 14 | uint256 value; 15 | bool executed; 16 | } 17 | 18 | constructor(address[] memory _owners, uint256 _required) { 19 | require(_owners.length >= 1, "No owners set"); 20 | require(_required >= 1, "Zero required confirmation set"); 21 | require( 22 | _required <= _owners.length, 23 | "cannot set confirmation more the owners" 24 | ); 25 | owners = _owners; 26 | required = _required; 27 | } 28 | 29 | modifier onlyOwners() { 30 | bool isOwner; 31 | for (uint256 i = 0; i < owners.length; i++) { 32 | if (msg.sender == owners[i]) { 33 | isOwner = true; 34 | } 35 | } 36 | require(isOwner, "Not an owner"); 37 | _; 38 | } 39 | 40 | function addTransaction(address to, uint256 value) 41 | internal 42 | returns (uint256) 43 | { 44 | require(to != address(0), "invalid recipient"); 45 | require(value > 0, "value is 0"); 46 | uint256 txCount = transactions.length; 47 | transactions.push(Transaction(to, value, false)); 48 | 49 | return txCount; 50 | } 51 | 52 | function confirmTransaction(uint256 txId) public onlyOwners { 53 | confirmations[txId][msg.sender] = true; 54 | } 55 | 56 | function submitTransaction(address to, uint256 value) external { 57 | uint256 txId = transactions.length; // No of tx as txId, this is zero-based so we are doing it before push 58 | addTransaction(to, value); 59 | confirmTransaction(txId); 60 | } 61 | 62 | // view/pure function 63 | function transactionCount() public view returns (uint256) { 64 | return transactions.length; 65 | } 66 | 67 | function getConfirmationsCount(uint256 transactionId) 68 | public 69 | view 70 | returns (uint256) 71 | { 72 | uint256 count; 73 | for (uint256 i = 0; i < owners.length; i++) { 74 | if (confirmations[transactionId][owners[i]]) { 75 | count++; 76 | } 77 | } 78 | return count; 79 | } 80 | 81 | receive() external payable {} 82 | } 83 | -------------------------------------------------------------------------------- /solidity-core/party-split/1-rsvp-Party.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Party { 5 | uint256 amountToSend; 6 | address[] participants; 7 | 8 | constructor(uint256 amount) { 9 | amountToSend = amount; 10 | } 11 | 12 | function rsvp() external payable { 13 | require(msg.value == amountToSend, "amount is not correct"); 14 | // reading from storage is expensive, so we create a memory variable to copy the array 15 | address[] memory _participants = participants; 16 | for (uint256 i = 0; i < _participants.length; i++) { 17 | if (_participants[i] == msg.sender) { 18 | revert("Already joined"); 19 | } 20 | } 21 | participants.push(msg.sender); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /solidity-core/party-split/2-rsvp-payBills.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | contract Party { 5 | uint256 amountToSend; 6 | address[] participants; 7 | 8 | constructor(uint256 amount) { 9 | amountToSend = amount; 10 | } 11 | 12 | function rsvp() external payable { 13 | require(msg.value == amountToSend, "amount is not correct"); 14 | address[] memory _participants = participants; 15 | for (uint256 i = 0; i < _participants.length; i++) { 16 | if (_participants[i] == msg.sender) { 17 | revert("Already joined"); 18 | } 19 | } 20 | participants.push(msg.sender); 21 | } 22 | 23 | function payBill(address venue, uint256 amount) external { 24 | (bool success, ) = payable(venue).call{value: amount}(""); 25 | require(success, "Transfer to organiser Failed"); 26 | uint256 remainingBalance = address(this).balance; 27 | if (remainingBalance != 0) { 28 | uint256 sharePerPerson = remainingBalance / participants.length; 29 | address[] memory _participants = participants; 30 | for (uint256 i = 0; i < _participants.length; i++) { 31 | (bool _success, ) = payable(_participants[i]).call{ 32 | value: sharePerPerson 33 | }(""); 34 | require(_success, "Transfer to participant Failed"); 35 | } 36 | } 37 | } 38 | } 39 | --------------------------------------------------------------------------------