Merge remote-tracking branch 'upstream/release-8.1' into release-8.5

This commit is contained in:
Taranto 2023-06-15 20:40:22 +01:00
commit 78be4a47b6
21 changed files with 58 additions and 45 deletions

View file

@ -34,12 +34,12 @@ const BINARIES = {
dir: 'bitcoin-23.1/bin'
},
ETH: {
url: 'https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.11.6-ea9e62ca.tar.gz',
dir: 'geth-linux-amd64-1.11.6-ea9e62ca'
url: 'https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.12.0-e501b3b0.tar.gz',
dir: 'geth-linux-amd64-1.12.0-e501b3b0'
},
ZEC: {
url: 'https://z.cash/downloads/zcash-5.5.0-linux64-debian-bullseye.tar.gz',
dir: 'zcash-5.5.0/bin'
url: 'https://z.cash/downloads/zcash-5.5.1-linux64-debian-bullseye.tar.gz',
dir: 'zcash-5.5.1/bin'
},
DASH: {
url: 'https://github.com/dashpay/dash/releases/download/v18.1.0/dashcore-18.1.0-x86_64-linux-gnu.tar.gz',
@ -52,8 +52,8 @@ const BINARIES = {
dir: 'litecoin-0.21.2.2/bin'
},
BCH: {
url: 'https://github.com/bitcoin-cash-node/bitcoin-cash-node/releases/download/v26.0.0/bitcoin-cash-node-26.0.0-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-cash-node-26.0.0/bin',
url: 'https://github.com/bitcoin-cash-node/bitcoin-cash-node/releases/download/v26.1.0/bitcoin-cash-node-26.1.0-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-cash-node-26.1.0/bin',
files: [['bitcoind', 'bitcoincashd'], ['bitcoin-cli', 'bitcoincash-cli']]
},
XMR: {

View file

@ -210,7 +210,7 @@ function isDisabled (crypto) {
case 'ETH':
return 'Use admin\'s Infura plugin'
case 'ZEC':
return isInstalled(crypto) && 'Installed' || isInstalled(_.find(it => it.code === 'monero', cryptos)) && 'Insufficient resources. Contact support.'
return 'Use admin\'s BitGo plugin'
case 'XMR':
return isInstalled(crypto) && 'Installed' || isInstalled(_.find(it => it.code === 'zcash', cryptos)) && 'Insufficient resources. Contact support.'
default:

View file

@ -25,7 +25,7 @@ case
else 'Pending'
end`
module.exports = {post, monitorPending, cancel, PENDING_INTERVAL, TRANSACTION_STATES}
module.exports = { post, monitorPending, cancel, PENDING_INTERVAL, TRANSACTION_STATES }
function post (machineTx, pi) {
logger.silly('Updating cashin tx:', machineTx)
@ -51,12 +51,12 @@ function post (machineTx, pi) {
}
return postProcess(r, pi, blacklisted, addressReuse, walletScore)
})
.then(changes => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, changes))
.then(changes => cashInLow.update(db, updatedTx, changes))
.then(tx => _.set('bills', machineTx.bills, tx))
.then(tx => _.set('blacklisted', blacklisted, tx))
.then(tx => _.set('addressReuse', addressReuse, tx))
.then(tx => _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid, tx))
.then(tx => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, tx))
})
}
@ -180,9 +180,9 @@ function doesTxReuseAddress (tx) {
}
function getWalletScore (tx, pi) {
pi.isWalletScoringEnabled(tx)
return pi.isWalletScoringEnabled(tx)
.then(isEnabled => {
if(!isEnabled) return null
if (!isEnabled) return null
if (!tx.fiat || tx.fiat.isZero()) {
return pi.rateWallet(tx.cryptoCode, tx.toAddress)
}
@ -223,7 +223,8 @@ function cancel (txId) {
const updateRec = {
error: 'Operator cancel',
error_code: 'operatorCancel',
operator_completed: true
operator_completed: true,
batch_id: null
}
return Promise.resolve()

View file

@ -115,22 +115,23 @@ function processTxStatus (tx, settings) {
}
function getWalletScore (tx, pi) {
const rejectEmpty = message => x => _.isNil(x) || _.isEmpty(x) ? Promise.reject({ message }) : x
const statuses = ['published', 'authorized', 'confirmed']
const rejectEmpty = message => x => _.isNil(x) || _.isEmpty(x) ? Promise.reject(new Error(message)) : x
const statuses = ['published', 'authorized', 'confirmed', 'insufficientFunds']
if (_.includes(tx.status, statuses) && _.isNil(tx.walletScore))
if (!_.includes(tx.status, statuses) || !_.isNil(tx.walletScore)) {
return tx
}
// Transaction shows up on the blockchain, we can request the sender address
// Transaction shows up on the blockchain, we can request the sender address
return pi.isWalletScoringEnabled(tx)
.then(isEnabled => {
if (!isEnabled) return tx
return pi.getTransactionHash(tx)
.then(rejectEmpty("No transaction hashes"))
.then(rejectEmpty('No transaction hashes'))
.then(txHashes => pi.getInputAddresses(tx, txHashes))
.then(rejectEmpty("No input addresses"))
.then(rejectEmpty('No input addresses'))
.then(addresses => Promise.all(_.map(it => pi.rateWallet(tx.cryptoCode, it), addresses)))
.then(rejectEmpty("No score ratings"))
.then(rejectEmpty('No score ratings'))
.then(_.maxBy(_.get(['score'])))
.then(highestScore =>
// Conservatively assign the highest risk of all input addresses to the risk of this transaction

View file

@ -1,5 +1,3 @@
// const configManager = require('./new-config-manager')
const logger = require('./logger')
const ph = require('./plugin-helper')
function sendMessage (settings, rec) {

View file

@ -29,7 +29,7 @@ const ALL_ACCOUNTS = [
{ code: 'bitcoind', display: 'bitcoind', class: WALLET, cryptos: [BTC] },
{ code: 'no-layer2', display: 'No Layer 2', class: LAYER_2, cryptos: ALL_CRYPTOS },
{ code: 'infura', display: 'Infura', class: WALLET, cryptos: [ETH, USDT] },
{ code: 'geth', display: 'geth', class: WALLET, cryptos: [ETH, USDT] },
{ code: 'geth', display: 'geth (deprecated)', class: WALLET, cryptos: [ETH, USDT] },
{ code: 'zcashd', display: 'zcashd', class: WALLET, cryptos: [ZEC] },
{ code: 'litecoind', display: 'litecoind', class: WALLET, cryptos: [LTC] },
{ code: 'dashd', display: 'dashd', class: WALLET, cryptos: [DASH] },

View file

@ -212,6 +212,7 @@ function complianceNotify (customer, deviceId, action, period) {
notifyIfActive('compliance', 'customerComplianceNotify', customer, deviceId, action, period)
return Promise.all(promises)
.catch(err => console.error(`An error occurred when sending a notification. Please check your notification preferences and 3rd party account configuration: ${err.stack}`))
})
}
@ -259,6 +260,7 @@ function sendTransactionMessage (rec, isHighValueTx) {
if (webhookActive) promises.push(webhookFuncs.sendMessage(settings, rec))
return Promise.all(promises)
.catch(err => console.error(`An error occurred when sending a notification. Please check your notification preferences and 3rd party account configuration: ${err.stack}`))
})
}
@ -301,6 +303,7 @@ function cashboxNotify (deviceId) {
notifyIfActive('security', 'cashboxNotify', deviceId)
return Promise.all(promises)
.catch(err => console.error(`An error occurred when sending a notification. Please check your notification preferences and 3rd party account configuration: ${err.stack}`))
})
}

View file

@ -1,10 +1,11 @@
const coins = require('@lamassu/coins')
const axios = require('axios')
const _ = require('lodash/fp')
const logger = require('../../../logger')
const NAME = 'CipherTrace'
const SUPPORTED_COINS = ['BTC', 'ETH', 'BCH', 'LTC', 'BNB', 'RSK']
const SUPPORTED_COINS = ['BTC', 'ETH', 'BCH', 'LTC']
function getClient (account) {
if (_.isNil(account) || !account.enabled) return null
@ -128,11 +129,15 @@ function getInputAddresses (account, cryptoCode, txHashes) {
}
function isWalletScoringEnabled (account, cryptoCode) {
if (!SUPPORTED_COINS.includes(cryptoCode)) {
const isAccountEnabled = !_.isNil(account) && account.enabled
if (!isAccountEnabled) return Promise.resolve(false)
if (!SUPPORTED_COINS.includes(cryptoCode) && !coins.utils.isErc20Token(cryptoCode)) {
return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode))
}
return Promise.resolve(!_.isNil(account) && account.enabled)
return Promise.resolve(true)
}
module.exports = {

View file

@ -112,7 +112,7 @@ function triggerSuspend (req, res, next) {
const triggers = configManager.getTriggers(req.settings.config)
const getSuspendDays = _.compose(_.get('suspensionDays'), _.find(_.matches({ id: triggerId })))
const days = triggerId === 'no-ff-camera' ? 1 : getSuspendDays(triggers)
const days = _.includes(triggerId, ['no-ff-camera', 'id-card-photo-disabled']) ? 1 : getSuspendDays(triggers)
const suspensionDuration = intervalToDuration({ start: 0, end: T.day * days })

View file

@ -6,7 +6,8 @@ const wallet = require('./wallet')
function submitBatch (settings, batch) {
txBatching.getBatchTransactions(batch)
.then(txs => {
wallet.sendCoinsBatch(settings, txs, batch.crypto_code)
if (_.isEmpty(txs)) return Promise.resolve()
return wallet.sendCoinsBatch(settings, txs, batch.crypto_code)
.then(res => txBatching.confirmSentBatch(batch, res))
.catch(err => txBatching.setErroredBatch(batch, err.message))
})

View file

@ -227,6 +227,7 @@ const overrides = (auxData, currency, auxElements) => {
return getOverridesFields(getData, currency, auxElements)
}
const percentMin = -15
const percentMax = 100
const getSchema = locale => {
const bills = getBillOptions(locale, denominations).map(it => it.code)
@ -235,12 +236,12 @@ const getSchema = locale => {
return Yup.object().shape({
cashIn: Yup.number()
.label('Cash-in')
.min(0)
.min(percentMin)
.max(percentMax)
.required(),
cashOut: Yup.number()
.label('Cash-out')
.min(0)
.min(percentMin)
.max(percentMax)
.required(),
fixedFee: Yup.number()
@ -330,12 +331,12 @@ const getOverridesSchema = (values, rawData, locale) => {
.min(1),
cashIn: Yup.number()
.label('Cash-in')
.min(0)
.min(percentMin)
.max(percentMax)
.required(),
cashOut: Yup.number()
.label('Cash-out')
.min(0)
.min(percentMin)
.max(percentMax)
.required(),
fixedFee: Yup.number()
@ -441,12 +442,12 @@ const getListCommissionsSchema = locale => {
.min(1),
cashIn: Yup.number()
.label('Cash-in')
.min(0)
.min(percentMin)
.max(percentMax)
.required(),
cashOut: Yup.number()
.label('Cash-out')
.min(0)
.min(percentMin)
.max(percentMax)
.required(),
fixedFee: Yup.number()

View file

@ -29,8 +29,10 @@ export default {
settings: {
enabled: true,
disabledMessage: 'This plugin is disabled',
label: 'Enabled',
requirement: null
label:
'Enabled (Supported coins: BTC, ETH, BCH, LTC and all active ERC-20 tokens)',
requirement: null,
rightSideLabel: true
},
face: true
}

View file

@ -383,7 +383,8 @@ const DetailsRow = ({ it: tx, timezone }) => {
) : (
errorElements
)}
{tx.txClass === 'cashOut' && getStatus(tx) === 'Pending' && (
{((tx.txClass === 'cashOut' && getStatus(tx) === 'Pending') ||
(tx.txClass === 'cashIn' && getStatus(tx) === 'Batched')) && (
<ActionButton
color="primary"
Icon={CancelIcon}

2
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "lamassu-server",
"version": "8.5.0-beta.2",
"version": "8.5.0-beta.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -2,7 +2,7 @@
"name": "lamassu-server",
"description": "bitcoin atm client server protocol module",
"keywords": [],
"version": "8.5.0-beta.2",
"version": "8.5.0-beta.3",
"license": "Unlicense",
"author": "Lamassu (https://lamassu.is)",
"dependencies": {

View file

@ -1,7 +1,7 @@
{
"files": {
"main.js": "/static/js/main.1d985014.chunk.js",
"main.js.map": "/static/js/main.1d985014.chunk.js.map",
"main.js": "/static/js/main.900511f9.chunk.js",
"main.js.map": "/static/js/main.900511f9.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.5b925903.js",
"runtime-main.js.map": "/static/js/runtime-main.5b925903.js.map",
"static/js/2.4b3df17b.chunk.js": "/static/js/2.4b3df17b.chunk.js",
@ -154,6 +154,6 @@
"entrypoints": [
"static/js/runtime-main.5b925903.js",
"static/js/2.4b3df17b.chunk.js",
"static/js/main.1d985014.chunk.js"
"static/js/main.900511f9.chunk.js"
]
}

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="robots" content="noindex"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Lamassu Admin</title></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root" class="root"></div><script>!function(e){function r(r){for(var n,a,l=r[0],i=r[1],f=r[2],c=0,s=[];c<l.length;c++)a=l[c],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var i=t[l];0!==o[i]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/";var l=this["webpackJsonplamassu-admin"]=this["webpackJsonplamassu-admin"]||[],i=l.push.bind(l);l.push=r,l=l.slice();for(var f=0;f<l.length;f++)r(l[f]);var p=i;t()}([])</script><script src="/static/js/2.4b3df17b.chunk.js"></script><script src="/static/js/main.1d985014.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="robots" content="noindex"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Lamassu Admin</title></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root" class="root"></div><script>!function(e){function r(r){for(var n,a,l=r[0],i=r[1],f=r[2],c=0,s=[];c<l.length;c++)a=l[c],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var i=t[l];0!==o[i]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/";var l=this["webpackJsonplamassu-admin"]=this["webpackJsonplamassu-admin"]||[],i=l.push.bind(l);l.push=r,l=l.slice();for(var f=0;f<l.length;f++)r(l[f]);var p=i;t()}([])</script><script src="/static/js/2.4b3df17b.chunk.js"></script><script src="/static/js/main.900511f9.chunk.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long