├── .babelrc ├── run.sh ├── video.mp4 ├── Diagram.png ├── PrintPaper.pdf ├── issue_candy.sh ├── PrintPaper.pages ├── receiverAddress.png ├── video_thumbnail2.png ├── .gitignore ├── package.json ├── README.md ├── lircd.conf ├── erc20abi.json └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | npm run start > run.log 2>&1 & 3 | -------------------------------------------------------------------------------- /video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizzahackathon/candoreum/HEAD/video.mp4 -------------------------------------------------------------------------------- /Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizzahackathon/candoreum/HEAD/Diagram.png -------------------------------------------------------------------------------- /PrintPaper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizzahackathon/candoreum/HEAD/PrintPaper.pdf -------------------------------------------------------------------------------- /issue_candy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /usr/bin/irsend SEND_ONCE /home/pi/lircd.conf KEY_1 3 | -------------------------------------------------------------------------------- /PrintPaper.pages: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizzahackathon/candoreum/HEAD/PrintPaper.pages -------------------------------------------------------------------------------- /receiverAddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizzahackathon/candoreum/HEAD/receiverAddress.png -------------------------------------------------------------------------------- /video_thumbnail2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizzahackathon/candoreum/HEAD/video_thumbnail2.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /src/views/Test.vue 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | run.log 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw* 24 | firebase-function/ 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "candoreum", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "rimraf dist/ && babel ./ --out-dir dist/ --ignore ./node_modules,./.babelrc,./package.json,./npm-debug.log --copy-files", 9 | "start": "npm run build && node dist/index.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "babel-cli": "^6.26.0", 16 | "babel-preset-es2015": "^6.24.1", 17 | "rimraf": "^2.6.2" 18 | }, 19 | "dependencies": { 20 | "web3": "^1.0.0-beta.35" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Intruduction 2 | Candoreum is a demonstration project for Pizza Hackathong 2018, Bangkok. 3 | Allow user to send ETH Testnet on their wallet to pay for candy. 4 | 5 | [![Watch the video](https://raw.githubusercontent.com/pizzahackathon/candoreum/master/video_thumbnail2.png)](https://youtu.be/kKiIBf9d23I) 6 | 7 | 8 | ## Daigram 9 |

10 | 11 | 12 | 13 |

