Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 5f0190c

Browse files
authored
stake-pool-py: Update to newer solana-py / solders (#7050)
* stake-pool-py: Update to newer solana-py / solders * Harden tests further
1 parent 2d2c4bb commit 5f0190c

28 files changed

+788
-792
lines changed

stake-pool/py/bot/rebalance.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import asyncio
33
import json
44

5-
from solana.keypair import Keypair
6-
from solana.publickey import PublicKey
5+
from solders.keypair import Keypair
6+
from solders.pubkey import Pubkey
77
from solana.rpc.async_api import AsyncClient
88
from solana.rpc.commitment import Confirmed
99

@@ -27,30 +27,30 @@ async def get_client(endpoint: str) -> AsyncClient:
2727
return async_client
2828

2929

30-
async def rebalance(endpoint: str, stake_pool_address: PublicKey, staker: Keypair, retained_reserve_amount: float):
30+
async def rebalance(endpoint: str, stake_pool_address: Pubkey, staker: Keypair, retained_reserve_amount: float):
3131
async_client = await get_client(endpoint)
3232

33-
resp = await async_client.get_epoch_info(commitment=Confirmed)
34-
epoch = resp['result']['epoch']
33+
epoch_resp = await async_client.get_epoch_info(commitment=Confirmed)
34+
epoch = epoch_resp.value.epoch
3535
resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
36-
data = resp['result']['value']['data']
37-
stake_pool = StakePool.decode(data[0], data[1])
36+
data = resp.value.data if resp.value else bytes()
37+
stake_pool = StakePool.decode(data)
3838

3939
print(f'Stake pool last update epoch {stake_pool.last_update_epoch}, current epoch {epoch}')
4040
if stake_pool.last_update_epoch != epoch:
4141
print('Updating stake pool')
4242
await update_stake_pool(async_client, staker, stake_pool_address)
4343
resp = await async_client.get_account_info(stake_pool_address, commitment=Confirmed)
44-
data = resp['result']['value']['data']
45-
stake_pool = StakePool.decode(data[0], data[1])
44+
data = resp.value.data if resp.value else bytes()
45+
stake_pool = StakePool.decode(data)
4646

47-
resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
48-
stake_rent_exemption = resp['result']
47+
rent_resp = await async_client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
48+
stake_rent_exemption = rent_resp.value
4949
retained_reserve_lamports = int(retained_reserve_amount * LAMPORTS_PER_SOL)
5050

51-
resp = await async_client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
52-
data = resp['result']['value']['data']
53-
validator_list = ValidatorList.decode(data[0], data[1])
51+
val_resp = await async_client.get_account_info(stake_pool.validator_list, commitment=Confirmed)
52+
data = val_resp.value.data if val_resp.value else bytes()
53+
validator_list = ValidatorList.decode(data)
5454

5555
print('Stake pool stats:')
5656
print(f'* {stake_pool.total_lamports} total lamports')
@@ -107,7 +107,7 @@ def keypair_from_file(keyfile_name: str) -> Keypair:
107107
data = keyfile.read()
108108
int_list = json.loads(data)
109109
bytes_list = [value.to_bytes(1, 'little') for value in int_list]
110-
return Keypair.from_secret_key(b''.join(bytes_list))
110+
return Keypair.from_seed(b''.join(bytes_list))
111111

112112

113113
if __name__ == "__main__":
@@ -124,9 +124,9 @@ def keypair_from_file(keyfile_name: str) -> Keypair:
124124
help='RPC endpoint to use, e.g. https://api.mainnet-beta.solana.com')
125125

