Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/cardano-services-client/src/blockfrost/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ export const fetchSequentially = async <Response, Item = Response>(
haveEnoughItems?: (allItems: Item[], lastResponseBatch: Response[]) => boolean;
paginationOptions?: PaginationOptions;
},
page = 1,
accumulated: Item[] = []
): Promise<Item[]> => {
const count = props.paginationOptions?.count || 100;
const page = props.paginationOptions?.page || 1;
try {
const response = await props.request(buildQueryString({ count, order: props.paginationOptions?.order, page }));
const maybeTranslatedResponse = props.responseTranslator ? props.responseTranslator(response) : response;
const newAccumulatedItems = [...accumulated, ...maybeTranslatedResponse] as Item[];
const haveEnoughItems = props.haveEnoughItems?.(newAccumulatedItems, response);
if (response.length === count && !haveEnoughItems) {
return fetchSequentially<Response, Item>(props, page + 1, newAccumulatedItems);
return fetchSequentially<Response, Item>(
{ ...props, paginationOptions: { ...props.paginationOptions, page: page + 1 } },
newAccumulatedItems
);
}
return newAccumulatedItems;
} catch (error) {
Expand Down
53 changes: 46 additions & 7 deletions packages/wallet/src/services/TransactionsTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import { newAndStoredMulticast } from './util/newAndStoredMulticast';
import chunk from 'lodash/chunk.js';
import sortBy from 'lodash/sortBy.js';

const ONE_MONTH_BLOCK_TIME = 21_600 * 6;

export interface TransactionsTrackerProps {
chainHistoryProvider: ChainHistoryProvider;
addresses$: Observable<Cardano.PaymentAddress[]>;
Expand Down Expand Up @@ -140,7 +142,7 @@ const allTransactionsByAddresses = async (

startAt += PAGE_SIZE;
response = [...response, ...pageResults];
} while (pageResults.length === PAGE_SIZE);
} while (pageResults.length >= PAGE_SIZE);
} else {
const txes = await chainHistoryProvider.transactionsByAddresses({
addresses: addressGroup,
Expand Down Expand Up @@ -201,6 +203,43 @@ export const revertLastBlock = (
return deduplicateSortedArray(result, txEquals);
};

/**
* Fetches the last `historicalTransactionsFetchLimit` transactions for a set of addresses.
* If there is a single address, it returns the most recent ones up to `historicalTransactionsFetchLimit`. If there
* are more than one address, it returns all transaction from all addresses, one month back from the most recent transaction.
*
* @param {ChainHistoryProvider} chainHistoryProvider - The chain history provider used to fetch transaction history.
* @param {Cardano.PaymentAddress[]} addresses - A list of Cardano payment addresses to fetch transactions for.
* @param {number} historicalTransactionsFetchLimit - The maximum number of transactions to fetch in the initial pass.
* @returns {Promise<Cardano.HydratedTx[]>} A promise that resolves to a list of hydrated transactions from the given addresses.
*/
const fetchInitialTransactions = async (
chainHistoryProvider: ChainHistoryProvider,
addresses: Cardano.PaymentAddress[],
historicalTransactionsFetchLimit: number
): Promise<Cardano.HydratedTx[]> => {
const firstPassTxs = await allTransactionsByAddresses(chainHistoryProvider, {
addresses,
filterBy: { limit: historicalTransactionsFetchLimit, type: 'tip' }
});

if (firstPassTxs.length === 0) {
return [];
}

if (addresses.length === 1) {
return firstPassTxs;
}

const highBlockNo = Cardano.BlockNo(Math.max(...firstPassTxs.map((tx) => tx.blockHeader.blockNo)));
const onMonthBack = Cardano.BlockNo(Math.max(highBlockNo - ONE_MONTH_BLOCK_TIME, 0));

return await allTransactionsByAddresses(chainHistoryProvider, {
addresses,
filterBy: { blockRange: { lowerBound: onMonthBack }, type: 'blockRange' }
});
};

const findIntersectionAndUpdateTxStore = ({
chainHistoryProvider,
historicalTransactionsFetchLimit,
Expand Down Expand Up @@ -245,12 +284,12 @@ const findIntersectionAndUpdateTxStore = ({
);

const lowerBound = lastStoredTransaction?.blockHeader.blockNo;
const newTransactions = await allTransactionsByAddresses(chainHistoryProvider, {
addresses,
filterBy: lowerBound
? { blockRange: { lowerBound }, type: 'blockRange' }
: { limit: historicalTransactionsFetchLimit, type: 'tip' }
});
const newTransactions = await (lowerBound === undefined
? fetchInitialTransactions(chainHistoryProvider, addresses, historicalTransactionsFetchLimit)
: allTransactionsByAddresses(chainHistoryProvider, {
addresses,
filterBy: { blockRange: { lowerBound }, type: 'blockRange' }
}));

logger.debug(
`chainHistoryProvider returned ${newTransactions.length} transactions`,
Expand Down
Loading