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

Use process_transaction_with_metadata #60

Merged
merged 10 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## [0.18.0] - Unreleased

### Changed

- Rename `process_transaction_with_metadata` to just `process_transaction`.
Remove `process_transaction_with_preflight` and the old `process_transaction`
which had too many footguns. The new `process_transaction` uses the Rust
`process_transaction_with_metadata` under the hood. [(#60)](https://github.com/kevinheavey/solders/pull/60)

### Fixed

- Remove `.string()` from `pubkey.pyi` as the method no longer exists [(#57)](https://github.com/kevinheavey/solders/pull/57)
- Fix `pre_token_balances` getter [(#59)](https://github.com/kevinheavey/solders/pull/59)

## [0.17.0] - 2023-05-11

### Added
Expand Down
78 changes: 15 additions & 63 deletions crates/bankrun/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,66 +74,15 @@ impl BanksClient {
})
}

/// Send a transaction and wait until the transaction has been finalized or rejected.
///
/// Args:
/// transaction (VersionedTransaction): The transaction to send.
/// commitment (Optional[CommitmentLevel]): The commitment to use.
///
pub fn process_transaction<'p>(
&'p mut self,
py: Python<'p>,
transaction: VersionedTransaction,
commitment: Option<CommitmentLevel>,
) -> PyResult<&'p PyAny> {
let tx_inner = transaction.0.into_legacy_transaction().unwrap();
let commitment_inner = CommitmentLevelOriginal::from(commitment.unwrap_or_default());
let mut underlying = self.0.clone();
pyo3_asyncio::tokio::future_into_py(py, async move {
let res = underlying
.process_transaction_with_commitment(tx_inner, commitment_inner)
.await
.map_err(to_py_err);
let pyobj: PyResult<PyObject> = Python::with_gil(|py| res.map(|x| x.into_py(py)));
pyobj
})
}

/// Send a transaction and raise any preflight (sanitization or simulation) errors, or return
/// after the transaction has been rejected or reached the given level of commitment.
///
/// Args:
/// transaction (VersionedTransaction): The transaction to send.
/// commitment (Optional[CommitmentLevel]): The commitment to use.
///
pub fn process_transaction_with_preflight<'p>(
&'p mut self,
py: Python<'p>,
transaction: VersionedTransaction,
commitment: Option<CommitmentLevel>,
) -> PyResult<&'p PyAny> {
let tx_inner = transaction.0.into_legacy_transaction().unwrap();
let commitment_inner = CommitmentLevelOriginal::from(commitment.unwrap_or_default());
let mut underlying = self.0.clone();
pyo3_asyncio::tokio::future_into_py(py, async move {
let res = underlying
.process_transaction_with_preflight_and_commitment(tx_inner, commitment_inner)
.await
.map_err(to_py_err);
let pyobj: PyResult<PyObject> = Python::with_gil(|py| res.map(|x| x.into_py(py)));
pyobj
})
}

