diff --git a/Dockerfile b/Dockerfile index 58ca644..9c69de5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,3 +2,6 @@ FROM node:7-onbuild ENV PORT 8080 EXPOSE 8080 + +ENV NAME autobounty +ENV STANDARD_BOUNTY 0.001 diff --git a/index.js b/index.js index 878f95c..5d1f62d 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,19 @@ +/* + * Bot that receives a POST request (from a GitHub issue comment webhook) + * and in case it's a comment that has "@autobounty " + * awards that bounty to the address posted earlier in the thread (by the + * commiteth bot). + * TODO tests + * REVIEW parsing, non-persisting storage of addresses, hardcoded string length. + * Depends on commiteth version as of 2017-06-10. + */ + const SignerProvider = require('ethjs-provider-signer'); const sign = require('ethjs-signer').sign; const Eth = require('ethjs-query'); -const address = process.env.ADDRESS +const address = process.env.ADDRESS; +const name = process.env.NAME; const provider = new SignerProvider(process.env.NODE, { signTransaction: (rawTx, cb) => cb(null, sign(rawTx, process.env.KEY)), @@ -12,32 +23,65 @@ const eth = new Eth(provider); var express = require('express'), cors = require('cors'), - app = express(); + app = express(), + bodyParser = require('body-parser'), + jsonParser = bodyParser.json(); app.use(cors()); -app.get('/address/:address', function(req, res, next){ - eth.getTransactionCount(address, (err, nonce) => { - eth.sendTransaction({ - from: address, - to: req.params.address, - gas: 100000, - value: (parseFloat(process.env.AMOUNT) || 1.5) * 1e18, - data: '0xde5f72fd', // sha3('faucet()') - nonce, - }, (err, txID) => { - if (err) { - console.log('Request failed', err) - return res.status(500).json(err) +// Store issue ids and their bounty addresses +var issueData = {}; + +// Receive a POST request at the address specified by an env. var. +app.post('/' + address.toString(), jsonParser, function(req, res, next){ + if (!req.body) + return res.sendStatus(400); + var commentBody = req.body.comment.body; + var issueId = req.body.issue.id; + var namePosition = commentBody.search("@" + name); + // Store toAddress from commiteth + if (namePosition == -1 && req.body.comment.user.login == 'commiteth') { // TODO no existence check + issueData[issueId] = {"toAddress": commentBody.substring(commentBody.search("Contract address:") + 18, commentBody.search("Contract address:") + 60)} + console.log(issueData); + return res.status(204); + } + else { + var postNameWords = commentBody.substring(namePosition + 1 + name.length + 1).trim().split(' '); + var amount = 0; + if (postNameWords.length > 0) { + if(postNameWords[0] == "standard") { + amount = process.env.STANDARD_BOUNTY; } else { - console.log('Successful request:', txID) - res.json({ txID }) + amount = parseFloat(postNameWords[0]); } + } + console.log("Trying to give " + amount + " ETH to " + issueData[issueId].toAddress + " for issue " + issueId); + issueData[issueId].amount = amount; + + // Conduct the transaction + eth.getTransactionCount(address, (err, nonce) => { + eth.sendTransaction({ + from: address, // Specified in webhook, secret + to: issueData[issueId].toAddress, // Address from earlier in the thread + gas: 100000, + value: issueData[issueId].amount, + nonce, + }, (err, txID) => { + if (err) { + console.log('Request failed', err) + return res.status(500).json(err) + } + else { + console.log('Successful request:', txID) + res.json({ txID }) + } + }); }); - }) + } }); const port = process.env.PORT || 8181 app.listen(port, function(){ - console.log('Faucet listening on port', port); + console.log('Autobounty listening on port', port); +}); diff --git a/package.json b/package.json index ca2dca5..c1ba9e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "kovan-faucet", + "name": "autobounty", "version": "1.0.0", - "description": "", + "description": "Automatically award bounty specified to the address in issue tracker", "main": "index.js", "scripts": { "start": "node index.js", @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "dependencies": { + "body-parser": "^1.17.2", "cors": "^2.8.1", "ethjs-provider-signer": "^0.1.4", "ethjs-query": "^0.2.4",