BlockchainStreamReaderTF

scalus.cardano.node.stream.BlockchainStreamReaderTF

Read-only streaming view of a blockchain: BlockchainReaderTF plus rollback-aware event subscriptions.

Stream / one-shot duality

Everything that changes over time has both a one-shot read and a subscription, and the two read the same state — a one-shot is semantically subscribeXxx().head. That is what stops two methods disagreeing about the current value. Polling disappears with it: pollForConfirmation(h) becomes subscribeTransactionStatus(h) with no sleep loop and no missed-update window.

Subscriptions are live when subscribe returns

Registration is eager and synchronous. Two consequences, both load-bearing:

  • subscribe(q) followed by submit(tx) on the same thread is race-free — the subscription is registered before subscribe returns, so the submitted transaction's events reach it. This is what makes emulator-driven tests deterministic.
  • The caller owns releasing the subscription. A subscription that is never consumed still accumulates events. Adapters expose this as a resource (fs2 Resource, pekko KillSwitch, an ox scope); the underlying release is ScalusAsyncSource.cancel().

Refusal

A request the provider cannot serve throws scalus.cardano.infra.UnsupportedSubscriptionException synchronously, from the call that caused it, before anything is registered — exactly when SubscriptionSupport.of(request, streamCapabilities) says Unsupported, or says Unindexed and the request did not set allowUnindexedScan. Callers that want to decide before asking consult the same function.

Choosing a stream type

The stream type is chosen per call, not per provider, so one provider instance can hand fs2 streams to application code while a test pulls raw ScalusAsyncSources from it. C is inferred from the expected type:

val tips: Stream[IO, ChainTip]        = provider.subscribeTip()  // needs the fs2 adapter given
val raw:  ScalusAsyncSource[ChainTip] = provider.subscribeTip()  // no adapter module needed

Where there is no expected type, C is decided by which adapter is in implicit scope — an imported adapter outranks the ScalusAsyncStreamAdapter.identity instance in this companion. Importing an adapter is therefore what makes subscribe return that library's type. Two adapters imported into one file with no expected type is an ambiguity, and the compiler says so; annotate or pass the type argument explicitly.

Type parameters

F

effect type for one-shot operations

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Known subtypes

Members list

Value members

Abstract methods

def close(): F[Unit]

What this provider can do. The only thing an implementation declares; per-request support is derived from it by SubscriptionSupport.of.

What this provider can do. The only thing an implementation declares; per-request support is derived from it by SubscriptionSupport.of.

Attributes

Latest-value stream of protocol parameters: the current value on subscribe, then changes.

Latest-value stream of protocol parameters: the current value on subscribe, then changes.

Attributes

Latest-value stream of chain-tip updates — newer wins, so a subscriber always sees the most recent tip when it pulls rather than a backlog of stale ones.

Latest-value stream of chain-tip updates — newer wins, so a subscriber always sees the most recent tip when it pulls rather than a backlog of stale ones.

Attributes

Latest-value stream of one transaction's status, following it through the mempool into a block — and back out again if a rollback orphans it.

Latest-value stream of one transaction's status, following it through the mempool into a block — and back out again if a rollback orphans it.

Attributes

Concrete methods

Subscribe with default options.

Subscribe with default options.

Attributes

Subscribe with default options.

Subscribe with default options.

Attributes

Subscribe with default options.

Subscribe with default options.

Attributes

Inherited methods

def findUtxo(input: TransactionInput): F[Either[UtxoQueryError, Utxo]]

Find a single UTxO by its transaction input.

Find a single UTxO by its transaction input.

Attributes

Returns

Right(utxo) if found, Left(NotFound) otherwise

Inherited from:
BlockchainReaderTF
def findUtxos(address: Address): F[Either[UtxoQueryError, Utxos]]

Find all UTxOs at the given address.

Find all UTxOs at the given address.

Attributes

Inherited from:
BlockchainReaderTF
def findUtxos(inputs: Set[TransactionInput]): F[Either[UtxoQueryError, Utxos]]

Find UTxOs by a set of transaction inputs (fails with NotFound if not all are found).

Find UTxOs by a set of transaction inputs (fails with NotFound if not all are found).

Attributes

Inherited from:
BlockchainReaderTF
inline def queryUtxos(inline f: Utxo => Boolean): UtxoQueryWithReaderTF[F]

Query UTxOs using a lambda DSL.

Query UTxOs using a lambda DSL.

Translates the lambda to a UtxoQuery at compile time and returns a builder that can be further configured before execution. Effect-polymorphic — the resulting .execute() returns the reader's own F[Either[UtxoQueryError, Utxos]], so the same call shape works on Future-typed providers (Blockfrost, JS) and direct-style providers (ox Id).

Example:

// Simple query — execute immediately
reader.queryUtxos { u =>
 u.output.address == myAddress
}.execute()

// With pagination and minimum total
reader.queryUtxos { u =>
 u.output.address == myAddress && u.output.value.hasAsset(policyId, assetName)
}.minTotal(Coin.ada(100)).limit(10).execute()

Supported expressions:

  • u.output.address == addr — query by address
  • u.input.transactionId == txId — query by transaction
  • u.output.value.hasAsset(policyId, assetName) — query/filter by asset
  • u.output.value.coin >= amount — filter by minimum lovelace
  • u.output.hasDatumHash(hash) — filter by datum hash
  • && — AND combination
  • || — OR combination

Value parameters

f

Lambda expression from Utxo to Boolean

Attributes

Returns

A UtxoQueryWithReaderTF builder over this reader's effect type

Inherited from:
BlockchainReaderTF

Inherited and Abstract methods

Returns CardanoInfo for this provider.

Returns CardanoInfo for this provider.

Attributes

Inherited from:
BlockchainReaderTF

Check the status of a transaction on the blockchain.

Check the status of a transaction on the blockchain.

Value parameters

txHash

the transaction hash to check

Attributes

Returns

the current status of the transaction

Inherited from:
BlockchainReaderTF

Returns the current slot number.

Returns the current slot number.

Attributes

Inherited from:
BlockchainReaderTF

Fetches the latest protocol parameters from the network.

Fetches the latest protocol parameters from the network.

Attributes

Inherited from:
BlockchainReaderTF
def findUtxos(query: UtxoQuery): F[Either[UtxoQueryError, Utxos]]

Find UTxOs using a type-safe query.

Find UTxOs using a type-safe query.

Attributes

Inherited from:
BlockchainReaderTF
def getDatum(datumHash: DataHash): F[Option[Data]]

Look up a datum by its hash. Returns None if unknown.

Look up a datum by its hash. Returns None if unknown.

Attributes

Inherited from:
BlockchainReaderTF
protected def mapF[A, B](fa: F[A])(f: A => B): F[B]

Map over this reader's effect F — the one primitive needed to give the convenience lookups above (findUtxo and the findUtxos overloads) a single effect-polymorphic default, without imposing an external Functor/Monad constraint on F. Future-based readers map via their captured ExecutionContext; monadic effects map via their monad.

Map over this reader's effect F — the one primitive needed to give the convenience lookups above (findUtxo and the findUtxos overloads) a single effect-polymorphic default, without imposing an external Functor/Monad constraint on F. Future-based readers map via their captured ExecutionContext; monadic effects map via their monad.

Attributes

Inherited from:
BlockchainReaderTF