wallet: classify.
This commit is contained in:
parent
9240d2f827
commit
f313ca166d
@ -908,7 +908,7 @@ class ChainDB {
|
|||||||
return this.db.values({
|
return this.db.values({
|
||||||
gte: layout.e(encoding.ZERO_HASH),
|
gte: layout.e(encoding.ZERO_HASH),
|
||||||
lte: layout.e(encoding.MAX_HASH),
|
lte: layout.e(encoding.MAX_HASH),
|
||||||
parse: value => ChainEntry.fromRaw(value)
|
parse: data => ChainEntry.fromRaw(data)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,32 +17,22 @@ const HD = require('../hd/hd');
|
|||||||
const {encoding} = bio;
|
const {encoding} = bio;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Account
|
||||||
* Represents a BIP44 Account belonging to a {@link Wallet}.
|
* Represents a BIP44 Account belonging to a {@link Wallet}.
|
||||||
* Note that this object does not enforce locks. Any method
|
* Note that this object does not enforce locks. Any method
|
||||||
* that does a write is internal API only and will lead
|
* that does a write is internal API only and will lead
|
||||||
* to race conditions if used elsewhere.
|
* to race conditions if used elsewhere.
|
||||||
* @alias module:wallet.Account
|
* @alias module:wallet.Account
|
||||||
* @constructor
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {HDPublicKey} options.accountKey
|
|
||||||
* @param {Boolean?} options.witness - Whether to use witness programs.
|
|
||||||
* @param {Number} options.accountIndex - The BIP44 account index.
|
|
||||||
* @param {Number?} options.receiveDepth - The index of the _next_ receiving
|
|
||||||
* address.
|
|
||||||
* @param {Number?} options.changeDepth - The index of the _next_ change
|
|
||||||
* address.
|
|
||||||
* @param {String?} options.type - Type of wallet (pubkeyhash, multisig)
|
|
||||||
* (default=pubkeyhash).
|
|
||||||
* @param {Number?} options.m - `m` value for multisig.
|
|
||||||
* @param {Number?} options.n - `n` value for multisig.
|
|
||||||
* @param {String?} options.wid - Wallet ID
|
|
||||||
* @param {String?} options.name - Account name
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Account(wdb, options) {
|
class Account {
|
||||||
if (!(this instanceof Account))
|
/**
|
||||||
return new Account(wdb, options);
|
* Create an account.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(wdb, options) {
|
||||||
assert(wdb, 'Database is required.');
|
assert(wdb, 'Database is required.');
|
||||||
|
|
||||||
this.wdb = wdb;
|
this.wdb = wdb;
|
||||||
@ -69,34 +59,13 @@ function Account(wdb, options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Account types.
|
|
||||||
* @enum {Number}
|
|
||||||
* @default
|
|
||||||
*/
|
|
||||||
|
|
||||||
Account.types = {
|
|
||||||
PUBKEYHASH: 0,
|
|
||||||
MULTISIG: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Account types by value.
|
|
||||||
* @const {RevMap}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Account.typesByVal = {
|
|
||||||
0: 'pubkeyhash',
|
|
||||||
1: 'multisig'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(options, 'Options are required.');
|
assert(options, 'Options are required.');
|
||||||
assert((options.wid >>> 0) === options.wid);
|
assert((options.wid >>> 0) === options.wid);
|
||||||
assert(common.isName(options.id), 'Bad Wallet ID.');
|
assert(common.isName(options.id), 'Bad Wallet ID.');
|
||||||
@ -193,7 +162,7 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate account from options.
|
* Instantiate account from options.
|
||||||
@ -202,16 +171,9 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Account}
|
* @returns {Account}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.fromOptions = function fromOptions(wdb, options) {
|
static fromOptions(wdb, options) {
|
||||||
return new Account(wdb).fromOptions(options);
|
return new this(wdb).fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Default address lookahead.
|
|
||||||
* @const {Number}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Account.MAX_LOOKAHEAD = 40;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to intialize the account (generating
|
* Attempt to intialize the account (generating
|
||||||
@ -221,7 +183,7 @@ Account.MAX_LOOKAHEAD = 40;
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.init = async function init(b) {
|
async init(b) {
|
||||||
// Waiting for more keys.
|
// Waiting for more keys.
|
||||||
if (this.keys.length !== this.n - 1) {
|
if (this.keys.length !== this.n - 1) {
|
||||||
assert(!this.initialized);
|
assert(!this.initialized);
|
||||||
@ -236,7 +198,7 @@ Account.prototype.init = async function init(b) {
|
|||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
await this.initDepth(b);
|
await this.initDepth(b);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a public account key to the account (multisig).
|
* Add a public account key to the account (multisig).
|
||||||
@ -246,7 +208,7 @@ Account.prototype.init = async function init(b) {
|
|||||||
* @throws Error on non-hdkey/non-accountkey.
|
* @throws Error on non-hdkey/non-accountkey.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.pushKey = function pushKey(key) {
|
pushKey(key) {
|
||||||
if (typeof key === 'string')
|
if (typeof key === 'string')
|
||||||
key = HD.PublicKey.fromBase58(key, this.network);
|
key = HD.PublicKey.fromBase58(key, this.network);
|
||||||
|
|
||||||
@ -273,7 +235,7 @@ Account.prototype.pushKey = function pushKey(key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a public account key to the account (multisig).
|
* Remove a public account key to the account (multisig).
|
||||||
@ -283,7 +245,7 @@ Account.prototype.pushKey = function pushKey(key) {
|
|||||||
* @throws Error on non-hdkey/non-accountkey.
|
* @throws Error on non-hdkey/non-accountkey.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.spliceKey = function spliceKey(key) {
|
spliceKey(key) {
|
||||||
if (typeof key === 'string')
|
if (typeof key === 'string')
|
||||||
key = HD.PublicKey.fromBase58(key, this.network);
|
key = HD.PublicKey.fromBase58(key, this.network);
|
||||||
|
|
||||||
@ -300,7 +262,7 @@ Account.prototype.spliceKey = function spliceKey(key) {
|
|||||||
throw new Error('Cannot remove key.');
|
throw new Error('Cannot remove key.');
|
||||||
|
|
||||||
return binary.remove(this.keys, key, cmp);
|
return binary.remove(this.keys, key, cmp);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a public account key to the account (multisig).
|
* Add a public account key to the account (multisig).
|
||||||
@ -309,7 +271,7 @@ Account.prototype.spliceKey = function spliceKey(key) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.addSharedKey = async function addSharedKey(b, key) {
|
async addSharedKey(b, key) {
|
||||||
const result = this.pushKey(key);
|
const result = this.pushKey(key);
|
||||||
|
|
||||||
if (await this.hasDuplicate()) {
|
if (await this.hasDuplicate()) {
|
||||||
@ -321,7 +283,7 @@ Account.prototype.addSharedKey = async function addSharedKey(b, key) {
|
|||||||
await this.init(b);
|
await this.init(b);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure accounts are not sharing keys.
|
* Ensure accounts are not sharing keys.
|
||||||
@ -329,7 +291,7 @@ Account.prototype.addSharedKey = async function addSharedKey(b, key) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.hasDuplicate = async function hasDuplicate() {
|
async hasDuplicate() {
|
||||||
if (this.keys.length !== this.n - 1)
|
if (this.keys.length !== this.n - 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -337,7 +299,7 @@ Account.prototype.hasDuplicate = async function hasDuplicate() {
|
|||||||
const hash = ring.getScriptHash('hex');
|
const hash = ring.getScriptHash('hex');
|
||||||
|
|
||||||
return this.wdb.hasPath(this.wid, hash);
|
return this.wdb.hasPath(this.wid, hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a public account key from the account (multisig).
|
* Remove a public account key from the account (multisig).
|
||||||
@ -346,7 +308,7 @@ Account.prototype.hasDuplicate = async function hasDuplicate() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.removeSharedKey = function removeSharedKey(b, key) {
|
removeSharedKey(b, key) {
|
||||||
const result = this.spliceKey(key);
|
const result = this.spliceKey(key);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
@ -355,34 +317,34 @@ Account.prototype.removeSharedKey = function removeSharedKey(b, key) {
|
|||||||
this.save(b);
|
this.save(b);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new receiving address (increments receiveDepth).
|
* Create a new receiving address (increments receiveDepth).
|
||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.createReceive = function createReceive() {
|
createReceive() {
|
||||||
return this.createKey(0);
|
return this.createKey(0);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new change address (increments receiveDepth).
|
* Create a new change address (increments receiveDepth).
|
||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.createChange = function createChange() {
|
createChange() {
|
||||||
return this.createKey(1);
|
return this.createKey(1);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new change address (increments receiveDepth).
|
* Create a new change address (increments receiveDepth).
|
||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.createNested = function createNested() {
|
createNested() {
|
||||||
return this.createKey(2);
|
return this.createKey(2);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new address (increments depth).
|
* Create a new address (increments depth).
|
||||||
@ -390,7 +352,7 @@ Account.prototype.createNested = function createNested() {
|
|||||||
* @returns {Promise} - Returns {@link WalletKey}.
|
* @returns {Promise} - Returns {@link WalletKey}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.createKey = async function createKey(b, branch) {
|
async createKey(b, branch) {
|
||||||
let key, lookahead;
|
let key, lookahead;
|
||||||
|
|
||||||
switch (branch) {
|
switch (branch) {
|
||||||
@ -422,7 +384,7 @@ Account.prototype.createKey = async function createKey(b, branch) {
|
|||||||
this.save();
|
this.save();
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive a receiving address at `index`. Do not increment depth.
|
* Derive a receiving address at `index`. Do not increment depth.
|
||||||
@ -430,9 +392,9 @@ Account.prototype.createKey = async function createKey(b, branch) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.deriveReceive = function deriveReceive(index, master) {
|
deriveReceive(index, master) {
|
||||||
return this.deriveKey(0, index, master);
|
return this.deriveKey(0, index, master);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive a change address at `index`. Do not increment depth.
|
* Derive a change address at `index`. Do not increment depth.
|
||||||
@ -440,9 +402,9 @@ Account.prototype.deriveReceive = function deriveReceive(index, master) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.deriveChange = function deriveChange(index, master) {
|
deriveChange(index, master) {
|
||||||
return this.deriveKey(1, index, master);
|
return this.deriveKey(1, index, master);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive a nested address at `index`. Do not increment depth.
|
* Derive a nested address at `index`. Do not increment depth.
|
||||||
@ -450,12 +412,12 @@ Account.prototype.deriveChange = function deriveChange(index, master) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.deriveNested = function deriveNested(index, master) {
|
deriveNested(index, master) {
|
||||||
if (!this.witness)
|
if (!this.witness)
|
||||||
throw new Error('Cannot derive nested on non-witness account.');
|
throw new Error('Cannot derive nested on non-witness account.');
|
||||||
|
|
||||||
return this.deriveKey(2, index, master);
|
return this.deriveKey(2, index, master);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive an address from `path` object.
|
* Derive an address from `path` object.
|
||||||
@ -464,7 +426,7 @@ Account.prototype.deriveNested = function deriveNested(index, master) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.derivePath = function derivePath(path, master) {
|
derivePath(path, master) {
|
||||||
switch (path.keyType) {
|
switch (path.keyType) {
|
||||||
case Path.types.HD: {
|
case Path.types.HD: {
|
||||||
return this.deriveKey(path.branch, path.index, master);
|
return this.deriveKey(path.branch, path.index, master);
|
||||||
@ -489,7 +451,7 @@ Account.prototype.derivePath = function derivePath(path, master) {
|
|||||||
throw new Error('Bad key type.');
|
throw new Error('Bad key type.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive an address at `index`. Do not increment depth.
|
* Derive an address at `index`. Do not increment depth.
|
||||||
@ -498,7 +460,7 @@ Account.prototype.derivePath = function derivePath(path, master) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.deriveKey = function deriveKey(branch, index, master) {
|
deriveKey(branch, index, master) {
|
||||||
assert(typeof branch === 'number');
|
assert(typeof branch === 'number');
|
||||||
|
|
||||||
const keys = [];
|
const keys = [];
|
||||||
@ -531,7 +493,7 @@ Account.prototype.deriveKey = function deriveKey(branch, index, master) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ring;
|
return ring;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the account to the database. Necessary
|
* Save the account to the database. Necessary
|
||||||
@ -539,9 +501,9 @@ Account.prototype.deriveKey = function deriveKey(branch, index, master) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.save = function save(b) {
|
save(b) {
|
||||||
return this.wdb.saveAccount(b, this);
|
return this.wdb.saveAccount(b, this);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save addresses to path map.
|
* Save addresses to path map.
|
||||||
@ -549,9 +511,9 @@ Account.prototype.save = function save(b) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.saveKey = function saveKey(b, ring) {
|
saveKey(b, ring) {
|
||||||
return this.wdb.saveKey(b, this.wid, ring);
|
return this.wdb.saveKey(b, this.wid, ring);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save paths to path map.
|
* Save paths to path map.
|
||||||
@ -559,16 +521,16 @@ Account.prototype.saveKey = function saveKey(b, ring) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.savePath = function savePath(b, path) {
|
savePath(b, path) {
|
||||||
return this.wdb.savePath(b, this.wid, path);
|
return this.wdb.savePath(b, this.wid, path);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize address depths (including lookahead).
|
* Initialize address depths (including lookahead).
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.initDepth = async function initDepth(b) {
|
async initDepth(b) {
|
||||||
// Receive Address
|
// Receive Address
|
||||||
this.receiveDepth = 1;
|
this.receiveDepth = 1;
|
||||||
|
|
||||||
@ -596,7 +558,7 @@ Account.prototype.initDepth = async function initDepth(b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.save(b);
|
this.save(b);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate new lookahead addresses if necessary.
|
* Allocate new lookahead addresses if necessary.
|
||||||
@ -606,7 +568,7 @@ Account.prototype.initDepth = async function initDepth(b) {
|
|||||||
* @returns {Promise} - Returns {@link WalletKey}.
|
* @returns {Promise} - Returns {@link WalletKey}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.syncDepth = async function syncDepth(b, receive, change, nested) {
|
async syncDepth(b, receive, change, nested) {
|
||||||
let derived = false;
|
let derived = false;
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
@ -662,7 +624,7 @@ Account.prototype.syncDepth = async function syncDepth(b, receive, change, neste
|
|||||||
this.save(b);
|
this.save(b);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate new lookahead addresses.
|
* Allocate new lookahead addresses.
|
||||||
@ -670,7 +632,7 @@ Account.prototype.syncDepth = async function syncDepth(b, receive, change, neste
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.setLookahead = async function setLookahead(b, lookahead) {
|
async setLookahead(b, lookahead) {
|
||||||
if (lookahead === this.lookahead)
|
if (lookahead === this.lookahead)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -722,38 +684,38 @@ Account.prototype.setLookahead = async function setLookahead(b, lookahead) {
|
|||||||
|
|
||||||
this.lookahead = lookahead;
|
this.lookahead = lookahead;
|
||||||
this.save(b);
|
this.save(b);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current receive key.
|
* Get current receive key.
|
||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.receiveKey = function receiveKey() {
|
receiveKey() {
|
||||||
if (!this.initialized)
|
if (!this.initialized)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return this.deriveReceive(this.receiveDepth - 1);
|
return this.deriveReceive(this.receiveDepth - 1);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current change key.
|
* Get current change key.
|
||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.changeKey = function changeKey() {
|
changeKey() {
|
||||||
if (!this.initialized)
|
if (!this.initialized)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return this.deriveChange(this.changeDepth - 1);
|
return this.deriveChange(this.changeDepth - 1);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current nested key.
|
* Get current nested key.
|
||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.nestedKey = function nestedKey() {
|
nestedKey() {
|
||||||
if (!this.initialized)
|
if (!this.initialized)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -761,56 +723,56 @@ Account.prototype.nestedKey = function nestedKey() {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return this.deriveNested(this.nestedDepth - 1);
|
return this.deriveNested(this.nestedDepth - 1);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current receive address.
|
* Get current receive address.
|
||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.receiveAddress = function receiveAddress() {
|
receiveAddress() {
|
||||||
const key = this.receiveKey();
|
const key = this.receiveKey();
|
||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return key.getAddress();
|
return key.getAddress();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current change address.
|
* Get current change address.
|
||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.changeAddress = function changeAddress() {
|
changeAddress() {
|
||||||
const key = this.changeKey();
|
const key = this.changeKey();
|
||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return key.getAddress();
|
return key.getAddress();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current nested address.
|
* Get current nested address.
|
||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.nestedAddress = function nestedAddress() {
|
nestedAddress() {
|
||||||
const key = this.nestedKey();
|
const key = this.nestedKey();
|
||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return key.getAddress();
|
return key.getAddress();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the account to a more inspection-friendly object.
|
* Convert the account to a more inspection-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
const receive = this.receiveAddress();
|
const receive = this.receiveAddress();
|
||||||
const change = this.changeAddress();
|
const change = this.changeAddress();
|
||||||
const nested = this.nestedAddress();
|
const nested = this.nestedAddress();
|
||||||
@ -837,7 +799,7 @@ Account.prototype.inspect = function inspect() {
|
|||||||
accountKey: this.accountKey.toBase58(this.network),
|
accountKey: this.accountKey.toBase58(this.network),
|
||||||
keys: this.keys.map(key => key.toBase58(this.network))
|
keys: this.keys.map(key => key.toBase58(this.network))
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the account to an object suitable for
|
* Convert the account to an object suitable for
|
||||||
@ -845,7 +807,7 @@ Account.prototype.inspect = function inspect() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.toJSON = function toJSON(balance) {
|
toJSON(balance) {
|
||||||
const receive = this.receiveAddress();
|
const receive = this.receiveAddress();
|
||||||
const change = this.changeAddress();
|
const change = this.changeAddress();
|
||||||
const nested = this.nestedAddress();
|
const nested = this.nestedAddress();
|
||||||
@ -870,27 +832,27 @@ Account.prototype.toJSON = function toJSON(balance) {
|
|||||||
keys: this.keys.map(key => key.toBase58(this.network)),
|
keys: this.keys.map(key => key.toBase58(this.network)),
|
||||||
balance: balance ? balance.toJSON(true) : null
|
balance: balance ? balance.toJSON(true) : null
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate serialization size.
|
* Calculate serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
size += encoding.sizeVarString(this.name, 'ascii');
|
size += encoding.sizeVarString(this.name, 'ascii');
|
||||||
size += 105;
|
size += 105;
|
||||||
size += this.keys.length * 82;
|
size += this.keys.length * 82;
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the account.
|
* Serialize the account.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const bw = bio.write(size);
|
const bw = bio.write(size);
|
||||||
|
|
||||||
@ -912,7 +874,7 @@ Account.prototype.toRaw = function toRaw() {
|
|||||||
bw.writeBytes(key.toRaw(this.network));
|
bw.writeBytes(key.toRaw(this.network));
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -921,7 +883,7 @@ Account.prototype.toRaw = function toRaw() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = bio.read(data);
|
const br = bio.read(data);
|
||||||
|
|
||||||
this.name = br.readVarString('ascii');
|
this.name = br.readVarString('ascii');
|
||||||
@ -947,7 +909,7 @@ Account.prototype.fromRaw = function fromRaw(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a account from serialized data.
|
* Instantiate a account from serialized data.
|
||||||
@ -956,9 +918,9 @@ Account.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Account}
|
* @returns {Account}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.fromRaw = function fromRaw(wdb, data) {
|
static fromRaw(wdb, data) {
|
||||||
return new Account(wdb).fromRaw(data);
|
return new this(wdb).fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object to see if it is a Account.
|
* Test an object to see if it is a Account.
|
||||||
@ -966,10 +928,39 @@ Account.fromRaw = function fromRaw(wdb, data) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.isAccount = function isAccount(obj) {
|
static isAccount(obj) {
|
||||||
return obj instanceof Account;
|
return obj instanceof Account;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Account types.
|
||||||
|
* @enum {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
Account.types = {
|
||||||
|
PUBKEYHASH: 0,
|
||||||
|
MULTISIG: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Account types by value.
|
||||||
|
* @const {RevMap}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Account.typesByVal = [
|
||||||
|
'pubkeyhash',
|
||||||
|
'multisig'
|
||||||
|
];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default address lookahead.
|
||||||
|
* @const {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Account.MAX_LOOKAHEAD = 40;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -26,14 +26,16 @@ const HDPrivateKey = require('../hd/private');
|
|||||||
const HDPublicKey = require('../hd/public');
|
const HDPublicKey = require('../hd/public');
|
||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
|
|
||||||
class HTTP extends Server {
|
|
||||||
/**
|
/**
|
||||||
* HTTP
|
* HTTP
|
||||||
* @alias module:wallet.HTTP
|
* @alias module:wallet.HTTP
|
||||||
|
*/
|
||||||
|
|
||||||
|
class HTTP extends Server {
|
||||||
|
/**
|
||||||
|
* Create an http server.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @see HTTPBase
|
|
||||||
* @emits HTTP#socket
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
|||||||
@ -22,17 +22,20 @@ const {encoding} = bio;
|
|||||||
const {Mnemonic} = HD;
|
const {Mnemonic} = HD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Master Key
|
||||||
* Master BIP32 key which can exist
|
* Master BIP32 key which can exist
|
||||||
* in a timed out encrypted state.
|
* in a timed out encrypted state.
|
||||||
* @alias module:wallet.MasterKey
|
* @alias module:wallet.MasterKey
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MasterKey {
|
||||||
|
/**
|
||||||
|
* Create a master key.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function MasterKey(options) {
|
constructor(options) {
|
||||||
if (!(this instanceof MasterKey))
|
|
||||||
return new MasterKey(options);
|
|
||||||
|
|
||||||
this.encrypted = false;
|
this.encrypted = false;
|
||||||
this.iv = null;
|
this.iv = null;
|
||||||
this.ciphertext = null;
|
this.ciphertext = null;
|
||||||
@ -54,43 +57,13 @@ function MasterKey(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Key derivation salt.
|
|
||||||
* @const {Buffer}
|
|
||||||
* @default
|
|
||||||
*/
|
|
||||||
|
|
||||||
MasterKey.SALT = Buffer.from('bcoin', 'ascii');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key derivation algorithms.
|
|
||||||
* @enum {Number}
|
|
||||||
* @default
|
|
||||||
*/
|
|
||||||
|
|
||||||
MasterKey.alg = {
|
|
||||||
PBKDF2: 0,
|
|
||||||
SCRYPT: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key derivation algorithms by value.
|
|
||||||
* @enum {String}
|
|
||||||
* @default
|
|
||||||
*/
|
|
||||||
|
|
||||||
MasterKey.algByVal = {
|
|
||||||
0: 'PBKDF2',
|
|
||||||
1: 'SCRYPT'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(options);
|
assert(options);
|
||||||
|
|
||||||
if (options.network != null)
|
if (options.network != null)
|
||||||
@ -155,16 +128,16 @@ MasterKey.prototype.fromOptions = function fromOptions(options) {
|
|||||||
assert(this.encrypted ? !this.key : this.key);
|
assert(this.encrypted ? !this.key : this.key);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate master key from options.
|
* Instantiate master key from options.
|
||||||
* @returns {MasterKey}
|
* @returns {MasterKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new MasterKey().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt the key and set a timeout to destroy decrypted data.
|
* Decrypt the key and set a timeout to destroy decrypted data.
|
||||||
@ -173,14 +146,14 @@ MasterKey.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Promise} - Returns {@link HDPrivateKey}.
|
* @returns {Promise} - Returns {@link HDPrivateKey}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.unlock = async function unlock(passphrase, timeout) {
|
async unlock(passphrase, timeout) {
|
||||||
const _unlock = await this.locker.lock();
|
const _unlock = await this.locker.lock();
|
||||||
try {
|
try {
|
||||||
return await this._unlock(passphrase, timeout);
|
return await this._unlock(passphrase, timeout);
|
||||||
} finally {
|
} finally {
|
||||||
_unlock();
|
_unlock();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt the key without a lock.
|
* Decrypt the key without a lock.
|
||||||
@ -190,7 +163,7 @@ MasterKey.prototype.unlock = async function unlock(passphrase, timeout) {
|
|||||||
* @returns {Promise} - Returns {@link HDPrivateKey}.
|
* @returns {Promise} - Returns {@link HDPrivateKey}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype._unlock = async function _unlock(passphrase, timeout) {
|
async _unlock(passphrase, timeout) {
|
||||||
if (this.key) {
|
if (this.key) {
|
||||||
if (this.encrypted) {
|
if (this.encrypted) {
|
||||||
assert(this.timer != null);
|
assert(this.timer != null);
|
||||||
@ -214,7 +187,7 @@ MasterKey.prototype._unlock = async function _unlock(passphrase, timeout) {
|
|||||||
this.aesKey = key;
|
this.aesKey = key;
|
||||||
|
|
||||||
return this.key;
|
return this.key;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the destroy timer.
|
* Start the destroy timer.
|
||||||
@ -222,7 +195,7 @@ MasterKey.prototype._unlock = async function _unlock(passphrase, timeout) {
|
|||||||
* @param {Number} [timeout=60000] timeout in ms.
|
* @param {Number} [timeout=60000] timeout in ms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.start = function start(timeout) {
|
start(timeout) {
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
timeout = 60;
|
timeout = 60;
|
||||||
|
|
||||||
@ -233,20 +206,20 @@ MasterKey.prototype.start = function start(timeout) {
|
|||||||
|
|
||||||
this.until = util.now() + timeout;
|
this.until = util.now() + timeout;
|
||||||
this.timer = setTimeout(this._onTimeout, timeout * 1000);
|
this.timer = setTimeout(this._onTimeout, timeout * 1000);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the destroy timer.
|
* Stop the destroy timer.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.stop = function stop() {
|
stop() {
|
||||||
if (this.timer != null) {
|
if (this.timer != null) {
|
||||||
clearTimeout(this.timer);
|
clearTimeout(this.timer);
|
||||||
this.timer = null;
|
this.timer = null;
|
||||||
this.until = 0;
|
this.until = 0;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive an aes key based on params.
|
* Derive an aes key based on params.
|
||||||
@ -254,7 +227,7 @@ MasterKey.prototype.stop = function stop() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.derive = async function derive(passwd) {
|
async derive(passwd) {
|
||||||
const salt = MasterKey.SALT;
|
const salt = MasterKey.SALT;
|
||||||
const N = this.N;
|
const N = this.N;
|
||||||
const r = this.r;
|
const r = this.r;
|
||||||
@ -271,7 +244,7 @@ MasterKey.prototype.derive = async function derive(passwd) {
|
|||||||
default:
|
default:
|
||||||
throw new Error(`Unknown algorithm: ${this.alg}.`);
|
throw new Error(`Unknown algorithm: ${this.alg}.`);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt data with in-memory aes key.
|
* Encrypt data with in-memory aes key.
|
||||||
@ -280,7 +253,7 @@ MasterKey.prototype.derive = async function derive(passwd) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.encipher = function encipher(data, iv) {
|
encipher(data, iv) {
|
||||||
if (!this.aesKey)
|
if (!this.aesKey)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -288,7 +261,7 @@ MasterKey.prototype.encipher = function encipher(data, iv) {
|
|||||||
iv = Buffer.from(iv, 'hex');
|
iv = Buffer.from(iv, 'hex');
|
||||||
|
|
||||||
return aes.encipher(data, this.aesKey, iv.slice(0, 16));
|
return aes.encipher(data, this.aesKey, iv.slice(0, 16));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt data with in-memory aes key.
|
* Decrypt data with in-memory aes key.
|
||||||
@ -297,7 +270,7 @@ MasterKey.prototype.encipher = function encipher(data, iv) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.decipher = function decipher(data, iv) {
|
decipher(data, iv) {
|
||||||
if (!this.aesKey)
|
if (!this.aesKey)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -305,7 +278,7 @@ MasterKey.prototype.decipher = function decipher(data, iv) {
|
|||||||
iv = Buffer.from(iv, 'hex');
|
iv = Buffer.from(iv, 'hex');
|
||||||
|
|
||||||
return aes.decipher(data, this.aesKey, iv.slice(0, 16));
|
return aes.decipher(data, this.aesKey, iv.slice(0, 16));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the key by zeroing the
|
* Destroy the key by zeroing the
|
||||||
@ -314,14 +287,14 @@ MasterKey.prototype.decipher = function decipher(data, iv) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.lock = async function lock() {
|
async lock() {
|
||||||
const unlock = await this.locker.lock();
|
const unlock = await this.locker.lock();
|
||||||
try {
|
try {
|
||||||
return await this._lock();
|
return await this._lock();
|
||||||
} finally {
|
} finally {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the key by zeroing the
|
* Destroy the key by zeroing the
|
||||||
@ -329,7 +302,7 @@ MasterKey.prototype.lock = async function lock() {
|
|||||||
* the timer if there is one.
|
* the timer if there is one.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype._lock = function _lock() {
|
_lock() {
|
||||||
if (!this.encrypted) {
|
if (!this.encrypted) {
|
||||||
assert(this.timer == null);
|
assert(this.timer == null);
|
||||||
assert(this.key);
|
assert(this.key);
|
||||||
@ -347,16 +320,16 @@ MasterKey.prototype._lock = function _lock() {
|
|||||||
cleanse(this.aesKey);
|
cleanse(this.aesKey);
|
||||||
this.aesKey = null;
|
this.aesKey = null;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the key permanently.
|
* Destroy the key permanently.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.destroy = async function destroy() {
|
async destroy() {
|
||||||
await this.lock();
|
await this.lock();
|
||||||
this.locker.destroy();
|
this.locker.destroy();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt the key permanently.
|
* Decrypt the key permanently.
|
||||||
@ -364,14 +337,14 @@ MasterKey.prototype.destroy = async function destroy() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.decrypt = async function decrypt(passphrase, clean) {
|
async decrypt(passphrase, clean) {
|
||||||
const unlock = await this.locker.lock();
|
const unlock = await this.locker.lock();
|
||||||
try {
|
try {
|
||||||
return await this._decrypt(passphrase, clean);
|
return await this._decrypt(passphrase, clean);
|
||||||
} finally {
|
} finally {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt the key permanently without a lock.
|
* Decrypt the key permanently without a lock.
|
||||||
@ -380,7 +353,7 @@ MasterKey.prototype.decrypt = async function decrypt(passphrase, clean) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype._decrypt = async function _decrypt(passphrase, clean) {
|
async _decrypt(passphrase, clean) {
|
||||||
if (!this.encrypted)
|
if (!this.encrypted)
|
||||||
throw new Error('Master key is not encrypted.');
|
throw new Error('Master key is not encrypted.');
|
||||||
|
|
||||||
@ -403,7 +376,7 @@ MasterKey.prototype._decrypt = async function _decrypt(passphrase, clean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt the key permanently.
|
* Encrypt the key permanently.
|
||||||
@ -411,14 +384,14 @@ MasterKey.prototype._decrypt = async function _decrypt(passphrase, clean) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.encrypt = async function encrypt(passphrase, clean) {
|
async encrypt(passphrase, clean) {
|
||||||
const unlock = await this.locker.lock();
|
const unlock = await this.locker.lock();
|
||||||
try {
|
try {
|
||||||
return await this._encrypt(passphrase, clean);
|
return await this._encrypt(passphrase, clean);
|
||||||
} finally {
|
} finally {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt the key permanently without a lock.
|
* Encrypt the key permanently without a lock.
|
||||||
@ -427,7 +400,7 @@ MasterKey.prototype.encrypt = async function encrypt(passphrase, clean) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype._encrypt = async function _encrypt(passphrase, clean) {
|
async _encrypt(passphrase, clean) {
|
||||||
if (this.encrypted)
|
if (this.encrypted)
|
||||||
throw new Error('Master key is already encrypted.');
|
throw new Error('Master key is already encrypted.');
|
||||||
|
|
||||||
@ -454,14 +427,14 @@ MasterKey.prototype._encrypt = async function _encrypt(passphrase, clean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate key serialization size.
|
* Calculate key serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.keySize = function keySize() {
|
keySize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += this.key.getSize();
|
size += this.key.getSize();
|
||||||
@ -471,14 +444,14 @@ MasterKey.prototype.keySize = function keySize() {
|
|||||||
size += this.mnemonic.getSize();
|
size += this.mnemonic.getSize();
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize key and menmonic to a single buffer.
|
* Serialize key and menmonic to a single buffer.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.writeKey = function writeKey() {
|
writeKey() {
|
||||||
const bw = bio.write(this.keySize());
|
const bw = bio.write(this.keySize());
|
||||||
|
|
||||||
this.key.toWriter(bw, this.network);
|
this.key.toWriter(bw, this.network);
|
||||||
@ -491,14 +464,14 @@ MasterKey.prototype.writeKey = function writeKey() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized key.
|
* Inject properties from serialized key.
|
||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.readKey = function readKey(data) {
|
readKey(data) {
|
||||||
const br = bio.read(data);
|
const br = bio.read(data);
|
||||||
|
|
||||||
this.key = HD.PrivateKey.fromReader(br, this.network);
|
this.key = HD.PrivateKey.fromReader(br, this.network);
|
||||||
@ -507,14 +480,14 @@ MasterKey.prototype.readKey = function readKey(data) {
|
|||||||
this.mnemonic = Mnemonic.fromReader(br);
|
this.mnemonic = Mnemonic.fromReader(br);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate serialization size.
|
* Calculate serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
if (this.encrypted) {
|
if (this.encrypted) {
|
||||||
@ -529,7 +502,7 @@ MasterKey.prototype.getSize = function getSize() {
|
|||||||
size += encoding.sizeVarlen(this.keySize());
|
size += encoding.sizeVarlen(this.keySize());
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the key in the form of:
|
* Serialize the key in the form of:
|
||||||
@ -537,7 +510,7 @@ MasterKey.prototype.getSize = function getSize() {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const bw = bio.write(this.getSize());
|
const bw = bio.write(this.getSize());
|
||||||
|
|
||||||
if (this.encrypted) {
|
if (this.encrypted) {
|
||||||
@ -569,7 +542,7 @@ MasterKey.prototype.toRaw = function toRaw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -577,7 +550,7 @@ MasterKey.prototype.toRaw = function toRaw() {
|
|||||||
* @param {Buffer} raw
|
* @param {Buffer} raw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.fromRaw = function fromRaw(raw, network) {
|
fromRaw(raw, network) {
|
||||||
const br = bio.read(raw);
|
const br = bio.read(raw);
|
||||||
|
|
||||||
this.network = Network.get(network);
|
this.network = Network.get(network);
|
||||||
@ -607,16 +580,16 @@ MasterKey.prototype.fromRaw = function fromRaw(raw, network) {
|
|||||||
this.mnemonic = Mnemonic.fromReader(br);
|
this.mnemonic = Mnemonic.fromReader(br);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate master key from serialized data.
|
* Instantiate master key from serialized data.
|
||||||
* @returns {MasterKey}
|
* @returns {MasterKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.fromRaw = function fromRaw(raw, network) {
|
static fromRaw(raw, network) {
|
||||||
return new MasterKey().fromRaw(raw, network);
|
return new this().fromRaw(raw, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from an HDPrivateKey.
|
* Inject properties from an HDPrivateKey.
|
||||||
@ -625,7 +598,7 @@ MasterKey.fromRaw = function fromRaw(raw, network) {
|
|||||||
* @param {Mnemonic?} mnemonic
|
* @param {Mnemonic?} mnemonic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.fromKey = function fromKey(key, mnemonic, network) {
|
fromKey(key, mnemonic, network) {
|
||||||
this.encrypted = false;
|
this.encrypted = false;
|
||||||
this.iv = null;
|
this.iv = null;
|
||||||
this.ciphertext = null;
|
this.ciphertext = null;
|
||||||
@ -633,7 +606,7 @@ MasterKey.prototype.fromKey = function fromKey(key, mnemonic, network) {
|
|||||||
this.mnemonic = mnemonic || null;
|
this.mnemonic = mnemonic || null;
|
||||||
this.network = Network.get(network);
|
this.network = Network.get(network);
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate master key from an HDPrivateKey.
|
* Instantiate master key from an HDPrivateKey.
|
||||||
@ -642,9 +615,9 @@ MasterKey.prototype.fromKey = function fromKey(key, mnemonic, network) {
|
|||||||
* @returns {MasterKey}
|
* @returns {MasterKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.fromKey = function fromKey(key, mnemonic, network) {
|
static fromKey(key, mnemonic, network) {
|
||||||
return new MasterKey().fromKey(key, mnemonic, network);
|
return new this().fromKey(key, mnemonic, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert master key to a jsonifiable object.
|
* Convert master key to a jsonifiable object.
|
||||||
@ -653,7 +626,7 @@ MasterKey.fromKey = function fromKey(key, mnemonic, network) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.toJSON = function toJSON(unsafe) {
|
toJSON(unsafe) {
|
||||||
if (this.encrypted) {
|
if (this.encrypted) {
|
||||||
return {
|
return {
|
||||||
encrypted: true,
|
encrypted: true,
|
||||||
@ -672,14 +645,14 @@ MasterKey.prototype.toJSON = function toJSON(unsafe) {
|
|||||||
key: unsafe ? this.key.toJSON(this.network) : undefined,
|
key: unsafe ? this.key.toJSON(this.network) : undefined,
|
||||||
mnemonic: unsafe && this.mnemonic ? this.mnemonic.toJSON() : undefined
|
mnemonic: unsafe && this.mnemonic ? this.mnemonic.toJSON() : undefined
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the key.
|
* Inspect the key.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
const json = this.toJSON(true);
|
const json = this.toJSON(true);
|
||||||
|
|
||||||
if (this.key)
|
if (this.key)
|
||||||
@ -689,7 +662,7 @@ MasterKey.prototype.inspect = function inspect() {
|
|||||||
json.mnemonic = this.mnemonic.toJSON();
|
json.mnemonic = this.mnemonic.toJSON();
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is a MasterKey.
|
* Test whether an object is a MasterKey.
|
||||||
@ -697,10 +670,41 @@ MasterKey.prototype.inspect = function inspect() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.isMasterKey = function isMasterKey(obj) {
|
static isMasterKey(obj) {
|
||||||
return obj instanceof MasterKey;
|
return obj instanceof MasterKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key derivation salt.
|
||||||
|
* @const {Buffer}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
MasterKey.SALT = Buffer.from('bcoin', 'ascii');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key derivation algorithms.
|
||||||
|
* @enum {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
MasterKey.alg = {
|
||||||
|
PBKDF2: 0,
|
||||||
|
SCRYPT: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key derivation algorithms by value.
|
||||||
|
* @enum {String}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
MasterKey.algByVal = [
|
||||||
|
'PBKDF2',
|
||||||
|
'SCRYPT'
|
||||||
|
];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -13,43 +13,43 @@ const EventEmitter = require('events');
|
|||||||
* Null Client
|
* Null Client
|
||||||
* Sort of a fake local client for separation of concerns.
|
* Sort of a fake local client for separation of concerns.
|
||||||
* @alias module:node.NullClient
|
* @alias module:node.NullClient
|
||||||
|
*/
|
||||||
|
|
||||||
|
class NullClient extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Create a client.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function NullClient(wdb) {
|
constructor(wdb) {
|
||||||
if (!(this instanceof NullClient))
|
super();
|
||||||
return new NullClient(wdb);
|
|
||||||
|
|
||||||
EventEmitter.call(this);
|
|
||||||
|
|
||||||
this.wdb = wdb;
|
this.wdb = wdb;
|
||||||
this.network = wdb.network;
|
this.network = wdb.network;
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(NullClient.prototype, EventEmitter.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the client.
|
* Open the client.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.open = async function open(options) {
|
async open(options) {
|
||||||
assert(!this.opened, 'NullClient is already open.');
|
assert(!this.opened, 'NullClient is already open.');
|
||||||
this.opened = true;
|
this.opened = true;
|
||||||
setImmediate(() => this.emit('connect'));
|
setImmediate(() => this.emit('connect'));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the client.
|
* Close the client.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.close = async function close() {
|
async close() {
|
||||||
assert(this.opened, 'NullClient is not open.');
|
assert(this.opened, 'NullClient is not open.');
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
setImmediate(() => this.emit('disconnect'));
|
setImmediate(() => this.emit('disconnect'));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a listener.
|
* Add a listener.
|
||||||
@ -57,9 +57,9 @@ NullClient.prototype.close = async function close() {
|
|||||||
* @param {Function} handler
|
* @param {Function} handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.bind = function bind(type, handler) {
|
bind(type, handler) {
|
||||||
return this.on(type, handler);
|
return this.on(type, handler);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a listener.
|
* Add a listener.
|
||||||
@ -67,19 +67,19 @@ NullClient.prototype.bind = function bind(type, handler) {
|
|||||||
* @param {Function} handler
|
* @param {Function} handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.hook = function hook(type, handler) {
|
hook(type, handler) {
|
||||||
return this.on(type, handler);
|
return this.on(type, handler);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get chain tip.
|
* Get chain tip.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.getTip = async function getTip() {
|
async getTip() {
|
||||||
const {hash, height, time} = this.network.genesis;
|
const {hash, height, time} = this.network.genesis;
|
||||||
return { hash, height, time };
|
return { hash, height, time };
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get chain entry.
|
* Get chain entry.
|
||||||
@ -87,9 +87,9 @@ NullClient.prototype.getTip = async function getTip() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.getEntry = async function getEntry(hash) {
|
async getEntry(hash) {
|
||||||
return { hash, height: 0, time: 0 };
|
return { hash, height: 0, time: 0 };
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a transaction. Do not wait for promise.
|
* Send a transaction. Do not wait for promise.
|
||||||
@ -97,9 +97,9 @@ NullClient.prototype.getEntry = async function getEntry(hash) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.send = async function send(tx) {
|
async send(tx) {
|
||||||
this.wdb.emit('send', tx);
|
this.wdb.emit('send', tx);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set bloom filter.
|
* Set bloom filter.
|
||||||
@ -107,9 +107,9 @@ NullClient.prototype.send = async function send(tx) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.setFilter = async function setFilter(filter) {
|
async setFilter(filter) {
|
||||||
this.wdb.emit('set filter', filter);
|
this.wdb.emit('set filter', filter);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add data to filter.
|
* Add data to filter.
|
||||||
@ -117,18 +117,18 @@ NullClient.prototype.setFilter = async function setFilter(filter) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.addFilter = async function addFilter(data) {
|
async addFilter(data) {
|
||||||
this.wdb.emit('add filter', data);
|
this.wdb.emit('add filter', data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset filter.
|
* Reset filter.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.resetFilter = async function resetFilter() {
|
async resetFilter() {
|
||||||
this.wdb.emit('reset filter');
|
this.wdb.emit('reset filter');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Esimate smart fee.
|
* Esimate smart fee.
|
||||||
@ -136,9 +136,9 @@ NullClient.prototype.resetFilter = async function resetFilter() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.estimateFee = async function estimateFee(blocks) {
|
async estimateFee(blocks) {
|
||||||
return this.network.feeRate;
|
return this.network.feeRate;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get hash range.
|
* Get hash range.
|
||||||
@ -147,9 +147,9 @@ NullClient.prototype.estimateFee = async function estimateFee(blocks) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.getHashes = async function getHashes(start = -1, end = -1) {
|
async getHashes(start = -1, end = -1) {
|
||||||
return [this.network.genesis.hash];
|
return [this.network.genesis.hash];
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rescan for any missed transactions.
|
* Rescan for any missed transactions.
|
||||||
@ -159,9 +159,10 @@ NullClient.prototype.getHashes = async function getHashes(start = -1, end = -1)
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NullClient.prototype.rescan = async function rescan(start) {
|
async rescan(start) {
|
||||||
;
|
;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -14,19 +14,20 @@ const {encoding} = bio;
|
|||||||
/**
|
/**
|
||||||
* Path
|
* Path
|
||||||
* @alias module:wallet.Path
|
* @alias module:wallet.Path
|
||||||
* @constructor
|
|
||||||
* @property {WalletID} wid
|
|
||||||
* @property {String} name - Account name.
|
* @property {String} name - Account name.
|
||||||
* @property {Number} account - Account index.
|
* @property {Number} account - Account index.
|
||||||
* @property {Number} branch - Branch index.
|
* @property {Number} branch - Branch index.
|
||||||
* @property {Number} index - Address index.
|
* @property {Number} index - Address index.
|
||||||
* @property {Address|null} address
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Path(options) {
|
class Path {
|
||||||
if (!(this instanceof Path))
|
/**
|
||||||
return new Path(options);
|
* Create a path.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.keyType = Path.types.HD;
|
this.keyType = Path.types.HD;
|
||||||
|
|
||||||
this.name = null; // Passed in by caller.
|
this.name = null; // Passed in by caller.
|
||||||
@ -46,18 +47,6 @@ function Path(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Path types.
|
|
||||||
* @enum {Number}
|
|
||||||
* @default
|
|
||||||
*/
|
|
||||||
|
|
||||||
Path.types = {
|
|
||||||
HD: 0,
|
|
||||||
KEY: 1,
|
|
||||||
ADDRESS: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate path from options object.
|
* Instantiate path from options object.
|
||||||
* @private
|
* @private
|
||||||
@ -65,7 +54,7 @@ Path.types = {
|
|||||||
* @returns {Path}
|
* @returns {Path}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
this.keyType = options.keyType;
|
this.keyType = options.keyType;
|
||||||
|
|
||||||
this.name = options.name;
|
this.name = options.name;
|
||||||
@ -81,7 +70,7 @@ Path.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.hash = options.hash;
|
this.hash = options.hash;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate path from options object.
|
* Instantiate path from options object.
|
||||||
@ -89,17 +78,17 @@ Path.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Path}
|
* @returns {Path}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new Path().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone the path object.
|
* Clone the path object.
|
||||||
* @returns {Path}
|
* @returns {Path}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.clone = function clone() {
|
clone() {
|
||||||
const path = new Path();
|
const path = new this.constructor();
|
||||||
|
|
||||||
path.keyType = this.keyType;
|
path.keyType = this.keyType;
|
||||||
|
|
||||||
@ -116,7 +105,7 @@ Path.prototype.clone = function clone() {
|
|||||||
path.hash = this.hash;
|
path.hash = this.hash;
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -124,7 +113,7 @@ Path.prototype.clone = function clone() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = bio.read(data);
|
const br = bio.read(data);
|
||||||
|
|
||||||
this.account = br.readU32();
|
this.account = br.readU32();
|
||||||
@ -154,7 +143,7 @@ Path.prototype.fromRaw = function fromRaw(data) {
|
|||||||
this.type = 4;
|
this.type = 4;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate path from serialized data.
|
* Instantiate path from serialized data.
|
||||||
@ -162,16 +151,16 @@ Path.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Path}
|
* @returns {Path}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new Path().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate serialization size.
|
* Calculate serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += 5;
|
size += 5;
|
||||||
@ -189,14 +178,14 @@ Path.prototype.getSize = function getSize() {
|
|||||||
size += 2;
|
size += 2;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize path.
|
* Serialize path.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const bw = bio.write(size);
|
const bw = bio.write(size);
|
||||||
|
|
||||||
@ -229,7 +218,7 @@ Path.prototype.toRaw = function toRaw() {
|
|||||||
bw.writeU8(this.type);
|
bw.writeU8(this.type);
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from address.
|
* Inject properties from address.
|
||||||
@ -238,7 +227,7 @@ Path.prototype.toRaw = function toRaw() {
|
|||||||
* @param {Address} address
|
* @param {Address} address
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.fromAddress = function fromAddress(account, address) {
|
fromAddress(account, address) {
|
||||||
this.keyType = Path.types.ADDRESS;
|
this.keyType = Path.types.ADDRESS;
|
||||||
this.name = account.name;
|
this.name = account.name;
|
||||||
this.account = account.accountIndex;
|
this.account = account.accountIndex;
|
||||||
@ -246,7 +235,7 @@ Path.prototype.fromAddress = function fromAddress(account, address) {
|
|||||||
this.type = address.type;
|
this.type = address.type;
|
||||||
this.hash = address.getHash('hex');
|
this.hash = address.getHash('hex');
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate path from address.
|
* Instantiate path from address.
|
||||||
@ -255,54 +244,79 @@ Path.prototype.fromAddress = function fromAddress(account, address) {
|
|||||||
* @returns {Path}
|
* @returns {Path}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.fromAddress = function fromAddress(account, address) {
|
static fromAddress(account, address) {
|
||||||
return new Path().fromAddress(account, address);
|
return new this().fromAddress(account, address);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert path object to string derivation path.
|
* Convert path object to string derivation path.
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.toPath = function toPath() {
|
toPath() {
|
||||||
if (this.keyType !== Path.types.HD)
|
if (this.keyType !== Path.types.HD)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return `m/${this.account}'/${this.branch}/${this.index}`;
|
return `m/${this.account}'/${this.branch}/${this.index}`;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert path object to an address (currently unused).
|
* Convert path object to an address (currently unused).
|
||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.toAddress = function toAddress() {
|
toAddress() {
|
||||||
return Address.fromHash(this.hash, this.type, this.version);
|
return Address.fromHash(this.hash, this.type, this.version);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert path to a json-friendly object.
|
* Convert path to a json-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return {
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
account: this.account,
|
account: this.account,
|
||||||
change: this.branch === 1,
|
change: this.branch === 1,
|
||||||
derivation: this.toPath()
|
derivation: this.toPath()
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the path.
|
* Inspect the path.
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return `<Path: ${this.name}:${this.toPath()}>`;
|
return `<Path: ${this.name}:${this.toPath()}>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path types.
|
||||||
|
* @enum {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
Path.types = {
|
||||||
|
HD: 0,
|
||||||
|
KEY: 1,
|
||||||
|
ADDRESS: 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path types.
|
||||||
|
* @enum {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
Path.typesByVal = [
|
||||||
|
'HD',
|
||||||
|
'KEY',
|
||||||
|
'ADDRESS'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -20,13 +20,18 @@ const plugin = exports;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin
|
* Plugin
|
||||||
|
* @extends EventEmitter
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Plugin extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Create a plugin.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Node} node
|
* @param {Node} node
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Plugin(node) {
|
constructor(node) {
|
||||||
if (!(this instanceof Plugin))
|
super();
|
||||||
return new Plugin(node);
|
|
||||||
|
|
||||||
const config = node.config;
|
const config = node.config;
|
||||||
|
|
||||||
@ -68,22 +73,21 @@ function Plugin(node) {
|
|||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Plugin.prototype, EventEmitter.prototype);
|
init() {
|
||||||
|
|
||||||
Plugin.prototype.init = function init() {
|
|
||||||
this.wdb.on('error', err => this.emit('error', err));
|
this.wdb.on('error', err => this.emit('error', err));
|
||||||
this.http.on('error', err => this.emit('error', err));
|
this.http.on('error', err => this.emit('error', err));
|
||||||
};
|
}
|
||||||
|
|
||||||
Plugin.prototype.open = async function open() {
|
async open() {
|
||||||
await this.wdb.open();
|
await this.wdb.open();
|
||||||
this.rpc.wallet = this.wdb.primary;
|
this.rpc.wallet = this.wdb.primary;
|
||||||
};
|
}
|
||||||
|
|
||||||
Plugin.prototype.close = async function close() {
|
async close() {
|
||||||
this.rpc.wallet = this.wdb.primary;
|
this.rpc.wallet = null;
|
||||||
await this.wdb.close();
|
await this.wdb.close();
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin name.
|
* Plugin name.
|
||||||
|
|||||||
@ -18,13 +18,15 @@ const {encoding} = bio;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain State
|
* Chain State
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ChainState {
|
||||||
|
/**
|
||||||
|
* Create a chain state.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function ChainState() {
|
constructor() {
|
||||||
if (!(this instanceof ChainState))
|
|
||||||
return new ChainState();
|
|
||||||
|
|
||||||
this.startHeight = 0;
|
this.startHeight = 0;
|
||||||
this.startHash = encoding.NULL_HASH;
|
this.startHash = encoding.NULL_HASH;
|
||||||
this.height = 0;
|
this.height = 0;
|
||||||
@ -36,14 +38,14 @@ function ChainState() {
|
|||||||
* @returns {ChainState}
|
* @returns {ChainState}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainState.prototype.clone = function clone() {
|
clone() {
|
||||||
const state = new ChainState();
|
const state = new ChainState();
|
||||||
state.startHeight = this.startHeight;
|
state.startHeight = this.startHeight;
|
||||||
state.startHash = this.startHash;
|
state.startHash = this.startHash;
|
||||||
state.height = this.height;
|
state.height = this.height;
|
||||||
state.marked = this.marked;
|
state.marked = this.marked;
|
||||||
return state;
|
return state;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -51,7 +53,7 @@ ChainState.prototype.clone = function clone() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainState.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = bio.read(data);
|
const br = bio.read(data);
|
||||||
|
|
||||||
this.startHeight = br.readU32();
|
this.startHeight = br.readU32();
|
||||||
@ -60,7 +62,7 @@ ChainState.prototype.fromRaw = function fromRaw(data) {
|
|||||||
this.marked = br.readU8() === 1;
|
this.marked = br.readU8() === 1;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate chain state from serialized data.
|
* Instantiate chain state from serialized data.
|
||||||
@ -69,16 +71,16 @@ ChainState.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {ChainState}
|
* @returns {ChainState}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainState.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new ChainState().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the chain state.
|
* Serialize the chain state.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainState.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const bw = bio.write(41);
|
const bw = bio.write(41);
|
||||||
|
|
||||||
bw.writeU32(this.startHeight);
|
bw.writeU32(this.startHeight);
|
||||||
@ -87,20 +89,23 @@ ChainState.prototype.toRaw = function toRaw() {
|
|||||||
bw.writeU8(this.marked ? 1 : 0);
|
bw.writeU8(this.marked ? 1 : 0);
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block Meta
|
* Block Meta
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BlockMeta {
|
||||||
|
/**
|
||||||
|
* Create block meta.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Hash} hash
|
* @param {Hash} hash
|
||||||
* @param {Number} height
|
* @param {Number} height
|
||||||
* @param {Number} time
|
* @param {Number} time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function BlockMeta(hash, height, time) {
|
constructor(hash, height, time) {
|
||||||
if (!(this instanceof BlockMeta))
|
|
||||||
return new BlockMeta(hash, height, time);
|
|
||||||
|
|
||||||
this.hash = hash || encoding.NULL_HASH;
|
this.hash = hash || encoding.NULL_HASH;
|
||||||
this.height = height != null ? height : -1;
|
this.height = height != null ? height : -1;
|
||||||
this.time = time || 0;
|
this.time = time || 0;
|
||||||
@ -111,18 +116,18 @@ function BlockMeta(hash, height, time) {
|
|||||||
* @returns {BlockMeta}
|
* @returns {BlockMeta}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.prototype.clone = function clone() {
|
clone() {
|
||||||
return new BlockMeta(this.hash, this.height, this.time);
|
return new this.constructor(this.hash, this.height, this.time);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get block meta hash as a buffer.
|
* Get block meta hash as a buffer.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.prototype.toHash = function toHash() {
|
toHash() {
|
||||||
return Buffer.from(this.hash, 'hex');
|
return Buffer.from(this.hash, 'hex');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block meta from chain entry.
|
* Instantiate block meta from chain entry.
|
||||||
@ -130,12 +135,12 @@ BlockMeta.prototype.toHash = function toHash() {
|
|||||||
* @param {ChainEntry} entry
|
* @param {ChainEntry} entry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.prototype.fromEntry = function fromEntry(entry) {
|
fromEntry(entry) {
|
||||||
this.hash = entry.hash;
|
this.hash = entry.hash;
|
||||||
this.height = entry.height;
|
this.height = entry.height;
|
||||||
this.time = entry.time;
|
this.time = entry.time;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block meta from json object.
|
* Instantiate block meta from json object.
|
||||||
@ -143,12 +148,12 @@ BlockMeta.prototype.fromEntry = function fromEntry(entry) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
this.hash = encoding.revHex(json.hash);
|
this.hash = encoding.revHex(json.hash);
|
||||||
this.height = json.height;
|
this.height = json.height;
|
||||||
this.time = json.time;
|
this.time = json.time;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block meta from serialized tip data.
|
* Instantiate block meta from serialized tip data.
|
||||||
@ -156,13 +161,13 @@ BlockMeta.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = bio.read(data);
|
const br = bio.read(data);
|
||||||
this.hash = br.readHash('hex');
|
this.hash = br.readHash('hex');
|
||||||
this.height = br.readU32();
|
this.height = br.readU32();
|
||||||
this.time = br.readU32();
|
this.time = br.readU32();
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block meta from chain entry.
|
* Instantiate block meta from chain entry.
|
||||||
@ -170,9 +175,9 @@ BlockMeta.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {BlockMeta}
|
* @returns {BlockMeta}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.fromEntry = function fromEntry(entry) {
|
static fromEntry(entry) {
|
||||||
return new BlockMeta().fromEntry(entry);
|
return new this().fromEntry(entry);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block meta from json object.
|
* Instantiate block meta from json object.
|
||||||
@ -180,9 +185,9 @@ BlockMeta.fromEntry = function fromEntry(entry) {
|
|||||||
* @returns {BlockMeta}
|
* @returns {BlockMeta}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new BlockMeta().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block meta from serialized data.
|
* Instantiate block meta from serialized data.
|
||||||
@ -191,47 +196,50 @@ BlockMeta.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {BlockMeta}
|
* @returns {BlockMeta}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new BlockMeta().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block meta.
|
* Serialize the block meta.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const bw = bio.write(42);
|
const bw = bio.write(42);
|
||||||
bw.writeHash(this.hash);
|
bw.writeHash(this.hash);
|
||||||
bw.writeU32(this.height);
|
bw.writeU32(this.height);
|
||||||
bw.writeU32(this.time);
|
bw.writeU32(this.time);
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block meta to a more json-friendly object.
|
* Convert the block meta to a more json-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BlockMeta.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return {
|
return {
|
||||||
hash: encoding.revHex(this.hash),
|
hash: encoding.revHex(this.hash),
|
||||||
height: this.height,
|
height: this.height,
|
||||||
time: this.time
|
time: this.time
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TX Record
|
* TX Record
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TXRecord {
|
||||||
|
/**
|
||||||
|
* Create tx record.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
* @param {BlockMeta?} block
|
* @param {BlockMeta?} block
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function TXRecord(tx, block) {
|
constructor(tx, block) {
|
||||||
if (!(this instanceof TXRecord))
|
|
||||||
return new TXRecord(tx, block);
|
|
||||||
|
|
||||||
this.tx = null;
|
this.tx = null;
|
||||||
this.hash = null;
|
this.hash = null;
|
||||||
this.mtime = util.now();
|
this.mtime = util.now();
|
||||||
@ -252,7 +260,7 @@ function TXRecord(tx, block) {
|
|||||||
* @returns {TXRecord}
|
* @returns {TXRecord}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.fromTX = function fromTX(tx, block) {
|
fromTX(tx, block) {
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
this.hash = tx.hash('hex');
|
this.hash = tx.hash('hex');
|
||||||
|
|
||||||
@ -260,7 +268,7 @@ TXRecord.prototype.fromTX = function fromTX(tx, block) {
|
|||||||
this.setBlock(block);
|
this.setBlock(block);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate tx record from tx and block.
|
* Instantiate tx record from tx and block.
|
||||||
@ -269,42 +277,42 @@ TXRecord.prototype.fromTX = function fromTX(tx, block) {
|
|||||||
* @returns {TXRecord}
|
* @returns {TXRecord}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.fromTX = function fromTX(tx, block) {
|
static fromTX(tx, block) {
|
||||||
return new TXRecord().fromTX(tx, block);
|
return new this().fromTX(tx, block);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set block data (confirm).
|
* Set block data (confirm).
|
||||||
* @param {BlockMeta} block
|
* @param {BlockMeta} block
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.setBlock = function setBlock(block) {
|
setBlock(block) {
|
||||||
this.height = block.height;
|
this.height = block.height;
|
||||||
this.block = block.hash;
|
this.block = block.hash;
|
||||||
this.time = block.time;
|
this.time = block.time;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unset block (unconfirm).
|
* Unset block (unconfirm).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.unsetBlock = function unsetBlock() {
|
unsetBlock() {
|
||||||
this.height = -1;
|
this.height = -1;
|
||||||
this.block = null;
|
this.block = null;
|
||||||
this.time = 0;
|
this.time = 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert tx record to a block meta.
|
* Convert tx record to a block meta.
|
||||||
* @returns {BlockMeta}
|
* @returns {BlockMeta}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.getBlock = function getBlock() {
|
getBlock() {
|
||||||
if (this.height === -1)
|
if (this.height === -1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new BlockMeta(this.block, this.height, this.time);
|
return new BlockMeta(this.block, this.height, this.time);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate current number of transaction confirmations.
|
* Calculate current number of transaction confirmations.
|
||||||
@ -312,7 +320,7 @@ TXRecord.prototype.getBlock = function getBlock() {
|
|||||||
* @returns {Number} confirmations
|
* @returns {Number} confirmations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.getDepth = function getDepth(height) {
|
getDepth(height) {
|
||||||
assert(typeof height === 'number', 'Must pass in height.');
|
assert(typeof height === 'number', 'Must pass in height.');
|
||||||
|
|
||||||
if (this.height === -1)
|
if (this.height === -1)
|
||||||
@ -322,14 +330,14 @@ TXRecord.prototype.getDepth = function getDepth(height) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return height - this.height + 1;
|
return height - this.height + 1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get serialization size.
|
* Get serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += this.tx.getSize();
|
size += this.tx.getSize();
|
||||||
@ -344,14 +352,14 @@ TXRecord.prototype.getSize = function getSize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a transaction to "extended format".
|
* Serialize a transaction to "extended format".
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const bw = bio.write(size);
|
const bw = bio.write(size);
|
||||||
|
|
||||||
@ -375,7 +383,7 @@ TXRecord.prototype.toRaw = function toRaw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from "extended" format.
|
* Inject properties from "extended" format.
|
||||||
@ -383,7 +391,7 @@ TXRecord.prototype.toRaw = function toRaw() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = bio.read(data);
|
const br = bio.read(data);
|
||||||
|
|
||||||
this.tx = new TX();
|
this.tx = new TX();
|
||||||
@ -402,7 +410,7 @@ TXRecord.prototype.fromRaw = function fromRaw(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a transaction from a buffer
|
* Instantiate a transaction from a buffer
|
||||||
@ -411,70 +419,77 @@ TXRecord.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {TX}
|
* @returns {TX}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRecord.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new TXRecord().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map Record
|
* Map Record
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MapRecord {
|
||||||
|
/**
|
||||||
|
* Create map record.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function MapRecord() {
|
constructor() {
|
||||||
this.wids = new Set();
|
this.wids = new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapRecord.prototype.add = function add(wid) {
|
add(wid) {
|
||||||
if (this.wids.has(wid))
|
if (this.wids.has(wid))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this.wids.add(wid);
|
this.wids.add(wid);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.prototype.remove = function remove(wid) {
|
remove(wid) {
|
||||||
return this.wids.delete(wid);
|
return this.wids.delete(wid);
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
bw.writeU32(this.wids.size);
|
bw.writeU32(this.wids.size);
|
||||||
|
|
||||||
for (const wid of this.wids)
|
for (const wid of this.wids)
|
||||||
bw.writeU32(wid);
|
bw.writeU32(wid);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return 4 + this.wids.size * 4;
|
return 4 + this.wids.size * 4;
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(bio.write(size)).render();
|
return this.toWriter(bio.write(size)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
const count = br.readU32();
|
const count = br.readU32();
|
||||||
|
|
||||||
for (let i = 0; i < count; i++)
|
for (let i = 0; i < count; i++)
|
||||||
this.wids.add(br.readU32());
|
this.wids.add(br.readU32());
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(bio.read(data));
|
return this.fromReader(bio.read(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new MapRecord().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
MapRecord.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new MapRecord().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -16,14 +16,17 @@ const RPC = require('./rpc');
|
|||||||
/**
|
/**
|
||||||
* Wallet Node
|
* Wallet Node
|
||||||
* @extends Node
|
* @extends Node
|
||||||
* @constructor
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function WalletNode(options) {
|
class WalletNode extends Node {
|
||||||
if (!(this instanceof WalletNode))
|
/**
|
||||||
return new WalletNode(options);
|
* Create a wallet node.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
Node.call(this, 'bcoin', 'wallet.conf', 'wallet.log', options);
|
constructor(options) {
|
||||||
|
super('bcoin', 'wallet.conf', 'wallet.log', options);
|
||||||
|
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
|
|
||||||
@ -72,19 +75,17 @@ function WalletNode(options) {
|
|||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(WalletNode.prototype, Node.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the node.
|
* Initialize the node.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletNode.prototype.init = function init() {
|
init() {
|
||||||
this.wdb.on('error', err => this.error(err));
|
this.wdb.on('error', err => this.error(err));
|
||||||
this.http.on('error', err => this.error(err));
|
this.http.on('error', err => this.error(err));
|
||||||
|
|
||||||
this.loadPlugins();
|
this.loadPlugins();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the node and all its child objects,
|
* Open the node and all its child objects,
|
||||||
@ -93,7 +94,7 @@ WalletNode.prototype.init = function init() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletNode.prototype.open = async function open() {
|
async open() {
|
||||||
assert(!this.opened, 'WalletNode is already open.');
|
assert(!this.opened, 'WalletNode is already open.');
|
||||||
this.opened = true;
|
this.opened = true;
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ WalletNode.prototype.open = async function open() {
|
|||||||
await this.handleOpen();
|
await this.handleOpen();
|
||||||
|
|
||||||
this.logger.info('Wallet node is loaded.');
|
this.logger.info('Wallet node is loaded.');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the node, wait for the database to close.
|
* Close the node, wait for the database to close.
|
||||||
@ -116,7 +117,7 @@ WalletNode.prototype.open = async function open() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletNode.prototype.close = async function close() {
|
async close() {
|
||||||
assert(this.opened, 'WalletNode is not open.');
|
assert(this.opened, 'WalletNode is not open.');
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
|
|
||||||
@ -129,7 +130,8 @@ WalletNode.prototype.close = async function close() {
|
|||||||
|
|
||||||
await this.wdb.close();
|
await this.wdb.close();
|
||||||
await this.handleClose();
|
await this.handleClose();
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -36,79 +36,6 @@ class WalletKey extends KeyRing {
|
|||||||
this.index = -1;
|
this.index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate key ring from options.
|
|
||||||
* @param {Object} options
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromOptions(options) {
|
|
||||||
return new this().fromOptions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate wallet key from a private key.
|
|
||||||
* @param {Buffer} key
|
|
||||||
* @param {Boolean?} compressed
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromPrivate(key, compressed) {
|
|
||||||
return new this().fromPrivate(key, compressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a wallet key.
|
|
||||||
* @param {Boolean?} compressed
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static generate(compressed) {
|
|
||||||
return new this().generate(compressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate wallet key from a public key.
|
|
||||||
* @param {Buffer} publicKey
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromPublic(key) {
|
|
||||||
return new this().fromPublic(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate wallet key from a public key.
|
|
||||||
* @param {Buffer} publicKey
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromKey(key, compressed) {
|
|
||||||
return new this().fromKey(key, compressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate wallet key from script.
|
|
||||||
* @param {Buffer} key
|
|
||||||
* @param {Script} script
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromScript(key, script, compressed) {
|
|
||||||
return new this().fromScript(key, script, compressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate a wallet key from a serialized CBitcoinSecret.
|
|
||||||
* @param {Base58String} secret
|
|
||||||
* @param {Network?} network
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromSecret(data, network) {
|
|
||||||
return new this().fromSecret(data, network);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an WalletKey to a more json-friendly object.
|
* Convert an WalletKey to a more json-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
@ -130,26 +57,6 @@ class WalletKey extends KeyRing {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate an WalletKey from a jsonified transaction object.
|
|
||||||
* @param {Object} json - The jsonified transaction object.
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromJSON(json) {
|
|
||||||
return new this().fromJSON(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate a wallet key from serialized data.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @returns {WalletKey}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static fromRaw(data) {
|
|
||||||
return new this().fromRaw(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from hd key.
|
* Inject properties from hd key.
|
||||||
* @private
|
* @private
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user