Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
123 lines (109 sloc) 4.58 KB
part of rippledex.daemon;
void handleTransaction(TransactionResult tx) {
TransactionType type = tx.transaction.type;
if(!(type == TransactionType.PAYMENT || type == TransactionType.OFFER_CREATE))
return;
if(tx.meta == null)
return;
// extract modified and deleted OFFER entries in tx meta
Iterable<AffectedNode> relevantOffers = findModifiedOffers(tx.meta);
// convert the nodes to ValueExchange objects
Iterable<ValueExchange> exchanges = parseOffersForExchanges(relevantOffers);
// we only want items from known gateways
exchanges = exchanges.where((ex) =>
xrpOrGateway(ex.getAmount.issue) && xrpOrGateway(ex.payAmount.issue));
// filter out those where neither of the issues is XRP
//TODO try to find method to incorporate non-XRP offers
exchanges = exchanges.where((ex) => ex.hasXRP);
// save
if(exchanges.isEmpty)
return;
log.fine("Saving ${exchanges.length} ValueExchange objects: $exchanges");
mongo.saveExchanges(exchanges);
}
bool xrpOrGateway(Issue issue) => issue.isNative || gateways.addresses.contains(issue.issuer.address);
Iterable<AffectedNode> findModifiedOffers(TransactionMeta meta) {
return meta.affectedNodes.where((AffectedNode node) =>
node.ledgerEntryType == LedgerEntryType.OFFER && node is! CreatedNode);
}
Iterable<ValueExchange> parseOffersForExchanges(Iterable<AffectedNode> offers) {
return offers.where((node) => !(node is DeletedNode && node.previousFields == null)).map((node) {
Amount newTakerGets = node.finalFields["TakerGets"];
Amount newTakerPays = node.finalFields["TakerPays"];
Amount oldTakerGets = node.previousFields["TakerGets"];
Amount oldTakerPays = node.previousFields["TakerPays"];
if(newTakerGets == null || newTakerPays == null || oldTakerGets == null || oldTakerPays == null)
return null;
Amount payAmount = oldTakerPays - newTakerPays;
Amount getAmount = oldTakerGets - newTakerGets;
return new ValueExchange(payAmount, getAmount);
}).where((ve) => ve != null);
}
// old code with a different approach. might come in handy to extend the offer-only approach
//
//Iterable<AffectedNode> findRelevantNodes(TransactionMeta meta) {
// return meta.affectedNodes.where((AffectedNode node) =>
// node.ledgerEntryType == LedgerEntryType.ACCOUNT_ROOT ||
// node.ledgerEntryType == LedgerEntryType.RIPPLE_STATE
// );
//}
//
//List<BalanceChange> parseBalanceChanges(Iterable<AffectedNode> nodes) {
// List<BalanceChange> changes = new List<BalanceChange>();
// nodes.forEach((AffectedNode node) {
// Map finalFields;
// Map previousFields;
// if(node is ModifiedNode) {
// finalFields = node.finalFields;
// previousFields = node.previousFields;
// } else if(node is DeletedNode) {
// finalFields = node.finalFields;
// previousFields = node.previousFields;
// } else if(node is CreatedNode) {
// finalFields = node.newFields;
// if(finalFields == null) return;
// previousFields = {"Balance": new Amount(zero, finalFields["Balance"].currency, finalFields["Balance"].issuer)};
// }
// if(finalFields == null || previousFields == null) {
// log.warning("Some fields were null: $node");
// return;
// }
// Amount newBalance = finalFields["Balance"];
// Amount oldBalance = previousFields["Balance"];
// if(oldBalance == null || newBalance == null)
// return;
// Amount change = newBalance - oldBalance;
// Account account;
// if(node.ledgerEntryType == LedgerEntryType.ACCOUNT_ROOT) {
// account = finalFields["Account"];
// } else if(node.ledgerEntryType == LedgerEntryType.RIPPLE_STATE) {
// Amount lowLimit = new Amount.fromJson(finalFields["LowLimit"]);
// Amount highLimit = new Amount.fromJson(finalFields["HighLimit"]);
// Account issuer;
// if(lowLimit.value == zero && highLimit.value != zero) {
// issuer = lowLimit.issuer;
// account = highLimit.issuer;
// } else if(highLimit.value == zero && lowLimit.value != zero) {
// issuer = highLimit.issuer;
// account = lowLimit.issuer;
// change = -change;
// } else {
// // rather rare case, not sure what to do here
// log.warning("Both limits zero in ripple_state change: $nodes");
// return;
// }
// change = new Amount(change.value, change.currency, issuer);
// }
// changes.add(new BalanceChange(account, change));
// });
// return changes;
//}
//Decimal zero = Decimal.parse("0");
//
//class BalanceChange {
// Account account;
// Amount change;
// BalanceChange(this.account, this.change);
// @override
// String toString() => "$account: $change";
//}