<commit_before>const _ = require('lodash/fp')
const mem = require('mem')
const hkdf = require('futoin-hkdf')

const configManager = require('./config-manager')
const pify = require('pify')
const fs = pify(require('fs'))

const mnemonicHelpers = require('./mnemonic-helpers')
const options = require('./options')
const ph = require('./plugin-helper')
const layer2 = require('./layer2')

const FETCH_INTERVAL = 5000
const INSUFFICIENT_FUNDS_CODE = 570
const INSUFFICIENT_FUNDS_NAME = 'InsufficientFunds'
const ZERO_CONF_EXPIRATION = 60000

function httpError (msg, code) {
  const err = new Error(msg)
  err.name = 'HTTPError'
  err.code = code || 500

  return err
}

function computeSeed (masterSeed) {
  return hkdf(masterSeed, 32, {salt: 'lamassu-server-salt', info: 'wallet-seed'})
}

function fetchWallet (settings, cryptoCode) {
  return fs.readFile(options.mnemonicPath, 'utf8')
    .then(mnemonic => {
      const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic)
      const plugin = configManager.cryptoScoped(cryptoCode, settings.config).wallet
      const wallet = ph.load(ph.WALLET, plugin)
      const rawAccount = settings.accounts[plugin]
      const account = _.set('seed', computeSeed(masterSeed), rawAccount)
      if (_.isFunction(wallet.run)) wallet.run(account)

      return { wallet, account }
    })
}

const lastBalance = {}

function _balance (settings, cryptoCode) {
  return fetchWallet(settings, cryptoCode)
    .then(r => r.wallet.balance(r.account, cryptoCode))
    .then(balance => ({ balance, timestamp: Date.now() }))
    .then(r => {
      lastBalance[cryptoCode] = r
      return r
    })
    .catch(err => {
      console.error(err)
      return lastBalance[cryptoCode]
    })
}

function sendCoins (settings, toAddress, cryptoAtoms, cryptoCode) {
  return fetchWallet(settings, cryptoCode)
    .then(r => {
      return r.wallet.sendCoins(r.account, toAddress, cryptoAtoms, cryptoCode)
        .then(res => {
          mem.clear(module.exports.balance)
          return res
        })
    })
    .catch(err => {
      if (err.name === INSUFFICIENT_FUNDS_NAME) {
        throw httpError(INSUFFICIENT_FUNDS_NAME, INSUFFICIENT_FUNDS_CODE)
      }

      throw err
    })
}

function newAddress (settings, info) {
  const walletAddressPromise = fetchWallet(settings, info.cryptoCode)
    .then(r => r.wallet.newAddress(r.account, info))

  return Promise.all([
    walletAddressPromise,
    layer2.newAddress(settings, info)
  ])
    .then(([toAddress, layer2Address]) => ({
      toAddress,
      layer2Address
    }))
}

function newFunding (settings, cryptoCode, address) {
  return fetchWallet(settings, cryptoCode)
    .then(r => {
      const wallet = r.wallet
      const account = r.account

      return wallet.newFunding(account, cryptoCode)
    })
}

function mergeStatus (a, b) {
  if (!a) return b
  if (!b) return a

  return { receivedCryptoAtoms: a.receivedCryptoAtoms, status: mergeStatusMode(a.status, b.status) }
}

function mergeStatusMode (a, b) {
  const cleared = ['authorized', 'confirmed', 'instant']
  if (_.includes(a, cleared)) return a
  if (_.includes(b, cleared)) return b

  if (a === 'published') return a
  if (b === 'published') return b

  if (a === 'rejected') return a
  if (b === 'rejected') return b

  return 'notSeen'
}

function getWalletStatus (settings, tx) {
  const fudgeFactorEnabled = configManager.unscoped(settings.config).fudgeFactor
  const fudgeFactor = fudgeFactorEnabled ? 10 : 0

  const walletStatusPromise = fetchWallet(settings, tx.cryptoCode)
    .then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms.minus(fudgeFactor), tx.cryptoCode))

  return Promise.all([
    walletStatusPromise,
    layer2.getStatus(settings, tx)
  ])
    .then(([walletStatus, layer2Status]) => {
      return mergeStatus(walletStatus, layer2Status)
    })
}
<commit_msg>fix: rename fudge factor and change value<commit_after>const _ = require('lodash/fp')
const mem = require('mem')
const hkdf = require('futoin-hkdf')