126126
args = parser.parse_args()
127-
stake_pool = PublicKey(args.stake_pool)
127+
stake_pool = Pubkey(args.stake_pool)
128128
staker = keypair_from_file(args.staker)
129129
print(f'Rebalancing stake pool {stake_pool}')
130-
print(f'Staker public key: {staker.public_key}')
130+
print(f'Staker public key: {staker.pubkey()}')
131131
print(f'Amount to leave in the reserve: {args.reserve_amount} SOL')
132132
asyncio.run(rebalance(args.endpoint, stake_pool, staker, args.reserve_amount))
Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
attrs==22.1.0
2-
flake8==5.0.3
3-
iniconfig==1.1.1
1+
flake8==7.1.0
2+
iniconfig==2.0.0
43
mccabe==0.7.0
5-
mypy==0.971
6-
mypy-extensions==0.4.3
7-
packaging==21.3
8-
pluggy==1.0.0
9-
py==1.11.0
10-
pycodestyle==2.9.0
11-
pyflakes==2.5.0
12-
pyparsing==3.0.9
13-
pytest==7.1.2
14-
pytest-asyncio==0.19.0
15-
tomli==2.0.1
4+
mypy==1.11.0
5+
mypy-extensions==1.0.0
6+
packaging==24.1
7+
pluggy==1.5.0
8+
pycodestyle==2.12.0
9+
pyflakes==3.2.0
10+
pytest==8.3.1
11+
pytest-asyncio==0.23.8

stake-pool/py/requirements.txt

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
1-
anyio==3.6.1
2-
base58==2.1.1
3-
cachetools==4.2.4
1+
anyio==4.4.0
42
certifi==2024.7.4
5-
cffi==1.15.1
6-
charset-normalizer==2.1.0
73
construct==2.10.68
8-
h11==0.12.0
9-
httpcore==0.15.0
10-
httpx==0.23.0
4+
construct-typing==0.5.6
5+
h11==0.14.0
6+
httpcore==1.0.5
7+
httpx==0.27.0
118
idna==3.7
12-
pycparser==2.21
13-
PyNaCl==1.5.0
14-
requests==2.32.0
15-
rfc3986==1.5.0
16-
sniffio==1.2.0
17-
solana==0.18.1
18-
typing_extensions==4.3.0
19-
urllib3==1.26.19
9+
jsonalias==0.1.1
10+
sniffio==1.3.1
11+
solana==0.34.2
12+
solders==0.21.0
13+
typing_extensions==4.12.2
14+
websockets==11.0.3

stake-pool/py/spl_token/actions.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,62 @@
1-
from solana.publickey import PublicKey
2-
from solana.keypair import Keypair
1+
from solders.pubkey import Pubkey
2+
from solders.keypair import Keypair
33
from solana.rpc.async_api import AsyncClient
44
from solana.rpc.commitment import Confirmed
55
from solana.rpc.types import TxOpts
66
from solana.transaction import Transaction
7-
import solana.system_program as sys
7+
import solders.system_program as sys
88

99
from spl.token.constants import TOKEN_PROGRAM_ID
1010
from spl.token.async_client import AsyncToken
1111
from spl.token._layouts import MINT_LAYOUT
1212
import spl.token.instructions as spl_token
1313

1414

