mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-07 09:08:14 -07:00
88 lines
2.0 KiB
JavaScript
88 lines
2.0 KiB
JavaScript
import { mapConcurrent } from "../../concurrent.js";
|
|
|
|
const HISTORY_CONCURRENCY = 4;
|
|
const MAX_SELECTED_ADDRESS_TXS = 100;
|
|
|
|
const historyByBucketKey =
|
|
/** @type {Map<string, Promise<Map<string, ApiTransaction[]>>>} */ (new Map());
|
|
|
|
/**
|
|
* @typedef {import("../../scan/index.js").WalletAddress} WalletAddress
|
|
* @typedef {import("./transaction.js").ApiTransaction} ApiTransaction
|
|
*/
|
|
|
|
/**
|
|
* @typedef {Object} AddressHistoryClient
|
|
* @property {(address: string, options?: { cache?: boolean }) => Promise<ApiTransaction[]>} getAddressTxs
|
|
*/
|
|
|
|
/**
|
|
* @typedef {Object} AddressHistory
|
|
* @property {ApiTransaction[]} transactions
|
|
*/
|
|
|
|
/**
|
|
* @param {readonly string[]} addresses
|
|
*/
|
|
function createBucketKey(addresses) {
|
|
return [...addresses].sort().join("\n");
|
|
}
|
|
|
|
/**
|
|
* @param {AddressHistoryClient} client
|
|
* @param {readonly string[]} addresses
|
|
* @returns {Promise<Map<string, ApiTransaction[]>>}
|
|
*/
|
|
async function fetchBucketHistory(client, addresses) {
|
|
const entries = await mapConcurrent(
|
|
addresses,
|
|
HISTORY_CONCURRENCY,
|
|
async (address) => {
|
|
const transactions = await client.getAddressTxs(address, { cache: false });
|
|
|
|
return /** @type {const} */ ([address, transactions]);
|
|
},
|
|
);
|
|
|
|
return new Map(entries);
|
|
}
|
|
|
|
/**
|
|
* @param {AddressHistoryClient} client
|
|
* @param {WalletAddress} address
|
|
* @returns {Promise<AddressHistory>}
|
|
*/
|
|
async function load(client, address) {
|
|
if (
|
|
address.txCount > MAX_SELECTED_ADDRESS_TXS ||
|
|
address.historyAddresses.length === 0
|
|
) {
|
|
return {
|
|
transactions: [],
|
|
};
|
|
}
|
|
|
|
const key = createBucketKey(address.historyAddresses);
|
|
let history = historyByBucketKey.get(key);
|
|
|
|
if (!history) {
|
|
history = fetchBucketHistory(client, address.historyAddresses).catch(
|
|
(error) => {
|
|
historyByBucketKey.delete(key);
|
|
throw error;
|
|
},
|
|
);
|
|
historyByBucketKey.set(key, history);
|
|
}
|
|
|
|
const bucketHistory = await history;
|
|
|
|
return {
|
|
transactions: bucketHistory.get(address.address) ?? [],
|
|
};
|
|
}
|
|
|
|
export const addressHistory = /** @type {const} */ ({
|
|
load,
|
|
});
|