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 EventEmitter = require('events').EventEmitter;
|
||||
var Amount = require('./amount.js').Amount;
|
||||
var UInt160 = require('./amount.js').UInt160;
|
||||
var Amount = require('./amount').Amount;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
|
||||
var Account = function (network, account) {
|
||||
this._network = network;
|
||||
this._account = UInt160.json_rewrite(account);
|
||||
var Account = function (remote, account) {
|
||||
var self = this;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
// 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 UInt160 = require('./amount').UInt160;
|
||||
var Transaction = require('./transaction').Transaction;
|
||||
var Account = require('./account').Account;
|
||||
var Meta = require('./meta').Meta;
|
||||
|
||||
var utils = require('./utils');
|
||||
var config = require('./config');
|
||||
@@ -233,6 +235,7 @@ var Remote = function (opts, trace) {
|
||||
}
|
||||
|
||||
// Cache information for accounts.
|
||||
// DEPRECATED, will be removed
|
||||
this.accounts = {
|
||||
// Consider sequence numbers stable if you know you're not generating bad transactions.
|
||||
// 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.
|
||||
this.secrets = {
|
||||
// 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.
|
||||
Remote.prototype._connect_message = function (ws, json) {
|
||||
var self = this;
|
||||
var message = JSON.parse(json);
|
||||
var unexpected = false;
|
||||
var request;
|
||||
@@ -557,6 +564,23 @@ Remote.prototype._connect_message = function (ws, json) {
|
||||
case 'account':
|
||||
// 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);
|
||||
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.
|
||||
// <-- undefined or Sequence
|
||||
Remote.prototype.account_seq = function (account, advance) {
|
||||
|
||||
Reference in New Issue
Block a user