packages feed

solana-haskell-sdk-1.4.0.0: CHANGELOG.md

# Revision history for solana-haskell-sdk

## 1.4.0.0 -- 2026-10-19

* Added v1 transaction support (SIMD-0385), in the new
  `Network.Solana.Core.MessageV1`: `compileV1Message`,
  `newV1TransactionIntent`, and the `TransactionConfig` record (with
  `emptyTransactionConfig`) carrying a v1 message's priority fee,
  compute-unit limit, loaded-accounts data size limit and heap size.
  v1 lists every address inline (it has no address lookup tables), moves
  resource requests out of `ComputeBudget` instructions and into a header
  configuration mask, places the signatures after the message rather than
  before it, and raises the transaction size limit to 4096 bytes.

  Both entry points take the fee payer explicitly, unlike their legacy and
  v0 counterparts, which derive it from the instruction list. The reference
  implementation's only v1 compile path does the same, and the implicit
  form is a trap in this format: the priority fee travels inside the
  message, so instruction order alone would decide who pays it.

  Compilation rejects a message the network would refuse, or would accept
  and charge for without it being able to do any work:
  `LimitExceeded` for more than 64 addresses, more than 64 instructions,
  more than 12 required signatures, an instruction with more than 255
  accounts or 65535 data bytes, or a transaction over 4096 bytes once
  signed; `InvalidMessage` for no instructions at all, the fee payer named
  as a program id, a compute-unit or loaded-accounts request of zero, or a
  heap request that is not a multiple of 1024 within [32768, 262144].

  Note that in v1 an absent resource request means the *minimum*, not the
  generous default earlier formats use: an absent compute-unit limit means
  0 rather than a per-instruction allowance, and an absent loaded-accounts
  data size limit means 0 rather than 64 MiB. `emptyTransactionConfig` is
  therefore a base for record update rather than a usable configuration,
  and compiling with it unchanged fails.
* Changed (breaking): `CompileException` is no longer a newtype over a
  single `MissingIndex` constructor. It gains `LimitExceeded` and
  `InvalidMessage`, so the v1 checks above report something other than a
  missing index, and callers can discriminate without matching on the
  message text. Existing `MissingIndex` matches still compile but are no
  longer exhaustive.
* Changed (behavioural): `getBlock` and `getTransaction` now send
  `maxSupportedTransactionVersion: 1` instead of `0`. Without it a node
  refuses any block holding a v1 transaction with error -32015, which now
  covers most blocks. A v1 message's `transactionConfig` is not surfaced by
  `CompiledMessage`, which drops it as it already drops a v0 message's
  `addressTableLookups` — and, unlike a legacy transaction's
  `ComputeBudget` instructions, it is not recoverable from the parsed
  instruction list either.
* Added: `Network.Solana.Core.Instruction` now also exports
  `CompiledInstruction`'s constructor and fields (`ciProgramIdIndex`,
  `ciAccounts`, `ciData`), which the v1 serializer needs, since v1 writes
  the fixed-width instruction headers apart from the variable-width
  payloads. Code importing that module unqualified and defining names of
  its own that collide will need a `hiding` clause.

## 1.3.0.0 -- 2026-09-13

