Skip to content

Commit b017042

Browse files
authored
feat(iota-sdk-ffi): DryRunResult, Event, TransactionEvent records (#71)
* feat(iota-sdk-ffi): records for: DryRunResult, Event, TransactionEvent, ObjectRef, Validator, BigInt, DateTime, PageInfo, ValidatorSet, ValidatorConnection, GQLAddress, ValidatorCredentials, MoveObject * clippy * address review comments * still need derive_more::From for some objects * revert to uniffi::remote * fmt * fix merge
1 parent bb3b374 commit b017042

File tree

3 files changed

+252
-21
lines changed

3 files changed

+252
-21
lines changed

crates/iota-graphql-client/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ impl DynamicFieldOutput {
131131
pub fn deserialize_name<T: DeserializeOwned>(&self, expected_type: &TypeTag) -> Result<T> {
132132
assert_eq!(
133133
expected_type, &self.name.type_,
134-
"Expected type {}, but got {}",
135-
expected_type, &self.name.type_
134+
"Expected type {expected_type}, but got {}",
135+
&self.name.type_
136136
);
137137

138138
let bcs = &self.name.bcs;

crates/iota-sdk-ffi/src/types/graphql.rs

Lines changed: 249 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
// Copyright (c) 2025 IOTA Stiftung
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use std::sync::Arc;
4+
use std::{str::FromStr, sync::Arc};
55

66
use base64ct::Encoding;
77
use iota_graphql_client::{
88
pagination::{Direction, PaginationFilter},
9-
query_types::{
10-
Base64, GQLAddress, MoveObject, PageInfo, TransactionBlockKindInput, ValidatorCredentials,
11-
},
9+
query_types::{Base64, PageInfo, TransactionBlockKindInput, ValidatorCredentials},
1210
};
11+
use iota_types::{Identifier, StructTag, TransactionDigest};
1312

1413
use crate::types::{
1514
address::Address,
@@ -23,7 +22,7 @@ pub struct TransactionMetadata {
2322
#[uniffi(default = None)]
2423
pub gas_budget: Option<u64>,
2524
#[uniffi(default = None)]
26-
pub gas_objects: Option<Vec<Arc<ObjectRef>>>,
25+
pub gas_objects: Option<Vec<ObjectRef>>,
2726
#[uniffi(default = None)]
2827
pub gas_price: Option<u64>,
2928
#[uniffi(default = None)]
@@ -38,7 +37,7 @@ impl From<iota_graphql_client::query_types::TransactionMetadata> for Transaction
3837
gas_budget: value.gas_budget,
3938
gas_objects: value
4039
.gas_objects
41-
.map(|v| v.into_iter().map(Into::into).map(Arc::new).collect()),
40+
.map(|v| v.into_iter().map(Into::into).collect()),
4241
gas_price: value.gas_price,
4342
gas_sponsor: value.gas_sponsor.map(Into::into).map(Arc::new),
4443
sender: value.sender.map(Into::into).map(Arc::new),
@@ -52,7 +51,7 @@ impl From<TransactionMetadata> for iota_graphql_client::query_types::Transaction
5251
gas_budget: value.gas_budget,
5352
gas_objects: value
5453
.gas_objects
55-
.map(|v| v.into_iter().map(|o| o.0.clone()).collect()),
54+
.map(|v| v.into_iter().map(Into::into).collect()),
5655
gas_price: value.gas_price,
5756
gas_sponsor: value.gas_sponsor.map(|a| **a),
5857
sender: value.sender.map(|a| **a),
@@ -149,14 +148,108 @@ impl From<TransactionsFilter> for iota_graphql_client::query_types::Transactions
149148
}
150149
}
151150

152-
#[derive(Clone, Debug, derive_more::From, uniffi::Object)]
153-
pub struct DryRunResult(pub iota_graphql_client::DryRunResult);
151+
/// The result of a dry run, which includes the effects of the transaction and
152+
/// any errors that may have occurred.
153+
#[derive(Clone, Debug, uniffi::Record)]
154+
pub struct DryRunResult {
155+
pub effects: Option<Arc<TransactionEffects>>,
156+
pub error: Option<String>,
157+
}
154158

155-
#[derive(Clone, Debug, derive_more::From, uniffi::Object)]
156-
pub struct Event(pub iota_types::Event);
159+
impl From<iota_graphql_client::DryRunResult> for DryRunResult {
160+
fn from(value: iota_graphql_client::DryRunResult) -> Self {
161+
DryRunResult {
162+
effects: value.effects.map(|e| Arc::new(e.into())),
163+
error: value.error,
164+
}
165+
}
166+
}
157167

158-
#[derive(Clone, Debug, derive_more::From, uniffi::Object)]
159-
pub struct ObjectRef(pub iota_graphql_client::query_types::ObjectRef);
168+
impl From<DryRunResult> for iota_graphql_client::DryRunResult {
169+
fn from(value: DryRunResult) -> Self {
170+
iota_graphql_client::DryRunResult {
171+
effects: value.effects.map(|e| e.0.clone()),
172+
error: value.error,
173+
}
174+
}
175+
}
176+
177+
/// An event
178+
///
179+
/// # BCS
180+
///
181+
/// The BCS serialized form for this type is defined by the following ABNF:
182+
///
183+
/// ```text
184+
/// event = object-id identifier address struct-tag bytes
185+
/// ```
186+
#[derive(Clone, Debug, uniffi::Record)]
187+
pub struct Event {
188+
/// Package id of the top-level function invoked by a MoveCall command which
189+
/// triggered this event to be emitted.
190+
pub package_id: Arc<ObjectId>,
191+
/// Module name of the top-level function invoked by a MoveCall command
192+
/// which triggered this event to be emitted.
193+
pub module: String,
194+
/// Address of the account that sent the transaction where this event was
195+
/// emitted.
196+
pub sender: Arc<Address>,
197+
/// The type of the event emitted
198+
pub type_: String,
199+
/// BCS serialized bytes of the event
200+
pub contents: Vec<u8>,
201+
}
202+
203+
impl From<iota_types::Event> for Event {
204+
fn from(value: iota_types::Event) -> Self {
205+
Self {
206+
package_id: Arc::new(value.package_id.into()),
207+
module: value.module.to_string(),
208+
sender: Arc::new(value.sender.into()),
209+
type_: value.type_.to_string(),
210+
contents: value.contents,
211+
}
212+
}
213+
}
214+
215+
impl From<Event> for iota_types::Event {
216+
fn from(value: Event) -> Self {
217+
Self {
218+
package_id: (**value.package_id),
219+
module: Identifier::from_str(&value.module).unwrap(),
220+
sender: (**value.sender),
221+
type_: StructTag::from_str(&value.type_).unwrap(),
222+
contents: value.contents,
223+
}
224+
}
225+
}
226+
227+
#[derive(Clone, Debug, uniffi::Record)]
228+
pub struct ObjectRef {
229+
pub address: Arc<ObjectId>,
230+
pub digest: String,
231+
pub version: u64,
232+
}
233+
234+
impl From<iota_graphql_client::query_types::ObjectRef> for ObjectRef {
235+
fn from(value: iota_graphql_client::query_types::ObjectRef) -> Self {
236+
Self {
237+
address: Arc::new(value.address.into()),
238+
digest: value.digest.to_string(),
239+
version: value.version,
240+
}
241+
}
242+
}
243+
244+
impl From<ObjectRef> for iota_graphql_client::query_types::ObjectRef {
245+
fn from(value: ObjectRef) -> Self {
246+
Self {
247+
address: (**value.address),
248+
digest: value.digest,
249+
version: value.version,
250+
}
251+
}
252+
}
160253

161254
#[derive(Clone, Debug, derive_more::From, uniffi::Object)]
162255
pub struct Epoch(pub iota_graphql_client::query_types::Epoch);
@@ -420,8 +513,9 @@ impl From<Validator> for iota_graphql_client::query_types::Validator {
420513
Self {
421514
apy: value.apy,
422515
address: GQLAddress {
423-
address: **value.address,
424-
},
516+
address: value.address.clone(),
517+
}
518+
.into(),
425519
commission_rate: value.commission_rate,
426520
credentials: value.credentials,
427521
description: value.description,
@@ -433,8 +527,11 @@ impl From<Validator> for iota_graphql_client::query_types::Validator {
433527
next_epoch_credentials: value.next_epoch_credentials,
434528
next_epoch_gas_price: value.next_epoch_gas_price.map(|v| v.to_string().into()),
435529
next_epoch_stake: value.next_epoch_stake.map(|v| v.to_string().into()),
436-
operation_cap: value.operation_cap.map(|o| MoveObject {
437-
bcs: Some(base64ct::Base64::encode_string(&o).into()),
530+
operation_cap: value.operation_cap.map(|o| {
531+
MoveObject {
532+
bcs: Some(base64ct::Base64::encode_string(&o)),
533+
}
534+
.into()
438535
}),
439536
pending_pool_token_withdraw: value
440537
.pending_pool_token_withdraw
@@ -447,7 +544,7 @@ impl From<Validator> for iota_graphql_client::query_types::Validator {
447544
project_url: value.project_url,
448545
rewards_pool: value.rewards_pool.map(|v| v.to_string().into()),
449546
staking_pool_activation_epoch: value.staking_pool_activation_epoch,
450-
staking_pool_id: **value.staking_pool_id,
547+
staking_pool_id: (**value.staking_pool_id),
451548
staking_pool_iota_balance: value
452549
.staking_pool_iota_balance
453550
.map(|v| v.to_string().into()),
@@ -478,30 +575,164 @@ pub enum TransactionBlockKindInput {
478575
EndOfEpochTx,
479576
}
480577

578+
#[derive(Clone, Debug, uniffi::Record)]
579+
pub struct BigInt {
580+
pub value: String,
581+
}
582+
583+
impl From<iota_graphql_client::query_types::BigInt> for BigInt {
584+
fn from(value: iota_graphql_client::query_types::BigInt) -> Self {
585+
BigInt { value: value.0 }
586+
}
587+
}
588+
589+
impl From<BigInt> for iota_graphql_client::query_types::BigInt {
590+
fn from(value: BigInt) -> Self {
591+
iota_graphql_client::query_types::BigInt(value.value)
592+
}
593+
}
594+
595+
#[derive(Clone, Debug, uniffi::Record)]
596+
pub struct DateTime {
597+
pub value: String,
598+
}
599+
600+
impl From<iota_graphql_client::query_types::DateTime> for DateTime {
601+
fn from(value: iota_graphql_client::query_types::DateTime) -> Self {
602+
DateTime { value: value.0 }
603+
}
604+
}
605+
606+
impl From<DateTime> for iota_graphql_client::query_types::DateTime {
607+
fn from(value: DateTime) -> Self {
608+
iota_graphql_client::query_types::DateTime(value.value)
609+
}
610+
}
611+
612+
/// Information about pagination in a connection.
481613
#[uniffi::remote(Record)]
482614
pub struct PageInfo {
615+
/// When paginating backwards, are there more items?
483616
pub has_previous_page: bool,
617+
/// Are there more items when paginating forwards?
484618
pub has_next_page: bool,
619+
/// When paginating backwards, the cursor to continue.
620+
#[uniffi(default = None)]
485621
pub start_cursor: Option<String>,
622+
/// When paginating forwards, the cursor to continue.
623+
#[uniffi(default = None)]
486624
pub end_cursor: Option<String>,
487625
}
488626

627+
/// Pagination options for querying the GraphQL server. It defaults to forward
628+
/// pagination with the GraphQL server's max page size.
489629
#[uniffi::remote(Record)]
490630
pub struct PaginationFilter {
491631
pub direction: Direction,
492632
#[uniffi(default = None)]
493633
pub cursor: Option<String>,
634+
/// The maximum number of items to return. If this is omitted, it will
635+
/// lazily query the service configuration for the max page size.
494636
#[uniffi(default = None)]
495637
pub limit: Option<i32>,
496638
}
497639

640+
/// Pagination direction.
498641
#[uniffi::remote(Enum)]
499642
pub enum Direction {
500643
#[default]
501644
Forward,
502645
Backward,
503646
}
504647

648+
#[derive(Clone, Debug, uniffi::Record)]
649+
pub struct ValidatorSet {
650+
pub active_validators: ValidatorConnection,
651+
}
652+
653+
impl From<iota_graphql_client::query_types::ValidatorSet> for ValidatorSet {
654+
fn from(value: iota_graphql_client::query_types::ValidatorSet) -> Self {
655+
ValidatorSet {
656+
active_validators: value.active_validators.into(),
657+
}
658+
}
659+
}
660+
661+
impl From<ValidatorSet> for iota_graphql_client::query_types::ValidatorSet {
662+
fn from(value: ValidatorSet) -> Self {
663+
iota_graphql_client::query_types::ValidatorSet {
664+
active_validators: value.active_validators.into(),
665+
}
666+
}
667+
}
668+
669+
#[derive(Clone, Debug, uniffi::Record)]
670+
pub struct ValidatorConnection {
671+
pub page_info: PageInfo,
672+
pub nodes: Vec<Validator>,
673+
}
674+
675+
impl From<iota_graphql_client::query_types::ValidatorConnection> for ValidatorConnection {
676+
fn from(value: iota_graphql_client::query_types::ValidatorConnection) -> Self {
677+
ValidatorConnection {
678+
page_info: value.page_info,
679+
nodes: value.nodes.into_iter().map(Into::into).collect(),
680+
}
681+
}
682+
}
683+
684+
impl From<ValidatorConnection> for iota_graphql_client::query_types::ValidatorConnection {
685+
fn from(value: ValidatorConnection) -> Self {
686+
iota_graphql_client::query_types::ValidatorConnection {
687+
page_info: value.page_info,
688+
nodes: value.nodes.into_iter().map(Into::into).collect(),
689+
}
690+
}
691+
}
692+
693+
#[derive(Clone, Debug, uniffi::Record)]
694+
pub struct GQLAddress {
695+
pub address: Arc<Address>,
696+
}
697+
698+
impl From<iota_graphql_client::query_types::GQLAddress> for GQLAddress {
699+
fn from(value: iota_graphql_client::query_types::GQLAddress) -> Self {
700+
GQLAddress {
701+
address: Arc::new(value.address.into()),
702+
}
703+
}
704+
}
705+
706+
impl From<GQLAddress> for iota_graphql_client::query_types::GQLAddress {
707+
fn from(value: GQLAddress) -> Self {
708+
iota_graphql_client::query_types::GQLAddress {
709+
address: (**value.address),
710+
}
711+
}
712+
}
713+
714+
#[derive(Clone, Debug, uniffi::Record)]
715+
pub struct MoveObject {
716+
#[uniffi(default = None)]
717+
pub bcs: Option<String>,
718+
}
719+
720+
impl From<iota_graphql_client::query_types::MoveObject> for MoveObject {
721+
fn from(value: iota_graphql_client::query_types::MoveObject) -> Self {
722+
MoveObject {
723+
bcs: value.bcs.map(|v| v.0),
724+
}
725+
}
726+
}
727+
728+
impl From<MoveObject> for iota_graphql_client::query_types::MoveObject {
729+
fn from(value: MoveObject) -> Self {
730+
iota_graphql_client::query_types::MoveObject {
731+
bcs: value.bcs.map(iota_graphql_client::query_types::Base64),
732+
}
733+
}
734+
}
735+
505736
#[derive(Clone, Debug, derive_more::From, uniffi::Object)]
506737
pub struct ProtocolConfigs(pub iota_graphql_client::query_types::ProtocolConfigs);
507738

crates/iota-sdk-ffi/src/uniffi_helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ define_paged_record!(CheckpointSummaryPage, CheckpointSummary);
3939
define_paged_record!(SignedTransactionPage, SignedTransaction);
4040
define_paged_record!(TransactionDataEffectsPage, TransactionDataEffects);
4141
define_paged_record!(DynamicFieldOutputPage, DynamicFieldOutput);
42+
define_paged_record!(EventPage, Event);
4243
define_paged_record!(ValidatorPage, Validator);
4344

4445
macro_rules! define_paged_object {
@@ -69,7 +70,6 @@ macro_rules! define_paged_object {
6970
};
7071
}
7172

72-
define_paged_object!(EventPage, Event);
7373
define_paged_object!(CoinPage, Coin);
7474
define_paged_object!(ObjectPage, Object);
7575
define_paged_object!(TransactionEffectsPage, TransactionEffects);

0 commit comments

Comments
 (0)