Advertisement
Guest User

Untitled

a guest
Apr 9th, 2017
655
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'use strict';
  2.  
  3. module.exports = function(){
  4.     var config = require('./config.json');
  5.     var dConf = require('./dConf.json');
  6.     var library = require ('./library.js');
  7.     var nodemailer = require('nodemailer');
  8.     var jsonfile = require('jsonfile');
  9.     var request = require('request');
  10.     var fs = require('fs');
  11.     var logStr = "";
  12.     var JsonDB = require('node-json-db');
  13.     var db = new JsonDB("db", true, false);
  14.     var lastInit = config.lastInit = dConf.lastInit || Date.now();
  15.     var meta = {
  16.         initTime: Date.now(),
  17.         withdrawBalance: 0,
  18.         balance: {},
  19.         currencies: [],
  20.         orders: {},
  21.         recordTradeHistory : [],
  22.         withdraw: {
  23.             addresses: [],
  24.         }
  25.     };
  26.  
  27.     var metaClone = JSON.parse(JSON.stringify(meta));
  28.     var configClone = JSON.parse(JSON.stringify(config));
  29.  
  30.     if(checkPercentage()){
  31.     run();
  32.     } else{
  33.         throw new Error('Percentage is not valid!');
  34.     }
  35.  
  36.     function run() {
  37.         meta = metaClone;
  38.         metaClone = JSON.parse(JSON.stringify(meta));
  39.         config = configClone;
  40.         configClone = JSON.parse(JSON.stringify(config));
  41.         config.lastInit = Date.now();
  42.         dConf.lastInit = config.lastInit;
  43.         jsonfile.writeFileSync("./dConf.json", dConf);
  44.  
  45.         getBalance().then((balances) => {
  46.             let exchangeCurrs = Object.keys(balances);
  47.         console.log('balances:', balances);
  48.            
  49.         meta.initBalance = balances;
  50.  
  51.             if(exchangeCurrs.length === 1 && exchangeCurrs[0] == 'BTC') {
  52.                 console.log(`Step 1. No Currency To Exchange. Let\'s Withdraw ${meta.balance.BTC} BTC`);
  53.  
  54.                waitingForCompletion().then(()=>{
  55.                    withdrawForAll().then(onSuccess, onError);
  56.                });
  57.            } else {
  58.                meta.currencies = exchangeCurrs.filter((currency) => {
  59.                    if(currency != 'BTC'){
  60.                        return currency;
  61.                    }
  62.                });
  63.                
  64.                placeOrders().then(()=>{
  65.                    console.log('Orders was placed!');
  66.                    waitingForCompletion().then(()=>{
  67.                        console.log('Orders resolved!');
  68.                        withdrawForAll().then(()=>{
  69.                            console.log('Withdrawed!');
  70.                            onSuccess()
  71.                        }, onError);
  72.                    }, onError);
  73.                }, onError);
  74.            }
  75.  
  76.            function onSuccess(){
  77.                recordHistory().then(()=>{
  78.                    writeLog();
  79.  
  80.                    getUsdRate().then(function(rate){
  81.                        sendEmail(rate);
  82.                    }, sendEmail)
  83.                  
  84.                }, onError);
  85.            }
  86.        });
  87.    }
  88.  
  89.  
  90.    /**
  91.     * Get balances
  92.     * @return {object} promise
  93.     */
  94.    function getBalance() {
  95.        return new Promise((resolve, reject)=> {
  96.            let balanceParams = {
  97.                query: `command=returnAvailableAccountBalances&nonce=${Date.now()}`
  98.            };
  99.  
  100.            library.postReq(balanceParams, (balances) => {
  101.                console.log('balances.exchange', balances, balances.exchange['BTC']);
  102.         if(balances.exchange) {
  103.                    meta.balance = balances.exchange;
  104.                    meta.balance['BTC'] = parseFloat(meta.balance['BTC']) > 0.05 ? parseFloat(meta.balance['BTC']) - 0.001 : 0
  105.            
  106.                    console.log(`Step 1. (6) Current Balance: ${JSON.stringify(meta.balance)}`);
  107.  
  108.                    resolve(meta.balance);
  109.                } else {
  110.                    reject('Step 1. (6) Nothing to exchange');
  111.                }
  112.            });
  113.        })
  114.    }
  115.  
  116.  
  117.    /**
  118.     * Place orders
  119.     * @return {object} Promise
  120.     */
  121.    function placeOrders() {
  122.        return new Promise((resolve, reject)=> {
  123.            iterator(meta.currencies[0], meta.currencies, newOrder, resolve);
  124.            
  125.            function newOrder(currency){
  126.                var currencyPair = `BTC_${currency}`;
  127.                var orderBookParams = {
  128.                    query: `https://poloniex.com/public?command=returnOrderBook&currencyPair=${currencyPair}&depth=1`
  129.                }
  130.  
  131.                return new Promise(function(resolve, reject){
  132.                    library.getReqt(orderBookParams, (res) => {
  133.                        if(res.error){ reject(res.error) }
  134.                        
  135.                        var order = {
  136.                            currencyPair: currencyPair,
  137.                            rate: res.bids[0][0],
  138.                            bid: res.bids
  139.                        };
  140.  
  141.                        var sellParams = {
  142.                            currencyPair,
  143.                            rate: order.bid[0][0],
  144.                            amount: meta.balance[currency]
  145.                        }
  146.  
  147.                        sellParams.query = `command=sell&currencyPair=${sellParams.currencyPair}&rate=${sellParams.rate}&amount=${sellParams.amount}&nonce=${Date.now()}`;
  148.  
  149.                        library.postReq(sellParams, (res) => {
  150.                            if (res.orderNumber) {
  151.                           console.log(`Step 2. Order № ${res.orderNumber} Placed For ${sellParams.currencyPair}. Rate: ${sellParams.rate}; Amount: ${sellParams.amount}`);
  152.                        
  153.                                meta.orders[currency.toUpperCase()] = order;
  154.                         } else {
  155.                            console.log(res);
  156.                        }
  157.  
  158.                            resolve();
  159.                        });
  160.                    });
  161.                });
  162.            }
  163.        })
  164.    }
  165.  
  166.  
  167.    /**
  168.     * Waiting for the completion of all orders
  169.     * @return {object} promise
  170.     */
  171.    function waitingForCompletion(){
  172.        return new Promise((resolve, reject)=> {
  173.            var intervalID = setInterval(function(){
  174.                library.postReq({query: `command=returnOpenOrders&currencyPair=all&nonce=${Date.now()}`}, (res) => {
  175.                    if(!res.error) {
  176.                        var orders = [];
  177.  
  178.                        for(let key in res){
  179.                            orders = orders.concat(res[key]);
  180.                        }
  181.  
  182.                        console.log('Orders opened:', orders.length);
  183.                        console.log(orders);
  184.  
  185.                        if(!orders.length){
  186.                            clearInterval(intervalID);
  187.                            resolve();
  188.                        }
  189.                    } else{
  190.                        if(res.error){
  191.                            console.log(res.error);
  192.                        } else{
  193.                            console.log('Not closed yet..', res.length);
  194.                        }
  195.                    }
  196.                });
  197.            }, 5000);
  198.        });
  199.    }
  200.  
  201.  
  202.    /**
  203.     * Get trade history from poloniex
  204.     * @return {object} promise
  205.     */
  206.    function recordHistory() {
  207.        return new Promise((resolve, reject)=> {
  208.            var params = {
  209.                query: `command=returnTradeHistory&currencyPair=all&start=${meta.initTime / 1000}&end=${Date.now()/1000}&nonce=${Date.now()}`
  210.            }
  211.      
  212.            library.postReq(params,(res) => {
  213.  
  214.                if(!res.error){
  215.                    for(let key in res){
  216.                        for(let order of res[key]){
  217.                            console.log(`Order ${key}, Rate: ${order.rate}, Amount: ${order.amount}, Fee: ${order.fee}, Total: ${order.total} BTC`);
  218.                        }
  219.                    }
  220.                }
  221.  
  222.                meta.recordTradeHistory.push(res);
  223.                resolve();
  224.            });
  225.        });
  226.    }
  227.  
  228.  
  229.    /**
  230.     * Withdraw all BTC to users accounts
  231.     * @return {[type]} [description]
  232.     */
  233.    function withdrawForAll(){
  234.        return new Promise(function(resolve, reject){
  235.            var addrs = Object.keys(config.withdrawRatio);
  236.            
  237.            getUsdRate().then(function(btcRate){
  238.                var hours = (Date.now() - lastInit) / (1000 * 60 * 60);
  239.                var btcRate = btcRate || 600;
  240.                var powerCosts = config.kWtHourUsdRate * config.kWHour * config.cardsCount * hours;
  241.                var powerCostsBTC = parseFloat((powerCosts / btcRate).toFixed(8));
  242.  
  243.                getBalance().then(function(){
  244.                    var powerAccount;
  245.  
  246.                    addrs.forEach(function(addr){
  247.                        if(config.withdrawRatio[addr].isPower){
  248.                            powerAccount = config.withdrawRatio[addr];
  249.                        }
  250.                    });
  251.  
  252.                    if(powerAccount){
  253.                        addrs.forEach(function(addr){
  254.                            if(config.withdrawRatio[addr].isJesus){
  255.                                powerAccount.percents = 1 / meta.balance['BTC'] * powerCostsBTC * config.withdrawRatio[addr].percents;
  256.                                config.withdrawRatio[addr].percents -= powerAccount.percents;
  257.                            }
  258.                        });
  259.                    }
  260.  
  261.                    iterator(addrs[0], addrs, withdraw, resolve);
  262.  
  263.                    function withdraw(addr){
  264.                        return new Promise(function(resolve, reject){  
  265.                            var amount = parseFloat(meta.balance['BTC']) * parseFloat(config.withdrawRatio[addr].percents);
  266.                            var params = {query: `command=withdraw&currency=BTC&amount=${amount}&address=${addr}&nonce=${Date.now()}`}
  267.                            var withdrawStr = `Withdraw ${amount} BTC to ${addr}. (${parseFloat(config.withdrawRatio[addr].percents) * 100}% from ${meta.balance['BTC']} BTC)`
  268.  
  269.                            library.postReq(params,(res) => {
  270.                                meta.withdrawBalance += amount;
  271.                                meta.withdraw.addresses.push({
  272.                                    address: addr,
  273.                                    amount: amount,
  274.                                    percents: config.withdrawRatio[addr].percents,
  275.                                    label: config.withdrawRatio[addr].label,
  276.                                    success: res.response
  277.                                });
  278.  
  279.                                resolve();
  280.                            });
  281.                        });
  282.                    }
  283.                });
  284.            });
  285.        });
  286.    }
  287.  
  288.  
  289.    /**
  290.     * Write meta object to log file
  291.     * @return {object} promise
  292.     */
  293.    function writeLog() {
  294.        return new Promise((resolve, reject)=> {
  295.            console.log('Step 5. (8) Recording Log File');
  296.            fs.access(config.logFile, fs.constants.R_OK | fs.constants.W_OK, (err) => {
  297.                if (err) {
  298.                    fs.writeFile(config.logFile, `${JSON.stringify(meta)}\n`, 'utf-8', (err) => {
  299.                        if (!err) {
  300.                            resolve();
  301.                        } else {
  302.                            reject(err);
  303.                        }
  304.                    });
  305.                } else {
  306.                    fs.appendFile(config.logFile, `${JSON.stringify(meta)}\n`, 'utf-8', (err) => {
  307.                        if (!err) {
  308.                            resolve();
  309.                        } else {
  310.                            reject(err);
  311.                        }
  312.                    });
  313.                }
  314.            });
  315.        })
  316.    }
  317.  
  318.  
  319.    /**
  320.     * Do "Step to step" requests
  321.     * @param  {any} fnAsync param
  322.     * @param  {array} Array of params
  323.     * @param  {function} Async function what return a promise
  324.     * @param  {function} Global promise resolver
  325.     * @return {undefined}
  326.     */
  327.    function iterator(item, arr, fnAsync, resolve){
  328.        setTimeout(function(){
  329.            arr.shift();
  330.  
  331.            fnAsync(item).then(function(){
  332.                if(arr[0]){
  333.                    iterator(arr[0], arr, fnAsync, resolve)
  334.                } else{
  335.                    resolve();
  336.                }
  337.            }, onError);
  338.        }, 500)
  339.    }
  340.  
  341.  
  342.    /**
  343.     * Send meta object via E-mail
  344.     * @return {undefined}
  345.     */
  346.    function sendEmail(btcRate, err){
  347.        var transporter = nodemailer.createTransport('smtps://axbt.bots:ungdrXW9A@smtp.gmail.com');
  348.         var data = Object.assign({}, meta);
  349.         var totalExpected = 0;
  350.         var hours = (Date.now() - lastInit) / (1000 * 60 * 60);
  351.         var btcRate = btcRate || 600;
  352.         var powerCosts = config.kWtHourUsdRate * config.kWHour * config.cardsCount * hours;
  353.         var powerCostsBTC = parseFloat((powerCosts / btcRate).toFixed(8));
  354.         var remainingTime = getRemainingTime(lastInit, Date.now());
  355.         var withdrawBalance = parseFloat(meta.withdrawBalance.toFixed(8));
  356.         var withdrawBalanceUsd = parseFloat((meta.withdrawBalance * btcRate).toFixed(2));        
  357.         var powerCostsUSD = parseFloat(powerCosts.toFixed(2));
  358.         var deviceProfit = parseFloat((withdrawBalanceUsd / config.cardsCount).toFixed(2));
  359.  
  360.     db.push("/sessions[]", {data, hours, btcRate, powerCosts, powerCostsBTC, remainingTime, withdrawBalance, withdrawBalanceUsd, powerCostsUSD, deviceProfit, config}, true);
  361.  
  362.         var body = `
  363.             ${err ? "ERROR: " + err : ""}
  364.             <div style="font-size: 14px; max-width: 600px;">
  365.                 All mined coins for <b>${remainingTime.days}d. ${remainingTime.hours}h.</b> was converted to <b>${withdrawBalance} BTC (${withdrawBalanceUsd} USD)</b> and withdrawed to several accounts by static shares.
  366.                 Static number of devices is <b>${config.cardsCount}</b>, average consumption of power is <b>${config.kWHour} kW/h</b> for one device. Consumption (the power) of all devices for the last period is <b>$${powerCostsUSD} (${powerCostsBTC} BTC)</b>.
  367.                 Current profitability of one device for ${remainingTime.days}d. ${remainingTime.hours}h. is <b>${deviceProfit}$</b> without power costs and <b>${((withdrawBalanceUsd - powerCostsUSD) / config.cardsCount).toFixed(2)}$</b> with power costs.
  368.  
  369.                 Current BTC/USD rate from Poloniex is <b>$${btcRate}</b>.
  370.             </div>
  371.         `;
  372.        
  373.        
  374.         body += `
  375.             <div style="margin: 20px 0;">${makeOrdersTable()}</div>
  376.         `;
  377.  
  378.         makeWithdrawsTable();
  379.        
  380.  
  381.         var mailOptions = {
  382.             from: `"POLONIEX trader (JESUS)" <AXBT.bots@gmail.com>`,
  383.             to: 'legko777@fastmail.fm, legkodymov.lev@gmail.com, toxa@a-xbt.com, 89094568777@mail.ru',
  384.             subject: `Paid $${withdrawBalanceUsd} / ${withdrawBalance} BTC`,
  385.             html:  body
  386.         };
  387.  
  388.         transporter.sendMail(mailOptions, function(error, info){
  389.             console.log('Message sent: ' + (error || info.response));
  390.         });
  391.  
  392.  
  393.  
  394.         function makeOrdersTable(){
  395.             var trigger = 1;
  396.             var table = "";
  397.  
  398.            
  399.             table += `
  400.                 <h2>Exchange coins to BTC</h2>
  401.                  <table>
  402.                     <tr>
  403.                         <td style="padding: 10px; text-align: center"><b>Coin</b></td>
  404.                         <td style="padding: 10px; text-align: center"><b>Amount</b></td>
  405.                         <td style="padding: 10px; text-align: center"><b>Rate (BTC)</b></td>
  406.                         <td style="padding: 10px; text-align: center"><b>Exchanged (BTC)</b></td>
  407.                         <td style="padding: 10px; text-align: center"><b>Exchanged (USD)</b></td>
  408.                     </tr>
  409.             `;
  410.  
  411.             for(let coinName in meta.initBalance){
  412.                 let total = parseFloat(((meta.orders[coinName] ? meta.orders[coinName].rate : 1) * meta.initBalance[coinName]).toFixed(8));
  413.  
  414.                 totalExpected += total;
  415.  
  416.                 table += `
  417.                     <tr style="${trigger % 2 ? "background-color: #f0f0f0" : ""}">
  418.                         <td style="padding: 10px; text-align: center">${coinName}</td>
  419.                         <td style="padding: 10px; text-align: center">${meta.initBalance[coinName]}</td>
  420.                         <td style="padding: 10px; text-align: center">${meta.orders[coinName] ? meta.orders[coinName].rate : 1}</td>
  421.                         <td style="padding: 10px; text-align: center">${total}</td>
  422.                         <td style="padding: 10px; text-align: center">${parseFloat(total * btcRate).toFixed(2)}</td>
  423.                     </tr>
  424.                 `
  425.  
  426.                 trigger++;
  427.             }
  428.  
  429.             var feesBTC = parseFloat((totalExpected - meta.withdrawBalance).toFixed(8));
  430.             var feesUSD = parseFloat(((totalExpected - meta.withdrawBalance) * btcRate).toFixed(2));
  431.  
  432.             table += `
  433.                     <tr style="${trigger % 2 ? "background-color: #f0f0f0" : ""}">
  434.                         <td style="padding: 10px; text-align: center"><b>Formula:</b></td>
  435.                         <td style="padding: 10px; text-align: center">A</td>
  436.                         <td style="padding: 10px; text-align: center">R</td>
  437.                         <td style="padding: 10px; text-align: center">A * R</td>
  438.                         <td style="padding: 10px; text-align: center">toUSD(A * R) </td>
  439.                     </tr>
  440.                     <tr style="${trigger % 2 ? "background-color: #f0f0f0" : ""}">
  441.                         <td style="padding: 10px; text-align: center"><b>Fees:</b></td>
  442.                         <td style="padding: 10px; text-align: center">-</td>
  443.                         <td style="padding: 10px; text-align: center">-</td>
  444.                         <td style="padding: 10px; text-align: center">${feesBTC}</td>
  445.                         <td style="padding: 10px; text-align: center">${feesUSD}</td>
  446.                     </tr>
  447.                     <tr style="${trigger % 2 ? "background-color: #f0f0f0" : ""}">
  448.                         <td style="padding: 10px; text-align: center"><b>To withdraw:</b></td>
  449.                         <td style="padding: 10px; text-align: center">-</td>
  450.                         <td style="padding: 10px; text-align: center">-</td>
  451.                         <td style="padding: 10px; text-align: center"><b>${withdrawBalance}</b></td>
  452.                         <td style="padding: 10px; text-align: center"><b>${withdrawBalanceUsd}</b></td>
  453.                     </tr>
  454.                 </table>
  455.             `;
  456.  
  457.             return table;
  458.         }
  459.  
  460.         function makeWithdrawsTable(){
  461.             var trigger = 1;
  462.            
  463.             body += `
  464.                 <h2>Withdraw the shares</h2>
  465.                 <table>
  466.                     <tr>
  467.                         <td style="padding: 10px; text-align: center"><b>Address</b></td>
  468.                         <td style="padding: 10px; text-align: center"><b>Share size</b></td>
  469.                         <td style="padding: 10px; text-align: center"><b>Amount BTC</b></td>
  470.                         <td style="padding: 10px; text-align: center"><b>Amount USD</b></td>
  471.                         <td style="padding: 10px; text-align: center"><b>Comment</b></td>
  472.                     </tr>
  473.             `;
  474.  
  475.             for(let withdraw of meta.withdraw.addresses){
  476.                 body += `
  477.                     <tr style="${trigger % 2 ? "background-color: #f0f0f0" : ""}">
  478.                         <td style="padding: 10px; text-align: center">${withdraw.address}</td>
  479.                         <td style="padding: 10px; text-align: center">${(withdraw.percents * 100).toFixed(2)}%</td>
  480.                         <td style="padding: 10px; text-align: center">${parseFloat(withdraw.amount.toFixed(8))}</td>
  481.                         <td style="padding: 10px; text-align: center">${(withdraw.amount * btcRate).toFixed(2)}</td>
  482.                         <td style="padding: 10px; text-align: center">${withdraw.label}</td>
  483.                     </tr>
  484.                 `
  485.  
  486.                 trigger++;
  487.             }
  488.  
  489.             body += `</table>`;
  490.         }
  491.     }
  492.  
  493.  
  494.     /**
  495.      * Percentage neet do be < 100
  496.      * @return {bool}
  497.      */
  498.     function checkPercentage(){
  499.         let summ = 0;
  500.  
  501.         for (let address in config.withdrawRatio) {
  502.             summ += config.withdrawRatio[address].percents;
  503.         }
  504.  
  505.         console.log(summ);
  506.         return summ > 1 ? false : true;
  507.     }
  508.  
  509.     /**
  510.      * Get time iterval
  511.      * @param  {number} start timestamp in milliseconds
  512.      * @param  {number} end timestamp in milliseconds
  513.      * @return {object} {
  514.      *    days: {number} - count of full days,
  515.      *    hours: {number} - count of full hours after last day,
  516.      *    minutes: {number} - count of full minutes after last hour,
  517.      *    time: {string} - tine in hh:mm
  518.      * }
  519.      */
  520.     function getRemainingTime(start, end){
  521.         if(!start){
  522.             return {
  523.                 hours: 0,
  524.                 minutes: 0,
  525.                 time: 0,
  526.                 days: 9999
  527.             };
  528.         }
  529.  
  530.         if(end - start < 1000){
  531.             return {
  532.                 hours: 0,
  533.                 minutes: 0,
  534.                 time: 0,
  535.                 days: 0
  536.             };
  537.         }
  538.        
  539.         var periodInSec = (end - start) / 1000;
  540.         var hoursFloat = periodInSec / 3600;
  541.         var hours = parseInt(hoursFloat);
  542.         var minutes = parseInt(60 * (hoursFloat - hours));
  543.         var time = `${hours}:${minutes}`;
  544.         var days = parseInt(hours / 24);
  545.         var seconds = parseInt((60 * (hoursFloat - hours) - minutes) * 60);
  546.  
  547.  
  548.         return {
  549.             hours: hours - days * 24,
  550.             minutes: minutes,
  551.             time: time,
  552.             days: days,
  553.             seconds:  seconds
  554.         };
  555.     }
  556.  
  557.     /**
  558.      * Error logger
  559.      * @param  {object|string}
  560.      * @return {undefined}
  561.      */
  562.     function onError(err) {
  563.          getUsdRate().then(function(rate){
  564.             sendEmail(rate, err);
  565.         }, sendEmail)
  566.  
  567.         console.log(err);
  568.     }
  569.  
  570.  
  571.     function getUsdRate(){
  572.         var url = "https://poloniex.com/public?command=returnTicker";
  573.  
  574.         return new Promise(function(resolve, reject){
  575.            request.get(url, function(err, res, body){
  576.                 try{
  577.                     if(!err){
  578.                         var coinRate = parseFloat(JSON.parse(body)["USDT_BTC"].last);
  579.                        
  580.                         if(coinRate && typeof coinRate === "number" && coinRate > 0){
  581.                             resolve(coinRate.toFixed(2));
  582.                         } else{
  583.                             reject();
  584.                         }
  585.                     }  else{
  586.                         reject();
  587.                     }
  588.                 } catch(e){
  589.                     console.log("poloniex", e, err);
  590.                     return reject();
  591.                 }
  592.             });
  593.         });
  594.     }
  595. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement