Hello, decentralized world!
19 |This is a template for a dApp desktop app. It is built using Muon + MetaMask + Electron Builder.
20 |Send me some ether to see it working (make sure you're using the testnet)
21 | 22 | 23 |├── .gitignore ├── .npmrc ├── your-app ├── package.json ├── index.js ├── package-lock.json └── index.html ├── setup.js ├── main.js ├── extensions.js ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | extensions/ 2 | node_modules/ 3 | dist/ 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | runtime = electron 2 | target_arch = x64 3 | brave_electron_version = 4.7.1 4 | chromedriver_version = 2.33 5 | target = 4.7.1 6 | disturl=http://brave-laptop-binaries.s3.amazonaws.com/atom-shell/dist/ 7 | build_from_source = true 8 | -------------------------------------------------------------------------------- /your-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "your-app", 3 | "version": "1.0.0", 4 | "description": "Your App's package.json", 5 | "main": "dist/main.js", 6 | "author": { 7 | "name": "You", 8 | "email": "you@your.email" 9 | }, 10 | "scripts": { 11 | "build": "cp index.js dist && cp index.html dist" 12 | }, 13 | "license": "Apache-2.0", 14 | "dependencies": { 15 | "web3": "^0.20.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /setup.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const spawn = require('child_process').spawn 3 | 4 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 5 | const options = { 6 | env: process.env, 7 | stdio: 'inherit', 8 | shell: true 9 | } 10 | const muon = spawn('electron', [__dirname, ...process.argv.slice(2)], options) 11 | 12 | muon.on('error', (err) => { 13 | console.error(`could not start electron ${err}`) 14 | }) 15 | 16 | muon.on('exit', (code, signal) => { 17 | console.log(`process exited with code ${code}`) 18 | process.exit(code) 19 | }) 20 | 21 | muon.on('SIGTERM', () => { 22 | electron.kill('SIGTERM') 23 | }) 24 | 25 | muon.on('SIGINT', () => { 26 | electron.kill('SIGINT') 27 | }) 28 | -------------------------------------------------------------------------------- /your-app/index.js: -------------------------------------------------------------------------------- 1 | if (typeof window.web3 !== 'undefined') { 2 | window.web3 = new Web3(window.web3.currentProvider); 3 | } else { 4 | // Other provider 5 | window.web3 = new Web3(new Web3.providers.HttpProvider('yourOtherProvider')); 6 | } 7 | 8 | function isElectron() { 9 | if(chrome.ipcRenderer) return true; 10 | return false; 11 | } 12 | 13 | function sendToElectron(message) { 14 | chrome.ipcRenderer.send(message); 15 | } 16 | 17 | function openMetamaskPopup() { 18 | sendToElectron('open-metamask-popup'); 19 | } 20 | 21 | function closeMetamaskPopup() { 22 | sendToElectron('close-metamask-popup'); 23 | } 24 | 25 | function openMetamaskNotification() { 26 | sendToElectron('open-metamask-notification'); 27 | } 28 | 29 | function closeMetamaskNotification() { 30 | sendToElectron('close-metamask-notification'); 31 | } 32 | 33 | function sendEther(contractFunction) { 34 | web3.eth.sendTransaction({ 35 | to: '0x8f6c0c887F7CAF7D512C964eA2a3e668D94C5304', 36 | value: '1000000000000' 37 | }, (err, res) => { 38 | if (err) closeMetamaskNotification(); 39 | if (res) closeMetamaskNotification(); 40 | }); 41 | 42 | setTimeout(() => { 43 | openMetamaskNotification(); 44 | }, 500); 45 | } 46 | -------------------------------------------------------------------------------- /your-app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "your-app", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "bignumber.js": { 8 | "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" 9 | }, 10 | "crypto-js": { 11 | "version": "3.1.8", 12 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", 13 | "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" 14 | }, 15 | "utf8": { 16 | "version": "2.1.2", 17 | "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", 18 | "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" 19 | }, 20 | "web3": { 21 | "version": "0.20.4", 22 | "resolved": "https://registry.npmjs.org/web3/-/web3-0.20.4.tgz", 23 | "integrity": "sha1-QA5leaZbtKPd5xpuv2UJr63DOgQ=", 24 | "requires": { 25 | "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", 26 | "crypto-js": "3.1.8", 27 | "utf8": "2.1.2", 28 | "xhr2": "0.1.4", 29 | "xmlhttprequest": "1.8.0" 30 | } 31 | }, 32 | "xhr2": { 33 | "version": "0.1.4", 34 | "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", 35 | "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" 36 | }, 37 | "xmlhttprequest": { 38 | "version": "1.8.0", 39 | "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", 40 | "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const { app, BrowserWindow, shell, session, Menu, ipcMain } = require('electron'); 2 | const path = require('path'); 3 | const url = require('url'); 4 | const fs = require('fs'); 5 | 6 | const extensions = require('./extensions'); 7 | 8 | let isDev; 9 | try { 10 | isDev = require('electron-is-dev'); 11 | } catch(e) { 12 | isDev = false; 13 | } 14 | 15 | if(isDev) { 16 | require('electron-reload')(path.join(__dirname)); 17 | } 18 | 19 | let win; 20 | 21 | function createWindow() { 22 | win = new BrowserWindow({ 23 | width: 1920, 24 | height: 1080 25 | }); 26 | 27 | extensions.loadMetamask(session, win, isDev); 28 | 29 | let indexPath; 30 | isDev ? indexPath = path.join(`brave/${__dirname}`, 'your-app/index.html') : indexPath = path.join(`brave/${__dirname}`, 'index.html'); 31 | 32 | setTimeout(() => { 33 | win.loadURL(url.format({ 34 | pathname: indexPath, 35 | protocol: 'chrome', 36 | slashes: true 37 | })); 38 | var template = [{ 39 | label: "Edit", 40 | submenu: [ 41 | { label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" }, 42 | { label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" }, 43 | { label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" } 44 | ]} 45 | ]; 46 | 47 | Menu.setApplicationMenu(Menu.buildFromTemplate(template)); 48 | win.maximize(); 49 | }, 200); 50 | 51 | win.webContents.openDevTools(); 52 | if(isDev) { 53 | } 54 | 55 | ipcMain.on('open-link', (evt, link) => { 56 | shell.openExternal(link); 57 | }); 58 | 59 | win.on('closed', () => { 60 | win = null; 61 | }); 62 | } 63 | 64 | app.on('ready', createWindow); 65 | 66 | app.on('window-all-closed', () => { 67 | if (process.platform !== 'darwin') { 68 | app.quit(); 69 | } 70 | }); 71 | 72 | app.on('activate', () => { 73 | if (win === null) { 74 | createWindow(); 75 | } 76 | }); 77 | -------------------------------------------------------------------------------- /your-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |This is a template for a dApp desktop app. It is built using Muon + MetaMask + Electron Builder.
20 |Send me some ether to see it working (make sure you're using the testnet)
21 | 22 | 23 |