Merge branch 'dev' into fix/lam-298/custom_info_requests_flow

This commit is contained in:
André Sá 2022-01-27 11:13:41 +00:00
commit c5bf50b932
46 changed files with 441 additions and 149 deletions

View file

@ -14,13 +14,13 @@ function setup (dataDir) {
const config = buildConfig(auth)
common.writeFile(path.resolve(dataDir, coinRec.configFile), config)
const cmd = `/usr/local/bin/${coinRec.daemon} --data-dir ${dataDir} --config-file ${dataDir}/${coinRec.configFile}`
const walletCmd = `/usr/local/bin/${coinRec.wallet} --stagenet --rpc-login ${auth} --daemon-host 127.0.0.1 --daemon-port 38081 --trusted-daemon --daemon-login ${auth} --rpc-bind-port 38083 --wallet-dir ${dataDir}/wallets`
const walletCmd = `/usr/local/bin/${coinRec.wallet} --stagenet --rpc-login ${auth} --daemon-host 127.0.0.1 --daemon-port 18081 --trusted-daemon --daemon-login ${auth} --rpc-bind-port 18082 --wallet-dir ${dataDir}/wallets`
common.writeSupervisorConfig(coinRec, cmd, walletCmd)
}
function buildConfig (auth) {
return `rpc-login=${auth}
stagenet=1
stagenet=0
restricted-rpc=1
db-sync-mode=safe
out-peers=20

View file

@ -8,7 +8,7 @@ const E = require('../error')
const PENDING_INTERVAL_MS = 60 * T.minutes
const massageFields = ['direction', 'cryptoNetwork', 'bills', 'blacklisted', 'addressReuse', 'promoCodeApplied', 'failedWalletScore']
const massageFields = ['direction', 'cryptoNetwork', 'bills', 'blacklisted', 'addressReuse', 'promoCodeApplied', 'validWalletScore']
const massageUpdateFields = _.concat(massageFields, 'cryptoAtoms')
const massage = _.flow(_.omit(massageFields),

View file

@ -15,7 +15,6 @@ const cashInLow = require('./cash-in-low')
const PENDING_INTERVAL = '60 minutes'
const MAX_PENDING = 10
const WALLET_SCORE_THRESHOLD = 10
const TRANSACTION_STATES = `
case
@ -34,13 +33,13 @@ function post (machineTx, pi) {
const updatedTx = r.tx
let blacklisted = false
let addressReuse = false
let failedWalletScore = false
let walletScore = {}
return Promise.all([settingsLoader.loadLatest(), checkForBlacklisted(updatedTx), doesTxReuseAddress(updatedTx), doesWalletScoreFail(updatedTx, pi)])
.then(([{ config }, blacklistItems, isReusedAddress, walletScoreFailed]) => {
return Promise.all([settingsLoader.loadLatest(), checkForBlacklisted(updatedTx), doesTxReuseAddress(updatedTx), getWalletScore(updatedTx, pi)])
.then(([{ config }, blacklistItems, isReusedAddress, fetchedWalletScore]) => {
const rejectAddressReuse = configManager.getCompliance(config).rejectAddressReuse
failedWalletScore = walletScoreFailed
walletScore = fetchedWalletScore
if (_.some(it => it.address === updatedTx.toAddress)(blacklistItems)) {
blacklisted = true
@ -49,13 +48,14 @@ function post (machineTx, pi) {
notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, true)
addressReuse = true
}
return postProcess(r, pi, blacklisted, addressReuse, failedWalletScore)
return postProcess(r, pi, blacklisted, addressReuse, walletScore)
})
.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('failedWalletScore', failedWalletScore, tx))
.then(tx => _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid, tx))
.then(tx => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, tx))
})
}
@ -93,7 +93,7 @@ function checkForBlacklisted (tx) {
return Promise.resolve(false)
}
function postProcess (r, pi, isBlacklisted, addressReuse, failedWalletScore) {
function postProcess (r, pi, isBlacklisted, addressReuse, walletScore) {
if (addressReuse) {
return Promise.resolve({
operatorCompleted: true,
@ -108,10 +108,11 @@ function postProcess (r, pi, isBlacklisted, addressReuse, failedWalletScore) {
})
}
if (failedWalletScore) {
if (!_.isNil(walletScore) && !walletScore.isValid) {
return Promise.resolve({
walletScore: walletScore.score,
operatorCompleted: true,
error: 'Failed wallet score'
error: 'Ciphertrace score is above defined threshold'
})
}
@ -171,12 +172,17 @@ function doesTxReuseAddress (tx) {
return Promise.resolve(false)
}
function doesWalletScoreFail (tx, pi) {
function getWalletScore (tx, pi) {
if (!tx.fiat || tx.fiat.isZero()) {
return pi.rateWallet(tx.toAddress)
.then(res => res >= WALLET_SCORE_THRESHOLD)
return pi.rateWallet(tx.cryptoCode, tx.toAddress)
}
return Promise.resolve(false)
// Passthrough the previous result
return pi.isValidWalletScore(tx.walletScore)
.then(isValid => ({
address: tx.toAddress,
score: tx.walletScore,
isValid
}))
}
function monitorPending (settings) {

View file

@ -21,6 +21,8 @@ const MANUAL = 'manual'
const CASH_OUT_DISPENSE_READY = 'cash_out_dispense_ready'
const CONFIRMATION_CODE = 'sms_code'
const WALLET_SCORE_THRESHOLD = 9
module.exports = {
anonymousCustomer,
CASSETTE_MAX_CAPACITY,
@ -34,5 +36,6 @@ module.exports = {
CASH_OUT_DISPENSE_READY,
CONFIRMATION_CODE,
CASH_OUT_MINIMUM_AMOUNT_OF_CASSETTES,
CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES
CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES,
WALLET_SCORE_THRESHOLD
}

View file

@ -14,6 +14,7 @@ const SMS = 'sms'
const ID_VERIFIER = 'idVerifier'
const EMAIL = 'email'
const ZERO_CONF = 'zeroConf'
const WALLET_SCORING = 'wallet_scoring'
const ALL_ACCOUNTS = [
{ code: 'binanceus', display: 'Binance.us', class: TICKER, cryptos: binanceus.CRYPTO },
@ -50,7 +51,9 @@ const ALL_ACCOUNTS = [
{ code: 'mailgun', display: 'Mailgun', class: EMAIL },
{ code: 'none', display: 'None', class: ZERO_CONF, cryptos: [BTC, ZEC, LTC, DASH, BCH, ETH, XMR] },
{ code: 'blockcypher', display: 'Blockcypher', class: ZERO_CONF, cryptos: [BTC] },
{ code: 'mock-zero-conf', display: 'Mock 0-conf', class: ZERO_CONF, cryptos: ALL_CRYPTOS, dev: true }
{ code: 'mock-zero-conf', display: 'Mock 0-conf', class: ZERO_CONF, cryptos: ALL_CRYPTOS, dev: true },
{ code: 'ciphertrace', display: 'CipherTrace', class: WALLET_SCORING, cryptos: [BTC, ETH, LTC, BCH] },
{ code: 'mock-scoring', display: 'Mock scoring', class: WALLET_SCORING, cryptos: ALL_CRYPTOS, dev: true }
]
const devMode = require('minimist')(process.argv.slice(2)).dev

View file

@ -4,25 +4,20 @@ const _ = require('lodash/fp')
const userManagement = require('../userManagement')
const credentials = require('../../../../hardware-credentials')
const options = require('../../../../options')
const T = require('../../../../time')
const users = require('../../../../users')
const domain = options.hostname
const devMode = require('minimist')(process.argv.slice(2)).dev
const REMEMBER_ME_AGE = 90 * T.day
const rpID = devMode ? `localhost:3001` : domain
const expectedOrigin = `https://${rpID}`
const generateAttestationOptions = (session, options) => {
return users.getUserById(options.userId).then(user => {
return Promise.all([credentials.getHardwareCredentialsByUserId(user.id), user])
}).then(([userDevices, user]) => {
const options = simpleWebauthn.generateAttestationOptions({
const opts = simpleWebauthn.generateAttestationOptions({
rpName: 'Lamassu',
rpID,
rpID: options.domain,
userName: user.username,
userID: user.id,
timeout: 60000,
@ -40,11 +35,11 @@ const generateAttestationOptions = (session, options) => {
session.webauthn = {
attestation: {
challenge: options.challenge
challenge: opts.challenge
}
}
return options
return opts
})
}
@ -59,7 +54,7 @@ const generateAssertionOptions = (session, options) => {
transports: ['usb', 'ble', 'nfc', 'internal']
})),
userVerification: 'discouraged',
rpID
rpID: options.domain
})
session.webauthn = {
@ -82,8 +77,8 @@ const validateAttestation = (session, options) => {
simpleWebauthn.verifyAttestationResponse({
credential: options.attestationResponse,
expectedChallenge: `${expectedChallenge}`,
expectedOrigin,
expectedRPID: rpID
expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`,
expectedRPID: options.domain
})
])
.then(([user, verification]) => {
@ -142,8 +137,8 @@ const validateAssertion = (session, options) => {
verification = simpleWebauthn.verifyAssertionResponse({
credential: options.assertionResponse,
expectedChallenge: `${expectedChallenge}`,
expectedOrigin,
expectedRPID: rpID,
expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`,
expectedRPID: options.domain,
authenticator: convertedAuthenticator
})
} catch (err) {

View file

@ -3,25 +3,20 @@ const base64url = require('base64url')
const _ = require('lodash/fp')
const credentials = require('../../../../hardware-credentials')
const options = require('../../../../options')
const T = require('../../../../time')
const users = require('../../../../users')
const domain = options.hostname
const devMode = require('minimist')(process.argv.slice(2)).dev
const REMEMBER_ME_AGE = 90 * T.day
const rpID = devMode ? `localhost:3001` : domain
const expectedOrigin = `https://${rpID}`
const generateAttestationOptions = (session, options) => {
return users.getUserById(options.userId).then(user => {
return Promise.all([credentials.getHardwareCredentialsByUserId(user.id), user])
}).then(([userDevices, user]) => {
const opts = simpleWebauthn.generateAttestationOptions({
rpName: 'Lamassu',
rpID,
rpID: options.domain,
userName: user.username,
userID: user.id,
timeout: 60000,
@ -58,7 +53,7 @@ const generateAssertionOptions = (session, options) => {
transports: ['usb', 'ble', 'nfc', 'internal']
})),
userVerification: 'discouraged',
rpID
rpID: options.domain
})
session.webauthn = {
@ -81,8 +76,8 @@ const validateAttestation = (session, options) => {
simpleWebauthn.verifyAttestationResponse({
credential: options.attestationResponse,
expectedChallenge: `${expectedChallenge}`,
expectedOrigin,
expectedRPID: rpID
expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`,
expectedRPID: options.domain
})
])
.then(([user, verification]) => {
@ -141,8 +136,8 @@ const validateAssertion = (session, options) => {
verification = simpleWebauthn.verifyAssertionResponse({
credential: options.assertionResponse,
expectedChallenge: `${expectedChallenge}`,
expectedOrigin,
expectedRPID: rpID,
expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`,
expectedRPID: options.domain,
authenticator: convertedAuthenticator
})
} catch (err) {

View file

@ -3,23 +3,18 @@ const base64url = require('base64url')
const _ = require('lodash/fp')
const credentials = require('../../../../hardware-credentials')
const options = require('../../../../options')
const T = require('../../../../time')
const users = require('../../../../users')
const domain = options.hostname
const devMode = require('minimist')(process.argv.slice(2)).dev
const REMEMBER_ME_AGE = 90 * T.day
const rpID = devMode ? `localhost:3001` : domain
const expectedOrigin = `https://${rpID}`
const generateAttestationOptions = (session, options) => {
return credentials.getHardwareCredentials().then(devices => {
const opts = simpleWebauthn.generateAttestationOptions({
rpName: 'Lamassu',
rpID,
rpID: options.domain,
userName: `Usernameless user created at ${new Date().toISOString()}`,
userID: options.userId,
timeout: 60000,
@ -46,9 +41,9 @@ const generateAttestationOptions = (session, options) => {
})
}
const generateAssertionOptions = session => {
const generateAssertionOptions = (session, options) => {
return credentials.getHardwareCredentials().then(devices => {
const options = simpleWebauthn.generateAssertionOptions({
const opts = simpleWebauthn.generateAssertionOptions({
timeout: 60000,
allowCredentials: devices.map(dev => ({
id: dev.data.credentialID,
@ -56,15 +51,15 @@ const generateAssertionOptions = session => {
transports: ['usb', 'ble', 'nfc', 'internal']
})),
userVerification: 'discouraged',
rpID
rpID: options.domain
})
session.webauthn = {
assertion: {
challenge: options.challenge
challenge: opts.challenge
}
}
return options
return opts
})
}
@ -77,8 +72,8 @@ const validateAttestation = (session, options) => {
simpleWebauthn.verifyAttestationResponse({
credential: options.attestationResponse,
expectedChallenge: `${expectedChallenge}`,
expectedOrigin,
expectedRPID: rpID
expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`,
expectedRPID: options.domain
})
])
.then(([user, verification]) => {
@ -146,8 +141,8 @@ const validateAssertion = (session, options) => {
verification = simpleWebauthn.verifyAssertionResponse({
credential: options.assertionResponse,
expectedChallenge: `${expectedChallenge}`,
expectedOrigin,
expectedRPID: rpID,
expectedOrigin: `https://${options.domain}${devMode ? `:3001` : ``}`,
expectedRPID: options.domain,
authenticator: convertedAuthenticator
})
} catch (err) {

View file

@ -20,7 +20,7 @@ const txLogFields = ['txClass', 'id', 'deviceId', 'toAddress', 'cryptoAtoms',
'commissionPercentage', 'rawTickerPrice', 'receivedCryptoAtoms',
'discount', 'txHash', 'customerPhone', 'customerIdCardDataNumber',
'customerIdCardDataExpiration', 'customerIdCardData', 'customerName',
'customerFrontCameraPath', 'customerIdCardPhotoPath', 'expired', 'machineName']
'customerFrontCameraPath', 'customerIdCardPhotoPath', 'expired', 'machineName', 'walletScore']
const resolvers = {
Customer: {

View file

@ -6,11 +6,11 @@ const sessionManager = require('../../../session-manager')
const getAttestationQueryOptions = variables => {
switch (authentication.CHOSEN_STRATEGY) {
case 'FIDO2FA':
return { userId: variables.userID }
return { userId: variables.userID, domain: variables.domain }
case 'FIDOPasswordless':
return { userId: variables.userID }
return { userId: variables.userID, domain: variables.domain }
case 'FIDOUsernameless':
return { userId: variables.userID }
return { userId: variables.userID, domain: variables.domain }
default:
return {}
}
@ -19,11 +19,11 @@ const getAttestationQueryOptions = variables => {
const getAssertionQueryOptions = variables => {
switch (authentication.CHOSEN_STRATEGY) {
case 'FIDO2FA':
return { username: variables.username, password: variables.password }
return { username: variables.username, password: variables.password, domain: variables.domain }
case 'FIDOPasswordless':
return { username: variables.username }
return { username: variables.username, domain: variables.domain }
case 'FIDOUsernameless':
return {}
return { domain: variables.domain }
default:
return {}
}
@ -32,11 +32,11 @@ const getAssertionQueryOptions = variables => {
const getAttestationMutationOptions = variables => {
switch (authentication.CHOSEN_STRATEGY) {
case 'FIDO2FA':
return { userId: variables.userID, attestationResponse: variables.attestationResponse }
return { userId: variables.userID, attestationResponse: variables.attestationResponse, domain: variables.domain }
case 'FIDOPasswordless':
return { userId: variables.userID, attestationResponse: variables.attestationResponse }
return { userId: variables.userID, attestationResponse: variables.attestationResponse, domain: variables.domain }
case 'FIDOUsernameless':
return { userId: variables.userID, attestationResponse: variables.attestationResponse }
return { userId: variables.userID, attestationResponse: variables.attestationResponse, domain: variables.domain }
default:
return {}
}
@ -45,11 +45,11 @@ const getAttestationMutationOptions = variables => {
const getAssertionMutationOptions = variables => {
switch (authentication.CHOSEN_STRATEGY) {
case 'FIDO2FA':
return { username: variables.username, password: variables.password, rememberMe: variables.rememberMe, assertionResponse: variables.assertionResponse }
return { username: variables.username, password: variables.password, rememberMe: variables.rememberMe, assertionResponse: variables.assertionResponse, domain: variables.domain }
case 'FIDOPasswordless':
return { username: variables.username, rememberMe: variables.rememberMe, assertionResponse: variables.assertionResponse }
return { username: variables.username, rememberMe: variables.rememberMe, assertionResponse: variables.assertionResponse, domain: variables.domain }
case 'FIDOUsernameless':
return { assertionResponse: variables.assertionResponse }
return { assertionResponse: variables.assertionResponse, domain: variables.domain }
default:
return {}
}

View file

@ -47,6 +47,7 @@ const typeDef = gql`
txCustomerPhotoAt: Date
batched: Boolean
batchTime: Date
walletScore: Int
}
type Filter {

View file

@ -3,14 +3,14 @@ const authentication = require('../modules/authentication')
const getFIDOStrategyQueryTypes = () => {
switch (authentication.CHOSEN_STRATEGY) {
case 'FIDO2FA':
return `generateAttestationOptions(userID: ID!): JSONObject
generateAssertionOptions(username: String!, password: String!): JSONObject`
return `generateAttestationOptions(userID: ID!, domain: String!): JSONObject
generateAssertionOptions(username: String!, password: String!, domain: String!): JSONObject`
case 'FIDOPasswordless':
return `generateAttestationOptions(userID: ID!): JSONObject
generateAssertionOptions(username: String!): JSONObject`
return `generateAttestationOptions(userID: ID!, domain: String!): JSONObject
generateAssertionOptions(username: String!, domain: String!): JSONObject`
case 'FIDOUsernameless':
return `generateAttestationOptions(userID: ID!): JSONObject
generateAssertionOptions: JSONObject`
return `generateAttestationOptions(userID: ID!, domain: String!): JSONObject
generateAssertionOptions(domain: String!): JSONObject`
default:
return ``
}
@ -19,14 +19,14 @@ const getFIDOStrategyQueryTypes = () => {
const getFIDOStrategyMutationsTypes = () => {
switch (authentication.CHOSEN_STRATEGY) {
case 'FIDO2FA':
return `validateAttestation(userID: ID!, attestationResponse: JSONObject!): Boolean
validateAssertion(username: String!, password: String!, rememberMe: Boolean!, assertionResponse: JSONObject!): Boolean`
return `validateAttestation(userID: ID!, attestationResponse: JSONObject!, domain: String!): Boolean
validateAssertion(username: String!, password: String!, rememberMe: Boolean!, assertionResponse: JSONObject!, domain: String!): Boolean`
case 'FIDOPasswordless':
return `validateAttestation(userID: ID!, attestationResponse: JSONObject!): Boolean
validateAssertion(username: String!, rememberMe: Boolean!, assertionResponse: JSONObject!): Boolean`
return `validateAttestation(userID: ID!, attestationResponse: JSONObject!, domain: String!): Boolean
validateAssertion(username: String!, rememberMe: Boolean!, assertionResponse: JSONObject!, domain: String!): Boolean`
case 'FIDOUsernameless':
return `validateAttestation(userID: ID!, attestationResponse: JSONObject!): Boolean
validateAssertion(assertionResponse: JSONObject!): Boolean`
return `validateAttestation(userID: ID!, attestationResponse: JSONObject!, domain: String!): Boolean
validateAssertion(assertionResponse: JSONObject!, domain: String!): Boolean`
default:
return ``
}

View file

@ -21,7 +21,6 @@ router.use('*', async (req, res, next) => getOperatorId('authentication').then((
cookie: {
httpOnly: true,
secure: true,
domain: hostname,
sameSite: true,
maxAge: 60 * 10 * 1000 // 10 minutes
}

View file

@ -69,7 +69,7 @@ function batch (
AND ($12 is null or txs.to_address = $12)
AND ($13 is null or txs.txStatus = $13)
${excludeTestingCustomers ? `AND c.is_test_customer is false` : ``}
AND (fiat > 0)
AND (error IS NOT null OR fiat > 0)
ORDER BY created DESC limit $4 offset $5`
const cashOutSql = `SELECT 'cashOut' AS tx_class,

View file

@ -828,9 +828,12 @@ function plugins (settings, deviceId) {
.then(buildRates)
}
function rateWallet (address) {
return walletScoring.rateWallet(settings, address)
.then(res => res.rating)
function rateWallet (cryptoCode, address) {
return walletScoring.rateWallet(settings, cryptoCode, address)
}
function isValidWalletScore (score) {
return walletScoring.isValidWalletScore(settings, score)
}
return {
@ -861,7 +864,8 @@ function plugins (settings, deviceId) {
notifyOperator,
fetchCurrentConfigVersion,
pruneMachinesHeartbeat,
rateWallet
rateWallet,
isValidWalletScore
}
}

View file

@ -0,0 +1,47 @@
const axios = require('axios')
const _ = require('lodash/fp')
const NAME = 'CipherTrace'
const SUPPORTED_COINS = ['BTC', 'ETH', 'BCH', 'LTC', 'BNB', 'RSK']
function getClient(account) {
if (_.isNil(account) || !account.enabled) return null
const [ctv1, username, secretKey] = account.authorizationValue.split(':')
if (_.isNil(ctv1) || _.isNil(username) || _.isNil(secretKey)) {
throw new Error('Invalid CipherTrace configuration')
}
const apiVersion = ctv1.slice(-2)
const authHeader = {
"Authorization": account.authorizationValue
}
return { apiVersion, authHeader }
}
function rateWallet(account, cryptoCode, address) {
const client = getClient(account)
if (!_.includes(_.toUpper(cryptoCode), SUPPORTED_COINS) || _.isNil(client)) return Promise.resolve(null)
const { apiVersion, authHeader } = client
const threshold = account.scoreThreshold
return axios.get(`https://rest.ciphertrace.com/aml/${apiVersion}/${_.toLower(cryptoCode)}/risk?address=${address}`, {
headers: authHeader
})
.then(res => ({ address, score: res.data.risk, isValid: res.data.risk < threshold }))
}
function isValidWalletScore(account, score) {
const client = getClient(account)
if (_.isNil(client)) return Promise.resolve(true)
const threshold = account.scoreThreshold
return Promise.resolve(score < threshold)
}
module.exports = {
NAME,
rateWallet,
isValidWalletScore
}

View file

@ -1,15 +1,27 @@
const NAME = 'FakeScoring'
function rateWallet (account, address) {
const { WALLET_SCORE_THRESHOLD } = require('../../../constants')
function rateWallet (account, cryptoCode, address) {
return new Promise((resolve, _) => {
setTimeout(() => {
console.log('[WALLET-SCORING] DEBUG: Mock scoring rating wallet address %s', address)
return resolve({ address, rating: 5 })
return Promise.resolve(7)
.then(score => resolve({ address, score, isValid: score < WALLET_SCORE_THRESHOLD }))
}, 100)
})
}
function isValidWalletScore (account, score) {
return new Promise((resolve, _) => {
setTimeout(() => {
return resolve(score < WALLET_SCORE_THRESHOLD)
}, 100)
})
}
module.exports = {
NAME,
rateWallet
rateWallet,
isValidWalletScore
}

View file

@ -17,6 +17,8 @@ const configPath = utils.configPath(cryptoRec, blockchainDir)
const walletDir = path.resolve(utils.cryptoDir(cryptoRec, blockchainDir), 'wallets')
const unitScale = cryptoRec.unitScale
const SUPPORTS_BATCHING = false
function rpcConfig () {
try {
const config = jsonRpc.parseConf(configPath)
@ -186,9 +188,9 @@ function cryptoNetwork (account, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => {
switch(parseInt(rpcConfig().port, 10)) {
case 18083:
case 18082:
return 'main'
case 28083:
case 28082:
return 'test'
case 38083:
return 'stage'
@ -198,11 +200,17 @@ function cryptoNetwork (account, cryptoCode) {
})
}
function supportsBatching (cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => SUPPORTS_BATCHING)
}
module.exports = {
balance,
sendCoins,
newAddress,
getStatus,
newFunding,
cryptoNetwork
cryptoNetwork,
supportsBatching
}

View file

@ -3,25 +3,32 @@ const _ = require('lodash/fp')
const argv = require('minimist')(process.argv.slice(2))
function loadWalletScoring (settings) {
if (_.isNil(argv.mockScoring)) {
throw new Error('No wallet scoring API set!')
}
const pluginCode = argv.mockScoring ? 'mock-scoring' : ''
const pluginCode = argv.mockScoring ? 'mock-scoring' : 'ciphertrace'
const plugin = ph.load(ph.WALLET_SCORING, pluginCode)
const account = settings.accounts[pluginCode]
return { plugin, account }
}
function rateWallet (settings, address) {
function rateWallet (settings, cryptoCode, address) {
return Promise.resolve()
.then(() => {
const { plugin, account } = loadWalletScoring(settings)
return plugin.rateWallet(account, address)
return plugin.rateWallet(account, cryptoCode, address)
})
}
function isValidWalletScore (settings, score) {
return Promise.resolve()
.then(() => {
const { plugin, account } = loadWalletScoring(settings)
return plugin.isValidWalletScore(account, score)
})
}
module.exports = {
rateWallet
rateWallet,
isValidWalletScore
}