@bithomp/xrpl-api
Version:
A Bithomp JavaScript/TypeScript library for interacting with the XRP Ledger
105 lines (104 loc) • 4.67 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseOrderbookChanges = parseOrderbookChanges;
const lodash_1 = __importDefault(require("lodash"));
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const BigNumber = bignumber_js_1.default.clone({ DECIMAL_PLACES: 40 });
const xrpl_1 = require("xrpl");
const common_1 = require("../../common");
const models_1 = require("../../models");
const utils_1 = require("../utils");
const orderbook_quality_1 = require("./orderbook_quality");
const currency_amount_1 = __importDefault(require("../ledger/currency-amount"));
const offer_flags_1 = __importDefault(require("../ledger/offer-flags"));
const client_1 = require("../../client");
function getExpirationTime(node) {
const expirationTime = (node.finalFields.Expiration || node.newFields.Expiration);
if (expirationTime === undefined) {
return undefined;
}
return new Date((0, models_1.ledgerTimeToTimestamp)(expirationTime)).toISOString();
}
function getQuality(node) {
const takerGets = (node.finalFields.TakerGets || node.newFields.TakerGets);
const takerPays = (node.finalFields.TakerPays || node.newFields.TakerPays);
const takerGetsCurrency = takerGets.currency || (0, client_1.getNativeCurrency)();
const takerPaysCurrency = takerPays.currency || (0, client_1.getNativeCurrency)();
const bookDirectory = (node.finalFields.BookDirectory || node.newFields.BookDirectory);
const qualityHex = bookDirectory.substring(bookDirectory.length - 16);
return (0, orderbook_quality_1.parseOrderbookQuality)(qualityHex, takerGetsCurrency, takerPaysCurrency);
}
function parseOrderStatus(node) {
if (node.diffType === "CreatedNode") {
return "created";
}
if (node.diffType === "ModifiedNode") {
return "partially-filled";
}
if (node.diffType === "DeletedNode") {
if (node.previousFields.hasOwnProperty("TakerPays")) {
return "filled";
}
return "cancelled";
}
return undefined;
}
function calculateDelta(finalAmount, previousAmount) {
if (previousAmount) {
const finalValue = new BigNumber(finalAmount.value);
const previousValue = new BigNumber(previousAmount.value);
return finalValue.minus(previousValue).abs().toString();
}
return "0";
}
function parseChangeAmount(node, type) {
const status = parseOrderStatus(node);
if (status === "cancelled") {
return (0, currency_amount_1.default)(node.finalFields[type]);
}
else if (status === "created") {
return (0, currency_amount_1.default)(node.newFields[type]);
}
const finalAmount = (0, currency_amount_1.default)(node.finalFields[type]);
const previousAmount = (0, currency_amount_1.default)(node.previousFields[type]);
const value = calculateDelta(finalAmount, previousAmount);
return lodash_1.default.assign({}, finalAmount, { value: value });
}
function parseOrderChange(node) {
const flags = (0, offer_flags_1.default)(node.finalFields.Flags);
const takerPays = parseChangeAmount(node, "TakerPays");
const takerGets = parseChangeAmount(node, "TakerGets");
const orderChange = (0, common_1.removeUndefined)({
flags,
quantity: flags.sell === true ? takerGets : takerPays,
totalPrice: flags.sell === true ? takerPays : takerGets,
sequence: (node.finalFields.Sequence || node.newFields.Sequence),
status: parseOrderStatus(node),
makerExchangeRate: getQuality(node),
expirationTime: getExpirationTime(node),
direction: (node.finalFields.Flags & xrpl_1.LedgerEntry.OfferFlags.lsfSell) === 0 ? "buy" : "sell",
});
Object.defineProperty(orderChange, "account", {
value: node.finalFields.Account || node.newFields.Account,
});
return orderChange;
}
function groupByAddress(orderChanges) {
return lodash_1.default.groupBy(orderChanges, function (change) {
return change.account;
});
}
function parseOrderbookChanges(metadata) {
const affectedNodes = metadata.AffectedNodes.filter((affectedNode) => {
const node = affectedNode.CreatedNode || affectedNode.ModifiedNode || affectedNode.DeletedNode;
return node.LedgerEntryType === "Offer";
});
const orderChanges = affectedNodes.map((affectedNode) => {
const normalizedNode = (0, utils_1.normalizeNode)(affectedNode);
return parseOrderChange(normalizedNode);
});
return groupByAddress(orderChanges);
}