mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
JS: Handle account events through Account class.
This commit is contained in:
@@ -10,16 +10,75 @@
|
|||||||
// var network = require("./network.js");
|
// var network = require("./network.js");
|
||||||
|
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var Amount = require('./amount.js').Amount;
|
var Amount = require('./amount').Amount;
|
||||||
var UInt160 = require('./amount.js').UInt160;
|
var UInt160 = require('./uint160').UInt160;
|
||||||
|
|
||||||
var Account = function (network, account) {
|
var Account = function (remote, account) {
|
||||||
this._network = network;
|
var self = this;
|
||||||
this._account = UInt160.json_rewrite(account);
|
|
||||||
|
this._remote = remote;
|
||||||
|
this._account = UInt160.from_json(account);
|
||||||
|
|
||||||
|
// Ledger entry object
|
||||||
|
// Important: This must never be overwritten, only extend()-ed
|
||||||
|
this._entry = {};
|
||||||
|
|
||||||
|
this.on('newListener', function (type, listener) {
|
||||||
|
if (Account.subscribe_events.indexOf(type) !== -1) {
|
||||||
|
if (!this._subs && 'open' === this._remote._online_state) {
|
||||||
|
this._remote.request_subscribe()
|
||||||
|
.accounts(this._account.to_json())
|
||||||
|
.request();
|
||||||
|
}
|
||||||
|
this._subs += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('removeListener', function (type, listener) {
|
||||||
|
if (Account.subscribe_events.indexOf(type) !== -1) {
|
||||||
|
this._subs -= 1;
|
||||||
|
|
||||||
|
if (!this._subs && 'open' === this._remote._online_state) {
|
||||||
|
this._remote.request_unsubscribe([ 'transactions' ])
|
||||||
|
.accounts(this._account.to_json())
|
||||||
|
.request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._remote.on('connect', function () {
|
||||||
|
if (self._subs) {
|
||||||
|
this._remote.request_subscribe()
|
||||||
|
.accounts(this._account.to_json())
|
||||||
|
.request();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Account.prototype = new EventEmitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of events that require a remote subscription to the account.
|
||||||
|
*/
|
||||||
|
Account.subscribe_events = ['transaction', 'entry'];
|
||||||
|
|
||||||
|
Account.prototype.to_json = function ()
|
||||||
|
{
|
||||||
|
return this._account.to_json();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the AccountId is valid.
|
||||||
|
*
|
||||||
|
* Note: This does not tell you whether the account exists in the ledger.
|
||||||
|
*/
|
||||||
|
Account.prototype.is_valid = function ()
|
||||||
|
{
|
||||||
|
return this._account.is_valid();
|
||||||
|
};
|
||||||
|
|
||||||
exports.Account = Account;
|
exports.Account = Account;
|
||||||
|
|
||||||
// vim:sw=2:sts=2:ts=8:et
|
// vim:sw=2:sts=2:ts=8:et
|
||||||
|
|||||||
76
src/js/meta.js
Normal file
76
src/js/meta.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
var extend = require('extend');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meta data processing facility.
|
||||||
|
*/
|
||||||
|
var Meta = function (raw_data)
|
||||||
|
{
|
||||||
|
this.nodes = [];
|
||||||
|
|
||||||
|
for (var i = 0, l = raw_data.AffectedNodes.length; i < l; i++) {
|
||||||
|
var an = raw_data.AffectedNodes[i],
|
||||||
|
result = {};
|
||||||
|
|
||||||
|
["CreatedNode", "ModifiedNode", "DeletedNode"].forEach(function (x) {
|
||||||
|
if (an[x]) result.diffType = x;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.diffType) return null;
|
||||||
|
|
||||||
|
an = an[result.diffType];
|
||||||
|
|
||||||
|
result.entryType = an.LedgerEntryType;
|
||||||
|
result.ledgerIndex = an.LedgerIndex;
|
||||||
|
|
||||||
|
result.fields = extend({}, an.PreviousFields, an.NewFields, an.FinalFields);
|
||||||
|
result.fieldsPrev = an.PreviousFields || {};
|
||||||
|
result.fieldsNew = an.NewFields || {};
|
||||||
|
result.fieldsFinal = an.FinalFields || {};
|
||||||
|
|
||||||
|
this.nodes.push(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a function on each affected node.
|
||||||
|
*
|
||||||
|
* The callback is passed two parameters. The first is a node object which looks
|
||||||
|
* like this:
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* // Type of diff, e.g. CreatedNode, ModifiedNode
|
||||||
|
* diffType: 'CreatedNode'
|
||||||
|
*
|
||||||
|
* // Type of node affected, e.g. RippleState, AccountRoot
|
||||||
|
* entryType: 'RippleState',
|
||||||
|
*
|
||||||
|
* // Index of the ledger this change occurred in
|
||||||
|
* ledgerIndex: '01AB01AB...',
|
||||||
|
*
|
||||||
|
* // Contains all fields with later versions taking precedence
|
||||||
|
* //
|
||||||
|
* // This is a shorthand for doing things like checking which account
|
||||||
|
* // this affected without having to check the diffType.
|
||||||
|
* fields: {...},
|
||||||
|
*
|
||||||
|
* // Old fields (before the change)
|
||||||
|
* fieldsPrev: {...},
|
||||||
|
*
|
||||||
|
* // New fields (that have been added)
|
||||||
|
* fieldsNew: {...},
|
||||||
|
*
|
||||||
|
* // Changed fields
|
||||||
|
* fieldsFinal: {...}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* The second parameter to the callback is the index of the node in the metadata
|
||||||
|
* (first entry is index 0).
|
||||||
|
*/
|
||||||
|
Meta.prototype.each = function (fn)
|
||||||
|
{
|
||||||
|
for (var i = 0, l = this.nodes.length; i < l; i++) {
|
||||||
|
fn(this.nodes[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.Meta = Meta;
|
||||||
@@ -20,6 +20,8 @@ var Amount = require('./amount').Amount;
|
|||||||
var Currency = require('./amount').Currency;
|
var Currency = require('./amount').Currency;
|
||||||
var UInt160 = require('./amount').UInt160;
|
var UInt160 = require('./amount').UInt160;
|
||||||
var Transaction = require('./transaction').Transaction;
|
var Transaction = require('./transaction').Transaction;
|
||||||
|
var Account = require('./account').Account;
|
||||||
|
var Meta = require('./meta').Meta;
|
||||||
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var config = require('./config');
|
var config = require('./config');
|
||||||
@@ -233,6 +235,7 @@ var Remote = function (opts, trace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache information for accounts.
|
// Cache information for accounts.
|
||||||
|
// DEPRECATED, will be removed
|
||||||
this.accounts = {
|
this.accounts = {
|
||||||
// Consider sequence numbers stable if you know you're not generating bad transactions.
|
// Consider sequence numbers stable if you know you're not generating bad transactions.
|
||||||
// Otherwise, clear it to have it automatically refreshed from the network.
|
// Otherwise, clear it to have it automatically refreshed from the network.
|
||||||
@@ -241,6 +244,9 @@ var Remote = function (opts, trace) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hash map of Account objects by AccountId.
|
||||||
|
this._accounts = {};
|
||||||
|
|
||||||
// List of secrets that we know about.
|
// List of secrets that we know about.
|
||||||
this.secrets = {
|
this.secrets = {
|
||||||
// Secrets can be set by calling set_secret(account, secret).
|
// Secrets can be set by calling set_secret(account, secret).
|
||||||
@@ -507,6 +513,7 @@ Remote.prototype._connect_start = function () {
|
|||||||
|
|
||||||
// It is possible for messages to be dispatched after the connection is closed.
|
// It is possible for messages to be dispatched after the connection is closed.
|
||||||
Remote.prototype._connect_message = function (ws, json) {
|
Remote.prototype._connect_message = function (ws, json) {
|
||||||
|
var self = this;
|
||||||
var message = JSON.parse(json);
|
var message = JSON.parse(json);
|
||||||
var unexpected = false;
|
var unexpected = false;
|
||||||
var request;
|
var request;
|
||||||
@@ -557,6 +564,23 @@ Remote.prototype._connect_message = function (ws, json) {
|
|||||||
case 'account':
|
case 'account':
|
||||||
// XXX If not trusted, need proof.
|
// XXX If not trusted, need proof.
|
||||||
|
|
||||||
|
// Process metadata
|
||||||
|
message.mmeta = new Meta(message.meta);
|
||||||
|
|
||||||
|
// Pass the event on to any related Account objects
|
||||||
|
message.mmeta.each(function (an) {
|
||||||
|
if (an.entryType === 'AccountRoot') {
|
||||||
|
var account = self._accounts[an.fields.Account];
|
||||||
|
|
||||||
|
// Only trigger the event if the account object is actually
|
||||||
|
// subscribed - this prevents some weird phantom events from
|
||||||
|
// occurring.
|
||||||
|
if (account && account._subs) {
|
||||||
|
account.emit('transaction', message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.emit('account', message);
|
this.emit('account', message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -994,6 +1018,14 @@ Remote.prototype.request_owner_count = function (account, current) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Remote.prototype.account = function (accountId) {
|
||||||
|
var account = new Account(this, accountId);
|
||||||
|
|
||||||
|
if (!account.is_valid()) return account;
|
||||||
|
|
||||||
|
return this._accounts[account.to_json()] = account;
|
||||||
|
};
|
||||||
|
|
||||||
// Return the next account sequence if possible.
|
// Return the next account sequence if possible.
|
||||||
// <-- undefined or Sequence
|
// <-- undefined or Sequence
|
||||||
Remote.prototype.account_seq = function (account, advance) {
|
Remote.prototype.account_seq = function (account, advance) {
|
||||||
|
|||||||
Reference in New Issue
Block a user