hotfix: add fudge factor

This commit is contained in:
Taranto 2020-02-11 21:06:30 +00:00 committed by Josh Harvey
parent bf341476bb
commit fa69d2a030
18 changed files with 650 additions and 249 deletions

View file

@ -156,7 +156,7 @@ determineConfigCategory : String -> Maybe Category
determineConfigCategory configCode = determineConfigCategory configCode =
if List.member configCode [ "definition", "setup", "cashOut", "commissions", "balanceAlerts" ] then if List.member configCode [ "definition", "setup", "cashOut", "commissions", "balanceAlerts" ] then
Just MachineSettingsCat Just MachineSettingsCat
else if List.member configCode [ "walletSettings", "notifications", "compliance", "coinAtmRadar", "terms", "operatorInfo" ] then else if List.member configCode [ "walletSettings", "notifications", "compliance", "coinAtmRadar", "terms", "operatorInfo", "fudgeFactor" ] then
Just GlobalSettingsCat Just GlobalSettingsCat
else else
Nothing Nothing
@ -253,6 +253,7 @@ view route invalidGroups =
, configLink "coinAtmRadar" "Coin ATM Radar" , configLink "coinAtmRadar" "Coin ATM Radar"
, configLink "terms" "Terms and Conditions" , configLink "terms" "Terms and Conditions"
, configLink "operatorInfo" "Operator Info" , configLink "operatorInfo" "Operator Info"
, configLink "fudgeFactor" "Fudge Factor"
] ]
, ll ( "Third Party Services", AccountCat, AccountRoute "bitgo", True ) , ll ( "Third Party Services", AccountCat, AccountRoute "bitgo", True )
[ ( "BitGo", AccountRoute "bitgo", True ) [ ( "BitGo", AccountRoute "bitgo", True )

View file

@ -147,6 +147,15 @@
"operatorInfoWebsite", "operatorInfoWebsite",
"operatorInfoCompanyNumber" "operatorInfoCompanyNumber"
] ]
},
{
"code": "fudgeFactor",
"display": "Fudge Factor",
"cryptoScope": "global",
"machineScope": "global",
"fields": [
"fudgeFactorActive"
]
} }
], ],
"fields": [ "fields": [
@ -941,6 +950,14 @@
], ],
"fieldValidation": [] "fieldValidation": []
}, },
{
"code": "fudgeFactorActive",
"displayBottom": "Enabled",
"fieldType": "onOff",
"fieldClass": null,
"fieldValidation": [],
"default": false
},
{ {
"code": "operatorInfoActive", "code": "operatorInfoActive",
"displayBottom": "Info card enabled", "displayBottom": "Info card enabled",

View file

@ -11,14 +11,17 @@ module.exports = { redeemableTxs, toObj, toDb, REDEEMABLE_AGE }
const mapValuesWithKey = _.mapValues.convert({cap: false}) const mapValuesWithKey = _.mapValues.convert({cap: false})
function convertBigNumFields (obj) { function convertBigNumFields (obj) {
const convert = (value, key) => _.includes(key, [ const convert = (value, key) => {
'cryptoAtoms', if (_.includes(key, [ 'cryptoAtoms', 'receivedCryptoAtoms', 'fiat' ])) {
'fiat', return value.toString()
'commissionPercentage', }
'rawTickerPrice'
]) if (_.includes(key, [ 'commissionPercentage', 'rawTickerPrice' ]) && value) {
? value.toString() return value.toString()
: value }
return value
}
const convertKey = key => _.includes(key, ['cryptoAtoms', 'fiat']) const convertKey = key => _.includes(key, ['cryptoAtoms', 'fiat'])
? key + '#' ? key + '#'
@ -58,6 +61,10 @@ function toObj (row) {
keys.forEach(key => { keys.forEach(key => {
const objKey = _.camelCase(key) const objKey = _.camelCase(key)
if (key === 'received_crypto_atoms' && row[key]) {
newObj[objKey] = BN(row[key])
return
}
if (_.includes(key, ['crypto_atoms', 'fiat', 'commission_percentage', 'raw_ticker_price'])) { if (_.includes(key, ['crypto_atoms', 'fiat', 'commission_percentage', 'raw_ticker_price'])) {
newObj[objKey] = BN(row[key]) newObj[objKey] = BN(row[key])
return return

View file

@ -7,7 +7,8 @@ const toDb = helper.toDb
const toObj = helper.toObj const toObj = helper.toObj
const UPDATEABLE_FIELDS = ['txHash', 'txVersion', 'status', 'dispense', 'dispenseConfirmed', const UPDATEABLE_FIELDS = ['txHash', 'txVersion', 'status', 'dispense', 'dispenseConfirmed',
'notified', 'redeem', 'phone', 'error', 'swept', 'publishedAt', 'confirmedAt', 'errorCode'] 'notified', 'redeem', 'phone', 'error', 'swept', 'publishedAt', 'confirmedAt', 'errorCode',
'receivedCryptoAtoms' ]
module.exports = {upsert, update, insert} module.exports = {upsert, update, insert}

View file

@ -112,7 +112,7 @@ function processTxStatus (tx, settings) {
const pi = plugins(settings, tx.deviceId) const pi = plugins(settings, tx.deviceId)
return pi.getStatus(tx) return pi.getStatus(tx)
.then(res => _.assign(tx, {status: res.status})) .then(res => _.assign(tx, { receivedCryptoAtoms: res.receivedCryptoAtoms, status: res.status }))
.then(_tx => selfPost(_tx, pi)) .then(_tx => selfPost(_tx, pi))
} }

View file

@ -80,13 +80,13 @@ function getStatus (account, toAddress, requested, cryptoCode) {
return checkCryptoCode(cryptoCode) return checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress, cryptoCode)) .then(() => confirmedBalance(toAddress, cryptoCode))
.then(confirmed => { .then(confirmed => {
if (confirmed.gte(requested)) return {status: 'confirmed'} if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' }
return pendingBalance(toAddress, cryptoCode) return pendingBalance(toAddress, cryptoCode)
.then(pending => { .then(pending => {
if (pending.gte(requested)) return {status: 'authorized'} if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' }
if (pending.gt(0)) return {status: 'insufficientFunds'} if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' }
return {status: 'notSeen'} return { receivedCryptoAtoms: pending, status: 'notSeen' }
}) })
}) })
} }

View file

@ -80,13 +80,13 @@ function getStatus (account, toAddress, requested, cryptoCode) {
return checkCryptoCode(cryptoCode) return checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress, cryptoCode)) .then(() => confirmedBalance(toAddress, cryptoCode))
.then(confirmed => { .then(confirmed => {
if (confirmed.gte(requested)) return {status: 'confirmed'} if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' }
return pendingBalance(toAddress, cryptoCode) return pendingBalance(toAddress, cryptoCode)
.then(pending => { .then(pending => {
if (pending.gte(requested)) return {status: 'authorized'} if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' }
if (pending.gt(0)) return {status: 'insufficientFunds'} if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' }
return {status: 'notSeen'} return { receivedCryptoAtoms: pending, status: 'notSeen' }
}) })
}) })
} }

View file

@ -124,10 +124,10 @@ function getStatus (account, toAddress, requested, cryptoCode) {
const confirmed = _.compose(sum, toBn, filterConfirmed)(transfers) const confirmed = _.compose(sum, toBn, filterConfirmed)(transfers)
const pending = _.compose(sum, toBn, filterPending)(transfers) const pending = _.compose(sum, toBn, filterPending)(transfers)
if (confirmed.gte(requested)) return { status: 'confirmed' } if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' }
if (pending.gte(requested)) return { status: 'authorized' } if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' }
if (pending.gt(0)) return { status: 'insufficientFunds' } if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' }
return { status: 'notSeen' } return { receivedCryptoAtoms: pending, status: 'notSeen' }
}) })
} }

