Merge pull request #5 from PombeirP/feature/token-funding
Add funding using tokens and local debugging with VS code
This commit is contained in:
commit
9597cde0a2
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug via NPM",
|
||||||
|
"runtimeExecutable": "npm",
|
||||||
|
"runtimeArgs": [
|
||||||
|
"run-script",
|
||||||
|
"debug"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"WEBHOOK_SECRET": ""
|
||||||
|
},
|
||||||
|
"port": 9229
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Program",
|
||||||
|
"program": "${workspaceFolder}/index.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
89
bot/index.js
89
bot/index.js
|
@ -2,6 +2,7 @@ const winston = require('winston');
|
||||||
|
|
||||||
const ethers = require('ethers');
|
const ethers = require('ethers');
|
||||||
const Wallet = ethers.Wallet;
|
const Wallet = ethers.Wallet;
|
||||||
|
const Contract = ethers.Contract;
|
||||||
const providers = ethers.providers;
|
const providers = ethers.providers;
|
||||||
const utils = ethers.utils;
|
const utils = ethers.utils;
|
||||||
|
|
||||||
|
@ -9,6 +10,8 @@ const prices = require('./prices');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
const github = require('./github');
|
const github = require('./github');
|
||||||
|
|
||||||
|
const contractAddressString = 'Contract address:';
|
||||||
|
|
||||||
|
|
||||||
const logger = winston.createLogger({
|
const logger = winston.createLogger({
|
||||||
level: 'info',
|
level: 'info',
|
||||||
|
@ -34,7 +37,7 @@ const needsFunding = function (req) {
|
||||||
|
|
||||||
const hasAddress = function (req) {
|
const hasAddress = function (req) {
|
||||||
const commentBody = req.body.comment.body;
|
const commentBody = req.body.comment.body;
|
||||||
if (commentBody.search('Contract address:') === -1) {
|
if (commentBody.search(contractAddressString) === -1) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -43,34 +46,15 @@ const hasAddress = function (req) {
|
||||||
|
|
||||||
const getAddress = function (req) {
|
const getAddress = function (req) {
|
||||||
const commentBody = req.body.comment.body;
|
const commentBody = req.body.comment.body;
|
||||||
return commentBody.substring(commentBody.search("Contract address:") + 19, commentBody.search("Contract address:") + 61)
|
const index = commentBody.search(contractAddressString) + 19
|
||||||
}
|
return commentBody.substring(index, index + 42)
|
||||||
|
|
||||||
const getLabelMock = function (req) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
github.getLabels(req)
|
|
||||||
.then(labels => {
|
|
||||||
const bountyLabels = labels.filter(name => config.bountyLabels.hasOwnProperty(name));
|
|
||||||
if (bountyLabels.length === 1) {
|
|
||||||
resolve(bountyLabels[0]);
|
|
||||||
} else {
|
|
||||||
reject('Error getting bounty labels: ' + bountyLabels);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
reject(err)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getLabel = function (req) {
|
const getLabel = function (req) {
|
||||||
if (config.debug) {
|
|
||||||
return getLabelMock(req);
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
github.getLabels(req)
|
github.getLabels(req)
|
||||||
.then(labels => {
|
.then(labels => {
|
||||||
const bountyLabels = labels.filter(name => config.bountyLabels.hasOwnProperty(name));
|
const bountyLabels = labels.filter(label => config.bountyLabels.hasOwnProperty(label.name));
|
||||||
if (bountyLabels.length === 1) {
|
if (bountyLabels.length === 1) {
|
||||||
resolve(bountyLabels[0]);
|
resolve(bountyLabels[0]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -86,7 +70,6 @@ const getAmountMock = function (req) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
resolve(10);
|
resolve(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAmount = function (req) {
|
const getAmount = function (req) {
|
||||||
|
@ -98,7 +81,7 @@ const getAmount = function (req) {
|
||||||
.then(function (values) {
|
.then(function (values) {
|
||||||
let label = values[0];
|
let label = values[0];
|
||||||
let tokenPrice = values[1];
|
let tokenPrice = values[1];
|
||||||
let amountToPayDollar = config.priceHour * config.bountyLabels[label];
|
let amountToPayDollar = config.priceHour * config.bountyLabels[label.name];
|
||||||
resolve(amountToPayDollar / tokenPrice);
|
resolve(amountToPayDollar / tokenPrice);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
@ -128,10 +111,7 @@ const error = function (errorMessage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const sendTransaction = async function (to, amount, gasPrice) {
|
||||||
|
|
||||||
const sendTransaction = function (to, amount, gasPrice) {
|
|
||||||
|
|
||||||
var chainId = providers.Provider.chainId.ropsten;
|
var chainId = providers.Provider.chainId.ropsten;
|
||||||
var chainName = providers.networks.ropsten;
|
var chainName = providers.networks.ropsten;
|
||||||
|
|
||||||
|
@ -144,9 +124,8 @@ const sendTransaction = function (to, amount, gasPrice) {
|
||||||
const provider = ethers.providers.getDefaultProvider(chainName);
|
const provider = ethers.providers.getDefaultProvider(chainName);
|
||||||
|
|
||||||
wallet.provider = provider;
|
wallet.provider = provider;
|
||||||
|
if (config.token === 'ETH') {
|
||||||
|
const transaction = {
|
||||||
var transaction = {
|
|
||||||
gasLimit: config.gasLimit,
|
gasLimit: config.gasLimit,
|
||||||
gasPrice: gasPrice,
|
gasPrice: gasPrice,
|
||||||
to: to,
|
to: to,
|
||||||
|
@ -154,17 +133,43 @@ const sendTransaction = function (to, amount, gasPrice) {
|
||||||
chainId: chainId
|
chainId: chainId
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return await wallet.sendTransaction(transaction);
|
||||||
wallet.sendTransaction(transaction)
|
} else {
|
||||||
.then(function(hash) {
|
let hash = null;
|
||||||
logTransaction(hash);
|
|
||||||
resolve(hash);
|
|
||||||
}).catch(function(err) {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
async function getAddress() { return wallet.address; }
|
||||||
|
async function sign(transaction) { return wallet.sign(transaction); }
|
||||||
|
|
||||||
|
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); }
|
||||||
|
async function sendTransaction(transaction) {
|
||||||
|
hash = await provider.sendTransaction(transaction);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customSigner = {
|
||||||
|
getAddress: getAddress,
|
||||||
|
provider: {
|
||||||
|
resolveName: resolveName,
|
||||||
|
estimateGas: estimateGas,
|
||||||
|
getGasPrice: getGasPrice,
|
||||||
|
getTransactionCount: getTransactionCount,
|
||||||
|
sendTransaction: sendTransaction
|
||||||
|
},
|
||||||
|
sign: sign
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
needsFunding: needsFunding,
|
needsFunding: needsFunding,
|
||||||
|
|
|
@ -7,6 +7,42 @@ const BOUNTY_LABELS = {
|
||||||
'bounty-xl': 10000
|
'bounty-xl': 10000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ERC20_ABI = [
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_to",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_amount",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "transfer",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "success",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const TOKEN_CONTRACTS = {
|
||||||
|
'STT': {
|
||||||
|
address: '0xc55cF4B03948D7EBc8b9E8BAD92643703811d162',
|
||||||
|
abi: ERC20_ABI
|
||||||
|
},
|
||||||
|
'SNT': {
|
||||||
|
address: '0x744d70fdbe2ba4cf95131626614a1763df805b9e',
|
||||||
|
abi: ERC20_ABI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// Debug mode for testing the bot
|
// Debug mode for testing the bot
|
||||||
debug: true,
|
debug: true,
|
||||||
|
@ -38,6 +74,9 @@ module.exports = {
|
||||||
// Bounty Labels for the issues and the correspondent hours (e.g. {'bounty-xs': 3})
|
// Bounty Labels for the issues and the correspondent hours (e.g. {'bounty-xs': 3})
|
||||||
bountyLabels: BOUNTY_LABELS,
|
bountyLabels: BOUNTY_LABELS,
|
||||||
|
|
||||||
|
// Contract info for the different supported tokens
|
||||||
|
tokenContracts: TOKEN_CONTRACTS,
|
||||||
|
|
||||||
// username for the bot which has to comment for starting the process (e.g. status-bounty-)
|
// username for the bot which has to comment for starting the process (e.g. status-bounty-)
|
||||||
githubUsername: 'status-open-bounty',
|
githubUsername: 'status-open-bounty',
|
||||||
|
|
||||||
|
|
8
index.js
8
index.js
|
@ -96,17 +96,17 @@ const processRequest = function (req) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Promise.all([amountPromise, gasPricePromise])
|
Promise.all([amountPromise, gasPricePromise])
|
||||||
.then(function (results) {
|
.then(function (results) {
|
||||||
let amount = results[0];
|
const amount = results[0];
|
||||||
let gasPrice = results[1];
|
const gasPrice = results[1];
|
||||||
|
|
||||||
bot.sendTransaction(to, amount, gasPrice)
|
bot.sendTransaction(to, amount, gasPrice)
|
||||||
.then(function () {
|
.then(function (hash) {
|
||||||
|
bot.logTransaction(hash);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node index.js",
|
"start": "node index.js",
|
||||||
|
"debug": "node --inspect-brk index.js",
|
||||||
"test": "./node_modules/mocha/bin/mocha"
|
"test": "./node_modules/mocha/bin/mocha"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
|
|
Loading…
Reference in New Issue