Repository: solana-labs/solana-program-library
Pull request #7050 (2024-07-25 12:33:36)

stake-pool-py: Update to newer solana-py / solders
#### Problem

As part of the upgrade to 2.0.3, RPC methods have been removed, which the stake-pool python package relies on.

#### Solution

Update to the newest solana-py and solders packages, which use the new RPC methods.


Patch:
diff --git a/stake-pool/py/bot/rebalance.py b/stake-pool/py/bot/rebalance.py
index bc656a875..e12a6a9a6 100644
--- a/stake-pool/py/bot/rebalance.py
+++ b/stake-pool/py/bot/rebalance.py
@@ -2,8 +2,8 @@ import argparse
 import asyncio
 import json
 
-from solana.keypair import Keypair
-from solana.publickey import PublicKey
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
 from solana.rpc.async_api import AsyncClient
 from solana.rpc.commitment import Confirmed
 
@@ -27,30 +27,30 @@ async def get_client(endpoint: str) -> AsyncClient:
     return async_client
 
 
-async def rebalance(endpoint: str, stake_pool_address: PublicKey, staker: Keypair, retained_reserve_amount: float):
+async def rebalance(endpoint: str, stake_pool_address: Pubkey, staker: Keypair, retained_reserve_amount: float):
     async_client = await get_client(endpoint)
 
-    resp = await async_client.get_epoch_info(commitment=Confirmed)
-    epoch = resp['result']['epoch']
+    epoch_resp = await async_client.get_epoch_info(commitment=Confirmed)
+    epoch = epoch_resp.value.epoch
     resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     print(f'Stake pool last update epoch {stake_pool.last_update_epoch}, current epoch {epoch}')
     if stake_pool.last_update_epoch != epoch:
         print('Updating stake pool')
         await update_stake_pool(async_client, staker, stake_pool_address)
         resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-        data = resp['result']['value']['data']
-        stake_pool = StakePool.decode(data[0], data[1])
+        data = resp.value.data if resp.value else bytes()
+        stake_pool = StakePool.decode(data)
 
-    resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
-    stake_rent_exemption = resp['result']
+    rent_resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
+    stake_rent_exemption = rent_resp.value
     retained_reserve_lamports = int(retained_reserve_amount * LAMPORTS_PER_SOL)
 
-    resp = await async_client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    val_resp = await async_client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
+    data = val_resp.value.data if val_resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
 
     print('Stake pool stats:')
     print(f'* {stake_pool.total_lamports} total lamports')
@@ -107,7 +107,7 @@ def keypair_from_file(keyfile_name: str) -> Keypair:
         data = keyfile.read()
     int_list = json.loads(data)
     bytes_list = [value.to_bytes(1, 'little') for value in int_list]
-    return Keypair.from_secret_key(b''.join(bytes_list))
+    return Keypair.from_seed(b''.join(bytes_list))
 
 
 if __name__ == "__main__":
@@ -124,9 +124,9 @@ if __name__ == "__main__":
                         help='RPC endpoint to use, e.g. https://api.mainnet-beta.solana.com')
 
     args = parser.parse_args()
-    stake_pool = PublicKey(args.stake_pool)
+    stake_pool = Pubkey(args.stake_pool)
     staker = keypair_from_file(args.staker)
     print(f'Rebalancing stake pool {stake_pool}')
-    print(f'Staker public key: {staker.public_key}')
+    print(f'Staker public key: {staker.pubkey()}')
     print(f'Amount to leave in the reserve: {args.reserve_amount} SOL')
     asyncio.run(rebalance(args.endpoint, stake_pool, staker, args.reserve_amount))
diff --git a/stake-pool/py/optional-requirements.txt b/stake-pool/py/optional-requirements.txt
index 5aa593192..5f08be95a 100644
--- a/stake-pool/py/optional-requirements.txt
+++ b/stake-pool/py/optional-requirements.txt
@@ -1,15 +1,11 @@
-attrs==22.1.0
-flake8==5.0.3
-iniconfig==1.1.1
+flake8==7.1.0
+iniconfig==2.0.0
 mccabe==0.7.0
-mypy==0.971
-mypy-extensions==0.4.3
-packaging==21.3
-pluggy==1.0.0
-py==1.11.0
-pycodestyle==2.9.0
-pyflakes==2.5.0
-pyparsing==3.0.9
-pytest==7.1.2
-pytest-asyncio==0.19.0
-tomli==2.0.1
+mypy==1.11.0
+mypy-extensions==1.0.0
+packaging==24.1
+pluggy==1.5.0
+pycodestyle==2.12.0
+pyflakes==3.2.0
+pytest==8.3.1
+pytest-asyncio==0.23.8
diff --git a/stake-pool/py/requirements.txt b/stake-pool/py/requirements.txt
index 668602a5d..9b0f39a3f 100644
--- a/stake-pool/py/requirements.txt
+++ b/stake-pool/py/requirements.txt
@@ -1,19 +1,14 @@
-anyio==3.6.1
-base58==2.1.1
-cachetools==4.2.4
+anyio==4.4.0
 certifi==2024.7.4
-cffi==1.15.1
-charset-normalizer==2.1.0
 construct==2.10.68
-h11==0.12.0
-httpcore==0.15.0
-httpx==0.23.0
+construct-typing==0.5.6
+h11==0.14.0
+httpcore==1.0.5
+httpx==0.27.0
 idna==3.7
-pycparser==2.21
-PyNaCl==1.5.0
-requests==2.32.0
-rfc3986==1.5.0
-sniffio==1.2.0
-solana==0.18.1
-typing_extensions==4.3.0
-urllib3==1.26.19
+jsonalias==0.1.1
+sniffio==1.3.1
+solana==0.34.2
+solders==0.21.0
+typing_extensions==4.12.2
+websockets==11.0.3
diff --git a/stake-pool/py/spl_token/actions.py b/stake-pool/py/spl_token/actions.py
index 6c00a9285..99a03fd0d 100644
--- a/stake-pool/py/spl_token/actions.py
+++ b/stake-pool/py/spl_token/actions.py
@@ -1,10 +1,10 @@
-from solana.publickey import PublicKey
-from solana.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.keypair import Keypair
 from solana.rpc.async_api import AsyncClient
 from solana.rpc.commitment import Confirmed
 from solana.rpc.types import TxOpts
 from solana.transaction import Transaction
-import solana.system_program as sys
+import solders.system_program as sys
 
 from spl.token.constants import TOKEN_PROGRAM_ID
 from spl.token.async_client import AsyncToken
@@ -12,33 +12,37 @@ from spl.token._layouts import MINT_LAYOUT
 import spl.token.instructions as spl_token
 
 
+OPTS = TxOpts(skip_confirmation=False, preflight_commitment=Confirmed)
+
+
 async def create_associated_token_account(
     client: AsyncClient,
     payer: Keypair,
-    owner: PublicKey,
-    mint: PublicKey
-) -> PublicKey:
-    txn = Transaction()
+    owner: Pubkey,
+    mint: Pubkey
+) -> Pubkey:
+    txn = Transaction(fee_payer=payer.pubkey())
     create_txn = spl_token.create_associated_token_account(
-        payer=payer.public_key, owner=owner, mint=mint
+        payer=payer.pubkey(), owner=owner, mint=mint
     )
     txn.add(create_txn)
-    await client.send_transaction(txn, payer, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
-    return create_txn.keys[1].pubkey
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, payer, recent_blockhash=recent_blockhash, opts=OPTS)
+    return create_txn.accounts[1].pubkey
 
 
-async def create_mint(client: AsyncClient, payer: Keypair, mint: Keypair, mint_authority: PublicKey):
+async def create_mint(client: AsyncClient, payer: Keypair, mint: Keypair, mint_authority: Pubkey):
     mint_balance = await AsyncToken.get_min_balance_rent_for_exempt_for_mint(client)
-    print(f"Creating pool token mint {mint.public_key}")
-    txn = Transaction()
+    print(f"Creating pool token mint {mint.pubkey()}")
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         sys.create_account(
             sys.CreateAccountParams(
-                from_pubkey=payer.public_key,
-                new_account_pubkey=mint.public_key,
+                from_pubkey=payer.pubkey(),
+                to_pubkey=mint.pubkey(),
                 lamports=mint_balance,
                 space=MINT_LAYOUT.sizeof(),
-                program_id=TOKEN_PROGRAM_ID,
+                owner=TOKEN_PROGRAM_ID,
             )
         )
     )
@@ -46,12 +50,13 @@ async def create_mint(client: AsyncClient, payer: Keypair, mint: Keypair, mint_a
         spl_token.initialize_mint(
             spl_token.InitializeMintParams(
                 program_id=TOKEN_PROGRAM_ID,
-                mint=mint.public_key,
+                mint=mint.pubkey(),
                 decimals=9,
                 mint_authority=mint_authority,
                 freeze_authority=None,
             )
         )
     )
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
     await client.send_transaction(
-        txn, payer, mint, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+        txn, payer, mint, recent_blockhash=recent_blockhash, opts=OPTS)
diff --git a/stake-pool/py/stake/actions.py b/stake-pool/py/stake/actions.py
index 2963a43da..1147a56db 100644
--- a/stake-pool/py/stake/actions.py
+++ b/stake-pool/py/stake/actions.py
@@ -1,36 +1,40 @@
-from solana.publickey import PublicKey
-from solana.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.keypair import Keypair
+import solders.system_program as sys
+from solana.constants import SYSTEM_PROGRAM_ID
 from solana.rpc.async_api import AsyncClient
 from solana.rpc.commitment import Confirmed
 from solana.rpc.types import TxOpts
-from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY
+from solders.sysvar import CLOCK, STAKE_HISTORY
 from solana.transaction import Transaction
-import solana.system_program as sys
 
 from stake.constants import STAKE_LEN, STAKE_PROGRAM_ID, SYSVAR_STAKE_CONFIG_ID
 from stake.state import Authorized, Lockup, StakeAuthorize
 import stake.instructions as st
 
 
