Skip to content
Permalink
Browse files

modify code for tomochain faucet

  • Loading branch information...
thanhson1085 committed Aug 16, 2018
2 parents c094b9d + c1a0d24 commit d33b8dcb0bfee9804823bd12d09ff82d7ea5703c
Showing with 8,112 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +14 −0 Dockerfile
  3. +21 −0 LICENSE
  4. +35 −0 README.md
  5. +16 −0 config.json
  6. +8 −0 controllers/getTxCallBack.js
  7. +71 −0 controllers/index.js
  8. +49 −0 helpers/blockchainHelper.js
  9. +66 −0 helpers/captchaHelper.js
  10. +10 −0 helpers/configHelper.js
  11. +8 −0 helpers/debug.js
  12. +15 −0 helpers/generateResponse.js
  13. +43 −0 index.js
  14. +1,468 −0 package-lock.json
  15. +22 −0 package.json
  16. BIN public/assets/images/FAUCET_footer.png
  17. BIN public/assets/images/FAUCET_footer@2x.png
  18. BIN public/assets/images/bg_footer.png
  19. BIN public/assets/images/bg_header.png
  20. BIN public/assets/images/faucet_top.png
  21. BIN public/assets/images/faucet_top@2x.png
  22. BIN public/assets/images/intro.png
  23. BIN public/assets/images/loading.png
  24. BIN public/assets/images/loading@2x.png
  25. BIN public/assets/images/socials.png
  26. BIN public/assets/images/socials/github@2x.png
  27. BIN public/assets/images/socials/oracles@2x.png
  28. BIN public/assets/images/socials/reddit@2x.png
  29. BIN public/assets/images/socials/telegram@2x.png
  30. BIN public/assets/images/socials/twitter@2x.png
  31. BIN public/assets/images/socials@2x.png
  32. +23 −0 public/assets/javascripts/application/getTxCallBack.js
  33. +36 −0 public/assets/javascripts/application/index.js
  34. +2 −0 public/assets/javascripts/vendor/index.js
  35. +4 −0 public/assets/javascripts/vendor/jquery.min.js
  36. +1 −0 public/assets/javascripts/vendor/sweetalert2.min.js
  37. +1 −0 public/assets/stylesheets/application.css
  38. +1 −0 public/assets/stylesheets/index.scss
  39. +5 −0 public/assets/stylesheets/index/_0_variables.scss
  40. +24 −0 public/assets/stylesheets/index/_1_fonts.scss
  41. +10 −0 public/assets/stylesheets/index/_2_mixins.scss
  42. +48 −0 public/assets/stylesheets/index/_3_placeholders.scss
  43. +49 −0 public/assets/stylesheets/index/_4_base.scss
  44. +7 −0 public/assets/stylesheets/index/addition.scss
  45. +43 −0 public/assets/stylesheets/index/faucet.scss
  46. +59 −0 public/assets/stylesheets/index/footer.scss
  47. +37 −0 public/assets/stylesheets/index/header.scss
  48. +24 −0 public/assets/stylesheets/index/inputs.scss
  49. +79 −0 public/assets/stylesheets/index/loading.scss
  50. +34 −0 public/assets/stylesheets/index/nav.scss
  51. +7 −0 public/assets/stylesheets/index/recapture.scss
  52. +72 −0 public/assets/stylesheets/index/socials.scss
  53. +1 −0 public/assets/stylesheets/sweetalert2.min.css
  54. +44 −0 public/gulpfile.js
  55. +44 −0 public/index.html
  56. +5,571 −0 public/package-lock.json
  57. +34 −0 public/package.json
  58. +5 −0 run.sh
@@ -2,3 +2,4 @@
node_modules/
public/assets/javascripts/application.js
public/stylesheets/application.css
.*.sw*
@@ -0,0 +1,14 @@
FROM node:8
MAINTAINER ToMo Team

RUN npm install -g pm2

WORKDIR /build

COPY ./ /build
RUN npm install
RUN cd ./public && npm install && npm run sass && npm run coffee

EXPOSE 3000

CMD ["pm2", "start", "-x", "--no-daemon", "index.js"]
21 LICENSE
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2017 Oracles Network

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,35 @@
## Tomochain Testnet Faucet

### Building from source

