solana-haskell-sdk-1.2.0.0: test-integration/Test/Integration/Alt.hs
-- | Live address-lookup-table coverage: create a table, extend it with
-- addresses, decode it back, and send a v0 transaction that resolves its
-- recipient through the table (the fee payer and the System Program id stay
-- static keys -- signers and program ids are never eligible for a lookup).
module Test.Integration.Alt (tests) where
import Control.Exception (throwIO)
import Control.Monad.IO.Class (liftIO)
import Network.Solana.Core.Crypto (createSolanaKeyPair)
import Network.Solana.Core.VersionedMessage (altAddresses, newV0TransactionIntent)
import Network.Solana.NativePrograms.AddressLookupTable (createLookupTable, extendLookupTable)
import Network.Solana.NativePrograms.SystemProgram qualified as SystemProgram
import Network.Solana.RPC.HTTP.Account (getBalance)
import Network.Solana.RPC.HTTP.Block (getTheLatestBlockhash)
import Network.Solana.RPC.HTTP.Ledger (getSlot)
import Network.Solana.SolanaWeb3 (getLookupTable)
import Network.Web3.Provider (Web3)
import Test.Integration.Setup
import Test.Tasty
import Test.Tasty.HUnit
tests :: TestTree
tests =
testGroup
"Alt"
[testCase "on-chain ALT: create, extend, decode, v0 transfer through the table" (run altV0Flow)]
-- | Creates a lookup table at the current finalized slot (guaranteed present
-- in the SlotHashes sysvar for the on-chain create check), extends it with a
-- recipient and a spare address, waits for the extension to finalize, checks
-- the decoded table holds the extended addresses, then sends a v0
-- transaction that resolves the recipient through the table and checks the
-- transfer lands with the exact amount.
--
-- The v0 send goes through 'sendConfirmedPreflight' rather than a
-- @finalized@-commitment send: an address added to a lookup table in slot
-- @S@ (the extend's landing slot, exposed on-chain as
-- @last_extended_slot@) only resolves in slots strictly greater than @S@.
-- 'confirmFinalized' guarantees the rooted bank has reached @S@, not passed
-- it, so a @finalized@-commitment preflight can simulate against a bank
-- sitting exactly at @S@ -- where the table's active-address count is still
-- zero (it was empty before this extend) -- and reject the send with
-- \"Transaction address table lookup uses an invalid index\", even though
-- the extend is itself finalized and a fresh 'getLookupTable' read shows the
-- addresses. See 'sendConfirmedPreflight' for the full rationale.
altV0Flow :: Web3 ()
altV0Flow = do
(payerPk, payerSk) <- fundedKeypair 3_000_000_000
recipient <- fst <$> liftIO createSolanaKeyPair
extra <- fst <$> liftIO createSolanaKeyPair
slot <- getSlot
let (createIx, tablePk) = createLookupTable payerPk payerPk slot
_ <- sendAndConfirm [payerSk] [createIx]
extendSig <- sendAndConfirm [payerSk] [extendLookupTable tablePk payerPk (Just payerPk) [recipient, extra]]
confirmFinalized extendSig
table <- requireJust "lookup table" =<< getLookupTable tablePk
liftIO (assertBool "extended addresses present" (recipient `elem` altAddresses table))
bh <- getTheLatestBlockhash
tx <- either (liftIO . throwIO) pure (newV0TransactionIntent [payerSk] [SystemProgram.transfer payerPk recipient 200_000_000] [table] bh)
sig <- sendConfirmedPreflight tx
confirmFinalized sig
bal <- getBalance recipient
liftIO (bal @?= 200_000_000)