View file

@ -81,13 +81,13 @@ function getStatus (account, toAddress, requested, cryptoCode) {
return checkCryptoCode(cryptoCode) return checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress, cryptoCode)) .then(() => confirmedBalance(toAddress, cryptoCode))
.then(confirmed => { .then(confirmed => {
if (confirmed.gte(requested)) return {status: 'confirmed'} if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' }
return pendingBalance(toAddress, cryptoCode) return pendingBalance(toAddress, cryptoCode)
.then(pending => { .then(pending => {
if (pending.gte(requested)) return {status: 'authorized'} if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' }
if (pending.gt(0)) return {status: 'insufficientFunds'} if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' }
return {status: 'notSeen'} return { receivedCryptoAtoms: pending, status: 'notSeen' }
}) })
}) })
} }

View file

@ -158,13 +158,13 @@ function getStatus (account, toAddress, cryptoAtoms, cryptoCode) {
return checkCryptoCode(cryptoCode) return checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress)) .then(() => confirmedBalance(toAddress))
.then(confirmed => { .then(confirmed => {
if (confirmed.gte(cryptoAtoms)) return {status: 'confirmed'} if (confirmed.gte(cryptoAtoms)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' }
return pendingBalance(toAddress) return pendingBalance(toAddress)
.then(pending => { .then(pending => {
if (pending.gte(cryptoAtoms)) return {status: 'published'} if (pending.gte(cryptoAtoms)) return { receivedCryptoAtoms: pending, status: 'published' }
if (pending.gt(0)) return {status: 'insufficientFunds'} if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' }
return {status: 'notSeen'} return { receivedCryptoAtoms: pending, status: 'notSeen' }
}) })
}) })
} }

