diff --git a/lib/plugins.js b/lib/plugins.js index 6c673b98..072454eb 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -40,6 +40,11 @@ var lastRates = {} var tradesQueues = {} +var coins = { + BTC: {unitScale: 8}, + ETH: {unitScale: 18} +} + // that's basically a constructor exports.init = function init (databaseHandle) { if (!databaseHandle) { @@ -53,7 +58,7 @@ function loadPlugin (name, config) { // plugins definitions var moduleMethods = { ticker: ['ticker'], - trader: ['balance', 'purchase', 'sell'], + trader: ['purchase', 'sell'], wallet: ['balance', 'sendBitcoins', 'newAddress'], idVerifier: ['verifyUser', 'verifyTransaction'], info: ['checkAddress'] @@ -151,7 +156,7 @@ exports.configure = function configure (config) { cachedConfig = config deviceCurrency = config.exchanges.settings.currency - cryptoCodes = config.exchanges.settings.coins || ['BTC'] + cryptoCodes = config.exchanges.settings.coins || ['BTC', 'ETH'] cryptoCodes.forEach(function (cryptoCode) { // TICKER [required] configure (or load) @@ -248,21 +253,29 @@ function _sendCoins (toAddress, cryptoAtoms, cryptoCode, cb) { if (cryptoCode === 'BTC') { walletPlugin.sendBitcoins(toAddress, cryptoAtoms, transactionFee, cb) } else { - walletPlugin.sendCoins(toAddress, cryptoAtoms, cryptoCode, transactionFee, cb) + walletPlugin.sendBitcoins(toAddress, cryptoAtoms, cryptoCode, transactionFee, cb) } } function executeTx (session, tx, authority, cb) { db.addOutgoingTx(session, tx, function (err, toSend) { - if (err) return cb(err) - var cryptoAtomsToSend = toSend.cryptoAtoms + if (err) { + logger.error(err) + return cb(err) + } + var cryptoAtomsToSend = toSend.satoshis if (cryptoAtomsToSend === 0) { + logger.debug('No cryptoAtoms to send') return cb(null, {statusCode: 204, txId: tx.txId, txHash: null}) } - _sendCoins(tx.toAddress, cryptoAtomsToSend, function (_err, txHash) { + var cryptoCode = tx.cryptoCode + _sendCoins(tx.toAddress, cryptoAtomsToSend, cryptoCode, function (_err, txHash) { var fee = null // Need to fill this out in plugins - if (_err) toSend = {cryptoAtoms: new BigNumber(0), fiat: 0} + if (_err) { + logger.error(_err) + toSend = {cryptoAtoms: new BigNumber(0), fiat: 0} + } db.sentCoins(session, tx, authority, toSend, fee, _err, txHash) if (_err) return cb(_err) @@ -291,6 +304,7 @@ function reapTx (row) { satoshis: row.satoshis, toAddress: row.to_address, currencyCode: row.currency_code, + cryptoCode: row.crypto_code, incoming: row.incoming } if (!row.incoming) reapOutgoingTx(session, tx) @@ -314,6 +328,8 @@ function reapTxs () { // TODO: Run these in parallel and return success exports.trade = function trade (session, rawTrade, cb) { + logger.debug('DEBUG2') + // TODO: move this to DB, too // add bill to trader queue (if trader is enabled) var cryptoCode = rawTrade.cryptoCode || 'BTC' @@ -328,14 +344,18 @@ exports.trade = function trade (session, rawTrade, cb) { }) } + logger.debug('DEBUG3') + if (!rawTrade.toAddress) { var newRawTrade = _.cloneDeep(rawTrade) newRawTrade.toAddress = 'remit' return db.recordBill(session, newRawTrade, cb) } + logger.debug('DEBUG1') + async.parallel([ - async.apply(db.addOutgoingPending, session, rawTrade.currency, rawTrade.toAddress), + async.apply(db.addOutgoingPending, session, rawTrade.currency, rawTrade.cryptoCode, rawTrade.toAddress), async.apply(db.recordBill, session, rawTrade) ], cb) } @@ -376,17 +396,14 @@ exports.fiatBalance = function fiatBalance (cryptoCode) { if (!rawRate || !lastBalance) return null // The rate is actually our commission times real rate. - var rate = commission * rawRate + var rate = rawRate.times(commission) // `lowBalanceMargin` is our safety net. It's a number > 1, and we divide // all our balances by it to provide a safety margin. var lowBalanceMargin = cachedConfig.exchanges.settings.lowBalanceMargin - // `balance.transferBalance` is the balance of our transfer account (the one - // we use to send Bitcoins to clients) in satoshis. - var transferBalance = lastBalance.transferBalance - - var fiatTransferBalance = (transferBalance * rate) / lowBalanceMargin + var unitScale = new BigNumber(10).pow(coins[cryptoCode].unitScale) + var fiatTransferBalance = lastBalance.div(unitScale).times(rate).div(lowBalanceMargin) return fiatTransferBalance } @@ -441,9 +458,9 @@ function pollBalance (cryptoCode, cb) { return cb && cb(err) } - logger.debug('[%s] Balance update:', cryptoCode, balance) + logger.debug('[%s] Balance update: %j', cryptoCode, balance) balance.timestamp = Date.now() - lastBalances[cryptoCode] = balance + lastBalances[cryptoCode] = new BigNumber(balance[cryptoCode]) return cb && cb(null, lastBalances) }) @@ -472,7 +489,7 @@ function pollRate (cryptoCode, cb) { rates.ask = rates.ask && new BigNumber(rates.ask) rates.bid = rates.bid && new BigNumber(rates.bid) } - logger.debug('got rates: %j', resRates) + logger.debug('[%s] got rates: %j', cryptoCode, resRates) lastRates[cryptoCode] = resRates @@ -495,9 +512,8 @@ exports.getDeviceRate = function getDeviceRate (cryptoCode) { exports.getBalance = function getBalance (cryptoCode) { var lastBalance = lastBalances[cryptoCode] - if (!lastBalance) return null - return lastBalance.transferBalance + return lastBalance } /* diff --git a/lib/postgresql_interface.js b/lib/postgresql_interface.js index ca58093d..bcae7cbd 100644 --- a/lib/postgresql_interface.js +++ b/lib/postgresql_interface.js @@ -284,6 +284,7 @@ function insertTx(client, session, incoming, tx, satoshis, fiat, stage, 'to_address', 'satoshis', 'currency_code', + 'crypto_code', 'fiat', 'tx_hash', 'error' @@ -298,6 +299,7 @@ function insertTx(client, session, incoming, tx, satoshis, fiat, stage, tx.toAddress, satoshis, tx.currencyCode, + tx.cryptoCode, fiat, tx.txHash, tx.error @@ -322,13 +324,13 @@ function refreshPendingTx(client, session, cb) { }); } -function addPendingTx(client, session, incoming, currencyCode, toAddress, +function addPendingTx(client, session, incoming, currencyCode, cryptoCode, toAddress, satoshis, cb) { var fields = ['device_fingerprint', 'session_id', 'incoming', - 'currency_code', 'to_address', 'satoshis']; + 'currency_code', 'crypto_code', 'to_address', 'satoshis']; var sql = getInsertQuery('pending_transactions', fields, false); var values = [session.fingerprint, session.id, incoming, currencyCode, - toAddress, satoshis]; + cryptoCode, toAddress, satoshis]; query(client, sql, values, function(err) { cb(err); }); @@ -402,14 +404,14 @@ function ensureNotFinal(client, session, cb) { } exports.addOutgoingPending = function addOutgoingPending(session, currencyCode, - toAddress, cb) { + cryptoCode, toAddress, cb) { connect(function(cerr, client, done) { if (cerr) return cb(cerr); async.series([ async.apply(silentQuery, client, 'BEGIN', null), async.apply(ensureNotFinal, client, session), - async.apply(addPendingTx, client, session, false, currencyCode, toAddress, + async.apply(addPendingTx, client, session, false, currencyCode, cryptoCode, toAddress, 0) ], function(err) { if (err) { @@ -442,7 +444,7 @@ exports.addInitialIncoming = function addInitialIncoming(session, tx, cb) { async.series([ async.apply(silentQuery, client, 'BEGIN', null), async.apply(addPendingTx, client, session, true, tx.currencyCode, - tx.toAddress, tx.satoshis), + tx.cryptoCode, tx.toAddress, tx.satoshis), async.apply(insertIncoming, client, session, tx, tx.satoshis, tx.fiat, 'initial_request', 'pending') ], function(err) { diff --git a/lib/routes.js b/lib/routes.js index 8c46c35c..c6520654 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -46,13 +46,13 @@ function buildRates () { function buildBalances () { var cryptoCodes = plugins.getcryptoCodes() - var balances = {} + var _balances = {} cryptoCodes.forEach(function (cryptoCode) { var balance = plugins.fiatBalance(cryptoCode) - balances[cryptoCode] = balance + _balances[cryptoCode] = balance }) - return balances + return _balances } function poll (req, res) { @@ -106,6 +106,7 @@ function trade (req, res) { tx.cryptoAtoms = new BigNumber(tx.cryptoAtoms) plugins.trade(session(req), tx, function (err) { + if (err) logger.error(err) var statusCode = err ? 500 : 201 res.json(statusCode, {err: err}) }) @@ -235,7 +236,6 @@ function init (localConfig) { }) localApp.post('/reboot', function (req, res) { - console.log('DEBUG1') var pid = req.body.pid var fingerprint = req.body.fingerprint console.log('pid: %s, fingerprint: %s', pid, fingerprint) diff --git a/todo.txt b/todo.txt index ec0e1d8f..f2fa57a4 100644 --- a/todo.txt +++ b/todo.txt @@ -7,3 +7,30 @@ backwards compatibility: - clean up db stuff satoshis/cryptoAtoms - clean up other stuff + +- add 'ETH' to config in ssu crypto: config.exchanges.settings.coins + +[2016-04-06T19:58:17.827Z] ERROR: lamassu-server/39374 on MacBook-Pro: null value in column "satoshis" violates not-null constraint + error: null value in column "satoshis" violates not-null constraint + at Connection.parseE (/Users/josh/projects/lamassu-server/node_modules/pg/lib/connection.js:539:11) + at Connection.parseMessage (/Users/josh/projects/lamassu-server/node_modules/pg/lib/connection.js:366:17) + at Socket. (/Users/josh/projects/lamassu-server/node_modules/pg/lib/connection.js:105:22) + at Socket.emit (events.js:95:17) + at Socket. (_stream_readable.js:765:14) + at Socket.emit (events.js:92:17) + at emitReadable_ (_stream_readable.js:427:10) + at emitReadable (_stream_readable.js:423:5) + at readableAddChunk (_stream_readable.js:166:9) + at Socket.Readable.push (_stream_readable.js:128:10) + +alter table transactions alter satoshis TYPE bigint; +alter table transactions add crypto_code text default 'BTC'; +alter table pending_transactions add crypto_code text default 'BTC'; +alter table pending_transactions alter satoshis TYPE bigint; +alter table bills add crypto_code text default 'BTC'; +alter table bills alter satoshis TYPE bigint; + +- get cryptoCode from pending tx +- update cryptoCode for bills insert +- insert correct satoshis in pending tx -- actually this is supposed to be 0 +- fix satoshi math in postgres module by moving to bignumber math