@ledgerhq/coin-tron
Version:
Ledger Tron Coin integration
74 lines • 3.78 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.listOperations = listOperations;
const live_promise_1 = require("@ledgerhq/live-promise");
const uniqBy_1 = __importDefault(require("lodash/uniqBy"));
const network_1 = require("../network");
const trongrid_adapters_1 = require("../network/trongrid/trongrid-adapters");
const cursor_1 = require("./cursor");
const errors_1 = require("../types/errors");
async function listOperations(address, options) {
const { limit, order, cursor } = options;
const parsedCursor = (0, cursor_1.parseCursor)(cursor);
// For asc: cursor timestamp is the new lower bound (we're moving forward in time)
// For desc: cursor timestamp is the new upper bound (we're moving backward in time)
// minTimestamp remains the lower bound (the stopping point)
let fetchMinTimestamp;
let fetchMaxTimestamp;
if (order === "asc") {
fetchMinTimestamp = parsedCursor ? parsedCursor.timestamp : options.minTimestamp;
fetchMaxTimestamp = undefined;
}
else {
fetchMinTimestamp = options.minTimestamp;
fetchMaxTimestamp = parsedCursor?.timestamp;
}
// Fetch native and TRC20 transactions in parallel from TronGrid.
// Both endpoints are queried with the same timestamp bounds to ensure
// we can properly merge and sort them chronologically.
const { nativeTxs, trc20Txs } = await (0, network_1.fetchTronAccountTxsPage)(address, {
limit,
minTimestamp: fetchMinTimestamp,
maxTimestamp: fetchMaxTimestamp,
order,
});
// TronGrid occasionally returns an empty page for a valid cursor (transient API failure).
// A cursor is only issued when TronGrid indicated hasNextPage=true, so 0 results here
// is never a legitimate end-of-stream — throw so the client can retry with the same cursor.
if (parsedCursor && nativeTxs.txs.length === 0 && trc20Txs.txs.length === 0) {
throw new errors_1.TronEmptyPage(`TronGrid returned empty page for cursor ${cursor} — transient failure, retry required`);
}
// Merge and dedupe: some transactions appear in both native and TRC20 results
const mergedTxs = (0, uniqBy_1.default)([...nativeTxs.txs, ...trc20Txs.txs], tx => tx.txID);
const sortedTxs = [...mergedTxs].sort((0, cursor_1.compareTxsByTimestamp)(order));
const afterCursorTxs = (0, cursor_1.dropTxsBeforeCursor)({ txs: sortedTxs, order, cursor: parsedCursor });
const { txs: pageTxs, nextCursor } = (0, cursor_1.dropTxsAfterNextCursor)({
order,
cursor,
pageTxs: afterCursorTxs,
nativeResult: nativeTxs,
trc20Result: trc20Txs,
});
const blocksByHeight = new Map();
const uniqueHeights = Array.from(new Set(pageTxs.map(tx => tx.blockHeight).filter((h) => typeof h === "number")));
await (0, live_promise_1.promiseAllBatched)(5, uniqueHeights, async (height) => {
const fetchedBlock = await (0, network_1.getBlock)(height);
blocksByHeight.set(height, fetchedBlock);
});
const operations = pageTxs.map(tx => {
const height = tx.blockHeight;
if (typeof height !== "number") {
throw new Error(`Transaction ${tx.txID} has no block height`);
}
const txBlock = blocksByHeight.get(height);
if (!txBlock) {
throw new Error(`Block ${height} not found for transaction ${tx.txID}`);
}
return (0, trongrid_adapters_1.fromTrongridTxInfoToOperation)(tx, txBlock, address);
});
return { items: operations, next: nextCursor };
}
//# sourceMappingURL=listOperations.js.map