View file

@ -81,13 +81,13 @@ function getStatus (account, toAddress, requested, cryptoCode) {
return checkCryptoCode(cryptoCode) return checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress, cryptoCode)) .then(() => confirmedBalance(toAddress, cryptoCode))
.then(confirmed => { .then(confirmed => {
if (confirmed.gte(requested)) return {status: 'confirmed'} if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' }
return pendingBalance(toAddress, cryptoCode) return pendingBalance(toAddress, cryptoCode)
.then(pending => { .then(pending => {
if (pending.gte(requested)) return {status: 'authorized'} if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' }
if (pending.gt(0)) return {status: 'insufficientFunds'} if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' }
return {status: 'notSeen'} return { receivedCryptoAtoms: pending, status: 'notSeen' }
}) })
}) })
} }

View file

@ -79,9 +79,9 @@ function newFunding (account, cryptoCode) {
function getStatus (account, toAddress, cryptoAtoms, cryptoCode) { function getStatus (account, toAddress, cryptoAtoms, cryptoCode) {
const elapsed = Date.now() - t0 const elapsed = Date.now() - t0
if (elapsed < PUBLISH_TIME) return Promise.resolve({status: 'notSeen'}) if (elapsed < PUBLISH_TIME) return Promise.resolve({ receivedCryptoAtoms: cryptoAtoms - 10, status: 'notSeen' })
if (elapsed < AUTHORIZE_TIME) return Promise.resolve({status: 'published'}) if (elapsed < AUTHORIZE_TIME) return Promise.resolve({ receivedCryptoAtoms: cryptoAtoms - 10, status: 'published' })
if (elapsed < CONFIRM_TIME) return Promise.resolve({status: 'authorized'}) if (elapsed < CONFIRM_TIME) return Promise.resolve({ receivedCryptoAtoms: null, status: 'authorized' })
console.log('[%s] DEBUG: Mock wallet has confirmed transaction [%s]', cryptoCode, toAddress.slice(0, 5)) console.log('[%s] DEBUG: Mock wallet has confirmed transaction [%s]', cryptoCode, toAddress.slice(0, 5))

View file

@ -81,13 +81,13 @@ function getStatus (account, toAddress, requested, cryptoCode) {
return checkCryptoCode(cryptoCode) return checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress, cryptoCode)) .then(() => confirmedBalance(toAddress, cryptoCode))
.then(confirmed => { .then(confirmed => {
if (confirmed.gte(requested)) return {status: 'confirmed'} if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' }
return pendingBalance(toAddress, cryptoCode) return pendingBalance(toAddress, cryptoCode)
.then(pending => { .then(pending => {
if (pending.gte(requested)) return {status: 'authorized'} if (pending.gte(requested)) return { receivedCryptoAtoms: pending, status: 'authorized' }
if (pending.gt(0)) return {status: 'insufficientFunds'} if (pending.gt(0)) return { receivedCryptoAtoms: pending, status: 'insufficientFunds' }
return {status: 'notSeen'} return { receivedCryptoAtoms: pending, status: 'notSeen' }
}) })
}) })
} }

