├── .gitignore ├── LICENSE ├── README.md ├── contracts ├── .gitkeep └── Example.sol ├── deploy ├── .gitignore ├── compile.js ├── deploy.js ├── package-lock.json └── package.json ├── package.json ├── pages ├── _app.js ├── _document.js ├── about.js └── index.js ├── public ├── favicon.ico ├── icons │ ├── icon-192x192.png │ └── icon-512x512.png ├── img │ └── background.png ├── logo.svg ├── manifest.json └── robots.txt ├── src ├── components │ ├── ConnectWallet.jsx │ └── Navbar.jsx ├── contracts │ └── Example.js ├── hooks │ └── web3.js └── utils │ └── theme.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # misc 7 | .DS_Store 8 | .env.local 9 | .env.development.local 10 | .env.test.local 11 | .env.production.local 12 | 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Next.js 18 | /.next 19 | 20 | .env -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Aman Raj 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 |

Next.js Web3 template

3 | 4 |

🏗️ Next.js + Material UI + dark mode + web3 starter template ⚡

5 | 6 | This is a starter boilerplate Ethereum dapp using Next.js and material UI with dark mode. There are many web3 template available but most of them depends of web3-react. I tried to use minimum dependencies possible. 7 | 8 | ### Quick start 9 | 10 | The first things you need to do is clone repo. 11 | 12 | To compile and deploy contract 13 | 14 | ```bash 15 | cd deploy 16 | npm i 17 | npm start 18 | ``` 19 | 20 | Run the client on base directory 21 | 22 | ```bash 23 | yarn install 24 | yarn run dev 25 | ``` 26 | 27 | #### Project Structure 28 | 29 | ``` 30 | ├── contracts // All solidity files 31 | │ ├── Example.sol 32 | ├── deploy 33 | │ ├── compile.js // compiles contracts 34 | │ ├── deploy.js // deploy and get abi and bytecode 35 | │ ├── package.json 36 | ├── pages // All pages of nextjs 37 | │ ├── _app.js 38 | │ ├── _documesnt.js 39 | ├── public // contains static files 40 | │ ├── img 41 | │ ├── icons 42 | ├── src 43 | │ ├── contracts // here we store abi and bytecodes of contracts 44 | │ ├── components // react components 45 | │ ├── hooks // web and imp hooks 46 | │ ├── utils // theme and other lib files 47 | ├── .env 48 | ├── .gitignore 49 | ├── package.json 50 | └── README.md 51 | ``` 52 | -------------------------------------------------------------------------------- /contracts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmanRaj1608/nextjs-web3-template/d3b73ea56c7f2c7e54c2df39e11b800fcb72ecd9/contracts/.gitkeep -------------------------------------------------------------------------------- /contracts/Example.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.7.0 <0.8.3; 4 | 5 | contract Example { 6 | uint256 number; 7 | 8 | function store(uint256 num) public { 9 | number = num; 10 | } 11 | 12 | function retrieve() public view returns (uint256) { 13 | return number; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /deploy/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .env 3 | -------------------------------------------------------------------------------- /deploy/compile.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const solc = require('solc'); 4 | 5 | const contractPath = path.resolve(__dirname, '../contracts', 'Example.sol'); 6 | const source = fs.readFileSync(contractPath, 'utf8'); 7 | // console.log(source); 8 | 9 | const input = { 10 | language: 'Solidity', 11 | sources: { 12 | 'Example.sol': { 13 | content: source 14 | } 15 | }, 16 | settings: { 17 | outputSelection: { 18 | '*': { 19 | '*': ['*'] 20 | } 21 | } 22 | } 23 | } 24 | const result = JSON.parse(solc.compile(JSON.stringify(input))).contracts['Example.sol'].Example; 25 | // console.log(result); 26 | 27 | const { abi: interface, evm: { bytecode: { object } } } = result; 28 | // console.log(interface, object); 29 | 30 | module.exports = { interface, object }; // object is the actual name of the bytecode 31 | -------------------------------------------------------------------------------- /deploy/deploy.js: -------------------------------------------------------------------------------- 1 | const Web3 = require('web3'); 2 | const HDWalletProvider = require('@truffle/hdwallet-provider'); 3 | 4 | const { interface, object } = require('./compile'); 5 | 6 | const privateKey = '6ad90a424022be35f9a95ae44143db08c894ba44ed0de90b67199288e06924d5'; 7 | const rpcUrl = 'https://rinkeby.infura.io/v3/196440d5d02d41dfa2a8ee5bfd2e96bd'; 8 | 9 | const provider = new HDWalletProvider(privateKey, rpcUrl); 10 | const web3 = new Web3(provider); 11 | 12 | const deploy = async () => { 13 | const accounts = await web3.eth.getAccounts(); 14 | 15 | console.log('Attempting to deploy from account', accounts[0]); 16 | 17 | const result = await new web3.eth.Contract(interface) 18 | .deploy({ data: object }) 19 | .send({ gas: '1000000', from: accounts[0] }); 20 | 21 | console.log('Contract deployed to', result.options.address); 22 | }; 23 | 24 | deploy(); 25 | -------------------------------------------------------------------------------- /deploy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-web3-deploy", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "deploy.js", 6 | "scripts": { 7 | "start": "node deploy.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/AmanRaj1608/nextjs-web3-template.git" 12 | }, 13 | "keywords": [ 14 | "nextjs-web3-starter" 15 | ], 16 | "author": "Aman Raj ", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/AmanRaj1608/nextjs-web3-template/issues" 20 | }, 21 | "homepage": "https://github.com/AmanRaj1608/nextjs-web3-template#readme", 22 | "dependencies": { 23 | "@truffle/hdwallet-provider": "^1.2.2", 24 | "solc": "^0.8.2", 25 | "web3": "^1.3.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-web3-starter", 3 | "version": "1.0.0", 4 | "author": "Aman Raj ", 5 | "scripts": { 6 | "dev": "next", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "homepage": "https://github.com/AmanRaj1608/nextjs-web3-template", 11 | "license": "MIT", 12 | "dependencies": { 13 | "next": "^10.0.6", 14 | "react": "^17.0.1", 15 | "react-dom": "^17.0.1", 16 | "@material-ui/core": "^4.11.0", 17 | "@material-ui/icons": "^4.9.1", 18 | "web3": "^1.3.4", 19 | "ethers": "^5.0.31", 20 | "web3modal": "^1.9.3", 21 | "react-blockies": "^1.4.1", 22 | "@walletconnect/web3-provider": "^1.3.6" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import Head from 'next/head'; 3 | 4 | import { ThemeProvider } from '@material-ui/core/styles'; 5 | import CssBaseline from '@material-ui/core/CssBaseline'; 6 | 7 | import { darkTheme, lightTheme } from '../src/utils/theme'; 8 | import Navbar from '../src/components/Navbar'; 9 | 10 | const App = ({ Component, pageProps }) => { 11 | const [darkMode, setDarkMode] = useState(0); 12 | const [isMobile, setIsMobile] = useState(false); 13 | 14 | useEffect(() => { 15 | // Remove the server-side injected CSS. 16 | const jssStyles = document.querySelector('#jss-server-side'); 17 | if (jssStyles) { 18 | jssStyles.parentElement.removeChild(jssStyles); 19 | } 20 | // Setup darkmode 21 | setDarkMode( 22 | localStorage.getItem('mode') 23 | ? parseInt(localStorage.getItem('mode')) 24 | : 0 25 | ) 26 | // Naive check for mobile 27 | setIsMobile( 28 | navigator.userAgent.match( 29 | /(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i 30 | ) 31 | ) 32 | }, []); 33 | 34 | const toggleMode = () => { 35 | localStorage.setItem('mode', (1 - darkMode).toString()) 36 | setDarkMode(1 - darkMode) 37 | } 38 | 39 | const muiTheme = darkMode ? lightTheme : darkTheme; 40 | 41 | return ( 42 | 43 | 44 | Nextjs Web3 starter 45 | 46 | 47 | 48 | {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */} 49 | 50 | 55 | 59 | 60 | 61 | ); 62 | } 63 | 64 | export default App; -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Document, { Html, Head, Main, NextScript } from 'next/document'; 3 | 4 | import { ServerStyleSheets } from '@material-ui/core/styles'; 5 | 6 | export default class MyDocument extends Document { 7 | render() { 8 | return ( 9 | 10 | {/* SEO Part */} 11 | 12 | 13 | {/* Template by https://amanraj.dev/ */} 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | ); 35 | } 36 | } 37 | 38 | MyDocument.getInitialProps = async (ctx) => { 39 | const sheets = new ServerStyleSheets(); 40 | const originalRenderPage = ctx.renderPage; 41 | 42 | ctx.renderPage = () => 43 | originalRenderPage({ 44 | enhanceApp: (App) => (props) => sheets.collect(), 45 | }); 46 | 47 | const initialProps = await Document.getInitialProps(ctx); 48 | 49 | return { 50 | ...initialProps, 51 | // Styles fragment is rendered after the app and page rendering finish. 52 | styles: [ 53 | ...React.Children.toArray(initialProps.styles), 54 | sheets.getStyleElement(), 55 | ], 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /pages/about.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import Link from 'next/link'; 3 | 4 | import Typography from '@material-ui/core/Typography'; 5 | import { makeStyles } from '@material-ui/core/styles'; 6 | 7 | const Index = () => { 8 | const classes = useStyles(); 9 | 10 | return ( 11 |
12 |
13 | 14 | Web3 starter template 15 | 16 | 17 | Next.js + Material UI + dark mode + web3 starter template. Boilerplate to get starter quickly. 18 | 19 |
20 | 21 | Home 22 | 23 |
24 | ); 25 | } 26 | 27 | const useStyles = makeStyles((theme) => ({ 28 | main: { 29 | width: '100%', 30 | margin: '100px auto', 31 | maxWidth: 1100, 32 | textAlign: 'center' 33 | }, 34 | text: { 35 | fontSize: 18 36 | } 37 | })); 38 | 39 | export default Index; 40 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import Link from 'next/link'; 3 | 4 | import Typography from '@material-ui/core/Typography'; 5 | import { makeStyles } from '@material-ui/core/styles'; 6 | 7 | const Index = () => { 8 | const classes = useStyles(); 9 | 10 | return ( 11 |
12 |
13 | 14 | Web3 starter template 15 | 16 | 17 | Next.js + Material UI + dark mode + web3 starter template. Boilerplate to get starter quickly. 18 | 19 |
20 | 21 | About 22 | 23 |
24 | ); 25 | } 26 | 27 | const useStyles = makeStyles((theme) => ({ 28 | main: { 29 | width: '100%', 30 | margin: '100px auto', 31 | maxWidth: 1100, 32 | textAlign: 'center' 33 | }, 34 | text: { 35 | fontSize: 18 36 | } 37 | })); 38 | 39 | export default Index; 40 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmanRaj1608/nextjs-web3-template/d3b73ea56c7f2c7e54c2df39e11b800fcb72ecd9/public/favicon.ico -------------------------------------------------------------------------------- /public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmanRaj1608/nextjs-web3-template/d3b73ea56c7f2c7e54c2df39e11b800fcb72ecd9/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmanRaj1608/nextjs-web3-template/d3b73ea56c7f2c7e54c2df39e11b800fcb72ecd9/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /public/img/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmanRaj1608/nextjs-web3-template/d3b73ea56c7f2c7e54c2df39e11b800fcb72ecd9/public/img/background.png -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NextJS Web3 Starter", 3 | "short_name": "NextWeb3", 4 | "start_url": "/", 5 | "lang": "en-US", 6 | "display": "standalone", 7 | "background_color": "#000000", 8 | "theme_color": "#000000", 9 | "icons": [ 10 | { 11 | "src": "/icons/icon-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png", 20 | "purpose": "any" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | 4 | Sitemap: 5 | -------------------------------------------------------------------------------- /src/components/ConnectWallet.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Blockies from "react-blockies"; 3 | 4 | import { makeStyles } from '@material-ui/core/styles'; 5 | 6 | import { useWeb3Modal } from "../hooks/web3"; 7 | 8 | const truncateAddress = (address) => { 9 | return address.slice(0, 6) + "..." + address.slice(-4); 10 | }; 11 | 12 | const ConnectWallet = () => { 13 | const classes = useStyles(); 14 | 15 | const [signerAddress, setSignerAddress] = useState(""); 16 | // const [isWaiting, setWaiting] = useState(false) 17 | // const [isSent, setSent] = useState(false) 18 | // const [walletNotDetected, setWalletNotDetected] = useState(false) 19 | 20 | const { connectWallet, disconnectWallet, provider, error } = useWeb3Modal(); 21 | 22 | useEffect(() => { 23 | const getAddress = async () => { 24 | const signer = provider.getSigner(); 25 | const address = await signer.getAddress(); 26 | setSignerAddress(address); 27 | } 28 | if (provider) getAddress(); 29 | else setSignerAddress(""); 30 | }, [provider]); 31 | 32 | const handleClickConnect = async () => { 33 | await connectWallet(); 34 | }; 35 | 36 | const handleClickAddress = () => { 37 | disconnectWallet(); 38 | }; 39 | 40 | return ( 41 | 54 | ); 55 | } 56 | 57 | const useStyles = makeStyles((theme) => ({ 58 | btn: { 59 | background: 'rgb(183,192,238)', 60 | cursor: 'pointer', 61 | border: 0, 62 | outline: 'none', 63 | borderRadius: 9999, 64 | height: 35, 65 | display: 'flex', 66 | alignItems: 'center' 67 | }, 68 | img: { 69 | borderRadius: 999, 70 | marginRight: 5 71 | } 72 | })); 73 | 74 | export default ConnectWallet; -------------------------------------------------------------------------------- /src/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import AppBar from '@material-ui/core/AppBar'; 4 | import Toolbar from '@material-ui/core/Toolbar'; 5 | import Typography from '@material-ui/core/Typography'; 6 | import IconButton from '@material-ui/core/IconButton'; 7 | import { 8 | Brightness4Outlined as ToggleDarkModeIcon, 9 | Brightness5Outlined as ToggleLightModeIcon, 10 | } from "@material-ui/icons/"; 11 | import { makeStyles, useTheme } from '@material-ui/core/styles'; 12 | 13 | import dynamic from "next/dynamic"; 14 | const ConnectWallet = dynamic(() => import("./ConnectWallet"), { 15 | ssr: false, 16 | }); 17 | 18 | const Navbar = ({ toggleMode, darkMode }) => { 19 | const classes = useStyles(); 20 | const theme = useTheme(); 21 | 22 | return ( 23 | 24 | 25 | logo 26 | 27 | 28 | Next.js Web3 starter 29 | 30 | 31 | 38 | {darkMode ? : } 39 | 40 | 41 | 42 | 43 | 44 | ) 45 | } 46 | 47 | const useStyles = makeStyles((theme) => ({ 48 | root: { 49 | flexGrow: 1, 50 | margin: 'auto', 51 | maxWidth: 1100, 52 | boxShadow: 'none' 53 | }, 54 | img: { 55 | width: 50, 56 | marginRight: 20 57 | }, 58 | title: { 59 | flexGrow: 1, 60 | // color: '#784ffe', 61 | [theme.breakpoints.down('xs')]: { 62 | fontSize: 0, 63 | // display: 'none' 64 | }, 65 | }, 66 | toggleBtn: { 67 | marginRight: 20, 68 | [theme.breakpoints.down('xs')]: { 69 | marginRight: 5, 70 | }, 71 | } 72 | })); 73 | 74 | export default Navbar; -------------------------------------------------------------------------------- /src/contracts/Example.js: -------------------------------------------------------------------------------- 1 | export const abi = [ 2 | { 3 | "inputs": [], 4 | "name": "retrieve", 5 | "outputs": [ 6 | { 7 | "internalType": "uint256", 8 | "name": "", 9 | "type": "uint256" 10 | } 11 | ], 12 | "stateMutability": "view", 13 | "type": "function" 14 | }, 15 | { 16 | "inputs": [ 17 | { 18 | "internalType": "uint256", 19 | "name": "num", 20 | "type": "uint256" 21 | } 22 | ], 23 | "name": "store", 24 | "outputs": [], 25 | "stateMutability": "nonpayable", 26 | "type": "function" 27 | } 28 | ]; 29 | 30 | export const bytecode = { 31 | "generatedSources": [], 32 | "linkReferences": {}, 33 | "object": "608060405234801561001057600080fd5b5060c78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80632e64cec11460375780636057361d146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506087565b005b60008054905090565b806000819055505056fea26469706673582212209c3e0e66a7777942989215a6ccd2dc78a71a81a3f0a819541fddad256ac53d8664736f6c63430007040033", 34 | "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xC7 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x2E64CEC1 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x6057361D EQ PUSH1 0x53 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3D PUSH1 0x7E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x7C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x67 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x87 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST DUP1 PUSH1 0x0 DUP2 SWAP1 SSTORE POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 SWAP13 RETURNDATACOPY 0xE PUSH7 0xA7777942989215 0xA6 0xCC 0xD2 0xDC PUSH25 0xA71A81A3F0A819541FDDAD256AC53D8664736F6C6343000704 STOP CALLER ", 35 | "sourceMap": "74:206:0:-:0;;;;;;;;;;;;;;;;;;;" 36 | }; 37 | -------------------------------------------------------------------------------- /src/hooks/web3.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import { ethers } from "ethers"; 3 | import Web3Modal from "web3modal"; 4 | import WalletConnectProvider from "@walletconnect/web3-provider"; 5 | 6 | const providerOptions = { 7 | walletconnect: { 8 | package: WalletConnectProvider, 9 | options: { 10 | infuraId: '196440d5d02d41dfa2a8ee5bfd2e96bd', 11 | }, 12 | }, 13 | }; 14 | 15 | const web3Modal = new Web3Modal({ 16 | network: "kovan", 17 | cacheProvider: true, 18 | providerOptions, 19 | }); 20 | 21 | export function useWeb3Modal() { 22 | const [provider, setProvider] = useState(undefined); 23 | const [error, setError] = useState(null); 24 | 25 | // Automatically connect if the provider is cashed but has not yet 26 | // been set (e.g. page refresh) 27 | if (web3Modal.cachedProvider && !provider) { 28 | connectWallet(); 29 | } 30 | 31 | async function connectWallet() { 32 | try { 33 | const externalProvider = await web3Modal.connect(); 34 | const ethersProvider = new ethers.providers.Web3Provider(externalProvider); 35 | 36 | setProvider(ethersProvider); 37 | } catch(e) { 38 | setError('NO_WALLET_CONNECTED'); 39 | console.log('NO_WALLET_CONNECTED', e); 40 | } 41 | } 42 | 43 | function disconnectWallet() { 44 | web3Modal.clearCachedProvider(); 45 | setProvider(undefined); 46 | } 47 | 48 | return { connectWallet, disconnectWallet, provider, error } 49 | } 50 | -------------------------------------------------------------------------------- /src/utils/theme.js: -------------------------------------------------------------------------------- 1 | import { red, amber, grey } from "@material-ui/core/colors"; 2 | import { createMuiTheme, responsiveFontSizes } from "@material-ui/core/styles"; 3 | 4 | const fontFamilyRoboto = { 5 | fontFamily: [ 6 | "Roboto", 7 | "Arial", 8 | "sans-serif", 9 | '"Apple Color Emoji"', 10 | '"Segoe UI Emoji"', 11 | '"Segoe UI Symbol"' 12 | ].join(",") 13 | }; 14 | 15 | const fontFamilyMetropolis = { 16 | fontFamily: [ 17 | "Metropolis", 18 | "Arial", 19 | "sans-serif", 20 | '"Apple Color Emoji"', 21 | '"Segoe UI Emoji"', 22 | '"Segoe UI Symbol"' 23 | ].join(","), 24 | letterSpacing: "0.015rem" 25 | }; 26 | 27 | // A custom theme for this app 28 | const lightMuiTheme = createMuiTheme({ 29 | type: "light", 30 | palette: { 31 | primary: { 32 | main: "#FFF" 33 | }, 34 | secondary: { 35 | main: amber[500], 36 | light: "#feefc3" 37 | }, 38 | error: { 39 | main: red.A400 40 | }, 41 | background: { 42 | default: "#FFF", 43 | highlight: "#F1F3F4" 44 | } 45 | }, 46 | typography: { 47 | ...fontFamilyRoboto, 48 | overline: { 49 | fontWeight: 500, 50 | fontSize: "0.7rem" 51 | } 52 | }, 53 | shape: { 54 | borderRadius: "0.5rem" 55 | }, 56 | zIndex: { 57 | appBar: 1200, 58 | drawer: 1100 59 | }, 60 | mixins: { 61 | drawer: { 62 | minWidth: 280 63 | } 64 | }, 65 | overrides: { 66 | // MuiCssBaseline: { 67 | // "@global": { 68 | // "@font-face": [ 69 | // Fonts.MetropolisRegular, 70 | // Fonts.MetropolisBold, 71 | // Fonts.RobotoRegular, 72 | // Fonts.RobotoMedium, 73 | // Fonts.RobotoBold 74 | // ] 75 | // } 76 | // }, 77 | MuiListItemText: { 78 | primary: { 79 | ...fontFamilyMetropolis, 80 | fontWeight: 500, 81 | fontSize: "0.87rem" 82 | } 83 | } 84 | }, 85 | custom: { 86 | fontFamily: { 87 | roboto: fontFamilyRoboto, 88 | metropolis: fontFamilyMetropolis 89 | }, 90 | palette: { 91 | iconColor: "#5f6368", 92 | itemBorderColor: "#DDDDDD", 93 | iconHighlight: grey[900], 94 | notesCheckbox: grey[700], 95 | profilePopColor: "#FFF", 96 | noteBackground: { 97 | default: "#0000", 98 | red: "#F28B82", 99 | orange: "#FBBC04", 100 | yellow: "#FFF475", 101 | green: "#CCFF90", 102 | cyan: "#A7FFEB", 103 | lightblue: "#CBF0F8", 104 | darkblue: "#AECBFA", 105 | purple: "#D7AEFB", 106 | pink: "#FDCFE8", 107 | brown: "#E6C9A8", 108 | grey: "#E8EAED" 109 | }, 110 | noteColorCheck: "#0007", 111 | labelBackground: "#0002" 112 | } 113 | } 114 | }); 115 | 116 | const darkMuiTheme = createMuiTheme({ 117 | type: "dark", 118 | palette: { 119 | primary: { 120 | main: "#212121" 121 | }, 122 | secondary: { 123 | main: amber[500], 124 | light: "#41331C" 125 | }, 126 | error: { 127 | main: red.A400 128 | }, 129 | background: { 130 | default: "#212121", 131 | highlight: "#535456" 132 | }, 133 | text: { 134 | primary: "#E8EAED", 135 | secondary: "#FFFFFFDE" 136 | } 137 | }, 138 | typography: { 139 | ...fontFamilyRoboto, 140 | overline: { 141 | fontWeight: 500, 142 | fontSize: "0.7rem" 143 | } 144 | }, 145 | shape: { 146 | borderRadius: "0.5rem" 147 | }, 148 | zIndex: { 149 | appBar: 1200, 150 | drawer: 1100 151 | }, 152 | mixins: { 153 | drawer: { 154 | minWidth: 280 155 | } 156 | }, 157 | overrides: { 158 | // MuiCssBaseline: { 159 | // "@global": { 160 | // "@font-face": [ 161 | // Fonts.MetropolisRegular, 162 | // Fonts.MetropolisBold, 163 | // Fonts.RobotoRegular, 164 | // Fonts.RobotoMedium, 165 | // Fonts.RobotoBold 166 | // ] 167 | // } 168 | // }, 169 | MuiListItemText: { 170 | primary: { 171 | ...fontFamilyMetropolis, 172 | fontWeight: 500, 173 | fontSize: "0.87rem" 174 | } 175 | } 176 | }, 177 | custom: { 178 | fontFamily: { 179 | roboto: fontFamilyRoboto, 180 | metropolis: fontFamilyMetropolis 181 | }, 182 | palette: { 183 | iconColor: "#949596", 184 | itemBorderColor: "#5F6368", 185 | iconHighlight: "#888A8B", 186 | notesCheckbox: "#5F6368", 187 | profilePopColor: "#2D2E30", 188 | noteBackground: { 189 | default: "#0000", 190 | red: "#5C2B29", 191 | orange: "#614A19", 192 | yellow: "#635D18", 193 | green: "#345920", 194 | cyan: "#16504B", 195 | lightblue: "#2D555E", 196 | darkblue: "#1E3A5F", 197 | purple: "#42275E", 198 | pink: "#5B2245", 199 | brown: "#442F19", 200 | grey: "#3C3F43" 201 | }, 202 | noteColorCheck: "#FFF7", 203 | labelBackground: "#0002" 204 | } 205 | } 206 | }); 207 | 208 | export const lightTheme = responsiveFontSizes(lightMuiTheme); 209 | export const darkTheme = responsiveFontSizes(darkMuiTheme); --------------------------------------------------------------------------------