Skip to content
Draft
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
66,161 changes: 34,544 additions & 31,617 deletions bindings/python/lib/iota_sdk_ffi.py

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions crates/iota-sdk-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ base64ct = { version = "1.6.0", features = ["alloc", "std"] }
bcs = "0.1.6"
derive_more = { version = "2.0", features = ["from", "deref", "display"] }
hex = "0.4.3"
rand = "0.8"
roaring = { version = "0.11.2", default-features = false }
serde_json = "1.0.95"
tokio = { version = "1.36.0", features = ["time"] }
uniffi = { version = "0.29", features = ["cli", "tokio"] }

iota-crypto = { path = "../iota-crypto", features = ["bls12381", "ed25519", "secp256r1", "passkey", "secp256k1", "zklogin", "pem"] }
iota-graphql-client = { path = "../iota-graphql-client" }
iota-transaction-builder = { path = "../iota-transaction-builder" }
iota-types = { package = "iota-sdk-types", path = "../iota-sdk-types", features = ["hash", "rand"] }
rand = "0.8"
roaring = { version = "0.11.2", default-features = false }
serde_json = "1.0.95"
tokio = { version = "1.36.0", features = ["time"] }
uniffi = { git = "https://github.com/mozilla/uniffi-rs", features = ["cli", "tokio"] }
4 changes: 3 additions & 1 deletion crates/iota-sdk-ffi/src/types/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use crate::error::Result;
/// IOTA's binary representation of a `Digest` is prefixed with its length
/// meaning its serialized binary form (in bcs) is 33 bytes long vs a more
/// compact 32 bytes.
#[derive(derive_more::From, derive_more::Deref, uniffi::Object)]
// Implement Display via derive_more so wrapper delegates to inner type's Display.
#[derive(Debug, derive_more::From, derive_more::Deref, derive_more::Display, uniffi::Object)]
#[uniffi::export(Display)]
pub struct Digest(pub iota_types::Digest);

#[uniffi::export]
Expand Down
9 changes: 9 additions & 0 deletions crates/iota-sdk-ffi/src/types/execution_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ pub enum ExecutionStatus {
},
}

impl std::fmt::Display for ExecutionStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Success => write!(f, "SUCCESS"),
Self::Failure { .. } => write!(f, "FAILURE"),
}
}
}