-async def create_stake(client: AsyncClient, payer: Keypair, stake: Keypair, authority: PublicKey, lamports: int):
-    print(f"Creating stake {stake.public_key}")
+OPTS = TxOpts(skip_confirmation=False, preflight_commitment=Confirmed)
+
+
+async def create_stake(client: AsyncClient, payer: Keypair, stake: Keypair, authority: Pubkey, lamports: int):
+    print(f"Creating stake {stake.pubkey()}")
     resp = await client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         sys.create_account(
             sys.CreateAccountParams(
-                from_pubkey=payer.public_key,
-                new_account_pubkey=stake.public_key,
-                lamports=resp['result'] + lamports,
+                from_pubkey=payer.pubkey(),
+                to_pubkey=stake.pubkey(),
+                lamports=resp.value + lamports,
                 space=STAKE_LEN,
-                program_id=STAKE_PROGRAM_ID,
+                owner=STAKE_PROGRAM_ID,
             )
         )
     )
     txn.add(
         st.initialize(
             st.InitializeParams(
-                stake=stake.public_key,
+                stake=stake.pubkey(),
                 authorized=Authorized(
                     staker=authority,
                     withdrawer=authority,
@@ -38,50 +42,50 @@ async def create_stake(client: AsyncClient, payer: Keypair, stake: Keypair, auth
                 lockup=Lockup(
                     unix_timestamp=0,
                     epoch=0,
-                    custodian=sys.SYS_PROGRAM_ID,
+                    custodian=SYSTEM_PROGRAM_ID,
                 )
             )
         )
     )
-    await client.send_transaction(
-        txn, payer, stake, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, payer, stake, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
-async def delegate_stake(client: AsyncClient, payer: Keypair, staker: Keypair, stake: PublicKey, vote: PublicKey):
-    txn = Transaction()
+async def delegate_stake(client: AsyncClient, payer: Keypair, staker: Keypair, stake: Pubkey, vote: Pubkey):
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         st.delegate_stake(
             st.DelegateStakeParams(
                 stake=stake,
                 vote=vote,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
+                clock_sysvar=CLOCK,
+                stake_history_sysvar=STAKE_HISTORY,
                 stake_config_id=SYSVAR_STAKE_CONFIG_ID,
-                staker=staker.public_key,
+                staker=staker.pubkey(),
             )
         )
     )
-    signers = [payer, staker] if payer != staker else [payer]
-    await client.send_transaction(
-        txn, *signers, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    signers = [payer, staker] if payer.pubkey() != staker.pubkey() else [payer]
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, *signers, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def authorize(
-    client: AsyncClient, payer: Keypair, authority: Keypair, stake: PublicKey,
-    new_authority: PublicKey, stake_authorize: StakeAuthorize
+    client: AsyncClient, payer: Keypair, authority: Keypair, stake: Pubkey,
+    new_authority: Pubkey, stake_authorize: StakeAuthorize
 ):
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         st.authorize(
             st.AuthorizeParams(
                 stake=stake,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                authority=authority.public_key,
+                clock_sysvar=CLOCK,
+                authority=authority.pubkey(),
                 new_authority=new_authority,
                 stake_authorize=stake_authorize,
             )
         )
     )
-    signers = [payer, authority] if payer != authority else [payer]
-    await client.send_transaction(
-        txn, *signers, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    signers = [payer, authority] if payer.pubkey() != authority.pubkey() else [payer]
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, *signers, recent_blockhash=recent_blockhash, opts=OPTS)
diff --git a/stake-pool/py/stake/constants.py b/stake-pool/py/stake/constants.py
index 344a8a5e7..da1c644c7 100644
--- a/stake-pool/py/stake/constants.py
+++ b/stake-pool/py/stake/constants.py
@@ -1,11 +1,11 @@
 """Stake Program Constants."""
 
-from solana.publickey import PublicKey
+from solders.pubkey import Pubkey
 
-STAKE_PROGRAM_ID: PublicKey = PublicKey("Stake11111111111111111111111111111111111111")
+STAKE_PROGRAM_ID = Pubkey.from_string("Stake11111111111111111111111111111111111111")
 """Public key that identifies the Stake program."""
 
-SYSVAR_STAKE_CONFIG_ID: PublicKey = PublicKey("StakeConfig11111111111111111111111111111111")
+SYSVAR_STAKE_CONFIG_ID = Pubkey.from_string("StakeConfig11111111111111111111111111111111")
 """Public key that identifies the Stake config sysvar."""
 
 STAKE_LEN: int = 200
diff --git a/stake-pool/py/stake/instructions.py b/stake-pool/py/stake/instructions.py
index f4b116bac..91e7e7dc6 100644
--- a/stake-pool/py/stake/instructions.py
+++ b/stake-pool/py/stake/instructions.py
@@ -7,9 +7,9 @@ from construct import Switch  # type: ignore
 from construct import Int32ul, Pass  # type: ignore
 from construct import Bytes, Struct
 
-from solana.publickey import PublicKey
-from solana.sysvar import SYSVAR_RENT_PUBKEY
-from solana.transaction import AccountMeta, TransactionInstruction
+from solders.pubkey import Pubkey
+from solders.sysvar import RENT
+from solders.instruction import AccountMeta, Instruction
 
 from stake.constants import STAKE_PROGRAM_ID
 from stake.state import AUTHORIZED_LAYOUT, LOCKUP_LAYOUT, Authorized, Lockup, StakeAuthorize
@@ -20,7 +20,7 @@ PUBLIC_KEY_LAYOUT = Bytes(32)
 class InitializeParams(NamedTuple):
     """Initialize stake transaction params."""
 
-    stake: PublicKey
+    stake: Pubkey
     """`[w]` Uninitialized stake account."""
     authorized: Authorized
     """Information about the staker and withdrawer keys."""
@@ -31,32 +31,32 @@ class InitializeParams(NamedTuple):
 class DelegateStakeParams(NamedTuple):
     """Initialize stake transaction params."""
 
-    stake: PublicKey
+    stake: Pubkey
     """`[w]` Uninitialized stake account."""
-    vote: PublicKey
+    vote: Pubkey
     """`[]` Vote account to which this stake will be delegated."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """`[]` Stake history sysvar that carries stake warmup/cooldown history."""
-    stake_config_id: PublicKey
+    stake_config_id: Pubkey
     """`[]` Address of config account that carries stake config."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Stake authority."""
 
 
 class AuthorizeParams(NamedTuple):
     """Authorize stake transaction params."""
 
-    stake: PublicKey
+    stake: Pubkey
     """`[w]` Initialized stake account to modify."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    authority: PublicKey
+    authority: Pubkey
     """`[s]` Current stake authority."""
 
     # Params
-    new_authority: PublicKey
+    new_authority: Pubkey
     """New authority's public key."""
     stake_authorize: StakeAuthorize
     """Type of authority to modify, staker or withdrawer."""
@@ -116,12 +116,12 @@ INSTRUCTIONS_LAYOUT = Struct(
 )
 
 
-def initialize(params: InitializeParams) -> TransactionInstruction:
+def initialize(params: InitializeParams) -> Instruction:
     """Creates a transaction instruction to initialize a new stake."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake, is_signer=False, is_writable=True),
-            AccountMeta(pubkey=SYSVAR_RENT_PUBKEY, is_signer=False, is_writable=False),
+            AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
         ],
         program_id=STAKE_PROGRAM_ID,
         data=INSTRUCTIONS_LAYOUT.build(
@@ -136,10 +136,10 @@ def initialize(params: InitializeParams) -> TransactionInstruction:
     )
 
 
-def delegate_stake(params: DelegateStakeParams) -> TransactionInstruction:
+def delegate_stake(params: DelegateStakeParams) -> Instruction:
     """Creates an instruction to delegate a stake account."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake, is_signer=False, is_writable=True),
             AccountMeta(pubkey=params.vote, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.clock_sysvar, is_signer=False, is_writable=False),
@@ -157,10 +157,10 @@ def delegate_stake(params: DelegateStakeParams) -> TransactionInstruction:
     )
 
 
-def authorize(params: AuthorizeParams) -> TransactionInstruction:
+def authorize(params: AuthorizeParams) -> Instruction:
     """Creates an instruction to change the authority on a stake account."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake, is_signer=False, is_writable=True),
             AccountMeta(pubkey=params.clock_sysvar, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.authority, is_signer=True, is_writable=False),
diff --git a/stake-pool/py/stake/state.py b/stake-pool/py/stake/state.py
index 8d8ac81f1..45d1942ab 100644
--- a/stake-pool/py/stake/state.py
+++ b/stake-pool/py/stake/state.py
@@ -4,8 +4,7 @@ from enum import IntEnum
 from typing import NamedTuple, Dict
 from construct import Bytes, Container, Struct, Float64l, Int32ul, Int64ul  # type: ignore
 
-from solana.publickey import PublicKey
-from solana.utils.helpers import decode_byte_string
+from solders.pubkey import Pubkey
 
 PUBLIC_KEY_LAYOUT = Bytes(32)
 
@@ -14,14 +13,14 @@ class Lockup(NamedTuple):
     """Lockup for a stake account."""
     unix_timestamp: int
     epoch: int
-    custodian: PublicKey
+    custodian: Pubkey
 
     @classmethod
     def decode_container(cls, container: Container):
         return Lockup(
             unix_timestamp=container['unix_timestamp'],
             epoch=container['epoch'],
-            custodian=PublicKey(container['custodian']),
+            custodian=Pubkey(container['custodian']),
         )
 
     def as_bytes_dict(self) -> Dict:
@@ -32,8 +31,8 @@ class Lockup(NamedTuple):
 
 class Authorized(NamedTuple):
     """Define who is authorized to change a stake."""
-    staker: PublicKey
-    withdrawer: PublicKey
+    staker: Pubkey
+    withdrawer: Pubkey
 
     def as_bytes_dict(self) -> Dict:
         return {
@@ -62,9 +61,8 @@ class StakeStake(NamedTuple):
 
     """Stake state."""
     @classmethod
-    def decode(cls, data: str, encoding: str):
-        data_bytes = decode_byte_string(data, encoding)
-        parsed = STAKE_STATE_LAYOUT.parse(data_bytes)
+    def decode(cls, data: bytes):
+        parsed = STAKE_STATE_LAYOUT.parse(data)
         return StakeStake(
             state_type=parsed['state_type'],
             state=parsed['state'],
diff --git a/stake-pool/py/stake_pool/actions.py b/stake-pool/py/stake_pool/actions.py
index e44afba4d..400f92524 100644
--- a/stake-pool/py/stake_pool/actions.py
+++ b/stake-pool/py/stake_pool/actions.py
@@ -1,13 +1,13 @@
 from typing import Optional, Tuple
 
-from solana.keypair import Keypair
-from solana.publickey import PublicKey
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
 from solana.rpc.async_api import AsyncClient
 from solana.rpc.commitment import Confirmed
 from solana.rpc.types import TxOpts
-from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY
+from solders.sysvar import CLOCK, RENT, STAKE_HISTORY
 from solana.transaction import Transaction
-import solana.system_program as sys
+import solders.system_program as sys
 
 from spl.token.constants import TOKEN_PROGRAM_ID
 
@@ -31,54 +31,58 @@ from stake.actions import create_stake
 from spl_token.actions import create_mint, create_associated_token_account
 
 
+OPTS = TxOpts(skip_confirmation=False, preflight_commitment=Confirmed)
+
+
 async def create(client: AsyncClient, manager: Keypair,
                  stake_pool: Keypair, validator_list: Keypair,
-                 pool_mint: PublicKey, reserve_stake: PublicKey,
-                 manager_fee_account: PublicKey, fee: Fee, referral_fee: int):
+                 pool_mint: Pubkey, reserve_stake: Pubkey,
+                 manager_fee_account: Pubkey, fee: Fee, referral_fee: int):
     resp = await client.get_minimum_balance_for_rent_exemption(STAKE_POOL_LAYOUT.sizeof())
-    pool_balance = resp['result']
-    txn = Transaction()
+    pool_balance = resp.value
+    txn = Transaction(fee_payer=manager.pubkey())
     txn.add(
         sys.create_account(
             sys.CreateAccountParams(
-                from_pubkey=manager.public_key,
-                new_account_pubkey=stake_pool.public_key,
+                from_pubkey=manager.pubkey(),
+                to_pubkey=stake_pool.pubkey(),
                 lamports=pool_balance,
                 space=STAKE_POOL_LAYOUT.sizeof(),
-                program_id=STAKE_POOL_PROGRAM_ID,
+                owner=STAKE_POOL_PROGRAM_ID,
             )
         )
     )
     max_validators = 2950  # current supported max by the program, go big!
     validator_list_size = ValidatorList.calculate_validator_list_size(max_validators)
     resp = await client.get_minimum_balance_for_rent_exemption(validator_list_size)
-    validator_list_balance = resp['result']
+    validator_list_balance = resp.value
     txn.add(
         sys.create_account(
             sys.CreateAccountParams(
-                from_pubkey=manager.public_key,
-                new_account_pubkey=validator_list.public_key,
+                from_pubkey=manager.pubkey(),
+                to_pubkey=validator_list.pubkey(),
                 lamports=validator_list_balance,
                 space=validator_list_size,
-                program_id=STAKE_POOL_PROGRAM_ID,
+                owner=STAKE_POOL_PROGRAM_ID,
             )
         )
     )
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
     await client.send_transaction(
-        txn, manager, stake_pool, validator_list, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+        txn, manager, stake_pool, validator_list, recent_blockhash=recent_blockhash, opts=OPTS)
 
     (withdraw_authority, seed) = find_withdraw_authority_program_address(
-        STAKE_POOL_PROGRAM_ID, stake_pool.public_key)
-    txn = Transaction()
+        STAKE_POOL_PROGRAM_ID, stake_pool.pubkey())
+    txn = Transaction(fee_payer=manager.pubkey())
     txn.add(
         sp.initialize(
             sp.InitializeParams(
                 program_id=STAKE_POOL_PROGRAM_ID,
-                stake_pool=stake_pool.public_key,
-                manager=manager.public_key,
-                staker=manager.public_key,
+                stake_pool=stake_pool.pubkey(),
+                manager=manager.pubkey(),
+                staker=manager.pubkey(),
                 withdraw_authority=withdraw_authority,
-                validator_list=validator_list.public_key,
+                validator_list=validator_list.pubkey(),
                 reserve_stake=reserve_stake,
                 pool_mint=pool_mint,
                 manager_fee_account=manager_fee_account,
@@ -91,17 +95,17 @@ async def create(client: AsyncClient, manager: Keypair,
             )
         )
     )
-    await client.send_transaction(
-        txn, manager, validator_list, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, manager, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def create_all(
         client: AsyncClient, manager: Keypair, fee: Fee, referral_fee: int
-) -> Tuple[PublicKey, PublicKey, PublicKey]:
+) -> Tuple[Pubkey, Pubkey, Pubkey]:
     stake_pool = Keypair()
     validator_list = Keypair()
     (pool_withdraw_authority, seed) = find_withdraw_authority_program_address(
-        STAKE_POOL_PROGRAM_ID, stake_pool.public_key)
+        STAKE_POOL_PROGRAM_ID, stake_pool.pubkey())
 
     reserve_stake = Keypair()
     await create_stake(client, manager, reserve_stake, pool_withdraw_authority, MINIMUM_RESERVE_LAMPORTS)
@@ -112,26 +116,26 @@ async def create_all(
     manager_fee_account = await create_associated_token_account(
         client,
         manager,
-        manager.public_key,
-        pool_mint.public_key,
+        manager.pubkey(),
+        pool_mint.pubkey(),
     )
 
     fee = Fee(numerator=1, denominator=1000)
     referral_fee = 20
     await create(
-        client, manager, stake_pool, validator_list, pool_mint.public_key,
-        reserve_stake.public_key, manager_fee_account, fee, referral_fee)
-    return (stake_pool.public_key, validator_list.public_key, pool_mint.public_key)
+        client, manager, stake_pool, validator_list, pool_mint.pubkey(),
+        reserve_stake.pubkey(), manager_fee_account, fee, referral_fee)
+    return (stake_pool.pubkey(), validator_list.pubkey(), pool_mint.pubkey())
 
 
 async def add_validator_to_pool(
     client: AsyncClient, staker: Keypair,
-    stake_pool_address: PublicKey, validator: PublicKey
+    stake_pool_address: Pubkey, validator: Pubkey
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
-    txn = Transaction()
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
+    txn = Transaction(fee_payer=staker.pubkey())
     txn.add(
         sp.add_validator_to_pool_with_vote(
             STAKE_POOL_PROGRAM_ID,
@@ -143,22 +147,22 @@ async def add_validator_to_pool(
             None,
         )
     )
-    await client.send_transaction(
-        txn, staker, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, staker, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def remove_validator_from_pool(
     client: AsyncClient, staker: Keypair,
-    stake_pool_address: PublicKey, validator: PublicKey
+    stake_pool_address: Pubkey, validator: Pubkey
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
     resp = await client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     validator_info = next(x for x in validator_list.validators if x.vote_account_address == validator)
-    txn = Transaction()
+    txn = Transaction(fee_payer=staker.pubkey())
     txn.add(
         sp.remove_validator_from_pool_with_vote(
             STAKE_POOL_PROGRAM_ID,
@@ -170,22 +174,21 @@ async def remove_validator_from_pool(
             validator_info.transient_seed_suffix,
         )
     )
-    await client.send_transaction(
-        txn, staker,
-        opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, staker, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def deposit_sol(
-    client: AsyncClient, funder: Keypair, stake_pool_address: PublicKey,
-    destination_token_account: PublicKey, amount: int,
+    client: AsyncClient, funder: Keypair, stake_pool_address: Pubkey,
+    destination_token_account: Pubkey, amount: int,
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     (withdraw_authority, seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=funder.pubkey())
     txn.add(
         sp.deposit_sol(
             sp.DepositSolParams(
@@ -193,47 +196,47 @@ async def deposit_sol(
                 stake_pool=stake_pool_address,
                 withdraw_authority=withdraw_authority,
                 reserve_stake=stake_pool.reserve_stake,
-                funding_account=funder.public_key,
+                funding_account=funder.pubkey(),
                 destination_pool_account=destination_token_account,
                 manager_fee_account=stake_pool.manager_fee_account,
                 referral_pool_account=destination_token_account,
                 pool_mint=stake_pool.pool_mint,
-                system_program_id=sys.SYS_PROGRAM_ID,
+                system_program_id=sys.ID,
                 token_program_id=stake_pool.token_program_id,
                 amount=amount,
                 deposit_authority=None,
             )
         )
     )
-    await client.send_transaction(
-        txn, funder, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, funder, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def withdraw_sol(
-    client: AsyncClient, owner: Keypair, source_token_account: PublicKey,
-    stake_pool_address: PublicKey, destination_system_account: PublicKey, amount: int,
+    client: AsyncClient, owner: Keypair, source_token_account: Pubkey,
+    stake_pool_address: Pubkey, destination_system_account: Pubkey, amount: int,
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     (withdraw_authority, seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=owner.pubkey())
     txn.add(
         sp.withdraw_sol(
             sp.WithdrawSolParams(
                 program_id=STAKE_POOL_PROGRAM_ID,
                 stake_pool=stake_pool_address,
                 withdraw_authority=withdraw_authority,
-                source_transfer_authority=owner.public_key,
+                source_transfer_authority=owner.pubkey(),
                 source_pool_account=source_token_account,
                 reserve_stake=stake_pool.reserve_stake,
                 destination_system_account=destination_system_account,
                 manager_fee_account=stake_pool.manager_fee_account,
                 pool_mint=stake_pool.pool_mint,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
+                clock_sysvar=CLOCK,
+                stake_history_sysvar=STAKE_HISTORY,
                 stake_program_id=STAKE_PROGRAM_ID,
                 token_program_id=stake_pool.token_program_id,
                 amount=amount,
@@ -241,25 +244,25 @@ async def withdraw_sol(
             )
         )
     )
-    await client.send_transaction(
-        txn, owner, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, owner, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def deposit_stake(
     client: AsyncClient,
     deposit_stake_authority: Keypair,
-    stake_pool_address: PublicKey,
-    validator_vote: PublicKey,
-    deposit_stake: PublicKey,
-    destination_pool_account: PublicKey,
+    stake_pool_address: Pubkey,
+    validator_vote: Pubkey,
+    deposit_stake: Pubkey,
+    destination_pool_account: Pubkey,
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     resp = await client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
 
     validator_info = next(x for x in validator_list.validators if x.vote_account_address == validator_vote)
 
@@ -271,13 +274,13 @@ async def deposit_stake(
         validator_info.validator_seed_suffix or None,
     )
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=deposit_stake_authority.pubkey())
     txn.add(
         st.authorize(
             st.AuthorizeParams(
                 stake=deposit_stake,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                authority=deposit_stake_authority.public_key,
+                clock_sysvar=CLOCK,
+                authority=deposit_stake_authority.pubkey(),
                 new_authority=stake_pool.stake_deposit_authority,
                 stake_authorize=StakeAuthorize.STAKER,
             )
@@ -287,8 +290,8 @@ async def deposit_stake(
         st.authorize(
             st.AuthorizeParams(
                 stake=deposit_stake,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                authority=deposit_stake_authority.public_key,
+                clock_sysvar=CLOCK,
+                authority=deposit_stake_authority.pubkey(),
                 new_authority=stake_pool.stake_deposit_authority,
                 stake_authorize=StakeAuthorize.WITHDRAWER,
             )
@@ -309,15 +312,15 @@ async def deposit_stake(
                 manager_fee_account=stake_pool.manager_fee_account,
                 referral_pool_account=destination_pool_account,
                 pool_mint=stake_pool.pool_mint,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
+                clock_sysvar=CLOCK,
+                stake_history_sysvar=STAKE_HISTORY,
                 token_program_id=stake_pool.token_program_id,
                 stake_program_id=STAKE_PROGRAM_ID,
             )
         )
     )
-    await client.send_transaction(
-        txn, deposit_stake_authority, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, deposit_stake_authority, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def withdraw_stake(
@@ -325,19 +328,19 @@ async def withdraw_stake(
     payer: Keypair,
     source_transfer_authority: Keypair,
     destination_stake: Keypair,
-    stake_pool_address: PublicKey,
-    validator_vote: PublicKey,
-    destination_stake_authority: PublicKey,
-    source_pool_account: PublicKey,
+    stake_pool_address: Pubkey,
+    validator_vote: Pubkey,
+    destination_stake_authority: Pubkey,
+    source_pool_account: Pubkey,
     amount: int,
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     resp = await client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
 
     validator_info = next(x for x in validator_list.validators if x.vote_account_address == validator_vote)
 
@@ -349,18 +352,18 @@ async def withdraw_stake(
         validator_info.validator_seed_suffix or None,
     )
 
-    resp = await client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
-    stake_rent_exemption = resp['result']
+    rent_resp = await client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
+    stake_rent_exemption = rent_resp.value
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         sys.create_account(
             sys.CreateAccountParams(
-                from_pubkey=payer.public_key,
-                new_account_pubkey=destination_stake.public_key,
+                from_pubkey=payer.pubkey(),
+                to_pubkey=destination_stake.pubkey(),
                 lamports=stake_rent_exemption,
                 space=STAKE_LEN,
-                program_id=STAKE_PROGRAM_ID,
+                owner=STAKE_PROGRAM_ID,
             )
         )
     )
@@ -372,13 +375,13 @@ async def withdraw_stake(
                 validator_list=stake_pool.validator_list,
                 withdraw_authority=withdraw_authority,
                 validator_stake=validator_stake,
-                destination_stake=destination_stake.public_key,
+                destination_stake=destination_stake.pubkey(),
                 destination_stake_authority=destination_stake_authority,
-                source_transfer_authority=source_transfer_authority.public_key,
+                source_transfer_authority=source_transfer_authority.pubkey(),
                 source_pool_account=source_pool_account,
                 manager_fee_account=stake_pool.manager_fee_account,
                 pool_mint=stake_pool.pool_mint,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
+                clock_sysvar=CLOCK,
                 token_program_id=stake_pool.token_program_id,
                 stake_program_id=STAKE_PROGRAM_ID,
                 amount=amount,
@@ -387,18 +390,18 @@ async def withdraw_stake(
     )
     signers = [payer, source_transfer_authority, destination_stake] \
         if payer != source_transfer_authority else [payer, destination_stake]
-    await client.send_transaction(
-        txn, *signers, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, *signers, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
-async def update_stake_pool(client: AsyncClient, payer: Keypair, stake_pool_address: PublicKey):
+async def update_stake_pool(client: AsyncClient, payer: Keypair, stake_pool_address: Pubkey):
     """Create and send all instructions to completely update a stake pool after epoch change."""
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
     resp = await client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     (withdraw_authority, seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)
     update_list_instructions = []
     validator_chunks = [
@@ -431,8 +434,8 @@ async def update_stake_pool(client: AsyncClient, payer: Keypair, stake_pool_addr
                     withdraw_authority=withdraw_authority,
                     validator_list=stake_pool.validator_list,
                     reserve_stake=stake_pool.reserve_stake,
-                    clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                    stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
+                    clock_sysvar=CLOCK,
+                    stake_history_sysvar=STAKE_HISTORY,
                     stake_program_id=STAKE_PROGRAM_ID,
                     validator_and_transient_stake_pairs=validator_and_transient_stake_pairs,
                     start_index=start_index,
@@ -444,15 +447,16 @@ async def update_stake_pool(client: AsyncClient, payer: Keypair, stake_pool_addr
     if update_list_instructions:
         last_instruction = update_list_instructions.pop()
         for update_list_instruction in update_list_instructions:
-            txn = Transaction()
+            txn = Transaction(fee_payer=payer.pubkey())
             txn.add(update_list_instruction)
-            await client.send_transaction(
-                txn, payer, opts=TxOpts(skip_confirmation=True, preflight_commitment=Confirmed))
-        txn = Transaction()
+            recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+            await client.send_transaction(txn, payer, recent_blockhash=recent_blockhash,
+                                          opts=TxOpts(skip_confirmation=True, preflight_commitment=Confirmed))
+        txn = Transaction(fee_payer=payer.pubkey())
         txn.add(last_instruction)
-        await client.send_transaction(
-            txn, payer, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
-    txn = Transaction()
+        recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+        await client.send_transaction(txn, payer, recent_blockhash=recent_blockhash, opts=OPTS)
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         sp.update_stake_pool_balance(
             sp.UpdateStakePoolBalanceParams(
@@ -476,26 +480,26 @@ async def update_stake_pool(client: AsyncClient, payer: Keypair, stake_pool_addr
             )
         )
     )
-    await client.send_transaction(
-        txn, payer, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, payer, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def increase_validator_stake(
     client: AsyncClient,
     payer: Keypair,
     staker: Keypair,
-    stake_pool_address: PublicKey,
-    validator_vote: PublicKey,
+    stake_pool_address: Pubkey,
+    validator_vote: Pubkey,
     lamports: int,
     ephemeral_stake_seed: Optional[int] = None
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     resp = await client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     (withdraw_authority, seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)
 
     validator_info = next(x for x in validator_list.validators if x.vote_account_address == validator_vote)
@@ -520,7 +524,7 @@ async def increase_validator_stake(
         validator_stake_seed
     )
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
     if ephemeral_stake_seed is not None:
 
         # We assume there is an existing transient account that we will update
@@ -534,18 +538,18 @@ async def increase_validator_stake(
                 sp.IncreaseAdditionalValidatorStakeParams(
                     program_id=STAKE_POOL_PROGRAM_ID,
                     stake_pool=stake_pool_address,
-                    staker=staker.public_key,
+                    staker=staker.pubkey(),
                     withdraw_authority=withdraw_authority,
                     validator_list=stake_pool.validator_list,
                     reserve_stake=stake_pool.reserve_stake,
                     transient_stake=transient_stake,
                     validator_stake=validator_stake,
                     validator_vote=validator_vote,
-                    clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                    rent_sysvar=SYSVAR_RENT_PUBKEY,
-                    stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
+                    clock_sysvar=CLOCK,
+                    rent_sysvar=RENT,
+                    stake_history_sysvar=STAKE_HISTORY,
                     stake_config_sysvar=SYSVAR_STAKE_CONFIG_ID,
-                    system_program_id=sys.SYS_PROGRAM_ID,
+                    system_program_id=sys.ID,
                     stake_program_id=STAKE_PROGRAM_ID,
                     lamports=lamports,
                     transient_stake_seed=transient_stake_seed,
@@ -561,18 +565,18 @@ async def increase_validator_stake(
                 sp.IncreaseValidatorStakeParams(
                     program_id=STAKE_POOL_PROGRAM_ID,
                     stake_pool=stake_pool_address,
-                    staker=staker.public_key,
+                    staker=staker.pubkey(),
                     withdraw_authority=withdraw_authority,
                     validator_list=stake_pool.validator_list,
                     reserve_stake=stake_pool.reserve_stake,
                     transient_stake=transient_stake,
                     validator_stake=validator_stake,
                     validator_vote=validator_vote,
-                    clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                    rent_sysvar=SYSVAR_RENT_PUBKEY,
-                    stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
+                    clock_sysvar=CLOCK,
+                    rent_sysvar=RENT,
+                    stake_history_sysvar=STAKE_HISTORY,
                     stake_config_sysvar=SYSVAR_STAKE_CONFIG_ID,
-                    system_program_id=sys.SYS_PROGRAM_ID,
+                    system_program_id=sys.ID,
                     stake_program_id=STAKE_PROGRAM_ID,
                     lamports=lamports,
                     transient_stake_seed=transient_stake_seed,
@@ -581,26 +585,26 @@ async def increase_validator_stake(
         )
 
     signers = [payer, staker] if payer != staker else [payer]
-    await client.send_transaction(
-        txn, *signers, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, *signers, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
 async def decrease_validator_stake(
     client: AsyncClient,
     payer: Keypair,
     staker: Keypair,
-    stake_pool_address: PublicKey,
-    validator_vote: PublicKey,
+    stake_pool_address: Pubkey,
+    validator_vote: Pubkey,
     lamports: int,
     ephemeral_stake_seed: Optional[int] = None
 ):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     resp = await client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     (withdraw_authority, seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)
 
     validator_info = next(x for x in validator_list.validators if x.vote_account_address == validator_vote)
@@ -625,7 +629,7 @@ async def decrease_validator_stake(
         transient_stake_seed,
     )
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
 
     if ephemeral_stake_seed is not None:
 
@@ -640,16 +644,16 @@ async def decrease_validator_stake(
                 sp.DecreaseAdditionalValidatorStakeParams(
                     program_id=STAKE_POOL_PROGRAM_ID,
                     stake_pool=stake_pool_address,
-                    staker=staker.public_key,
+                    staker=staker.pubkey(),
                     withdraw_authority=withdraw_authority,
                     validator_list=stake_pool.validator_list,
                     reserve_stake=stake_pool.reserve_stake,
                     validator_stake=validator_stake,
                     transient_stake=transient_stake,
-                    clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                    rent_sysvar=SYSVAR_RENT_PUBKEY,
-                    stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
-                    system_program_id=sys.SYS_PROGRAM_ID,
+                    clock_sysvar=CLOCK,
+                    rent_sysvar=RENT,
+                    stake_history_sysvar=STAKE_HISTORY,
+                    system_program_id=sys.ID,
                     stake_program_id=STAKE_PROGRAM_ID,
                     lamports=lamports,
                     transient_stake_seed=transient_stake_seed,
@@ -666,15 +670,15 @@ async def decrease_validator_stake(
                 sp.DecreaseValidatorStakeWithReserveParams(
                     program_id=STAKE_POOL_PROGRAM_ID,
                     stake_pool=stake_pool_address,
-                    staker=staker.public_key,
+                    staker=staker.pubkey(),
                     withdraw_authority=withdraw_authority,
                     validator_list=stake_pool.validator_list,
                     reserve_stake=stake_pool.reserve_stake,
                     validator_stake=validator_stake,
                     transient_stake=transient_stake,
-                    clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                    stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
-                    system_program_id=sys.SYS_PROGRAM_ID,
+                    clock_sysvar=CLOCK,
+                    stake_history_sysvar=STAKE_HISTORY,
+                    system_program_id=sys.ID,
                     stake_program_id=STAKE_PROGRAM_ID,
                     lamports=lamports,
                     transient_stake_seed=transient_stake_seed,
@@ -683,20 +687,20 @@ async def decrease_validator_stake(
         )
 
     signers = [payer, staker] if payer != staker else [payer]
-    await client.send_transaction(
-        txn, *signers, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, *signers, recent_blockhash=recent_blockhash, opts=OPTS)
 
 
-async def create_token_metadata(client: AsyncClient, payer: Keypair, stake_pool_address: PublicKey,
+async def create_token_metadata(client: AsyncClient, payer: Keypair, stake_pool_address: Pubkey,
                                 name: str, symbol: str, uri: str):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     (withdraw_authority, _seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)
     (token_metadata, _seed) = find_metadata_account(stake_pool.pool_mint)
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         sp.create_token_metadata(
             sp.CreateTokenMetadataParams(
@@ -704,31 +708,31 @@ async def create_token_metadata(client: AsyncClient, payer: Keypair, stake_pool_
                 stake_pool=stake_pool_address,
                 manager=stake_pool.manager,
                 pool_mint=stake_pool.pool_mint,
-                payer=payer.public_key,
+                payer=payer.pubkey(),
                 name=name,
                 symbol=symbol,
                 uri=uri,
                 withdraw_authority=withdraw_authority,
                 token_metadata=token_metadata,
                 metadata_program_id=METADATA_PROGRAM_ID,
-                system_program_id=sys.SYS_PROGRAM_ID,
+                system_program_id=sys.ID,
             )
         )
     )
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, payer, recent_blockhash=recent_blockhash, opts=OPTS)
 
-    await client.send_transaction(txn, payer, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
 
-
-async def update_token_metadata(client: AsyncClient, payer: Keypair, stake_pool_address: PublicKey,
+async def update_token_metadata(client: AsyncClient, payer: Keypair, stake_pool_address: Pubkey,
                                 name: str, symbol: str, uri: str):
     resp = await client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     (withdraw_authority, _seed) = find_withdraw_authority_program_address(STAKE_POOL_PROGRAM_ID, stake_pool_address)
     (token_metadata, _seed) = find_metadata_account(stake_pool.pool_mint)
 
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         sp.update_token_metadata(
             sp.UpdateTokenMetadataParams(
@@ -745,5 +749,5 @@ async def update_token_metadata(client: AsyncClient, payer: Keypair, stake_pool_
             )
         )
     )
-
-    await client.send_transaction(txn, payer, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
+    await client.send_transaction(txn, payer, recent_blockhash=recent_blockhash, opts=OPTS)
diff --git a/stake-pool/py/stake_pool/constants.py b/stake-pool/py/stake_pool/constants.py
index ff1f1dbe2..8a09dfbb2 100644
--- a/stake-pool/py/stake_pool/constants.py
+++ b/stake-pool/py/stake_pool/constants.py
@@ -2,10 +2,10 @@
 
 from typing import Optional, Tuple
 
-from solana.publickey import PublicKey
+from solders.pubkey import Pubkey
 from stake.constants import MINIMUM_DELEGATION
 
-STAKE_POOL_PROGRAM_ID: PublicKey = PublicKey("SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy")
+STAKE_POOL_PROGRAM_ID = Pubkey.from_string("SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy")
 """Public key that identifies the SPL Stake Pool program."""
 
 MAX_VALIDATORS_TO_UPDATE: int = 5
@@ -17,40 +17,40 @@ MINIMUM_RESERVE_LAMPORTS: int = 0
 MINIMUM_ACTIVE_STAKE: int = MINIMUM_DELEGATION
 """Minimum active delegated staked required in a stake account"""
 
-METADATA_PROGRAM_ID: PublicKey = PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
+METADATA_PROGRAM_ID = Pubkey.from_string("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
 """Public key that identifies the Metaplex Token Metadata program."""
 
 
 def find_deposit_authority_program_address(
-    program_id: PublicKey,
-    stake_pool_address: PublicKey,
-) -> Tuple[PublicKey, int]:
+    program_id: Pubkey,
+    stake_pool_address: Pubkey,
+) -> Tuple[Pubkey, int]:
     """Generates the deposit authority program address for the stake pool"""
-    return PublicKey.find_program_address(
+    return Pubkey.find_program_address(
         [bytes(stake_pool_address), AUTHORITY_DEPOSIT],
         program_id,
     )
 
 
 def find_withdraw_authority_program_address(
-    program_id: PublicKey,
-    stake_pool_address: PublicKey,
-) -> Tuple[PublicKey, int]:
+    program_id: Pubkey,
+    stake_pool_address: Pubkey,
+) -> Tuple[Pubkey, int]:
     """Generates the withdraw authority program address for the stake pool"""
-    return PublicKey.find_program_address(
+    return Pubkey.find_program_address(
         [bytes(stake_pool_address), AUTHORITY_WITHDRAW],
         program_id,
     )
 
 
 def find_stake_program_address(
-    program_id: PublicKey,
-    vote_account_address: PublicKey,
-    stake_pool_address: PublicKey,
+    program_id: Pubkey,
+    vote_account_address: Pubkey,
+    stake_pool_address: Pubkey,
     seed: Optional[int]
-) -> Tuple[PublicKey, int]:
+) -> Tuple[Pubkey, int]:
     """Generates the stake program address for a validator's vote account"""
-    return PublicKey.find_program_address(
+    return Pubkey.find_program_address(
         [
             bytes(vote_account_address),
             bytes(stake_pool_address),
@@ -61,13 +61,13 @@ def find_stake_program_address(
 
 
 def find_transient_stake_program_address(
-    program_id: PublicKey,
-    vote_account_address: PublicKey,
-    stake_pool_address: PublicKey,
+    program_id: Pubkey,
+    vote_account_address: Pubkey,
+    stake_pool_address: Pubkey,
     seed: int,
-) -> Tuple[PublicKey, int]:
+) -> Tuple[Pubkey, int]:
     """Generates the stake program address for a validator's vote account"""
-    return PublicKey.find_program_address(
+    return Pubkey.find_program_address(
         [
             TRANSIENT_STAKE_SEED_PREFIX,
             bytes(vote_account_address),
@@ -79,13 +79,13 @@ def find_transient_stake_program_address(
 
 
 def find_ephemeral_stake_program_address(
-    program_id: PublicKey,
-    stake_pool_address: PublicKey,
+    program_id: Pubkey,
+    stake_pool_address: Pubkey,
     seed: int
-) -> Tuple[PublicKey, int]:
+) -> Tuple[Pubkey, int]:
 
     """Generates the ephemeral program address for stake pool redelegation"""
-    return PublicKey.find_program_address(
+    return Pubkey.find_program_address(
         [
             EPHEMERAL_STAKE_SEED_PREFIX,
             bytes(stake_pool_address),
@@ -96,10 +96,10 @@ def find_ephemeral_stake_program_address(
 
 
 def find_metadata_account(
-    mint_key: PublicKey
-) -> Tuple[PublicKey, int]:
+    mint_key: Pubkey
+) -> Tuple[Pubkey, int]:
     """Generates the metadata account program address"""
-    return PublicKey.find_program_address(
+    return Pubkey.find_program_address(
         [
             METADATA_SEED_PREFIX,
             bytes(METADATA_PROGRAM_ID),
diff --git a/stake-pool/py/stake_pool/instructions.py b/stake-pool/py/stake_pool/instructions.py
index 8a3ae4cf5..e5d9199cd 100644
--- a/stake-pool/py/stake_pool/instructions.py
+++ b/stake-pool/py/stake_pool/instructions.py
@@ -4,10 +4,10 @@ from enum import IntEnum
 from typing import List, NamedTuple, Optional
 from construct import Prefixed, GreedyString, Struct, Switch, Int8ul, Int32ul, Int64ul, Pass  # type: ignore
 
-from solana.publickey import PublicKey
-from solana.transaction import AccountMeta, TransactionInstruction
-from solana.system_program import SYS_PROGRAM_ID
-from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY
+from solana.constants import SYSTEM_PROGRAM_ID
+from solders.pubkey import Pubkey
+from solders.instruction import AccountMeta, Instruction
+from solders.sysvar import CLOCK, RENT, STAKE_HISTORY
 from spl.token.constants import TOKEN_PROGRAM_ID
 
 from stake.constants import STAKE_PROGRAM_ID, SYSVAR_STAKE_CONFIG_ID
@@ -41,25 +41,25 @@ class InitializeParams(NamedTuple):
     """Initialize token mint transaction params."""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """[w] Stake Pool account to initialize."""
-    manager: PublicKey
+    manager: Pubkey
     """[s] Manager for new stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """[] Staker for the new stake pool."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """[] Withdraw authority for the new stake pool."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """[w] Uninitialized validator list account for the new stake pool."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """[] Reserve stake account."""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """[w] Pool token mint account."""
-    manager_fee_account: PublicKey
+    manager_fee_account: Pubkey
     """[w] Manager's fee account"""
-    token_program_id: PublicKey
+    token_program_id: Pubkey
     """[] SPL Token program id."""
 
     # Params
@@ -75,40 +75,40 @@ class InitializeParams(NamedTuple):
     """Maximum number of possible validators in the pool."""
 
     # Optional
-    deposit_authority: Optional[PublicKey] = None
+    deposit_authority: Optional[Pubkey] = None
     """[] Optional deposit authority that must sign all deposits."""
 
 
 class AddValidatorToPoolParams(NamedTuple):
     """(Staker only) Adds stake account delegated to validator to the pool's list of managed validators."""
 
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Staker."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Reserve stake account."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[w]` Stake account to add to the pool."""
-    validator_vote: PublicKey
+    validator_vote: Pubkey
     """`[]` Validator this stake account will be delegated to."""
-    rent_sysvar: PublicKey
+    rent_sysvar: Pubkey
     """`[]` Rent sysvar."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """'[]' Stake history sysvar."""
-    stake_config_sysvar: PublicKey
+    stake_config_sysvar: Pubkey
     """'[]' Stake config sysvar."""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
 
     # Params
@@ -119,23 +119,23 @@ class AddValidatorToPoolParams(NamedTuple):
 class RemoveValidatorFromPoolParams(NamedTuple):
     """(Staker only) Removes validator from the pool."""
 
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Staker."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[w]` Stake account to remove from the pool."""
-    transient_stake: PublicKey
+    transient_stake: Pubkey
     """`[]` Transient stake account, to check that there's no activation ongoing."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """'[]' Stake config sysvar."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
 
 
@@ -143,27 +143,27 @@ class DecreaseValidatorStakeParams(NamedTuple):
     """(Staker only) Decrease active stake on a validator, eventually moving it to the reserve"""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Staker."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[w]` Canonical stake to split from."""
-    transient_stake: PublicKey
+    transient_stake: Pubkey
     """`[w]` Transient stake account to receive split."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    rent_sysvar: PublicKey
+    rent_sysvar: Pubkey
     """`[]` Rent sysvar."""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
 
     # Params
@@ -177,29 +177,29 @@ class DecreaseValidatorStakeWithReserveParams(NamedTuple):
     """(Staker only) Decrease active stake on a validator, eventually moving it to the reserve"""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Staker."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Stake pool's reserve."""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[w]` Canonical stake to split from."""
-    transient_stake: PublicKey
+    transient_stake: Pubkey
     """`[w]` Transient stake account to receive split."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """'[]' Stake history sysvar."""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
 
     # Params
@@ -213,35 +213,35 @@ class IncreaseValidatorStakeParams(NamedTuple):
     """(Staker only) Increase stake on a validator from the reserve account."""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Staker."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Stake pool's reserve."""
-    transient_stake: PublicKey
+    transient_stake: Pubkey
     """`[w]` Transient stake account to receive split."""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[]` Canonical stake account to check."""
-    validator_vote: PublicKey
+    validator_vote: Pubkey
     """`[]` Validator vote account to delegate to."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    rent_sysvar: PublicKey
+    rent_sysvar: Pubkey
     """`[]` Rent sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """'[]' Stake history sysvar."""
-    stake_config_sysvar: PublicKey
+    stake_config_sysvar: Pubkey
     """'[]' Stake config sysvar."""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
 
     # Params
@@ -259,23 +259,23 @@ class UpdateValidatorListBalanceParams(NamedTuple):
     """Updates balances of validator and transient stake accounts in the pool."""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Stake pool's reserve."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """'[]' Stake history sysvar."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
-    validator_and_transient_stake_pairs: List[PublicKey]
+    validator_and_transient_stake_pairs: List[Pubkey]
     """[] N pairs of validator and transient stake accounts"""
 
     # Params
@@ -288,102 +288,102 @@ class UpdateValidatorListBalanceParams(NamedTuple):
 class UpdateStakePoolBalanceParams(NamedTuple):
     """Updates total pool balance based on balances in the reserve and validator list."""
 
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Stake pool's reserve."""
-    manager_fee_account: PublicKey
+    manager_fee_account: Pubkey
     """`[w]` Account to receive pool fee tokens."""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """`[w]` Pool mint account."""
-    token_program_id: PublicKey
+    token_program_id: Pubkey
     """`[]` Pool token program."""
 
 
 class CleanupRemovedValidatorEntriesParams(NamedTuple):
     """Cleans up validator stake account entries marked as `ReadyForRemoval`"""
 
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
 
 
 class DepositStakeParams(NamedTuple):
     """Deposits a stake account into the pool in exchange for pool tokens"""
 
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool"""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account"""
-    deposit_authority: PublicKey
+    deposit_authority: Pubkey
     """`[s]/[]` Stake pool deposit authority"""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority"""
-    deposit_stake: PublicKey
+    deposit_stake: Pubkey
     """`[w]` Stake account to join the pool (stake's withdraw authority set to the stake pool deposit authority)"""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[w]` Validator stake account for the stake account to be merged with"""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Reserve stake account, to withdraw rent exempt reserve"""
-    destination_pool_account: PublicKey
+    destination_pool_account: Pubkey
     """`[w]` User account to receive pool tokens"""
-    manager_fee_account: PublicKey
+    manager_fee_account: Pubkey
     """`[w]` Account to receive pool fee tokens"""
-    referral_pool_account: PublicKey
+    referral_pool_account: Pubkey
     """`[w]` Account to receive a portion of pool fee tokens as referral fees"""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """`[w]` Pool token mint account"""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Sysvar clock account"""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """`[]` Sysvar stake history account"""
-    token_program_id: PublicKey
+    token_program_id: Pubkey
     """`[]` Pool token program id"""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program id"""
 
 
 class WithdrawStakeParams(NamedTuple):
     """Withdraws a stake account from the pool in exchange for pool tokens"""
 
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool"""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account"""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority"""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[w]` Validator or reserve stake account to split"""
-    destination_stake: PublicKey
+    destination_stake: Pubkey
     """`[w]` Unitialized stake account to receive withdrawal"""
-    destination_stake_authority: PublicKey
+    destination_stake_authority: Pubkey
     """`[]` User account to set as a new withdraw authority"""
-    source_transfer_authority: PublicKey
+    source_transfer_authority: Pubkey
     """`[s]` User transfer authority, for pool token account"""
-    source_pool_account: PublicKey
+    source_pool_account: Pubkey
     """`[w]` User account with pool tokens to burn from"""
-    manager_fee_account: PublicKey
+    manager_fee_account: Pubkey
     """`[w]` Account to receive pool fee tokens"""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """`[w]` Pool token mint account"""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Sysvar clock account"""
-    token_program_id: PublicKey
+    token_program_id: Pubkey
     """`[]` Pool token program id"""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program id"""
 
     # Params
@@ -408,27 +408,27 @@ class DepositSolParams(NamedTuple):
     representing ownership into the pool. Inputs are converted to the current ratio."""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Stake pool's reserve."""
-    funding_account: PublicKey
+    funding_account: Pubkey
     """`[ws]` Funding account (must be a system account)."""
-    destination_pool_account: PublicKey
+    destination_pool_account: Pubkey
     """`[w]` User account to receive pool tokens."""
-    manager_fee_account: PublicKey
+    manager_fee_account: Pubkey
     """`[w]` Manager's pool token account to receive deposit fee."""
-    referral_pool_account: PublicKey
+    referral_pool_account: Pubkey
     """`[w]` Referrer pool token account to receive referral fee."""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """`[w]` Pool token mint."""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program."""
-    token_program_id: PublicKey
+    token_program_id: Pubkey
     """`[]` Token program."""
 
     # Params
@@ -436,7 +436,7 @@ class DepositSolParams(NamedTuple):
     """Amount of SOL to deposit"""
 
     # Optional
-    deposit_authority: Optional[PublicKey] = None
+    deposit_authority: Optional[Pubkey] = None
     """`[s]` (Optional) Stake pool sol deposit authority."""
 
 
@@ -448,31 +448,31 @@ class WithdrawSolParams(NamedTuple):
     """Withdraw SOL directly from the pool's reserve account."""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[w]` Stake pool."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    source_transfer_authority: PublicKey
+    source_transfer_authority: Pubkey
     """`[s]` Transfer authority for user pool token account."""
-    source_pool_account: PublicKey
+    source_pool_account: Pubkey
     """`[w]` User's pool token account to burn pool tokens."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Stake pool's reserve."""
-    destination_system_account: PublicKey
+    destination_system_account: Pubkey
     """`[w]` Destination system account to receive lamports from the reserve."""
-    manager_fee_account: PublicKey
+    manager_fee_account: Pubkey
     """`[w]` Manager's pool token account to receive fee."""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """`[w]` Pool token mint."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """'[]' Stake history sysvar."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
-    token_program_id: PublicKey
+    token_program_id: Pubkey
     """`[]` Token program."""
 
     # Params
@@ -480,7 +480,7 @@ class WithdrawSolParams(NamedTuple):
     """Amount of pool tokens to burn"""
 
     # Optional
-    sol_withdraw_authority: Optional[PublicKey] = None
+    sol_withdraw_authority: Optional[Pubkey] = None
     """`[s]` (Optional) Stake pool sol withdraw authority."""
 
 
@@ -488,23 +488,23 @@ class CreateTokenMetadataParams(NamedTuple):
     """Create token metadata for the stake-pool token in the metaplex-token program."""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    manager: PublicKey
+    manager: Pubkey
     """`[s]` Manager."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """`[]` Pool token mint account."""
-    payer: PublicKey
+    payer: Pubkey
     """`[s, w]` Payer for creation of token metadata account."""
-    token_metadata: PublicKey
+    token_metadata: Pubkey
     """`[w]` Token metadata program account."""
-    metadata_program_id: PublicKey
+    metadata_program_id: Pubkey
     """`[]` Metadata program id"""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program id"""
 
     # Params
@@ -519,19 +519,19 @@ class CreateTokenMetadataParams(NamedTuple):
 class UpdateTokenMetadataParams(NamedTuple):
     """Update token metadata for the stake-pool token in the metaplex-token program."""
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    manager: PublicKey
+    manager: Pubkey
     """`[s]` Manager."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    pool_mint: PublicKey
+    pool_mint: Pubkey
     """`[]` Pool token mint account."""
-    token_metadata: PublicKey
+    token_metadata: Pubkey
     """`[w]` Token metadata program account."""
-    metadata_program_id: PublicKey
+    metadata_program_id: Pubkey
     """`[]` Metadata program id"""
 
     # Params
@@ -547,37 +547,37 @@ class IncreaseAdditionalValidatorStakeParams(NamedTuple):
     """(Staker only) Increase stake on a validator from the reserve account."""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Staker."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """`[w]` Stake pool's reserve."""
-    ephemeral_stake: PublicKey
+    ephemeral_stake: Pubkey
     """The ephemeral stake account used during the operation."""
-    transient_stake: PublicKey
+    transient_stake: Pubkey
     """`[w]` Transient stake account to receive split."""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[]` Canonical stake account to check."""
-    validator_vote: PublicKey
+    validator_vote: Pubkey
     """`[]` Validator vote account to delegate to."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    rent_sysvar: PublicKey
+    rent_sysvar: Pubkey
     """`[]` Rent sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """'[]' Stake history sysvar."""
-    stake_config_sysvar: PublicKey
+    stake_config_sysvar: Pubkey
     """'[]' Stake config sysvar."""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
 
     # Params
@@ -593,33 +593,33 @@ class DecreaseAdditionalValidatorStakeParams(NamedTuple):
     """(Staker only) Decrease active stake on a validator, eventually moving it to the reserve"""
 
     # Accounts
-    program_id: PublicKey
+    program_id: Pubkey
     """SPL Stake Pool program account."""
-    stake_pool: PublicKey
+    stake_pool: Pubkey
     """`[]` Stake pool."""
-    staker: PublicKey
+    staker: Pubkey
     """`[s]` Staker."""
-    withdraw_authority: PublicKey
+    withdraw_authority: Pubkey
     """`[]` Stake pool withdraw authority."""
-    validator_list: PublicKey
+    validator_list: Pubkey
     """`[w]` Validator stake list storage account."""
-    reserve_stake: PublicKey
+    reserve_stake: Pubkey
     """The reserve stake account to move the stake to."""
-    validator_stake: PublicKey
+    validator_stake: Pubkey
     """`[w]` Canonical stake to split from."""
-    ephemeral_stake: PublicKey
+    ephemeral_stake: Pubkey
     """The ephemeral stake account used during the operation."""
-    transient_stake: PublicKey
+    transient_stake: Pubkey
     """`[w]` Transient stake account to receive split."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    rent_sysvar: PublicKey
+    rent_sysvar: Pubkey
     """`[]` Rent sysvar."""
-    stake_history_sysvar: PublicKey
+    stake_history_sysvar: Pubkey
     """'[]' Stake history sysvar."""
-    system_program_id: PublicKey
+    system_program_id: Pubkey
     """`[]` System program."""
-    stake_program_id: PublicKey
+    stake_program_id: Pubkey
     """`[]` Stake program."""
 
     # Params
@@ -730,7 +730,7 @@ INSTRUCTIONS_LAYOUT = Struct(
 )
 
 
-def initialize(params: InitializeParams) -> TransactionInstruction:
+def initialize(params: InitializeParams) -> Instruction:
     """Creates a transaction instruction to initialize a new stake pool."""
 
     data = INSTRUCTIONS_LAYOUT.build(
@@ -745,7 +745,7 @@ def initialize(params: InitializeParams) -> TransactionInstruction:
             ),
         )
     )
-    keys = [
+    accounts = [
         AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
         AccountMeta(pubkey=params.manager, is_signer=True, is_writable=False),
         AccountMeta(pubkey=params.staker, is_signer=False, is_writable=False),
@@ -757,20 +757,20 @@ def initialize(params: InitializeParams) -> TransactionInstruction:
         AccountMeta(pubkey=TOKEN_PROGRAM_ID, is_signer=False, is_writable=False),
     ]
     if params.deposit_authority:
-        keys.append(
+        accounts.append(
             AccountMeta(pubkey=params.deposit_authority, is_signer=True, is_writable=False),
         )
-    return TransactionInstruction(
-        keys=keys,
+    return Instruction(
+        accounts=accounts,
         program_id=params.program_id,
         data=data,
     )
 
 
-def add_validator_to_pool(params: AddValidatorToPoolParams) -> TransactionInstruction:
+def add_validator_to_pool(params: AddValidatorToPoolParams) -> Instruction:
     """Creates instruction to add a validator to the pool."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
             AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
             AccountMeta(pubkey=params.reserve_stake, is_signer=False, is_writable=True),
@@ -796,14 +796,14 @@ def add_validator_to_pool(params: AddValidatorToPoolParams) -> TransactionInstru
 
 
 def add_validator_to_pool_with_vote(
-    program_id: PublicKey,
-    stake_pool: PublicKey,
-    staker: PublicKey,
-    validator_list: PublicKey,
-    reserve_stake: PublicKey,
-    validator: PublicKey,
+    program_id: Pubkey,
+    stake_pool: Pubkey,
+    staker: Pubkey,
+    validator_list: Pubkey,
+    reserve_stake: Pubkey,
+    validator: Pubkey,
     validator_stake_seed: Optional[int],
-) -> TransactionInstruction:
+) -> Instruction:
     """Creates instruction to add a validator based on their vote account address."""
     (withdraw_authority, _seed) = find_withdraw_authority_program_address(program_id, stake_pool)
     (validator_stake, _seed) = find_stake_program_address(program_id, validator, stake_pool, validator_stake_seed)
@@ -817,21 +817,21 @@ def add_validator_to_pool_with_vote(
             validator_list=validator_list,
             validator_stake=validator_stake,
             validator_vote=validator,
-            rent_sysvar=SYSVAR_RENT_PUBKEY,
-            clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-            stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
+            rent_sysvar=RENT,
+            clock_sysvar=CLOCK,
+            stake_history_sysvar=STAKE_HISTORY,
             stake_config_sysvar=SYSVAR_STAKE_CONFIG_ID,
-            system_program_id=SYS_PROGRAM_ID,
+            system_program_id=SYSTEM_PROGRAM_ID,
             stake_program_id=STAKE_PROGRAM_ID,
             seed=validator_stake_seed,
         )
     )
 
 
-def remove_validator_from_pool(params: RemoveValidatorFromPoolParams) -> TransactionInstruction:
+def remove_validator_from_pool(params: RemoveValidatorFromPoolParams) -> Instruction:
     """Creates instruction to remove a validator from the pool."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
             AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -852,14 +852,14 @@ def remove_validator_from_pool(params: RemoveValidatorFromPoolParams) -> Transac
 
 
 def remove_validator_from_pool_with_vote(
-    program_id: PublicKey,
-    stake_pool: PublicKey,
-    staker: PublicKey,
-    validator_list: PublicKey,
-    validator: PublicKey,
+    program_id: Pubkey,
+    stake_pool: Pubkey,
+    staker: Pubkey,
+    validator_list: Pubkey,
+    validator: Pubkey,
     validator_stake_seed: Optional[int],
     transient_stake_seed: int,
-) -> TransactionInstruction:
+) -> Instruction:
     """Creates instruction to remove a validator based on their vote account address."""
     (withdraw_authority, seed) = find_withdraw_authority_program_address(program_id, stake_pool)
     (validator_stake, seed) = find_stake_program_address(program_id, validator, stake_pool, validator_stake_seed)
@@ -874,15 +874,15 @@ def remove_validator_from_pool_with_vote(
             validator_list=validator_list,
             validator_stake=validator_stake,
             transient_stake=transient_stake,
-            clock_sysvar=SYSVAR_CLOCK_PUBKEY,
+            clock_sysvar=CLOCK,
             stake_program_id=STAKE_PROGRAM_ID,
         )
     )
 
 
-def deposit_stake(params: DepositStakeParams) -> TransactionInstruction:
+def deposit_stake(params: DepositStakeParams) -> Instruction:
     """Creates a transaction instruction to deposit a stake account into a stake pool."""
-    keys = [
+    accounts = [
         AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
         AccountMeta(pubkey=params.validator_list, is_signer=False, is_writable=True),
         AccountMeta(pubkey=params.deposit_authority, is_signer=False, is_writable=False),
@@ -899,8 +899,8 @@ def deposit_stake(params: DepositStakeParams) -> TransactionInstruction:
         AccountMeta(pubkey=params.token_program_id, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.stake_program_id, is_signer=False, is_writable=False),
     ]
-    return TransactionInstruction(
-        keys=keys,
+    return Instruction(
+        accounts=accounts,
         program_id=params.program_id,
         data=INSTRUCTIONS_LAYOUT.build(
             dict(
@@ -911,10 +911,10 @@ def deposit_stake(params: DepositStakeParams) -> TransactionInstruction:
     )
 
 
-def withdraw_stake(params: WithdrawStakeParams) -> TransactionInstruction:
+def withdraw_stake(params: WithdrawStakeParams) -> Instruction:
     """Creates a transaction instruction to withdraw active stake from a stake pool."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
             AccountMeta(pubkey=params.validator_list, is_signer=False, is_writable=True),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -939,9 +939,9 @@ def withdraw_stake(params: WithdrawStakeParams) -> TransactionInstruction:
     )
 
 
-def deposit_sol(params: DepositSolParams) -> TransactionInstruction:
+def deposit_sol(params: DepositSolParams) -> Instruction:
     """Creates a transaction instruction to deposit SOL into a stake pool."""
-    keys = [
+    accounts = [
         AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
         AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.reserve_stake, is_signer=False, is_writable=True),
@@ -954,9 +954,9 @@ def deposit_sol(params: DepositSolParams) -> TransactionInstruction:
         AccountMeta(pubkey=params.token_program_id, is_signer=False, is_writable=False),
     ]
     if params.deposit_authority:
-        keys.append(AccountMeta(pubkey=params.deposit_authority, is_signer=True, is_writable=False))
-    return TransactionInstruction(
-        keys=keys,
+        accounts.append(AccountMeta(pubkey=params.deposit_authority, is_signer=True, is_writable=False))
+    return Instruction(
+        accounts=accounts,
         program_id=params.program_id,
         data=INSTRUCTIONS_LAYOUT.build(
             dict(
@@ -967,9 +967,9 @@ def deposit_sol(params: DepositSolParams) -> TransactionInstruction:
     )
 
 
-def withdraw_sol(params: WithdrawSolParams) -> TransactionInstruction:
+def withdraw_sol(params: WithdrawSolParams) -> Instruction:
     """Creates a transaction instruction to withdraw SOL from a stake pool."""
-    keys = [
+    accounts = [
         AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
         AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.source_transfer_authority, is_signer=True, is_writable=False),
@@ -987,8 +987,8 @@ def withdraw_sol(params: WithdrawSolParams) -> TransactionInstruction:
     if params.sol_withdraw_authority:
         AccountMeta(pubkey=params.sol_withdraw_authority, is_signer=True, is_writable=False)
 
-    return TransactionInstruction(
-        keys=keys,
+    return Instruction(
+        accounts=accounts,
         program_id=params.program_id,
         data=INSTRUCTIONS_LAYOUT.build(
             dict(
@@ -999,9 +999,9 @@ def withdraw_sol(params: WithdrawSolParams) -> TransactionInstruction:
     )
 
 
-def update_validator_list_balance(params: UpdateValidatorListBalanceParams) -> TransactionInstruction:
+def update_validator_list_balance(params: UpdateValidatorListBalanceParams) -> Instruction:
     """Creates instruction to update a set of validators in the stake pool."""
-    keys = [
+    accounts = [
         AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.validator_list, is_signer=False, is_writable=True),
@@ -1010,12 +1010,12 @@ def update_validator_list_balance(params: UpdateValidatorListBalanceParams) -> T
         AccountMeta(pubkey=params.stake_history_sysvar, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.stake_program_id, is_signer=False, is_writable=False),
     ]
-    keys.extend([
+    accounts.extend([
         AccountMeta(pubkey=pubkey, is_signer=False, is_writable=True)
         for pubkey in params.validator_and_transient_stake_pairs
     ])
-    return TransactionInstruction(
-        keys=keys,
+    return Instruction(
+        accounts=accounts,
         program_id=params.program_id,
         data=INSTRUCTIONS_LAYOUT.build(
             dict(
@@ -1026,10 +1026,10 @@ def update_validator_list_balance(params: UpdateValidatorListBalanceParams) -> T
     )
 
 
-def update_stake_pool_balance(params: UpdateStakePoolBalanceParams) -> TransactionInstruction:
+def update_stake_pool_balance(params: UpdateStakePoolBalanceParams) -> Instruction:
     """Creates instruction to update the overall stake pool balance."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=True),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.validator_list, is_signer=False, is_writable=True),
@@ -1048,10 +1048,10 @@ def update_stake_pool_balance(params: UpdateStakePoolBalanceParams) -> Transacti
     )
 
 
-def cleanup_removed_validator_entries(params: CleanupRemovedValidatorEntriesParams) -> TransactionInstruction:
+def cleanup_removed_validator_entries(params: CleanupRemovedValidatorEntriesParams) -> Instruction:
     """Creates instruction to cleanup removed validator entries."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.validator_list, is_signer=False, is_writable=True),
         ],
@@ -1065,10 +1065,10 @@ def cleanup_removed_validator_entries(params: CleanupRemovedValidatorEntriesPara
     )
 
 
-def increase_validator_stake(params: IncreaseValidatorStakeParams) -> TransactionInstruction:
+def increase_validator_stake(params: IncreaseValidatorStakeParams) -> Instruction:
     """Creates instruction to increase the stake on a validator."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -1099,11 +1099,11 @@ def increase_validator_stake(params: IncreaseValidatorStakeParams) -> Transactio
 
 def increase_additional_validator_stake(
     params: IncreaseAdditionalValidatorStakeParams,
-  ) -> TransactionInstruction:
+  ) -> Instruction:
 
     """Creates `IncreaseAdditionalValidatorStake` instruction (rebalance from reserve account to transient account)"""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -1133,10 +1133,10 @@ def increase_additional_validator_stake(
     )
 
 
-def decrease_validator_stake(params: DecreaseValidatorStakeParams) -> TransactionInstruction:
+def decrease_validator_stake(params: DecreaseValidatorStakeParams) -> Instruction:
     """Creates instruction to decrease the stake on a validator."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -1161,11 +1161,11 @@ def decrease_validator_stake(params: DecreaseValidatorStakeParams) -> Transactio
     )
 
 
-def decrease_additional_validator_stake(params: DecreaseAdditionalValidatorStakeParams) -> TransactionInstruction:
+def decrease_additional_validator_stake(params: DecreaseAdditionalValidatorStakeParams) -> Instruction:
     """ Creates `DecreaseAdditionalValidatorStake` instruction (rebalance from validator account to
     transient account)."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -1193,10 +1193,10 @@ def decrease_additional_validator_stake(params: DecreaseAdditionalValidatorStake
     )
 
 
-def decrease_validator_stake_with_reserve(params: DecreaseValidatorStakeWithReserveParams) -> TransactionInstruction:
+def decrease_validator_stake_with_reserve(params: DecreaseValidatorStakeWithReserveParams) -> Instruction:
     """Creates instruction to decrease the stake on a validator."""
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        accounts=[
             AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
             AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -1222,10 +1222,10 @@ def decrease_validator_stake_with_reserve(params: DecreaseValidatorStakeWithRese
     )
 
 
-def create_token_metadata(params: CreateTokenMetadataParams) -> TransactionInstruction:
+def create_token_metadata(params: CreateTokenMetadataParams) -> Instruction:
     """Creates an instruction to create metadata using the mpl token metadata program for the pool token."""
 
-    keys = [
+    accounts = [
         AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.manager, is_signer=True, is_writable=False),
         AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
@@ -1235,8 +1235,8 @@ def create_token_metadata(params: CreateTokenMetadataParams) -> TransactionInstr
         AccountMeta(pubkey=params.metadata_program_id, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.system_program_id, is_signer=False, is_writable=False),
     ]
-    return TransactionInstruction(
-        keys=keys,
+    return Instruction(
+        accounts=accounts,
         program_id=params.program_id,
         data=INSTRUCTIONS_LAYOUT.build(
             dict(
@@ -1251,18 +1251,18 @@ def create_token_metadata(params: CreateTokenMetadataParams) -> TransactionInstr
     )
 
 
-def update_token_metadata(params: UpdateTokenMetadataParams) -> TransactionInstruction:
+def update_token_metadata(params: UpdateTokenMetadataParams) -> Instruction:
     """Creates an instruction to update metadata in the mpl token metadata program account for the pool token."""
 
-    keys = [
+    accounts = [
         AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.manager, is_signer=True, is_writable=False),
         AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
         AccountMeta(pubkey=params.token_metadata, is_signer=False, is_writable=True),
         AccountMeta(pubkey=params.metadata_program_id, is_signer=False, is_writable=False)
     ]
-    return TransactionInstruction(
-        keys=keys,
+    return Instruction(
+        accounts=accounts,
         program_id=params.program_id,
         data=INSTRUCTIONS_LAYOUT.build(
             dict(
diff --git a/stake-pool/py/stake_pool/state.py b/stake-pool/py/stake_pool/state.py
index 36be8a11d..b0bc5cbcb 100644
--- a/stake-pool/py/stake_pool/state.py
+++ b/stake-pool/py/stake_pool/state.py
@@ -4,16 +4,15 @@ from enum import IntEnum
 from typing import List, NamedTuple, Optional
 from construct import Bytes, Container, Struct, Switch, Int8ul, Int32ul, Int64ul, Pass  # type: ignore
 
-from solana.publickey import PublicKey
-from solana.utils.helpers import decode_byte_string
+from solders.pubkey import Pubkey
 from stake.state import Lockup, LOCKUP_LAYOUT
 
 PUBLIC_KEY_LAYOUT = Bytes(32)
 
 
-def decode_optional_publickey(container: Container) -> Optional[PublicKey]:
+def decode_optional_publickey(container: Container) -> Optional[Pubkey]:
     if container:
-        return PublicKey(container.popitem()[1])
+        return Pubkey(container.popitem()[1])
     else:
         return None
 
@@ -40,50 +39,49 @@ class Fee(NamedTuple):
 
 class StakePool(NamedTuple):
     """Stake pool and all its data."""
-    manager: PublicKey
-    staker: PublicKey
-    stake_deposit_authority: PublicKey
+    manager: Pubkey
+    staker: Pubkey
+    stake_deposit_authority: Pubkey
     stake_withdraw_bump_seed: int
-    validator_list: PublicKey
-    reserve_stake: PublicKey
-    pool_mint: PublicKey
-    manager_fee_account: PublicKey
-    token_program_id: PublicKey
+    validator_list: Pubkey
+    reserve_stake: Pubkey
+    pool_mint: Pubkey
+    manager_fee_account: Pubkey
+    token_program_id: Pubkey
     total_lamports: int
     pool_token_supply: int
     last_update_epoch: int
     lockup: Lockup
     epoch_fee: Fee
     next_epoch_fee: Optional[Fee]
-    preferred_deposit_validator: Optional[PublicKey]
-    preferred_withdraw_validator: Optional[PublicKey]
+    preferred_deposit_validator: Optional[Pubkey]
+    preferred_withdraw_validator: Optional[Pubkey]
     stake_deposit_fee: Fee
     stake_withdrawal_fee: Fee
     next_stake_withdrawal_fee: Optional[Fee]
     stake_referral_fee: int
-    sol_deposit_authority: Optional[PublicKey]
+    sol_deposit_authority: Optional[Pubkey]
     sol_deposit_fee: Fee
     sol_referral_fee: int
-    sol_withdraw_authority: Optional[PublicKey]
+    sol_withdraw_authority: Optional[Pubkey]
     sol_withdrawal_fee: Fee
     next_sol_withdrawal_fee: Optional[Fee]
     last_epoch_pool_token_supply: int
     last_epoch_total_lamports: int
 
     @classmethod
-    def decode(cls, data: str, encoding: str):
-        data_bytes = decode_byte_string(data, encoding)
-        parsed = DECODE_STAKE_POOL_LAYOUT.parse(data_bytes)
+    def decode(cls, data: bytes):
+        parsed = DECODE_STAKE_POOL_LAYOUT.parse(data)
         return StakePool(
-            manager=PublicKey(parsed['manager']),
-            staker=PublicKey(parsed['staker']),
-            stake_deposit_authority=PublicKey(parsed['stake_deposit_authority']),
+            manager=Pubkey(parsed['manager']),
+            staker=Pubkey(parsed['staker']),
+            stake_deposit_authority=Pubkey(parsed['stake_deposit_authority']),
             stake_withdraw_bump_seed=parsed['stake_withdraw_bump_seed'],
-            validator_list=PublicKey(parsed['validator_list']),
-            reserve_stake=PublicKey(parsed['reserve_stake']),
-            pool_mint=PublicKey(parsed['pool_mint']),
-            manager_fee_account=PublicKey(parsed['manager_fee_account']),
-            token_program_id=PublicKey(parsed['token_program_id']),
+            validator_list=Pubkey(parsed['validator_list']),
+            reserve_stake=Pubkey(parsed['reserve_stake']),
+            pool_mint=Pubkey(parsed['pool_mint']),
+            manager_fee_account=Pubkey(parsed['manager_fee_account']),
+            token_program_id=Pubkey(parsed['token_program_id']),
             total_lamports=parsed['total_lamports'],
             pool_token_supply=parsed['pool_token_supply'],
             last_update_epoch=parsed['last_update_epoch'],
@@ -144,7 +142,7 @@ class ValidatorStakeInfo(NamedTuple):
     status: StakeStatus
     """Status of the validator stake account."""
 
-    vote_account_address: PublicKey
+    vote_account_address: Pubkey
     """Validator vote account address."""
 
     @classmethod
@@ -157,7 +155,7 @@ class ValidatorStakeInfo(NamedTuple):
             unused=container['unused'],
             validator_seed_suffix=container['validator_seed_suffix'],
             status=container['status'],
-            vote_account_address=PublicKey(container['vote_account_address']),
+            vote_account_address=Pubkey(container['vote_account_address']),
         )
 
 
@@ -176,9 +174,8 @@ class ValidatorList(NamedTuple):
         return layout.sizeof()
 
     @classmethod
-    def decode(cls, data: str, encoding: str):
-        data_bytes = decode_byte_string(data, encoding)
-        parsed = DECODE_VALIDATOR_LIST_LAYOUT.parse(data_bytes)
+    def decode(cls, data: bytes):
+        parsed = DECODE_VALIDATOR_LIST_LAYOUT.parse(data)
         return ValidatorList(
             max_validators=parsed['max_validators'],
             validators=[ValidatorStakeInfo.decode_container(container) for container in parsed['validators']],
diff --git a/stake-pool/py/system/actions.py b/stake-pool/py/system/actions.py
index 0b16a0458..c4c025494 100644
--- a/stake-pool/py/system/actions.py
+++ b/stake-pool/py/system/actions.py
@@ -1,9 +1,8 @@
-from solana.publickey import PublicKey
+from solders.pubkey import Pubkey
 from solana.rpc.async_api import AsyncClient
-from solana.rpc.commitment import Confirmed
 
 
-async def airdrop(client: AsyncClient, receiver: PublicKey, lamports: int):
+async def airdrop(client: AsyncClient, receiver: Pubkey, lamports: int):
     print(f"Airdropping {lamports} lamports to {receiver}...")
-    resp = await client.request_airdrop(receiver, lamports, Confirmed)
-    await client.confirm_transaction(resp['result'], Confirmed)
+    resp = await client.request_airdrop(receiver, lamports)
+    await client.confirm_transaction(resp.value)
diff --git a/stake-pool/py/vote/actions.py b/stake-pool/py/vote/actions.py
index 9f3fc49f1..305d79a4c 100644
--- a/stake-pool/py/vote/actions.py
+++ b/stake-pool/py/vote/actions.py
@@ -1,11 +1,11 @@
-from solana.publickey import PublicKey
-from solana.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.keypair import Keypair
 from solana.rpc.async_api import AsyncClient
 from solana.rpc.commitment import Confirmed
 from solana.rpc.types import TxOpts
-from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY
+from solders.sysvar import CLOCK, RENT
 from solana.transaction import Transaction
-import solana.system_program as sys
+import solders.system_program as sys
 
 from vote.constants import VOTE_PROGRAM_ID, VOTE_STATE_LEN
 from vote.instructions import initialize, InitializeParams
@@ -13,33 +13,35 @@ from vote.instructions import initialize, InitializeParams
 
 async def create_vote(
         client: AsyncClient, payer: Keypair, vote: Keypair, node: Keypair,
-        voter: PublicKey, withdrawer: PublicKey, commission: int):
-    print(f"Creating vote account {vote.public_key}")
+        voter: Pubkey, withdrawer: Pubkey, commission: int):
+    print(f"Creating vote account {vote.pubkey()}")
     resp = await client.get_minimum_balance_for_rent_exemption(VOTE_STATE_LEN)
-    txn = Transaction()
+    txn = Transaction(fee_payer=payer.pubkey())
     txn.add(
         sys.create_account(
             sys.CreateAccountParams(
-                from_pubkey=payer.public_key,
-                new_account_pubkey=vote.public_key,
-                lamports=resp['result'],
+                from_pubkey=payer.pubkey(),
+                to_pubkey=vote.pubkey(),
+                lamports=resp.value,
                 space=VOTE_STATE_LEN,
-                program_id=VOTE_PROGRAM_ID,
+                owner=VOTE_PROGRAM_ID,
             )
         )
     )
     txn.add(
         initialize(
             InitializeParams(
-                vote=vote.public_key,
-                rent_sysvar=SYSVAR_RENT_PUBKEY,
-                clock_sysvar=SYSVAR_CLOCK_PUBKEY,
-                node=node.public_key,
+                vote=vote.pubkey(),
+                rent_sysvar=RENT,
+                clock_sysvar=CLOCK,
+                node=node.pubkey(),
                 authorized_voter=voter,
                 authorized_withdrawer=withdrawer,
                 commission=commission,
             )
         )
     )
+    recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
     await client.send_transaction(
-        txn, payer, vote, node, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
+        txn, payer, vote, node, recent_blockhash=recent_blockhash,
+        opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
diff --git a/stake-pool/py/vote/constants.py b/stake-pool/py/vote/constants.py
index 701c90a02..0da3846be 100644
--- a/stake-pool/py/vote/constants.py
+++ b/stake-pool/py/vote/constants.py
@@ -1,7 +1,7 @@
-from solana.publickey import PublicKey
+from solders.pubkey import Pubkey
 
 
-VOTE_PROGRAM_ID = PublicKey("Vote111111111111111111111111111111111111111")
+VOTE_PROGRAM_ID = Pubkey.from_string("Vote111111111111111111111111111111111111111")
 """Program id for the native vote program."""
 
 VOTE_STATE_LEN: int = 3762
diff --git a/stake-pool/py/vote/instructions.py b/stake-pool/py/vote/instructions.py
index 267aeb4aa..c8a0a69d8 100644
--- a/stake-pool/py/vote/instructions.py
+++ b/stake-pool/py/vote/instructions.py
@@ -5,9 +5,9 @@ from typing import NamedTuple
 
 from construct import Bytes, Struct, Switch, Int8ul, Int32ul, Pass  # type: ignore
 
-from solana.publickey import PublicKey
-from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY
-from solana.transaction import AccountMeta, TransactionInstruction
+from solders.pubkey import Pubkey
+from solders.sysvar import CLOCK, RENT
+from solders.instruction import AccountMeta, Instruction
 
 from vote.constants import VOTE_PROGRAM_ID
 
@@ -17,18 +17,18 @@ PUBLIC_KEY_LAYOUT = Bytes(32)
 class InitializeParams(NamedTuple):
     """Initialize vote account params."""
 
-    vote: PublicKey
+    vote: Pubkey
     """`[w]` Uninitialized vote account"""
-    rent_sysvar: PublicKey
+    rent_sysvar: Pubkey
     """`[]` Rent sysvar."""
-    clock_sysvar: PublicKey
+    clock_sysvar: Pubkey
     """`[]` Clock sysvar."""
-    node: PublicKey
+    node: Pubkey
     """`[s]` New validator identity."""
 
-    authorized_voter: PublicKey
+    authorized_voter: Pubkey
     """The authorized voter for this vote account."""
-    authorized_withdrawer: PublicKey
+    authorized_withdrawer: Pubkey
     """The authorized withdrawer for this vote account."""
     commission: int
     """Commission, represented as a percentage"""
@@ -73,7 +73,7 @@ INSTRUCTIONS_LAYOUT = Struct(
 )
 
 
-def initialize(params: InitializeParams) -> TransactionInstruction:
+def initialize(params: InitializeParams) -> Instruction:
     """Creates a transaction instruction to initialize a new stake."""
     data = INSTRUCTIONS_LAYOUT.build(
         dict(
@@ -86,13 +86,13 @@ def initialize(params: InitializeParams) -> TransactionInstruction:
             ),
         )
     )
-    return TransactionInstruction(
-        keys=[
+    return Instruction(
+        program_id=VOTE_PROGRAM_ID,
+        accounts=[
             AccountMeta(pubkey=params.vote, is_signer=False, is_writable=True),
-            AccountMeta(pubkey=params.rent_sysvar or SYSVAR_RENT_PUBKEY, is_signer=False, is_writable=False),
-            AccountMeta(pubkey=params.clock_sysvar or SYSVAR_CLOCK_PUBKEY, is_signer=False, is_writable=False),
+            AccountMeta(pubkey=params.rent_sysvar or RENT, is_signer=False, is_writable=False),
+            AccountMeta(pubkey=params.clock_sysvar or CLOCK, is_signer=False, is_writable=False),
             AccountMeta(pubkey=params.node, is_signer=True, is_writable=False),
         ],
-        program_id=VOTE_PROGRAM_ID,
         data=data,
     )


Test patch:
diff --git a/stake-pool/py/tests/conftest.py b/stake-pool/py/tests/conftest.py
index 242126788..647e9594f 100644
--- a/stake-pool/py/tests/conftest.py
+++ b/stake-pool/py/tests/conftest.py
@@ -7,8 +7,8 @@ import tempfile
 from typing import AsyncIterator, List, Tuple
 from subprocess import Popen
 
-from solana.keypair import Keypair
-from solana.publickey import PublicKey
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
 from solana.rpc.async_api import AsyncClient
 from solana.rpc.commitment import Confirmed
 
@@ -44,29 +44,28 @@ def solana_test_validator():
 
 
 @pytest_asyncio.fixture
-async def validators(async_client, payer) -> List[PublicKey]:
+async def validators(async_client, payer) -> List[Pubkey]:
     num_validators = 3
     validators = []
     for i in range(num_validators):
         vote = Keypair()
         node = Keypair()
-        await create_vote(async_client, payer, vote, node, payer.public_key, payer.public_key, 10)
-        validators.append(vote.public_key)
+        await create_vote(async_client, payer, vote, node, payer.pubkey(), payer.pubkey(), 10)
+        validators.append(vote.pubkey())
     return validators
 
 
 @pytest_asyncio.fixture
 async def stake_pool_addresses(
     async_client, payer, validators, waiter
-) -> Tuple[PublicKey, PublicKey, PublicKey]:
+) -> Tuple[Pubkey, Pubkey, Pubkey]:
     fee = Fee(numerator=1, denominator=1000)
     referral_fee = 20
-    # Change back to `wait_for_next_epoch_if_soon` once https://github.com/solana-labs/solana/pull/26851 is available
-    await waiter.wait_for_next_epoch(async_client)
+    await waiter.wait_for_next_epoch_if_soon(async_client)
     stake_pool_addresses = await create_all(async_client, payer, fee, referral_fee)
     stake_pool = stake_pool_addresses[0]
     pool_mint = stake_pool_addresses[2]
-    token_account = get_associated_token_address(payer.public_key, pool_mint)
+    token_account = get_associated_token_address(payer.pubkey(), pool_mint)
     await deposit_sol(async_client, payer, stake_pool, token_account, AIRDROP_LAMPORTS // 2)
     for validator in validators:
         await add_validator_to_pool(async_client, payer, stake_pool, validator)
@@ -91,7 +90,7 @@ async def async_client(solana_test_validator) -> AsyncIterator[AsyncClient]:
 @pytest_asyncio.fixture
 async def payer(async_client) -> Keypair:
     payer = Keypair()
-    await airdrop(async_client, payer.public_key, AIRDROP_LAMPORTS)
+    await airdrop(async_client, payer.pubkey(), AIRDROP_LAMPORTS)
     return payer
 
 
@@ -99,17 +98,18 @@ class Waiter:
     @staticmethod
     async def wait_for_next_epoch(async_client: AsyncClient):
         resp = await async_client.get_epoch_info(commitment=Confirmed)
-        current_epoch = resp['result']['epoch']
+        current_epoch = resp.value.epoch
         next_epoch = current_epoch
         while current_epoch == next_epoch:
             await asyncio.sleep(1.0)
             resp = await async_client.get_epoch_info(commitment=Confirmed)
-            next_epoch = resp['result']['epoch']
+            next_epoch = resp.value.epoch
+        await asyncio.sleep(0.4)  # wait one more block to avoid reward payout time
 
     @staticmethod
     async def wait_for_next_epoch_if_soon(async_client: AsyncClient):
         resp = await async_client.get_epoch_info(commitment=Confirmed)
-        if resp['result']['slotsInEpoch'] - resp['result']['slotIndex'] < NUM_SLOTS_PER_EPOCH // 2:
+        if resp.value.slots_in_epoch - resp.value.slot_index < NUM_SLOTS_PER_EPOCH // 2:
             await Waiter.wait_for_next_epoch(async_client)
             return True
         else:
diff --git a/stake-pool/py/tests/test_a_time_sensitive.py b/stake-pool/py/tests/test_a_time_sensitive.py
index 682d1202b..59e59e9e8 100644
--- a/stake-pool/py/tests/test_a_time_sensitive.py
+++ b/stake-pool/py/tests/test_a_time_sensitive.py
@@ -15,16 +15,16 @@ async def test_increase_decrease_this_is_very_slow(async_client, validators, pay
     (stake_pool_address, validator_list_address, _) = stake_pool_addresses
 
     resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
-    stake_rent_exemption = resp['result']
+    stake_rent_exemption = resp.value
     minimum_amount = MINIMUM_ACTIVE_STAKE + stake_rent_exemption
     increase_amount = MINIMUM_ACTIVE_STAKE * 4
     decrease_amount = increase_amount // 2
     deposit_amount = (increase_amount + stake_rent_exemption) * len(validators)
 
     resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
-    token_account = get_associated_token_address(payer.public_key, stake_pool.pool_mint)
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
+    token_account = get_associated_token_address(payer.pubkey(), stake_pool.pool_mint)
     await deposit_sol(async_client, payer, stake_pool_address, token_account, deposit_amount)
 
     # increase to all
@@ -36,8 +36,8 @@ async def test_increase_decrease_this_is_very_slow(async_client, validators, pay
 
     # validate the increase is now on the transient account
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.transient_stake_lamports == increase_amount // 2 + stake_rent_exemption
         assert validator.active_stake_lamports == minimum_amount
@@ -52,8 +52,8 @@ async def test_increase_decrease_this_is_very_slow(async_client, validators, pay
 
     # validate the additional increase is now on the transient account
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.transient_stake_lamports == increase_amount + stake_rent_exemption * 2
         assert validator.active_stake_lamports == minimum_amount
@@ -63,8 +63,8 @@ async def test_increase_decrease_this_is_very_slow(async_client, validators, pay
     await update_stake_pool(async_client, payer, stake_pool_address)
 
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.last_update_epoch != 0
         assert validator.transient_stake_lamports == 0
@@ -79,8 +79,8 @@ async def test_increase_decrease_this_is_very_slow(async_client, validators, pay
 
     # validate the decrease is now on the transient account
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.transient_stake_lamports == decrease_amount + stake_rent_exemption
         assert validator.active_stake_lamports == increase_amount - decrease_amount + minimum_amount + \
@@ -96,8 +96,8 @@ async def test_increase_decrease_this_is_very_slow(async_client, validators, pay
     await update_stake_pool(async_client, payer, stake_pool_address)
 
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.transient_stake_lamports == 0
         assert validator.active_stake_lamports == expected_active_stake_lamports
diff --git a/stake-pool/py/tests/test_add_remove.py b/stake-pool/py/tests/test_add_remove.py
index b2d96af39..abf47871e 100644
--- a/stake-pool/py/tests/test_add_remove.py
+++ b/stake-pool/py/tests/test_add_remove.py
@@ -12,11 +12,11 @@ from stake_pool.state import ValidatorList, StakeStatus
 async def test_add_remove_validators(async_client, validators, payer, stake_pool_addresses):
     (stake_pool_address, validator_list_address, _) = stake_pool_addresses
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     assert len(validator_list.validators) == len(validators)
     resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
-    stake_rent_exemption = resp['result']
+    stake_rent_exemption = resp.value
     futures = []
     for validator_info in validator_list.validators:
         assert validator_info.vote_account_address in validators
@@ -29,7 +29,7 @@ async def test_add_remove_validators(async_client, validators, payer, stake_pool
     await asyncio.gather(*futures)
 
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator_info in validator_list.validators:
         assert validator_info.status == StakeStatus.DEACTIVATING_VALIDATOR
diff --git a/stake-pool/py/tests/test_bot_rebalance.py b/stake-pool/py/tests/test_bot_rebalance.py
index c0283ef5f..c7da3f825 100644
--- a/stake-pool/py/tests/test_bot_rebalance.py
+++ b/stake-pool/py/tests/test_bot_rebalance.py
@@ -18,7 +18,7 @@ ENDPOINT: str = "http://127.0.0.1:8899"
 async def test_rebalance_this_is_very_slow(async_client, validators, payer, stake_pool_addresses, waiter):
     (stake_pool_address, validator_list_address, _) = stake_pool_addresses
     resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
-    stake_rent_exemption = resp['result']
+    stake_rent_exemption = resp.value
     # With minimum delegation at MINIMUM_DELEGATION + rent-exemption, when
     # decreasing, we'll need rent exemption + minimum delegation delegated to
     # cover all movements
@@ -27,10 +27,10 @@ async def test_rebalance_this_is_very_slow(async_client, validators, payer, stak
     deposit_amount = (increase_amount + stake_rent_exemption) * len(validators)
 
     resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
     total_lamports = stake_pool.total_lamports + deposit_amount
-    token_account = get_associated_token_address(payer.public_key, stake_pool.pool_mint)
+    token_account = get_associated_token_address(payer.pubkey(), stake_pool.pool_mint)
     await deposit_sol(async_client, payer, stake_pool_address, token_account, deposit_amount)
 
     # Test case 1: Increase everywhere
@@ -38,12 +38,12 @@ async def test_rebalance_this_is_very_slow(async_client, validators, payer, stak
 
     # should only have minimum left
     resp = await async_client.get_account_info(stake_pool.reserve_stake, commitment=Confirmed)
-    assert resp['result']['value']['lamports'] == stake_rent_exemption + MINIMUM_RESERVE_LAMPORTS
+    assert resp.value.lamports == stake_rent_exemption + MINIMUM_RESERVE_LAMPORTS
 
     # should all be the same
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.active_stake_lamports == minimum_amount
         assert validator.transient_stake_lamports == total_lamports / len(validators) - minimum_amount
@@ -56,13 +56,13 @@ async def test_rebalance_this_is_very_slow(async_client, validators, payer, stak
 
     # should still only have minimum left
     resp = await async_client.get_account_info(stake_pool.reserve_stake, commitment=Confirmed)
-    reserve_lamports = resp['result']['value']['lamports']
+    reserve_lamports = resp.value.lamports
     assert reserve_lamports == stake_rent_exemption + MINIMUM_RESERVE_LAMPORTS
 
     # should all be decreasing now
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.active_stake_lamports == minimum_amount
         assert validator.transient_stake_lamports == max_in_reserve / len(validators)
@@ -74,13 +74,13 @@ async def test_rebalance_this_is_very_slow(async_client, validators, payer, stak
 
     # should still only have minimum left + rent exemptions from increase
     resp = await async_client.get_account_info(stake_pool.reserve_stake, commitment=Confirmed)
-    reserve_lamports = resp['result']['value']['lamports']
+    reserve_lamports = resp.value.lamports
     assert reserve_lamports == stake_rent_exemption + max_in_reserve + MINIMUM_RESERVE_LAMPORTS
 
     # should all be decreased now
     resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    validator_list = ValidatorList.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    validator_list = ValidatorList.decode(data)
     for validator in validator_list.validators:
         assert validator.active_stake_lamports == minimum_amount
         assert validator.transient_stake_lamports == 0
diff --git a/stake-pool/py/tests/test_create.py b/stake-pool/py/tests/test_create.py
index 97600ae39..3b5a42a18 100644
--- a/stake-pool/py/tests/test_create.py
+++ b/stake-pool/py/tests/test_create.py
@@ -1,5 +1,5 @@
 import pytest
-from solana.keypair import Keypair
+from solders.keypair import Keypair
 from solana.rpc.commitment import Confirmed
 from spl.token.constants import TOKEN_PROGRAM_ID
 
@@ -19,7 +19,7 @@ async def test_create_stake_pool(async_client, payer):
     stake_pool = Keypair()
     validator_list = Keypair()
     (pool_withdraw_authority, seed) = find_withdraw_authority_program_address(
-        STAKE_POOL_PROGRAM_ID, stake_pool.public_key)
+        STAKE_POOL_PROGRAM_ID, stake_pool.pubkey())
 
     reserve_stake = Keypair()
     await create_stake(async_client, payer, reserve_stake, pool_withdraw_authority, MINIMUM_RESERVE_LAMPORTS)
@@ -30,25 +30,25 @@ async def test_create_stake_pool(async_client, payer):
     manager_fee_account = await create_associated_token_account(
         async_client,
         payer,
-        payer.public_key,
-        pool_mint.public_key,
+        payer.pubkey(),
+        pool_mint.pubkey(),
     )
 
     fee = Fee(numerator=1, denominator=1000)
     referral_fee = 20
     await create(
-        async_client, payer, stake_pool, validator_list, pool_mint.public_key,
-        reserve_stake.public_key, manager_fee_account, fee, referral_fee)
-    resp = await async_client.get_account_info(stake_pool.public_key, commitment=Confirmed)
-    assert resp['result']['value']['owner'] == str(STAKE_POOL_PROGRAM_ID)
-    data = resp['result']['value']['data']
-    pool_data = StakePool.decode(data[0], data[1])
-    assert pool_data.manager == payer.public_key
-    assert pool_data.staker == payer.public_key
+        async_client, payer, stake_pool, validator_list, pool_mint.pubkey(),
+        reserve_stake.pubkey(), manager_fee_account, fee, referral_fee)
+    resp = await async_client.get_account_info(stake_pool.pubkey(), commitment=Confirmed)
+    assert resp.value.owner == STAKE_POOL_PROGRAM_ID
+    data = resp.value.data if resp.value else bytes()
+    pool_data = StakePool.decode(data)
+    assert pool_data.manager == payer.pubkey()
+    assert pool_data.staker == payer.pubkey()
     assert pool_data.stake_withdraw_bump_seed == seed
-    assert pool_data.validator_list == validator_list.public_key
-    assert pool_data.reserve_stake == reserve_stake.public_key
-    assert pool_data.pool_mint == pool_mint.public_key
+    assert pool_data.validator_list == validator_list.pubkey()
+    assert pool_data.reserve_stake == reserve_stake.pubkey()
+    assert pool_data.pool_mint == pool_mint.pubkey()
     assert pool_data.manager_fee_account == manager_fee_account
     assert pool_data.token_program_id == TOKEN_PROGRAM_ID
     assert pool_data.total_lamports == 0
diff --git a/stake-pool/py/tests/test_create_update_token_metadata.py b/stake-pool/py/tests/test_create_update_token_metadata.py
index 10ae24f69..2ee0a7db2 100644
--- a/stake-pool/py/tests/test_create_update_token_metadata.py
+++ b/stake-pool/py/tests/test_create_update_token_metadata.py
@@ -2,20 +2,18 @@ import pytest
 from stake_pool.actions import create_all, create_token_metadata, update_token_metadata
 from stake_pool.state import Fee, StakePool
 from solana.rpc.commitment import Confirmed
-from solana.rpc.async_api import AsyncClient
-from solana.keypair import Keypair
 from stake_pool.constants import find_metadata_account
-from solana.utils.helpers import decode_byte_string
 
 
 @pytest.mark.asyncio
-async def test_create_metadata_success(async_client: AsyncClient, payer: Keypair):
+async def test_create_metadata_success(async_client, waiter, payer):
     fee = Fee(numerator=1, denominator=1000)
     referral_fee = 20
+    await waiter.wait_for_next_epoch_if_soon(async_client)
     (stake_pool_address, _validator_list_address, _) = await create_all(async_client, payer, fee, referral_fee)
     resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     name = "test_name"
     symbol = "SYM"
@@ -24,21 +22,21 @@ async def test_create_metadata_success(async_client: AsyncClient, payer: Keypair
 
     (metadata_program_address, _seed) = find_metadata_account(stake_pool.pool_mint)
     resp = await async_client.get_account_info(metadata_program_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    raw_data = decode_byte_string(data[0], data[1])
+    raw_data = resp.value.data if resp.value else bytes()
     assert name == str(raw_data[69:101], "utf-8")[:len(name)]
     assert symbol == str(raw_data[105:115], "utf-8")[:len(symbol)]
     assert uri == str(raw_data[119:319], "utf-8")[:len(uri)]
 
 
 @pytest.mark.asyncio
-async def test_update_metadata_success(async_client: AsyncClient, payer: Keypair):
+async def test_update_metadata_success(async_client, waiter, payer):
     fee = Fee(numerator=1, denominator=1000)
     referral_fee = 20
+    await waiter.wait_for_next_epoch_if_soon(async_client)
     (stake_pool_address, _validator_list_address, _) = await create_all(async_client, payer, fee, referral_fee)
     resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
 
     name = "test_name"
     symbol = "SYM"
@@ -47,8 +45,7 @@ async def test_update_metadata_success(async_client: AsyncClient, payer: Keypair
 
     (metadata_program_address, _seed) = find_metadata_account(stake_pool.pool_mint)
     resp = await async_client.get_account_info(metadata_program_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    raw_data = decode_byte_string(data[0], data[1])
+    raw_data = resp.value.data if resp.value else bytes()
     assert name == str(raw_data[69:101], "utf-8")[:len(name)]
     assert symbol == str(raw_data[105:115], "utf-8")[:len(symbol)]
     assert uri == str(raw_data[119:319], "utf-8")[:len(uri)]
@@ -60,8 +57,7 @@ async def test_update_metadata_success(async_client: AsyncClient, payer: Keypair
 
     (metadata_program_address, _seed) = find_metadata_account(stake_pool.pool_mint)
     resp = await async_client.get_account_info(metadata_program_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    raw_data = decode_byte_string(data[0], data[1])
+    raw_data = resp.value.data if resp.value else bytes()
     assert updated_name == str(raw_data[69:101], "utf-8")[:len(updated_name)]
     assert updated_symbol == str(raw_data[105:115], "utf-8")[:len(updated_symbol)]
     assert updated_uri == str(raw_data[119:319], "utf-8")[:len(updated_uri)]
diff --git a/stake-pool/py/tests/test_deposit_withdraw_sol.py b/stake-pool/py/tests/test_deposit_withdraw_sol.py
index 8057101e3..438c4afd2 100644
--- a/stake-pool/py/tests/test_deposit_withdraw_sol.py
+++ b/stake-pool/py/tests/test_deposit_withdraw_sol.py
@@ -1,6 +1,6 @@
 import pytest
 from solana.rpc.commitment import Confirmed, Processed
-from solana.keypair import Keypair
+from solders.keypair import Keypair
 from spl.token.instructions import get_associated_token_address
 
 from stake_pool.state import Fee, StakePool
@@ -8,20 +8,21 @@ from stake_pool.actions import create_all, deposit_sol, withdraw_sol
 
 
 @pytest.mark.asyncio
-async def test_deposit_withdraw_sol(async_client, payer):
+async def test_deposit_withdraw_sol(async_client, waiter, payer):
     fee = Fee(numerator=1, denominator=1000)
     referral_fee = 20
+    await waiter.wait_for_next_epoch(async_client)
     (stake_pool_address, validator_list_address, _) = await create_all(async_client, payer, fee, referral_fee)
     resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
-    token_account = get_associated_token_address(payer.public_key, stake_pool.pool_mint)
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
+    token_account = get_associated_token_address(payer.pubkey(), stake_pool.pool_mint)
     deposit_amount = 100_000_000
     await deposit_sol(async_client, payer, stake_pool_address, token_account, deposit_amount)
     pool_token_balance = await async_client.get_token_account_balance(token_account, Confirmed)
-    assert pool_token_balance['result']['value']['amount'] == str(deposit_amount)
+    assert pool_token_balance.value.amount == str(deposit_amount)
     recipient = Keypair()
-    await withdraw_sol(async_client, payer, token_account, stake_pool_address, recipient.public_key, deposit_amount)
+    await withdraw_sol(async_client, payer, token_account, stake_pool_address, recipient.pubkey(), deposit_amount)
     # for some reason, this is not always in sync when running all tests
     pool_token_balance = await async_client.get_token_account_balance(token_account, Processed)
-    assert pool_token_balance['result']['value']['amount'] == str('0')
+    assert pool_token_balance.value.amount == str('0')
diff --git a/stake-pool/py/tests/test_deposit_withdraw_stake.py b/stake-pool/py/tests/test_deposit_withdraw_stake.py
index 890fb9d1f..63b9e07db 100644
--- a/stake-pool/py/tests/test_deposit_withdraw_stake.py
+++ b/stake-pool/py/tests/test_deposit_withdraw_stake.py
@@ -1,6 +1,6 @@
 import pytest
 from solana.rpc.commitment import Confirmed
-from solana.keypair import Keypair
+from solders.keypair import Keypair
 from spl.token.instructions import get_associated_token_address
 
 from stake.actions import create_stake, delegate_stake
@@ -15,20 +15,20 @@ from stake_pool.state import StakePool
 async def test_deposit_withdraw_stake(async_client, validators, payer, stake_pool_addresses, waiter):
     (stake_pool_address, validator_list_address, _) = stake_pool_addresses
     resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_pool = StakePool.decode(data[0], data[1])
+    data = resp.value.data if resp.value else bytes()
+    stake_pool = StakePool.decode(data)
     validator = next(iter(validators))
     stake_amount = MINIMUM_ACTIVE_STAKE
     stake = Keypair()
-    await create_stake(async_client, payer, stake, payer.public_key, stake_amount)
-    stake = stake.public_key
+    await create_stake(async_client, payer, stake, payer.pubkey(), stake_amount)
+    stake = stake.pubkey()
     await delegate_stake(async_client, payer, payer, stake, validator)
     resp = await async_client.get_account_info(stake, commitment=Confirmed)
-    data = resp['result']['value']['data']
-    stake_state = StakeStake.decode(data[0], data[1])
-    token_account = get_associated_token_address(payer.public_key, stake_pool.pool_mint)
+    data = resp.value.data if resp.value else bytes()
+    stake_state = StakeStake.decode(data)
+    token_account = get_associated_token_address(payer.pubkey(), stake_pool.pool_mint)
     pre_pool_token_balance = await async_client.get_token_account_balance(token_account, Confirmed)
-    pre_pool_token_balance = int(pre_pool_token_balance['result']['value']['amount'])
+    pre_pool_token_balance = int(pre_pool_token_balance.value.amount)
     print(stake_state)
 
     await waiter.wait_for_next_epoch(async_client)
@@ -36,17 +36,17 @@ async def test_deposit_withdraw_stake(async_client, validators, payer, stake_poo
     await update_stake_pool(async_client, payer, stake_pool_address)
     await deposit_stake(async_client, payer, stake_pool_address, validator, stake, token_account)
     pool_token_balance = await async_client.get_token_account_balance(token_account, Confirmed)
-    pool_token_balance = pool_token_balance['result']['value']['amount']
+    pool_token_balance = pool_token_balance.value.amount
     resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
-    stake_rent_exemption = resp['result']
+    stake_rent_exemption = resp.value
     assert pool_token_balance == str(stake_amount + stake_rent_exemption + pre_pool_token_balance)
 
     destination_stake = Keypair()
     await withdraw_stake(
         async_client, payer, payer, destination_stake, stake_pool_address, validator,
-        payer.public_key, token_account, stake_amount
+        payer.pubkey(), token_account, stake_amount
     )
 
     pool_token_balance = await async_client.get_token_account_balance(token_account, Confirmed)
-    pool_token_balance = pool_token_balance['result']['value']['amount']
+    pool_token_balance = pool_token_balance.value.amount
     assert pool_token_balance == str(stake_rent_exemption + pre_pool_token_balance)
diff --git a/stake-pool/py/tests/test_stake.py b/stake-pool/py/tests/test_stake.py
index ab7cc3a44..7f89b8a75 100644
--- a/stake-pool/py/tests/test_stake.py
+++ b/stake-pool/py/tests/test_stake.py
@@ -1,6 +1,6 @@
 import asyncio
 import pytest
-from solana.keypair import Keypair
+from solders.keypair import Keypair
 
 from stake.actions import authorize, create_stake, delegate_stake
 from stake.constants import MINIMUM_DELEGATION
@@ -10,24 +10,24 @@ from stake.state import StakeAuthorize
 @pytest.mark.asyncio
 async def test_create_stake(async_client, payer):
     stake = Keypair()
-    await create_stake(async_client, payer, stake, payer.public_key, 1)
+    await create_stake(async_client, payer, stake, payer.pubkey(), 1)
 
 
 @pytest.mark.asyncio
 async def test_delegate_stake(async_client, validators, payer):
     validator = validators[0]
     stake = Keypair()
-    await create_stake(async_client, payer, stake, payer.public_key, MINIMUM_DELEGATION)
-    await delegate_stake(async_client, payer, payer, stake.public_key, validator)
+    await create_stake(async_client, payer, stake, payer.pubkey(), MINIMUM_DELEGATION)
+    await delegate_stake(async_client, payer, payer, stake.pubkey(), validator)
 
 
 @pytest.mark.asyncio
 async def test_authorize_stake(async_client, payer):
     stake = Keypair()
     new_authority = Keypair()
-    await create_stake(async_client, payer, stake, payer.public_key, MINIMUM_DELEGATION)
+    await create_stake(async_client, payer, stake, payer.pubkey(), MINIMUM_DELEGATION)
     await asyncio.gather(
-        authorize(async_client, payer, payer, stake.public_key, new_authority.public_key, StakeAuthorize.STAKER),
-        authorize(async_client, payer, payer, stake.public_key, new_authority.public_key, StakeAuthorize.WITHDRAWER)
+        authorize(async_client, payer, payer, stake.pubkey(), new_authority.pubkey(), StakeAuthorize.STAKER),
+        authorize(async_client, payer, payer, stake.pubkey(), new_authority.pubkey(), StakeAuthorize.WITHDRAWER)
     )
-    await authorize(async_client, payer, new_authority, stake.public_key, payer.public_key, StakeAuthorize.WITHDRAWER)
+    await authorize(async_client, payer, new_authority, stake.pubkey(), payer.pubkey(), StakeAuthorize.WITHDRAWER)
diff --git a/stake-pool/py/tests/test_system.py b/stake-pool/py/tests/test_system.py
index 31d2af343..f3b578ae2 100644
--- a/stake-pool/py/tests/test_system.py
+++ b/stake-pool/py/tests/test_system.py
@@ -1,5 +1,5 @@
 import pytest
-from solana.keypair import Keypair
+from solders.keypair import Keypair
 from solana.rpc.commitment import Confirmed
 
 import system.actions
@@ -9,6 +9,6 @@ import system.actions
 async def test_airdrop(async_client):
     manager = Keypair()
     airdrop_lamports = 1_000_000
-    await system.actions.airdrop(async_client, manager.public_key, airdrop_lamports)
-    resp = await async_client.get_balance(manager.public_key, commitment=Confirmed)
-    assert resp['result']['value'] == airdrop_lamports
+    await system.actions.airdrop(async_client, manager.pubkey(), airdrop_lamports)
+    resp = await async_client.get_balance(manager.pubkey(), commitment=Confirmed)
+    assert resp.value == airdrop_lamports
diff --git a/stake-pool/py/tests/test_token.py b/stake-pool/py/tests/test_token.py
index 1d92c179d..835feb15f 100644
--- a/stake-pool/py/tests/test_token.py
+++ b/stake-pool/py/tests/test_token.py
@@ -1,5 +1,5 @@
 import pytest
-from solana.keypair import Keypair
+from solders.keypair import Keypair
 
 from spl_token.actions import create_mint, create_associated_token_account
 
@@ -7,10 +7,10 @@ from spl_token.actions import create_mint, create_associated_token_account
 @pytest.mark.asyncio
 async def test_create_mint(async_client, payer):
     pool_mint = Keypair()
-    await create_mint(async_client, payer, pool_mint, payer.public_key)
+    await create_mint(async_client, payer, pool_mint, payer.pubkey())
     await create_associated_token_account(
         async_client,
         payer,
-        payer.public_key,
-        pool_mint.public_key,
+        payer.pubkey(),
+        pool_mint.pubkey(),
     )
diff --git a/stake-pool/py/tests/test_vote.py b/stake-pool/py/tests/test_vote.py
index b0861d465..3b3ff460f 100644
--- a/stake-pool/py/tests/test_vote.py
+++ b/stake-pool/py/tests/test_vote.py
@@ -1,6 +1,5 @@
 import pytest
-from solana.keypair import Keypair
-from solana.publickey import PublicKey
+from solders.keypair import Keypair
 from solana.rpc.commitment import Confirmed
 
 from vote.actions import create_vote
@@ -11,6 +10,6 @@ from vote.constants import VOTE_PROGRAM_ID
 async def test_create_vote(async_client, payer):
     vote = Keypair()
     node = Keypair()
-    await create_vote(async_client, payer, vote, node, payer.public_key, payer.public_key, 10)
-    resp = await async_client.get_account_info(vote.public_key, commitment=Confirmed)
-    assert PublicKey(resp['result']['value']['owner']) == VOTE_PROGRAM_ID
+    await create_vote(async_client, payer, vote, node, payer.pubkey(), payer.pubkey(), 10)
+    resp = await async_client.get_account_info(vote.pubkey(), commitment=Confirmed)
+    assert resp.value.owner == VOTE_PROGRAM_ID