Skip to content

Commit

Permalink
FIX simulate_transaction add parameters from new RPC API
Browse files Browse the repository at this point in the history
  • Loading branch information
pyz4 committed Jan 15, 2024
1 parent 36ab2b5 commit 3ce3007
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 15 deletions.
23 changes: 20 additions & 3 deletions src/solana/rpc/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from solders.keypair import Keypair
from solders.message import VersionedMessage
from solders.pubkey import Pubkey
from solders.rpc.config import RpcSimulateTransactionAccountsConfig
from solders.rpc.responses import (
GetAccountInfoMaybeJsonParsedResp,
GetAccountInfoResp,
Expand Down Expand Up @@ -60,6 +61,7 @@
ValidatorExitResp,
)
from solders.signature import Signature
from solders.transaction import Transaction as SoldersTransaction
from solders.transaction import VersionedTransaction

from solana.blockhash import BlockhashCache
Expand Down Expand Up @@ -1072,17 +1074,25 @@ def send_transaction(

def simulate_transaction(
self,
txn: Union[Transaction, VersionedTransaction],
txn: Union[SoldersTransaction, VersionedTransaction],
sig_verify: bool = False,
replace_recent_blockhash: bool = False,
commitment: Optional[Commitment] = None,
accounts: Optional[RpcSimulateTransactionAccountsConfig] = None,
min_context_slot: Optional[int] = None,
) -> SimulateTransactionResp:
"""Simulate sending a transaction.
Args:
txn: A transaction object.
txn: A Transaction object, a transaction in wire format, or a transaction as base-64 encoded string
The transaction must have a valid blockhash, but is not required to be signed.
sig_verify: If true the transaction signatures will be verified (default: false).
replace_recent_blockhash: if `true` the transaction recent blockhash will be replaced with the
most recent blockhash (default: false, conflicts with `sigVerify`).
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
accounts: List of accounts to be returned.
RpcSimulateTransactionAccountsConfig object containing `addresses` and `encoding` fields.
min_context_slot: the minimum slot that the request can be evaluated at
Example:
>>> solana_client = Client("http://localhost:8899")
Expand All @@ -1097,7 +1107,14 @@ def simulate_transaction(
>>> solana_client.simulate_transaction(tx).value.logs # doctest: +SKIP
['BPF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success']
"""
body = self._simulate_transaction_body(txn, sig_verify, commitment)
body = self._simulate_transaction_body(
txn,
sig_verify,
replace_recent_blockhash,
commitment,
accounts,
min_context_slot,
)
return self._provider.make_request(body, SimulateTransactionResp)

def validator_exit(self) -> ValidatorExitResp:
Expand Down
23 changes: 20 additions & 3 deletions src/solana/rpc/async_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from solders.keypair import Keypair
from solders.message import VersionedMessage
from solders.pubkey import Pubkey
from solders.rpc.config import RpcSimulateTransactionAccountsConfig
from solders.rpc.responses import (
GetAccountInfoMaybeJsonParsedResp,
GetAccountInfoResp,
Expand Down Expand Up @@ -58,6 +59,7 @@
ValidatorExitResp,
)
from solders.signature import Signature
from solders.transaction import Transaction as SoldersTransaction
from solders.transaction import VersionedTransaction

from solana.blockhash import BlockhashCache
Expand Down Expand Up @@ -620,7 +622,7 @@ async def get_multiple_accounts_json_parsed(
encoding="jsonParsed",
data_slice=None,
)
return await self._provider.make_request(body, GetMultipleAccountsResp)
return await self._provider.make_request(body, GetMultipleAccountsMaybeJsonParsedResp)

async def get_program_accounts( # pylint: disable=too-many-arguments
self,
Expand Down Expand Up @@ -1081,17 +1083,25 @@ async def send_transaction(

async def simulate_transaction(
self,
txn: Union[Transaction, VersionedTransaction],
txn: Union[SoldersTransaction, VersionedTransaction],
sig_verify: bool = False,
replace_recent_blockhash: bool = False,
commitment: Optional[Commitment] = None,
accounts: Optional[RpcSimulateTransactionAccountsConfig] = None,
min_context_slot: Optional[int] = None,
) -> SimulateTransactionResp:
"""Simulate sending a transaction.
Args:
txn: A Transaction object, a transaction in wire format, or a transaction as base-64 encoded string
The transaction must have a valid blockhash, but is not required to be signed.
sig_verify: If true the transaction signatures will be verified (default: false).
replace_recent_blockhash: if `true` the transaction recent blockhash will be replaced with the
most recent blockhash (default: false, conflicts with `sigVerify`).
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
accounts: List of accounts to be returned.
RpcSimulateTransactionAccountsConfig object containing `addresses` and `encoding` fields.
min_context_slot: the minimum slot that the request can be evaluated at
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
Expand All @@ -1106,7 +1116,14 @@ async def simulate_transaction(
>>> (await solana_client.simulate_transaction(tx)).value.logs # doctest: +SKIP
['BPF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success']
"""
body = self._simulate_transaction_body(txn, sig_verify, commitment)
body = self._simulate_transaction_body(
txn,
sig_verify,
replace_recent_blockhash,
commitment,
accounts,
min_context_slot,
)
return await self._provider.make_request(body, SimulateTransactionResp)

async def validator_exit(self) -> ValidatorExitResp:
Expand Down
44 changes: 35 additions & 9 deletions src/solana/rpc/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
RpcSendTransactionConfig,
RpcSignaturesForAddressConfig,
RpcSignatureStatusConfig,
RpcSimulateTransactionAccountsConfig,
RpcSimulateTransactionConfig,
RpcSupplyConfig,
RpcTokenAccountsFilterMint,
Expand Down Expand Up @@ -81,12 +82,12 @@
)
from solders.rpc.responses import GetLatestBlockhashResp, SendTransactionResp
from solders.signature import Signature
from solders.transaction import Transaction as SoldersTransaction
from solders.transaction import VersionedTransaction
from solders.transaction_status import UiTransactionEncoding

from solana.blockhash import BlockhashCache
from solana.rpc import types
from solana.transaction import Transaction

from .commitment import Commitment, Confirmed, Finalized, Processed

Expand Down Expand Up @@ -485,26 +486,51 @@ def _send_raw_transaction_post_send_args(

@overload
def _simulate_transaction_body(
self, txn: Transaction, sig_verify: bool, commitment: Optional[Commitment]
self,
txn: SoldersTransaction,
sig_verify: bool,
replace_recent_blockhash: bool,
commitment: Optional[Commitment],
accounts: Optional[RpcSimulateTransactionAccountsConfig],
min_context_slot: Optional[int],
) -> SimulateLegacyTransaction:
...

@overload
def _simulate_transaction_body(
self, txn: VersionedTransaction, sig_verify: bool, commitment: Optional[Commitment]
self,
txn: VersionedTransaction,
sig_verify: bool,
replace_recent_blockhash: bool,
commitment: Optional[Commitment],
accounts: Optional[RpcSimulateTransactionAccountsConfig],
min_context_slot: Optional[int],
) -> SimulateVersionedTransaction:
...

def _simulate_transaction_body(
self, txn: Union[Transaction, VersionedTransaction], sig_verify: bool, commitment: Optional[Commitment]
self,
txn: Union[SoldersTransaction, VersionedTransaction],
sig_verify: bool = False,
replace_recent_blockhash: bool = False,
commitment: Optional[Commitment] = None,
accounts: Optional[RpcSimulateTransactionAccountsConfig] = None,
min_context_slot: Optional[int] = None,
) -> Union[SimulateLegacyTransaction, SimulateVersionedTransaction]:
commitment_to_use = _COMMITMENT_TO_SOLDERS[commitment or self._commitment]
config = RpcSimulateTransactionConfig(sig_verify=sig_verify, commitment=commitment_to_use)
if isinstance(txn, Transaction):
if txn.recent_blockhash is None:
config = RpcSimulateTransactionConfig(
sig_verify=sig_verify,
replace_recent_blockhash=replace_recent_blockhash,
commitment=commitment_to_use,
accounts=accounts,
min_context_slot=min_context_slot,
)
if isinstance(txn, SoldersTransaction):
if txn.message.recent_blockhash is None:
raise ValueError("transaction must have a valid blockhash")
return SimulateLegacyTransaction(txn.to_solders(), config)
return SimulateVersionedTransaction(txn, config)
return SimulateLegacyTransaction(txn, config)
else:
return SimulateVersionedTransaction(txn, config)

@staticmethod
def _post_send(resp: SendTransactionResp) -> SendTransactionResp:
Expand Down

0 comments on commit 3ce3007

Please sign in to comment.