Skip to content

Conversation

@mkazlauskas
Copy link
Member

Context

See ticket description and attachments

Proposed Solution

See commit messages

Introduces PaymentCredential opaque type to represent payment credentials
as bech32-encoded strings following CIP-5 specification. This type supports
both key hash credentials (addr_vkh prefix) and script hash credentials
(script prefix).

This is foundational work for optimizing BlockfrostChainHistoryProvider's
transactionsByAddresses() method. The optimization will group addresses by
their underlying credentials and query Blockfrost's credential-based
endpoints (/addresses/:addr_vkh/transactions and /accounts/:stake_cred/transactions)
instead of querying each address individually. This can reduce API calls
by up to 95% for wallets with many addresses sharing the same stake key.

The PaymentCredential type provides:
- Validation for bech32-encoded payment credentials
- Conversion from Credential objects to bech32 format via fromCredential()
- Type safety through OpaqueString pattern
…tion utilities

Implements reusable utilities at package root for querying by credentials across providers:

extractCredentials(): Extracts payment credentials and reward accounts from addresses
- Converts payment credentials to CIP-5 bech32 (addr_vkh/script) - network-agnostic
- Converts stake keys to RewardAccount bech32 (stake/stake_test) - includes network ID
- Handles BaseAddress (payment + stake), EnterpriseAddress (payment only)
- Collects Byron and Pointer addresses for fallback

minimizeCredentialSet(): Finds minimal set using greedy algorithm
- Reduces API calls from N addresses to M credentials/accounts
- Prefers payment credentials over reward accounts when coverage is equal

Note: RewardAccount is used for stake keys as it's a stake address (credential + network ID),
which is what we need for API queries - a superset of a pure credential.

Enables optimization in BlockfrostChainHistoryProvider and BlockfrostUtxoProvider.

Ref: LW-13806
Add constructor overloads to BlockfrostChainHistoryProvider supporting
opt-in credential-based transaction querying. Feature flag defaults to
false for backward compatibility.

- Add BlockfrostChainHistoryProviderOptions interface
- Implement dual constructor signatures (old + new with options)
- Add constructor overload tests
- Refactor existing tests into "default behavior" suite
… queries

Refactor transactionsByAddresses() to query by payment credentials and reward
accounts when queryTxsByCredentials flag is enabled, reducing API calls for
multi-address wallets.
…ag to BlockfrostUtxoProvider

Add constructor overloads with queryUtxosByCredentials option (defaults to false).
Maintains backward compatibility with existing constructor signature.

Related to LW-13806
…ties for UTXO queries

Implement createPaymentCredentialFilter utility to support filtering UTXOs
by payment credentials. This is needed for querying UTXOs by stake address
(reward account) where we need to ensure we only include UTXOs where we
control the payment credential.

The filter uses a two-tier approach for optimal performance:
- O(1) fast path for exact address matches using Set lookup
- O(1) credential lookup for cross-address-type matching

Includes comprehensive test coverage (21 tests) for all Cardano address
types (Base, Enterprise, Pointer) and credential types (KeyHash, ScriptHash),
plus edge cases (Byron addresses, empty input, duplicates, testnet).
Implement optimized UTXO fetching using payment credentials and reward
accounts instead of individual addresses, reducing API calls to Blockfrost.

Changes:
- Add fetchUtxosByPaymentCredential() to query by payment credential
- Add fetchUtxosByRewardAccount() with payment credential filtering
- Add mergeAndDeduplicateUtxos() for result consolidation
- Update utxoByAddresses() to support queryUtxosByCredentials flag
- Add comprehensive integration tests with feature flag ON
- Reuse credential extraction/minimization from transaction history

The implementation maintains backward compatibility with feature flag
defaulting to false. When enabled, reduces API calls significantly for
wallets with shared stake keys (e.g., 20 addresses → 1 query).
Move sortTxIn and sortUtxoByTxIn from input-selection to core package
to make them available for other packages without creating circular
dependencies.

Changes:
- Add sortTxIn() and sortUtxoByTxIn() to core/src/util/utxo.ts
- Add unit tests for sorting utilities in core (11 test cases)
- Update input-selection to import and re-export from core
- Update BlockfrostUtxoProvider to use sortUtxoByTxIn from core

This allows cardano-services-client to use UTXO sorting without
depending on input-selection, which is a higher-level package.
Fix formatting issues:
- Add missing semicolon after export statement
- Reformat method signatures to single line per prettier rules
…ueries

Remove address-based chunking logic from UtxoTracker and TransactionsTracker.

The chunking was originally implemented for db-sync-based providers which
are now obsolete. Modern Blockfrost providers implement a different query
strategy: they group queries by payment credential (which requires all
addresses to be provided upfront), then execute requests sequentially for
each individual credential or address. This makes the PAGE_SIZE-based
chunking unnecessary and redundant.

BREAKING CHANGE: Wallets with many addresses may exceed provider page size
limits. If using db-sync based providers, configure the server with a large
enough page size limit to accommodate all wallet addresses in a single request.
@mkazlauskas mkazlauskas force-pushed the perf/query-by-credential-lw-13806 branch from 66d93cb to 726bc2e Compare November 6, 2025 14:33
@mkazlauskas mkazlauskas merged commit dd93d42 into master Nov 6, 2025
7 of 8 checks passed
@mkazlauskas mkazlauskas deleted the perf/query-by-credential-lw-13806 branch November 6, 2025 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants