@bithomp/xrpl-api
Version:
A Bithomp JavaScript/TypeScript library for interacting with the XRP Ledger
215 lines (214 loc) • 9.02 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.parseAmmChanges = parseAmmChanges;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const common_1 = require("../../common");
const utils_1 = require("../utils");
const amount_1 = __importDefault(require("../ledger/amount"));
const asset_1 = __importDefault(require("../ledger/asset"));
const auth_accounts_1 = __importDefault(require("../ledger/auth-accounts"));
const client_1 = require("../../client");
const models_1 = require("../../models");
function parseAmmStatus(node) {
if (node.diffType === "CreatedNode") {
return "created";
}
if (node.diffType === "ModifiedNode") {
return "modified";
}
if (node.diffType === "DeletedNode") {
return "deleted";
}
return undefined;
}
function parseAuctionSlot(auctionSlot) {
const slot = {
account: auctionSlot.Account,
authAccounts: (0, auth_accounts_1.default)(auctionSlot.AuthAccounts),
discountedFee: auctionSlot.DiscountedFee,
expiration: auctionSlot.Expiration ? (0, models_1.ledgerTimeToUnixTime)(auctionSlot.Expiration) : undefined,
price: auctionSlot.Price,
timeInterval: auctionSlot.TimeInterval,
};
return (0, common_1.removeUndefined)(slot);
}
function parseVoteSlot(voteSlot) {
return {
account: voteSlot.VoteEntry.Account,
tradingFee: voteSlot.VoteEntry.TradingFee,
voteWeight: voteSlot.VoteEntry.VoteWeight,
};
}
function summarizeVoteSlotsChanges(node) {
const final = node.diffType === "CreatedNode" ? node.newFields : node.finalFields;
const prev = node.previousFields;
const changes = final.VoteSlots.reduce((acc, slot) => {
const prevSlot = prev.VoteSlots.find((s) => s.VoteEntry.Account === slot.VoteEntry.Account);
if (!prevSlot) {
return acc.concat({
status: "added",
account: slot.VoteEntry.Account,
tradingFee: slot.VoteEntry.TradingFee,
voteWeight: slot.VoteEntry.VoteWeight,
});
}
const tradingFeeChange = slot.VoteEntry.TradingFee - prevSlot.VoteEntry.TradingFee;
const voteWeightChange = slot.VoteEntry.VoteWeight - prevSlot.VoteEntry.VoteWeight;
if (tradingFeeChange !== 0 || voteWeightChange !== 0) {
return acc.concat((0, common_1.removeUndefined)({
status: "modified",
account: slot.VoteEntry.Account,
tradingFee: slot.VoteEntry.TradingFee,
voteWeight: slot.VoteEntry.VoteWeight,
tradingFeeChange: tradingFeeChange || undefined,
voteWeightChange: voteWeightChange || undefined,
}));
}
return acc;
}, []);
const removed = prev.VoteSlots.filter((s) => {
return !final.VoteSlots.find((slot) => slot.VoteEntry.Account === s.VoteEntry.Account);
});
if (removed.length > 0) {
return changes.concat(removed.map((s) => {
return {
status: "removed",
account: s.VoteEntry.Account,
tradingFee: s.VoteEntry.TradingFee,
voteWeight: s.VoteEntry.VoteWeight,
};
}));
}
if (changes.length === 0) {
return undefined;
}
return changes;
}
function summarizeActionSlotChanges(node) {
const final = node.diffType === "CreatedNode" ? node.newFields : node.finalFields;
const prev = node.previousFields;
const changes = {};
if (prev.AuctionSlot) {
if (final.AuctionSlot.Account !== prev.AuctionSlot.Account) {
changes.accountChanges = final.AuctionSlot.Account;
}
if (final.AuctionSlot.DiscountedFee !== prev.AuctionSlot.DiscountedFee) {
changes.discountedFeeChange = final.AuctionSlot.DiscountedFee - prev.AuctionSlot.DiscountedFee;
}
if (final.AuctionSlot.Expiration !== prev.AuctionSlot.Expiration) {
changes.expirationChange = final.AuctionSlot.Expiration - prev.AuctionSlot.Expiration;
}
if (final.AuctionSlot.Price.value !== prev.AuctionSlot.Price.value) {
changes.priceChange = {
currency: final.AuctionSlot.Price.currency,
issuer: final.AuctionSlot.Price.issuer,
value: new bignumber_js_1.default(final.AuctionSlot.Price.value)
.minus(new bignumber_js_1.default(prev.AuctionSlot.Price.value))
.toString(10),
counterparty: final.AuctionSlot.Price.issuer,
};
}
if (final.AuctionSlot.TimeInterval !== prev.AuctionSlot.TimeInterval) {
changes.timeIntervalChange = final.AuctionSlot.TimeInterval - prev.AuctionSlot.TimeInterval;
}
if (!isEqualAuthAccounts(final.AuctionSlot.AuthAccounts, prev.AuctionSlot.AuthAccounts)) {
const prevAuthAccounts = prev.AuctionSlot.AuthAccounts || [];
const finalAuthAccounts = final.AuctionSlot.AuthAccounts || [];
let authAccountsChanges = finalAuthAccounts.map((auth) => {
if (!prevAuthAccounts.includes(auth.AuthAccount.Account)) {
return {
status: "added",
account: auth.AuthAccount.Account,
};
}
});
const removed = prevAuthAccounts.filter((auth) => {
return !finalAuthAccounts.includes(auth.AuthAccount.Account);
});
if (removed.length > 0) {
authAccountsChanges = authAccountsChanges.concat(removed.map((account) => {
return {
status: "removed",
account: account.AuthAccount.Account,
};
}));
}
changes.authAccountsChanges = authAccountsChanges;
}
}
if (Object.keys(changes).length === 0) {
return undefined;
}
return (0, common_1.removeUndefined)(changes);
}
function isEqualAuthAccounts(obj1, obj2) {
if (obj1 === undefined && obj2 === undefined) {
return true;
}
if ((obj1 === undefined && obj2 !== undefined) || (obj1 !== undefined && obj2 === undefined)) {
return false;
}
if (obj1.length !== obj2.length) {
return false;
}
const obj1Sorted = obj1.sort((a, b) => a.AuthAccount.Account.localeCompare(b.AuthAccount.Account));
const obj2Sorted = obj2.sort((a, b) => a.AuthAccount.Account.localeCompare(b.AuthAccount.Account));
for (let i = 0; i < obj1Sorted.length; i++) {
if (obj1Sorted[i].AuthAccount.Account !== obj2Sorted[i].AuthAccount.Account) {
return false;
}
}
return true;
}
function summarizeAmm(node) {
const final = node.diffType === "CreatedNode" ? node.newFields : node.finalFields;
const prev = node.previousFields;
let asset = (0, asset_1.default)(final.Asset);
if (node.diffType === "CreatedNode" && !asset) {
asset = { currency: (0, client_1.getNativeCurrency)() };
}
const summary = {
status: parseAmmStatus(node),
ammID: node.ledgerIndex,
account: final.Account,
asset: asset,
asset2: (0, asset_1.default)(final.Asset2),
auctionSlot: parseAuctionSlot(final.AuctionSlot),
lpTokenBalance: (0, amount_1.default)(final.LPTokenBalance),
tradingFee: final.TradingFee,
ownerNode: final.OwnerNode,
voteSlots: final.VoteSlots ? final.VoteSlots.map(parseVoteSlot) : undefined,
};
if (prev.LPTokenBalance) {
summary.lpTokenBalanceChange = {
currency: final.LPTokenBalance.currency,
issuer: final.LPTokenBalance.issuer,
value: new bignumber_js_1.default(final.LPTokenBalance.value).minus(new bignumber_js_1.default(prev.LPTokenBalance.value)).toString(10),
counterparty: final.LPTokenBalance.issuer,
};
}
if (prev.VoteSlots) {
summary.voteSlotsChanges = summarizeVoteSlotsChanges(node);
}
if (prev.TradingFee) {
summary.tradingFeeChanges = final.TradingFee - (prev.TradingFee || 0);
}
if (prev.AuctionSlot) {
summary.auctionSlotChanges = summarizeActionSlotChanges(node);
}
return (0, common_1.removeUndefined)(summary);
}
function parseAmmChanges(metadata) {
const affectedNodes = metadata.AffectedNodes.filter((affectedNode) => {
const node = affectedNode.CreatedNode || affectedNode.ModifiedNode || affectedNode.DeletedNode;
return node.LedgerEntryType === "AMM";
});
if (affectedNodes.length !== 1) {
return undefined;
}
const normalizedNode = (0, utils_1.normalizeNode)(affectedNodes[0]);
return summarizeAmm(normalizedNode);
}