310 lines
5.8 KiB
JavaScript
310 lines
5.8 KiB
JavaScript
/*!
|
|
* pathinfo.js - pathinfo object for bcoin
|
|
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
|
* https://github.com/bcoin-org/bcoin
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
var utils = require('../utils/utils');
|
|
|
|
/**
|
|
* Path Info
|
|
* @constructor
|
|
* @param {WalletDB} db
|
|
* @param {WalletID} wid
|
|
* @param {TX} tx
|
|
* @param {Object} table
|
|
*/
|
|
|
|
function PathInfo(wallet, tx, paths) {
|
|
if (!(this instanceof PathInfo))
|
|
return new PathInfo(wallet, tx, paths);
|
|
|
|
// All relevant Accounts for
|
|
// inputs and outputs (for database indexing).
|
|
this.accounts = [];
|
|
|
|
// All output paths (for deriving during sync).
|
|
this.paths = [];
|
|
|
|
// Wallet
|
|
this.wallet = wallet;
|
|
|
|
// Wallet ID
|
|
this.wid = wallet.wid;
|
|
|
|
// Wallet Label
|
|
this.id = wallet.id;
|
|
|
|
// Map of address hashes->paths.
|
|
this.pathMap = {};
|
|
|
|
// Current transaction.
|
|
this.tx = null;
|
|
|
|
// Wallet-specific details cache.
|
|
this._details = null;
|
|
this._json = null;
|
|
|
|
if (tx)
|
|
this.fromTX(tx, paths);
|
|
}
|
|
|
|
/**
|
|
* Instantiate path info from a transaction.
|
|
* @private
|
|
* @param {TX} tx
|
|
* @param {Object} table
|
|
* @returns {PathInfo}
|
|
*/
|
|
|
|
PathInfo.prototype.fromTX = function fromTX(tx, paths) {
|
|
var uniq = {};
|
|
var i, hashes, hash, path;
|
|
|
|
this.tx = tx;
|
|
|
|
for (i = 0; i < paths.length; i++) {
|
|
path = paths[i];
|
|
|
|
this.pathMap[path.hash] = path;
|
|
|
|
if (!uniq[path.account]) {
|
|
uniq[path.account] = true;
|
|
this.accounts.push(path.account);
|
|
}
|
|
}
|
|
|
|
hashes = tx.getOutputHashes('hex');
|
|
|
|
for (i = 0; i < hashes.length; i++) {
|
|
hash = hashes[i];
|
|
path = this.pathMap[hash];
|
|
if (path)
|
|
this.paths.push(path);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Instantiate path info from a transaction.
|
|
* @param {WalletDB} db
|
|
* @param {WalletID} wid
|
|
* @param {TX} tx
|
|
* @param {Object} table
|
|
* @returns {PathInfo}
|
|
*/
|
|
|
|
PathInfo.fromTX = function fromTX(wallet, tx, paths) {
|
|
return new PathInfo(wallet).fromTX(tx, paths);
|
|
};
|
|
|
|
/**
|
|
* Test whether the map has paths
|
|
* for a given address hash.
|
|
* @param {Hash} hash
|
|
* @returns {Boolean}
|
|
*/
|
|
|
|
PathInfo.prototype.hasPath = function hasPath(hash) {
|
|
if (!hash)
|
|
return false;
|
|
|
|
return this.pathMap[hash] != null;
|
|
};
|
|
|
|
/**
|
|
* Get path for a given address hash.
|
|
* @param {Hash} hash
|
|
* @returns {Path}
|
|
*/
|
|
|
|
PathInfo.prototype.getPath = function getPath(hash) {
|
|
if (!hash)
|
|
return;
|
|
|
|
return this.pathMap[hash];
|
|
};
|
|
|
|
/**
|
|
* Convert path info to transaction details.
|
|
* @returns {Details}
|
|
*/
|
|
|
|
PathInfo.prototype.toDetails = function toDetails() {
|
|
var details = this._details;
|
|
|
|
if (!details) {
|
|
details = new Details(this);
|
|
this._details = details;
|
|
}
|
|
|
|
return details;
|
|
};
|
|
|
|
/**
|
|
* Convert path info to JSON details (caches json).
|
|
* @returns {Object}
|
|
*/
|
|
|
|
PathInfo.prototype.toJSON = function toJSON() {
|
|
var json = this._json;
|
|
|
|
if (!json) {
|
|
json = this.toDetails().toJSON();
|
|
this._json = json;
|
|
}
|
|
|
|
return json;
|
|
};
|
|
|
|
/**
|
|
* Transaction Details
|
|
* @constructor
|
|
* @param {PathInfo} info
|
|
*/
|
|
|
|
function Details(info) {
|
|
if (!(this instanceof Details))
|
|
return new Details(info);
|
|
|
|
this.db = info.wallet.db;
|
|
this.network = this.db.network;
|
|
this.wid = info.wid;
|
|
this.id = info.id;
|
|
this.hash = info.tx.hash('hex');
|
|
this.height = info.tx.height;
|
|
this.block = info.tx.block;
|
|
this.index = info.tx.index;
|
|
this.confirmations = info.tx.getConfirmations(this.db.height);
|
|
this.fee = info.tx.getFee();
|
|
this.ts = info.tx.ts;
|
|
this.ps = info.tx.ps;
|
|
this.tx = info.tx;
|
|
this.inputs = [];
|
|
this.outputs = [];
|
|
|
|
this.init(info.pathMap);
|
|
}
|
|
|
|
/**
|
|
* Initialize transactions details
|
|
* by pushing on mapped members.
|
|
* @private
|
|
* @param {Object} table
|
|
*/
|
|
|
|
Details.prototype.init = function init(map) {
|
|
this._insert(this.tx.inputs, true, this.inputs, map);
|
|
this._insert(this.tx.outputs, false, this.outputs, map);
|
|
};
|
|
|
|
/**
|
|
* Insert members in the input or output vector.
|
|
* @private
|
|
* @param {Input[]|Output[]} vector
|
|
* @param {Array} target
|
|
* @param {Object} table
|
|
*/
|
|
|
|
Details.prototype._insert = function _insert(vector, input, target, map) {
|
|
var i, io, address, hash, path, member;
|
|
|
|
for (i = 0; i < vector.length; i++) {
|
|
io = vector[i];
|
|
member = new DetailsMember();
|
|
|
|
if (input) {
|
|
if (io.coin)
|
|
member.value = io.coin.value;
|
|
} else {
|
|
member.value = io.value;
|
|
}
|
|
|
|
address = io.getAddress();
|
|
|
|
if (address) {
|
|
member.address = address;
|
|
|
|
hash = address.getHash('hex');
|
|
path = map[hash];
|
|
|
|
if (path)
|
|
member.path = path;
|
|
}
|
|
|
|
target.push(member);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Convert details to a more json-friendly object.
|
|
* @returns {Object}
|
|
*/
|
|
|
|
Details.prototype.toJSON = function toJSON() {
|
|
var self = this;
|
|
return {
|
|
wid: this.wid,
|
|
id: this.id,
|
|
hash: utils.revHex(this.hash),
|
|
height: this.height,
|
|
block: this.block ? utils.revHex(this.block) : null,
|
|
ts: this.ts,
|
|
ps: this.ps,
|
|
index: this.index,
|
|
fee: utils.btc(this.fee),
|
|
confirmations: this.confirmations,
|
|
inputs: this.inputs.map(function(input) {
|
|
return input.toJSON(self.network);
|
|
}),
|
|
outputs: this.outputs.map(function(output) {
|
|
return output.toJSON(self.network);
|
|
}),
|
|
tx: this.tx.toRaw().toString('hex')
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Transaction Details Member
|
|
* @constructor
|
|
* @property {Number} value
|
|
* @property {Address} address
|
|
* @property {Path} path
|
|
*/
|
|
|
|
function DetailsMember() {
|
|
if (!(this instanceof DetailsMember))
|
|
return new DetailsMember();
|
|
|
|
this.value = 0;
|
|
this.address = null;
|
|
this.path = null;
|
|
}
|
|
|
|
/**
|
|
* Convert the member to a more json-friendly object.
|
|
* @param {Network} network
|
|
* @returns {Object}
|
|
*/
|
|
|
|
DetailsMember.prototype.toJSON = function toJSON(network) {
|
|
return {
|
|
value: utils.btc(this.value),
|
|
address: this.address
|
|
? this.address.toBase58(network)
|
|
: null,
|
|
path: this.path
|
|
? this.path.toJSON()
|
|
: null
|
|
};
|
|
};
|
|
|
|
/*
|
|
* Expose
|
|
*/
|
|
|
|
module.exports = PathInfo;
|