├── .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 | [](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 |
--------------------------------------------------------------------------------