* Fixed (security): `readSigningKeyFromFile` accepted key files of any length
  and silently wrapped out-of-range values, producing a malformed
  `SolanaPrivateKey` whose use in `dsign`/`sign` read past the end of the key
  buffer in the ed25519 C code. The loader now decodes the file as a JSON
  array of exactly 64 bytes and verifies the public-key half against the seed
  (as `solana-sdk`'s `Keypair::from_bytes` does), throwing an `IOError`
  otherwise.
* Added `mkPrivateKeyFromBytes`, a total constructor performing those checks
  on raw bytes.
* Changed: `unsafeSolanaPublicKeyRaw` and `unsafeSolanaPrivateKeyRaw` now call
  `error` unless given exactly 32 / 64 bytes, matching the other `unsafe*`
  constructors; `mkPrivateKeyFromString` (and so `unsafeSolanaPrivateKey`)
  applies the same public-key-half check as `mkPrivateKeyFromBytes`.
* Changed (breaking): `SolanaPublicKey`, `SolanaPrivateKey` and
  `SolanaSignature` no longer derive `Generic`, which let generic code build
  unchecked values behind the abstract constructors.
* Fixed: `newTransaction` now names its first signing key as the fee payer
  (via `newTransactionIntentWithPayer`), so transactions whose only signer is
  a read-only authority -- a memo-only transaction, or a standalone SPL
  `mintTo`/`transferChecked` -- are no longer rejected by the node with
  "Transaction failed to sanitize accounts offsets correctly". The first key
  is forced writable and pinned to account 0 even if no instruction
  references it (sponsored fees), the remaining keys may be passed in any
  order, an empty key list throws `userError`, and an unused key is reported
  as a `CompileException` before the send. Output is byte-identical for every
  transaction that was already valid.
* Added `compileV0MessageWithPayer` and `newV0TransactionIntentWithPayer`,
  the explicit-fee-payer counterparts of the v0 compiler and signer
  (mirroring the Rust SDK's `v0::Message::try_compile(payer, ..)`), plus
  `mkNewMessageWithPayer` and `orderSigningKeys` as exported building blocks.
* Fixed: `newNonceTransaction` now submits with `preflightCommitment =
  "confirmed"` (new `cfgNonceSendConfirmed`), matching the commitment it reads
  the nonce account at. Previously the node's default `finalized` preflight
  rejected the send with `BlockhashNotFound` whenever the nonce account had
  been created or advanced within the last ~32 slots -- i.e. on every
  back-to-back use -- unless the caller first waited for finalization.
* Fixed: `AccountData`'s `FromJSON` decoded a bare `data` string as (lenient)
  base64. Per the RPC account-data format a bare string is the node's legacy
  `binary` encoding, i.e. base58, so `getAccountInfo'`, `getProgramAccounts'`
  and `getTokenAccountsByOwner'`/`ByDelegate'` called with a configuration
  that omits `encoding` (or sets `"binary"`), and `getMultipleAccounts'` with
  `"binary"`, returned silently corrupted bytes for accounts of up to 128
  bytes. Bare strings now decode strictly as
  base58 (invalid input is a parse error) and `AccountData` round-trips
  through its own `ToJSON`; the `[data, "base64"]` form and the
  base64-requesting wrappers are unchanged.
* Fixed: `AccountData` now parses the `{program, parsed, space}` object a
  node returns for `encoding: "jsonParsed"` when it has a parser for the
  owner program (nonce, SPL Token, stake, vote, sysvars, ...). Previously
  every such response failed with `parsing AccountDataArray failed, expected
  Array, but encountered Object` through `getAccountInfo'`,
  `getMultipleAccounts'`, `getProgramAccounts'`, `getTokenAccountsByOwner'`
  and `getTokenAccountsByDelegate'`. The base64 pair the node falls back to
  when no parser exists still decodes to `AccountDataBinary`.
* Changed (breaking): `AccountDataJSON` now carries `accDataProgram ::
  String`, `accDataParsed :: Data.Aeson.Value` and `accDataSpace :: Word64`
  instead of `accDataObj :: String`, and its `ToJSON` instance emits the
  node's object. The `["...","json"]` / `["...","jsonParsed"]` pair forms,
  which no node emits, are no longer accepted. `base64+zstd` account data is
  still rejected as unsupported.
* Fixed: `createMasterEditionV3` now marks the metadata account (index 5)
  writable, matching the official `mpl-token-metadata` client. Previously the
  on-chain program silently left `token_standard` un-upgraded
  (`FungibleAsset` instead of `NonFungible`) when the instruction was sent on
  its own. The builder's account metas are now golden-tested against the
  crate (`master-edition-some-accounts`).
* Fixed: `compileInstruction`, and every message compiler built on it
  (`newMessage`, `newTransactionIntent`, `newTransactionIntentWithPayer`, the
  durable-nonce variants, `compileV0Message`, `newV0TransactionIntent`, and
  the `SolanaWeb3` senders), silently wrapped account indices at or past 256
  into the wrong byte, producing a message the node rejects; such messages
  now fail with a `CompileException` (`MissingIndex` carrying an "account
  index overflow" message), mirroring the Rust SDK's
  `CompileError::AccountIndexOverflow`. Messages with up to 256 account keys
  (static plus table-loaded for v0) are unaffected.
* Changed (breaking): `Context.apiVersion` is now `Maybe Text`,
  `PerformanceSample.numNonVoteTransactions` is now `Maybe Word64` and
  `SolanaVersion.feature_set` is now `Maybe Word32`, matching the upstream
  schema where older nodes and some RPC proxies omit `apiVersion` and older
  performance samples report `numNonVoteTransactions` as `null`; previously
  such responses failed to parse.
* WebSocket: a `signatureNotification` whose value lacks the `err` key is now
  rejected by `parseWsMessage` (and reported as `Left` by `awaitSignature`)
  instead of being treated as a successful confirmation.
* Docs: `getBlock`/`getBlock'`/`getBlockTime` now document that skipped,
  pruned and not-yet-available slots are JSON-RPC errors (-32007/-32001/
  -32004) raised as a `JsonRpcException` that `runWeb3'` does not catch,
  rather than `Nothing`; module headers added for `Core.Instruction`,
  `NativePrograms.ComputeBudget`, `NativePrograms.SystemProgram` and
  `SplPrograms.Memo`; the `SolanaWeb3` header reflects the integration suite;
  CONTRIBUTING links defined.
* Added `confirmFinalized` to `SolanaWeb3`: polls `getSignatureStatuses` up
  to 60 s until a signature is `finalized`, throwing on an on-chain error or
  timeout (previously an integration-suite-only helper). Use it before
  `printBalances`/`getBalance`, which read at the node's default `finalized`
  commitment; `confirmTransaction` returns at `confirmed`, so balances read
  right after it can still show pre-transaction state.
* README usage examples are now complete flows that run as-is against
  `solana-test-validator`: payers are funded and finalized, the SPL example
  creates its own mint and token account, and every flow finalizes before
  reading state. The SPL and priority-fee examples are built as the
  `example-spl-transfer` and `example-priority-fee` executables, and a unit
  test keeps the README text identical to them. The README now states that
  the examples also need the `web3-provider` package (`Network.Web3.Provider`)
  in `build-depends`.
* Corrected the 1.2.0.0 note below, which overstated RPC golden-test coverage.
  `tools/rpc-record` now records every RPC method the SDK binds except
  `requestAirdrop`, `sendTransaction` and `simulateTransaction`, aborts
  instead of silently skipping a method the node rejects, and requires
  `solana-test-validator --slots-per-epoch 32` so `getInflationReward` can be
  captured; `Test.RPC.Parsers` now asserts every RPC-layer `FromJSON`
  instance, including default-encoding (base58) and `jsonParsed` account data.
* The integration suite gains cases for the fixes above: memo-only sends
  through `newTransaction` (legacy and v0), the README SPL and priority-fee
  flows, back-to-back durable-nonce use right after a confirmed create or
  advance, default-encoding and `jsonParsed` account reads, and `getBlock` on
  a slot holding no block.

## 1.2.0.0 -- 2026-08-03

* Added on-chain account-state decoders (SPL token accounts and mints, address lookup tables, stake and nonce accounts, Metaplex metadata) with typed SolanaWeb3 fetch helpers; decoded lookup tables feed compileV0Message directly.
* Added developer-experience helpers: explicit fee-payer transactions with automatic signature ordering (sponsored fees supported), a durable-nonce transaction flow, and priority-fee estimation.
* Added an opt-in local-validator integration test suite (`integration-tests`, behind the `integration` cabal flag) covering SOL and sponsored transfers, the SPL token lifecycle, durable nonces, address lookup tables with v0 transactions, priority fees, and WebSocket confirmation; the suite skips itself when no validator is running.
* Added golden tests for the JSON-RPC response parsers, replaying 37 responses recorded from a live validator by `tools/rpc-record` (36 of the SDK's 52 RPC methods; every RPC-layer `FromJSON` instance except `HighestSnapshotSlot`, `PrioritizationFee` and `InflationReward`; account data in `base64` encoding only -- see the 1.3.0.0 entry).
* Added Solana PubSub (WebSocket) support in `Network.Solana.RPC.WebSocket`: signature and account subscribe/unsubscribe requests, notification parsing, and `awaitSignature` — a push-based confirmation that replaces polling. The module is transport-agnostic (`WsTransport`), so the library gains no new dependency and works with both `ws://` and `wss://` endpoints.

## 1.1.0.0 -- 2026-08-01

* Added Metaplex Token Metadata client (CreateMetadataAccountV3, UpdateMetadataAccountV2, CreateMasterEditionV3) with metadata/master-edition PDA derivation, built on a new minimal Borsh serialization layer.
* Added Address Lookup Table program client and versioned (v0) transaction support: compile messages against lookup tables and sign VersionedTransactions (encode-only; account-state parsing out of scope). The `CompileException` constructor (`MissingIndex`) is now exported for error inspection.
* Hackage-ready packaging: PVP upper bounds on all dependencies; homepage and bug-reports metadata.

## 1.0.0.0 -- 2026-08-01

First stable release: byte-verified clients for System, Compute Budget, Stake, Vote, BPF Loader (upgradeable), Secp256k1, SPL Memo, SPL Token, and Associated Token Account programs; PDA derivation; canonical Rust-identical message compilation.

* Changed: `sendTransaction`'s default configuration no longer skips preflight
  simulation and no longer caps retries — submissions now follow the node's
  defaults (preflight runs; the node rebroadcasts until blockhash expiry).
  Transactions failing simulation return an RPC error instead of a signature.
* Changed: account-fetching RPC methods now request `base64` encoding
  explicitly for reliable binary account data.
* Hardened all RPC-facing JSON parsers to be total: malformed or unexpected
  node responses (failed transactions, v0 transactions, pruned/unknown slots)
  no longer crash the client.
* Fixed: `mkPrivateKeyFromString` rejected valid 64-byte private keys; now
  parses them correctly.
* Fixed: `BlockHash` and `CompactArray` `Binary` decoding were asymmetric
  with their `put` (falling back to an incompatible/length-prefixed
  decoder); both now round-trip correctly.
* Fixed documentation typos referring to the `RPCResponse` type (the
  exported name never changed) and renamed RPC fields for consistency
  (`Ammount*` -> `Amount*`); changed transaction/account error fields to
  structured `Maybe Value` instead of partial `Maybe String`.
* Renamed `ClusterNodes.sharedVersion` to `shredVersion` (typo fix; matches
  the RPC field).
* Added `confirmTransaction` to `SolanaWeb3`: polls for `confirmed`/
  `finalized` status instead of a fixed `wait`.
* Haddock coverage completed for the Core, RPC/HTTP, and SolanaWeb3 modules
  touched by the quality pass (module headers and per-export documentation);
  `cabal haddock` exits 0 with a handful of internal native/SPL-program
  helpers still undocumented.
* Added upgradeable BPF loader client (buffer/write/deploy/upgrade/authority/
  close/extend) with program-data address derivation.
* Added secp256k1 precompile client: signature-verification instruction
  construction from a precomputed signature (signing is out of scope).
* Added Stake program client (initialize, authorize, delegate, split, withdraw,
  deactivate, lockup, merge, checked variants) — golden-tested against the Rust SDK.
* Added Vote program client (account management: initialize, authorize, withdraw,
  identity/commission updates); consensus voting instructions are out of scope.
* Added SPL Token program client (instructions 0-20: mint/account initialization,
  transfers, approvals, minting, burning, freezing, multisig support) —
  golden-tested against the `spl-token` Rust crate.
* Added Associated Token Account program client with address derivation.
* Added Program Derived Address (PDA) support: `createProgramAddress` /
  `findProgramAddress` with ed25519 on-curve rejection (new `crypton` and `memory` dependencies).
* Added Compute Budget program client: request heap frame, set compute unit
  limit, set compute unit price (priority fees), set loaded accounts data size
  limit — golden-tested against the Rust SDK.
* Added SPL Memo (v2) program client.
* Added binary decoding for `SystemInstruction` and `ComputeBudgetInstruction`
  (symmetric `Binary` instances, round-trip tested).
* Fixed: account keys within each privilege section are now ordered
  canonically (sorted by pubkey, fee payer first) to match the Rust SDK, so
  multi-program messages serialize byte-identically. For multi-signer
  transactions, signing keys must be passed in the canonical account order
  (fee payer first).
* Test suite: golden vectors generated from the Rust `solana-sdk` (byte-for-byte
  serialization checks at instruction, message, and signed-transaction level),
  plus QuickCheck properties for compact-u16, crypto round-trips, and message
  header/key-ordering invariants.
* Fixed: pubkeys inside System Program instruction data were serialized with a
  length prefix (invalid wire format).
* Fixed: `CreateAccountWithSeed` seed was missing its u64 length prefix.
* Fixed: `SolanaSignature` binary decoding read 32 bytes instead of 64.
* Fixed: the program id was appended as an extra account to every instruction;
  it is now added only to the message account keys.
* Fixed: account privilege deduplication in message building used the wrong
  buckets to decide writability, producing duplicate keys or wrongly-writable
  accounts when the same account appeared in several instructions with mixed
  privileges.
* Fixed: compact-u16 decoding now rejects aliased (non-canonical) encodings.
* Fixed: `CompiledInstruction` JSON parsing fails cleanly on invalid base58.
* Added the 9 remaining System Program instructions: nonce account management
  (advance, withdraw, initialize, authorize, upgrade) and
  allocate/assign/transfer with seed.
* Added CI (GitHub Actions).

## 0.1.0.0 -- 2024 (unreleased alpha)

* Initial alpha: JSON-RPC API client, key management, System Program transfers.