HORIZON HASKELLDocslts/ghc-9.14.xd82dee82026-10-12Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · d82dee8 · 2026-10-12

Modulesolana-haskell-sdk-1.3.0.0GHC2021

Network.Solana.Core.VersionedMessage

  • 2 types
  • 4 values

An address lookup table as loaded on-chain: its own address, and the ordered list of addresses it stores. Passed to compileV0Message as a candidate source of accounts, so message account keys can be replaced by a lookup index instead of being listed in full.

Constructors

Instances4Eq, Show, Generic, Rep

A v0 message's reference to one address lookup table: the table's own address, and the indexes within it to load as writable and read-only accounts respectively.

Constructors

Instances5Eq, Show, Generic, Binary, Rep

Compile a v0 message (mirrors the Rust SDK's v0::Message::try_compile): build the legacy message (privilege union + canonical key ordering, via mkNewMessage), then move eligible writable-unsigned and readonly-unsigned keys into the given lookup tables, in table order, with the first table containing a key winning. Program ids and signers never move to a lookup. Tables that end up with no keys loaded are omitted from the serialized message.

Fails with a CompileException if a table has more than 256 addresses and a key drained into it sits at position 256 or beyond — that position cannot be represented in the byte-sized lookup index the wire format requires, so it is rejected rather than silently truncated (wrapped) into the wrong index, mirroring Rust's AddressLookupTableIndexOverflow. Compilation also fails when the static and table-loaded keys together exceed 256, since instruction account indices are single bytes (the on-chain v0 sanitize rule; see compileInstruction).

A trap this module can't protect you from: an address only just added to a lookup table by an ExtendLookupTable instruction that landed in slot S only becomes eligible for lookup in a slot strictly greater than S -- on-chain, the table's last_extended_slot is set to S, and its active-address count stays at the length recorded in last_extended_slot_start_index (the table's length before the first extension that landed in S -- relevant if you batch several extends into the same slot) until the current slot passes S. The invariant that matters: whatever bank resolves the lookup (a preflight simulation, or the bank that actually processes the transaction) must be at a slot strictly greater than S, or the submission is rejected with "Transaction address table lookup uses an invalid index" -- not a bug in this function, but a real on-chain rule to wait out. Read S back with decodeLookupTable (its ltLastExtendedSlot field) if you need to check it explicitly; the convenience wrapper getLookupTable drops that field and returns only AddressLookupTableAccount, so it can't be used for this check.

Like compileV0Message, but with an explicitly named fee payer, seeded as a writable signer and pinned to account 0 via mkNewMessageWithPayer -- which is what the Rust SDK's v0::Message::try_compile(payer, ..) always does. Required when no instruction marks a signer writable (a memo-only or SPL authority-only instruction list) and for sponsored fees.

Sign a v0-compiled message with each signer's private key, and return the Base64-encoded signed versioned transaction (compact signature array followed by the message bytes). Mirrors newTransactionIntent. The private keys passed here must be ordered to match the resulting account order (fee payer first), otherwise the produced signatures will not correspond to the right account keys. If you would rather name the fee payer explicitly and not worry about signer order, use newV0TransactionIntentWithPayer.

If any given table was extended very recently, see the note on compileV0Message about the resulting transaction's activation window: whatever bank resolves the lookup must be at a slot strictly past the table's last extension, regardless of the preflight commitment level used to submit it (and regardless of preflight at all, if it is skipped).