<commit_before>import { isValidBitcoinAddress } from '../../utils/';
import { decimalToInteger, convertCurrency } from '../../utils/currency';
import { getWallet } from '../../utils/modalManager';
import app from '../../app';
import BaseModel from '../BaseModel';

class Spend extends BaseModel {
  url() {
    return app.getServerUrl('wallet/spend/');
  }

  defaults() {
    return {
      feeLevel: 'NORMAL',
      memo: '',
    };
  }

  get feeLevels() {
    return [
      'PRIORITY',
      'NORMAL',
      'ECONOMIC',
    ];
  }

  get amountInBitcoin() {
    let btcAmount = 0;
    const amount = this.get('amount');

    if (typeof amount === 'number') {
      btcAmount = convertCurrency(amount, this.get('currency'), 'BTC');
    }

    return btcAmount;
  }

  validate(attrs) {
    const errObj = {};
    const addError = (fieldName, error) => {
      errObj[fieldName] = errObj[fieldName] || [];
      errObj[fieldName].push(error);
    };

    if (!attrs.address) {
      addError('address', app.polyglot.t('spendModelErrors.provideAddress'));
    } else if (!isValidBitcoinAddress(attrs.address)) {
      addError('address', app.polyglot.t('spendModelErrors.invalidAddress'));
    }

    if (typeof attrs.amount !== 'number') {
      addError('amount', app.polyglot.t('spendModelErrors.provideAmountNumber'));
    } else if (attrs.amount <= 0) {
      addError('amount', app.polyglot.t('spendModelErrors.amountGreaterThanZero'));
    } else if (this.amountInBitcoin >= app.walletBalance.get('confirmed')) {
      addError('amount', app.polyglot.t('spendModelErrors.insufficientFunds'));
    }

    if (this.feeLevels.indexOf(attrs.feeLevel) === -1) {
      addError('feeLevel', `The fee level must be one of [${this.feeLevels}].`);
    }

    if (attrs.memo && typeof attrs.memo !== 'string') {
      addError('memo', 'If provided, the memo should be a string.');
    }

    if (!attrs.currency) {
      addError('currency', 'Please provide a currency.');
    }

    if (Object.keys(errObj).length) return errObj;

    return undefined;
  }

  sync(method, model, options) {
    options.attrs = options.attrs || this.toJSON();

    if (method === 'create' || method === 'update') {
      let amount = options.attrs.amount;

      if (options.attrs.currency !== 'BTC') {
        amount = this.amountInBitcoin;
      }
<commit_msg>factoring unconfirmed funds when decided if spend is possible<commit_after>import { isValidBitcoinAddress } from '../../utils/';
import { decimalToInteger, convertCurrency } from '../../utils/currency';
import { getWallet } from '../../utils/modalManager';
import app from '../../app';
import BaseModel from '../BaseModel';

class Spend extends BaseModel {
  url() {
    return app.getServerUrl('wallet/spend/');
  }

  defaults() {
    return {
      feeLevel: 'NORMAL',
      memo: '',
    };
  }

  get feeLevels() {
    return [
      'PRIORITY',
      'NORMAL',
      'ECONOMIC',
    ];
  }

  get amountInBitcoin() {
    let btcAmount = 0;
    const amount = this.get('amount');

    if (typeof amount === 'number') {
      btcAmount = convertCurrency(amount, this.get('currency'), 'BTC');
    }

    return btcAmount;
  }

  validate(attrs) {
    const errObj = {};
    const addError = (fieldName, error) => {
      errObj[fieldName] = errObj[fieldName] || [];
      errObj[fieldName].push(error);
    };

    if (!attrs.address) {
      addError('address', app.polyglot.t('spendModelErrors.provideAddress'));
    } else if (!isValidBitcoinAddress(attrs.address)) {
      addError('address', app.polyglot.t('spendModelErrors.invalidAddress'));
    }

    if (typeof attrs.amount !== 'number') {
      addError('amount', app.polyglot.t('spendModelErrors.provideAmountNumber'));
    } else if (attrs.amount <= 0) {
      addError('amount', app.polyglot.t('spendModelErrors.amountGreaterThanZero'));
    } else if (this.amountInBitcoin >=
      app.walletBalance.get('confirmed') + app.walletBalance.get('unconfirmed')) {
      addError('amount', app.polyglot.t('spendModelErrors.insufficientFunds'));
    }

    if (this.feeLevels.indexOf(attrs.feeLevel) === -1) {
      addError('feeLevel', `The fee level must be one of [${this.feeLevels}].`);
    }

    if (attrs.memo && typeof attrs.memo !== 'string') {
      addError('memo', 'If provided, the memo should be a string.');
    }

    if (!attrs.currency) {
      addError('currency', 'Please provide a currency.');
    }

    if (Object.keys(errObj).length) return errObj;

    return undefined;
  }

  sync(method, model, options) {
    options.attrs = options.attrs || this.toJSON();

    if (method === 'create' || method === 'update') {
      let amount = options.attrs.amount;

      if (options.attrs.currency !== 'BTC') {
        amount = this.amountInBitcoin;
      }

{'fraction_non_alphanumeric': 0.16795649445722652, 'fraction_numerical': 0.0012549675800041832, 'mean_word_length': 3.0354430379746837, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '6168544', 'n_tokens_mistral': 1524, 'n_tokens_neox': 1513, 'n_words': 313}