View file

@ -29,13 +29,13 @@ function massage (tx, pi) {
cashInFee: BN(r.cashInFee), cashInFee: BN(r.cashInFee),
cashInFeeCrypto: BN(r.cashInFeeCrypto), cashInFeeCrypto: BN(r.cashInFeeCrypto),
commissionPercentage: BN(r.commissionPercentage), commissionPercentage: BN(r.commissionPercentage),
rawTickerPrice: BN(r.rawTickerPrice), rawTickerPrice: r.rawTickerPrice ? BN(r.rawTickerPrice) : null,
minimumTx: BN(r.minimumTx) minimumTx: BN(r.minimumTx)
} }
: { : {
cryptoAtoms: BN(r.cryptoAtoms), cryptoAtoms: BN(r.cryptoAtoms),
fiat: BN(r.fiat), fiat: BN(r.fiat),
rawTickerPrice: BN(r.rawTickerPrice), rawTickerPrice: r.rawTickerPrice ? BN(r.rawTickerPrice) : null,
commissionPercentage: BN(r.commissionPercentage) commissionPercentage: BN(r.commissionPercentage)
} }

View file

@ -104,7 +104,7 @@ function mergeStatus (a, b) {
if (!a) return b if (!a) return b
if (!b) return a if (!b) return a
return { status: mergeStatusMode(a.status, b.status) } return { receivedCryptoAtoms: a.receivedCryptoAtoms, status: mergeStatusMode(a.status, b.status) }
} }
function mergeStatusMode (a, b) { function mergeStatusMode (a, b) {
@ -122,8 +122,11 @@ function mergeStatusMode (a, b) {
} }
function getWalletStatus (settings, tx) { function getWalletStatus (settings, tx) {
const fudgeFactorEnabled = configManager.unscoped(settings.config).fudgeFactor
const fudgeFactor = fudgeFactorEnabled ? 10 : 0
const walletStatusPromise = fetchWallet(settings, tx.cryptoCode) const walletStatusPromise = fetchWallet(settings, tx.cryptoCode)
.then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode)) .then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms.add(fudgeFactor), tx.cryptoCode))
return Promise.all([ return Promise.all([
walletStatusPromise, walletStatusPromise,
@ -170,7 +173,7 @@ function getStatus (settings, tx, machineId) {
const status = isAuthorized ? 'authorized' : unauthorizedStatus const status = isAuthorized ? 'authorized' : unauthorizedStatus
return { status } return { receivedCryptoAtoms: statusRec.receivedCryptoAtoms, status }
}) })
} }

View file

@ -0,0 +1,13 @@
const db = require('./db')
exports.up = function (next) {
var sql = [
'ALTER TABLE cash_out_txs ADD COLUMN received_crypto_atoms numeric(30) null DEFAULT null'
]
db.multi(sql, next)
}
exports.down = function (next) {
next()
}

751
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -37383,7 +37383,11 @@ var _user$project$NavBar$determineConfigCategory = function (configCode) {
_1: { _1: {
ctor: '::', ctor: '::',
_0: 'operatorInfo', _0: 'operatorInfo',
_1: {ctor: '[]'} _1: {
ctor: '::',
_0: 'fudgeFactor',
_1: {ctor: '[]'}
}
} }
} }
} }
@ -37836,7 +37840,11 @@ var _user$project$NavBar$view = F2(
_1: { _1: {
ctor: '::', ctor: '::',
_0: A2(configLink, 'operatorInfo', 'Operator Info'), _0: A2(configLink, 'operatorInfo', 'Operator Info'),
_1: {ctor: '[]'} _1: {
ctor: '::',
_0: A2(configLink, 'fudgeFactor', 'Fudge Factor'),
_1: {ctor: '[]'}
}
} }
} }
} }