2018-03-19 21:37:38 +00:00
|
|
|
const winston = require('winston')
|
2018-02-13 12:05:39 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
const ethers = require('ethers')
|
|
|
|
const Wallet = ethers.Wallet
|
|
|
|
const Contract = ethers.Contract
|
|
|
|
const providers = ethers.providers
|
|
|
|
const utils = ethers.utils
|
2018-02-13 12:05:39 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
const prices = require('./prices')
|
|
|
|
const config = require('../config')
|
|
|
|
const github = require('./github')
|
2018-01-19 17:33:27 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
const contractAddressString = 'Contract address:'
|
2018-03-19 20:43:57 +00:00
|
|
|
|
2018-01-19 17:33:27 +00:00
|
|
|
|
2018-01-22 11:24:19 +00:00
|
|
|
const logger = winston.createLogger({
|
2018-01-24 22:37:39 +00:00
|
|
|
level: 'info',
|
|
|
|
format: winston.format.json(),
|
|
|
|
transports: [
|
2018-02-23 16:33:00 +00:00
|
|
|
new winston.transports.File({ filename: './log/error.log', level: 'error' }),
|
|
|
|
new winston.transports.File({ filename: './log/info.log', level: 'info' }),
|
|
|
|
// new winston.transports.File({ filename: './log/combined.log' })
|
2018-01-24 22:37:39 +00:00
|
|
|
]
|
2018-03-19 21:37:38 +00:00
|
|
|
})
|
2018-01-19 17:33:27 +00:00
|
|
|
|
2018-01-20 12:51:57 +00:00
|
|
|
|
2018-01-24 22:37:39 +00:00
|
|
|
const needsFunding = function (req) {
|
2018-03-13 17:27:23 +00:00
|
|
|
if (req.body.action !== 'edited' || !req.body.hasOwnProperty('comment')) {
|
2018-01-19 17:33:27 +00:00
|
|
|
return false
|
2018-01-24 22:37:39 +00:00
|
|
|
} else if (req.body.comment.user.login !== config.githubUsername) {
|
2018-01-23 13:39:12 +00:00
|
|
|
return false
|
2018-01-25 00:01:57 +00:00
|
|
|
} else if (!hasAddress(req)) {
|
2018-03-19 21:37:38 +00:00
|
|
|
return false
|
2018-01-23 13:39:12 +00:00
|
|
|
}
|
2018-01-19 17:33:27 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-01-25 00:06:50 +00:00
|
|
|
const hasAddress = function (req) {
|
2018-03-19 21:37:38 +00:00
|
|
|
const commentBody = req.body.comment.body
|
2018-03-19 20:43:57 +00:00
|
|
|
if (commentBody.search(contractAddressString) === -1) {
|
2018-03-19 21:37:38 +00:00
|
|
|
return false
|
2018-01-25 00:01:57 +00:00
|
|
|
} else {
|
2018-03-19 21:37:38 +00:00
|
|
|
return true
|
2018-01-25 00:01:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-24 22:37:39 +00:00
|
|
|
const getAddress = function (req) {
|
2018-03-19 21:37:38 +00:00
|
|
|
const commentBody = req.body.comment.body
|
2018-03-19 20:43:57 +00:00
|
|
|
const index = commentBody.search(contractAddressString) + 19
|
|
|
|
return commentBody.substring(index, index + 42)
|
2018-01-24 22:37:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const getLabel = function (req) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
github.getLabels(req)
|
2018-01-25 00:06:50 +00:00
|
|
|
.then(labels => {
|
2018-03-19 21:37:38 +00:00
|
|
|
const bountyLabels = labels.filter(label => config.bountyLabels.hasOwnProperty(label.name))
|
2018-01-25 00:06:50 +00:00
|
|
|
if (bountyLabels.length === 1) {
|
2018-03-19 21:37:38 +00:00
|
|
|
resolve(bountyLabels[0])
|
2018-01-25 00:06:50 +00:00
|
|
|
} else {
|
2018-03-19 21:37:38 +00:00
|
|
|
reject('Error getting bounty labels')
|
2018-01-25 00:06:50 +00:00
|
|
|
}
|
|
|
|
}).catch(err => {
|
2018-03-19 21:37:38 +00:00
|
|
|
reject(err)
|
|
|
|
})
|
|
|
|
})
|
2018-01-19 17:33:27 +00:00
|
|
|
}
|
|
|
|
|
2018-01-25 00:06:50 +00:00
|
|
|
const getAmountMock = function (req) {
|
2018-01-22 16:05:42 +00:00
|
|
|
return new Promise((resolve, reject) => {
|
2018-03-19 21:37:38 +00:00
|
|
|
resolve(10)
|
|
|
|
})
|
2018-01-24 22:37:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const getAmount = function (req) {
|
|
|
|
return new Promise((resolve, reject) => {
|
2018-03-19 21:37:38 +00:00
|
|
|
const labelPromise = getLabel(req)
|
|
|
|
const tokenPricePromise = prices.getTokenPrice(config.token)
|
2018-01-19 17:33:27 +00:00
|
|
|
|
2018-01-22 20:21:31 +00:00
|
|
|
Promise.all([labelPromise, tokenPricePromise])
|
2018-01-24 22:37:39 +00:00
|
|
|
.then(function (values) {
|
2018-03-19 21:37:38 +00:00
|
|
|
let label = values[0]
|
|
|
|
let tokenPrice = values[1]
|
|
|
|
let amountToPayDollar = config.priceHour * config.bountyLabels[label.name]
|
|
|
|
resolve(amountToPayDollar / tokenPrice)
|
2018-01-24 22:37:39 +00:00
|
|
|
})
|
|
|
|
.catch((err) => {
|
2018-03-19 21:37:38 +00:00
|
|
|
reject(err)
|
|
|
|
})
|
|
|
|
})
|
2018-01-19 17:33:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-22 15:50:23 +00:00
|
|
|
// Logging functions
|
|
|
|
|
2018-02-27 11:11:59 +00:00
|
|
|
const logTransaction = function (tx) {
|
2018-03-19 21:37:38 +00:00
|
|
|
logger.info("[OK] Succesfully funded bounty with transaction " + tx.hash)
|
|
|
|
logger.info(" * From: " + tx.from)
|
|
|
|
logger.info(" * To: " + tx.to)
|
|
|
|
logger.info(" * Amount: " + tx.value)
|
|
|
|
logger.info(" * Gas Price: " + tx.gasPrice)
|
|
|
|
logger.info("====================================================")
|
2018-01-19 17:33:27 +00:00
|
|
|
}
|
|
|
|
|
2018-02-13 10:43:28 +00:00
|
|
|
const info = function (msg) {
|
2018-03-19 21:37:38 +00:00
|
|
|
logger.info(msg)
|
2018-01-19 17:33:27 +00:00
|
|
|
}
|
|
|
|
|
2018-01-24 22:37:39 +00:00
|
|
|
const error = function (errorMessage) {
|
2018-03-19 21:37:38 +00:00
|
|
|
logger.error("[ERROR] Request processing failed: " + errorMessage)
|
2018-01-22 15:50:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-19 20:43:57 +00:00
|
|
|
const sendTransaction = async function (to, amount, gasPrice) {
|
2018-03-19 21:37:38 +00:00
|
|
|
var chainId = providers.Provider.chainId.ropsten
|
|
|
|
var chainName = providers.networks.ropsten
|
2018-02-27 15:41:01 +00:00
|
|
|
|
|
|
|
if (config.realTransaction) {
|
2018-03-19 21:37:38 +00:00
|
|
|
chainId = providers.Provider.chainId.homestead
|
|
|
|
chainName = providers.networks.homestead
|
2018-02-27 14:08:52 +00:00
|
|
|
}
|
2018-02-27 10:24:56 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
const wallet = new Wallet(config.privateKey)
|
|
|
|
const provider = ethers.providers.getDefaultProvider(chainName)
|
2018-02-27 15:10:18 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
wallet.provider = provider
|
2018-03-19 20:43:57 +00:00
|
|
|
if (config.token === 'ETH') {
|
|
|
|
const transaction = {
|
|
|
|
gasLimit: config.gasLimit,
|
|
|
|
gasPrice: gasPrice,
|
|
|
|
to: to,
|
|
|
|
value: amount,
|
|
|
|
chainId: chainId
|
2018-03-19 21:37:38 +00:00
|
|
|
}
|
2018-03-19 20:43:57 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
return await wallet.sendTransaction(transaction)
|
2018-03-19 20:43:57 +00:00
|
|
|
} else {
|
2018-03-19 21:37:38 +00:00
|
|
|
let hash = null
|
2018-03-19 20:43:57 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
async function getAddress() { return wallet.address }
|
|
|
|
async function sign(transaction) { return wallet.sign(transaction) }
|
2018-03-19 20:43:57 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
async function resolveName(addressOrName) { return await provider.resolveName(addressOrName) }
|
|
|
|
async function estimateGas(transaction) { return await provider.estimateGas(transaction) }
|
|
|
|
async function getGasPrice() { return await provider.getGasPrice() }
|
|
|
|
async function getTransactionCount(blockTag) { return await provider.getTransactionCount(blockTag) }
|
2018-03-19 20:43:57 +00:00
|
|
|
async function sendTransaction(transaction) {
|
2018-03-19 21:37:38 +00:00
|
|
|
hash = await provider.sendTransaction(transaction)
|
|
|
|
return hash
|
2018-03-19 20:43:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const customSigner = {
|
|
|
|
getAddress: getAddress,
|
|
|
|
provider: {
|
|
|
|
resolveName: resolveName,
|
|
|
|
estimateGas: estimateGas,
|
|
|
|
getGasPrice: getGasPrice,
|
|
|
|
getTransactionCount: getTransactionCount,
|
|
|
|
sendTransaction: sendTransaction
|
|
|
|
},
|
|
|
|
sign: sign
|
|
|
|
}
|
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
const tokenContract = config.tokenContracts[config.token]
|
|
|
|
const contractAddress = tokenContract.address
|
|
|
|
const contract = new Contract(contractAddress, tokenContract.abi, customSigner)
|
|
|
|
const bigNumberAmount = ethers.utils.bigNumberify(amount)
|
|
|
|
await contract.transfer(to, bigNumberAmount)
|
2018-03-19 20:43:57 +00:00
|
|
|
|
2018-03-19 21:37:38 +00:00
|
|
|
return hash
|
2018-03-19 20:43:57 +00:00
|
|
|
}
|
2018-02-13 12:05:39 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 17:33:27 +00:00
|
|
|
module.exports = {
|
|
|
|
needsFunding: needsFunding,
|
|
|
|
getAddress: getAddress,
|
|
|
|
getAmount: getAmount,
|
2018-01-22 15:49:41 +00:00
|
|
|
getGasPrice: prices.getGasPrice,
|
2018-02-13 12:05:39 +00:00
|
|
|
sendTransaction: sendTransaction,
|
2018-02-13 10:45:55 +00:00
|
|
|
info: info,
|
2018-01-22 16:08:23 +00:00
|
|
|
logTransaction: logTransaction,
|
|
|
|
error: error
|
2018-01-19 17:33:27 +00:00
|
|
|
}
|