Skip to content
Open
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
55 changes: 55 additions & 0 deletions crates/common/src/local_db/query/fetch_transaction_by_hash/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::local_db::{
query::{SqlStatement, SqlValue},
OrderbookIdentifier,
};
use alloy::primitives::{Address, B256};
use serde::{Deserialize, Serialize};

const QUERY_TEMPLATE: &str = include_str!("query.sql");

/// Transaction info returned from local DB query.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct LocalDbTransaction {
pub transaction_hash: B256,
pub block_number: u64,
pub block_timestamp: u64,
pub sender: Address,
}

/// Builds a SQL statement to fetch transaction info by transaction hash
/// from the deposits and withdrawals tables.
pub fn build_fetch_transaction_by_hash_stmt(
ob_id: &OrderbookIdentifier,
tx_hash: B256,
) -> SqlStatement {
SqlStatement::new_with_params(
QUERY_TEMPLATE,
vec![
SqlValue::from(ob_id.chain_id),
SqlValue::from(ob_id.orderbook_address),
SqlValue::from(tx_hash),
],
)
}

#[cfg(test)]
mod tests {
use super::*;
use alloy::primitives::{address, b256};

#[test]
fn builds_correct_sql_with_params() {
let orderbook = address!("0x1234567890123456789012345678901234567890");
let tx_hash = b256!("0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890");
let ob_id = OrderbookIdentifier::new(1, orderbook);

let stmt = build_fetch_transaction_by_hash_stmt(&ob_id, tx_hash);

assert!(stmt.sql.contains("SELECT"));
assert!(stmt.sql.contains("FROM deposits"));
assert!(stmt.sql.contains("FROM withdrawals"));
assert!(stmt.sql.contains("transaction_hash"));
assert_eq!(stmt.params.len(), 3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
WITH params AS (
SELECT
?1 AS chain_id,
?2 AS orderbook_address,
?3 AS transaction_hash
),
combined AS (
SELECT
d.transaction_hash,
d.block_number,
d.block_timestamp,
d.sender,
d.log_index
FROM deposits d
JOIN params p
ON p.chain_id = d.chain_id
AND p.orderbook_address = d.orderbook_address
AND p.transaction_hash = d.transaction_hash
UNION ALL
SELECT
w.transaction_hash,
w.block_number,
w.block_timestamp,
w.sender,
w.log_index
FROM withdrawals w
JOIN params p
ON p.chain_id = w.chain_id
AND p.orderbook_address = w.orderbook_address
AND p.transaction_hash = w.transaction_hash
)
SELECT
transaction_hash AS transactionHash,
block_number AS blockNumber,
block_timestamp AS blockTimestamp,
sender
FROM combined
ORDER BY log_index ASC
LIMIT 1;

1 change: 1 addition & 0 deletions crates/common/src/local_db/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod fetch_orders;
pub mod fetch_store_addresses;
pub mod fetch_tables;
pub mod fetch_target_watermark;
pub mod fetch_transaction_by_hash;
pub mod fetch_vault_balance_changes;
pub mod fetch_vaults;
pub mod insert_db_metadata;
Expand Down
6 changes: 3 additions & 3 deletions crates/common/src/raindex_client/add_orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ impl RaindexClient {
Ok(orders) => return Ok(orders),
Err(RetryError::Operation(PollError::Inner(e))) => return Err(e),
Err(RetryError::InvalidMaxAttempts) => {
return Err(RaindexError::SubgraphIndexingTimeout { tx_hash, attempts })
return Err(RaindexError::TransactionIndexingTimeout { tx_hash, attempts })
}
Err(RetryError::Operation(PollError::Empty)) => {
// Local DB exhausted, fall through to subgraph
Expand Down Expand Up @@ -173,7 +173,7 @@ impl RaindexClient {
Ok(orders) => Ok(orders),
Err(RetryError::Operation(PollError::Inner(e))) => Err(e),
Err(RetryError::Operation(PollError::Empty)) | Err(RetryError::InvalidMaxAttempts) => {
Err(RaindexError::SubgraphIndexingTimeout { tx_hash, attempts })
Err(RaindexError::TransactionIndexingTimeout { tx_hash, attempts })
}
}
}
Expand Down Expand Up @@ -588,7 +588,7 @@ mod tests {
.unwrap_err();

match err {
RaindexError::SubgraphIndexingTimeout { attempts, .. } => {
RaindexError::TransactionIndexingTimeout { attempts, .. } => {
assert_eq!(attempts, DEFAULT_ADD_ORDER_POLL_ATTEMPTS);
}
other => panic!("expected timeout error, got {other:?}"),
Expand Down
1 change: 1 addition & 0 deletions crates/common/src/raindex_client/local_db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod executor;
pub mod orders;
pub mod pipeline;
pub mod query;
pub mod transactions;
pub mod vaults;

type ExecuteBatchFn =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use crate::local_db::query::fetch_transaction_by_hash::{
build_fetch_transaction_by_hash_stmt, LocalDbTransaction,
};
use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor};
use crate::local_db::OrderbookIdentifier;
use alloy::primitives::B256;

pub async fn fetch_transaction_by_hash<E: LocalDbQueryExecutor + ?Sized>(
exec: &E,
ob_id: &OrderbookIdentifier,
tx_hash: B256,
) -> Result<Vec<LocalDbTransaction>, LocalDbQueryError> {
let stmt = build_fetch_transaction_by_hash_stmt(ob_id, tx_hash);
exec.query_json(&stmt).await
}

#[cfg(all(test, target_family = "wasm"))]
mod wasm_tests {
use super::*;
use crate::raindex_client::local_db::executor::tests::create_sql_capturing_callback;
use crate::raindex_client::local_db::executor::JsCallbackExecutor;
use alloy::primitives::{address, b256, Address};
use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen_test::*;
use wasm_bindgen_utils::prelude::*;

#[wasm_bindgen_test]
async fn wrapper_uses_builder_sql_exactly() {
let tx_hash = b256!("0x0000000000000000000000000000000000000000000000000000000000000abc");
let orderbook = Address::from([0x51; 20]);
let expected_stmt =
build_fetch_transaction_by_hash_stmt(&OrderbookIdentifier::new(1, orderbook), tx_hash);

let store = Rc::new(RefCell::new((String::new(), JsValue::UNDEFINED)));
let callback = create_sql_capturing_callback("[]", store.clone());
let exec = JsCallbackExecutor::from_ref(&callback);

let res = super::fetch_transaction_by_hash(
&exec,
&OrderbookIdentifier::new(1, orderbook),
tx_hash,
)
.await;
assert!(res.is_ok());
assert_eq!(store.borrow().clone().0, expected_stmt.sql);
}

#[wasm_bindgen_test]
async fn wrapper_returns_rows_when_present() {
let tx_hash = b256!("0x0000000000000000000000000000000000000000000000000000000000000abc");
let orderbook = address!("0x5151515151515151515151515151515151515151");
let sender = address!("0x1111111111111111111111111111111111111111");
let expected_stmt =
build_fetch_transaction_by_hash_stmt(&OrderbookIdentifier::new(1, orderbook), tx_hash);

let row_json = format!(
r#"[{{
"transactionHash":"{}",
"blockNumber":100,
"blockTimestamp":999,
"sender":"{}"
}}]"#,
tx_hash, sender
);

let store = Rc::new(RefCell::new((
String::new(),
wasm_bindgen::JsValue::UNDEFINED,
)));
let callback = create_sql_capturing_callback(&row_json, store.clone());
let exec = JsCallbackExecutor::from_ref(&callback);

let res = super::fetch_transaction_by_hash(
&exec,
&OrderbookIdentifier::new(1, orderbook),
tx_hash,
)
.await;
assert!(res.is_ok());
let rows = res.unwrap();
assert_eq!(rows.len(), 1);
assert_eq!(store.borrow().clone().0, expected_stmt.sql);
}
Comment on lines +17 to +84
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

WASM tests exercise both SQL wiring and row deserialization effectively

The two wasm tests confirm that:

  • The exact SQL emitted by build_fetch_transaction_by_hash_stmt is what the wrapper sends, and
  • A correctly shaped JSON row round-trips into LocalDbTransaction.

This gives good coverage of the wrapper without over-reaching into implementation details; the only minor consideration is that depending on executor::tests::create_sql_capturing_callback couples these tests to another module’s test helpers, which is fine but could be brittle if those helpers are refactored. If that becomes an issue, consider moving the helper into a non-test-only module or re-exporting it at a stable path.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's fine as it is

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@findolor, sounds good! The current implementation works well for your use case.

(\ /)
( •.•)
/ > 🔍 noted


🧠 Learnings used
Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1860
File: packages/ui-components/src/lib/stores/transactionStore.ts:130-136
Timestamp: 2025-05-19T18:24:17.608Z
Learning: In the `rain.orderbook` project, the `getTransaction` function (and related entity fetch functions) use `wasmEncodedResult` to validate the returned data, ensuring that only valid data is returned. This makes a simple truthiness check (`!!data`) sufficient for the `isSuccess` predicate in `awaitSubgraphIndexing`.

Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2036
File: crates/js_api/src/filters/raindex_filter_store.rs:446-533
Timestamp: 2025-08-02T02:34:32.237Z
Learning: In the rainlanguage/rain.orderbook project's RaindexFilterStore WASM tests (crates/js_api/src/filters/raindex_filter_store.rs), brusherru decided to focus on testing only methods without side effects (that don't use web_sys) due to difficulties with mocking localStorage and window APIs in the WASM test environment. This pragmatic approach tests pure logic separately from browser integration.

Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2044
File: crates/common/src/raindex_client/vaults_list.rs:363-423
Timestamp: 2025-07-31T19:34:11.716Z
Learning: In the rainlanguage/rain.orderbook project, for WASM-exposed functionality like VaultsList, the team prefers to keep comprehensive tests in the non-WASM environment due to the complexity of recreating objects like RaindexVaults in WASM. WASM tests focus on basic functionality and error cases since the WASM code reuses the already-tested non-WASM implementation.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2237
File: crates/common/src/raindex_client/local_db/sync.rs:79-89
Timestamp: 2025-10-18T10:38:41.273Z
Learning: In `crates/common/src/raindex_client/local_db/sync.rs`, the sync_database method currently only supports indexing a single orderbook per chain ID, which is why `.first()` is used to select the orderbook configuration. Multi-orderbook support per chain ID is planned for future PRs.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1874
File: tauri-app/src-tauri/src/transaction_status.rs:87-114
Timestamp: 2025-05-27T06:16:12.195Z
Learning: In tauri-app/src-tauri/src/transaction_status.rs, testing one WriteTransactionStatus variant (like PendingPrepare) is sufficient for the update_status_and_emit method since all variants follow the same code path through the From<WriteTransactionStatus<T>> implementation.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1874
File: tauri-app/src-tauri/src/transaction_status.rs:69-127
Timestamp: 2025-05-27T06:16:35.738Z
Learning: In tauri-app/src-tauri/src/transaction_status.rs, directly accessing internal RwLock state in tests using `notice.0.read().unwrap()` is acceptable and does not require encapsulation through public getter methods.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2145
File: crates/common/src/raindex_client/local_db/query/fetch_orders/query.sql:6-7
Timestamp: 2025-10-06T11:28:30.692Z
Learning: In `crates/common/src/raindex_client/local_db/query/fetch_orders/query.sql`, the orderbook_address is currently hardcoded to '0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB' because the system only supports a single orderbook at the moment. Multiorderbook logic is not yet implemented and will be added in the future.

Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2036
File: packages/orderbook/test/js_api/filters.test.ts:19-36
Timestamp: 2025-08-02T03:55:25.215Z
Learning: In the rainlanguage/rain.orderbook project's WASM tests, the pattern of chaining `.value!` calls on WASM result types (like from VaultsFilterBuilder methods) is the established and preferred approach for handling WASM results, and should not be refactored into intermediate variables as it would add unnecessary verbosity without improving the code.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1715
File: crates/js_api/src/common/mod.rs:111-118
Timestamp: 2025-04-30T09:28:36.960Z
Learning: In the rain.orderbook repository, the WASM tests are already properly configured with conditional compilation using `#[cfg(target_family = "wasm")]` and `#[cfg(not(target_family = "wasm"))]`, and don't require additional `wasm_bindgen_test_configure!(run_in_browser)` directives.

Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1831
File: packages/ui-components/src/lib/types/transaction.ts:71-77
Timestamp: 2025-05-19T10:39:19.157Z
Learning: In the Rain Orderbook project, `orderHash` is intentionally typed as `string` (not `Hex`) in the `InternalTransactionArgs` interface because it matches the return type of the `getRemoveOrderCalldata` WASM function which returns `Promise<string>`. String operations like `.slice()` are performed on `orderHash` in the code. Meanwhile, `txHash` is typed as `Hex` for blockchain transaction hashes.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1715
File: crates/js_api/src/common/mod.rs:15-22
Timestamp: 2025-05-14T05:52:04.270Z
Learning: The project doesn't require `#[repr(transparent)]` for newtype wrappers in WASM contexts such as `AddOrderCalldata` and `RemoveOrderCalldata` as the current implementation is working as expected without it.

Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1870
File: packages/webapp/src/__tests__/WithdrawModal.test.ts:74-97
Timestamp: 2025-05-20T12:08:13.760Z
Learning: In the WithdrawModal test suite, testing that transactions are correctly passed to the transactionStore is considered sufficient coverage, without needing explicit tests for callback execution.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1903
File: crates/settings/src/yaml/orderbook.rs:371-377
Timestamp: 2025-06-17T16:21:24.384Z
Learning: In crates/settings/src/yaml/orderbook.rs tests, the user findolor considers RPC ordering in Vec<Url> assertions to be intentional and not a test brittleness issue. The ordering of RPCs in tests should be preserved as specified.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2202
File: crates/common/src/raindex_client/local_db/sync.rs:33-34
Timestamp: 2025-10-14T07:51:55.148Z
Learning: In `crates/common/src/raindex_client/local_db/sync.rs`, the hard-coded `DEFAULT_SYNC_CHAIN_ID` constant (set to `SUPPORTED_LOCAL_DB_CHAINS[0]`) will be replaced with proper chain ID handling in downstream PRs as part of the multi-network/orderbook implementation.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2145
File: crates/common/src/raindex_client/local_db/query/create_tables/query.sql:71-72
Timestamp: 2025-10-06T11:44:07.888Z
Learning: The local DB feature in the rain.orderbook codebase is not live yet (as of PR #2145), so schema migrations for existing databases are not required when modifying table structures in `crates/common/src/raindex_client/local_db/query/create_tables/query.sql`.

Learnt from: brusherru
Repo: rainlanguage/rain.orderbook PR: 2044
File: tauri-app/src/routes/orders/[chainId]-[orderbook]-[orderHash]/+page.svelte:76-78
Timestamp: 2025-07-31T19:03:56.594Z
Learning: In the rainlanguage/rain.orderbook project, when the Tauri app has issues preventing proper testing, the team prefers to defer Tauri-specific implementations to separate PRs rather than including untested code, especially for financial operations like withdrawals.

Learnt from: hardingjam
Repo: rainlanguage/rain.orderbook PR: 1504
File: tauri-app/src/routes/orders/[network]-[orderHash]/+page.svelte:33-37
Timestamp: 2025-04-08T16:35:15.127Z
Learning: In the Rain OrderBook project, the onDeposit and onWithdraw functions in page components are kept simple (just calling modal handlers and revalidating queries) because error handling for deposit and withdraw actions (including user cancellations and failed transactions) is handled within the modal components themselves.

Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.

Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.

Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.

Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.

Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T22:14:22.646Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, I must consistently report the PR size after EVERY new commit in the exact format "TOTAL=number\nADDITIONS=number\nDELETIONS=number" without any additional text or formatting blocks. The report must exclude lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, cargo.lock) and can be included either as part of the review or as a separate comment.

Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T22:14:22.646Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, I must consistently report the PR size after EVERY new commit in the exact format "TOTAL=number\nADDITIONS=number\nDELETIONS=number" without any formatting blocks. The report must exclude lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, cargo.lock) and can be included either as part of the review or as a separate comment.

Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2117
File: crates/js_api/src/gui/select_tokens.rs:421-424
Timestamp: 2025-09-02T08:04:34.729Z
Learning: User findolor in the rainlanguage/rain.orderbook codebase prefers not to change test code when tests are already passing, even if there appear to be type mismatches or potential issues. Working tests should be left alone unless there are actual errors.

Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:26:31.566Z
Learning: For PR #1884 and future PRs in rainlanguage/rain.orderbook repository, provide PR size reports in a separate comment with ONLY the exact format "TOTAL=number\nADDITIONS=number\nDELETIONS=number", without any additional text or explanation. Reports should exclude irrelevant files such as lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, cargo.lock).

}
1 change: 1 addition & 0 deletions crates/common/src/raindex_client/local_db/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod fetch_order_trades_count;
pub mod fetch_orders;
pub mod fetch_store_addresses;
pub mod fetch_tables;
pub mod fetch_transaction_by_hash;
pub mod fetch_vault_balance_changes;
pub mod fetch_vaults;
pub mod update_last_synced_block;
128 changes: 128 additions & 0 deletions crates/common/src/raindex_client/local_db/transactions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use super::super::transactions::RaindexTransaction;
use super::super::RaindexError;
use super::LocalDb;
use crate::local_db::query::fetch_transaction_by_hash::{
build_fetch_transaction_by_hash_stmt, LocalDbTransaction,
};
use crate::local_db::query::LocalDbQueryExecutor;
use crate::local_db::OrderbookIdentifier;
use alloy::primitives::B256;

pub struct LocalDbTransactions<'a> {
pub(crate) db: &'a LocalDb,
}