1. Clone repository
2. Update config.json `./config.json` (see config.json with placeholders below)
3. Update `./public/index.html`: Find `<div class="g-recaptcha" data-sitekey="type your reCaptcha plugin secret here"></div>` line and type your reCaptcha plugin secret in `data-sitekey` attribute. For more info, [see](https://developers.google.com/recaptcha/docs/verify?hl=ru)
4. `npm install` from project's root
5. cd `./public`
6. `npm install`
7. `npm run sass`
8. `npm run coffee`
9. Go to project's root and run `npm start`. Faucet will be launched at `http://localhost:5000`

### Server config.json (`./config.json`) with placeholders
```
{
"environment": "switcher between configurations: 'live' or 'dev'",
"debug": "switch on/off server logs: true or false",
"Captcha": {
"secret": "type your reCaptcha plugin secret here"
},
"Ethereum": {
"etherToTransfer": "type amount of Ether to be sent from faucet here, for example 0.5",
"gasLimit": "type Ethereum transaction gas limit here, for example, 0x7b0c",
"live": {
"rpc": "type Ethereum RPC address here, for example http://127.0.0.1:8545",
"account": "type sender address here, for example, 0xf36045454F66C7318adCDdF3B801E3bF8CfBc6a1",
"privateKey": "type private key of sender here, for example, 54dd4125ed5418a7a68341413f4006256159f9f5ade8fed94e82785ef59523ab"
},
"dev": {
...
}
}
}
@@ -0,0 +1,16 @@
{
"environment": "live",
"debug": false,
"Captcha": {
"secret": "6LeKZEAUAAAAAHNB3uSrfvTIebV-kH4w77nykq8J"
},
"Ethereum": {
"etherToTransfer": 1,
"gasLimit": "0x7b0c",
"live": {
"rpc": "https://core.tomocoin.io",
"account": "0xfa6FC26F897027289017bEC8279a3b4b2F3c50D4",
"privateKey": "a9b4e89b1a4b8139a0ee1772b7b13e98cc6b590c89609b86d780fe84bddc1aef"
}
}
}
@@ -0,0 +1,8 @@
module.exports = function (app) {
var getTxCallBack = app.getTxCallBack;

app.post('/getTxCallBack', function(request, response) {
var txHash = request.body.txHash;
getTxCallBack(txHash, response);
});
}
@@ -0,0 +1,71 @@
module.exports = function (app) {
var EthereumTx = app.EthereumTx;
var generateErrorResponse = app.generateErrorResponse;
var config = app.config;
var configureWeb3 = app.configureWeb3;
var validateCaptcha = app.validateCaptcha;

app.post('/', function(request, response) {
var recaptureResponse = request.body.captcha;
if (!recaptureResponse) return generateErrorResponse(response, {code: 500, title: "Error", message: "Invalid captcha"});

var receiver = request.body.receiver;
validateCaptcha(recaptureResponse, function(err, out) {
validateCaptchaResponse(err, out, receiver, response);
});
});

function validateCaptchaResponse(err, out, receiver, response) {
if (!out) return generateErrorResponse(response, {code: 500, title: "Error", message: "Invalid captcha"});
if (!out.success) return generateErrorResponse(response, {code: 500, title: "Error", message: "Invalid captcha"});

configureWeb3(config, function(err, web3) {
configureWeb3Response(err, web3, receiver, response);
});
}

function configureWeb3Response(err, web3, receiver, response) {
if (err) return generateErrorResponse(response, err);

var senderPrivateKey = config.Ethereum[config.environment].privateKey;
const privateKeyHex = Buffer.from(senderPrivateKey, 'hex')
if (!web3.isAddress(receiver)) return generateErrorResponse(response, {code: 500, title: "Error", message: "invalid address"});

var gasPrice = parseInt(web3.eth.gasPrice);
var gasPriceHex = web3.toHex(gasPrice);
var amount = parseInt(web3.toWei(config.Ethereum.etherToTransfer, "ether"));
var nonce = web3.eth.getTransactionCount(config.Ethereum[config.environment].account);
var nonceHex = web3.toHex(nonce);
const rawTx = {
nonce: nonceHex,
gasPrice: gasPriceHex,
gasLimit: config.Ethereum.gasLimit,
to: receiver,
value: web3.toHex(amount),
data: '0x00',
chainId: web3.toHex(web3.version.network)
};

var tx = new EthereumTx(rawTx);
tx.sign(privateKeyHex);

var serializedTx = tx.serialize();

web3.eth.sendRawTransaction("0x" + serializedTx.toString('hex'), function(err, hash) {
sendRawTransactionResponse(err, hash, response);
});
}

function sendRawTransactionResponse(err, hash, response) {
if (err) return generateErrorResponse(response, err);

var successResponse = {
code: 200,
title: "Success",
message: "Tx is posted to blockchain",
txHash: hash
};

response.send({ success: successResponse });
}
}
@@ -0,0 +1,49 @@
module.exports = function (app) {
var getConfig = app.getConfig;
var Web3 = app.Web3;
var generateErrorResponse = app.generateErrorResponse;

app.configureWeb3 = configureWeb3;
app.getTxCallBack = getTxCallBack;

function configureWeb3(config, cb) {
var web3;
if (typeof web3 !== 'undefined') web3 = new Web3(web3.currentProvider);
else web3 = new Web3(new Web3.providers.HttpProvider(config.Ethereum[config.environment].rpc));

if (!web3.isConnected()) return cb({code: 500, title: "Error", message: "check RPC"}, web3);

cb(null, web3);
}

function getTxCallBack(txHash, response) {
getConfig(function(config) {
getConfigResponse(config, txHash, response);
});
};

function getConfigResponse(config, txHash, response) {
configureWeb3(config, function(err, web3) {
configureWeb3Response(err, web3, txHash, response);
});
}

function configureWeb3Response(err, web3, txHash, response) {
if (err) return generateErrorResponse(response, err);

web3.eth.getTransaction(txHash, function(err, txDetails) {
getTransactionResponse(err, txDetails, response);
});
}

function getTransactionResponse(err, txDetails, response) {
if (err) return generateErrorResponse(response, err);
if (!txDetails.blockNumber) return generateErrorResponse(response, {code: 500, title: "Warning", message: "Tx is not signed yet"});

response.send({
code: 200,
title: "Success",
message: '0.5 POA successfully sent'
});
}
}
@@ -0,0 +1,66 @@
module.exports = function (app) {
var config = app.config;
var generateErrorResponse = app.generateErrorResponse;
var debug = app.debug;
var querystring = app.querystring;
var https = app.https;

app.validateCaptcha = validateCaptcha;

function validateCaptcha(captchaResponse, cb) {
var secret = config.Captcha.secret;
var post_data_json = {
"secret": secret,
"response": captchaResponse
}

var post_data = querystring.stringify(post_data_json);

debug(post_data_json);
debug(post_data);

// An object of options to indicate where to post to
var post_options = {
host: "www.google.com",
port: '443',
path: "/recaptcha/api/siteverify",
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};

debug(post_options);

var post_req = https.request(post_options, function (res) {
res.setEncoding('utf8');
var output = "";
res.on('data', function (chunk) {
output += chunk;
});

res.on('end', function () {
debug("##############");
debug('Output from validateCaptcha: ');
debug(output);
debug("##############");
if (output) {
debug(JSON.parse(output));
cb(null, JSON.parse(output));
} else {
cb();
}
});
});

post_req.on('error', function (err) {
debug(err);
cb(err);
});
// post the data
post_req.write(post_data, 'binary', function(e) {
if (e) debug(e);
});
post_req.end();
};
}
@@ -0,0 +1,10 @@
module.exports = function (app) {
var fs = app.fs;

app.getConfig = getConfig;

function getConfig(cb) {
var config = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
cb(config);
}
}
@@ -0,0 +1,8 @@
module.exports = function (app) {
app.debug = debug;

function debug(text) {
if (app.config.debug)
console.log(text);
}
}
@@ -0,0 +1,15 @@
module.exports = function (app) {
app.generateErrorResponse = generateErrorResponse;

function generateErrorResponse ( response, err ) {
var out = {
error : {
code : err.code,
title : err.title,
message : err.message
}
};
console.log(err);
response.send(out);
}
}
@@ -0,0 +1,43 @@
var express = require('express');
var fs = require('fs');
var https = require('https');
var bodyParser = require('body-parser');
var querystring = require('querystring');
var Web3 = require('web3');
var EthereumTx = require('ethereumjs-tx');
var app = express();

app.fs = fs;
app.https = https;
app.querystring = querystring;
app.Web3 = Web3;
app.EthereumTx = EthereumTx;

var config;
var configPath = './config.json';
var configExists = fs.existsSync(configPath, fs.F_OK);
if (configExists) config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
app.config = config;

app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));

require('./helpers/debug')(app);
require('./helpers/generateResponse')(app);
require('./helpers/configHelper')(app);
require('./helpers/blockchainHelper')(app);
require('./helpers/captchaHelper')(app);
require('./controllers/index')(app);
require('./controllers/getTxCallBack')(app);

app.get('/', function(request, response) {
response.send('Tomochain testnet faucet');
});

app.set('port', (process.env.PORT || 3000));

app.listen(app.get('port'), function () {
console.log('Tomochain Testnet faucet is running on port', app.get('port'));
});

Oops, something went wrong.

0 comments on commit d33b8dc

Please sign in to comment.
You can’t perform that action at this time.