/// Process a transaction and return the result with metadata.
/// Process a transaction and return the transaction metadata, raising any errors.
///
/// Args:
/// transaction (VersionedTransaction): The transaction to send.
///
/// Returns:
/// BanksTransactionResultWithMeta: The transaction result and metadata.
///
pub fn process_transaction_with_metadata<'p>(
pub fn process_transaction<'p>(
&'p mut self,
py: Python<'p>,
transaction: VersionedTransaction,
Expand All @@ -145,9 +94,14 @@ impl BanksClient {
.process_transaction_with_metadata(tx_inner)
.await
.map_err(to_py_err);
let pyobj: PyResult<PyObject> = Python::with_gil(|py| {
res.map(|x| BanksTransactionResultWithMeta::from(x).into_py(py))
});
let meta = match res {
Ok(r) => match r.result {
Err(e) => Err(to_py_err(e)),
Ok(()) => Ok(BanksTransactionMeta::from(r.metadata.unwrap())),
},
Err(e) => Err(e),
};
let pyobj: PyResult<PyObject> = Python::with_gil(|py| meta.map(|x| x.into_py(py)));
pyobj
})
}
Expand Down Expand Up @@ -477,7 +431,7 @@ fn new_bankrun(
/// compute_max_units (Optional[int]): Override the default compute unit limit for a transaction.
/// transaction_account_lock_limit (Optional[int]): Override the default transaction account lock limit.
/// use_bpf_jit (Optional[bool]): Execute the program with JIT if true, interpreted if false.

///
///
/// Returns:
/// ProgramTestContext: a container for stuff you'll need to send transactions and interact with the test environment.
Expand Down Expand Up @@ -546,12 +500,10 @@ pub fn start_anchor<'p>(
let toml_programs_raw = parsed_toml
.get("programs")
.and_then(|x| x.get("localnet"))
.ok_or_else(|| PyValueError::new_err(
"`programs.localnet` not found in Anchor.toml",
))?;
let toml_programs_parsed = toml_programs_raw.as_table().ok_or_else(|| PyValueError::new_err(
"Failed to parse `programs.localnet` table.",
))?;
.ok_or_else(|| PyValueError::new_err("`programs.localnet` not found in Anchor.toml"))?;
let toml_programs_parsed = toml_programs_raw
.as_table()
.ok_or_else(|| PyValueError::new_err("Failed to parse `programs.localnet` table."))?;
for (key, val) in toml_programs_parsed {
let pubkey_with_quotes = val.to_string();
let pubkey_str = &pubkey_with_quotes[1..pubkey_with_quotes.len() - 1];
Expand Down
2 changes: 1 addition & 1 deletion crates/token/src/associated.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use pyo3::prelude::*;
use spl_associated_token_account::get_associated_token_address as get_ata;
use solders_pubkey::Pubkey;
use spl_associated_token_account::get_associated_token_address as get_ata;

/// Derives the associated token account address for the given wallet address and token mint.
#[pyfunction]
Expand Down
7 changes: 2 additions & 5 deletions crates/token/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use std::collections::HashMap;

use pyo3::prelude::*;
pub mod state;
pub mod associated;
pub mod state;

pub fn create_token_mod(py: Python<'_>) -> PyResult<&PyModule> {
let token_mod = PyModule::new(py, "token")?;
let state_mod = state::create_state_mod(py)?;
let associated_mod = associated::create_associated_mod(py)?;
let submodules = [
state_mod,
associated_mod,
];
let submodules = [state_mod, associated_mod];
let modules: HashMap<String, &PyModule> = submodules
.iter()
.map(|x| (format!("solders.token.{}", x.name().unwrap()), *x))
Expand Down
23 changes: 10 additions & 13 deletions crates/token/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use derive_more::{From, Into};
use pyo3::{prelude::*, types::PyBytes};
use solana_program::{program_option::COption, program_pack::Pack};
use solders_macros::{common_methods_core, richcmp_eq_only, enum_original_mapping};
use solders_macros::{common_methods_core, enum_original_mapping, richcmp_eq_only};
use solders_pubkey::Pubkey;
use solders_traits_core::{
impl_display, to_py_value_err, CommonMethodsCore, PyBytesGeneral, PyFromBytesGeneral,
RichcmpEqualityOnly,
};
use spl_token::state::{Mint as MintOriginal, Account as TokenAccountOriginal, AccountState, Multisig as MultisigOriginal};
use spl_token::state::{
Account as TokenAccountOriginal, AccountState, Mint as MintOriginal,
Multisig as MultisigOriginal,
};

macro_rules! token_boilerplate {
($typ:ident, $inner:ident) => {
Expand All @@ -19,20 +22,19 @@ macro_rules! token_boilerplate {
PyBytes::new(py, &inner)
}
}

impl PyFromBytesGeneral for $typ {
fn py_from_bytes_general(raw: &[u8]) -> PyResult<Self> {
let inner = $inner::unpack(raw).map_err(|e| to_py_value_err(&e))?;
Ok(inner.into())
}
}

impl CommonMethodsCore for $typ {}
impl RichcmpEqualityOnly for $typ {}
};
}


/// A token mint.
///
/// Args:
Expand Down Expand Up @@ -143,7 +145,7 @@ pub enum TokenAccountState {
/// is_native (Optional[int]): If is_native is not ``None``,
/// this is a native token, and the value logs the rent-exempt reserve.
/// An Account is required to be rent-exempt, so the value is used by
/// the Processor to ensure that wrapped SOL accounts do not
/// the Processor to ensure that wrapped SOL accounts do not
/// drop below this threshold.
/// delegated_amount (int): The amount delegated.
/// close_authority (Optional[Pubkey]): Optional authority to close the account.
Expand Down Expand Up @@ -261,17 +263,12 @@ pub struct Multisig(pub MultisigOriginal);
#[pymethods]
impl Multisig {
#[new]
pub fn new(
m: u8,
n: u8,
is_initialized: bool,
signers: [Pubkey; 11],
) -> Self {
pub fn new(m: u8, n: u8, is_initialized: bool, signers: [Pubkey; 11]) -> Self {
MultisigOriginal {
m,
n,
is_initialized,
signers: signers.map(Into::into)
signers: signers.map(Into::into),
}
.into()
}
Expand Down
43 changes: 22 additions & 21 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 1 addition & 10 deletions python/solders/bankrun.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,7 @@ class BanksClient:
async def process_transaction(
self,
transaction: VersionedTransaction,
commitment: Optional[CommitmentLevel] = None,
) -> None: ...
async def process_transaction_with_metadata(
self, Transaction: VersionedTransaction
) -> BanksTransactionResultWithMeta: ...
async def process_transaction_with_preflight(
self,
transaction: VersionedTransaction,
commitment: Optional[CommitmentLevel] = None,
) -> None: ...
) -> BanksTransactionMeta: ...
async def send_transaction(self, transaction: VersionedTransaction) -> None: ...
async def simulate_transaction(
self,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use rpc::create_rpc_mod;
use solders_account::create_account_mod;
use solders_instruction::{AccountMeta, CompiledInstruction, Instruction};
use solders_system_program::create_system_program_mod;
use solders_token::create_token_mod;
use solders_traits::{BincodeError, CborError, ParseHashError, SerdeJSONError, SignerError};
use solders_transaction_status::create_transaction_status_mod;
use solders_token::create_token_mod;
use std::collections::HashMap;
use sysvar::create_sysvar_mod;
pub mod message;
Expand Down
6 changes: 3 additions & 3 deletions tests/bankrun/clock-example/test_clock_example.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from pytest import mark, raises
from solders.bankrun import BanksClientError, start
from solders.bankrun import start
from solders.clock import Clock
from solders.instruction import Instruction
from solders.message import Message
from solders.pubkey import Pubkey
from solders.transaction import VersionedTransaction
from solders.transaction import TransactionError, VersionedTransaction


@mark.asyncio
Expand All @@ -18,7 +18,7 @@ async def test_set_clock() -> None:
msg = Message.new_with_blockhash(ixs, payer.pubkey(), blockhash)
tx = VersionedTransaction(msg, [payer])
# this will fail because it's not January 1970 anymore
with raises(BanksClientError):
with raises(TransactionError):
await client.process_transaction(tx)
# so let's turn back time
current_clock = await client.get_clock()
Expand Down
Loading