Skip to content
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
26 changes: 25 additions & 1 deletion src/c/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ use types::{
};
use url::Url;

use crate::c::types::{ControllerQuery, TokenBalanceQuery, TokenQuery};
use crate::c::types::{
ControllerQuery, TokenBalanceQuery, TokenQuery, Transaction, TransactionQuery,
};
use crate::constants;
use crate::types::{
Account, ControllerAccount, Provider, RegisterSessionResponse, RegisteredAccount,
Expand Down Expand Up @@ -816,6 +818,28 @@ pub unsafe extern "C" fn client_metadata(client: *mut ToriiClient) -> Result<Wor
}
}

/// Retrieves transactions matching the given query
///
/// # Parameters
/// * `client` - Pointer to ToriiClient instance
/// * `query` - Query parameters
///
/// # Returns
/// Result containing array of matching transactions or error
#[no_mangle]
pub unsafe extern "C" fn client_transactions(
client: *mut ToriiClient,
query: TransactionQuery,
) -> Result<Page<Transaction>> {
let query = query.into();
let transactions_future = unsafe { (*client).inner.transactions(query) };

match RUNTIME.block_on(transactions_future) {
Ok(transactions) => Result::Ok(transactions.into()),
Err(e) => Result::Err(e.into()),
}
}

/// Subscribes to entity state updates
///
/// # Parameters
Expand Down
106 changes: 106 additions & 0 deletions src/c/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,112 @@ impl From<TokenBalanceQuery> for torii_proto::TokenBalanceQuery {
}
}

#[derive(Clone, Debug)]
#[repr(C)]
pub struct TransactionQuery {
pub transaction_hashes: CArray<FieldElement>,
pub caller_addresses: CArray<FieldElement>,
pub contract_addresses: CArray<FieldElement>,
pub entrypoints: CArray<*const c_char>,
pub model_selectors: CArray<FieldElement>,
pub from_block: COption<u64>,
pub to_block: COption<u64>,
pub pagination: Pagination,
}

impl From<TransactionQuery> for torii_proto::TransactionQuery {
fn from(val: TransactionQuery) -> Self {
let entrypoints: Vec<*const c_char> = val.entrypoints.into();
let entrypoints = entrypoints
.into_iter()
.map(|e| unsafe { CStr::from_ptr(e).to_string_lossy().to_string() })
.collect::<Vec<String>>();

torii_proto::TransactionQuery {
pagination: val.pagination.into(),
transaction_hashes: val.transaction_hashes.into(),
caller_addresses: val.caller_addresses.into(),
contract_addresses: val.contract_addresses.into(),
entrypoints,
model_selectors: val.model_selectors.into(),
from_block: val.from_block.into(),
to_block: val.to_block.into(),
}
}
}

#[derive(Clone, Debug)]
#[repr(C)]
pub struct Transaction {
pub transaction_hash: FieldElement,
pub sender_address: FieldElement,
pub calldata: CArray<FieldElement>,
pub max_fee: FieldElement,
pub signature: CArray<FieldElement>,
pub nonce: FieldElement,
pub block_number: u64,
pub transaction_type: *const c_char,
pub block_timestamp: u64,
pub calls: CArray<TransactionCall>,
pub unique_models: CArray<FieldElement>,
}

impl From<torii_proto::Transaction> for Transaction {
fn from(val: torii_proto::Transaction) -> Self {
Transaction {
transaction_hash: val.transaction_hash.into(),
sender_address: val.sender_address.into(),
calldata: val.calldata.into(),
max_fee: val.max_fee.into(),
signature: val.signature.into(),
nonce: val.nonce.into(),
block_number: val.block_number,
transaction_type: CString::new(val.transaction_type).unwrap().into_raw(),
block_timestamp: val.block_timestamp.timestamp() as u64,
calls: val.calls.into(),
unique_models: val.unique_models.into(),
}
}
}

#[derive(Clone, Debug)]
#[repr(C)]
pub enum CallType {
Execute,
ExecuteFromOutside,
}

impl From<torii_proto::CallType> for CallType {
fn from(val: torii_proto::CallType) -> Self {
match val {
torii_proto::CallType::Execute => CallType::Execute,
torii_proto::CallType::ExecuteFromOutside => CallType::ExecuteFromOutside,
}
}
}

#[derive(Clone, Debug)]
#[repr(C)]
pub struct TransactionCall {
pub contract_address: FieldElement,
pub entrypoint: *const c_char,
pub calldata: CArray<FieldElement>,
pub call_type: CallType,
pub caller_address: FieldElement,
}

impl From<torii_proto::TransactionCall> for TransactionCall {
fn from(val: torii_proto::TransactionCall) -> Self {
TransactionCall {
contract_address: val.contract_address.into(),
entrypoint: CString::new(val.entrypoint).unwrap().into_raw(),
calldata: val.calldata.into(),
call_type: val.call_type.into(),
caller_address: val.caller_address.into(),
}
}
}