15+
OPTS = TxOpts(skip_confirmation=False, preflight_commitment=Confirmed)
16+
17+
1518
async def create_associated_token_account(
1619
client: AsyncClient,
1720
payer: Keypair,
18-
owner: PublicKey,
19-
mint: PublicKey
20-
) -> PublicKey:
21-
txn = Transaction()
21+
owner: Pubkey,
22+
mint: Pubkey
23+
) -> Pubkey:
24+
txn = Transaction(fee_payer=payer.pubkey())
2225
create_txn = spl_token.create_associated_token_account(
23-
payer=payer.public_key, owner=owner, mint=mint
26+
payer=payer.pubkey(), owner=owner, mint=mint
2427
)
2528
txn.add(create_txn)
26-
await client.send_transaction(txn, payer, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
27-
return create_txn.keys[1].pubkey
29+
recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
30+
await client.send_transaction(txn, payer, recent_blockhash=recent_blockhash, opts=OPTS)
31+
return create_txn.accounts[1].pubkey
2832

2933

30-
async def create_mint(client: AsyncClient, payer: Keypair, mint: Keypair, mint_authority: PublicKey):
34+
async def create_mint(client: AsyncClient, payer: Keypair, mint: Keypair, mint_authority: Pubkey):
3135
mint_balance = await AsyncToken.get_min_balance_rent_for_exempt_for_mint(client)
32-
print(f"Creating pool token mint {mint.public_key}")
33-
txn = Transaction()
36+
print(f"Creating pool token mint {mint.pubkey()}")
37+
txn = Transaction(fee_payer=payer.pubkey())
3438
txn.add(
3539
sys.create_account(
3640
sys.CreateAccountParams(
37-
from_pubkey=payer.public_key,
38-
new_account_pubkey=mint.public_key,
41+
from_pubkey=payer.pubkey(),
42+
to_pubkey=mint.pubkey(),
3943
lamports=mint_balance,
4044
space=MINT_LAYOUT.sizeof(),
41-
program_id=TOKEN_PROGRAM_ID,
45+
owner=TOKEN_PROGRAM_ID,
4246
)
4347
)
4448
)
4549
txn.add(
4650
spl_token.initialize_mint(
4751
spl_token.InitializeMintParams(
4852
program_id=TOKEN_PROGRAM_ID,
49-
mint=mint.public_key,
53+
mint=mint.pubkey(),
5054
decimals=9,
5155
mint_authority=mint_authority,
5256
freeze_authority=None,
5357
)
5458
)
5559
)
60+
recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
5661
await client.send_transaction(
57-
txn, payer, mint, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
62+
txn, payer, mint, recent_blockhash=recent_blockhash, opts=OPTS)

stake-pool/py/stake/actions.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,91 @@
1-
from solana.publickey import PublicKey
2-
from solana.keypair import Keypair
1+
from solders.pubkey import Pubkey
2+
from solders.keypair import Keypair
3+
import solders.system_program as sys
4+
from solana.constants import SYSTEM_PROGRAM_ID
35
from solana.rpc.async_api import AsyncClient
46
from solana.rpc.commitment import Confirmed
57
from solana.rpc.types import TxOpts
6-
from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY
8+
from solders.sysvar import CLOCK, STAKE_HISTORY
79
from solana.transaction import Transaction
8-
import solana.system_program as sys
910

1011
from stake.constants import STAKE_LEN, STAKE_PROGRAM_ID, SYSVAR_STAKE_CONFIG_ID
1112
from stake.state import Authorized, Lockup, StakeAuthorize
1213
import stake.instructions as st
1314

1415

15-
async def create_stake(client: AsyncClient, payer: Keypair, stake: Keypair, authority: PublicKey, lamports: int):
16-
print(f"Creating stake {stake.public_key}")
16+
OPTS = TxOpts(skip_confirmation=False, preflight_commitment=Confirmed)
17+
18+
19+
async def create_stake(client: AsyncClient, payer: Keypair, stake: Keypair, authority: Pubkey, lamports: int):
20+
print(f"Creating stake {stake.pubkey()}")
1721
resp = await client.get_minimum_balance_for_rent_exemption(STAKE_LEN)
18-
txn = Transaction()
22+
txn = Transaction(fee_payer=payer.pubkey())
1923
txn.add(
2024
sys.create_account(
2125
sys.CreateAccountParams(
22-
from_pubkey=payer.public_key,
23-
new_account_pubkey=stake.public_key,
24-
lamports=resp['result'] + lamports,
26+
from_pubkey=payer.pubkey(),
27+
to_pubkey=stake.pubkey(),
28+
lamports=resp.value + lamports,
2529
space=STAKE_LEN,
26-
program_id=STAKE_PROGRAM_ID,
30+
owner=STAKE_PROGRAM_ID,
2731
)
2832
)
2933
)
3034
txn.add(
3135
st.initialize(
3236
st.InitializeParams(
33-
stake=stake.public_key,
37+
stake=stake.pubkey(),
3438
authorized=Authorized(
3539
staker=authority,
3640
withdrawer=authority,
3741
),
3842
lockup=Lockup(
3943
unix_timestamp=0,
4044
epoch=0,
41-
custodian=sys.SYS_PROGRAM_ID,
45+
custodian=SYSTEM_PROGRAM_ID,
4246
)
4347
)
4448
)
4549
)
46-
await client.send_transaction(
47-
txn, payer, stake, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
50+
recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
51+
await client.send_transaction(txn, payer, stake, recent_blockhash=recent_blockhash, opts=OPTS)
4852

4953

50-
async def delegate_stake(client: AsyncClient, payer: Keypair, staker: Keypair, stake: PublicKey, vote: PublicKey):
51-
txn = Transaction()
54+
async def delegate_stake(client: AsyncClient, payer: Keypair, staker: Keypair, stake: Pubkey, vote: Pubkey):
55+
txn = Transaction(fee_payer=payer.pubkey())
5256
txn.add(
5357
st.delegate_stake(
5458
st.DelegateStakeParams(
5559
stake=stake,
5660
vote=vote,
57-
clock_sysvar=SYSVAR_CLOCK_PUBKEY,
58-
stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
61+
clock_sysvar=CLOCK,
62+
stake_history_sysvar=STAKE_HISTORY,
5963
stake_config_id=SYSVAR_STAKE_CONFIG_ID,
60-
staker=staker.public_key,
64+
staker=staker.pubkey(),
6165
)
6266
)
6367
)
64-
signers = [payer, staker] if payer != staker else [payer]
65-
await client.send_transaction(
66-
txn, *signers, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
68+
signers = [payer, staker] if payer.pubkey() != staker.pubkey() else [payer]
69+
recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
70+
await client.send_transaction(txn, *signers, recent_blockhash=recent_blockhash, opts=OPTS)
6771

6872

6973
async def authorize(
70-
client: AsyncClient, payer: Keypair, authority: Keypair, stake: PublicKey,
71-
new_authority: PublicKey, stake_authorize: StakeAuthorize
74+
client: AsyncClient, payer: Keypair, authority: Keypair, stake: Pubkey,
75+
new_authority: Pubkey, stake_authorize: StakeAuthorize
7276
):
73-
txn = Transaction()
77+
txn = Transaction(fee_payer=payer.pubkey())
7478
txn.add(
7579
st.authorize(
7680
st.AuthorizeParams(
7781
stake=stake,
78-
clock_sysvar=SYSVAR_CLOCK_PUBKEY,
79-
authority=authority.public_key,
82+
clock_sysvar=CLOCK,
83+
authority=authority.pubkey(),
8084
new_authority=new_authority,
8185
stake_authorize=stake_authorize,
8286
)
8387
)
8488
)
85-
signers = [payer, authority] if payer != authority else [payer]
86-
await client.send_transaction(
87-
txn, *signers, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed))
89+
signers = [payer, authority] if payer.pubkey() != authority.pubkey() else [payer]
90+
recent_blockhash = (await client.get_latest_blockhash()).value.blockhash
91+
await client.send_transaction(txn, *signers, recent_blockhash=recent_blockhash, opts=OPTS)

stake-pool/py/stake/constants.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""Stake Program Constants."""
22

3-
from solana.publickey import PublicKey
3+
from solders.pubkey import Pubkey
44

5-
STAKE_PROGRAM_ID: PublicKey = PublicKey("Stake11111111111111111111111111111111111111")
5+
STAKE_PROGRAM_ID = Pubkey.from_string("Stake11111111111111111111111111111111111111")
66
"""Public key that identifies the Stake program."""
77

8-
SYSVAR_STAKE_CONFIG_ID: PublicKey = PublicKey("StakeConfig11111111111111111111111111111111")
8+
SYSVAR_STAKE_CONFIG_ID = Pubkey.from_string("StakeConfig11111111111111111111111111111111")
99
"""Public key that identifies the Stake config sysvar."""
1010

1111
STAKE_LEN: int = 200

0 commit comments

Comments
 (0)