Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate transaction module #442

Merged
merged 24 commits into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
42af4a2
delete pointless test
kevinheavey Jul 5, 2024
00da75e
remove transaction module
kevinheavey Jul 5, 2024
9404f6e
small docstring fix
kevinheavey Jul 5, 2024
1441a2b
update sync send_transaction method
kevinheavey Jul 5, 2024
a791b4c
update _simulate_transaction_body
kevinheavey Jul 5, 2024
aefa01c
update token client to use solders transaction
kevinheavey Jul 5, 2024
12d0a6e
unused import
kevinheavey Jul 5, 2024
5742d5a
update integration tests to use solders transaction
kevinheavey Jul 5, 2024
3b57d5a
fix some send_transaction calls
kevinheavey Jul 5, 2024
8076411
remove references to compile_message()
kevinheavey Jul 5, 2024
7b04bf7
missing await
kevinheavey Jul 5, 2024
dee1b3a
remove unnecessary .sign() calls
kevinheavey Jul 5, 2024
a5ae4f0
try use real blockhash in get_fee_for_message tests
kevinheavey Jul 5, 2024
1c54661
fix _create_account_args
kevinheavey Jul 5, 2024
37b4b75
fix _create_multisig_args
kevinheavey Jul 5, 2024
47adbf6
Merge remote-tracking branch 'origin/master' into remove-transaction
michaelhly Oct 12, 2024
e4b3a64
Deprecate transaction module instead of removal
michaelhly Oct 12, 2024
482a34d
Update depcrecation message
michaelhly Oct 12, 2024
91b4e0c
Lint
michaelhly Oct 12, 2024
48ba546
Add back send_legacy_transaction rpc methods
michaelhly Oct 12, 2024
bc9155f
Add deprecation warning
michaelhly Oct 12, 2024
1d7ed08
Rename
michaelhly Oct 12, 2024
5799680
Add back unit test for legacy transaction
michaelhly Oct 12, 2024
858b9d8
Less diff
michaelhly Oct 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 42 additions & 19 deletions src/solana/rpc/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from time import sleep, time
from typing import Dict, List, Optional, Sequence, Union
from warnings import warn

from solders.hash import Hash as Blockhash
from solders.keypair import Keypair
Expand Down Expand Up @@ -62,10 +63,10 @@
ValidatorExitResp,
)
from solders.signature import Signature
from solders.transaction import VersionedTransaction
from solders.transaction import Transaction, VersionedTransaction

from solana.rpc import types
from solana.transaction import Transaction
from solana.transaction import Transaction as LegacyTransaction