#[derive(Clone, Debug)]
#[repr(C)]
pub struct Query {
Expand Down
22 changes: 20 additions & 2 deletions src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ use wasm_bindgen::prelude::*;
use crate::constants;
use crate::types::{Account, Provider, Subscription, ToriiClient};
use crate::utils::watch_tx;
use crate::wasm::types::{ControllerQuery, TokenBalanceQuery, TokenQuery};
use crate::wasm::types::{ControllerQuery, TokenBalanceQuery, TokenQuery, TransactionQuery};

mod types;

use types::{
BlockId, Call, Calls, Clause, ClientConfig, Controller, Controllers, Entities, Entity,
IndexerUpdate, KeysClause, KeysClauses, Message, Model, Page, Query, Signature, Token,
TokenBalance, TokenBalances, TokenCollections, Tokens, WasmU256,
TokenBalance, TokenBalances, TokenCollections, Tokens, Transaction, Transactions, WasmU256,
};

const JSON_COMPAT_SERIALIZER: serde_wasm_bindgen::Serializer =
Expand Down Expand Up @@ -726,6 +726,24 @@ impl ToriiClient {
Ok(Controllers(controllers.into()))
}

/// Gets transactions matching the given query
///
/// # Parameters
/// * `query` - Query parameters
///
/// # Returns
/// Result containing transactions or error
#[wasm_bindgen(js_name = getTransactions)]
pub async fn get_transactions(&self, query: TransactionQuery) -> Result<Transactions, JsValue> {
let query = query.into();
let transactions = self
.inner
.transactions(query)
.await
.map_err(|e| JsValue::from(format!("failed to get transactions: {e}")))?;
Ok(Transactions(transactions.into()))
}

/// Gets token information for the given contract addresses
///
/// # Parameters
Expand Down
120 changes: 120 additions & 0 deletions src/wasm/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,126 @@ impl From<torii_proto::TokenBalance> for TokenBalance {
}
}

#[derive(Tsify, Serialize, Deserialize, Debug)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct TransactionQuery {
pub transaction_hashes: Vec<String>,
pub caller_addresses: Vec<String>,
pub contract_addresses: Vec<String>,
pub entrypoints: Vec<String>,
pub model_selectors: Vec<String>,
pub from_block: Option<u64>,
pub to_block: Option<u64>,
pub pagination: Pagination,
}

impl From<TransactionQuery> for torii_proto::TransactionQuery {
fn from(val: TransactionQuery) -> Self {
torii_proto::TransactionQuery {
pagination: val.pagination.into(),
transaction_hashes: val
.transaction_hashes
.into_iter()
.map(|h| Felt::from_str(h.as_str()).unwrap())
.collect(),
caller_addresses: val
.caller_addresses
.into_iter()
.map(|h| Felt::from_str(h.as_str()).unwrap())
.collect(),
contract_addresses: val
.contract_addresses
.into_iter()
.map(|h| Felt::from_str(h.as_str()).unwrap())
.collect(),
entrypoints: val.entrypoints,
model_selectors: val
.model_selectors
.into_iter()
.map(|h| Felt::from_str(h.as_str()).unwrap())
.collect(),
from_block: val.from_block.into(),
to_block: val.to_block.into(),
}
}
}

#[derive(Tsify, Serialize, Deserialize, Debug)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct Transactions(pub Page<Transaction>);

#[derive(Tsify, Serialize, Deserialize, Debug)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct Transaction {
pub transaction_hash: String,
pub sender_address: String,
pub calldata: Vec<String>,
pub max_fee: String,
pub signature: Vec<String>,
pub nonce: String,
pub block_number: u64,
pub transaction_type: String,
pub block_timestamp: u64,
pub calls: Vec<TransactionCall>,
pub unique_models: Vec<String>,
}

impl From<torii_proto::Transaction> for Transaction {
fn from(val: torii_proto::Transaction) -> Self {
Transaction {
transaction_hash: format!("{:#x}", val.transaction_hash),
sender_address: format!("{:#x}", val.sender_address),
calldata: val.calldata.into_iter().map(|c| format!("{:#x}", c)).collect(),
max_fee: format!("{:#x}", val.max_fee),
signature: val.signature.into_iter().map(|s| format!("{:#x}", s)).collect(),
nonce: format!("{:#x}", val.nonce),
block_number: val.block_number,
transaction_type: val.transaction_type,
block_timestamp: val.block_timestamp.timestamp() as u64,
calls: val.calls.into_iter().map(|c| c.into()).collect(),
unique_models: val.unique_models.into_iter().map(|m| format!("{:#x}", m)).collect(),
}
}
}

#[derive(Tsify, Serialize, Deserialize, Debug)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub enum CallType {
Execute,
ExecuteFromOutside,
}

impl From<torii_proto::CallType> for CallType {
fn from(val: torii_proto::CallType) -> Self {
match val {
torii_proto::CallType::Execute => CallType::Execute,
torii_proto::CallType::ExecuteFromOutside => CallType::ExecuteFromOutside,
}
}
}

#[derive(Tsify, Serialize, Deserialize, Debug)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct TransactionCall {
pub contract_address: String,
pub entrypoint: String,
pub calldata: Vec<String>,
pub call_type: CallType,
pub caller_address: String,
}

impl From<torii_proto::TransactionCall> for TransactionCall {
fn from(val: torii_proto::TransactionCall) -> Self {
TransactionCall {
contract_address: format!("{:#x}", val.contract_address),
entrypoint: val.entrypoint,
calldata: val.calldata.into_iter().map(|c| format!("{:#x}", c)).collect(),
call_type: val.call_type.into(),
caller_address: format!("{:#x}", val.caller_address),
}
}
}

#[derive(Tsify, Serialize, Deserialize, Debug)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct ControllerQuery {
Expand Down