From 82f14395fb2f3da0afa68842341af366f179885e Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Fri, 15 Feb 2013 14:43:24 +0100 Subject: [PATCH] JS: Correctly calculate affected accounts when routing account events. --- src/js/meta.js | 36 +++++++++++++++++++++++++++++++++++- src/js/remote.js | 20 ++++++++++---------- src/js/uint.js | 4 ++++ 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/js/meta.js b/src/js/meta.js index ac0e108c..5d93446d 100644 --- a/src/js/meta.js +++ b/src/js/meta.js @@ -1,4 +1,6 @@ var extend = require('extend'); +var UInt160 = require('./uint160').UInt160; +var Amount = require('./amount').Amount; /** * Meta data processing facility. @@ -71,6 +73,38 @@ Meta.prototype.each = function (fn) for (var i = 0, l = this.nodes.length; i < l; i++) { fn(this.nodes[i], i); } -} +}; + +var amountFieldsAffectingIssuer = [ + "LowLimit", "HighLimit", "TakerPays", "TakerGets" +]; +Meta.prototype.getAffectedAccounts = function () +{ + var accounts = []; + + // This code should match the behavior of the C++ method: + // TransactionMetaSet::getAffectedAccounts + this.each(function (an) { + var fields = (an.diffType === "CreatedNode") ? an.fieldsNew : an.fieldsFinal; + + for (var i in fields) { + var field = fields[i]; + + if ("string" === typeof field && UInt160.is_valid(field)) { + accounts.push(field); + } else if (amountFieldsAffectingIssuer.indexOf(i) !== -1) { + var amount = Amount.from_json(field); + var issuer = amount.issuer(); + if (issuer.is_valid() && !issuer.is_zero()) { + accounts.push(issuer.to_json()); + } + } + } + }); + + console.log("AFFECTS", accounts); + + return accounts; +}; exports.Meta = Meta; diff --git a/src/js/remote.js b/src/js/remote.js index 0bb467bc..9fdd70f6 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -573,23 +573,23 @@ Remote.prototype._connect_message = function (ws, json) { case 'account': // XXX If not trusted, need proof. + if (this.trace) utils.logObject("remote: account: %s", message); // 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]; + var affected = message.mmeta.getAffectedAccounts(); + for (var i = 0, l = affected.length; i < l; i++) { + var account = self._accounts[affected[i]]; - // 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); - } + // 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; diff --git a/src/js/uint.js b/src/js/uint.js index 100dfc9c..c02d8b27 100644 --- a/src/js/uint.js +++ b/src/js/uint.js @@ -92,6 +92,10 @@ UInt.prototype.is_valid = function () { return this._value instanceof BigInteger; }; +UInt.prototype.is_zero = function () { + return this._value.equals(BigInteger.ZERO); +}; + // value = NaN on error. UInt.prototype.parse_generic = function (j) { // Canonicalize and validate