impl<'a> LocalDbTransactions<'a> {
pub(crate) fn new(db: &'a LocalDb) -> Self {
Self { db }
}

/// Fetch transaction info by transaction hash from the local DB.
/// Returns None if no transaction with that hash is found.
pub async fn get_by_tx_hash(
&self,
ob_id: &OrderbookIdentifier,
tx_hash: B256,
) -> Result<Option<RaindexTransaction>, RaindexError> {
let stmt = build_fetch_transaction_by_hash_stmt(ob_id, tx_hash);
let results: Vec<LocalDbTransaction> = self.db.query_json(&stmt).await?;

if let Some(local_tx) = results.into_iter().next() {
let tx = RaindexTransaction::from_local_parts(
local_tx.transaction_hash,
local_tx.sender,
local_tx.block_number,
local_tx.block_timestamp,
)?;
return Ok(Some(tx));
}

Ok(None)
}
}

#[cfg(test)]
mod tests {
#[cfg(target_family = "wasm")]
use super::*;

#[cfg(target_family = "wasm")]
mod wasm_tests {
use super::*;
use crate::raindex_client::local_db::executor::JsCallbackExecutor;
use crate::raindex_client::local_db::LocalDb;
use alloy::primitives::{address, b256};
use serde_json::json;
use wasm_bindgen_test::wasm_bindgen_test;
use wasm_bindgen_utils::prelude::*;

fn create_mock_callback(response_json: &str) -> js_sys::Function {
let json_str = response_json.to_string();
let result = WasmEncodedResult::Success::<String> {
value: json_str,
error: None,
};
let payload = js_sys::JSON::stringify(&serde_wasm_bindgen::to_value(&result).unwrap())
.unwrap()
.as_string()
.unwrap();

let closure =
Closure::wrap(Box::new(move |_sql: String, _params: JsValue| -> JsValue {
js_sys::JSON::parse(&payload).unwrap()
})
as Box<dyn Fn(String, JsValue) -> JsValue>);

closure.into_js_value().dyn_into().unwrap()
}

#[wasm_bindgen_test]
async fn test_get_by_tx_hash_returns_transaction_when_found() {
let tx_hash =
b256!("0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890");
let sender = address!("0x1111111111111111111111111111111111111111");
let orderbook = address!("0x2222222222222222222222222222222222222222");

let tx_json = json!([{
"transactionHash": tx_hash.to_string(),
"blockNumber": 12345,
"blockTimestamp": 1700000000,
"sender": sender.to_string()
}]);

let callback = create_mock_callback(&tx_json.to_string());
let exec = JsCallbackExecutor::from_ref(&callback);
let local_db = LocalDb::new(exec);

let transactions = LocalDbTransactions::new(&local_db);
let ob_id = OrderbookIdentifier::new(1, orderbook);

let result = transactions.get_by_tx_hash(&ob_id, tx_hash).await;

assert!(result.is_ok());
let tx = result.unwrap();
assert!(tx.is_some());
let tx = tx.unwrap();
assert_eq!(tx.id().to_lowercase(), tx_hash.to_string().to_lowercase());
}

#[wasm_bindgen_test]
async fn test_get_by_tx_hash_returns_none_when_not_found() {
let tx_hash =
b256!("0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890");
let orderbook = address!("0x2222222222222222222222222222222222222222");

let callback = create_mock_callback("[]");
let exec = JsCallbackExecutor::from_ref(&callback);
let local_db = LocalDb::new(exec);

let transactions = LocalDbTransactions::new(&local_db);
let ob_id = OrderbookIdentifier::new(1, orderbook);

let result = transactions.get_by_tx_hash(&ob_id, tx_hash).await;

assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
}
}
8 changes: 4 additions & 4 deletions crates/common/src/raindex_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ pub enum RaindexError {
NoNetworksConfigured,
#[error("Subgraph not configured for chain ID: {0}")]
SubgraphNotConfigured(String),
#[error("Subgraph did not index transaction {tx_hash:#x} after {attempts} attempts")]
SubgraphIndexingTimeout { tx_hash: B256, attempts: usize },
#[error("Transaction {tx_hash:#x} was not indexed after {attempts} attempts")]
TransactionIndexingTimeout { tx_hash: B256, attempts: usize },
#[error(transparent)]
YamlError(#[from] YamlError),
#[error(transparent)]
Expand Down Expand Up @@ -354,9 +354,9 @@ impl RaindexError {
RaindexError::SubgraphNotConfigured(chain_id) => {
format!("No subgraph is configured for chain ID '{}'.", chain_id)
}
RaindexError::SubgraphIndexingTimeout { tx_hash, attempts } => {
RaindexError::TransactionIndexingTimeout { tx_hash, attempts } => {
format!(
"Timeout waiting for the subgraph to index transaction {tx_hash:#x} after {attempts} attempts."
"Timeout waiting for transaction {tx_hash:#x} to be indexed after {attempts} attempts."
)
}
RaindexError::YamlError(err) => format!(
Expand Down
Loading