From 35cbb466884a8355b5e02ed1066ab0e6d17610bb Mon Sep 17 00:00:00 2001 From: Josh Harvey Date: Wed, 1 Jun 2016 00:49:51 +0300 Subject: [PATCH] WIP --- .gitignore | 1 + lib/plugins.js | 36 ++++++++++++++----------- lib/postgresql_interface.js | 18 ++++++++++++- migrations/011-transactions-reload-2.js | 6 ++--- migrations/012-add-hd-path-serial.js | 20 ++++++++++++++ todo.txt | 4 +-- 6 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 migrations/012-add-hd-path-serial.js diff --git a/.gitignore b/.gitignore index 4cbee9e4..01f6cfee 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ options.mine.js raqia.json scratch/ +seeds/ diff --git a/lib/plugins.js b/lib/plugins.js index 1a013d69..8565e56c 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -1,8 +1,8 @@ 'use strict' +var fs = require('fs') var R = require('ramda') var async = require('async') - var BigNumber = require('bignumber.js') BigNumber.config({CRYPTO: true}) @@ -34,6 +34,7 @@ var idVerifierPlugin = null var infoPlugin = null var emailPlugin = null var smsPlugin = null +var masterSeed = null var currentlyUsedPlugins = {} @@ -54,12 +55,8 @@ var alertFingerprint = null var lastAlertTime = null // that's basically a constructor -exports.init = function init (databaseHandle) { - if (!databaseHandle) { - throw new Error('\'db\' is required') - } - - db = databaseHandle +exports.init = function init () { + fs.readFileSync('seeds/seed.txt') } function loadPlugin (name, config) { @@ -121,7 +118,7 @@ function loadPlugin (name, config) { return plugin } -function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCode, currency, +function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCode, options, onChangeCallback) { cryptoCode = cryptoCode || 'BTC' @@ -137,11 +134,11 @@ function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCode, currency, else { // some plugins may be disabled var pluginConfig = cachedConfig.exchanges.plugins.settings[currentName] || {} - if (currency) pluginConfig.currency = currency + const mergedConfig = R.merge(pluginConfig, options) - if (pluginHandle && !pluginChanged) pluginHandle.config(pluginConfig) + if (pluginHandle && !pluginChanged) pluginHandle.config(mergedConfig) else { - pluginHandle = loadPlugin(currentName, pluginConfig) + pluginHandle = loadPlugin(currentName, mergedConfig) currentlyUsedPlugins[cryptoCode] = currentlyUsedPlugins[cryptoCode] || {} currentlyUsedPlugins[cryptoCode][pluginType] = currentName logger.debug('[%s] plugin(%s) loaded: %s', cryptoCode, pluginType, pluginHandle.NAME || @@ -149,7 +146,7 @@ function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCode, currency, } } - if (typeof onChangeCallback === 'function') onChangeCallback(pluginHandle, currency) + if (typeof onChangeCallback === 'function') onChangeCallback(pluginHandle) return pluginHandle } @@ -171,7 +168,7 @@ exports.configure = function configure (config) { tickerPlugins[cryptoCode], 'ticker', cryptoCode, - deviceCurrency, // device currency + {currency: deviceCurrency}, function onTickerChange (newTicker) { tickerPlugins[cryptoCode] = newTicker pollRate(cryptoCode) @@ -183,7 +180,10 @@ exports.configure = function configure (config) { walletPlugins[cryptoCode], 'transfer', cryptoCode, - null, + { + nextCashOutSerialHD: db.nextCashOutSerialHD(cryptoCode), + masterSeed: masterSeed + }, function onWalletChange (newWallet) { walletPlugins[cryptoCode] = newWallet pollBalance(cryptoCode) @@ -360,8 +360,12 @@ exports.cashOut = function cashOut (session, tx) { walletPlugin.newAddress(tmpInfo, function (err, address) { if (err) return reject(err) - const newTx = R.assoc('toAddress', address, tx) - return db.addInitialIncoming(session, newTx) + const addressRec = R.is(String, address) + ? {address: address} + : address + + const newTx = R.assoc('toAddress', addressRec.address, tx) + return db.addInitialIncoming(session, newTx, addressRec) .then(() => resolve(address)) }) }) diff --git a/lib/postgresql_interface.js b/lib/postgresql_interface.js index bd2137a1..9f406fbd 100644 --- a/lib/postgresql_interface.js +++ b/lib/postgresql_interface.js @@ -113,7 +113,7 @@ exports.sentCoins = function sentCoins (session, tx, toSend, fee, error, txHash) return db.none(sql, [txHash, error, session.id]) } -exports.addInitialIncoming = function addInitialIncoming (session, tx) { +exports.addInitialIncoming = function addInitialIncoming (session, tx, addressRec) { const fields = ['session_id', 'device_fingerprint', 'to_address', 'crypto_atoms', 'crypto_code', 'currency_code', 'fiat', 'tx_hash', 'phone', 'error' @@ -133,6 +133,15 @@ exports.addInitialIncoming = function addInitialIncoming (session, tx) { ] return db.none(getInsertQuery('cash_out_txs', fields), values) + .then(() => { + const hd = addressRec.hd + if (hd) { + const fields2 = ['session_id', 'to_address', 'crypto_code', + 'hd_path_prefix', 'hd_serial'] + const values2 = [tx.sessionId, tx.toAddress, tx.cryptoCode, hd.pathPrefix, hd.serial] + return db.none(getInsertQuery('cash_out_hds', fields2), values2) + } + }) } function insertDispense (session, tx, cartridges) { @@ -424,3 +433,10 @@ exports.cacheResponse = function (session, path, method, body) { return db.none(sql, values) } + +exports.nextCashOutSerialHD = function nextCashOutSerialHD (cryptoCode) { + const sql = `select hd_serial from cash_out_hds + where crypto_code=$1 order by hd_serial desc limit 1` + return db.oneOrNone(sql, [cryptoCode]) + .then(row => row ? row.hd_serial + 1 : 0) +} diff --git a/migrations/011-transactions-reload-2.js b/migrations/011-transactions-reload-2.js index 440ccf44..bb84e8df 100644 --- a/migrations/011-transactions-reload-2.js +++ b/migrations/011-transactions-reload-2.js @@ -21,8 +21,7 @@ exports.up = function (next) { tx_hash text, phone text, error text, - created timestamptz NOT NULL default now(), - unique (session_id) + created timestamptz NOT NULL default now() )`, `create table cash_out_txs ( session_id uuid PRIMARY KEY, @@ -40,8 +39,7 @@ exports.up = function (next) { phone text, error text, created timestamptz NOT NULL default now(), - confirmation_time timestamptz, - unique (session_id) + confirmation_time timestamptz )`, `create type cash_out_action_types AS ENUM (${actions})`, `create table cash_out_actions ( diff --git a/migrations/012-add-hd-path-serial.js b/migrations/012-add-hd-path-serial.js new file mode 100644 index 00000000..b2b84700 --- /dev/null +++ b/migrations/012-add-hd-path-serial.js @@ -0,0 +1,20 @@ +var db = require('./db') + +exports.up = function (next) { + var sql = [ + `create table cash_out_hds ( + session_id uuid PRIMARY KEY, + to_address text NOT NULL, + crypto_code text NOT NULL, + hd_path_prefix text NOT NULL, + hd_serial integer NOT NULL, + created timestamptz NOT NULL default now(), + unique (crypto_code, hd_serial) + )` + ] + db.multi(sql, next) +} + +exports.down = function (next) { + next() +} diff --git a/todo.txt b/todo.txt index c0250e76..01ebf149 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,4 @@ - l-m shouldn't keep polling l-s when not on pending screen (low priority) -- don't record multiple tx authorizations to db -- processTxStatus isn't atomic +- need more bulletproof way to ensure only unique serials for each coin +- use tx to read last, then insert new row