diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,59 @@
 # 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
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@
 
 ## Documentation
 
-API documentation is generated with Haddock (`cabal haddock`). Serialization correctness methodology: every instruction, message, and transaction encoder is asserted byte-identical to vectors generated from the official Rust crates (solana-sdk, spl-token, mpl-token-metadata) — see [tools/README.md](https://github.com/mariusgeorgescu/solana-haskell-sdk/blob/main/tools/README.md).
+API documentation is generated with Haddock (`cabal haddock`). Serialization correctness methodology: each instruction, message, and transaction encoder is asserted byte-identical to a golden vector — generated from the official Rust crates (solana-sdk, spl-token, mpl-token-metadata), except for the v1 transaction format, whose vector is a transaction recorded from devnet (the pinned Rust crates predate it) — see [tools/README.md](https://github.com/mariusgeorgescu/solana-haskell-sdk/blob/main/tools/README.md).
 
 ## Integration tests
 
@@ -67,6 +67,7 @@
 - [x] Transaction building, signing and submission
   - [x] Priority fees via Compute Budget (`setComputeUnitLimit`, `setComputeUnitPrice`)
   - [x] Versioned (v0) transactions and Address Lookup Tables
+  - [x] v1 transactions (SIMD-0385): inline addresses, header config mask, 4096-byte limit
   - [x] Clients for native programs
     - [x] Address Lookup Table
     - [x] BPF Loader (upgradeable)
@@ -82,11 +83,11 @@
   - [x] Metaplex Token Metadata (create/update metadata, master edition)
 - [x] On-chain account state decoders (SPL token accounts and mints, lookup tables, stake and nonce accounts, Metaplex metadata)
 - [x] PubSub (WebSocket) signature and account subscriptions, with push-based confirmation
-- [x] Serialization verified byte-for-byte against the official Rust crates (solana-sdk, spl-token, mpl-token-metadata) (golden-vector tests)
+- [x] Serialization verified byte-for-byte by golden-vector tests, against the official Rust crates (solana-sdk, spl-token, mpl-token-metadata) — and, for v1, against a transaction recorded from devnet
 
 ### Release status
 
-The current stable release is **v1.3.0.0**. Serialization is verified byte-for-byte against the official Rust SDK by golden-vector tests (see test/fixtures/ and [tools/README.md](https://github.com/mariusgeorgescu/solana-haskell-sdk/blob/main/tools/README.md)).
+The current stable release is **v1.4.0.0**. Serialization is verified byte-for-byte by golden-vector tests — against the official Rust SDK, and for the v1 format against a transaction recorded from devnet (see test/fixtures/ and [tools/README.md](https://github.com/mariusgeorgescu/solana-haskell-sdk/blob/main/tools/README.md)).
 
 ## Usage Examples
 
diff --git a/solana-haskell-sdk.cabal b/solana-haskell-sdk.cabal
--- a/solana-haskell-sdk.cabal
+++ b/solana-haskell-sdk.cabal
@@ -1,6 +1,6 @@
 cabal-version:   3.0
 name:            solana-haskell-sdk
-version:         1.3.0.0
+version:         1.4.0.0
 synopsis:        Solana SDK: transaction building, signing, program clients, and JSON-RPC.
 homepage:        https://github.com/mariusgeorgescu/solana-haskell-sdk
 bug-reports:     https://github.com/mariusgeorgescu/solana-haskell-sdk/issues
@@ -12,7 +12,9 @@
 
   This library is aimed at developers building Solana dApps, tools, or infrastructure in Haskell.
 
-  All serialization is verified byte-for-byte against the official Rust SDK by golden-vector tests.
+  Serialization is verified byte-for-byte by golden-vector tests: against vectors generated
+  from the official Rust crates, except the v1 (SIMD-0385) transaction format, whose vector is
+  a transaction recorded from devnet because the pinned Rust crates predate the format.
 
 license:         Apache-2.0
 license-file:    LICENSE
@@ -58,6 +60,7 @@
     Network.Solana.Core.Crypto
     Network.Solana.Core.Instruction
     Network.Solana.Core.Message
+    Network.Solana.Core.MessageV1
     Network.Solana.Core.Pda
     Network.Solana.Core.Transaction
     Network.Solana.Core.VersionedMessage
@@ -180,6 +183,7 @@
     Test.Core.Crypto
     Test.Core.Instruction
     Test.Core.Message
+    Test.Core.MessageV1
     Test.Core.Pda
     Test.Core.VersionedMessage
     Test.Fixtures
diff --git a/src/Network/Solana/Core/Instruction.hs b/src/Network/Solana/Core/Instruction.hs
--- a/src/Network/Solana/Core/Instruction.hs
+++ b/src/Network/Solana/Core/Instruction.hs
@@ -16,7 +16,7 @@
     AccountMeta (..),
     InstructionData (..),
     compileInstruction,
-    CompiledInstruction,
+    CompiledInstruction (..),
     CompileException (..),
   )
 where
@@ -189,11 +189,24 @@
 -- *** CompileException
 
 ------------------------------------------------------------------------------------------------
--- | Compilation failure, carrying a message: an instruction references an
--- account key that is missing from the message's account table, an account
--- or lookup-table index does not fit in a byte, or a signing key does not
--- match the message's required signers.
-newtype CompileException = MissingIndex String
+-- | Compilation failure. Each constructor carries a human-readable
+-- explanation; the constructor says which kind of problem it is, so callers
+-- can react without matching on the text.
+data CompileException
+  = -- | An instruction references an account key that is missing from the
+    -- message's account table, an account or lookup-table index does not
+    -- fit in a byte, or a signing key does not match the message's
+    -- required signers.
+    MissingIndex String
+  | -- | A count or size exceeds what the transaction format allows: how
+    -- many addresses, instructions or signatures a message may carry, how
+    -- large a single instruction may be, or how large the whole signed
+    -- transaction may be.
+    LimitExceeded String
+  | -- | The message is structurally well-formed, but the network would
+    -- reject it at sanitize time -- or would accept it, charge the fee
+    -- payer, and run a transaction that cannot do any work.
+    InvalidMessage String
   deriving (Show)
 
 instance Exception CompileException
diff --git a/src/Network/Solana/Core/MessageV1.hs b/src/Network/Solana/Core/MessageV1.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Solana/Core/MessageV1.hs
@@ -0,0 +1,352 @@
+{-# LANGUAGE RecordWildCards #-}
+
+-- |
+-- Module      : Network.Solana.Core.MessageV1
+-- Description : v1 message compilation (SIMD-0385) and v1 transaction signing.
+--
+-- The v1 transaction format carries its resource requests in a header
+-- configuration mask instead of @ComputeBudget@ instructions, lists every
+-- address inline (it has no address lookup tables), and places the
+-- signatures /after/ the message rather than before it. See
+-- "Network.Solana.Core.VersionedMessage" for v0, which is the format to use
+-- when lookup tables are needed.
+--
+-- Unlike the legacy and v0 builders, both entry points here take the fee
+-- payer explicitly. The reference implementation's only v1 compile path
+-- does the same (@v1::Message::try_compile_with_config(payer, ..)@), and
+-- deriving the payer implicitly from the instruction list is a trap this
+-- format makes expensive: the priority fee travels inside the message, so
+-- whoever lands in account 0 pays it.
+module Network.Solana.Core.MessageV1
+  ( TransactionConfig (..),
+    emptyTransactionConfig,
+    compileV1Message,
+    newV1TransactionIntent,
+  )
+where
+
+import Data.Binary (Word16, Word32, Word64, Word8, put)
+import Data.Binary.Put
+import Data.Bits ((.|.))
+import Data.ByteString qualified as BS
+import Data.ByteString.Lazy qualified as BL
+import GHC.Generics (Generic)
+import Network.Solana.Core.Block (BlockHash)
+import Network.Solana.Core.Compact (unCompact)
+import Network.Solana.Core.Crypto
+  ( SolanaPrivateKey,
+    SolanaPublicKey,
+    dsign,
+    getSolanaSignatureRaw,
+    toBase64String,
+  )
+import Network.Solana.Core.Instruction
+import Network.Solana.Core.Message
+
+------------------------------------------------------------------------------------------------
+
+-- * TransactionConfig
+
+------------------------------------------------------------------------------------------------
+
+-- | The resource requests a v1 message carries in place of the
+-- @ComputeBudget@ instructions earlier formats use. Each field present
+-- sets its bit in the message's configuration mask and appends its value.
+--
+-- __An absent field does not mean \"the usual default\"__: SIMD-0385 uses
+-- the /minimum/ value instead, which for two of these fields is zero. A
+-- transaction requesting zero compute units, or zero bytes of loaded
+-- account data, is still accepted into a block and still charges its fee
+-- payer -- it simply fails without doing anything. 'compileV1Message'
+-- therefore refuses to build one; see 'emptyTransactionConfig'.
+--
+-- @ComputeBudget@ instructions placed in a v1 transaction are ignored for
+-- configuration purposes -- they still execute, as successful no-ops that
+-- consume compute units -- so resource requests must be made here.
+data TransactionConfig = TransactionConfig
+  { -- | Total priority fee, in lamports; absent means 0.
+    --
+    -- __Not the same unit as @ComputeBudget@__: @SetComputeUnitPrice@ takes
+    -- micro-lamports /per compute unit/, while this is a flat total. A
+    -- value carried across unconverted overpays by a factor of up to a
+    -- million, and the network accepts it. To port one, multiply the price
+    -- by the compute-unit limit and divide by 1e6.
+    tcPriorityFee :: Maybe Word64,
+    -- | Maximum compute units the transaction may consume. Absent means 0,
+    -- which cannot execute anything, so this is effectively required.
+    tcComputeUnitLimit :: Maybe Word32,
+    -- | Maximum bytes of account data the transaction may load. Absent
+    -- means 0 -- not the 64 MiB earlier formats default to -- so this is
+    -- effectively required too.
+    tcLoadedAccountsDataSizeLimit :: Maybe Word32,
+    -- | Heap size in bytes; absent means 32 KiB. When given it must be a
+    -- multiple of 1024 and within [32768, 262144]; 'compileV1Message'
+    -- rejects anything else.
+    tcHeapSize :: Maybe Word32
+  }
+  deriving (Show, Eq, Generic)
+
+-- | A configuration requesting nothing at all.
+--
+-- This is a base for record update, not a usable configuration:
+-- 'compileV1Message' rejects it, because a v1 message with no compute-unit
+-- limit and no loaded-accounts limit requests zero of both and so is
+-- guaranteed to be charged for and then fail (see 'TransactionConfig').
+-- Fill in at least those two fields:
+--
+-- > emptyTransactionConfig
+-- >   { tcComputeUnitLimit = Just 200000,
+-- >     tcLoadedAccountsDataSizeLimit = Just 131072
+-- >   }
+emptyTransactionConfig :: TransactionConfig
+emptyTransactionConfig =
+  TransactionConfig
+    { tcPriorityFee = Nothing,
+      tcComputeUnitLimit = Nothing,
+      tcLoadedAccountsDataSizeLimit = Nothing,
+      tcHeapSize = Nothing
+    }
+
+------------------------------------------------------------------------------------------------
+
+-- * Compile v1 message
+
+------------------------------------------------------------------------------------------------
+
+-- | Compile a v1 message for the given fee payer: assemble the account keys
+-- exactly as the legacy and v0 builders do (privilege union, then canonical
+-- ordering, via 'mkNewMessageWithPayer', which seeds the payer as a writable
+-- signer and pins it to account 0), then serialize them in the v1 layout
+-- behind the @129@ version byte. Naming the payer also supports sponsored
+-- fees: it need not appear in any instruction.
+--
+-- Fails with a 'CompileException' when the result would not be a usable v1
+-- message:
+--
+-- * 'LimitExceeded' -- more than 64 addresses, more than 64 instructions,
+--   more than 12 required signatures, an instruction with more than 255
+--   accounts or more than 65535 data bytes, or a transaction that would
+--   exceed 4096 bytes once signed.
+-- * 'InvalidMessage' -- no instructions at all, the fee payer used as a
+--   program id, a compute-unit or loaded-accounts request of zero (see
+--   'TransactionConfig'), or a heap request that is not a multiple of 1024
+--   within [32768, 262144].
+compileV1Message ::
+  SolanaPublicKey -> BlockHash -> [Instruction] -> TransactionConfig -> Either CompileException BS.ByteString
+compileV1Message payer bh instructions =
+  compileV1FromLegacy (mkNewMessageWithPayer payer bh instructions)
+
+-- | Build and sign a v1 transaction for the given fee payer, returning it
+-- Base64-encoded. A v1 transaction puts the message first and the
+-- signatures last, as a bare sequence of 64-byte signatures with no length
+-- prefix -- the reverse of the legacy and v0 envelopes, and the reason the
+-- signature count has to match the message's required signers exactly:
+-- there is no count on the wire to describe a mismatch.
+--
+-- The given private keys may be listed in any order. They are matched
+-- against the compiled message's required signers and placed in message
+-- order automatically, so a key for the wrong account, a missing key or a
+-- spare key is a 'MissingIndex' failure rather than a silently malformed
+-- transaction.
+newV1TransactionIntent ::
+  SolanaPublicKey ->
+  [SolanaPrivateKey] ->
+  [Instruction] ->
+  TransactionConfig ->
+  BlockHash ->
+  Either CompileException String
+newV1TransactionIntent payer signingKeys instructions config bh = do
+  let legacy = mkNewMessageWithPayer payer bh instructions
+  msg <- compileV1FromLegacy legacy config
+  orderedKeys <- orderSigningKeys legacy signingKeys
+  return $ toBase64String (msg <> signaturesOver msg orderedKeys)
+
+------------------------------------------------------------------------------------------------
+
+-- * Internal helpers
+
+------------------------------------------------------------------------------------------------
+
+-- | Serialize an assembled legacy message in the v1 layout.
+--
+-- The header's @numReadonlySignedAccounts < numRequiredSignatures@ sanitize
+-- rule needs no check here: every caller routes through
+-- 'mkNewMessageWithPayer', which puts the payer in the writable-signer
+-- section and never demotes it, so that section is never empty.
+compileV1FromLegacy :: Message -> TransactionConfig -> Either CompileException BS.ByteString
+compileV1FromLegacy legacy config = do
+  compiled <- mapM (compileInstruction keys) (mInstructions legacy)
+  checkLimits legacy compiled config
+  let bytes = BL.toStrict . runPut $ do
+        putWord8 v1Prefix
+        put (mHeader legacy)
+        putWord32le (configMask config)
+        put (mRecentBlockhash legacy)
+        putWord8 (fromIntegral (length compiled))
+        putWord8 (fromIntegral (length keys))
+        mapM_ put keys
+        putConfigValues config
+        mapM_ putInstructionHeader compiled
+        mapM_ putInstructionPayload compiled
+  checkTransactionSize legacy bytes
+  return bytes
+  where
+    keys = mAccountKeys legacy
+
+-- | The trailing signature array: each signer's 64 raw signature bytes over
+-- the whole serialized message, concatenated without a length prefix.
+signaturesOver :: BS.ByteString -> [SolanaPrivateKey] -> BS.ByteString
+signaturesOver msg signers = mconcat (getSolanaSignatureRaw . flip dsign msg <$> signers)
+
+-- | The version byte a v1 transaction opens with.
+v1Prefix :: Word8
+v1Prefix = 129
+
+-- | The configuration mask: one bit per requested field, except the
+-- priority fee, which occupies two (both must be set, and its value is
+-- eight bytes wide rather than four).
+--
+-- The compute-unit and loaded-accounts bits are only distinguishable from
+-- each other when exactly one of the two is present, which 'checkLimits'
+-- forbids -- so no test can pin them apart while that guard stands. Relax
+-- the guard and they need pinning.
+configMask :: TransactionConfig -> Word32
+configMask TransactionConfig {..} =
+  bitFor tcPriorityFee 0b11
+    .|. bitFor tcComputeUnitLimit 0b100
+    .|. bitFor tcLoadedAccountsDataSizeLimit 0b1000
+    .|. bitFor tcHeapSize 0b10000
+  where
+    bitFor field bits = maybe 0 (const bits) field
+
+-- | The requested values, in field order, each present only when its mask
+-- bit is set.
+putConfigValues :: TransactionConfig -> Put
+putConfigValues TransactionConfig {..} = do
+  mapM_ putWord64le tcPriorityFee
+  mapM_ putWord32le tcComputeUnitLimit
+  mapM_ putWord32le tcLoadedAccountsDataSizeLimit
+  mapM_ putWord32le tcHeapSize
+
+-- | One instruction's fixed-width header: program id index, account count,
+-- and data length. All headers precede all payloads on the wire.
+putInstructionHeader :: CompiledInstruction -> Put
+putInstructionHeader CompiledInstruction {..} = do
+  putWord8 ciProgramIdIndex
+  putWord8 (fromIntegral (length (unCompact ciAccounts)))
+  putWord16le (fromIntegral (length (unCompact ciData)))
+
+-- | One instruction's variable-width payload: its account indices followed
+-- by its data bytes, neither length-prefixed (the header carries both
+-- lengths).
+putInstructionPayload :: CompiledInstruction -> Put
+putInstructionPayload CompiledInstruction {..} = do
+  mapM_ putWord8 (unCompact ciAccounts)
+  mapM_ putWord8 (unCompact ciData)
+
+-- | Everything the builder can check before serializing: the format's count
+-- caps, the sanitize rules reachable from here, and the resource requests
+-- that would make the transaction pay to do nothing.
+checkLimits :: Message -> [CompiledInstruction] -> TransactionConfig -> Either CompileException ()
+checkLimits legacy compiled TransactionConfig {..} = do
+  limit "addresses" maxAddresses (length (mAccountKeys legacy))
+  limit "instructions" maxInstructions (length compiled)
+  limit "required signatures" maxSignatures (fromIntegral (numRequiredSignatures (mHeader legacy)))
+  checkNonEmpty
+  mapM_ checkInstruction compiled
+  checkRequest "compute-unit limit" tcComputeUnitLimit
+  checkRequest "loaded-accounts data size limit" tcLoadedAccountsDataSizeLimit
+  mapM_ checkHeapSize tcHeapSize
+  where
+    limit what cap actual
+      | actual <= cap = Right ()
+      | otherwise =
+          Left
+            ( LimitExceeded
+                ("v1 message has " <> show actual <> " " <> what <> ", more than the " <> show cap <> " allowed")
+            )
+    checkNonEmpty
+      | null compiled = Left (InvalidMessage "v1 message has no instructions, so it would pay a fee to do nothing")
+      | otherwise = Right ()
+    checkInstruction CompiledInstruction {..} = do
+      limit "accounts in one instruction" maxInstructionAccounts (length (unCompact ciAccounts))
+      limit "data bytes in one instruction" maxInstructionData (length (unCompact ciData))
+      if ciProgramIdIndex == 0
+        then Left (InvalidMessage "v1 instruction invokes account 0, but the fee payer cannot be a program id")
+        else Right ()
+    -- Absent or zero are the same request on the wire, and both guarantee
+    -- an included, charged, failing transaction -- so both are refused.
+    checkRequest what request
+      | request `elem` [Nothing, Just 0] =
+          Left
+            ( InvalidMessage
+                ( "v1 message requests a "
+                    <> what
+                    <> " of 0, which cannot execute anything; set it in the TransactionConfig"
+                )
+            )
+      | otherwise = Right ()
+    checkHeapSize n
+      | n `mod` 1024 /= 0 =
+          Left (InvalidMessage ("v1 heap size " <> show n <> " is not a multiple of 1024"))
+      | n < minHeapSize =
+          Left (InvalidMessage ("v1 heap size " <> show n <> " is below the minimum of " <> show minHeapSize))
+      | n > maxHeapSize =
+          Left (InvalidMessage ("v1 heap size " <> show n <> " is above the maximum of " <> show maxHeapSize))
+      | otherwise = Right ()
+
+-- | Reject a message whose transaction -- the message plus one 64-byte
+-- signature per required signer -- would exceed the v1 size cap. Checked on
+-- the message, since the header fixes the signature count and
+-- 'newV1TransactionIntent' signs exactly that many.
+checkTransactionSize :: Message -> BS.ByteString -> Either CompileException ()
+checkTransactionSize legacy bytes
+  | total <= maxTransactionSize = Right ()
+  | otherwise =
+      Left
+        ( LimitExceeded
+            ( "v1 transaction is "
+                <> show total
+                <> " bytes, more than the "
+                <> show maxTransactionSize
+                <> " allowed"
+            )
+        )
+  where
+    signatures = signatureSize * fromIntegral (numRequiredSignatures (mHeader legacy))
+    total = BS.length bytes + signatures
+
+-- | Addresses are counted by a single byte and capped at 64 by SIMD-0385.
+maxAddresses :: Int
+maxAddresses = 64
+
+-- | Instructions are counted by a single byte and capped at 64.
+maxInstructions :: Int
+maxInstructions = 64
+
+-- | A v1 transaction may carry at most 12 signatures.
+maxSignatures :: Int
+maxSignatures = 12
+
+-- | An instruction's account count is a single byte.
+maxInstructionAccounts :: Int
+maxInstructionAccounts = fromIntegral (maxBound :: Word8)
+
+-- | An instruction's data length is a 'Word16'.
+maxInstructionData :: Int
+maxInstructionData = fromIntegral (maxBound :: Word16)
+
+-- | A v1 transaction may be at most 4096 bytes on the wire (SIMD-0296),
+-- against the 1232 of earlier formats.
+maxTransactionSize :: Int
+maxTransactionSize = 4096
+
+-- | One ed25519 signature.
+signatureSize :: Int
+signatureSize = 64
+
+minHeapSize :: Word32
+minHeapSize = 32 * 1024
+
+maxHeapSize :: Word32
+maxHeapSize = 256 * 1024
diff --git a/src/Network/Solana/RPC/HTTP/Block.hs b/src/Network/Solana/RPC/HTTP/Block.hs
--- a/src/Network/Solana/RPC/HTTP/Block.hs
+++ b/src/Network/Solana/RPC/HTTP/Block.hs
@@ -46,16 +46,24 @@
 {-# INLINE getBlock' #-}
 
 -- | Returns identity and transaction information about a confirmed block in
--- the ledger. Sets @maxSupportedTransactionVersion@ so that blocks
--- containing versioned (v0) transactions can be decoded (without it, such
--- blocks make the node respond with error -32015); as a result, v0
--- transactions are returned without their address-lookup-table data, so
--- instruction account indices may reference addresses not present in the
--- parsed account keys.
+-- the ledger. Sets @maxSupportedTransactionVersion@ to 1, so that blocks
+-- containing v0 or v1 (SIMD-0385) transactions can be decoded -- without a
+-- high enough value such blocks make the node respond with error -32015,
+-- and v1 transactions are now a routine part of blocks.
+--
+-- Versioned transactions are returned without the message parts
+-- t'Network.Solana.Core.Message.CompiledMessage' does not model: a v0
+-- transaction's address-lookup-table data (so instruction account indices
+-- may reference addresses not present in the parsed account keys), and a v1
+-- transaction's @transactionConfig@ resource requests (its priority fee,
+-- compute-unit limit, loaded-accounts size limit and heap size -- which in
+-- v1 replace the @ComputeBudget@ instructions earlier formats carry, so
+-- unlike a legacy transaction's, they are not visible among the parsed
+-- instructions either).
 -- A slot holding no block is a JSON-RPC error rather than 'Nothing'; see
 -- 'getBlock''.
 getBlock :: (JsonRpc m) => Slot -> m (Maybe BlockInfo)
-getBlock slot = getBlock' slot (defaultConfigObject {encoding = Just "json", maxSupportedTransactionVersion = Just 0})
+getBlock slot = getBlock' slot (defaultConfigObject {encoding = Just "json", maxSupportedTransactionVersion = Just 1})
 {-# INLINE getBlock #-}
 
 -- | Contains identity and transaction information for a block.
diff --git a/src/Network/Solana/RPC/HTTP/Transaction.hs b/src/Network/Solana/RPC/HTTP/Transaction.hs
--- a/src/Network/Solana/RPC/HTTP/Transaction.hs
+++ b/src/Network/Solana/RPC/HTTP/Transaction.hs
@@ -55,14 +55,19 @@
 {-# INLINE getTransaction' #-}
 
 -- | Returns metadata and content for a confirmed transaction identified by
--- its signature. Sets @maxSupportedTransactionVersion@ so that versioned
--- (v0) transactions can be decoded (without it, the node responds with
--- error -32015); as a result, v0 transactions are returned without their
--- address-lookup-table data, so instruction account indices may reference
--- addresses not present in the parsed account keys.
+-- its signature. Sets @maxSupportedTransactionVersion@ to 1, so that v0 and
+-- v1 (SIMD-0385) transactions can be decoded -- without a high enough value
+-- the node responds with error -32015.
+--
+-- Versioned transactions are returned without the message parts
+-- t'Network.Solana.Core.Message.CompiledMessage' does not model: a v0
+-- transaction's address-lookup-table data (so instruction account indices
+-- may reference addresses not present in the parsed account keys), and a v1
+-- transaction's @transactionConfig@ resource requests (see
+-- 'Network.Solana.RPC.HTTP.Block.getBlock').
 -- Returns 'Nothing' if the signature is unknown or has expired.
 getTransaction :: (JsonRpc m) => SolanaSignature -> m (Maybe TransactionResult)
-getTransaction sig = getTransaction' sig (defaultConfigObject {encoding = Just "json", maxSupportedTransactionVersion = Just 0})
+getTransaction sig = getTransaction' sig (defaultConfigObject {encoding = Just "json", maxSupportedTransactionVersion = Just 1})
 {-# INLINE getTransaction #-}
 
 -- | Contains metadata and transaction information returned by 'getTransaction'.
diff --git a/src/Network/Solana/RPC/HTTP/Types.hs b/src/Network/Solana/RPC/HTTP/Types.hs
--- a/src/Network/Solana/RPC/HTTP/Types.hs
+++ b/src/Network/Solana/RPC/HTTP/Types.hs
@@ -94,9 +94,14 @@
     minContextSlot :: Maybe Int,
     -- | Whether to search older confirmed transaction history.
     searchTransactionHistory :: Maybe Bool,
-    -- | The maximum transaction version to return in responses. Required to
-    -- fetch blocks or transactions containing versioned (v0) transactions;
-    -- omitting it causes the RPC to reject them with error -32015.
+    -- | The maximum transaction version to return in responses. A node
+    -- rejects a block or transaction whose version exceeds this with error
+    -- -32015, and omitting it admits legacy transactions only, so fetching
+    -- v0 requires at least @0@ and v1 (SIMD-0385) at least @1@. The
+    -- bindings' own defaults send @1@.
+    --
+    -- A value of @1@ or above cannot be combined with @base58@ encoding;
+    -- a current node answers that combination with @invalid_params@.
     maxSupportedTransactionVersion :: Maybe Int
   }
   deriving (Generic, Show)
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -7,6 +7,7 @@
 import Test.Core.Crypto qualified
 import Test.Core.Instruction qualified
 import Test.Core.Message qualified
+import Test.Core.MessageV1 qualified
 import Test.Core.Pda qualified
 import Test.Core.VersionedMessage qualified
 import Test.Metaplex.TokenMetadata qualified
@@ -40,6 +41,7 @@
           Test.Core.Crypto.tests,
           Test.Core.Instruction.tests,
           Test.Core.Message.tests,
+          Test.Core.MessageV1.tests,
           Test.Core.Pda.tests,
           Test.Core.VersionedMessage.tests,
           Test.Metaplex.TokenMetadata.tests,
diff --git a/test/Test/Core/MessageV1.hs b/test/Test/Core/MessageV1.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Core/MessageV1.hs
@@ -0,0 +1,475 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Golden and behaviour tests for v1 (SIMD-0385) message compilation.
+--
+-- The golden vector is a real transaction recorded from devnet
+-- (@test\/fixtures\/v1_transactions.json@), not a hand-written sample: its
+-- inputs are fed back through the builder and the result must match the
+-- bytes the network actually carried. That is how the layout stays pinned
+-- while @tools\/fixture-gen@ remains on its solana-sdk 1.18 pin, which
+-- predates the format and so cannot generate a vector for it.
+--
+-- One recorded transaction cannot pin everything, so the cases after it
+-- cover what it structurally cannot: it has a single instruction (so it
+-- cannot tell all-headers-then-all-payloads apart from interleaved), a
+-- single signer (so it cannot tell signature slots apart), and no heap
+-- request. Each limit is pinned by a pair of cases straddling it rather
+-- than by matching a number in an error message.
+module Test.Core.MessageV1 (tests) where
+
+import Data.Binary (Binary (..), Word8)
+import Data.Binary.Put (putByteString)
+import Data.ByteString qualified as BS
+import Data.List (isInfixOf)
+import Network.Solana.Core.Block (BlockHash (..))
+import Network.Solana.Core.Crypto
+import Network.Solana.Core.Instruction (AccountMeta (..), CompileException (..), Instruction, mkInstruction)
+import Network.Solana.Core.MessageV1
+import Network.Solana.NativePrograms.SystemProgram qualified as SP
+import Test.Fixtures
+import Test.Tasty
+import Test.Tasty.HUnit
+
+-- | Instruction data passed through verbatim; 'mkInstruction' encodes its
+-- payload with 'Binary', and the standard instances for 'BS.ByteString' and
+-- lists prepend a length the wire format must not carry.
+newtype RawData = RawData BS.ByteString
+
+instance Binary RawData where
+  put (RawData bs) = putByteString bs
+  get = fail "RawData: decoding not used"
+
+------------------------------------------------------------------------------------------------
+-- The recorded devnet transaction, as its own inputs.
+------------------------------------------------------------------------------------------------
+
+-- | Fee payer: the single required signer, writable.
+devnetPayer :: SolanaPublicKey
+devnetPayer = unsafeSolanaPublicKey "4QVtKaZkDhEwKszzJWa7LJPZBFkkcgUVRG4xE3fkWNGt"
+
+-- | The one writable unsigned account.
+devnetWritable :: SolanaPublicKey
+devnetWritable = unsafeSolanaPublicKey "55gx5ra96qkYXXMGShkVjwQz1k4j9bS26HhdksFa9buL"
+
+-- | The invoked program.
+devnetProgram :: SolanaPublicKey
+devnetProgram = unsafeSolanaPublicKey "MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM"
+
+devnetClock :: SolanaPublicKey
+devnetClock = unsafeSolanaPublicKey "SysvarC1ock11111111111111111111111111111111"
+
+devnetBlockhash :: BlockHash
+devnetBlockhash = BlockHash (requireBase58 "4iSS7zQNeY8BTSWZ9VRMBo8B17AyijyLDD8C2EycoW19")
+
+-- | The recorded instruction's 90 data bytes.
+devnetInstructionData :: BS.ByteString
+devnetInstructionData =
+  requireBase58
+    "2isQdwGHZhqBC7JtD5qgwY3fpHY2d1ciRmLgt9KN5x75VY2UxdpWv67RMmcvfJCqk5SAeAV4zDVqkkrgrJga5gREAVsRKJUhgqq5ZxqV2rNZhRkuobuQtQubPy9"
+
+-- | @priorityFee = 0@, @computeUnitLimit = 324@,
+-- @loadedAccountsDataSizeLimit = 43008@, no heap request -- config mask 0xF.
+devnetConfig :: TransactionConfig
+devnetConfig =
+  TransactionConfig
+    { tcPriorityFee = Just 0,
+      tcComputeUnitLimit = Just 324,
+      tcLoadedAccountsDataSizeLimit = Just 43008,
+      tcHeapSize = Nothing
+    }
+
+requireBase58 :: String -> BS.ByteString
+requireBase58 s = maybe (error ("bad base58: " <> s)) id (fromBase58String s)
+
+tests :: TestTree
+tests =
+  testGroup
+    "v1 message compilation (SIMD-0385)"
+    [ testCase "message bytes match a transaction recorded from devnet" $ do
+        (expectedMessage, signature) <- devnetGolden
+        let ix =
+              mkInstruction
+                devnetProgram
+                [ AccountMeta devnetPayer True True,
+                  AccountMeta devnetClock False False,
+                  AccountMeta devnetWritable False True
+                ]
+                (RawData devnetInstructionData)
+        bytes <- requireRight (compileV1Message devnetPayer devnetBlockhash [ix] devnetConfig)
+        bytes @?= expectedMessage
+        -- Cross-check the fixture against itself: the bytes the golden
+        -- compares to must be exactly what the recorded signature signs, so
+        -- a re-recording with a different signer count cannot silently
+        -- shift the split point.
+        assertBool
+          "the recorded signature verifies over the recorded message"
+          (dverify devnetPayer expectedMessage signature),
+      testGroup "wire layout the recorded transaction cannot pin" layoutTests,
+      testGroup "configuration mask" maskTests,
+      testGroup "signatures" signatureTests,
+      testGroup "limits" limitTests,
+      testGroup "refused as unusable" unusableTests
+    ]
+
+-- | The recorded transaction, split into the message and its one signature
+-- using the signer count the header itself declares (byte 1) rather than a
+-- hardcoded offset.
+devnetGolden :: IO (BS.ByteString, SolanaSignature)
+devnetGolden = do
+  fs <- loadFixtures "test/fixtures/v1_transactions.json"
+  let wire = requireFixture "devnet-v1-transaction" fs
+      signers = fromIntegral (BS.index wire 1)
+      msgLen = BS.length wire - 64 * signers
+  signers @?= (1 :: Int)
+  pure (BS.take msgLen wire, unsafeSigFromString (toBase58String (BS.drop msgLen wire)))
+
+------------------------------------------------------------------------------------------------
+-- Layout
+------------------------------------------------------------------------------------------------
+
+layoutTests :: [TestTree]
+layoutTests =
+  [ testCase "all instruction headers precede all payloads" $ do
+      -- Three instructions with distinct account counts (1, 2, 3) and
+      -- distinct data lengths (1, 2, 3). Interleaving each header with its
+      -- own payload -- the legacy and v0 layout, and so the likeliest wrong
+      -- edit -- puts an account index where the second header belongs, and
+      -- this assertion fails.
+      let ix n dat =
+            mkInstruction
+              layoutProgram
+              (AccountMeta payerPk True True : [AccountMeta k False True | k <- take (n - 1) [keyA, keyB]])
+              (RawData (BS.pack dat))
+          instrs = [ix 1 [0xA0], ix 2 [0xB0, 0xB1], ix 3 [0xC0, 0xC1, 0xC2]]
+      bytes <- requireRight (compileV1Message payerPk fixedBlockhash instrs minimalConfig)
+      -- payer, keyA, keyB are accounts 0..2 and the program is account 3.
+      let headers = [3, 1, 1, 0, 3, 2, 2, 0, 3, 3, 3, 0]
+          payloads = [0, 0xA0, 0, 1, 0xB0, 0xB1, 0, 1, 2, 0xC0, 0xC1, 0xC2]
+          expected = BS.pack (headers <> payloads)
+      BS.drop (BS.length bytes - BS.length expected) bytes @?= expected
+  ]
+
+------------------------------------------------------------------------------------------------
+-- Configuration mask
+------------------------------------------------------------------------------------------------
+
+-- | The mask bytes and the config values sit immediately after the
+-- addresses; @addressesEnd@ is where the values begin.
+maskTests :: [TestTree]
+maskTests =
+  [ maskCase "compute-unit and loaded-accounts limits only" minimalConfig 0b1100 8,
+    maskCase "with a priority fee (two bits, eight bytes)" minimalConfig {tcPriorityFee = Just 7} 0b1111 16,
+    maskCase "with a heap request" minimalConfig {tcHeapSize = Just (64 * 1024)} 0b11100 12,
+    maskCase
+      "with every field set"
+      minimalConfig {tcPriorityFee = Just 7, tcHeapSize = Just (64 * 1024)}
+      0b11111
+      20,
+    testCase "values are little-endian and in field order" $ do
+      let full =
+            TransactionConfig
+              { tcPriorityFee = Just 0x1122334455667788,
+                tcComputeUnitLimit = Just 0x0A0B0C0D,
+                tcLoadedAccountsDataSizeLimit = Just 0x01020304,
+                tcHeapSize = Just (64 * 1024)
+              }
+      bytes <- requireRight (compileV1Message payerPk fixedBlockhash [simpleInstruction] full)
+      assertEqual
+        "priority fee u64, then three u32s"
+        ( BS.pack
+            [ 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
+              0x0d, 0x0c, 0x0b, 0x0a,
+              0x04, 0x03, 0x02, 0x01,
+              0x00, 0x00, 0x01, 0x00
+            ]
+        )
+        (BS.take 20 (BS.drop (valuesOffset bytes) bytes))
+  ]
+
+-- | Assert a configuration's mask bytes and the number of value bytes it
+-- appends. The byte count is what distinguishes the two-bit, eight-byte
+-- priority fee from the one-bit, four-byte fields.
+maskCase :: String -> TransactionConfig -> Word -> Int -> TestTree
+maskCase name config mask valueBytes =
+  testCase name $ do
+    bytes <- requireRight (compileV1Message payerPk fixedBlockhash [simpleInstruction] config)
+    assertEqual "mask" (BS.pack [fromIntegral mask, fromIntegral (mask `div` 256), 0, 0]) (BS.take 4 (BS.drop 4 bytes))
+    bare <- requireRight (compileV1Message payerPk fixedBlockhash [simpleInstruction] minimalConfig)
+    -- Every configuration here differs from the baseline only in its value
+    -- bytes, so the length difference is exactly the extra values.
+    BS.length bytes - BS.length bare @?= valueBytes - 8
+
+-- | Where the config values start: the 42-byte fixed header followed by the
+-- address array, whose length byte sits at offset 41.
+valuesOffset :: BS.ByteString -> Int
+valuesOffset bytes = 42 + 32 * fromIntegral (BS.index bytes 41)
+
+------------------------------------------------------------------------------------------------
+-- Signatures
+------------------------------------------------------------------------------------------------
+
+signatureTests :: [TestTree]
+signatureTests =
+  [ testCase "one signature follows the message, unprefixed, and verifies over it" $ do
+      msg <- requireRight (compileV1Message payerPk fixedBlockhash [simpleInstruction] minimalConfig)
+      signed <- requireRight (newV1TransactionIntent payerPk [payerSk] [simpleInstruction] minimalConfig fixedBlockhash)
+      let wire = fromBase64String signed
+      BS.length wire @?= BS.length msg + 64
+      assertEqual "message comes first" msg (BS.take (BS.length msg) wire)
+      assertBool
+        "signature verifies over the message bytes"
+        (dverify payerPk msg (sigAt msg wire 0)),
+      testCase "two signatures occupy their signers' account slots, in message order" $ do
+        -- co-signer is seeded writable so both are writable signers; the
+        -- payer is pinned to account 0 and the other follows.
+        let ix = mkInstruction layoutProgram [AccountMeta payerPk True True, AccountMeta coPk True True] ()
+        msg <- requireRight (compileV1Message payerPk fixedBlockhash [ix] minimalConfig)
+        signed <- requireRight (newV1TransactionIntent payerPk [payerSk, coSk] [ix] minimalConfig fixedBlockhash)
+        let wire = fromBase64String signed
+        BS.length wire @?= BS.length msg + 128
+        assertBool "slot 0 is the fee payer's" (dverify payerPk msg (sigAt msg wire 0))
+        assertBool "slot 1 is the co-signer's" (dverify coPk msg (sigAt msg wire 1))
+        assertBool "slot 0 is not the co-signer's" (not (dverify coPk msg (sigAt msg wire 0)))
+        -- The keys are matched to the message's signers, so the order they
+        -- are supplied in cannot change the bytes.
+        reversed <-
+          requireRight (newV1TransactionIntent payerPk [coSk, payerSk] [ix] minimalConfig fixedBlockhash)
+        reversed @?= signed,
+      testCase "a key for no required signer is refused" $
+        assertRejected
+          "unused signing key"
+          (newV1TransactionIntent payerPk [payerSk, coSk] [simpleInstruction] minimalConfig fixedBlockhash),
+      testCase "a missing signer is refused" $ do
+        let ix = mkInstruction layoutProgram [AccountMeta payerPk True True, AccountMeta coPk True True] ()
+        assertRejected "missing signer" (newV1TransactionIntent payerPk [payerSk] [ix] minimalConfig fixedBlockhash)
+  ]
+
+-- | The @n@th 64-byte signature slot of a signed transaction.
+sigAt :: BS.ByteString -> BS.ByteString -> Int -> SolanaSignature
+sigAt msg wire n =
+  unsafeSigFromString (toBase58String (BS.take 64 (BS.drop (BS.length msg + 64 * n) wire)))
+
+------------------------------------------------------------------------------------------------
+-- Limits, each pinned by a pair of cases straddling it
+------------------------------------------------------------------------------------------------
+
+limitTests :: [TestTree]
+limitTests =
+  [ testCase "64 addresses compile, 65 do not" $ do
+      _ <- requireRight (compileV1Message payerPk fixedBlockhash [wideInstruction 62] minimalConfig)
+      assertRejected "addresses" (compileV1Message payerPk fixedBlockhash [wideInstruction 63] minimalConfig),
+    testCase "64 instructions compile, 65 do not" $ do
+      _ <- requireRight (compileV1Message payerPk fixedBlockhash (replicate 64 simpleInstruction) minimalConfig)
+      assertRejected
+        "instructions"
+        (compileV1Message payerPk fixedBlockhash (replicate 65 simpleInstruction) minimalConfig),
+    testCase "255 accounts in one instruction compile, 256 do not" $ do
+      _ <- requireRight (compileV1Message payerPk fixedBlockhash [repeatedAccounts 255] minimalConfig)
+      assertRejected
+        "accounts in one instruction"
+        (compileV1Message payerPk fixedBlockhash [repeatedAccounts 256] minimalConfig),
+    testCase "12 signatures compile, 13 do not" $ do
+      _ <- requireRight (compileV1Message payerPk fixedBlockhash [manySigners 12] minimalConfig)
+      assertRejected
+        "required signatures"
+        (compileV1Message payerPk fixedBlockhash [manySigners 13] minimalConfig),
+    testCase "a transaction of exactly 4096 bytes compiles, 4097 does not" $ do
+      bytes <- requireRight (compileV1Message payerPk fixedBlockhash [bigDataInstruction atCap] minimalConfig)
+      -- One required signer, so the signed transaction is 64 bytes longer.
+      BS.length bytes + 64 @?= 4096
+      assertRejected
+        "4096"
+        (compileV1Message payerPk fixedBlockhash [bigDataInstruction (atCap + 1)] minimalConfig),
+    testCase "the size cap counts one signature per required signer" $ do
+      -- With 12 signers the signature array is 768 bytes, so a message that
+      -- would fit comfortably on its own must still be refused. A size
+      -- check that ignored the signer count would accept this.
+      let twelve n = mkInstruction layoutProgram (signerMetas 12) (RawData (BS.replicate n 7))
+      big <- pure (compileV1Message payerPk fixedBlockhash [twelve 3000] minimalConfig)
+      assertRejected "4096" big
+      small <- requireRight (compileV1Message payerPk fixedBlockhash [twelve 2000] minimalConfig)
+      assertBool "the accepted one leaves room for 12 signatures" (BS.length small + 12 * 64 <= 4096),
+    testCase "the heap request's bounds are inclusive" $ do
+      _ <- requireRight (compileV1Message payerPk fixedBlockhash [simpleInstruction] (heap 32768))
+      _ <- requireRight (compileV1Message payerPk fixedBlockhash [simpleInstruction] (heap 262144))
+      assertRejected "below the minimum" (compileV1Message payerPk fixedBlockhash [simpleInstruction] (heap 31744))
+      assertRejected "above the maximum" (compileV1Message payerPk fixedBlockhash [simpleInstruction] (heap 263168))
+      assertRejected
+        "multiple of 1024"
+        (compileV1Message payerPk fixedBlockhash [simpleInstruction] (heap 33000))
+  ]
+  where
+    heap n = minimalConfig {tcHeapSize = Just n}
+
+-- | The instruction data length that makes the signed transaction exactly
+-- 4096 bytes: the cap, less one signature, the 42-byte fixed header, three
+-- 32-byte addresses, eight config bytes, one instruction header and the two
+-- account indices.
+atCap :: Int
+atCap = 4096 - 64 - 42 - 3 * 32 - 8 - 4 - 2
+
+------------------------------------------------------------------------------------------------
+-- Refused as unusable
+------------------------------------------------------------------------------------------------
+
+unusableTests :: [TestTree]
+unusableTests =
+  [ testCase "an empty instruction list" $
+      assertRejected "no instructions" (compileV1Message payerPk fixedBlockhash [] minimalConfig),
+    testCase "a config requesting nothing" $
+      assertRejected
+        "compute-unit limit of 0"
+        (compileV1Message payerPk fixedBlockhash [simpleInstruction] emptyTransactionConfig),
+    testCase "an absent compute-unit limit" $
+      assertRejected
+        "compute-unit limit of 0"
+        ( compileV1Message
+            payerPk
+            fixedBlockhash
+            [simpleInstruction]
+            minimalConfig {tcComputeUnitLimit = Nothing}
+        ),
+    testCase "an explicitly zero compute-unit limit" $
+      assertRejected
+        "compute-unit limit of 0"
+        ( compileV1Message
+            payerPk
+            fixedBlockhash
+            [simpleInstruction]
+            minimalConfig {tcComputeUnitLimit = Just 0}
+        ),
+    testCase "an absent loaded-accounts data size limit" $
+      assertRejected
+        "loaded-accounts data size limit of 0"
+        ( compileV1Message
+            payerPk
+            fixedBlockhash
+            [simpleInstruction]
+            minimalConfig {tcLoadedAccountsDataSizeLimit = Nothing}
+        ),
+    testCase "an explicitly zero loaded-accounts data size limit" $
+      assertRejected
+        "loaded-accounts data size limit of 0"
+        ( compileV1Message
+            payerPk
+            fixedBlockhash
+            [simpleInstruction]
+            minimalConfig {tcLoadedAccountsDataSizeLimit = Just 0}
+        ),
+    testCase "the fee payer named as a program id" $
+      assertRejected
+        "cannot be a program id"
+        ( compileV1Message
+            layoutProgram
+            fixedBlockhash
+            [mkInstruction layoutProgram [AccountMeta payerPk False True] ()]
+            minimalConfig
+        )
+  ]
+
+------------------------------------------------------------------------------------------------
+-- Fixtures and helpers
+------------------------------------------------------------------------------------------------
+
+-- | The smallest configuration the builder accepts: both effectively
+-- required fields set, nothing else.
+minimalConfig :: TransactionConfig
+minimalConfig =
+  emptyTransactionConfig
+    { tcComputeUnitLimit = Just 200000,
+      tcLoadedAccountsDataSizeLimit = Just 131072
+    }
+
+-- | An instruction touching @n@ distinct writable accounts, so the compiled
+-- message carries @n + 2@ addresses (the payer and the program).
+wideInstruction :: Int -> Instruction
+wideInstruction n =
+  mkInstruction
+    layoutProgram
+    (AccountMeta payerPk True True : [AccountMeta (numberedKey i) False True | i <- [1 .. n]])
+    ()
+
+-- | An instruction naming the same account @n@ times, so its account-index
+-- count can exceed the message's address count.
+repeatedAccounts :: Int -> Instruction
+repeatedAccounts n =
+  mkInstruction layoutProgram (AccountMeta payerPk True True : replicate (n - 1) (AccountMeta keyA False True)) ()
+
+-- | An instruction requiring @n@ signatures.
+manySigners :: Int -> Instruction
+manySigners n = mkInstruction layoutProgram (signerMetas n) ()
+
+signerMetas :: Int -> [AccountMeta]
+signerMetas n = AccountMeta payerPk True True : [AccountMeta (numberedKey i) True True | i <- [1 .. n - 1]]
+
+-- | An instruction carrying @n@ data bytes and two account indices.
+bigDataInstruction :: Int -> Instruction
+bigDataInstruction n =
+  mkInstruction
+    layoutProgram
+    [AccountMeta payerPk True True, AccountMeta keyA False True]
+    (RawData (BS.replicate n 7))
+
+simpleInstruction :: Instruction
+simpleInstruction = SP.transfer payerPk keyA 1
+
+payerKeys :: (SolanaPublicKey, SolanaPrivateKey)
+payerKeys = seededKeypair 1
+
+coSignerKeys :: (SolanaPublicKey, SolanaPrivateKey)
+coSignerKeys = seededKeypair 2
+
+payerPk :: SolanaPublicKey
+payerPk = fst payerKeys
+
+payerSk :: SolanaPrivateKey
+payerSk = snd payerKeys
+
+coPk :: SolanaPublicKey
+coPk = fst coSignerKeys
+
+coSk :: SolanaPrivateKey
+coSk = snd coSignerKeys
+
+seededKeypair :: Word8 -> (SolanaPublicKey, SolanaPrivateKey)
+seededKeypair seed =
+  case createSolanaKeypairFromSeed (BS.replicate 32 seed) of
+    Just kp -> kp
+    Nothing -> error ("failed to derive keypair from seed " <> show seed)
+
+-- | Two ordinary accounts, chosen so that their raw bytes sort in this
+-- order (the layout test depends on their account indices).
+keyA, keyB :: SolanaPublicKey
+keyA = unsafeSolanaPublicKeyRaw (5 : replicate 31 0)
+keyB = unsafeSolanaPublicKeyRaw (6 : replicate 31 0)
+
+-- | A program id sorting after 'keyA' and 'keyB', so it is the last
+-- address.
+layoutProgram :: SolanaPublicKey
+layoutProgram = unsafeSolanaPublicKeyRaw (9 : replicate 31 0)
+
+fixedBlockhash :: BlockHash
+fixedBlockhash = BlockHash (BS.replicate 32 9)
+
+-- | A distinct 32-byte key per number, for large key sets.
+numberedKey :: Int -> SolanaPublicKey
+numberedKey b = unsafeSolanaPublicKeyRaw (3 : fromIntegral (b `div` 256) : fromIntegral (b `mod` 256) : replicate 29 0)
+
+requireRight :: Either CompileException a -> IO a
+requireRight = either (assertFailure . show) pure
+
+-- | Assert a compile failed, and that its message names the reason -- so a
+-- rejection for an unrelated reason cannot pass for the right one.
+assertRejected :: String -> Either CompileException a -> Assertion
+assertRejected expected = \case
+  Right _ -> assertFailure ("expected rejection mentioning " <> show expected)
+  Left err ->
+    let msg = compileExceptionMessage err
+     in assertBool ("expected " <> show expected <> " in: " <> msg) (expected `isInfixOf` msg)
+
+compileExceptionMessage :: CompileException -> String
+compileExceptionMessage = \case
+  MissingIndex m -> m
+  LimitExceeded m -> m
+  InvalidMessage m -> m
diff --git a/test/Test/RPC/Parsers.hs b/test/Test/RPC/Parsers.hs
--- a/test/Test/RPC/Parsers.hs
+++ b/test/Test/RPC/Parsers.hs
@@ -5,8 +5,10 @@
 
 -- | Golden tests for the RPC response parsers.
 --
--- Every fixture here is a real response captured from a local validator by
--- @tools/rpc-record/record.py@ -- not a hand-written sample -- so these tests
+-- Every fixture here is a real response captured from a node -- not a
+-- hand-written sample: the local validator via
+-- @tools/rpc-record/record.py@, and devnet for the v1 responses the pinned
+-- validator cannot produce -- so these tests
 -- pin the @FromJSON@ instances against JSON a node actually produces,
 -- including the fields it omits. That is the one thing the Rust-generated
 -- byte vectors cannot cover, since the RPC layer's input is JSON rather than
@@ -17,7 +19,7 @@
 -- parser wired to the wrong key.
 module Test.RPC.Parsers (tests) where
 
-import Data.Aeson (FromJSON, Value)
+import Data.Aeson (FromJSON, Key, Value, toJSON, withObject, (.:), (.:?))
 import Data.Aeson.Types (parseEither, parseJSON)
 import Data.Map.Strict qualified as M
 import Data.Maybe (isJust)
@@ -31,7 +33,10 @@
     lamports,
   )
 import Network.Solana.Core.Block (BlockHash, BlockHeight)
+import Network.Solana.Core.Transaction (Transaction (..))
+import Network.Solana.Core.Compact (unCompact)
 import Network.Solana.Core.Crypto (SolanaPublicKey)
+import Network.Solana.Core.Instruction (CompiledInstruction (..))
 import Network.Solana.RPC.HTTP.Account hiding (lamports)
 import Network.Solana.RPC.HTTP.Account qualified as RpcAccount
 import Network.Solana.RPC.HTTP.Block
@@ -75,8 +80,80 @@
       testGroup "tokenomics" tokenomicsTests,
       testGroup "accounts" accountTests,
       testGroup "transactions" transactionTests,
-      testGroup "SPL token" tokenTests
+      testGroup "SPL token" tokenTests,
+      testGroup "v1 transactions (SIMD-0385)" v1Tests
     ]
+
+-- | Responses carrying v1 transactions, recorded from devnet (which runs
+-- them) rather than from the local validator, since the pinned
+-- @solana-test-validator@ predates the format. A v1 message reports its
+-- resource requests in a @transactionConfig@ object and carries no
+-- @addressTableLookups@; these pin that neither shape breaks the parsers.
+v1Tests :: [TestTree]
+v1Tests =
+  [ testCase "getTransaction decodes a v1 transaction" $ withV1Result @(Maybe TransactionResult) "getTransaction-v1" $ \case
+      Nothing -> assertFailure "expected a transaction"
+      Just result -> do
+        slotTx result @?= 512843755
+        map show (signatures (transactionTx result))
+          @?= ["Mq9Qb7wwtfyRtrtGFF4YjjCaUAhaG9iddBu7DquQ84hKe4D4R7ixgkKjz3DxbvS7UpC7Q2SmSK4htWcwu2wjcGZ"]
+        keys <- messageField @[SolanaPublicKey] "accountKeys" (transactionTx result)
+        length keys @?= 4
+        blockhash <- messageField @BlockHash "recentBlockhash" (transactionTx result)
+        show blockhash @?= "4iSS7zQNeY8BTSWZ9VRMBo8B17AyijyLDD8C2EycoW19"
+        -- Reach into the v1-specific part: the compiled instruction. These
+        -- are the same values Test.Core.MessageV1 transcribes by hand from
+        -- the wire bytes, so agreement here cross-checks that transcription
+        -- against the node's own JSON rendering of the same transaction.
+        ixs <- messageField @[CompiledInstruction] "instructions" (transactionTx result)
+        case ixs of
+          [ix] -> do
+            ciProgramIdIndex ix @?= 2
+            unCompact (ciAccounts ix) @?= [0, 3, 1]
+            length (unCompact (ciData ix)) @?= 90
+          other -> assertFailure ("expected one instruction, got " <> show (length other))
+        -- Pin the documented loss: the recorded response does carry a
+        -- transactionConfig object, and CompiledMessage drops it.
+        config <- optionalMessageField @Value "transactionConfig" (transactionTx result)
+        assertEqual "transactionConfig is not surfaced" Nothing config,
+    testCase "getBlock decodes a block mixing legacy, v0 and v1 transactions" $
+      withV1Result @(Maybe BlockInfo) "getBlock-v1-trimmed" $ \case
+        Nothing -> assertFailure "expected a block"
+        Just block -> do
+          -- The fixture keeps two v1, two legacy and one v0 transaction, in
+          -- that recorded order. Asserting each one's account-key count
+          -- distinguishes the entries from one another, so a mis-trimmed
+          -- fixture or a parser that silently defaulted a message cannot
+          -- pass on the count alone.
+          counts <-
+            mapM
+              (fmap length . messageField @[SolanaPublicKey] "accountKeys" . transaction)
+              (transactionsBI block)
+          counts @?= [4, 4, 10, 19, 10]
+  ]
+
+-- | As 'withResult', against the devnet-recorded v1 fixtures.
+withV1Result :: forall a. (FromJSON a) => String -> (a -> Assertion) -> Assertion
+withV1Result name check = do
+  fs <- loadRpcFixtures "test/fixtures/v1_rpc_responses.json"
+  case parseEither (parseJSON @a) (requireRpcResult name fs) of
+    Left err -> assertFailure ("failed to parse recorded " <> name <> " response: " <> err)
+    Right parsed -> check parsed
+
+-- | Read one field of a parsed transaction's message. 'CompiledMessage' is
+-- abstract, so its contents are only reachable through its 'ToJSON'
+-- rendering -- which is also all a caller of the RPC bindings gets.
+messageField :: forall a. (FromJSON a) => Key -> Transaction -> IO a
+messageField name tx =
+  either (assertFailure . ((show name <> ": ") <>)) pure $
+    parseEither (withObject "message" (.: name)) (toJSON (message tx))
+
+-- | As 'messageField', but 'Nothing' when the rendered message has no such
+-- field -- for asserting that something is absent.
+optionalMessageField :: forall a. (FromJSON a) => Key -> Transaction -> IO (Maybe a)
+optionalMessageField name tx =
+  either (assertFailure . ((show name <> ": ") <>)) pure $
+    parseEither (withObject "message" (.:? name)) (toJSON (message tx))
 
 clusterTests :: [TestTree]
 clusterTests =
diff --git a/test/fixtures/v1_rpc_responses.json b/test/fixtures/v1_rpc_responses.json
new file mode 100644
--- /dev/null
+++ b/test/fixtures/v1_rpc_responses.json
@@ -0,0 +1,952 @@
+[
+ {
+  "method": "getTransaction",
+  "name": "getTransaction-v1",
+  "response": {
+   "id": 1,
+   "jsonrpc": "2.0",
+   "result": {
+    "blockTime": 1792423794,
+    "meta": {
+     "computeUnitsConsumed": 182,
+     "costUnits": 1532,
+     "err": null,
+     "fee": 5000,
+     "innerInstructions": [],
+     "loadedAddresses": {
+      "readonly": [],
+      "writable": []
+     },
+     "logMessages": [
+      "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM invoke [1]",
+      "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM consumed 182 of 324 compute units",
+      "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM success"
+     ],
+     "postBalances": [
+      3539480000,
+      11054080,
+      833120,
+      1169280
+     ],
+     "postTokenBalances": [],
+     "preBalances": [
+      3539485000,
+      11054080,
+      833120,
+      1169280
+     ],
+     "preTokenBalances": [],
+     "rewards": [],
+     "status": {
+      "Ok": null
+     }
+    },
+    "slot": 512843755,
+    "transaction": {
+     "message": {
+      "accountKeys": [
+       "4QVtKaZkDhEwKszzJWa7LJPZBFkkcgUVRG4xE3fkWNGt",
+       "55gx5ra96qkYXXMGShkVjwQz1k4j9bS26HhdksFa9buL",
+       "MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM",
+       "SysvarC1ock11111111111111111111111111111111"
+      ],
+      "header": {
+       "numReadonlySignedAccounts": 0,
+       "numReadonlyUnsignedAccounts": 2,
+       "numRequiredSignatures": 1
+      },
+      "instructions": [
+       {
+        "accounts": [
+         0,
+         3,
+         1
+        ],
+        "data": "2isQdwGHZhqBC7JtD5qgwY3fpHY2d1ciRmLgt9KN5x75VY2UxdpWv67RMmcvfJCqk5SAeAV4zDVqkkrgrJga5gREAVsRKJUhgqq5ZxqV2rNZhRkuobuQtQubPy9",
+        "programIdIndex": 2,
+        "stackHeight": 1
+       }
+      ],
+      "recentBlockhash": "4iSS7zQNeY8BTSWZ9VRMBo8B17AyijyLDD8C2EycoW19",
+      "transactionConfig": {
+       "computeUnitLimit": 324,
+       "heapSize": null,
+       "loadedAccountsDataSizeLimit": 43008,
+       "priorityFee": 0
+      }
+     },
+     "signatures": [
+      "Mq9Qb7wwtfyRtrtGFF4YjjCaUAhaG9iddBu7DquQ84hKe4D4R7ixgkKjz3DxbvS7UpC7Q2SmSK4htWcwu2wjcGZ"
+     ]
+    },
+    "transactionIndex": 0,
+    "version": 1
+   }
+  }
+ },
+ {
+  "method": "getBlock",
+  "name": "getBlock-v1-trimmed",
+  "response": {
+   "id": 1,
+   "jsonrpc": "2.0",
+   "result": {
+    "blockHeight": 500055305,
+    "blockTime": 1792423794,
+    "blockhash": "DmA3KRYyXZVKsb3QneRspksx4d63SPx9JWdRPh5tTCTA",
+    "parentSlot": 512843754,
+    "previousBlockhash": "G357hNHZs3tep1pYUXgvuQt1SAspAu3e4wTLVRU9MuLN",
+    "transactions": [
+     {
+      "meta": {
+       "computeUnitsConsumed": 182,
+       "costUnits": 1532,
+       "err": null,
+       "fee": 5000,
+       "innerInstructions": [],
+       "loadedAddresses": {
+        "readonly": [],
+        "writable": []
+       },
+       "logMessages": [
+        "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM invoke [1]",
+        "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM consumed 182 of 324 compute units",
+        "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM success"
+       ],
+       "postBalances": [
+        3539480000,
+        11054080,
+        833120,
+        1169280
+       ],
+       "postTokenBalances": [],
+       "preBalances": [
+        3539485000,
+        11054080,
+        833120,
+        1169280
+       ],
+       "preTokenBalances": [],
+       "rewards": null,
+       "status": {
+        "Ok": null
+       }
+      },
+      "transaction": {
+       "message": {
+        "accountKeys": [
+         "4QVtKaZkDhEwKszzJWa7LJPZBFkkcgUVRG4xE3fkWNGt",
+         "55gx5ra96qkYXXMGShkVjwQz1k4j9bS26HhdksFa9buL",
+         "MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM",
+         "SysvarC1ock11111111111111111111111111111111"
+        ],
+        "header": {
+         "numReadonlySignedAccounts": 0,
+         "numReadonlyUnsignedAccounts": 2,
+         "numRequiredSignatures": 1
+        },
+        "instructions": [
+         {
+          "accounts": [
+           0,
+           3,
+           1
+          ],
+          "data": "2isQdwGHZhqBC7JtD5qgwY3fpHY2d1ciRmLgt9KN5x75VY2UxdpWv67RMmcvfJCqk5SAeAV4zDVqkkrgrJga5gREAVsRKJUhgqq5ZxqV2rNZhRkuobuQtQubPy9",
+          "programIdIndex": 2,
+          "stackHeight": 1
+         }
+        ],
+        "recentBlockhash": "4iSS7zQNeY8BTSWZ9VRMBo8B17AyijyLDD8C2EycoW19",
+        "transactionConfig": {
+         "computeUnitLimit": 324,
+         "heapSize": null,
+         "loadedAccountsDataSizeLimit": 43008,
+         "priorityFee": 0
+        }
+       },
+       "signatures": [
+        "Mq9Qb7wwtfyRtrtGFF4YjjCaUAhaG9iddBu7DquQ84hKe4D4R7ixgkKjz3DxbvS7UpC7Q2SmSK4htWcwu2wjcGZ"
+       ]
+      },
+      "version": 1
+     },
+     {
+      "meta": {
+       "computeUnitsConsumed": 182,
+       "costUnits": 1532,
+       "err": null,
+       "fee": 5000,
+       "innerInstructions": [],
+       "loadedAddresses": {
+        "readonly": [],
+        "writable": []
+       },
+       "logMessages": [
+        "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM invoke [1]",
+        "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM consumed 182 of 324 compute units",
+        "Program MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM success"
+       ],
+       "postBalances": [
+        3539475000,
+        11054080,
+        833120,
+        1169280
+       ],
+       "postTokenBalances": [],
+       "preBalances": [
+        3539480000,
+        11054080,
+        833120,
+        1169280
+       ],
+       "preTokenBalances": [],
+       "rewards": null,
+       "status": {
+        "Ok": null
+       }
+      },
+      "transaction": {
+       "message": {
+        "accountKeys": [
+         "4QVtKaZkDhEwKszzJWa7LJPZBFkkcgUVRG4xE3fkWNGt",
+         "55gx5ra96qkYXXMGShkVjwQz1k4j9bS26HhdksFa9buL",
+         "MktiyFj9mVdLQgj45AXvJdoaHvF9PkuU1UmA2uwPJWM",
+         "SysvarC1ock11111111111111111111111111111111"
+        ],
+        "header": {
+         "numReadonlySignedAccounts": 0,
+         "numReadonlyUnsignedAccounts": 2,
+         "numRequiredSignatures": 1
+        },
+        "instructions": [
+         {
+          "accounts": [
+           0,
+           3,
+           1
+          ],
+          "data": "2ctyYDVbUY5FNMbayMXaPmLmKVPMDm4zcowcVkjfi1EDA8eeMr3gjJzYPP4fYrwKgyGDfUfjyze6sp8bfm7jGzqUv1hGWbzGr68X4UcbM8CZRQpmw58SmMqdTfV",
+          "programIdIndex": 2,
+          "stackHeight": 1
+         }
+        ],
+        "recentBlockhash": "4iSS7zQNeY8BTSWZ9VRMBo8B17AyijyLDD8C2EycoW19",
+        "transactionConfig": {
+         "computeUnitLimit": 324,
+         "heapSize": null,
+         "loadedAccountsDataSizeLimit": 43008,
+         "priorityFee": 0
+        }
+       },
+       "signatures": [
+        "4WqBxBMEJ4HU29xfBB9Mx2ckZBo54dhD7cDPMaFTMU3ZRQtdK4X5AikT57ZTeqSdtwFkHxro31yfBWCPD7ANyUh2"
+       ]
+      },
+      "version": 1
+     },
+     {
+      "meta": {
+       "computeUnitsConsumed": 4723,
+       "costUnits": 7421,
+       "err": null,
+       "fee": 10000,
+       "innerInstructions": [],
+       "loadedAddresses": {
+        "readonly": [],
+        "writable": []
+       },
+       "logMessages": [
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
+        "Program log: CreateIdempotent",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 4618 of 400000 compute units",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 105 of 395382 compute units",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success"
+       ],
+       "postBalances": [
+        7946257653,
+        0,
+        2039280,
+        2039280,
+        1,
+        1009200,
+        20381277856,
+        454525905289,
+        5938070540,
+        0
+       ],
+       "postTokenBalances": [
+        {
+         "accountIndex": 2,
+         "mint": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
+         "owner": "Cf9abfrZbkkcKthpkKqwmA8H3LiGtGZ2ZL8NsfQzYLQP",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "115055020000",
+          "decimals": 6,
+          "uiAmount": 115055.02,
+          "uiAmountString": "115055.02"
+         }
+        },
+        {
+         "accountIndex": 3,
+         "mint": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
+         "owner": "D7d6ZP2KcmHzhEh4nGrpe7zMKFjXP8wtvceecGB3fKVp",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "4114000000",
+          "decimals": 6,
+          "uiAmount": 4114.0,
+          "uiAmountString": "4114"
+         }
+        }
+       ],
+       "preBalances": [
+        7946267653,
+        0,
+        2039280,
+        2039280,
+        1,
+        1009200,
+        20381277856,
+        454525905289,
+        5938070540,
+        0
+       ],
+       "preTokenBalances": [
+        {
+         "accountIndex": 2,
+         "mint": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
+         "owner": "Cf9abfrZbkkcKthpkKqwmA8H3LiGtGZ2ZL8NsfQzYLQP",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "115054020000",
+          "decimals": 6,
+          "uiAmount": 115054.02,
+          "uiAmountString": "115054.02"
+         }
+        },
+        {
+         "accountIndex": 3,
+         "mint": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
+         "owner": "D7d6ZP2KcmHzhEh4nGrpe7zMKFjXP8wtvceecGB3fKVp",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "4115000000",
+          "decimals": 6,
+          "uiAmount": 4115.0,
+          "uiAmountString": "4115"
+         }
+        }
+       ],
+       "rewards": null,
+       "status": {
+        "Ok": null
+       }
+      },
+      "transaction": {
+       "message": {
+        "accountKeys": [
+         "DmxEUYwgTX2qYnsf29LXBBScxYkKp1yn1Doodqf95SP7",
+         "D7d6ZP2KcmHzhEh4nGrpe7zMKFjXP8wtvceecGB3fKVp",
+         "5iv62nJJJHsV7pgJcA3sf9kp98uWaQcjyKtxFZ5dEbcW",
+         "GXGc5RJU7W4j8FrH38vfGbryht5av3zeiZCmhDN7yRPU",
+         "11111111111111111111111111111111",
+         "SysvarRent111111111111111111111111111111111",
+         "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
+         "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
+         "Cf9abfrZbkkcKthpkKqwmA8H3LiGtGZ2ZL8NsfQzYLQP"
+        ],
+        "header": {
+         "numReadonlySignedAccounts": 0,
+         "numReadonlyUnsignedAccounts": 6,
+         "numRequiredSignatures": 2
+        },
+        "instructions": [
+         {
+          "accounts": [
+           0,
+           2,
+           9,
+           7,
+           4,
+           6,
+           5
+          ],
+          "data": "2",
+          "programIdIndex": 8,
+          "stackHeight": 1
+         },
+         {
+          "accounts": [
+           3,
+           7,
+           2,
+           1
+          ],
+          "data": "gvPShZQhKrzGM",
+          "programIdIndex": 6,
+          "stackHeight": 1
+         }
+        ],
+        "recentBlockhash": "6CqcYVxH594qe8fuXWJbLtbihbfiZZvR7LgwbeGGYWf1"
+       },
+       "signatures": [
+        "3pEGq7f179YAoezTopf5eDW6g2eArox5eQFee5Gn86JvqCdUvoUTfitckqU5nDuYut6cKkGPqKahBSxKaDsB7w1W",
+        "Y9k8CevfXqQGkDPorJ13wr5HYrkUMugo8Lk7QgkBZqEaTCuM8YMUwgH3XKbeenUNzq7qti6RTfAvQ95dN8XYP3Y"
+       ]
+      },
+      "version": "legacy"
+     },
+     {
+      "meta": {
+       "computeUnitsConsumed": 83720,
+       "costUnits": 87635,
+       "err": null,
+       "fee": 5000,
+       "innerInstructions": [
+        {
+         "index": 3,
+         "instructions": [
+          {
+           "accounts": [
+            1,
+            6,
+            0
+           ],
+           "data": "3dStPEjaYDXV",
+           "programIdIndex": 12,
+           "stackHeight": 2
+          },
+          {
+           "accounts": [
+            1,
+            7,
+            0
+           ],
+           "data": "3Rk7VTcM4FDy",
+           "programIdIndex": 12,
+           "stackHeight": 2
+          },
+          {
+           "accounts": [
+            8,
+            2,
+            17
+           ],
+           "data": "3rsvjYLBF3B5",
+           "programIdIndex": 12,
+           "stackHeight": 2
+          },
+          {
+           "accounts": [
+            4,
+            3,
+            16
+           ],
+           "data": "6pA1XnvgKh8j",
+           "programIdIndex": 12,
+           "stackHeight": 2
+          },
+          {
+           "accounts": [
+            18
+           ],
+           "data": "5PNV38RXxo7nDN1FxWX2okYSSYqwNQvBzFVDE7E7mJrgW3ShtoatTrZNqVjc22Zkevpkh3i7Wihh1JHuJTGN2211EijwSVekwENhxWS5Tbt8bswfQB7ExHPFGLyi4gWCU5E2vcMzUKR8r2qLSr53cRLNvgzRayLE6yZjtcSfAmbw1SwufEav2aaa7qfWtVQqTvC4qeevtfDv9UrQkTy9QXpPWitxEQqRPHnFXapyGkrGkeFrbMfYHQBPcg6PmgqSD8NMyYrwfr1pD5diBWy1gAhm92FZFmvSRLLELAj5pE8KMRByatxkpG8ipxyZgjihoMUcz95",
+           "programIdIndex": 14,
+           "stackHeight": 2
+          }
+         ]
+        }
+       ],
+       "loadedAddresses": {
+        "readonly": [],
+        "writable": []
+       },
+       "logMessages": [
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
+        "Program log: CreateIdempotent",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 4338 of 800000 compute units",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
+        "Program log: CreateIdempotent",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 7338 of 795662 compute units",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
+        "Program log: CreateIdempotent",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 7337 of 788324 compute units",
+        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
+        "Program XuXkWAz3xRktfEjAfFDdkFksYBqFzet8JPkQxZMoRfi invoke [1]",
+        "Program log: Instruction: Buy",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 76 of 734476 compute units",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 76 of 732583 compute units",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 76 of 730762 compute units",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 120 of 728966 compute units",
+        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
+        "Program XuXkWAz3xRktfEjAfFDdkFksYBqFzet8JPkQxZMoRfi invoke [2]",
+        "Program XuXkWAz3xRktfEjAfFDdkFksYBqFzet8JPkQxZMoRfi consumed 424 of 721485 compute units",
+        "Program XuXkWAz3xRktfEjAfFDdkFksYBqFzet8JPkQxZMoRfi success",
+        "Program XuXkWAz3xRktfEjAfFDdkFksYBqFzet8JPkQxZMoRfi consumed 64707 of 780987 compute units",
+        "Program XuXkWAz3xRktfEjAfFDdkFksYBqFzet8JPkQxZMoRfi success"
+       ],
+       "postBalances": [
+        3720280,
+        1488440,
+        1488440,
+        1488440,
+        1066800,
+        4231640,
+        1488440,
+        1488440,
+        1488440,
+        5938070540,
+        1066800,
+        1,
+        20381277856,
+        1066800,
+        11141440,
+        1767840,
+        0,
+        0,
+        0
+       ],
+       "postTokenBalances": [
+        {
+         "accountIndex": 1,
+         "mint": "GwMYubfhtHzP2vNcoDVRbt64T5ruHRpq5w2wCXGMNTB7",
+         "owner": "AAHy9ocUHXcdg7xpUE8DTvJCLaHqgmgJYeRVHomiKMFD",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "8918007091",
+          "decimals": 6,
+          "uiAmount": 8918.007091,
+          "uiAmountString": "8918.007091"
+         }
+        },
+        {
+         "accountIndex": 2,
+         "mint": "BYRX2nT98QKcKvPf6gpHtBEcF9DBHrmY3FiTQwWVEaNj",
+         "owner": "AAHy9ocUHXcdg7xpUE8DTvJCLaHqgmgJYeRVHomiKMFD",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "18985407",
+          "decimals": 6,
+          "uiAmount": 18.985407,
+          "uiAmountString": "18.985407"
+         }
+        },
+        {
+         "accountIndex": 3,
+         "mint": "FTWhjeTdTA4k4Ak89saHKTwnizDaMZfQNJQdMJgYNC4K",
+         "owner": "AAHy9ocUHXcdg7xpUE8DTvJCLaHqgmgJYeRVHomiKMFD",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "18985407",
+          "decimals": 6,
+          "uiAmount": 18.985407,
+          "uiAmountString": "18.985407"
+         }
+        },
+        {
+         "accountIndex": 6,
+         "mint": "GwMYubfhtHzP2vNcoDVRbt64T5ruHRpq5w2wCXGMNTB7",
+         "owner": "EQ5bGv95Ptt4A8nJMJv1SCuma5dAcrAbw9E8eoamrLPp",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "5601370072",
+          "decimals": 6,
+          "uiAmount": 5601.370072,
+          "uiAmountString": "5601.370072"
+         }
+        },
+        {
+         "accountIndex": 7,
+         "mint": "GwMYubfhtHzP2vNcoDVRbt64T5ruHRpq5w2wCXGMNTB7",
+         "owner": "8u5r3QSngjMoX7XbBwuRbwTkrwiiSdoEZ3o4JxRp5Uyt",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "3920386062232",
+          "decimals": 6,
+          "uiAmount": 3920386.062232,
+          "uiAmountString": "3920386.062232"
+         }
+        },
+        {
+         "accountIndex": 8,
+         "mint": "BYRX2nT98QKcKvPf6gpHtBEcF9DBHrmY3FiTQwWVEaNj",
+         "owner": "EQ5bGv95Ptt4A8nJMJv1SCuma5dAcrAbw9E8eoamrLPp",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "345584742",
+          "decimals": 6,
+          "uiAmount": 345.584742,
+          "uiAmountString": "345.584742"
+         }
+        }
+       ],
+       "preBalances": [
+        3725280,
+        1488440,
+        1488440,
+        1488440,
+        1066800,
+        4231640,
+        1488440,
+        1488440,
+        1488440,
+        5938070540,
+        1066800,
+        1,
+        20381277856,
+        1066800,
+        11141440,
+        1767840,
+        0,
+        0,
+        0
+       ],
+       "preTokenBalances": [
+        {
+         "accountIndex": 1,
+         "mint": "GwMYubfhtHzP2vNcoDVRbt64T5ruHRpq5w2wCXGMNTB7",
+         "owner": "AAHy9ocUHXcdg7xpUE8DTvJCLaHqgmgJYeRVHomiKMFD",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "8964135691",
+          "decimals": 6,
+          "uiAmount": 8964.135691,
+          "uiAmountString": "8964.135691"
+         }
+        },
+        {
+         "accountIndex": 2,
+         "mint": "BYRX2nT98QKcKvPf6gpHtBEcF9DBHrmY3FiTQwWVEaNj",
+         "owner": "AAHy9ocUHXcdg7xpUE8DTvJCLaHqgmgJYeRVHomiKMFD",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "13498592",
+          "decimals": 6,
+          "uiAmount": 13.498592,
+          "uiAmountString": "13.498592"
+         }
+        },
+        {
+         "accountIndex": 3,
+         "mint": "FTWhjeTdTA4k4Ak89saHKTwnizDaMZfQNJQdMJgYNC4K",
+         "owner": "AAHy9ocUHXcdg7xpUE8DTvJCLaHqgmgJYeRVHomiKMFD",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "13498592",
+          "decimals": 6,
+          "uiAmount": 13.498592,
+          "uiAmountString": "13.498592"
+         }
+        },
+        {
+         "accountIndex": 6,
+         "mint": "GwMYubfhtHzP2vNcoDVRbt64T5ruHRpq5w2wCXGMNTB7",
+         "owner": "EQ5bGv95Ptt4A8nJMJv1SCuma5dAcrAbw9E8eoamrLPp",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "5555467593",
+          "decimals": 6,
+          "uiAmount": 5555.467593,
+          "uiAmountString": "5555.467593"
+         }
+        },
+        {
+         "accountIndex": 7,
+         "mint": "GwMYubfhtHzP2vNcoDVRbt64T5ruHRpq5w2wCXGMNTB7",
+         "owner": "8u5r3QSngjMoX7XbBwuRbwTkrwiiSdoEZ3o4JxRp5Uyt",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "3920385836111",
+          "decimals": 6,
+          "uiAmount": 3920385.836111,
+          "uiAmountString": "3920385.836111"
+         }
+        },
+        {
+         "accountIndex": 8,
+         "mint": "BYRX2nT98QKcKvPf6gpHtBEcF9DBHrmY3FiTQwWVEaNj",
+         "owner": "EQ5bGv95Ptt4A8nJMJv1SCuma5dAcrAbw9E8eoamrLPp",
+         "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "uiTokenAmount": {
+          "amount": "351071557",
+          "decimals": 6,
+          "uiAmount": 351.071557,
+          "uiAmountString": "351.071557"
+         }
+        }
+       ],
+       "rewards": null,
+       "status": {
+        "Ok": null
+       }
+      },
+      "transaction": {
+       "message": {
+        "accountKeys": [
+         "AAHy9ocUHXcdg7xpUE8DTvJCLaHqgmgJYeRVHomiKMFD",
+         "F5hYRkGysQaBgLQt28pQD7Qfe1iayQcSd67mSjw6wtVp",
+         "J5BSHuWBq8VueexXADTJRFEpxqw7wLbw7goYkcTcBAyc",
+         "7sAVWnpuqRSk6qSVuDgG2P8Ls7ELHkt3ioSwCWGfnmWa",
+         "FTWhjeTdTA4k4Ak89saHKTwnizDaMZfQNJQdMJgYNC4K",
+         "9bcaAahcx6VV6mrs2ceT5DUtWVCKE1T4sHyXoXFyuum9",
+         "HmmT5ZGx4nvUpSRsQramrqZYAwx2z7r5unt5V1krwa48",
+         "8u5r3QSngjMoX7XbBwuRbwTkrwiiSdoEZ3o4JxRp5Uyt",
+         "EDuLkMZRSYg5JfdMUjiaN7nQiTgb3KYBAfCZB5Xy8XAX",
+         "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
+         "GwMYubfhtHzP2vNcoDVRbt64T5ruHRpq5w2wCXGMNTB7",
+         "11111111111111111111111111111111",
+         "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+         "BYRX2nT98QKcKvPf6gpHtBEcF9DBHrmY3FiTQwWVEaNj",
+         "XuXkWAz3xRktfEjAfFDdkFksYBqFzet8JPkQxZMoRfi",
+         "4J2Vd4GTJAvpg9NWP4BdMoEbaeThp1Tw7KFeMqmSMNPT",
+         "9ee77R4PK6qkvrNj4WwKDVQd9t3YFMWCBenaoHH2iEdW",
+         "EQ5bGv95Ptt4A8nJMJv1SCuma5dAcrAbw9E8eoamrLPp",
+         "HgmY1JtUBoLymMdSHEUUz6ktsDMk7W9SQR76rDGgfwrZ"
+        ],
+        "addressTableLookups": [],
+        "header": {
+         "numReadonlySignedAccounts": 0,
+         "numReadonlyUnsignedAccounts": 10,
+         "numRequiredSignatures": 1
+        },
+        "instructions": [
+         {
+          "accounts": [
+           0,
+           1,
+           0,
+           10,
+           11,
+           12
+          ],
+          "data": "2",
+          "programIdIndex": 9,
+          "stackHeight": 1
+         },
+         {
+          "accounts": [
+           0,
+           2,
+           0,
+           13,
+           11,
+           12
+          ],
+          "data": "2",
+          "programIdIndex": 9,
+          "stackHeight": 1
+         },
+         {
+          "accounts": [
+           0,
+           3,
+           0,
+           4,
+           11,
+           12
+          ],
+          "data": "2",
+          "programIdIndex": 9,
+          "stackHeight": 1
+         },
+         {
+          "accounts": [
+           0,
+           5,
+           15,
+           10,
+           13,
+           4,
+           16,
+           17,
+           6,
+           7,
+           1,
+           2,
+           3,
+           12,
+           8,
+           14,
+           18,
+           14
+          ],
+          "data": "48CS5rNxJb96c6eTcZQYYvRDkB4Uz8pTkB3m",
+          "programIdIndex": 14,
+          "stackHeight": 1
+         }
+        ],
+        "recentBlockhash": "6Y9h3uJmp6eFM7xzSLC6UYw498ZajgZATErWovuPg849"
+       },
+       "signatures": [
+        "7TvEfsbrjHodqtCZMc7vduuuuB5Hu4SxfHCfxWw6pkxx5vSUmLTxvNuYFnQ6XdV1a7d6bxfvAFvAvvVBSRLh1QY"
+       ]
+      },
+      "version": 0
+     },
+     {
+      "meta": {
+       "computeUnitsConsumed": 28793,
+       "costUnits": 33377,
+       "err": null,
+       "fee": 10000,
+       "innerInstructions": [
+        {
+         "index": 2,
+         "instructions": [
+          {
+           "accounts": [
+            0,
+            4,
+            2,
+            3,
+            9
+           ],
+           "data": "6VhAuisxVjhwQuJTnG8UEz2TNTdjsRwFB2WKsBAXkyqBwCqVPHMexZQRaA5ySszVoo54NkjkQJyStT3graU7JCcW4AD2PtvAbyfjQKzGA3kwFM8TwwfrPfz3VjjbrVPxHVsJ1PL9G4zLAHHDEK7X83DGkQAa9BuAnQr4xp82AmhmJmizVBhmqhqqbpDx3Ex34CeC8HcGLk6KjXYpGmvab7HyuhZ",
+           "programIdIndex": 7,
+           "stackHeight": 2
+          },
+          {
+           "accounts": [
+            0,
+            2
+           ],
+           "data": "3Bxs412MvVNQj175",
+           "programIdIndex": 3,
+           "stackHeight": 3
+          }
+         ]
+        }
+       ],
+       "loadedAddresses": {
+        "readonly": [],
+        "writable": []
+       },
+       "logMessages": [
+        "Program ComputeBudget111111111111111111111111111111 invoke [1]",
+        "Program ComputeBudget111111111111111111111111111111 success",
+        "Program q8WWu9FefmPYtLrz4mKRBYVEX5apB4UmRW1F3TxmaW3 invoke [1]",
+        "Program log: Instruction: TouchOracle",
+        "Program pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt invoke [2]",
+        "Program log: Instruction: VerifyMessage",
+        "Program 11111111111111111111111111111111 invoke [3]",
+        "Program 11111111111111111111111111111111 success",
+        "Program pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt consumed 12401 of 35714 compute units",
+        "Program return: pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt gO/B9IDFYVrz+2c9Qih+mT2p+8NQa25B36MpUIIMLmwrAAAAddPHkwBbjS8zXgYAAgECAAAABABiLfosOAAAAAT4/wW+SLcMAAAAAAMZAA==",
+        "Program pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt success",
+        "Program data: KslRnrd07eUB4JbIVKEBAADUxcXBMQIAAFCVyFShAQAA61+RHgAAAAAzm8MQdZvMAxMmy+gJxC/3R0tMuVl3NcUtPx5/WLPK2A==",
+        "Program q8WWu9FefmPYtLrz4mKRBYVEX5apB4UmRW1F3TxmaW3 consumed 28643 of 44850 compute units",
+        "Program return: q8WWu9FefmPYtLrz4mKRBYVEX5apB4UmRW1F3TxmaW3 gO/B9IDFYVrz+2c9Qih+mT2p+8NQa25B36MpUIIMLmwrAAAAddPHkwBbjS8zXgYAAgECAAAABABiLfosOAAAAAT4/wW+SLcMAAAAAAMZAA==",
+        "Program q8WWu9FefmPYtLrz4mKRBYVEX5apB4UmRW1F3TxmaW3 success"
+       ],
+       "postBalances": [
+        5110523511,
+        5821680,
+        27042354983,
+        1,
+        3542640,
+        1,
+        1,
+        1141440,
+        833120,
+        0
+       ],
+       "postTokenBalances": [],
+       "preBalances": [
+        5110533512,
+        5821680,
+        27042354982,
+        1,
+        3542640,
+        1,
+        1,
+        1141440,
+        833120,
+        0
+       ],
+       "preTokenBalances": [],
+       "returnData": {
+        "data": [
+         "gO/B9IDFYVrz+2c9Qih+mT2p+8NQa25B36MpUIIMLmwrAAAAddPHkwBbjS8zXgYAAgECAAAABABiLfosOAAAAAT4/wW+SLcMAAAAAAMZAA==",
+         "base64"
+        ],
+        "programId": "pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt"
+       },
+       "rewards": null,
+       "status": {
+        "Ok": null
+       }
+      },
+      "transaction": {
+       "message": {
+        "accountKeys": [
+         "4UTYriXvwcpVTuzwGYUx1DJNposddSYSRvijXVaMhRdq",
+         "HCayMtvKa5smx9aoXDoA3icaftHYCy8gkiULzy7fawpX",
+         "opsLibxVY7Vz5eYMmSfX8cLFCFVYTtH6fr6MiifMpA7",
+         "11111111111111111111111111111111",
+         "3rdJbqfnagQ4yx9HXJViD4zc4xpiSqmFsKpPuSCQVyQL",
+         "ComputeBudget111111111111111111111111111111",
+         "Ed25519SigVerify111111111111111111111111111",
+         "pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt",
+         "q8WWu9FefmPYtLrz4mKRBYVEX5apB4UmRW1F3TxmaW3",
+         "Sysvar1nstructions1111111111111111111111111"
+        ],
+        "header": {
+         "numReadonlySignedAccounts": 0,
+         "numReadonlyUnsignedAccounts": 7,
+         "numRequiredSignatures": 1
+        },
+        "instructions": [
+         {
+          "accounts": [],
+          "data": "8AWWfCk8qZYPYNvxfj8Xh",
+          "programIdIndex": 6,
+          "stackHeight": 1
+         },
+         {
+          "accounts": [],
+          "data": "KDaxvT",
+          "programIdIndex": 5,
+          "stackHeight": 1
+         },
+         {
+          "accounts": [
+           0,
+           1,
+           4,
+           7,
+           2,
+           3,
+           9
+          ],
+          "data": "EM44qLUkPBifopW5RXDNSmDSiyMndC41PxvuzuzYaccmoDFqZNqNXpMDxgoqHsuHFUnWMsWBZ4zLKAZhZ6FXe6x98amBNN8KsjdXK68h9rEj5Jx7b8rnVXTJZNHfVkdHN44JDmmzxcApVAaV7ufSmz84nkQhnPuKr7KfQUUiJCpkVJqCprM1KBxMZkk7muGeqSd5tDUmThE7256ku3UiXxCf",
+          "programIdIndex": 8,
+          "stackHeight": 1
+         }
+        ],
+        "recentBlockhash": "EPNGy384xLyceSrG7nDNXx7sCeN29WFh7KJ7mNpoC4Me"
+       },
+       "signatures": [
+        "63hTA2JgPTUrnKuJbJjeKqubt651VUkf6YMxrnXHmyXJ3VeZcXqUB9xv4nPMHEYf6rvyDMskpVMEenoCKXVCJktW"
+       ]
+      },
+      "version": "legacy"
+     }
+    ]
+   }
+  }
+ }
+]
diff --git a/test/fixtures/v1_transactions.json b/test/fixtures/v1_transactions.json
new file mode 100644
--- /dev/null
+++ b/test/fixtures/v1_transactions.json
@@ -0,0 +1,6 @@
+[
+  {
+    "hex": "810100020f0000003730a19a717b2d94ccb9d7904cc55053fc510d69ab42dc2405b27efa3a38713c01043298145ee11647cb918dafa3a779ccab852090bc53e28737e12bdbce9f99ab853ca23e02fb0274b1b2ab5896f53140b233e6690151de172698c66c74a23ce1b305513eaa1518a123f4723dd48d606f905017a2f3d82692f71c2bbd61ab12521a06a7d51718c774c928566398691d5eb68b5eb8a39b4b6d5c73555b210000000000000000000000004401000000a8000002035a000003010afc8eafb5f1f7df180000000000804f1e166a41700100000010271027d78f0000e08f000000000000000000802a4d61b6f1f7df1800000000003090a0f83142700100000010271027d78f0000e08f000000000000000000800011f68c121d83a11de76d99261b406d7e8c93ddd47cc19bcae28a3664cc19fd1f16414ba804c83b9f10f8630cf8fea1c5149664535c516616e9658e937d67be02",
+    "name": "devnet-v1-transaction"
+  }
+]