const configManager = require('./config-manager')
const pify = require('pify')
const fs = pify(require('fs'))

const mnemonicHelpers = require('./mnemonic-helpers')
const options = require('./options')
const ph = require('./plugin-helper')
const layer2 = require('./layer2')

const FETCH_INTERVAL = 5000
const INSUFFICIENT_FUNDS_CODE = 570
const INSUFFICIENT_FUNDS_NAME = 'InsufficientFunds'
const ZERO_CONF_EXPIRATION = 60000

function httpError (msg, code) {
  const err = new Error(msg)
  err.name = 'HTTPError'
  err.code = code || 500

  return err
}

function computeSeed (masterSeed) {
  return hkdf(masterSeed, 32, {salt: 'lamassu-server-salt', info: 'wallet-seed'})
}

function fetchWallet (settings, cryptoCode) {
  return fs.readFile(options.mnemonicPath, 'utf8')
    .then(mnemonic => {
      const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic)
      const plugin = configManager.cryptoScoped(cryptoCode, settings.config).wallet
      const wallet = ph.load(ph.WALLET, plugin)
      const rawAccount = settings.accounts[plugin]
      const account = _.set('seed', computeSeed(masterSeed), rawAccount)
      if (_.isFunction(wallet.run)) wallet.run(account)

      return { wallet, account }
    })
}

const lastBalance = {}

function _balance (settings, cryptoCode) {
  return fetchWallet(settings, cryptoCode)
    .then(r => r.wallet.balance(r.account, cryptoCode))
    .then(balance => ({ balance, timestamp: Date.now() }))
    .then(r => {
      lastBalance[cryptoCode] = r
      return r
    })
    .catch(err => {
      console.error(err)
      return lastBalance[cryptoCode]
    })
}

function sendCoins (settings, toAddress, cryptoAtoms, cryptoCode) {
  return fetchWallet(settings, cryptoCode)
    .then(r => {
      return r.wallet.sendCoins(r.account, toAddress, cryptoAtoms, cryptoCode)
        .then(res => {
          mem.clear(module.exports.balance)
          return res
        })
    })
    .catch(err => {
      if (err.name === INSUFFICIENT_FUNDS_NAME) {
        throw httpError(INSUFFICIENT_FUNDS_NAME, INSUFFICIENT_FUNDS_CODE)
      }

      throw err
    })
}

function newAddress (settings, info) {
  const walletAddressPromise = fetchWallet(settings, info.cryptoCode)
    .then(r => r.wallet.newAddress(r.account, info))

  return Promise.all([
    walletAddressPromise,
    layer2.newAddress(settings, info)
  ])
    .then(([toAddress, layer2Address]) => ({
      toAddress,
      layer2Address
    }))
}

function newFunding (settings, cryptoCode, address) {
  return fetchWallet(settings, cryptoCode)
    .then(r => {
      const wallet = r.wallet
      const account = r.account

      return wallet.newFunding(account, cryptoCode)
    })
}

function mergeStatus (a, b) {
  if (!a) return b
  if (!b) return a

  return { receivedCryptoAtoms: a.receivedCryptoAtoms, status: mergeStatusMode(a.status, b.status) }
}

function mergeStatusMode (a, b) {
  const cleared = ['authorized', 'confirmed', 'instant']
  if (_.includes(a, cleared)) return a
  if (_.includes(b, cleared)) return b

  if (a === 'published') return a
  if (b === 'published') return b

  if (a === 'rejected') return a
  if (b === 'rejected') return b

  return 'notSeen'
}

function getWalletStatus (settings, tx) {
  const fudgeFactorEnabled = configManager.unscoped(settings.config).fudgeFactorActive
  const fudgeFactor = fudgeFactorEnabled ? 100 : 0

  const walletStatusPromise = fetchWallet(settings, tx.cryptoCode)
    .then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms.minus(fudgeFactor), tx.cryptoCode))

  return Promise.all([
    walletStatusPromise,
    layer2.getStatus(settings, tx)
  ])
    .then(([walletStatus, layer2Status]) => {
      return mergeStatus(walletStatus, layer2Status)
    })
}

{'fraction_non_alphanumeric': 0.12901147055032866, 'fraction_numerical': 0.007604072689779611, 'mean_word_length': 3.746177370030581, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6559964', 'n_tokens_mistral': 2560, 'n_tokens_neox': 2519, 'n_words': 566}