Table of Contents

Class OnchainHtlcState

Namespace
NArk.ArkadeIntents.Onchain
Assembly
NArk.ArkadeIntents.dll

Reading an L1 HTLC's state back off the chain, for a client that no longer knows it.

public static class OnchainHtlcState
Inheritance
OnchainHtlcState
Inherited Members

Remarks

The corridor's normal path never needs this: it drives forward from a row it wrote itself. This is for the case where that row is gone or stale — a restored wallet, a process that was down across the window, an operator asking what actually happened. The distinction matters because the answers differ in kind: the drive path asks "may I act yet", and recovery asks "what is true".

Everything here is derived from the chain and the contract, never from a counterparty's account of either.

Methods

AwaitFillAsync(IBitcoinBlockchain, OnchainHtlc, int, TimeSpan, TimeSpan?, CancellationToken)

Wait until the HTLC holds enough confirmed value to act on, or give up.

public static Task<OnchainHtlcStatus> AwaitFillAsync(IBitcoinBlockchain blockchain, OnchainHtlc htlc, int minConfirmations, TimeSpan within, TimeSpan? poll = null, CancellationToken cancellationToken = default)

Parameters

blockchain IBitcoinBlockchain

Where to read from.

htlc OnchainHtlc

The HTLC to watch.

minConfirmations int

The count this swap was quoted at.

within TimeSpan

How long to keep looking.

poll TimeSpan?

How often to look. Defaults to five seconds.

cancellationToken CancellationToken

Cancels the wait.

Returns

Task<OnchainHtlcStatus>

The status once it is claimable, or the last one seen when the time ran out — Empty when nothing ever arrived while this was watching.

Remarks

Polling, because an L1 funding raises no event this SDK subscribes to — which is the same reason the advance pass proposes its onchain actions on every tick rather than on a trigger. Returning the last status rather than throwing keeps "it never arrived" an answer the caller can branch on alongside the others.

ClassifyAsync(IBitcoinBlockchain, OnchainHtlc, int, CancellationToken)

Classify an HTLC from the chain.

public static Task<OnchainHtlcStatus> ClassifyAsync(IBitcoinBlockchain blockchain, OnchainHtlc htlc, int minConfirmations, CancellationToken cancellationToken = default)

Parameters

blockchain IBitcoinBlockchain

Where to read outputs and the tip from.

htlc OnchainHtlc

The HTLC to look at.

minConfirmations int

The count this swap was quoted at.

cancellationToken CancellationToken

Cancels the lookups.

Returns

Task<OnchainHtlcStatus>

The phase, and the outputs behind it.

Remarks

Maturity is judged against the tip's median time past, which is the clock consensus applies to CLTV and which trails wall clock by roughly an hour. Classifying against a local clock would report Refundable for up to that long before a refund would actually be accepted — and, worse in the other direction, would call a window closed while a claim could still have landed.

ExtractPreimage(Transaction, uint256)

Recover a preimage from the transaction that spent an HTLC.

public static byte[]? ExtractPreimage(Transaction tx, uint256 paymentHash)

Parameters

tx Transaction

The spending transaction.

paymentHash uint256

The hash it must open, as the swap recorded it.

Returns

byte[]

The preimage, or null when this transaction proved none.

Remarks

The L1 counterpart of SwapPreimageReader, which reads Arkade spends through the indexer and so cannot answer for a Bitcoin transaction.

Every candidate is checked against the hash before it is believed. A 32-byte push is not evidence; one that hashes to this swap's payment hash is, and it is evidence nobody can forge — which is what makes it safe to act on without trusting whoever built the spend.

A null answer is not proof of a refund. A transaction that carried no preimage and one this failed to parse are the same silence here, and both mean only that the spend is not provably a claim.