14 | 15 | # Setup 16 | Configure IR Transmiter with this http://www.lirc.org/html/lircd.conf.html 17 | ** Learn IR with your remote control. 18 | 19 | # Run it 20 | - npm install 21 | - npm run start 22 | -------------------------------------------------------------------------------- /lircd.conf: -------------------------------------------------------------------------------- 1 | 2 | # Please make this file available to others 3 | # by sending it to 4 | # 5 | # this config file was automatically generated 6 | # using lirc-0.9.0-pre1(default) on Mon Jul 30 11:30:41 2018 7 | # 8 | # contributed by 9 | # 10 | # brand: /home/pi/lircd.conf 11 | # model no. of remote control: 12 | # devices being controlled by this remote: 13 | # 14 | 15 | begin remote 16 | 17 | name /home/pi/lircd.conf 18 | bits 0 19 | flags SPACE_ENC|CONST_LENGTH 20 | eps 30 21 | aeps 100 22 | 23 | header 8938 4502 24 | one 548 1692 25 | zero 548 564 26 | ptrail 542 27 | pre_data_bits 32 28 | pre_data 0xFFC23D 29 | gap 106775 30 | toggle_bit_mask 0x0 31 | 32 | begin codes 33 | KEY_1 0x0 34 | KEY_0 0x0 35 | end codes 36 | 37 | end remote 38 | 39 | 40 | -------------------------------------------------------------------------------- /erc20abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "totalSupply", 6 | "outputs": [ 7 | { 8 | "name": "", 9 | "type": "uint256" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "view", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": true, 18 | "inputs": [ 19 | { 20 | "name": "_owner", 21 | "type": "address" 22 | } 23 | ], 24 | "name": "balanceOf", 25 | "outputs": [ 26 | { 27 | "name": "balance", 28 | "type": "uint256" 29 | } 30 | ], 31 | "payable": false, 32 | "stateMutability": "view", 33 | "type": "function" 34 | }, 35 | { 36 | "constant": false, 37 | "inputs": [ 38 | { 39 | "name": "_to", 40 | "type": "address" 41 | }, 42 | { 43 | "name": "_value", 44 | "type": "uint256" 45 | } 46 | ], 47 | "name": "transfer", 48 | "outputs": [], 49 | "payable": false, 50 | "stateMutability": "nonpayable", 51 | "type": "function" 52 | }, 53 | { 54 | "anonymous": false, 55 | "inputs": [ 56 | { 57 | "indexed": true, 58 | "name": "from", 59 | "type": "address" 60 | }, 61 | { 62 | "indexed": true, 63 | "name": "to", 64 | "type": "address" 65 | }, 66 | { 67 | "indexed": false, 68 | "name": "value", 69 | "type": "uint256" 70 | } 71 | ], 72 | "name": "Transfer", 73 | "type": "event" 74 | } 75 | ] -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3' 2 | const util = require('util') 3 | const exec = util.promisify(require('child_process').exec) 4 | const ISSUE_CANDY_COMMAND = './issue_candy.sh' 5 | const RECEIVER_ADDRESS = '0x7357c4eb39e8e7c4d66635e2d76b343be759c88b' 6 | 7 | const enableERC20Receiver = true 8 | 9 | let erc20 = null 10 | const erc20Address = '0x10be9de395276482721e102de303316a384c0c9b' 11 | let latestFetchBlockHeight = 3397268 12 | const erc20Abi = require('./erc20abi.json') 13 | 14 | // Initial web3 15 | // const web3 = new Web3('wss://mainnet.infura.io/_ws') 16 | // const web3 = new Web3('wss://ropsten.infura.io/_ws') 17 | // const web3 = new Web3('wss://rinkeby.infura.io/_ws') 18 | const web3 = new Web3('wss://kovan.infura.io/ws') 19 | // const web3 = new Web3('https://public-node.testnet.rsk.co/') 20 | 21 | // Issue candy command, use IR transmit to send signal to candy machine. 22 | async function issueCandy() { 23 | const { stdout, stderr } = await exec(ISSUE_CANDY_COMMAND) 24 | console.log('stdout:', stdout) 25 | console.log('stderr:', stderr) 26 | } 27 | 28 | async function startCheckingERC20 () { 29 | let currentBlockHeight = await web3.eth.getBlockNumber() 30 | latestFetchBlockHeight = currentBlockHeight - 1 31 | checkReceiveNewERC20() 32 | } 33 | 34 | async function checkReceiveNewERC20 () { 35 | let currentBlockHeight = await web3.eth.getBlockNumber() 36 | 37 | // No need to fetch when no new block 38 | if (latestFetchBlockHeight + 1 > currentBlockHeight) { 39 | setTimeout(() => { 40 | checkReceiveNewERC20() 41 | }, 1000) 42 | } else { 43 | erc20.getPastEvents('Transfer', { 44 | filter: { 45 | to: '0x7357c4eb39e8e7c4d66635e2d76b343be759c88b' 46 | }, 47 | fromBlock: latestFetchBlockHeight + 1, 48 | toBlock: currentBlockHeight 49 | }).then(events => { 50 | // Received ERC20 from new blocks 51 | console.log(`found ${events.length} txs in blocks ${latestFetchBlockHeight} - ${currentBlockHeight}`) // same results as the optional callback above 52 | 53 | // issue candy if any payment found 54 | if (events.length >= 1) { 55 | issueCandy() 56 | } 57 | 58 | latestFetchBlockHeight = currentBlockHeight 59 | setTimeout(() => { 60 | checkReceiveNewERC20() 61 | }, 1000) 62 | }) 63 | } 64 | } 65 | 66 | // Accept ERC20 67 | if (enableERC20Receiver) { 68 | erc20 = new web3.eth.Contract(erc20Abi, erc20Address) 69 | console.log(`Ready, feed me some ERC20 to ${RECEIVER_ADDRESS}`) 70 | startCheckingERC20() 71 | 72 | // Accept eth 73 | } else { 74 | // Subsribe to pending transaciton 75 | var subscription = web3.eth.subscribe('pendingTransactions') 76 | .on("data", transaction => { 77 | web3.eth.getTransaction(transaction).then(result => { 78 | // Found a new transaciton 79 | // Validate transaction info 80 | if (typeof result === 'undefined' || result == null || typeof result.to === 'undefined' || result.to === null) { 81 | return 82 | } 83 | 84 | // For debug uncomment this line 85 | // console.log('from: ' + result.from + ' to: ' + result.to + ' tx: ' + transaction) 86 | 87 | // Watch on incoming ether to RECEIVER_ADDRESS 88 | if (result.to.toLocaleLowerCase() === RECEIVER_ADDRESS.toLocaleLowerCase()) { 89 | console.log('from: ' + result.from + ' to: ' + result.to + ' tx: ' + transaction) 90 | issueCandy() 91 | } 92 | }) 93 | }) 94 | 95 | console.log(`Ready, feed me some ETHs to ${RECEIVER_ADDRESS}`) 96 | } 97 | --------------------------------------------------------------------------------