Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e7d1225
Add library docs
DaughterOfMars Oct 14, 2025
d63b8f5
Add method docs and more info
DaughterOfMars Oct 14, 2025
f800cea
missed
DaughterOfMars Oct 14, 2025
e02f672
use main fn
DaughterOfMars Oct 14, 2025
c81e124
review
DaughterOfMars Oct 14, 2025
f8defa8
Update crates/iota-transaction-builder/src/lib.rs
DaughterOfMars Oct 16, 2025
e53a9f0
fix fmt
DaughterOfMars Oct 16, 2025
cb70f29
Merge branch 'sdk-bindings' into chore/txn-builder-docs
DaughterOfMars Oct 16, 2025
ba68f92
review and add docs to FFI
DaughterOfMars Oct 20, 2025
a6cfbf6
Merge branch 'sdk-bindings' into chore/txn-builder-docs
DaughterOfMars Oct 20, 2025
b738f58
fix link
DaughterOfMars Oct 20, 2025
b51c4ac
fix docs
DaughterOfMars Oct 20, 2025
b681377
move lib doc to README
DaughterOfMars Oct 20, 2025
37a2138
Remove feature flag section
DaughterOfMars Oct 20, 2025
67da2c8
Update crates/iota-sdk-ffi/src/transaction_builder/mod.rs
DaughterOfMars Oct 20, 2025
367c635
allow some more lints and re gen bindings
DaughterOfMars Oct 20, 2025
e3af51d
Merge branch 'chore/txn-builder-docs' of https://github.com/iotaledge…
DaughterOfMars Oct 20, 2025
3be7d0c
Merge branch 'sdk-bindings' into chore/txn-builder-docs
DaughterOfMars Oct 20, 2025
7dbde27
dprint and bindings again
DaughterOfMars Oct 20, 2025
9531a46
Update crates/iota-sdk-ffi/README.md
DaughterOfMars Oct 21, 2025
04f47a1
Remove useless doc links in ffi crate
DaughterOfMars Oct 21, 2025
3362101
bindings and fix links
DaughterOfMars Oct 21, 2025
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
205 changes: 95 additions & 110 deletions bindings/go/iota_sdk_ffi/iota_sdk_ffi.go

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions bindings/go/iota_sdk_ffi/iota_sdk_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -4314,6 +4314,11 @@ void* uniffi_iota_sdk_ffi_fn_method_transactionbuilder_gas(void* ptr, void* obje
void* uniffi_iota_sdk_ffi_fn_method_transactionbuilder_gas_budget(void* ptr, uint64_t budget, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_METHOD_TRANSACTIONBUILDER_GAS_COINS
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_METHOD_TRANSACTIONBUILDER_GAS_COINS
void* uniffi_iota_sdk_ffi_fn_method_transactionbuilder_gas_coins(void* ptr, RustBuffer object_ids, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_METHOD_TRANSACTIONBUILDER_GAS_PRICE
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_METHOD_TRANSACTIONBUILDER_GAS_PRICE
void* uniffi_iota_sdk_ffi_fn_method_transactionbuilder_gas_price(void* ptr, uint64_t price, RustCallStatus *out_status
Expand Down Expand Up @@ -7842,6 +7847,12 @@ uint16_t uniffi_iota_sdk_ffi_checksum_method_transactionbuilder_gas(void
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_METHOD_TRANSACTIONBUILDER_GAS_BUDGET
uint16_t uniffi_iota_sdk_ffi_checksum_method_transactionbuilder_gas_budget(void

);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_METHOD_TRANSACTIONBUILDER_GAS_COINS
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_METHOD_TRANSACTIONBUILDER_GAS_COINS
uint16_t uniffi_iota_sdk_ffi_checksum_method_transactionbuilder_gas_coins(void

);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_METHOD_TRANSACTIONBUILDER_GAS_PRICE
Expand Down
213 changes: 103 additions & 110 deletions bindings/kotlin/lib/iota_sdk/iota_sdk_ffi.kt

Large diffs are not rendered by default.

217 changes: 107 additions & 110 deletions bindings/python/lib/iota_sdk_ffi.py

Large diffs are not rendered by default.

109 changes: 109 additions & 0 deletions crates/iota-sdk-ffi/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,116 @@
# IOTA SDK FFI

Core type definitions for the IOTA blockchain.

This crate can generate bindings for various languages using [UniFFI](https://github.com/mozilla/uniffi-rs).

[IOTA](https://iota.org) is a next-generation smart contract platform with high throughput, low latency, and an asset-oriented programming model powered by the Move programming language. This crate provides type definitions for working with the data that makes up the IOTA blockchain.

## BCS

[BCS](https://docs.rs/bcs) is the serialization format used to represent the state of the blockchain and is used extensively throughout the IOTA ecosystem. In particular the BCS format is leveraged because it _"guarantees canonical serialization, meaning that for any given data type, there is a one-to-one correspondence between in-memory values and valid byte representations."_

One benefit of this property of having a canonical serialized representation is to allow different entities in the ecosystem to all agree on how a particular type should be interpreted and more importantly define a deterministic representation for hashing and signing.

This library strives to guarantee that the types defined are fully BCS-compatible with the data that the network produces. The one caveat to this would be that as the IOTA protocol evolves, new type variants are added and older versions of this library may not support those newly added variants. The expectation is that the most recent release of this library will support new variants and types as they are released to IOTA's `testnet` network.

See the documentation for the various types defined by this crate for a specification of their BCS serialized representation which will be defined using ABNF notation as described by [RFC-5234](https://datatracker.ietf.org/doc/html/rfc5234). In addition to the format itself, some types have an extra layer of verification and may impose additional restrictions on valid byte representations above and beyond those already provided by BCS. In these instances the documentation for those types will clearly specify these additional restrictions.

Here are some common rules:

```text
; --- BCS Value ---
bcs-value = bcs-struct / bcs-enum / bcs-length-prefixed / bcs-fixed-length
bcs-length-prefixed = bytes / string / vector / option
bcs-fixed-length = u8 / u16 / u32 / u64 / u128 /
i8 / i16 / i32 / i64 / i128 /
boolean
bcs-struct = *bcs-value ; Sequence of serialized fields
bcs-enum = uleb128-index bcs-value ; Enum index and associated value
; --- Length-prefixed types ---
bytes = uleb128 *OCTET ; Raw bytes of the specified length
string = uleb128 *OCTET ; valid utf8 string of the specified length
vector = uleb128 *bcs-value ; Length-prefixed list of values
option = %x00 / (%x01 bcs-value) ; optional value
; --- Fixed-length types ---
u8 = OCTET ; 1-byte unsigned integer
u16 = 2OCTET ; 2-byte unsigned integer, little-endian
u32 = 4OCTET ; 4-byte unsigned integer, little-endian
u64 = 8OCTET ; 8-byte unsigned integer, little-endian
u128 = 16OCTET ; 16-byte unsigned integer, little-endian
i8 = OCTET ; 1-byte signed integer
i16 = 2OCTET ; 2-byte signed integer, little-endian
i32 = 4OCTET ; 4-byte signed integer, little-endian
i64 = 8OCTET ; 8-byte signed integer, little-endian
i128 = 16OCTET ; 16-byte signed integer, little-endian
boolean = %x00 / %x01 ; Boolean: 0 = false, 1 = true
array = *(bcs-value) ; Fixed-length array
; --- ULEB128 definition ---
uleb128 = 1*5uleb128-byte ; Variable-length ULEB128 encoding
uleb128-byte = %x00-7F / %x80-FF ; ULEB128 continuation rules
uleb128-index = uleb128 ; ULEB128-encoded variant index
```

## Transaction Builder

This crate contains the
[TransactionBuilder](./src/transaction_builder/mod.rs), which allows
for construction of Programmable Transactions which can be executed on the
IOTA network.

### Methods

The following methods are available:

#### Commands

Each command method adds one or more commands to the final transaction. Some commands have optional follow-up methods. Most command results can be named, which allows them to be used later in the transaction via the `PTBArgument::Res` variant. When a single name is provided, the result will be named, and when a list of names is provided, the names will be used for the individual nested results.

- `move_call`: Call a move function.
- `send_iota`: Send IOTA coins to a recipient address.
- `send_coins`: Send coins of any type to a recipient address.
- `merge_coins`: Merge a list of coins into a single primary coin.
- `split_coins`: Split a coin into coins of various amounts.
- `transfer_objects`: Send objects to a recipient address.
- `publish`: Publish a move package.
- `upgrade`: Upgrade a move package.
- `make_move_vec`: Create a move `vector`.

#### Metadata

These methods set various metadata which may be needed for the execution.

- `gas`: Add a gas coin to pay for the execution.
- `gas_coins`: Add gas coins to pay for the execution.
- `gas_budget`: Set the maximum gas budget to spend.
- `gas_price`: Set the gas price.
- `sponsor`: Set the gas sponsor address.
- `gas_station_sponsor`: Set the gas station URL. See [Gas Station](#gas-station) for more info.
- `expiration`: Set the transaction expiration epoch.

### Finalization and Execution

There are several ways to finish the builder. First, the [finish](transaction_builder::TransactionBuilder::finish) method can be used to return the resulting [Transaction](iota_types::Transaction), which can be manually serialized, executed, etc.

Additionally, the builder can directly [dry_run](transaction_builder::TransactionBuilder::dry_run) or [execute](transaction_builder::TransactionBuilder::execute) the transaction.

When the transaction is resolved, the builder will try to ensure a valid state by de-duplicating and converting appropriate inputs into references to the gas coin. This means that the same input can be passed multiple times and the final transaction will only contain one instance. However, in some cases an invalid state can still be reached. For instance, if a coin is used both for gas and as part of a group of coins, i.e. when transferring objects, the transaction can not possibly be valid.

#### Defaults

The builder can set some values by default. The
following are the default behaviors for each metadata value.

- Gas: One page of coins owned by the sender.
- Gas Budget: A dry run will be used to estimate.
- Gas Price: The current reference gas price.

### Gas Station

The Transaction Builder supports executing via a [Gas Station](https://github.com/iotaledger/gas-station). To do so, the URL, duration, and headers must be provided via [gas_station_sponsor](transaction_builder::TransactionBuilder::gas_station_sponsor).

By default the request will contain the header `Content-Type: application/json` When this data has been set, calling [execute](transaction_builder::TransactionBuilder::execute) will request gas from and send the resulting transaction to this endpoint instead of using the GraphQL client.

## Supported languages

- [Go](../../bindings/go)
Expand Down
4 changes: 2 additions & 2 deletions crates/iota-sdk-ffi/src/faucet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct FaucetClient(iota_graphql_client::faucet::FaucetClient);
#[uniffi::export(async_runtime = "tokio")]
impl FaucetClient {
/// Construct a new `FaucetClient` with the given faucet service URL. This
/// [`FaucetClient`] expects that the service provides two endpoints:
/// `FaucetClient` expects that the service provides two endpoints:
/// /v1/gas and /v1/status. As such, do not provide the request
/// endpoint, just the top level service endpoint.
///
Expand Down Expand Up @@ -68,7 +68,7 @@ impl FaucetClient {

/// Check the faucet request status.
///
/// Possible statuses are defined in: [`BatchSendStatusType`]
/// Possible statuses are defined in: `BatchSendStatusType`
pub async fn request_status(&self, id: String) -> Result<Option<BatchSendStatus>> {
Ok(self
.0
Expand Down
22 changes: 11 additions & 11 deletions crates/iota-sdk-ffi/src/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ impl GraphQLClient {
// Checkpoints API
// ===========================================================================

/// Get the [`CheckpointSummary`] for a given checkpoint digest or
/// Get the `CheckpointSummary` for a given checkpoint digest or
/// checkpoint id. If none is provided, it will use the last known
/// checkpoint id.
#[uniffi::method(default(digest = None, seq_num = None))]
Expand All @@ -249,7 +249,7 @@ impl GraphQLClient {
.map(Arc::new))
}

/// Get a page of [`CheckpointSummary`] for the provided parameters.
/// Get a page of `CheckpointSummary` for the provided parameters.
#[uniffi::method(default(pagination_filter = None))]
pub async fn checkpoints(
&self,
Expand Down Expand Up @@ -339,7 +339,7 @@ impl GraphQLClient {
// Objects API
// ===========================================================================

/// Return an object based on the provided [`Address`].
/// Return an object based on the provided `Address`.
///
/// If the object does not exist (e.g., due to pruning), this will return
/// `Ok(None)`. Similarly, if this is not an object but an address, it
Expand All @@ -362,7 +362,7 @@ impl GraphQLClient {

/// Return a page of objects based on the provided parameters.
///
/// Use this function together with the [`ObjectFilter::owner`] to get the
/// Use this function together with the `ObjectFilter::owner` to get the
/// objects owned by an address.
///
/// # Example
Expand Down Expand Up @@ -395,8 +395,8 @@ impl GraphQLClient {
.into())
}

/// Return the object's bcs content [`Vec<u8>`] based on the provided
/// [`Address`].
/// Return the object's bcs content `Vec<u8>` based on the provided
/// `Address`.
pub async fn object_bcs(&self, object_id: &ObjectId) -> Result<Option<Vec<u8>>> {
Ok(self.0.read().await.object_bcs(**object_id).await?)
}
Expand Down Expand Up @@ -736,7 +736,7 @@ impl GraphQLClient {
///
/// The `name` argument is a json serialized type.
///
/// This returns [`DynamicFieldOutput`] which contains the name, the value
/// This returns `DynamicFieldOutput` which contains the name, the value
/// as json, and object.
///
/// # Example
Expand Down Expand Up @@ -771,7 +771,7 @@ impl GraphQLClient {
///
/// The `name` argument is a json serialized type.
///
/// This returns [`DynamicFieldOutput`] which contains the name, the value
/// This returns `DynamicFieldOutput` which contains the name, the value
/// as json, and object.
pub async fn dynamic_object_field(
&self,
Expand All @@ -791,7 +791,7 @@ impl GraphQLClient {
/// Get a page of dynamic fields for the provided address. Note that this
/// will also fetch dynamic fields on wrapped objects.
///
/// This returns [`Page`] of [`DynamicFieldOutput`]s.
/// This returns a page of `DynamicFieldOutput`s.
#[uniffi::method(default(pagination_filter = None))]
pub async fn dynamic_fields(
&self,
Expand Down Expand Up @@ -824,7 +824,7 @@ impl GraphQLClient {
// Dry Run API
// ===========================================================================

/// Dry run a [`Transaction`] and return the transaction effects and dry run
/// Dry run a `Transaction` and return the transaction effects and dry run
/// error (if any).
///
/// `skipChecks` optional flag disables the usual verification checks that
Expand All @@ -842,7 +842,7 @@ impl GraphQLClient {
.into())
}

/// Dry run a [`TransactionKind`] and return the transaction effects and dry
/// Dry run a `TransactionKind` and return the transaction effects and dry
/// run error (if any).
///
/// `skipChecks` optional flag disables the usual verification checks that
Expand Down
122 changes: 12 additions & 110 deletions crates/iota-sdk-ffi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,120 +1,22 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

//! Core type definitions for the IOTA blockchain.
//!
//! [IOTA] is a next-generation smart contract platform with high throughput,
//! low latency, and an asset-oriented programming model powered by the Move
//! programming language. This crate provides type definitions for working with
//! the data that makes up the IOTA blockchain.
//!
//! [IOTA]: https://iota.org
//!
//! # Feature flags
//!
//! This library uses a set of [feature flags] to reduce the number of
//! dependencies and amount of compiled code. By default, no features are
//! enabled which allows one to enable a subset specifically for their use case.
//! Below is a list of the available feature flags.
//!
//! - `schemars`: Enables JSON schema generation using the [schemars] library.
//! - `serde`: Enables support for serializing and deserializing types to/from
//! BCS utilizing [serde] library.
//! - `rand`: Enables support for generating random instances of a number of
//! types via the [rand] library.
//! - `hash`: Enables support for hashing, which is required for deriving
//! addresses and calculating digests for various types.
//! - `proptest`: Enables support for the [proptest] library by providing
//! implementations of [proptest::arbitrary::Arbitrary] for many types.
//!
//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
//! [serde]: https://docs.rs/serde
//! [rand]: https://docs.rs/rand
//! [proptest]: https://docs.rs/proptest
//! [schemars]: https://docs.rs/schemars
//! [proptest::arbitrary::Arbitrary]: https://docs.rs/proptest/latest/proptest/arbitrary/trait.Arbitrary.html
//!
//! # BCS
//!
//! [BCS] is the serialization format used to represent the state of the
//! blockchain and is used extensively throughout the IOTA ecosystem. In
//! particular the BCS format is leveraged because it _"guarantees canonical
//! serialization, meaning that for any given data type, there is a one-to-one
//! correspondence between in-memory values and valid byte representations."_
//! One benefit of this property of having a canonical serialized representation
//! is to allow different entities in the ecosystem to all agree on how a
//! particular type should be interpreted and more importantly define a
//! deterministic representation for hashing and signing.
//!
//! This library strives to guarantee that the types defined are fully
//! BCS-compatible with the data that the network produces. The one caveat to
//! this would be that as the IOTA protocol evolves, new type variants are added
//! and older versions of this library may not support those newly
//! added variants. The expectation is that the most recent release of this
//! library will support new variants and types as they are released to IOTA's
//! `testnet` network.
//!
//! See the documentation for the various types defined by this crate for a
//! specification of their BCS serialized representation which will be defined
//! using ABNF notation as described by [RFC-5234]. In addition to the format
//! itself, some types have an extra layer of verification and may impose
//! additional restrictions on valid byte representations above and beyond those
//! already provided by BCS. In these instances the documentation for those
//! types will clearly specify these additional restrictions.
//!
//! Here are some common rules:
//!
//! ```text
//! ; --- BCS Value ---
//! bcs-value = bcs-struct / bcs-enum / bcs-length-prefixed / bcs-fixed-length
//! bcs-length-prefixed = bytes / string / vector / option
//! bcs-fixed-length = u8 / u16 / u32 / u64 / u128 /
//! i8 / i16 / i32 / i64 / i128 /
//! boolean
//! bcs-struct = *bcs-value ; Sequence of serialized fields
//! bcs-enum = uleb128-index bcs-value ; Enum index and associated value
//!
//! ; --- Length-prefixed types ---
//! bytes = uleb128 *OCTET ; Raw bytes of the specified length
//! string = uleb128 *OCTET ; valid utf8 string of the specified length
//! vector = uleb128 *bcs-value ; Length-prefixed list of values
//! option = %x00 / (%x01 bcs-value) ; optional value
//!
//! ; --- Fixed-length types ---
//! u8 = OCTET ; 1-byte unsigned integer
//! u16 = 2OCTET ; 2-byte unsigned integer, little-endian
//! u32 = 4OCTET ; 4-byte unsigned integer, little-endian
//! u64 = 8OCTET ; 8-byte unsigned integer, little-endian
//! u128 = 16OCTET ; 16-byte unsigned integer, little-endian
//! i8 = OCTET ; 1-byte signed integer
//! i16 = 2OCTET ; 2-byte signed integer, little-endian
//! i32 = 4OCTET ; 4-byte signed integer, little-endian
//! i64 = 8OCTET ; 8-byte signed integer, little-endian
//! i128 = 16OCTET ; 16-byte signed integer, little-endian
//! boolean = %x00 / %x01 ; Boolean: 0 = false, 1 = true
//! array = *(bcs-value) ; Fixed-length array
//!
//! ; --- ULEB128 definition ---
//! uleb128 = 1*5uleb128-byte ; Variable-length ULEB128 encoding
//! uleb128-byte = %x00-7F / %x80-FF ; ULEB128 continuation rules
//! uleb128-index = uleb128 ; ULEB128-encoded variant index
//! ```
//!
//! [BCS]: https://docs.rs/bcs
//! [RFC-5234]: https://datatracker.ietf.org/doc/html/rfc5234
#![expect(unused)]
#![allow(clippy::wrong_self_convention)]
#![allow(
clippy::wrong_self_convention,
clippy::should_implement_trait,
clippy::new_without_default
)]

use base64ct::Encoding;

mod crypto;
mod error;
mod faucet;
mod graphql;
mod transaction_builder;
mod types;
mod uniffi_helpers;
pub mod crypto;
pub mod error;
pub mod faucet;
pub mod graphql;
pub mod transaction_builder;
pub mod types;
pub mod uniffi_helpers;

uniffi::setup_scaffolding!();

Expand Down
Loading