feat: Use block_in_place instead of block_on
This is necessary when we run tycho-execution in an environment that already has a runtime. Make sure that if no runtime exists, like in the testing scenario inside tycho-execution, we save the new runtime in an attribute of permit2. If we don't do this, then the runtime just dies and our handle points to nothing at all and all tests fail --- don't change below this line --- ENG-4088 Took 17 minutes Took 5 seconds
This commit is contained in:
@@ -11,7 +11,10 @@ use alloy_primitives::{PrimitiveSignature as Signature, B256};
|
|||||||
use alloy_sol_types::{eip712_domain, sol, SolStruct, SolValue};
|
use alloy_sol_types::{eip712_domain, sol, SolStruct, SolValue};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::{
|
||||||
|
runtime::{Handle, Runtime},
|
||||||
|
task::block_in_place,
|
||||||
|
};
|
||||||
use tycho_core::Bytes;
|
use tycho_core::Bytes;
|
||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
@@ -29,9 +32,15 @@ use crate::encoding::{
|
|||||||
pub struct Permit2 {
|
pub struct Permit2 {
|
||||||
address: Address,
|
address: Address,
|
||||||
client: Arc<RootProvider<BoxTransport>>,
|
client: Arc<RootProvider<BoxTransport>>,
|
||||||
runtime: Arc<Runtime>,
|
|
||||||
signer: PrivateKeySigner,
|
signer: PrivateKeySigner,
|
||||||
chain_id: ChainId,
|
chain_id: ChainId,
|
||||||
|
runtime_handle: Handle,
|
||||||
|
// Store the runtime to prevent it from being dropped before use.
|
||||||
|
// This is required since tycho-execution does not have a pre-existing runtime.
|
||||||
|
// However, if the library is used in a context where a runtime already exists, it is not
|
||||||
|
// necessary to store it.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
runtime: Option<Arc<Runtime>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type alias for representing allowance data as a tuple of (amount, expiration, nonce). Used for
|
/// Type alias for representing allowance data as a tuple of (amount, expiration, nonce). Used for
|
||||||
@@ -61,15 +70,16 @@ sol! {
|
|||||||
|
|
||||||
impl Permit2 {
|
impl Permit2 {
|
||||||
pub fn new(signer_pk: String, chain: Chain) -> Result<Self, EncodingError> {
|
pub fn new(signer_pk: String, chain: Chain) -> Result<Self, EncodingError> {
|
||||||
let runtime = tokio::runtime::Handle::try_current()
|
let (handle, runtime) = match Handle::try_current() {
|
||||||
.is_err()
|
Ok(h) => (h, None),
|
||||||
.then(|| {
|
Err(_) => {
|
||||||
tokio::runtime::Runtime::new().map_err(|_| {
|
let rt = Arc::new(Runtime::new().map_err(|_| {
|
||||||
EncodingError::FatalError("Failed to create tokio runtime".to_string())
|
EncodingError::FatalError("Failed to create a new tokio runtime".to_string())
|
||||||
})
|
})?);
|
||||||
})
|
(rt.handle().clone(), Some(rt))
|
||||||
.ok_or(EncodingError::FatalError("Failed to get tokio runtime".to_string()))??;
|
}
|
||||||
let client = runtime.block_on(get_client())?;
|
};
|
||||||
|
let client = block_in_place(|| handle.block_on(get_client()))?;
|
||||||
let pk = B256::from_str(&signer_pk).map_err(|_| {
|
let pk = B256::from_str(&signer_pk).map_err(|_| {
|
||||||
EncodingError::FatalError("Failed to convert signer private key to B256".to_string())
|
EncodingError::FatalError("Failed to convert signer private key to B256".to_string())
|
||||||
})?;
|
})?;
|
||||||
@@ -80,9 +90,10 @@ impl Permit2 {
|
|||||||
address: Address::from_str("0x000000000022D473030F116dDEE9F6B43aC78BA3")
|
address: Address::from_str("0x000000000022D473030F116dDEE9F6B43aC78BA3")
|
||||||
.map_err(|_| EncodingError::FatalError("Permit2 address not valid".to_string()))?,
|
.map_err(|_| EncodingError::FatalError("Permit2 address not valid".to_string()))?,
|
||||||
client,
|
client,
|
||||||
runtime: Arc::new(runtime),
|
runtime_handle: handle,
|
||||||
signer,
|
signer,
|
||||||
chain_id: chain.id,
|
chain_id: chain.id,
|
||||||
|
runtime,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,9 +112,10 @@ impl Permit2 {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let output = self
|
let output = block_in_place(|| {
|
||||||
.runtime
|
self.runtime_handle
|
||||||
.block_on(async { self.client.call(&tx).await });
|
.block_on(async { self.client.call(&tx).await })
|
||||||
|
});
|
||||||
match output {
|
match output {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
let allowance: Allowance =
|
let allowance: Allowance =
|
||||||
@@ -290,14 +302,16 @@ mod tests {
|
|||||||
input: TransactionInput { input: Some(AlloyBytes::from(data)), data: None },
|
input: TransactionInput { input: Some(AlloyBytes::from(data)), data: None },
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let receipt = permit2.runtime.block_on(async {
|
let receipt = block_in_place(|| {
|
||||||
let pending_tx = permit2
|
permit2.runtime_handle.block_on(async {
|
||||||
.client
|
let pending_tx = permit2
|
||||||
.send_transaction(tx)
|
.client
|
||||||
.await
|
.send_transaction(tx)
|
||||||
.unwrap();
|
.await
|
||||||
// Wait for the transaction to be mined
|
.unwrap();
|
||||||
pending_tx.get_receipt().await.unwrap()
|
// Wait for the transaction to be mined
|
||||||
|
pending_tx.get_receipt().await.unwrap()
|
||||||
|
})
|
||||||
});
|
});
|
||||||
assert!(receipt.status(), "Approve transaction failed");
|
assert!(receipt.status(), "Approve transaction failed");
|
||||||
|
|
||||||
@@ -321,7 +335,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = permit2.runtime.block_on(async {
|
let result = permit2.runtime_handle.block_on(async {
|
||||||
let pending_tx = permit2
|
let pending_tx = permit2
|
||||||
.client
|
.client
|
||||||
.send_transaction(tx)
|
.send_transaction(tx)
|
||||||
|
|||||||
Reference in New Issue
Block a user