Consensix Labs

Consensix Labs

pyiota: A Native Python SDK for IOTA Rebased

IOTA Rebased is a ground-up rebuild of the IOTA network, launched in May 2025, that replaced the original Tangle and UTXO model with a Move-based object ledger, delegated proof-of-stake consensus, and smart contracts at the base layer. It was one of the more significant architectural shifts a major blockchain project has undertaken: not an incremental upgrade, but a complete change in execution model, consensus mechanism, and programming paradigm.

The official developer tooling followed accordingly. The IOTA Foundation provides a TypeScript SDK (@iota/iota-sdk, part of the iotaledger/iota monorepo) and a Rust SDK, both targeting the new Rebased architecture. There is also an older Python package (iota-sdk on PyPI) – but that’s a set of Rust FFI bindings for the pre-Rebased Stardust protocol. It doesn’t speak the Rebased JSON-RPC API, doesn’t build Move-compatible Programmable Transaction Blocks, and doesn’t handle the new BCS serialization format. When we needed Python tooling for IOTA Rebased, there was nothing available – so we built our own.

Why

We’ve been working with multiple blockchain ecosystems as part of our research at Consensix Labs – Ethereum and IOTA in particular. Our cross-chain asset provenance work uses both, and our proof-of-concept implementations involve a fair amount of scripting: building transactions, querying state, verifying on-chain data. Python is where most of that scripting happens.

When IOTA Rebased launched, we found ourselves reaching for Python tooling that didn’t exist. The TypeScript SDK is comprehensive, but switching languages mid-workflow to build a single transaction is friction we’d rather avoid. So we started building a Python client for internal use, and as it became more complete, it made sense to open-source it.

The result is pyiota – a pure-Python SDK for IOTA Rebased, available on PyPI as iota-rebased.

What It Does

pyiota provides async and synchronous clients for interacting with IOTA Rebased nodes via JSON-RPC. The core workflow – generate a keypair, build a transaction, sign it, submit it – looks like this:

import asyncio
from pyiota import IotaClient, Network, Transaction, NANOS_PER_IOTA
from pyiota.crypto import Ed25519Keypair

async def main():
    sender = Ed25519Keypair.generate()
    recipient = Ed25519Keypair.generate()

    async with IotaClient(Network.TESTNET) as client:
        # Fund the sender from the testnet faucet
        await client.request_testnet_tokens(sender.address)
        await asyncio.sleep(3)

        # Build a transfer: split 0.1 IOTA from gas, send to recipient
        tx = Transaction()
        coin = tx.split_coins(tx.gas, [NANOS_PER_IOTA // 10])
        tx.transfer_objects([coin], recipient.address)

        # Sign and execute
        tx_bytes = await tx.build(client=client, signer=sender)
        result = await client.sign_and_execute_transaction(
            signer=sender,
            tx_bytes=tx_bytes,
            show_effects=True,
        )
        print(f"Transaction: {result.digest}")
        print(f"Status: {result.effects.status}")

asyncio.run(main())

That’s a real, working example. It runs against the IOTA testnet as-is.

Under the hood, the library handles client-side BCS (Binary Canonical Serialization) for Programmable Transaction Blocks, Ed25519 keypair generation with IOTA’s address derivation scheme (Blake2b-256 of the public key, no flag prefix), intent-based transaction signing, and typed Pydantic response models for all RPC responses.

The transaction builder supports split_coins, transfer_objects, merge_coins, and move_call. The client provides queries for balances, coins, objects, and events, plus testnet faucet integration.

The Hard Part

The most technically interesting – and highest-risk – part of the library is the BCS serialization. IOTA Rebased uses BCS to encode transaction data before signing and submission. The format is compact, untagged, and unforgiving: a single byte off and the node rejects the transaction with an opaque deserialization error.

The official TypeScript and Rust SDKs use their own BCS libraries. We implemented BCS serialization from scratch in Python, covering ULEB128 variable-length encoding, fixed-width integers (u8 through u256), length-prefixed byte vectors, Move type tags with nested generics, and the full TransactionData envelope (V1 variant, with ProgrammableTransaction kind, gas data, sender, and expiration).

To verify correctness, we wrote a set of golden vector tests: a TypeScript script that uses the official @iota/iota-sdk to serialize specific structures and dump the raw bytes, paired with Python tests that build the same structures and assert identical output. The test suite covers 57 vectors across every serialization layer – from raw primitives up through complete signed transactions. If our Python output diverges from the official SDK by even one byte, the tests fail.

This is probably the most useful part of the project for anyone else building IOTA tooling outside the official SDK ecosystem. The BCS format isn’t fully documented; the authoritative reference is the TypeScript SDK source code (the BCS module inside @iota/iota-sdk). Our golden vectors and the generator scripts that produce them are included in the repository.

Installation

pip install iota-rebased

The import remains pyiota:

from pyiota import IotaClient, Transaction
from pyiota.crypto import Ed25519Keypair

Requires Python 3.12 or later. The only runtime dependencies are httpx, pydantic, and pynacl.

What’s Next

This is v0.1.0 – functional for the core transaction lifecycle, but far from complete coverage of the IOTA Rebased API surface. There are areas we’d like to expand as needs arise: event subscriptions via WebSocket, multi-signature support, object query pagination, Move call response parsing with type-aware deserialization, and dry-run transaction execution for gas estimation. How quickly we get to any of these depends on what we need for our own projects and what the community asks for.

The code is on GitHub under the MIT license. Issues, feedback, and contributions are welcome.