impl From<iota_types::ExecutionStatus> for ExecutionStatus {
fn from(value: iota_types::ExecutionStatus) -> Self {
match value {
Expand Down
13 changes: 11 additions & 2 deletions crates/iota-sdk-ffi/src/types/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,16 @@ use crate::{
/// ```text
/// object-id = 32*OCTET
/// ```
#[derive(PartialEq, Eq, Hash, derive_more::From, derive_more::Deref, uniffi::Object)]
#[derive(
Debug,
PartialEq,
Eq,
Hash,
derive_more::From,
derive_more::Deref,
derive_more::Display,
uniffi::Object,
)]
#[uniffi::export(Hash)]
pub struct ObjectId(pub iota_types::ObjectId);

Expand Down Expand Up @@ -481,7 +490,7 @@ impl From<MoveStruct> for iota_types::MoveStruct {
/// owner-shared = %x02 u64
/// owner-immutable = %x03
/// ```
#[derive(derive_more::From, derive_more::Deref, derive_more::Display, uniffi::Object)]
#[derive(Debug, derive_more::From, derive_more::Deref, derive_more::Display, uniffi::Object)]
#[uniffi::export(Display)]
pub struct Owner(pub iota_types::Owner);

Expand Down
143 changes: 137 additions & 6 deletions crates/iota-sdk-ffi/src/types/transaction/v1.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use std::sync::Arc;
use std::{fmt, sync::Arc};

use iota_types::{GasCostSummary, IdOperation};

Expand Down Expand Up @@ -31,6 +31,7 @@ use crate::types::{
/// (option digest) ; auxiliary data digest
/// ```
#[derive(uniffi::Record)]
#[uniffi::export(Display)]
pub struct TransactionEffectsV1 {
/// The status of the execution
pub status: ExecutionStatus,
Expand Down Expand Up @@ -69,6 +70,68 @@ pub struct TransactionEffectsV1 {
pub auxiliary_data_digest: Option<Arc<Digest>>,
}

impl fmt::Display for TransactionEffectsV1 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Helper to format optional digest
let fmt_opt_digest = |d: &Option<Arc<Digest>>| -> String {
d.as_ref()
.map(|v| v.to_string())
.unwrap_or_else(|| "-".to_string())
};
let dependencies = if self.dependencies.is_empty() {
String::from("[]")
} else {
format!(
"[{}]",
self.dependencies
.iter()
.map(|d| d.to_string())
.collect::<Vec<_>>()
.join(", ")
)
};
let changed = if self.changed_objects.is_empty() {
String::from("[]")
} else {
format!(
"[{}]",
self.changed_objects
.iter()
.map(|c| c.to_string())
.collect::<Vec<_>>()
.join(", ")
)
};
let unchanged = if self.unchanged_shared_objects.is_empty() {
String::from("[]")
} else {
format!(
"[{}]",
self.unchanged_shared_objects
.iter()
.map(|c| c.to_string())
.collect::<Vec<_>>()
.join(", ")
)
};
write!(
f,
"TransactionEffectsV1(status={}, epoch={}, gas_used={}, tx_digest={}, gas_object_index={:?}, events_digest={}, dependencies={}, lamport_version={}, changed_objects={}, unchanged_shared_objects={}, auxiliary_data_digest={})",
self.status,
self.epoch,
self.gas_used,
self.transaction_digest,
self.gas_object_index,
fmt_opt_digest(&self.events_digest),
dependencies,
self.lamport_version,
changed,
unchanged,
fmt_opt_digest(&self.auxiliary_data_digest)
)
}
}

impl From<iota_types::TransactionEffectsV1> for TransactionEffectsV1 {
fn from(value: iota_types::TransactionEffectsV1) -> Self {
Self {
Expand Down Expand Up @@ -127,7 +190,8 @@ impl From<TransactionEffectsV1> for iota_types::TransactionEffectsV1 {
/// ```text
/// changed-object = object-id object-in object-out id-operation
/// ```
#[derive(uniffi::Record)]
#[derive(Debug, uniffi::Record)]
#[uniffi::export(Display)]
pub struct ChangedObject {
/// Id of the object
pub object_id: Arc<ObjectId>,
Expand All @@ -141,6 +205,12 @@ pub struct ChangedObject {
pub id_operation: IdOperation,
}

impl fmt::Display for ChangedObject {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ChangedObject(object_id={})", self.object_id)
}
}

impl From<iota_types::ChangedObject> for ChangedObject {
fn from(value: iota_types::ChangedObject) -> Self {
Self {
Expand Down Expand Up @@ -172,12 +242,23 @@ impl From<ChangedObject> for iota_types::ChangedObject {
/// ```text
/// unchanged-shared-object = object-id unchanged-shared-object-kind
/// ```
#[derive(uniffi::Record)]
#[derive(Debug, uniffi::Record)]
#[uniffi::export(Display)]
pub struct UnchangedSharedObject {
pub object_id: Arc<ObjectId>,
pub kind: UnchangedSharedKind,
}

impl fmt::Display for UnchangedSharedObject {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"UnchangedSharedObject(object_id={}, kind={})",
self.object_id, self.kind
)
}
}

impl From<iota_types::UnchangedSharedObject> for UnchangedSharedObject {
fn from(value: iota_types::UnchangedSharedObject) -> Self {
Self {
Expand Down Expand Up @@ -215,7 +296,7 @@ impl From<UnchangedSharedObject> for iota_types::UnchangedSharedObject {
/// cancelled = %x03 u64
/// per-epoch-config = %x04
/// ```
#[derive(uniffi::Enum)]
#[derive(Debug, uniffi::Enum)]
pub enum UnchangedSharedKind {
/// Read-only shared objects from the input. We don't really need
/// ObjectDigest for protocol correctness, but it will make it easier to
Expand Down Expand Up @@ -285,7 +366,7 @@ impl From<UnchangedSharedKind> for iota_types::UnchangedSharedKind {
/// object-in-missing = %x00
/// object-in-data = %x01 u64 digest owner
/// ```
#[derive(uniffi::Enum)]
#[derive(Debug, uniffi::Enum)]
pub enum ObjectIn {
Missing,
/// The old version, digest and owner.
Expand Down Expand Up @@ -346,7 +427,7 @@ impl From<ObjectIn> for iota_types::ObjectIn {
/// object-out-object-write = %x01 digest owner
/// object-out-package-write = %x02 version digest
/// ```
#[derive(uniffi::Enum)]
#[derive(Debug, uniffi::Enum)]
pub enum ObjectOut {
/// Same definition as in ObjectIn.
Missing,
Expand Down Expand Up @@ -376,6 +457,27 @@ impl From<iota_types::ObjectOut> for ObjectOut {
}
}

// Display impls for enums (placed after their definitions)
impl fmt::Display for UnchangedSharedKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UnchangedSharedKind::ReadOnlyRoot { version, digest } => {
write!(f, "ReadOnlyRoot(version={}, digest={})", version, digest)
}
UnchangedSharedKind::MutateDeleted { version } => {
write!(f, "MutateDeleted(version={})", version)
}
UnchangedSharedKind::ReadDeleted { version } => {
write!(f, "ReadDeleted(version={})", version)
}
UnchangedSharedKind::Cancelled { version } => {
write!(f, "Cancelled(version={})", version)
}
UnchangedSharedKind::PerEpochConfig => write!(f, "PerEpochConfig"),
}
}
}

impl From<ObjectOut> for iota_types::ObjectOut {
fn from(value: ObjectOut) -> Self {
match value {
Expand All @@ -392,6 +494,35 @@ impl From<ObjectOut> for iota_types::ObjectOut {
}
}

impl fmt::Display for ObjectIn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ObjectIn::Missing => write!(f, "Missing"),
ObjectIn::Data {
version,
digest,
owner: _,
} => {
write!(f, "Data(version={}, digest={})", version, digest)
}
}
}
}

impl fmt::Display for ObjectOut {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ObjectOut::Missing => write!(f, "Missing"),
ObjectOut::ObjectWrite { digest, owner: _ } => {
write!(f, "ObjectWrite(digest={})", digest)
}
ObjectOut::PackageWrite { version, digest } => {
write!(f, "PackageWrite(version={}, digest={})", version, digest)
}
}
}
}

/// Defines what happened to an ObjectId during execution
///
/// # BCS
Expand Down