from .commitment import Commitment, Finalized
from .core import (
Expand Down Expand Up @@ -408,13 +409,13 @@ def get_fee_for_message(
Example:
>>> from solders.keypair import Keypair
>>> from solders.system_program import TransferParams, transfer
>>> from solana.transaction import Transaction
>>> from solders.message import Message
>>> leading_zeros = [0] * 31
>>> sender, receiver = Keypair.from_seed(leading_zeros + [1]), Keypair.from_seed(leading_zeros + [2])
>>> txn = Transaction().add(transfer(TransferParams(
... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000)))
>>> msg = Message([transfer(TransferParams(
... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000))])
>>> solana_client = Client("http://localhost:8899")
>>> solana_client.get_fee_for_message(txn.compile_message()).value # doctest: +SKIP
>>> solana_client.get_fee_for_message(msg).value # doctest: +SKIP
5000
"""
body = self._get_fee_for_message_body(message, commitment)
Expand Down Expand Up @@ -997,14 +998,14 @@ def send_raw_transaction(self, txn: bytes, opts: Optional[types.TxOpts] = None)
post_send_args = self._send_raw_transaction_post_send_args(resp, opts_to_use)
return self.__post_send_with_confirm(*post_send_args)

def send_transaction(
def send_legacy_transaction(
self,
txn: Union[VersionedTransaction, Transaction],
txn: LegacyTransaction,
*signers: Keypair,
opts: Optional[types.TxOpts] = None,
recent_blockhash: Optional[Blockhash] = None,
) -> SendTransactionResp:
"""Send a transaction.
"""Send a legacy transaction.

Args:
txn: transaction object.
Expand All @@ -1030,15 +1031,8 @@ def send_transaction(
1111111111111111111111111111111111111111111111111111111111111111,
)
"""
if isinstance(txn, VersionedTransaction):
if signers:
msg = "*signers args are not used when sending VersionedTransaction."
raise ValueError(msg)
if recent_blockhash is not None:
msg = "recent_blockhash arg is not used when sending VersionedTransaction."
raise ValueError(msg)
versioned_tx_opts = types.TxOpts(preflight_commitment=self._commitment) if opts is None else opts
return self.send_raw_transaction(bytes(txn), opts=versioned_tx_opts)
warn("send_legacy_transaction is deprecated. Use send_transaction instead.", DeprecationWarning)

last_valid_block_height = None
if recent_blockhash is None:
blockhash_resp = self.get_latest_blockhash(Finalized)
Expand All @@ -1060,6 +1054,34 @@ def send_transaction(
txn_resp = self.send_raw_transaction(txn.serialize(), opts=opts_to_use)
return txn_resp

def send_transaction(
self,
txn: Union[VersionedTransaction, Transaction],
opts: Optional[types.TxOpts] = None,
) -> SendTransactionResp:
"""Send a transaction.

Args:
txn: transaction object.
opts: (optional) Transaction options.

Example:
>>> from solders.keypair import Keypair
>>> from solders.pubkey import Pubkey
>>> from solana.rpc.api import Client
>>> from solders.system_program import TransferParams, transfer
>>> from solders.message import Message
>>> leading_zeros = [0] * 31
>>> sender, receiver = Keypair.from_seed(leading_zeros + [1]), Keypair.from_seed(leading_zeros + [2])
>>> ixns = [transfer(TransferParams(
... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000))]
>>> msg = Message(ixns, sender.pubkey())
>>> client = Client("http://localhost:8899")
>>> client.send_transaction(Transaction([sender], msg, client.get_latest_blockhash()).value.blockhash) # doctest: +SKIP
""" # noqa: E501
tx_opts = types.TxOpts(preflight_commitment=self._commitment) if opts is None else opts
return self.send_raw_transaction(bytes(txn), opts=tx_opts)

def simulate_transaction(
self,
txn: Union[Transaction, VersionedTransaction],
Expand All @@ -1075,6 +1097,7 @@ def simulate_transaction(
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".

Example:
>>> from solders.transaction import Transaction
>>> solana_client = Client("http://localhost:8899")
>>> full_signed_tx_hex = (
... '01b3795ccfaac3eee838bb05c3b8284122c18acedcd645c914fe8e178c3b62640d8616d061cc818b26cab8ecf3855ecc'
Expand All @@ -1083,7 +1106,7 @@ def simulate_transaction(
... '000000000000000000000000000000000000000000839618f701ba7e9ba27ae59825dd6d6bb66d14f6d5d0eae215161d7'
... '1851a106901020200010c0200000040420f0000000000'
... )
>>> tx = Transaction.deserialize(bytes.fromhex(full_signed_tx_hex))
>>> tx = Transaction.from_bytes(bytes.fromhex(full_signed_tx_hex))
>>> solana_client.simulate_transaction(tx).value.logs # doctest: +SKIP
['BPF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success']
"""
Expand Down
65 changes: 45 additions & 20 deletions src/solana/rpc/async_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import asyncio
from time import time
from typing import Dict, List, Optional, Sequence, Union
from warnings import warn

from solders.hash import Hash as Blockhash
from solders.keypair import Keypair
Expand Down Expand Up @@ -60,13 +61,18 @@
ValidatorExitResp,
)
from solders.signature import Signature
from solders.transaction import VersionedTransaction
from solders.transaction import Transaction, VersionedTransaction

from solana.rpc import types
from solana.transaction import Transaction
from solana.transaction import Transaction as LegacyTransaction

from .commitment import Commitment, Finalized
from .core import _COMMITMENT_TO_SOLDERS, TransactionExpiredBlockheightExceededError, UnconfirmedTxError, _ClientCore
from .core import (
_COMMITMENT_TO_SOLDERS,
TransactionExpiredBlockheightExceededError,
UnconfirmedTxError,
_ClientCore,
)
from .providers import async_http


Expand Down Expand Up @@ -415,13 +421,13 @@ async def get_fee_for_message(
Example:
>>> from solders.keypair import Keypair
>>> from solders.system_program import TransferParams, transfer
>>> from solana.transaction import Transaction
>>> from solders.message import Message
>>> leading_zeros = [0] * 31
>>> sender, receiver = Keypair.from_seed(leading_zeros + [1]), Keypair.from_seed(leading_zeros + [2])
>>> txn = Transaction().add(transfer(TransferParams(
... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000)))
>>> msg = Message([transfer(TransferParams(
... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000))])
>>> solana_client = AsyncClient("http://localhost:8899")
>>> (await solana_client.get_fee_for_message(txn.compile_message())).value # doctest: +SKIP
>>> (await solana_client.get_fee_for_message(msg)).value # doctest: +SKIP
5000
"""
body = self._get_fee_for_message_body(message, commitment)
Expand Down Expand Up @@ -1005,14 +1011,14 @@ async def send_raw_transaction(self, txn: bytes, opts: Optional[types.TxOpts] =
post_send_args = self._send_raw_transaction_post_send_args(resp, opts_to_use)
return await self.__post_send_with_confirm(*post_send_args)

async def send_transaction(
async def send_legacy_transaction(
self,
txn: Union[VersionedTransaction, Transaction],
txn: LegacyTransaction,
*signers: Keypair,
opts: Optional[types.TxOpts] = None,
recent_blockhash: Optional[Blockhash] = None,
) -> SendTransactionResp:
"""Send a transaction.
"""Send a legacy transaction.

Args:
txn: transaction object.
Expand All @@ -1036,15 +1042,8 @@ async def send_transaction(
1111111111111111111111111111111111111111111111111111111111111111,
)
"""
if isinstance(txn, VersionedTransaction):
if signers:
msg = "*signers args are not used when sending VersionedTransaction."
raise ValueError(msg)
if recent_blockhash is not None:
msg = "recent_blockhash arg is not used when sending VersionedTransaction."
raise ValueError(msg)
versioned_tx_opts = types.TxOpts(preflight_commitment=self._commitment) if opts is None else opts
return await self.send_raw_transaction(bytes(txn), opts=versioned_tx_opts)
warn("send_legacy_transaction is deprecated. Use send_transaction instead.", DeprecationWarning)

last_valid_block_height = None
if recent_blockhash is None:
blockhash_resp = await self.get_latest_blockhash(Finalized)
Expand All @@ -1065,6 +1064,32 @@ async def send_transaction(
txn_resp = await self.send_raw_transaction(txn.serialize(), opts=opts_to_use)
return txn_resp

async def send_transaction(
self,
txn: Union[VersionedTransaction, Transaction],
opts: Optional[types.TxOpts] = None,
) -> SendTransactionResp:
"""Send a transaction.

Args:
txn: transaction object.
opts: (optional) Transaction options.

Example:
>>> from solders.keypair import Keypair
>>> from solders.system_program import TransferParams, transfer
>>> from solders.message import Message
>>> from solders.transaction import Transaction
>>> leading_zeros = [0] * 31
>>> sender, receiver = Keypair.from_seed(leading_zeros + [1]), Keypair.from_seed(leading_zeros + [2])
>>> ixns = [transfer(TransferParams(
... from_pubkey=sender.pubkey(), to_pubkey=receiver.pubkey(), lamports=1000))]
>>> msg = Message(ixns, sender.pubkey())
>>> client = AsyncClient("http://localhost:8899")
>>> (await client.send_transaction(Transaction([sender], msg, (await client.get_latest_blockhash()).value.blockhash))) # doctest: +SKIP
""" # noqa: E501
return await self.send_raw_transaction(bytes(txn), opts=opts)

async def simulate_transaction(
self,
txn: Union[Transaction, VersionedTransaction],
Expand All @@ -1088,7 +1113,7 @@ async def simulate_transaction(
... '000000000000000000000000000000000000000000839618f701ba7e9ba27ae59825dd6d6bb66d14f6d5d0eae215161d7'
... '1851a106901020200010c0200000040420f0000000000'
... )
>>> tx = Transaction.deserialize(bytes.fromhex(full_signed_tx_hex))
>>> tx = Transaction.from_bytes(bytes.fromhex(full_signed_tx_hex))
>>> (await solana_client.simulate_transaction(tx)).value.logs # doctest: +SKIP
['BPF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success']
"""
Expand Down
6 changes: 2 additions & 4 deletions src/solana/rpc/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
from solders.transaction_status import UiTransactionEncoding

from solana.rpc import types
from solana.transaction import Transaction
from solders.transaction import Transaction

from .commitment import Commitment, Confirmed, Finalized, Processed

Expand Down Expand Up @@ -499,9 +499,7 @@ def _simulate_transaction_body(
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:
raise ValueError("transaction must have a valid blockhash")
return SimulateLegacyTransaction(txn.to_solders(), config)
return SimulateLegacyTransaction(txn, config)
return SimulateVersionedTransaction(txn, config)

@staticmethod
Expand Down
10 changes: 7 additions & 3 deletions src/solana/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import annotations

from typing import Any, List, NamedTuple, Optional, Sequence, Tuple, Union
from warnings import warn

from solders.hash import Hash as Blockhash
from solders.instruction import AccountMeta, Instruction
Expand Down Expand Up @@ -78,9 +79,6 @@ class Transaction:
instructions: The instructions to be executed in this transaction.
"""

# Default (empty) signature
__DEFAULT_SIG = bytes(64)

def __init__(
self,
recent_blockhash: Optional[Blockhash] = None,
Expand All @@ -89,6 +87,12 @@ def __init__(
instructions: Optional[Sequence[Instruction]] = None,
) -> None:
"""Init transaction object."""
warn(
"""Transaction is deprecated and will be removed in a later release.
Please use the Transaction module from solders.transaction instead.""",
DeprecationWarning,
)

self._solders = _build_solders_tx(
recent_blockhash=recent_blockhash,
nonce_info=nonce_info,
Expand Down
Loading