From cd9801f74a8131a89d7b09e306ca20302e28560f Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 14 Feb 2025 13:17:50 +0800 Subject: [PATCH 1/4] feat(client): refactor proto for tokens & remove rpc --- Cargo.lock | 12 ++++++------ Cargo.toml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94cf10e..9be21f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,7 +1751,7 @@ dependencies = [ [[package]] name = "dojo-types" version = "1.2.0" -source = "git+https://github.com/dojoengine/dojo?rev=1aa06e1#1aa06e1cc9a060380b4d44ca2717a2ef97e1677c" +source = "git+https://github.com/dojoengine/dojo?rev=0a186fa#0a186faefcaad5f26a26598a87616253bb1fa9c1" dependencies = [ "anyhow", "cainome 0.4.11", @@ -1773,7 +1773,7 @@ dependencies = [ [[package]] name = "dojo-world" version = "1.2.0" -source = "git+https://github.com/dojoengine/dojo?rev=1aa06e1#1aa06e1cc9a060380b4d44ca2717a2ef97e1677c" +source = "git+https://github.com/dojoengine/dojo?rev=0a186fa#0a186faefcaad5f26a26598a87616253bb1fa9c1" dependencies = [ "anyhow", "async-trait", @@ -6838,7 +6838,7 @@ dependencies = [ [[package]] name = "torii-client" version = "1.2.0" -source = "git+https://github.com/dojoengine/dojo?rev=1aa06e1#1aa06e1cc9a060380b4d44ca2717a2ef97e1677c" +source = "git+https://github.com/dojoengine/dojo?rev=0a186fa#0a186faefcaad5f26a26598a87616253bb1fa9c1" dependencies = [ "async-trait", "crypto-bigint", @@ -6866,7 +6866,7 @@ dependencies = [ [[package]] name = "torii-grpc" version = "1.2.0" -source = "git+https://github.com/dojoengine/dojo?rev=1aa06e1#1aa06e1cc9a060380b4d44ca2717a2ef97e1677c" +source = "git+https://github.com/dojoengine/dojo?rev=0a186fa#0a186faefcaad5f26a26598a87616253bb1fa9c1" dependencies = [ "crypto-bigint", "dojo-types", @@ -6905,7 +6905,7 @@ dependencies = [ [[package]] name = "torii-relay" version = "1.2.0" -source = "git+https://github.com/dojoengine/dojo?rev=1aa06e1#1aa06e1cc9a060380b4d44ca2717a2ef97e1677c" +source = "git+https://github.com/dojoengine/dojo?rev=0a186fa#0a186faefcaad5f26a26598a87616253bb1fa9c1" dependencies = [ "anyhow", "futures", @@ -6923,7 +6923,7 @@ dependencies = [ [[package]] name = "torii-typed-data" version = "1.2.0" -source = "git+https://github.com/dojoengine/dojo?rev=1aa06e1#1aa06e1cc9a060380b4d44ca2717a2ef97e1677c" +source = "git+https://github.com/dojoengine/dojo?rev=0a186fa#0a186faefcaad5f26a26598a87616253bb1fa9c1" dependencies = [ "cainome 0.4.11", "crypto-bigint", diff --git a/Cargo.toml b/Cargo.toml index 8349ea8..4f6e767 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,14 +7,14 @@ version = "1.0.9" crate-type = ["cdylib", "rlib", "staticlib"] [dependencies] -dojo-world = { git = "https://github.com/dojoengine/dojo", rev = "1aa06e1" } -dojo-types = { git = "https://github.com/dojoengine/dojo", rev = "1aa06e1"} -torii-client = { git = "https://github.com/dojoengine/dojo", rev = "1aa06e1" } +dojo-world = { git = "https://github.com/dojoengine/dojo", rev = "0a186fa" } +dojo-types = { git = "https://github.com/dojoengine/dojo", rev = "0a186fa"} +torii-client = { git = "https://github.com/dojoengine/dojo", rev = "0a186fa" } torii-grpc = { git = "https://github.com/dojoengine/dojo", features = [ "client", -], rev = "1aa06e1" } -torii-typed-data = { git = "https://github.com/dojoengine/dojo", rev = "1aa06e1" } -torii-relay = { git = "https://github.com/dojoengine/dojo", rev = "1aa06e1" } +], rev = "0a186fa" } +torii-typed-data = { git = "https://github.com/dojoengine/dojo", rev = "0a186fa" } +torii-relay = { git = "https://github.com/dojoengine/dojo", rev = "0a186fa" } starknet = "0.12.0" starknet-crypto = "0.7.2" From 11e4338176a83b099107ced29581efd41bea0219 Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 14 Feb 2025 13:49:50 +0800 Subject: [PATCH 2/4] feat: update c bindings --- dojo.h | 51 ++++++++++++---- dojo.hpp | 33 ++++++---- dojo.pyx | 38 +++++++++--- src/c/mod.rs | 161 +++++++++++++++++++++++++++++++++++++------------ src/c/types.rs | 34 ++++++++--- 5 files changed, 238 insertions(+), 79 deletions(-) diff --git a/dojo.h b/dojo.h index ea7ff56..64e20d2 100644 --- a/dojo.h +++ b/dojo.h @@ -19,6 +19,7 @@ struct Subscription; struct EntityKeysClause; struct Struct; struct Token; +struct U256; struct TokenBalance; struct Provider; struct Account; @@ -211,6 +212,23 @@ typedef struct WorldMetadata { struct CArrayCHashItemFieldElementModelMetadata models; } WorldMetadata; +typedef enum ResultWorldMetadata_Tag { + OkWorldMetadata, + ErrWorldMetadata, +} ResultWorldMetadata_Tag; + +typedef struct ResultWorldMetadata { + ResultWorldMetadata_Tag tag; + union { + struct { + struct WorldMetadata ok; + }; + struct { + struct Error err; + }; + }; +} ResultWorldMetadata; + typedef enum ResultSubscription_Tag { OkSubscription, ErrSubscription, @@ -266,9 +284,13 @@ typedef struct ResultCArrayToken { }; } ResultCArrayToken; +typedef struct U256 { + uint8_t data[32]; +} U256; + typedef struct Token { - const char *id; struct FieldElement contract_address; + struct U256 token_id; const char *name; const char *symbol; uint8_t decimals; @@ -305,14 +327,10 @@ typedef struct IndexerUpdate { } IndexerUpdate; typedef struct TokenBalance { - uint64_t balance[4]; -#if defined(TARGET_POINTER_WIDTH_32) - uint32_t balance[8] -#endif - ; + struct U256 balance; struct FieldElement account_address; struct FieldElement contract_address; - const char *token_id; + struct U256 token_id; } TokenBalance; typedef enum ResultCArrayFieldElement_Tag { @@ -788,7 +806,6 @@ extern "C" { * Result containing pointer to new ToriiClient instance or error */ struct ResultToriiClient client_new(const char *torii_url, - const char *rpc_url, const char *libp2p_relay_url, struct FieldElement world); @@ -1015,7 +1032,7 @@ struct ResultCArrayEntity client_event_messages(struct ToriiClient *client, * # Returns * WorldMetadata structure containing world information */ -struct WorldMetadata client_metadata(struct ToriiClient *client); +struct ResultWorldMetadata client_metadata(struct ToriiClient *client); /** * Subscribes to entity state updates @@ -1121,7 +1138,9 @@ struct ResultSubscription client_on_starknet_event(struct ToriiClient *client, */ struct ResultCArrayToken client_tokens(struct ToriiClient *client, const struct FieldElement *contract_addresses, - uintptr_t contract_addresses_len); + uintptr_t contract_addresses_len, + const struct U256 *token_ids, + uintptr_t token_ids_len); /** * Subscribes to token updates @@ -1137,6 +1156,8 @@ struct ResultCArrayToken client_tokens(struct ToriiClient *client, struct ResultSubscription client_on_token_update(struct ToriiClient *client, const struct FieldElement *contract_addresses, uintptr_t contract_addresses_len, + const struct U256 *token_ids, + uintptr_t token_ids_len, void (*callback)(struct Token)); /** @@ -1156,7 +1177,9 @@ struct ResultCArrayTokenBalance client_token_balances(struct ToriiClient *client const struct FieldElement *contract_addresses, uintptr_t contract_addresses_len, const struct FieldElement *account_addresses, - uintptr_t account_addresses_len); + uintptr_t account_addresses_len, + const struct U256 *token_ids, + uintptr_t token_ids_len); /** * Subscribes to indexer updates @@ -1192,6 +1215,8 @@ struct ResultSubscription client_on_token_balance_update(struct ToriiClient *cli uintptr_t contract_addresses_len, const struct FieldElement *account_addresses, uintptr_t account_addresses_len, + const struct U256 *token_ids, + uintptr_t token_ids_len, void (*callback)(struct TokenBalance)); /** @@ -1213,7 +1238,9 @@ struct Resultbool client_update_token_balance_subscription(struct ToriiClient *c const struct FieldElement *contract_addresses, uintptr_t contract_addresses_len, const struct FieldElement *account_addresses, - uintptr_t account_addresses_len); + uintptr_t account_addresses_len, + const struct U256 *token_ids, + uintptr_t token_ids_len); /** * Serializes a string into a byte array diff --git a/dojo.hpp b/dojo.hpp index 0883a64..0331a02 100644 --- a/dojo.hpp +++ b/dojo.hpp @@ -592,9 +592,13 @@ struct Event { FieldElement transaction_hash; }; +struct U256 { + uint8_t data[32]; +}; + struct Token { - const char *id; FieldElement contract_address; + U256 token_id; const char *name; const char *symbol; uint8_t decimals; @@ -602,14 +606,10 @@ struct Token { }; struct TokenBalance { - uint64_t balance[4]; -#if defined(TARGET_POINTER_WIDTH_32) - uint32_t balance[8] -#endif - ; + U256 balance; FieldElement account_address; FieldElement contract_address; - const char *token_id; + U256 token_id; }; struct IndexerUpdate { @@ -947,7 +947,6 @@ extern "C" { /// # Returns /// Result containing pointer to new ToriiClient instance or error Result client_new(const char *torii_url, - const char *rpc_url, const char *libp2p_relay_url, FieldElement world); @@ -1144,7 +1143,7 @@ Result> client_event_messages(ToriiClient *client, /// /// # Returns /// WorldMetadata structure containing world information -WorldMetadata client_metadata(ToriiClient *client); +Result client_metadata(ToriiClient *client); /// Subscribes to entity state updates /// @@ -1236,7 +1235,9 @@ Result client_on_starknet_event(ToriiClient *client, /// Result containing array of Token information or error Result> client_tokens(ToriiClient *client, const FieldElement *contract_addresses, - uintptr_t contract_addresses_len); + uintptr_t contract_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len); /// Subscribes to token updates /// @@ -1250,6 +1251,8 @@ Result> client_tokens(ToriiClient *client, Result client_on_token_update(ToriiClient *client, const FieldElement *contract_addresses, uintptr_t contract_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len, void (*callback)(Token)); /// Gets token balances for given accounts and contracts @@ -1267,7 +1270,9 @@ Result> client_token_balances(ToriiClient *client, const FieldElement *contract_addresses, uintptr_t contract_addresses_len, const FieldElement *account_addresses, - uintptr_t account_addresses_len); + uintptr_t account_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len); /// Subscribes to indexer updates /// @@ -1299,6 +1304,8 @@ Result client_on_token_balance_update(ToriiClient *client, uintptr_t contract_addresses_len, const FieldElement *account_addresses, uintptr_t account_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len, void (*callback)(TokenBalance)); /// Updates an existing token balance subscription @@ -1318,7 +1325,9 @@ Result client_update_token_balance_subscription(ToriiClient *client, const FieldElement *contract_addresses, uintptr_t contract_addresses_len, const FieldElement *account_addresses, - uintptr_t account_addresses_len); + uintptr_t account_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len); /// Serializes a string into a byte array /// diff --git a/dojo.pyx b/dojo.pyx index 615b882..a645a44 100644 --- a/dojo.pyx +++ b/dojo.pyx @@ -136,6 +136,15 @@ cdef extern from *: FieldElement world_address; CArrayCHashItemFieldElementModelMetadata models; + cdef enum ResultWorldMetadata_Tag: + OkWorldMetadata, + ErrWorldMetadata, + + cdef struct ResultWorldMetadata: + ResultWorldMetadata_Tag tag; + WorldMetadata ok; + Error err; + cdef enum ResultSubscription_Tag: OkSubscription, ErrSubscription, @@ -171,9 +180,12 @@ cdef extern from *: CArrayToken ok; Error err; + cdef struct U256: + uint8_t data[32]; + cdef struct Token: - const char *id; FieldElement contract_address; + U256 token_id; const char *name; const char *symbol; uint8_t decimals; @@ -199,11 +211,10 @@ cdef extern from *: FieldElement contract_address; cdef struct TokenBalance: - uint64_t balance[4]; - uint32_t balance[8]; + U256 balance; FieldElement account_address; FieldElement contract_address; - const char *token_id; + U256 token_id; cdef enum ResultCArrayFieldElement_Tag: OkCArrayFieldElement, @@ -494,7 +505,6 @@ cdef extern from *: # # Returns # Result containing pointer to new ToriiClient instance or error ResultToriiClient client_new(const char *torii_url, - const char *rpc_url, const char *libp2p_relay_url, FieldElement world); @@ -691,7 +701,7 @@ cdef extern from *: # # # Returns # WorldMetadata structure containing world information - WorldMetadata client_metadata(ToriiClient *client); + ResultWorldMetadata client_metadata(ToriiClient *client); # Subscribes to entity state updates # @@ -783,7 +793,9 @@ cdef extern from *: # Result containing array of Token information or error ResultCArrayToken client_tokens(ToriiClient *client, const FieldElement *contract_addresses, - uintptr_t contract_addresses_len); + uintptr_t contract_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len); # Subscribes to token updates # @@ -797,6 +809,8 @@ cdef extern from *: ResultSubscription client_on_token_update(ToriiClient *client, const FieldElement *contract_addresses, uintptr_t contract_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len, void (*callback)(Token)); # Gets token balances for given accounts and contracts @@ -814,7 +828,9 @@ cdef extern from *: const FieldElement *contract_addresses, uintptr_t contract_addresses_len, const FieldElement *account_addresses, - uintptr_t account_addresses_len); + uintptr_t account_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len); # Subscribes to indexer updates # @@ -846,6 +862,8 @@ cdef extern from *: uintptr_t contract_addresses_len, const FieldElement *account_addresses, uintptr_t account_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len, void (*callback)(TokenBalance)); # Updates an existing token balance subscription @@ -865,7 +883,9 @@ cdef extern from *: const FieldElement *contract_addresses, uintptr_t contract_addresses_len, const FieldElement *account_addresses, - uintptr_t account_addresses_len); + uintptr_t account_addresses_len, + const U256 *token_ids, + uintptr_t token_ids_len); # Serializes a string into a byte array # diff --git a/src/c/mod.rs b/src/c/mod.rs index 2fe2c9d..1718d19 100644 --- a/src/c/mod.rs +++ b/src/c/mod.rs @@ -27,6 +27,7 @@ use axum::Router; use base64::engine::general_purpose::STANDARD as BASE64; use base64::Engine as _; use cainome::cairo_serde::{self, ByteArray, CairoSerde}; +use crypto_bigint::U256; use directories::ProjectDirs; use dojo_world::contracts::naming::compute_selector_from_tag; use futures::FutureExt; @@ -81,16 +82,14 @@ lazy_static! { #[no_mangle] pub unsafe extern "C" fn client_new( torii_url: *const c_char, - rpc_url: *const c_char, libp2p_relay_url: *const c_char, world: types::FieldElement, ) -> Result<*mut ToriiClient> { let torii_url = unsafe { CStr::from_ptr(torii_url).to_string_lossy().into_owned() }; - let rpc_url = unsafe { CStr::from_ptr(rpc_url).to_string_lossy().into_owned() }; let libp2p_relay_url = unsafe { CStr::from_ptr(libp2p_relay_url).to_string_lossy().into_owned() }; - let client_future = TClient::new(torii_url, rpc_url.clone(), libp2p_relay_url, (&world).into()); + let client_future = TClient::new(torii_url, libp2p_relay_url, (&world).into()); let client = match RUNTIME.block_on(client_future) { Ok(client) => client, @@ -739,9 +738,13 @@ pub unsafe extern "C" fn client_controllers( contract_addresses: *const types::FieldElement, contract_addresses_len: usize, ) -> Result> { - let contract_addresses = - unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; - let contract_addresses = contract_addresses.iter().map(|f| f.into()).collect::>(); + let contract_addresses = if contract_addresses.is_null() || contract_addresses_len == 0 { + Vec::new() + } else { + let addresses = + unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; + addresses.iter().map(|f| (&f.clone()).into()).collect::>() + }; let controllers_future = unsafe { (*client).inner.controllers(contract_addresses) }; @@ -815,8 +818,12 @@ pub unsafe extern "C" fn client_event_messages( /// # Returns /// WorldMetadata structure containing world information #[no_mangle] -pub unsafe extern "C" fn client_metadata(client: *mut ToriiClient) -> WorldMetadata { - unsafe { (&(*client).inner.metadata().clone()).into() } +pub unsafe extern "C" fn client_metadata(client: *mut ToriiClient) -> Result { + let metadata_future = unsafe { (*client).inner.metadata() }; + match RUNTIME.block_on(metadata_future) { + Ok(metadata) => Result::Ok((&metadata).into()), + Err(e) => Result::Err(e.into()), + } } /// Subscribes to entity state updates @@ -837,8 +844,12 @@ pub unsafe extern "C" fn client_on_entity_state_update( callback: unsafe extern "C" fn(types::FieldElement, CArray), ) -> Result<*mut Subscription> { let client = Arc::new(unsafe { &*client }); - let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; - let clauses = clauses.iter().map(|c| c.into()).collect::>(); + let clauses = if clauses.is_null() || clauses_len == 0 { + Vec::new() + } else { + let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; + clauses.iter().map(|c| c.into()).collect::>() + }; let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -898,8 +909,12 @@ pub unsafe extern "C" fn client_update_entity_subscription( clauses: *const EntityKeysClause, clauses_len: usize, ) -> Result { - let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; - let clauses = clauses.iter().map(|c| c.into()).collect::>(); + let clauses = if clauses.is_null() || clauses_len == 0 { + Vec::new() + } else { + let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; + clauses.iter().map(|c| c.into()).collect::>() + }; match RUNTIME.block_on( (*client) @@ -931,8 +946,12 @@ pub unsafe extern "C" fn client_on_event_message_update( callback: unsafe extern "C" fn(types::FieldElement, CArray), ) -> Result<*mut Subscription> { let client = Arc::new(unsafe { &*client }); - let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; - let clauses = clauses.iter().map(|c| c.into()).collect::>(); + let clauses = if clauses.is_null() || clauses_len == 0 { + Vec::new() + } else { + let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; + clauses.iter().map(|c| c.into()).collect::>() + }; let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -995,8 +1014,12 @@ pub unsafe extern "C" fn client_update_event_message_subscription( clauses_len: usize, historical: bool, ) -> Result { - let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; - let clauses = clauses.iter().map(|c| c.into()).collect::>(); + let clauses = if clauses.is_null() || clauses_len == 0 { + Vec::new() + } else { + let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; + clauses.iter().map(|c| c.into()).collect::>() + }; match RUNTIME.block_on((*client).inner.update_event_message_subscription( (*subscription).id.load(Ordering::SeqCst), @@ -1026,8 +1049,12 @@ pub unsafe extern "C" fn client_on_starknet_event( callback: unsafe extern "C" fn(Event), ) -> Result<*mut Subscription> { let client = Arc::new(unsafe { &*client }); - let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; - let clauses = clauses.iter().map(|c| c.into()).collect::>(); + let clauses = if clauses.is_null() || clauses_len == 0 { + Vec::new() + } else { + let clauses = unsafe { std::slice::from_raw_parts(clauses, clauses_len) }; + clauses.iter().map(|c| c.into()).collect::>() + }; let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -1080,12 +1107,24 @@ pub unsafe extern "C" fn client_tokens( client: *mut ToriiClient, contract_addresses: *const types::FieldElement, contract_addresses_len: usize, + token_ids: *const types::U256, + token_ids_len: usize, ) -> Result> { - let contract_addresses = - unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; - let contract_addresses = - contract_addresses.iter().map(|f| (&f.clone()).into()).collect::>(); - let tokens = match RUNTIME.block_on((*client).inner.tokens(contract_addresses)) { + let contract_addresses = if contract_addresses.is_null() || contract_addresses_len == 0 { + Vec::new() + } else { + let addresses = + unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; + addresses.iter().map(|f| (&f.clone()).into()).collect::>() + }; + let token_ids = if token_ids.is_null() || token_ids_len == 0 { + Vec::new() + } else { + let ids = unsafe { std::slice::from_raw_parts(token_ids, token_ids_len) }; + ids.iter().map(|f| (&f.clone()).into()).collect::>() + }; + + let tokens = match RUNTIME.block_on((*client).inner.tokens(contract_addresses, token_ids)) { Ok(tokens) => tokens, Err(e) => return Result::Err(e.into()), }; @@ -1108,6 +1147,8 @@ pub unsafe extern "C" fn client_on_token_update( client: *mut ToriiClient, contract_addresses: *const types::FieldElement, contract_addresses_len: usize, + token_ids: *const types::U256, + token_ids_len: usize, callback: unsafe extern "C" fn(Token), ) -> Result<*mut Subscription> { let client = Arc::new(unsafe { &*client }); @@ -1121,6 +1162,13 @@ pub unsafe extern "C" fn client_on_token_update( addresses.iter().map(|f| (&f.clone()).into()).collect::>() }; + let token_ids = if token_ids.is_null() || token_ids_len == 0 { + Vec::new() + } else { + let ids = unsafe { std::slice::from_raw_parts(token_ids, token_ids_len) }; + ids.iter().map(|f| (&f.clone()).into()).collect::>() + }; + let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -1133,7 +1181,7 @@ pub unsafe extern "C" fn client_on_token_update( let max_backoff = Duration::from_secs(60); loop { - let rcv = client_clone.inner.on_token_updated(contract_addresses.clone()).await; + let rcv = client_clone.inner.on_token_updated(contract_addresses.clone(), token_ids.clone()).await; if let Ok(rcv) = rcv { backoff = Duration::from_secs(1); // Reset backoff on successful connection @@ -1178,19 +1226,34 @@ pub unsafe extern "C" fn client_token_balances( contract_addresses_len: usize, account_addresses: *const types::FieldElement, account_addresses_len: usize, + token_ids: *const types::U256, + token_ids_len: usize, ) -> Result> { - let account_addresses = - unsafe { std::slice::from_raw_parts(account_addresses, account_addresses_len) }; - let account_addresses = - account_addresses.iter().map(|f| (&f.clone()).into()).collect::>(); + let account_addresses = if account_addresses.is_null() || account_addresses_len == 0 { + Vec::new() + } else { + let addresses = + unsafe { std::slice::from_raw_parts(account_addresses, account_addresses_len) }; + addresses.iter().map(|f| (&f.clone()).into()).collect::>() + }; - let contract_addresses = - unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; - let contract_addresses = - contract_addresses.iter().map(|f| (&f.clone()).into()).collect::>(); + let contract_addresses = if contract_addresses.is_null() || contract_addresses_len == 0 { + Vec::new() + } else { + let addresses = + unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; + addresses.iter().map(|f| (&f.clone()).into()).collect::>() + }; + + let token_ids = if token_ids.is_null() || token_ids_len == 0 { + Vec::new() + } else { + let ids = unsafe { std::slice::from_raw_parts(token_ids, token_ids_len) }; + ids.iter().map(|f| (&f.clone()).into()).collect::>() + }; let token_balances = match RUNTIME - .block_on((*client).inner.token_balances(account_addresses, contract_addresses)) + .block_on((*client).inner.token_balances(account_addresses, contract_addresses, token_ids)) { Ok(balances) => balances, Err(e) => return Result::Err(e.into()), @@ -1277,6 +1340,8 @@ pub unsafe extern "C" fn client_on_token_balance_update( contract_addresses_len: usize, account_addresses: *const types::FieldElement, account_addresses_len: usize, + token_ids: *const types::U256, + token_ids_len: usize, callback: unsafe extern "C" fn(TokenBalance), ) -> Result<*mut Subscription> { let client = Arc::new(unsafe { &*client }); @@ -1299,6 +1364,13 @@ pub unsafe extern "C" fn client_on_token_balance_update( addresses.iter().map(|f| (&f.clone()).into()).collect::>() }; + let token_ids = if token_ids.is_null() || token_ids_len == 0 { + Vec::new() + } else { + let ids = unsafe { std::slice::from_raw_parts(token_ids, token_ids_len) }; + ids.iter().map(|f| (&f.clone()).into()).collect::>() + }; + let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -1313,7 +1385,7 @@ pub unsafe extern "C" fn client_on_token_balance_update( loop { let rcv = client_clone .inner - .on_token_balance_updated(contract_addresses.clone(), account_addresses.clone()) + .on_token_balance_updated(contract_addresses.clone(), account_addresses.clone(), token_ids.clone()) .await; if let Ok(rcv) = rcv { @@ -1361,9 +1433,16 @@ pub unsafe extern "C" fn client_update_token_balance_subscription( contract_addresses_len: usize, account_addresses: *const types::FieldElement, account_addresses_len: usize, + token_ids: *const types::U256, + token_ids_len: usize, ) -> Result { - let clauses = unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; - let clauses = clauses.iter().map(|f| (&f.clone()).into()).collect::>(); + let contract_addresses = if contract_addresses.is_null() || contract_addresses_len == 0 { + Vec::new() + } else { + let addresses = + unsafe { std::slice::from_raw_parts(contract_addresses, contract_addresses_len) }; + addresses.iter().map(|f| (&f.clone()).into()).collect::>() + }; let account_addresses = if account_addresses.is_null() || account_addresses_len == 0 { Vec::new() @@ -1373,10 +1452,18 @@ pub unsafe extern "C" fn client_update_token_balance_subscription( addresses.iter().map(|f| (&f.clone()).into()).collect::>() }; + let token_ids = if token_ids.is_null() || token_ids_len == 0 { + Vec::new() + } else { + let ids = unsafe { std::slice::from_raw_parts(token_ids, token_ids_len) }; + ids.iter().map(|f| (&f.clone()).into()).collect::>() + }; + match RUNTIME.block_on((*client).inner.update_token_balance_subscription( (*subscription).id.load(Ordering::SeqCst), - clauses, + contract_addresses, account_addresses, + token_ids, )) { Ok(_) => Result::Ok(true), Err(e) => Result::Err(e.into()), diff --git a/src/c/types.rs b/src/c/types.rs index 3438a79..2386730 100644 --- a/src/c/types.rs +++ b/src/c/types.rs @@ -1,5 +1,6 @@ use std::ffi::{c_char, CStr, CString}; +use crypto_bigint::Encoding; use starknet::core::utils::get_selector_from_name; use torii_client::client::Client; @@ -103,8 +104,8 @@ impl From<&torii_grpc::types::Controller> for Controller { #[derive(Debug, Clone)] #[repr(C)] pub struct Token { - id: *const c_char, pub contract_address: FieldElement, + pub token_id: U256, pub name: *const c_char, pub symbol: *const c_char, pub decimals: u8, @@ -114,7 +115,7 @@ pub struct Token { impl From<&torii_grpc::types::Token> for Token { fn from(val: &torii_grpc::types::Token) -> Self { Token { - id: CString::new(val.id.clone()).unwrap().into_raw(), + token_id: (&val.token_id).into(), contract_address: (&val.contract_address).into(), name: CString::new(val.name.clone()).unwrap().into_raw(), symbol: CString::new(val.symbol.clone()).unwrap().into_raw(), @@ -127,22 +128,19 @@ impl From<&torii_grpc::types::Token> for Token { #[derive(Debug, Clone)] #[repr(C)] pub struct TokenBalance { - #[cfg(target_pointer_width = "64")] - pub balance: [u64; 4], - #[cfg(target_pointer_width = "32")] - pub balance: [u32; 8], + pub balance: U256, pub account_address: FieldElement, pub contract_address: FieldElement, - pub token_id: *const c_char, + pub token_id: U256, } impl From<&torii_grpc::types::TokenBalance> for TokenBalance { fn from(val: &torii_grpc::types::TokenBalance) -> Self { TokenBalance { - balance: val.balance.to_words(), + balance: (&val.balance).into(), account_address: (&val.account_address).into(), contract_address: (&val.contract_address).into(), - token_id: CString::new(val.token_id.clone()).unwrap().into_raw(), + token_id: (&val.token_id).into(), } } } @@ -349,6 +347,24 @@ where } } +#[derive(Clone, Debug)] +#[repr(C)] +pub struct U256 { + data: [u8; 32], +} + +impl From<&U256> for crypto_bigint::U256 { + fn from(val: &U256) -> Self { + crypto_bigint::U256::from_be_slice(&val.data) + } +} + +impl From<&crypto_bigint::U256> for U256 { + fn from(val: &crypto_bigint::U256) -> Self { + U256 { data: val.to_be_bytes() } + } +} + #[derive(Clone, Debug)] #[repr(C)] pub struct FieldElement { From d9fd673b243b0efcde36eac618c3a697cc178d43 Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 14 Feb 2025 14:07:55 +0800 Subject: [PATCH 3/4] update wasm --- src/wasm/mod.rs | 55 +++++++++++++++++++++++++++++++++++++++++------ src/wasm/types.rs | 11 ++++------ 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/wasm/mod.rs b/src/wasm/mod.rs index 20705cb..0a60c56 100644 --- a/src/wasm/mod.rs +++ b/src/wasm/mod.rs @@ -624,16 +624,25 @@ impl ToriiClient { /// # Returns /// Result containing token information or error #[wasm_bindgen(js_name = getTokens)] - pub async fn get_tokens(&self, contract_addresses: Vec) -> Result { + pub async fn get_tokens( + &self, + contract_addresses: Vec, + token_ids: Vec, + ) -> Result { let contract_addresses = contract_addresses .into_iter() .map(|c| Felt::from_str(&c)) .collect::, _>>() .map_err(|e| JsValue::from(format!("failed to parse contract addresses: {e}")))?; + let token_ids = token_ids + .into_iter() + .map(|t| U256::from_be_hex(&t)) + .collect::>(); + let tokens = self .inner - .tokens(contract_addresses) + .tokens(contract_addresses, token_ids) .await .map_err(|e| JsValue::from(format!("failed to get tokens: {e}")))?; @@ -652,6 +661,7 @@ impl ToriiClient { pub fn on_token_updated( &self, contract_addresses: Vec, + token_ids: Vec, callback: js_sys::Function, ) -> Result { #[cfg(feature = "console-error-panic")] @@ -666,6 +676,11 @@ impl ToriiClient { }) .collect::, _>>()?; + let token_ids = token_ids + .into_iter() + .map(|t| U256::from_be_hex(&t)) + .collect::>(); + let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -679,7 +694,10 @@ impl ToriiClient { let max_backoff = 60000; loop { - if let Ok(stream) = client.on_token_updated(contract_addresses.clone()).await { + if let Ok(stream) = client + .on_token_updated(contract_addresses.clone(), token_ids.clone()) + .await + { backoff = 1000; // Reset backoff on successful connection let mut stream = stream.take_until_if(tripwire.clone()); @@ -721,6 +739,7 @@ impl ToriiClient { &self, contract_addresses: Vec, account_addresses: Vec, + token_ids: Vec, ) -> Result { let account_addresses = account_addresses .into_iter() @@ -734,9 +753,14 @@ impl ToriiClient { .collect::, _>>() .map_err(|e| JsValue::from(format!("failed to parse contract addresses: {e}")))?; + let token_ids = token_ids + .into_iter() + .map(|t| U256::from_be_hex(&t)) + .collect::>(); + let token_balances = self .inner - .token_balances(account_addresses, contract_addresses) + .token_balances(account_addresses, contract_addresses, token_ids) .await .map_err(|e| JsValue::from(format!("failed to get token balances: {e}")))?; @@ -1129,6 +1153,7 @@ impl ToriiClient { &self, contract_addresses: Vec, account_addresses: Vec, + token_ids: Vec, callback: js_sys::Function, ) -> Result { #[cfg(feature = "console-error-panic")] @@ -1151,6 +1176,11 @@ impl ToriiClient { }) .collect::, _>>()?; + let token_ids = token_ids + .into_iter() + .map(|t| U256::from_be_hex(&t)) + .collect::>(); + let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -1165,7 +1195,11 @@ impl ToriiClient { loop { if let Ok(stream) = client - .on_token_balance_updated(contract_addresses.clone(), account_addresses.clone()) + .on_token_balance_updated( + contract_addresses.clone(), + account_addresses.clone(), + token_ids.clone(), + ) .await { backoff = 1000; // Reset backoff on successful connection @@ -1211,6 +1245,7 @@ impl ToriiClient { subscription: &Subscription, contract_addresses: Vec, account_addresses: Vec, + token_ids: Vec, ) -> Result<(), JsValue> { let account_addresses = account_addresses .into_iter() @@ -1229,11 +1264,17 @@ impl ToriiClient { }) .collect::, _>>()?; + let token_ids = token_ids + .into_iter() + .map(|t| U256::from_be_hex(&t)) + .collect::>(); + self.inner .update_token_balance_subscription( subscription.id.load(Ordering::SeqCst), contract_addresses, account_addresses, + token_ids, ) .await .map_err(|err| JsValue::from(format!("failed to update subscription: {err}"))) @@ -1296,12 +1337,12 @@ pub async fn create_client(config: ClientConfig) -> Result #[cfg(feature = "console-error-panic")] console_error_panic_hook::set_once(); - let ClientConfig { rpc_url, torii_url, relay_url, world_address } = config; + let ClientConfig { torii_url, relay_url, world_address } = config; let world_address = Felt::from_str(&world_address) .map_err(|err| JsValue::from(format!("failed to parse world address: {err}")))?; - let client = torii_client::client::Client::new(torii_url, rpc_url, relay_url, world_address) + let client = torii_client::client::Client::new(torii_url, relay_url, world_address) .await .map_err(|err| JsValue::from(format!("failed to build client: {err}")))?; diff --git a/src/wasm/types.rs b/src/wasm/types.rs index d05fcb5..bf89cbe 100644 --- a/src/wasm/types.rs +++ b/src/wasm/types.rs @@ -46,8 +46,8 @@ pub struct TokenBalances(pub Vec); #[derive(Tsify, Serialize, Deserialize, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct Token { - pub id: String, pub contract_address: String, + pub token_id: String, pub name: String, pub symbol: String, pub decimals: u8, @@ -57,8 +57,8 @@ pub struct Token { impl From<&torii_grpc::types::Token> for Token { fn from(value: &torii_grpc::types::Token) -> Self { Self { - id: value.id.clone(), contract_address: format!("{:#x}", value.contract_address), + token_id: format!("0x{:x}", value.token_id), name: value.name.clone(), symbol: value.symbol.clone(), decimals: value.decimals, @@ -82,7 +82,7 @@ impl From<&torii_grpc::types::TokenBalance> for TokenBalance { balance: format!("0x{:x}", value.balance), account_address: format!("{:#x}", value.account_address), contract_address: format!("{:#x}", value.contract_address), - token_id: value.token_id.to_string(), + token_id: format!("0x{:x}", value.token_id), } } } @@ -121,8 +121,6 @@ impl From<&torii_grpc::types::IndexerUpdate> for IndexerUpdate { #[derive(Tsify, Serialize, Deserialize, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct ClientConfig { - #[serde(rename = "rpcUrl")] - pub rpc_url: String, #[serde(rename = "toriiUrl")] pub torii_url: String, #[serde(rename = "relayUrl")] @@ -135,12 +133,11 @@ pub struct ClientConfig { impl ClientConfig { #[wasm_bindgen(constructor)] pub fn new( - rpc_url: String, torii_url: String, relay_url: String, world_address: String, ) -> Self { - Self { rpc_url, torii_url, relay_url, world_address } + Self { torii_url, relay_url, world_address } } } From dd7b997dd981e70be232f06e0c1226a00d673dde Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 14 Feb 2025 14:12:12 +0800 Subject: [PATCH 4/4] fmt --- src/c/mod.rs | 19 ++++++++++++++----- src/wasm/mod.rs | 30 +++++++----------------------- src/wasm/types.rs | 6 +----- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/src/c/mod.rs b/src/c/mod.rs index 1718d19..38d7f2d 100644 --- a/src/c/mod.rs +++ b/src/c/mod.rs @@ -1181,7 +1181,10 @@ pub unsafe extern "C" fn client_on_token_update( let max_backoff = Duration::from_secs(60); loop { - let rcv = client_clone.inner.on_token_updated(contract_addresses.clone(), token_ids.clone()).await; + let rcv = client_clone + .inner + .on_token_updated(contract_addresses.clone(), token_ids.clone()) + .await; if let Ok(rcv) = rcv { backoff = Duration::from_secs(1); // Reset backoff on successful connection @@ -1252,9 +1255,11 @@ pub unsafe extern "C" fn client_token_balances( ids.iter().map(|f| (&f.clone()).into()).collect::>() }; - let token_balances = match RUNTIME - .block_on((*client).inner.token_balances(account_addresses, contract_addresses, token_ids)) - { + let token_balances = match RUNTIME.block_on((*client).inner.token_balances( + account_addresses, + contract_addresses, + token_ids, + )) { Ok(balances) => balances, Err(e) => return Result::Err(e.into()), }; @@ -1385,7 +1390,11 @@ pub unsafe extern "C" fn client_on_token_balance_update( loop { let rcv = client_clone .inner - .on_token_balance_updated(contract_addresses.clone(), account_addresses.clone(), token_ids.clone()) + .on_token_balance_updated( + contract_addresses.clone(), + account_addresses.clone(), + token_ids.clone(), + ) .await; if let Ok(rcv) = rcv { diff --git a/src/wasm/mod.rs b/src/wasm/mod.rs index 0a60c56..6fbfa7f 100644 --- a/src/wasm/mod.rs +++ b/src/wasm/mod.rs @@ -635,10 +635,7 @@ impl ToriiClient { .collect::, _>>() .map_err(|e| JsValue::from(format!("failed to parse contract addresses: {e}")))?; - let token_ids = token_ids - .into_iter() - .map(|t| U256::from_be_hex(&t)) - .collect::>(); + let token_ids = token_ids.into_iter().map(|t| U256::from_be_hex(&t)).collect::>(); let tokens = self .inner @@ -676,10 +673,7 @@ impl ToriiClient { }) .collect::, _>>()?; - let token_ids = token_ids - .into_iter() - .map(|t| U256::from_be_hex(&t)) - .collect::>(); + let token_ids = token_ids.into_iter().map(|t| U256::from_be_hex(&t)).collect::>(); let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -694,9 +688,8 @@ impl ToriiClient { let max_backoff = 60000; loop { - if let Ok(stream) = client - .on_token_updated(contract_addresses.clone(), token_ids.clone()) - .await + if let Ok(stream) = + client.on_token_updated(contract_addresses.clone(), token_ids.clone()).await { backoff = 1000; // Reset backoff on successful connection @@ -753,10 +746,7 @@ impl ToriiClient { .collect::, _>>() .map_err(|e| JsValue::from(format!("failed to parse contract addresses: {e}")))?; - let token_ids = token_ids - .into_iter() - .map(|t| U256::from_be_hex(&t)) - .collect::>(); + let token_ids = token_ids.into_iter().map(|t| U256::from_be_hex(&t)).collect::>(); let token_balances = self .inner @@ -1176,10 +1166,7 @@ impl ToriiClient { }) .collect::, _>>()?; - let token_ids = token_ids - .into_iter() - .map(|t| U256::from_be_hex(&t)) - .collect::>(); + let token_ids = token_ids.into_iter().map(|t| U256::from_be_hex(&t)).collect::>(); let subscription_id = Arc::new(AtomicU64::new(0)); let (trigger, tripwire) = Tripwire::new(); @@ -1264,10 +1251,7 @@ impl ToriiClient { }) .collect::, _>>()?; - let token_ids = token_ids - .into_iter() - .map(|t| U256::from_be_hex(&t)) - .collect::>(); + let token_ids = token_ids.into_iter().map(|t| U256::from_be_hex(&t)).collect::>(); self.inner .update_token_balance_subscription( diff --git a/src/wasm/types.rs b/src/wasm/types.rs index bf89cbe..28d9c2f 100644 --- a/src/wasm/types.rs +++ b/src/wasm/types.rs @@ -132,11 +132,7 @@ pub struct ClientConfig { #[wasm_bindgen] impl ClientConfig { #[wasm_bindgen(constructor)] - pub fn new( - torii_url: String, - relay_url: String, - world_address: String, - ) -> Self { + pub fn new(torii_url: String, relay_url: String, world_address: String) -> Self { Self { torii_url, relay_url, world_address } } }