The ONE seam between the rendering layer and the wallet FFI handle.
WHY a Dart-side port (design invariant 2 — hexagonal; flutter-patterns
§ State Management): the live-sync providers must be unit-testable on
the host VM with NO native library and NO device (a real WalletHandle
is an opaque FRB object that cannot be constructed in a flutter test).
The providers depend on THIS interface; tests inject a fake, and the
future onboarding slice injects the real adapter by overriding
walletSessionProvider. This is NOT a Dart-side data cache — Rust stays
the single source of truth (design invariant 1); every method forwards
straight to the core.
Surface kept minimal — exactly what the host UI drives. Key-material
methods (restore, revealMnemonic) deliberately live OUTSIDE this
port: they are separate, crypto-reviewed key-crossing slices and the
sync/balance UI never touches them.
- Implementers
Properties
- hashCode → int
-
The hash code for this object.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
AUTHORIZE a parked send NOW (FR-23-b / #361) — sign a send the user already
committed, at this user-present moment, instead of waiting for a background
pass to sign it. Pass BOTH the
idAND thecreatedAtfrom theParkedSend. -
birthdayHeight(
) → Future< int?> -
The account's birthday height — the scan FLOOR the wallet's history
starts at (#317).
nullbefore the account is provisioned (the first sync hasn't run yet). The rescan sheet uses it as the range DEFAULT: a rescan from the floor covers everything THIS wallet has ever seen without hiding older funds (an above-floor rebuild hides the span between the old and new floor — the SDK's LOWER-ONLY contract) and without scanning pointlessly before the wallet existed. NOT a clamp on user picks: an explicitly EARLIER date is the post-restore recovery path (this floor may itself be a too-recent restore estimate). A height, never money. Cheap, local, no network. -
cancelParkedSend(
{required int id, required int createdAt}) → Future< bool> -
CANCEL a parked (queued) send (2e-2b-v-4a) — the user-facing escape hatch to
DISCARD a parked send of EITHER kind (the SAFE counter-affordance; never a
re-send; the guard is kind-agnostic — any still-
Queuedrow is fundless). Pass BOTH theidAND thecreatedAtfrom theParkedSendthe user is cancelling. Returnstrueif removed,falseif it was already gone / began sending / its rowid was reused (idempotent). Onfalse, re-read listParkedSends — but do NOT present it as definitively "cancelled" nor invite a re-send: a send that began sending may be IN-FLIGHT (direct the user to the activity list; a re-send risks a DOUBLE-PAY). MONEY-SAFE: only a still-Queuedintent is deleted (nothing signed, no tx on-chain). IRREVERSIBLE — the host MUST confirm before calling. Throws a typedWalletApiError(invalid-state on a closed handle). -
checkOlderSwapAddresses(
) → Future< SwapAddressCheckReport> -
#390 — "Check older swap addresses": widen the range the wallet watches so
the normal sync surfaces older swap deposits/refunds that a SEED-ONLY
RESTORE of a long swap history left unchecked. It does NOT itself find funds
— it WIDENS, then any older swap money appears in the balance over the next
minutes of sync. Returns a COUNTS-only
SwapAddressCheckReport(never an address/index) — render "checking as your wallet syncs; anything found will appear in your balance", NEVER "found X". Rerunnable (each accepted run goes deeper). Moves NO money (no authorizer). Throws a typedWalletApiError`swapAddressCheckRefused`(branch onreason:swapDisabled— swap is off;checkOutstanding— a prior check is still running, one per settlement window) or invalid-state on a closed handle. -
composePaymentUri(
{required String recipient, required int amountZat, String? memoText, List< int> ? memoBytes}) → String -
Compose a ZIP-321 payment URI (the §2.4 lossless request token) from one
form leg — the form flow's bridge into propose/queueSend; a scanned-QR
flow would call those with the URI directly. SYNCHRONOUS, no money movement:
the adapter validates the recipient + memo against the wallet's OWN network
(so a cross-network address is the SDK's typed
NetworkMismatch, never a host-supplied-network footgun) and returns the URI string. The bridge crossing (encodePaymentUri) lives in the adapter — never in the UI layer — so this whole flow stays host-VM testable behind a fake. Throws a typedWalletApiErrorfor a bad address / un-sendable memo. -
currentAddress(
) → Future< String> - The wallet's current receive address (the unified address for account 0) — what the user shares to RECEIVE ZEC. NOT key material (it is public by design; the spending key never leaves Rust), so it belongs on this port. §5.4 NEVER-LOG applies (an address is a never-log value) — display it, allow copy, but never write it to a log. Cheap, local, no network.
-
currentTransparentAddress(
) → Future< String> - The wallet's TRANSPARENT receive address (Recv-2 / ADR-0528) — the account's external-scope P2PKH t-address, surfaced ALONGSIDE the shielded UA behind the receive screen's address-type toggle (default shielded). PUBLIC + visible on-chain + reused-address-linkable: the UI labels it as such and keeps the shielded UA the recommended default. NOT key material (the spending key never leaves Rust); §5.4 NEVER-LOG applies. Cheap, local, no network.
-
deliveryState(
String txidHex) → Future< DeliveryState?> -
The wallet's DELIVERY OBLIGATION for one transaction it created (stage S8
obligation) — the same reading a history row carries onTxSummary.delivery, for thetxidHexa send result named. Read it after asendthat was not all-success: onlyDeliveryState.retryPendinglicenses "saved — your wallet will send it on a later sync";null(not the wallet's, expired, or no row) and every other state do not. -
dismissSwapRecord(
{required String swapId}) → Future< bool> -
Remove one in-flight swap record. USER-INTENT only since #367 — the
terminal card's Done (the outcome rendered = seen) or the home row's
explicit Remove; a terminal OBSERVATION pins via recordSwapOutcome
instead. Display-only state: never touches the deposit outbox / guard /
detection. Idempotent (
falsefor an already-absent id — a raced double-dismiss is harmless). -
enableNearSwap(
{required SwapProviderConfig config, required bool swapEnabled, SwapKill? declaredKill}) → Future< void> -
Turn the swap on-ramp ON — construct the NEAR provider over the wallet's OWN
transport (the same host-provided dialer + Tor policy sync uses; internal Tor
is OPTIONAL — the host may bring its own) and apply the §3.5 kill state. A
ONE-TIME setup, called after the wallet is open (set-once, first-wins). On a
build compiled WITHOUT the adapter it degrades honestly to a typed
SwapDisabled(the method is always present so the surface is stable). Throws a typedSwapApiError(watchOnlyon a watch-only wallet — STRUCTURAL, never retryable, checked first (#397 §3.7 D3): render view-only framing, not a retry;providerUnavailablewhen the transport can't be resolved — retryable;swapStateUnavailableon a torn-down handle). -
exportUfvk(
) → Future< String> -
EXPORT this wallet's Unified Full Viewing Key (#397 §3.7 D1 / ADR-0538) — the
uview…string that grants FULL history visibility (every past and future transaction, amounts, memos) and NO spend authority. -
isWatchOnly(
) → Future< bool> -
Is this a WATCH-ONLY wallet (#397 §3.7 D4/D5)? The reference UI keys its
chrome on this: a "Watch-only" header badge, hidden Send/Shield/Swap
affordances, and the Security screen's no-backup ("Export viewing key")
arm. The typed
WalletErrorKind.watchOnlyrefusals stand at the SDK regardless, so a host ignoring this only ever sees honest errors — never a wrong behavior. Cheap, local, no network, no key material. -
listInFlightSends(
) → Future< List< InFlightSend> > - The IN-FLIGHT two-step (TEX) sends (#309): first leg signed + broadcast, send not yet complete — money is IN MOTION through a wallet-controlled one-time address. Drives the DURABLE wallet-screen "on its way — don't send it again" cue (the post-send result screen's caution is dismissible; without this, an in-flight two-step reads as an ordinary pending send exactly when a worried user is most tempted to re-pay). DISJOINT from listParkedSends (parked = queued, nothing signed; in-flight = signed + broadcast). A row leaves by three exits: completion, the strand transition (recoverableEphemeralFunds takes over — the two can OVERLAP while the unshield settles; both cues together is correct), or a return to the queue (every tx expired unmined — no money moved; it reappears parked, cancellable again). AMOUNT-only (§5.4 — no recipient/txid); the amount annotates the SAME pending payment the activity list shows — never double-count it. Cheap, LOCAL, no network; empty is the common case.
-
listInFlightSwaps(
) → Future< List< SwapRecord> > -
The durable IN-FLIGHT SWAP surface (W-swap-5, #366): every swap whose order
was registered at execute and has neither been dismissed nor self-lapsed.
THE kill→relaunch re-attach — after a process restart the wallet screen
lists these and re-opens live tracking by feeding
SwapRecord.idto watchSwapStatus. NOT gated on swap being enabled or the §3.5 kill (a local read is not swap traffic — the user never loses sight of money in motion). Read-only, cheap + LOCAL; called on the same edges as the parked/in-flight send surfaces. §5.4:SwapRecord.idis render-never-log. -
listParkedSends(
) → Future< List< ParkedSend> > -
EVERY queued send that has not completed yet (2e-2b-v-3, widened by #331):
a one-time-address (TEX) two-step awaiting drain / ceiling-parked, or a
plain single-step send waiting in the offline queue — the
ParkedSend.kindsays which (presentation-only). They sit in the queue with NO on-chain transaction (INVISIBLE in the activity list), so across an app relaunch this surface is the ONLY place the committed spend exists — hidden, a queued send is a DOUBLE-PAY window (the user re-enters it and both drain on reconnect). EachParkedSendis amount + id + kind + createdAt; the recipient address NEVER crosses the bridge (§5.4 never-render). A read-only PULL; each parked send auto-broadcasts once it can drain — present it per the DOUBLE-PAY caution (never invite a re-send) and EARMARK its amount over the balance (it stays spendable). Cheap, LOCAL, no network. LIVE since gate-removal (2e-2b-v-5a): both the interactive send andqueueSendpaths can park here. -
machineMemos(
String txidHex) → Future< List< Uint8List> > -
FR-27 — the machine-memo bytes of one transaction, scoped to the prefixes
registered on the wallet's
WalletConfig. Returns them in output order;txidHexis passed back verbatim from a history row. -
mintDiversifiedAddress(
) → Future< WalletMintedAddress> - Mint the NEXT public diversified receive address (FR-8 / Recv-4, ADR-0537): a fresh unlinkable unified address for a contact/invoice that still credits this one wallet — payments to it are detected by the normal shielded scan (including after a seed-only restore), with no extra host work. Same receiver set as currentAddress (shielded-only), so no compatibility downgrade. Every call returns a NEW address from the SDK's never-recycle, restore-surviving counter; deterministic per WalletMintedAddress.diversifierIndex — keep the index as the durable host-side attribution key. Cheap, local, no network, not gated on sync. Throws the typed bridge error before an account is provisioned (exotic — accounts import eagerly at create). §5.4 NEVER-LOG applies to BOTH fields.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
parseSendRequest(
String uri) → WalletSendRequest -
Parse a ZIP-321
zcash:payment URI (a scanned QR, a deep link — HOSTILE input) into a WalletSendRequest for the FR-25 prefilled-send seam — the DECODE inverse of composePaymentUri. SYNCHRONOUS, no money movement: the adapter runs it through the audited corepayment_uriparser against the wallet's OWN network (so a cross-network URI is the SDK's typedNetworkMismatch, never a host-supplied-network footgun), and applies the single-recipient / text-memo seam policy. The bridge crossing (parsePaymentUri) lives in the adapter — never in the UI layer — so the prefill flow stays host-VM testable behind a fake. Throws a typed WalletSendRequestException (malformed / wrong-network / multi-leg / unsupported-memo) so the host rejects at the seam, never a half-filled form. WalletSendRequest.fromUri is the public sugar over this. -
probeSyncServer(
SyncServerChoice choice) → Future< SyncServerProbe> -
Dial
choiceunder the wallet's own Tor policy and ask the server who it is (one round trip, 15 s budget). Throws typed —WalletErrorKind.syncServerUnreachable,.networkMismatch,.syncServerNotOffered,.invalidEndpoint(a custom URL the door refuses) — and NEVER switches: the picker's "Check server" step. The switch itself is the provisioner's (WalletProvisioner.switchSyncServer) because it swaps the session. -
propose(
String requestUri) → Future< SendProposal> -
Prepare a send from a ZIP-321 payment URI (the §2.4 lossless request token
the host composes via composePaymentUri, or a scanned QR). DETERMINISTIC,
LOCAL: runs the audited note-selection + fee + change over the wallet DB and
returns the numbers the user confirms before signing — no keys, no proofs,
no network, no DB writes, nothing sent. The proposal stays an opaque,
Rust-retained one-shot token; send consumes it by
proposalId. -
proposeShield(
) → Future< SendProposal?> - Propose shielding the wallet's detected TRANSPARENT funds into its shielded pool (Recv-3 — the companion to currentTransparentAddress). Exchange withdrawals + swap-in deliveries land transparent; this is the privacy-POSITIVE "move them shielded" action. DETERMINISTIC, LOCAL like propose: no keys, no proofs, no network, no DB writes — NOTHING is sent.
-
queueSend(
String requestUri) → Future< String> -
Queue a send for OFFLINE-first delivery (invariant 4): durably persist the
send INTENT (the same ZIP-321 URI) and return immediately — no network, no
signing, no money movement. It survives a process kill and proposes → signs
→ broadcasts on the next online sync (proposing at SEND time, not now, is
what stops a long-queued send from ever carrying a stale anchor). Returns
the opaque queued-send id; throws
queuedSendsFullat the durable cap (a real send is never silently dropped). -
reclaimEphemeralSlots(
) → Future< ReclaimOutcome> -
REOPEN a one-time-address (TEX) send window bricked by leaked reservations (#315
slice 2) — sends that reserved a one-time address but never confirmed, which the
wallet cannot free on its own. Self-mints a small amount from your SHIELDED balance
to the highest provably-abandoned one-time address; mining it reopens the whole
window. MONEY-MOVING + EXPLICIT: authorize it (the #327 seam) with the honest-cost
disclosure (the mint + a later recovery are TWO transactions, ~4 network fees; the
moved principal returns to your wallet via sweepEphemeralFunds). Returns a
ReclaimOutcome:Minted(INITIATED — the window reopens once it confirms),NothingToReclaim(no abandoned reservation — the window is transient), orNotBroadcast(money-safe transport miss; retry). It unblocks the WINDOW only — it NEVER re-sends a paused/queued payment (no double-pay). ⚠ HOST GATING: offer it ONLY when a send is actually parked/paused — the SDK cannot tell a bricked window from a healthy one (no engine occupancy read), so a call otherwise mints uselessly (fee-waste, never fund-loss). Throws a typedWalletApiError(seedRequiredwith no key,insufficientFundswhen the shielded balance can't fund the mint, invalid-state on a closed handle). -
recordSwapOutcome(
{required String swapId, required SwapOutcome outcome}) → Future< bool> -
Pin an OBSERVED terminal outcome into an in-flight swap record (#367) —
call when the tracking stream reports a TERMINAL status, so the home row
renders the truth even if the user was away at observation time (deleting
on observation erased outcomes the user never saw — durably, if the
process died in the gap). First-wins + idempotent (
falsefor an absent / lapsed / already-pinned id). Display-only state. -
recoverableEphemeralFunds(
) → Future< List< RecoverableEphemeralFunds> > -
The wallet's RECOVERABLE one-time-address funds (2e-2b) — amounts sitting on
wallet-controlled single-use (ephemeral) transparent addresses: an expired
TEX forward whose second step never completed, OR an exchange that returned a
deposit to such an address. Each entry is AMOUNT-ONLY — the one-time address
is wallet-internal and NEVER crosses the bridge (§5.4 never-render). The
amount is a SUBSET of
BalanceSnapshot.transparentZat/.totalZat(the engine already folds these outputs into the displayed balance), so the host renders it as "X OF your balance is on a one-time address", NEVER "+X" (that would over-count holdings ~2×). Cheap, LOCAL (a SQLite read), no network, no money movement. LIVE since gate-removal (2e-2b-v-5a) — empty only on a wallet that has stranded nothing on a one-time address. -
retryParkedSend(
{required int id, required int createdAt}) → Future< bool> -
RETRY a
pausedparked send (#315 slice 1) — resume the SAME queued intent after the wallet gave up auto-retrying it (ParkedSend.paused): retries of a one-time-address send are capped because each one permanently uses up one of a small number of address slots. When the user believes conditions changed (back online, the recipient service reachable), THIS is the resume path — never cancel + re-enter (double-pay risk + it silently evades the retry cap on a fresh send). Pass BOTH theidAND thecreatedAtfrom theParkedSend. Returnstrueif re-armed (it attempts again on the next background pass — not instantly),falseif already gone / began sending / rowid reused (idempotent — re-read listParkedSends). MONEY-SAFE: only re-arms the existing intent's retry budget; nothing is signed or sent by the call itself. Throws a typedWalletApiError(invalid-state on a closed handle). -
send(
int proposalId) → Future< List< TxSubmitResult> > -
Sign + broadcast a prepared proposal — consumes the one-shot
proposalId. A per-tx broadcast outcome is first-class DATA (the returned list), NEVER a thrown error: a tx that fails to broadcast is persisted and re-sent by the resubmission machinery on the next sync, so even a total broadcast failure loses no funds, only immediacy. Throws only for a consumed token (proposalAlreadyUsed), a stale anchor (proposalStale⇒ re-propose), or a build/sign failure (signFailed). -
snapshot(
) → Future< WalletState> -
The on-resume cold snapshot (spec §3.3): balance, sync status, Tor
state, chain tip, balance age, and the monotonic
seq. Cheap; safe to call on resume before re-subscribing to the live stream. -
startSync(
) → Future< void> -
Start the background sync loop — required for watchSyncStatus to
advance past
idle. Idempotent. -
stopSync(
) → Future< void> - Stop the background sync loop. Idempotent; durable progress is kept (the chain is the source of truth). Pauses sync WITHOUT closing.
-
swapAddressCheckCoverage(
) → Future< SwapAddressCoverage> -
#390 — the render-only coverage read for the "Check older swap addresses"
sheet: how far the wallet has already checked (
coveredSwaps) and how many addresses are still to be registered + polled (pending;0= nothing outstanding). COUNTS-only. Read-only, side-effect-free — safe to re-pull while the sheet is open. Throws invalid-state on a closed handle. -
swapExecute(
{required SwapQuote quote}) → Future< String> -
Execute a quote — register the swap intent with the provider and (for an
OutOfZec quote) queue the §4.4 ZEC deposit send. Pass back the
SwapQuoteswapQuote returned; the SDK claims its own durable single-flight by the quote id BEFORE anything happens (idempotent against a double-tap / crash retry — exactly ONE deposit per quote), and the deposit uses the SDK's own frozen record, NEVER this DTO, so a tampered field can't redirect funds. Returns the opaque provider swap id (do NOT parse it; pass it to watchSwapStatus). Throws a typedSwapApiError(quoteExpired⇒ re-quote — since #367 this also covers a not-issued/already-executed quote (every take-miss reads "no longer valid");swapStateBusy⇒ retry the SAME execute (nothing consumed);depositSendFailed⇒ re-quote). -
swapListTokens(
) → Future< SwapTokenList> -
The dynamic source-asset list for the IntoZec picker (spec §3.3b D5/L6).
LAZY — called when the user opens the IntoZec form (NOT on launch: §5.2
honest-off, an idle user emits no token traffic). The SDK fetches
/v0/tokensover the swap dialer (Tor-optional, its OWN circuit), filters the ZEC asset + $0/null-price entries, and caches the result. On a fetch fault it serves the LAST good list withSwapTokenList.fresh= false (the host shows a "couldn't refresh, showing cached" banner — honest degradation, never a blank picker); a first-ever fault with no cache throws a typedSwapApiError. An emptytokenswithfresh == trueis the honest "no assets available right now". No wallet key material crosses — token metadata is §5.4 never-logged. -
swapQuote(
{required QuoteRequest request}) → Future< SwapQuote> -
Request a bounds-checked swap quote (spec §2.6) — the FIRST step of the
on-ramp. DETERMINISTIC against the user's exact side; funds NEVER move. The
returned
SwapQuotecarries the deposit address, the min-out floor, the ZEC side in zatoshis, and the §2.6 privacydisclosurethe host MUST render. Throws a typedSwapApiError(slippageToleranceTooHigh,quoteOutOfBounds,destinationInvalid,providerUnavailable,swapDisabled, …) the controller maps to an honest inline fault. -
sweepEphemeralFunds(
) → Future< EphemeralSweepSummary> -
MANUALLY recover funds stranded on wallet-controlled one-time (ephemeral)
transparent addresses into the wallet's OWN shielded balance (2e-2b-v-2) — the
"recover now" action behind the recoverableEphemeralFunds note, PLUS late
exchange returns / a 2nd deposit the automatic surface can't see. MONEY-MOVING:
it signs + broadcasts one consolidating tx per funded address (each over its own
circuit, never co-spent — so a recovery never links the one-time-address set
on-chain). The returned
EphemeralSweepSummaryis COUNTS-only (the one-time addresses NEVER cross the bridge);recoveredZatis PROVISIONAL (accepted ≠ mined — render "pending" until the scan settles it) and IDEMPOTENT on re-run (the engine excludes already-spent UTXOs, so it can never double-spend);failed > 0⇒ some funds stay on-chain + re-runnable;truncated > 0⇒ a heavy wallet hit the per-invocation cap — run again. Throws a typedWalletApiError(seedRequiredwhen the wallet cannot sign, invalid-state on a closed handle). Gate the affordance on a SUCCESSFUL recoverableEphemeralFunds read showing funds — NEVER offer it from an error/empty fallback (a failed read must not read as "nothing to recover", hiding held funds). LIVE since gate-removal (2e-2b-v-5a): a no-op only when no one-time address holds funds. -
syncServers(
) → Future< List< SyncServer> > -
The sync servers the host OFFERS (the picker, P3-13 —
WalletConfig. syncServersas validated), WITHOUT their keys (authValueis always null here;authHeadersays whether an entry is gated). Read-only. -
syncServerStatus(
) → Future< SyncServerStatus> - Which server the wallet dials, which remembered choice produced it, and whether a fallback is in force — the connection's own truth, which is what the sync sheet's Server row renders (host only, never the URL).
-
toString(
) → String -
A string representation of this object.
inherited
-
transactions(
{required int limit, String? after}) → Future< HistoryPage> -
The transaction history for the activity list (FR-1), newest first and
paginated by an OPAQUE keyset cursor: pending (unmined) rows sort above
confirmed ones;
afterisnullfor the first page or the previousHistoryPage.nextCursorfor the following page (passed back VERBATIM — never parse it);limitcaps the page (clamped Rust-side). The keyset cursor means a page boundary never drops a same-height row nor strands the confirmed history behind a full page of pending txs. EachTxSummarycarries the SIGNED net amount, status/confirmations, fee, and a memo flag — DISPLAY data only (no key material; §5.4 NEVER-LOG: txids/amounts/cursors). Reads librustzcash'sv_transactionsview off the sync lock, so it's cheap and never blocks scanning. -
validateRecipient(
String address) → ValidatedAddress -
Classify a recipient address against the wallet's OWN network — its memo
capability (the §5.1 SHIELDED-vs-TRANSPARENT / private-vs-public axis) —
WITHOUT composing or proposing anything. Drives the send form's LIVE
recipient feedback + memo gating. The screen never needs to know
mainnet/testnet (the same network-hiding seam as composePaymentUri, so a
host-supplied network can never be a footgun). SYNCHRONOUS, local, NO
network, no money movement — safe to call on every keystroke and fully
offline (the same audited
Address::parsegateproposelowers through, so the live check can never disagree with what a send will accept). Throws a typedWalletApiError(addressInvalidfor malformed,networkMismatchfor an other-network address) the host maps to an honest inline status. -
watchIncomingFunds(
{String? sinceCursor}) → Stream< IncomingFundsEvent> -
The incoming-funds event stream (spec §3.3 / ADR-0536, amended by ADR-0539 —
the FR-1 "funds arrived" hook). ONE
replayevent first (arrivals already in history strictly abovesinceCursor; a null cursor gets a count-0 baseline that hands the subscriber a cursor to keep), then aliveevent per scan batch that detected arrivals, and amemoRefreshnudge when a later enhancement pass changes how existing rows read — either decrypted tx data landed, or a transaction's chain status did, somemoRefreshmeans "re-pull", NEVER "new memo data exists". The payload is counts + heights + an opaque cursor ONLY (safe to log or forward); details are a pull via transactions. Delivery is at-least-once with latest-wins coalescing —totalTxDetectedis the coalesce-proof monotonic. A rescan/restore REPLAYS history with old spans: the stream is a freshness signal, never an accounting ledger. A malformedsinceCursorsurfaces as a stream error (typedstoreCorrupt) — including aHistoryPage.nextCursorkeyset token passed here by mistake (the two cursor families are deliberately incompatible). NOTIFICATION-driving hosts: gate onspanToHeight > your own acked watermark(the max you have told the user about — tracked on YOUR side; the cursor is only forsinceCursor) plus your own consumed-txid ledger for exactly-once. -
watchSwapStatus(
{required String swapId}) → Stream< SwapStatus> -
The live
SwapStatusstream for one in-flight swap (spec §3.3/§7). Emits the CURRENT status immediately on subscribe (so a re-subscribe after a background gap re-renders at once), then polls at a bounded cadence. It NEVER completes on a transient provider fault (a stall is retried behind the scenes, not a dead stream); it completes only on a TERMINAL status (success/refunded/failed) — drained first — or when the wallet is closed/swap is hard-killed.swapIdis the opaque id swapExecute returned. -
watchSyncStatus(
) → Stream< SyncStatus> -
The live
SyncStatusstream (spec §3.3). Emits the CURRENT status immediately on subscribe (so a re-subscribe after a background gap re-renders at once), then every change coalesced latest-wins. It NEVER completes on a transient fault — a stall is aSyncStatus.stalledEVENT, not an error or EOF.
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited