Fix up various flow issues.
This commit is contained in:
parent
08bd7da33f
commit
0d8a8547f5
8 changed files with 60 additions and 40 deletions
|
|
@ -88,7 +88,7 @@ function redeemableTxs (deviceId) {
|
|||
and redeem=$2
|
||||
and dispense=$3
|
||||
and provisioned_1 is not null
|
||||
and (extract(epoch from (now() - greatest(created, confirmation_time))) * 1000) < $4`
|
||||
and (extract(epoch from (now() - greatest(created, confirmed_at))) * 1000) < $4`
|
||||
|
||||
return db.any(sql, [deviceId, true, false, REDEEMABLE_AGE])
|
||||
.then(_.map(toObj))
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const logger = require('./logger')
|
|||
const plugins = require('./plugins')
|
||||
const helper = require('./cash-out-helper')
|
||||
const socket = require('./socket-client')
|
||||
const E = require('./error')
|
||||
|
||||
module.exports = {
|
||||
post,
|
||||
|
|
@ -17,8 +18,8 @@ module.exports = {
|
|||
cancel
|
||||
}
|
||||
|
||||
const UPDATEABLE_FIELDS = ['txHash', 'status', 'dispense', 'dispenseConfirmed',
|
||||
'notified', 'redeem', 'phone', 'error', 'swept']
|
||||
const UPDATEABLE_FIELDS = ['txHash', 'txVersion', 'status', 'dispense', 'dispenseConfirmed',
|
||||
'notified', 'redeem', 'phone', 'error', 'swept', 'publishedAt', 'confirmedAt']
|
||||
|
||||
const STALE_INCOMING_TX_AGE = T.week
|
||||
const STALE_LIVE_INCOMING_TX_AGE = 10 * T.minutes
|
||||
|
|
@ -37,7 +38,11 @@ function httpError (msg, code) {
|
|||
return err
|
||||
}
|
||||
|
||||
function post (tx, pi) {
|
||||
function selfPost (tx, pi) {
|
||||
return post(tx, pi, false)
|
||||
}
|
||||
|
||||
function post (tx, pi, fromClient = true) {
|
||||
const TransactionMode = pgp.txMode.TransactionMode
|
||||
const isolationLevel = pgp.txMode.isolationLevel
|
||||
const tmSRD = new TransactionMode({tiLevel: isolationLevel.serializable})
|
||||
|
|
@ -48,6 +53,9 @@ function post (tx, pi) {
|
|||
return t.oneOrNone(sql, [tx.id])
|
||||
.then(toObj)
|
||||
.then(oldTx => {
|
||||
const isStale = fromClient && oldTx && (oldTx.txVersion >= tx.txVersion)
|
||||
if (isStale) throw new E.StaleTxError('Stale tx')
|
||||
|
||||
return preProcess(oldTx, tx, pi)
|
||||
.then(preProcessedTx => upsert(oldTx, preProcessedTx))
|
||||
})
|
||||
|
|
@ -280,8 +288,33 @@ function postProcess (txVector, pi) {
|
|||
return Promise.resolve({})
|
||||
}
|
||||
|
||||
function isPublished (status) {
|
||||
return _.includes(status, ['published', 'rejected', 'authorized', 'instant', 'confirmed'])
|
||||
}
|
||||
|
||||
function isConfirmed (status) {
|
||||
return status === 'confirmed'
|
||||
}
|
||||
|
||||
function updateStatus (oldTx, newTx) {
|
||||
return _.set('status', ratchetStatus(oldTx.status, newTx.status), newTx)
|
||||
const oldStatus = oldTx.status
|
||||
const newStatus = ratchetStatus(oldStatus, newTx.status)
|
||||
|
||||
const publishedAt = !oldTx.publishedAt && isPublished(newStatus)
|
||||
? 'now()^'
|
||||
: undefined
|
||||
|
||||
const confirmedAt = !oldTx.confirmedAt && isConfirmed(newStatus)
|
||||
? 'now()^'
|
||||
: undefined
|
||||
|
||||
const updateRec = {
|
||||
publishedAt,
|
||||
confirmedAt,
|
||||
status: newStatus
|
||||
}
|
||||
|
||||
return _.merge(newTx, updateRec)
|
||||
}
|
||||
|
||||
function ratchetStatus (oldStatus, newStatus) {
|
||||
|
|
@ -311,8 +344,8 @@ function processTxStatus (tx, settings) {
|
|||
const pi = plugins(settings, tx.deviceId)
|
||||
|
||||
return pi.getStatus(tx)
|
||||
.then(res => _.set('status', res.status, tx))
|
||||
.then(_tx => post(_tx, pi))
|
||||
.then(res => _.assign(tx, {status: res.status}))
|
||||
.then(_tx => selfPost(_tx, pi))
|
||||
}
|
||||
|
||||
function monitorLiveIncoming (settings) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ const NAME = 'FakeWallet'
|
|||
const SECONDS = 1000
|
||||
const PUBLISH_TIME = 2 * SECONDS
|
||||
const AUTHORIZE_TIME = PUBLISH_TIME + 6 * SECONDS
|
||||
const CONFIRM_TIME = AUTHORIZE_TIME + 180 * SECONDS
|
||||
const CONFIRM_TIME = AUTHORIZE_TIME + 120 * SECONDS
|
||||
|
||||
let t0
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ function authorize (account, toAddress, cryptoAtoms, cryptoCode) {
|
|||
.then(() => {
|
||||
if (cryptoCode !== 'BTC') throw new Error('Unsupported crypto: ' + cryptoCode)
|
||||
|
||||
const isAuthorized = true
|
||||
const isAuthorized = false
|
||||
return isAuthorized
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ function toCashOutTx (row) {
|
|||
function fetchPhoneTx (phone) {
|
||||
const sql = `select * from cash_out_txs
|
||||
where phone=$1 and dispense=$2
|
||||
and (extract(epoch from (coalesce(confirmation_time, now()) - created))) * 1000 < $3`
|
||||
and (extract(epoch from (coalesce(confirmed_at, now()) - created))) * 1000 < $3`
|
||||
|
||||
const values = [phone, false, TRANSACTION_EXPIRATION]
|
||||
|
||||
|
|
|
|||
|
|
@ -188,19 +188,6 @@ function pair (req, res, next) {
|
|||
.catch(next)
|
||||
}
|
||||
|
||||
function phoneCode (req, res, next) {
|
||||
const pi = plugins(req.settings, req.deviceId)
|
||||
const phone = req.body.phone
|
||||
|
||||
return pi.getPhoneCode(phone)
|
||||
.then(code => respond(req, res, {code}))
|
||||
.catch(err => {
|
||||
if (err.name === 'BadNumberError') throw httpError('Bad number', 410)
|
||||
throw err
|
||||
})
|
||||
.catch(next)
|
||||
}
|
||||
|
||||
function errorHandler (err, req, res, next) {
|
||||
const statusCode = err.name === 'HTTPError'
|
||||
? err.code || 500
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ const pify = require('pify')
|
|||
const fs = pify(require('fs'))
|
||||
const options = require('./options')
|
||||
const ph = require('./plugin-helper')
|
||||
const db = require('./db')
|
||||
|
||||
const FETCH_INTERVAL = 5000
|
||||
const INSUFFICIENT_FUNDS_CODE = 570
|
||||
|
|
@ -111,27 +110,14 @@ function authorizeZeroConf (settings, tx, machineId) {
|
|||
return zeroConf.authorize(account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode)
|
||||
}
|
||||
|
||||
function getPublishAge (txId) {
|
||||
const sql = `select extract(epoch from (now() - created)) * 1000 as age
|
||||
from cash_out_actions
|
||||
where tx_id=$1
|
||||
and action=$2`
|
||||
|
||||
return db.oneOrNone(sql, [txId, 'published'])
|
||||
.then(row => row && row.age)
|
||||
}
|
||||
|
||||
function getStatus (settings, tx, machineId) {
|
||||
return getWalletStatus(settings, tx)
|
||||
.then((statusRec) => {
|
||||
if (statusRec.status === 'authorized') {
|
||||
const promises = [
|
||||
getPublishAge(tx.id),
|
||||
authorizeZeroConf(settings, tx, machineId)
|
||||
]
|
||||
return authorizeZeroConf(settings, tx, machineId)
|
||||
.then(isAuthorized => {
|
||||
const publishAge = Date.now() - tx.publishedAt
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(([publishAge, isAuthorized]) => {
|
||||
const unauthorizedStatus = publishAge < ZERO_CONF_EXPIRATION
|
||||
? 'published'
|
||||
: 'rejected'
|
||||
|
|
|
|||
14
migrations/1505044429557-add_cash_out_txs_published_at.js
Normal file
14
migrations/1505044429557-add_cash_out_txs_published_at.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
var db = require('./db')
|
||||
|
||||
exports.up = function (next) {
|
||||
const sql = [
|
||||
'alter table cash_out_txs add column published_at timestamptz',
|
||||
'alter table cash_out_txs rename column confirmation_time to confirmed_at'
|
||||
]
|
||||
|
||||
db.multi(sql, next)
|
||||
}
|
||||
|
||||
exports.down = function (next) {
|
||||
next()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue