mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-12-06 17:27:59 +00:00
Broadcast transaction submission requests, use average server fee
This commit is contained in:
@@ -688,7 +688,7 @@ Server.prototype._computeFee = function(transaction) {
|
||||
var units;
|
||||
|
||||
if (transaction instanceof Transaction) {
|
||||
units = transaction.feeUnits();
|
||||
units = transaction._getFeeUnits();
|
||||
} else if (typeof transaction === 'number') {
|
||||
units = transaction;
|
||||
} else {
|
||||
|
||||
@@ -245,37 +245,29 @@ Transaction.prototype._accountSecret = function(account) {
|
||||
* @return {Number} Number of fee units for this transaction.
|
||||
*/
|
||||
|
||||
Transaction.prototype.getFee =
|
||||
Transaction.prototype._getFeeUnits =
|
||||
Transaction.prototype.feeUnits = function() {
|
||||
return Transaction.fee_units['default'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the server whose fee is currently the lowest
|
||||
* Compute average server fee
|
||||
*/
|
||||
|
||||
Transaction.prototype._getServer = function() {
|
||||
var self = this;
|
||||
Transaction.prototype._computeFee = function() {
|
||||
var servers = this.remote._servers;
|
||||
var fee = Infinity;
|
||||
var result;
|
||||
var serverCount = 0;
|
||||
var fee = 0;
|
||||
|
||||
for (var i=0; i<servers.length; i++) {
|
||||
var server = servers[i];
|
||||
|
||||
if (!server._connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var serverFee = server._computeFee(this);
|
||||
|
||||
if (serverFee < fee) {
|
||||
result = server;
|
||||
fee = serverFee;
|
||||
if (server._connected) {
|
||||
serverCount += 1;
|
||||
fee += Number(server._computeFee(this));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return String(Math.floor(fee / serverCount));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -315,8 +307,7 @@ Transaction.prototype.complete = function() {
|
||||
// an assigned server
|
||||
if (this.remote && typeof this.tx_json.Fee === 'undefined') {
|
||||
if (this.remote.local_fee || !this.remote.trusted) {
|
||||
this._server = this._getServer();
|
||||
this.tx_json.Fee = this._server._computeFee(this);
|
||||
this.tx_json.Fee = this._computeFee();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,15 +900,18 @@ Transaction.prototype.transactionManager = function() {
|
||||
};
|
||||
|
||||
Transaction.prototype.abort = function(callback) {
|
||||
var callback = (typeof callback === 'function') ? callback : function(){};
|
||||
if (!this.finalized) {
|
||||
var callback = (typeof callback === 'function') ? callback : function(){};
|
||||
this.once('final', callback);
|
||||
this.emit('abort');
|
||||
}
|
||||
};
|
||||
|
||||
Transaction.prototype.iff = function(fn) {
|
||||
this._iff = fn;
|
||||
var self = this;
|
||||
this._iff = function(callback) {
|
||||
fn(self.summary(), callback);
|
||||
};
|
||||
};
|
||||
|
||||
Transaction.prototype.summary = function() {
|
||||
@@ -934,7 +928,7 @@ Transaction.summary = function() {
|
||||
initialSubmitIndex: this.initialSubmitIndex,
|
||||
lastLedgerSequence: this.lastLedgerSequence,
|
||||
state: this.state,
|
||||
server: this._server ? this._server._opts.url : void(0),
|
||||
server: this._server ? this._server._opts.url : void(0),
|
||||
finalized: this.finalized
|
||||
};
|
||||
|
||||
|
||||
@@ -41,10 +41,10 @@ function TransactionManager(account) {
|
||||
var submission = self._pending.getSubmission(hash);
|
||||
|
||||
if (self._remote.trace) {
|
||||
log.info('transaction received:', transaction.transaction);
|
||||
log.info('transaction received:', transaction.tx_json);
|
||||
}
|
||||
|
||||
if (submission) {
|
||||
if (submission instanceof Transaction) {
|
||||
// ND: A `success` handler will `finalize` this later
|
||||
submission.emit('success', transaction);
|
||||
} else {
|
||||
@@ -54,36 +54,7 @@ function TransactionManager(account) {
|
||||
|
||||
this._account.on('transaction-outbound', transactionReceived);
|
||||
|
||||
function adjustFees(loadData, server) {
|
||||
// ND: note, that `Fee` is a component of a transactionID
|
||||
self._pending.forEach(function(pending) {
|
||||
if (pending._server !== server) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(self._remote.local_fee && pending.tx_json.Fee)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldFee = pending.tx_json.Fee;
|
||||
var newFee = server.computeFee(pending);
|
||||
|
||||
if (Number(newFee) > self._maxFee) {
|
||||
return pending.once('presubmit', function() {
|
||||
pending.emit('error', 'tejMaxFeeExceeded');
|
||||
});
|
||||
}
|
||||
|
||||
pending.tx_json.Fee = newFee;
|
||||
pending.emit('fee_adjusted', oldFee, newFee);
|
||||
|
||||
if (self._remote.trace) {
|
||||
log.info('fee adjusted:', pending.tx_json, oldFee, newFee);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this._remote.on('load_changed', adjustFees);
|
||||
this._remote.on('load_changed', this._adjustFees.bind(this));
|
||||
|
||||
function updatePendingStatus(ledger) {
|
||||
self._pending.forEach(function(pending) {
|
||||
@@ -113,6 +84,7 @@ function TransactionManager(account) {
|
||||
ledger_index_min: -1,
|
||||
ledger_index_max: -1,
|
||||
binary: true,
|
||||
parseBinary: true,
|
||||
limit: 100,
|
||||
filter: 'outbound'
|
||||
};
|
||||
@@ -193,6 +165,38 @@ TransactionManager.normalizeTransaction = function(tx) {
|
||||
return transaction;
|
||||
};
|
||||
|
||||
// Transaction fees are adjusted in real-time
|
||||
TransactionManager.prototype._adjustFees = function(loadData) {
|
||||
// ND: note, that `Fee` is a component of a transactionID
|
||||
var self = this;
|
||||
|
||||
if (!this._remote.local_fee) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._pending.forEach(function(pending) {
|
||||
var oldFee = pending.tx_json.Fee;
|
||||
var newFee = pending._computeFee();
|
||||
|
||||
function maxFeeExceeded() {
|
||||
pending.once('presubmit', function() {
|
||||
pending.emit('error', 'tejMaxFeeExceeded');
|
||||
});
|
||||
};
|
||||
|
||||
if (Number(newFee) > self._maxFee) {
|
||||
return maxFeeExceeded();
|
||||
}
|
||||
|
||||
pending.tx_json.Fee = newFee;
|
||||
pending.emit('fee_adjusted', oldFee, newFee);
|
||||
|
||||
if (self._remote.trace) {
|
||||
log.info('fee adjusted:', pending.tx_json, oldFee, newFee);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//Fill an account transaction sequence
|
||||
TransactionManager.prototype._fillSequence = function(tx, callback) {
|
||||
var self = this;
|
||||
@@ -281,6 +285,7 @@ TransactionManager.prototype._resubmit = function(ledgers, pending) {
|
||||
while (self._pending.hasSequence(pending.tx_json.Sequence)) {
|
||||
//Sequence number has been consumed by another transaction
|
||||
pending.tx_json.Sequence += 1;
|
||||
|
||||
if (self._remote.trace) {
|
||||
log.info('incrementing sequence:', pending.tx_json);
|
||||
}
|
||||
@@ -328,6 +333,7 @@ TransactionManager.prototype._waitLedgers = function(ledgers, callback) {
|
||||
}
|
||||
|
||||
self._remote.removeListener('ledger_closed', ledgerClosed);
|
||||
|
||||
callback();
|
||||
};
|
||||
|
||||
@@ -343,12 +349,6 @@ TransactionManager.prototype._request = function(tx) {
|
||||
}
|
||||
|
||||
if (tx.attempts > 0 && !remote.local_signing) {
|
||||
// && tx.submittedTxnIDs.length != tx.attempts
|
||||
// ^^^ Above commented out intentionally
|
||||
// ^^^^ We might be a bit cleverer about allowing this in SOME cases, but
|
||||
// it's not really worth it, and would be prone to error. Use
|
||||
// `local_signing`
|
||||
|
||||
var message = ''
|
||||
+ 'It is not possible to resubmit transactions automatically safely without '
|
||||
+ 'synthesizing the transactionID locally. See `local_signing` config option';
|
||||
@@ -415,7 +415,7 @@ TransactionManager.prototype._request = function(tx) {
|
||||
}
|
||||
|
||||
if (self._remote.local_fee && (message.engine_result === 'telINSUF_FEE_P')) {
|
||||
self._resubmit(1, tx);
|
||||
self._resubmit(2, tx);
|
||||
} else {
|
||||
submissionError(message);
|
||||
}
|
||||
@@ -509,17 +509,17 @@ TransactionManager.prototype._request = function(tx) {
|
||||
submitRequest.server = tx._server;
|
||||
}
|
||||
|
||||
if (typeof tx._iff !== 'function') {
|
||||
return submitTransaction();
|
||||
if (typeof tx._iff === 'function') {
|
||||
tx._iff(function(err, proceed) {
|
||||
if (err || !proceed) {
|
||||
tx.emit('abort');
|
||||
} else {
|
||||
submitTransaction();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
submitTransaction();
|
||||
}
|
||||
|
||||
tx._iff(tx.summary(), function(err, proceed) {
|
||||
if (err || !proceed) {
|
||||
tx.emit('abort');
|
||||
} else {
|
||||
submitTransaction();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function requestTimeout() {
|
||||
@@ -553,7 +553,7 @@ TransactionManager.prototype._request = function(tx) {
|
||||
}
|
||||
|
||||
submitRequest.timeout(self._submissionTimeout, requestTimeout);
|
||||
submitRequest.request();
|
||||
submitRequest.broadcast();
|
||||
|
||||
tx.attempts++;
|
||||
tx.emit('postsubmit');
|
||||
@@ -608,7 +608,7 @@ TransactionManager._isTooBusy = function(error) {
|
||||
/**
|
||||
* Entry point for TransactionManager submission
|
||||
*
|
||||
* @param {Object} tx
|
||||
* @param {Transaction} tx
|
||||
*/
|
||||
|
||||
TransactionManager.prototype.submit = function(tx) {
|
||||
|
||||
Reference in New Issue
Block a user