Source: wallet/walletcoinview.js

/*!
 * walletcoinview.js - wallet coin viewpoint object for hsd
 * Copyright (c) 2019, Boyma Fahnbulleh (MIT License).
 * https://github.com/handshake-org/hsd
 */

'use strict';

const assert = require('bsert');
const {BufferMap} = require('buffer-map');
const Paths = require('./paths');
const CoinView = require('../coins/coinview');

/**
 * Wallet Coin View
 * Represents a wallet, coin viewpoint: a snapshot of {@link Coins} objects
 * and the HD paths for their associated keys.
 * @alias module:wallet.WalletCoinView
 * @property {Object} map
 * @property {Object} paths
 * @property {UndoCoins} undo
 */

class WalletCoinView extends CoinView {
  /**
   * Create a wallet coin view.
   * @constructor
   */

  constructor() {
    super();
    this.paths = new BufferMap();
  }

  /**
   * Inject properties from coin view object.
   * @private
   * @param {CoinView} view
   */

  fromCoinView(view) {
    assert(view instanceof CoinView, 'View must be instance of CoinView');
    this.map = view.map;
    this.undo = view.undo;
    this.bits = view.bits;
    return this;
  }

  /**
   * Instantiate wallet coin view from coin view.
   * @param {CoinView} view
   * @returns {WalletCoinView}
   */

  static fromCoinView(view) {
    return new this().fromCoinView(view);
  }

  /**
   * Add paths to the collection.
   * @param {Hash} hash
   * @param {Paths} path
   * @returns {Paths|null}
   */

  addPaths(hash, paths) {
    this.paths.set(hash, paths);
    return paths;
  }

  /**
   * Get paths.
   * @param {Hash} hash
   * @returns {Paths} paths
   */

  getPaths(hash) {
    return this.paths.get(hash);
  }

  /**
   * Test whether the view has a paths entry.
   * @param {Hash} hash
   * @returns {Boolean}
   */

  hasPaths(hash) {
    return this.paths.has(hash);
  }

  /**
   * Ensure existence of paths object in the collection.
   * @param {Hash} hash
   * @returns {Coins}
   */

  ensurePaths(hash) {
    const paths = this.paths.get(hash);

    if (paths)
      return paths;

    return this.addPaths(hash, new Paths());
  }

  /**
   * Remove paths from the collection.
   * @param {Paths} paths
   * @returns {Paths|null}
   */

  removePaths(hash) {
    const paths = this.paths.get(hash);

    if (!paths)
      return null;

    this.paths.delete(hash);

    return paths;
  }

  /**
   * Add an HD path to the collection.
   * @param {Outpoint} prevout
   * @param {Path} path
   * @returns {Path|null}
   */

  addPath(prevout, path) {
    const {hash, index} = prevout;
    const paths = this.ensurePaths(hash);
    return paths.add(index, path);
  }

  /**
   * Get an HD path by prevout.
   * @param {Outpoint} prevout
   * @returns {Path|null}
   */

  getPath(prevout) {
    const {hash, index} = prevout;
    const paths = this.getPaths(hash);

    if (!paths)
      return null;

    return paths.get(index);
  }

  /**
   * Remove an HD path.
   * @param {Outpoint} prevout
   * @returns {Path|null}
   */

  removePath(prevout) {
    const {hash, index} = prevout;
    const paths = this.getPaths(hash);

    if (!paths)
      return null;

    return paths.remove(index);
  }

  /**
   * Test whether the view has a path by prevout.
   * @param {Outpoint} prevout
   * @returns {Boolean}
   */

  hasPath(prevout) {
    const {hash, index} = prevout;
    const paths = this.getPaths(hash);

    if (!paths)
      return false;

    return paths.has(index);
  }

  /**
   * Get a single path by input.
   * @param {Input} input
   * @returns {Path|null}
   */

  getPathFor(input) {
    return this.getPath(input.prevout);
  }
}

/*
 * Expose
 */

module.exports = WalletCoinView;