Changelog¶
All notable changes to this project are documented here. The format follows Keep a Changelog, and the project uses Semantic Versioning.
[Unreleased]¶
Changed¶
The development-chain tests (
scripts/devchain.sh,-m integration) run on the Robonomics runtime v52 wasm, the newest release that ships one, instead of v50. It has no Sudo, soscripts/seed_auctions.pywrites RWS auctions into the genesis state, and the RWS tests are rebuilt around one user story: a new account without XRT is funded by transfer, bids in an auction, waits for the rotation, sets devices and writes datalog through the subscription, for both key types. The para id of the dev spec is now 2000, the one the preset writes into the genesis; with another one v52 panics on the first block. The library itself is unchanged.
[3.1.0] — 2026-10-28¶
The release of the 3.1 line; the code is that of 3.1.0rc1 (see below for what 3.1 adds).
Checked¶
On Polkadot with 3.1.0rc1 installed from PyPI: an sr25519 account wrote two datalog records, read them back, and an sr25519 integrator opened an encrypted report whose id it read from the datalog. A report for a recipient of the other key type is refused.
CI installs the wheel with
[sr25519]inpython:3.13-alpineon aarch64 and x86_64 without a compiler, and runs the core without the extra.
[3.1.0rc1] — 2026-10-28¶
sr25519 next to ED25519. The 3.0 API only grows; Keypair.from_mnemonic(m) and every
ED25519 package, signature and extrinsic are byte for byte what 3.0.0 produced. The core
installs and works without the new extra.
Added¶
The
[sr25519]extra (py-sr25519-bindings,rbcl; wheels for musl and aarch64, no compiler), imported lazily: without it, an sr25519 key raises anImportErrorthat names the extra.SR25519next toED25519,Keypair.crypto_type, and a keyword-onlycrypto_type=(the constant or"sr25519") onfrom_seed,from_mnemonic,from_uri,from_secret,from_public_keyandfrom_address. Addresses, derivation paths (//,/,///password) and signatures match substrate-interface and polkadot.js. The default stays ED25519.Extrinsics signed with sr25519 keys; the
MultiSignaturevariant comes from the key.Keypair.encrypt_message/decrypt_messagefor sr25519: the ECIES scheme ofpy-sr25519-encryption(Ivan Berman) and SubMessage, the same bytes, so blobs open in both and in polkadot.js. Every failure is aDecryptionError; the MAC is checked before decrypting. The scheme does not authenticate the sender.The report envelope for sr25519: the type of a package is the type of the sender’s key; a mixed recipient list raises
RecipientError, and opening with a key of the wrong type raisesPayloadErrorthat names the mismatch.Keypair.from_json(backup, password): import of a polkadot.js keyring backup (version 3), ED25519 or sr25519 as the file says. Scrypt parameters are limited to those polkadot.js accepts.
Changed¶
The development-chain tests run for both key types and include an encrypted report end to end. They still use the runtime v50 wasm (Sudo is needed to set the RWS oracle); mainnet runs spec 53, where Sudo is gone, OpenGov and CPS v1.1 are in, and Datalog, RWS, System, Balances and the signed extensions are unchanged. The mainnet smoke test passes on 53 for both key types.
CI runs the tests with and without the extra, and in
python:3.13-alpineon aarch64 and x86_64 without a compiler.
[3.0.0] — 2026-10-27¶
The release of the 3.0 line; the API is the one of 3.0.0rc2.
Fixed¶
A request timeout no longer drops the connection when the node still answers a
system_healthping. Dropping it ended every subscription on the shared connection, so one slow read (query_mapon a Raspberry Pi, say) turned a pendingauthor_submitAndWatchExtrinsicintoExtrinsicOutcomeUnknown. A timeout on a live node is raised asRequestTimeoutand is not retried on another endpoint; a node that answers neither is dropped and failed over as before.
Added¶
The Sphinx documentation is back: API reference built from the docstrings, plus the README, MIGRATION.md and the changelog, published to GitHub Pages from
main.
Changed¶
Checked against the Robonomics runtime
spec_version 52on Polkadot (Sudo removed from production, OpenGov, CPS v1.1): the metadata, signed extensions, and the Datalog, RWS, System and Balances pallets are unchanged for this library. The offline fixtures are recorded from spec 52. The development-chain tests still run on the runtime v50 wasm, because the production runtime no longer has Sudo.
[3.0.0rc2] — 2026-09-27¶
From three days of rc1 in rrs-connector, rrs-admin and rrs-ha-integration.
Fixed¶
The default TLS context for
wss://endpoints is built once per client, in a worker thread, and shared by every connection. Before, asyncio built one per connection on the event loop, reading the CA store from disk — Home Assistant reported a blocking call. Passingssl=works as before.
Added¶
Block hashes given as
at=or toclient.chain.block_number()are checked (0x+ 64 hex digits) before any request; a bad one raisesEncodeError.A test pins the API the Report Service projects use; MIGRATION.md lists it under “Stable API”.
Integration tests that send transactions refuse a non-loopback node unless
ROBONOMICS_DEV_ALLOW_REMOTE=1, and refuse production chains outright.A weekly read-only smoke test against mainnet in CI.
Changed¶
Robonomics on Kusama is legacy and is shutting down. A client refuses a Kusama node by default with “switch to Polkadot” in the reason; with
genesis_hash=Noneit connects and logs a warning. No Kusama constant is provided.
[3.0.0rc1] — 2026-09-24¶
A rewrite for the current Robonomics runtime. Not compatible with 2.x: see MIGRATION.md for the mapping and the behaviour that changed.
Added¶
Keypair(ED25519) from a mnemonic (with optional password), a raw seed, a Substrate secret URI with hard derivation (//Alice,<phrase>//a//b///password), a public key or an address.from_secret()accepts only what a person should paste: a mnemonic or a seed, never a derivation path.Message encryption (
encrypt_message/decrypt_message) byte-compatible with substrate-interface.Multi-recipient envelope:
encrypt_for_recipients,decrypt_package,parse_decrypted, in the format Robonomics Report Service publishes.SS58 helpers:
encode_address,decode_address,address_format,is_valid_address(format 32 by default).BIP39 English:
generate_mnemonic,validate_mnemonic.A typed exception hierarchy rooted at
RobonomicsError; input errors are alsoValueError. No exception message contains secret material.Runtime metadata (V14) decoded from the chain itself:
Runtimedescribes one runtime version (pallets, storage entries, constants, SCALE encode/decode);RuntimeCachefetches metadata per(genesis_hash, spec_version), parses it off the event loop and reloads it after a runtime upgrade.Storage: every hasher (
Identity,Twox64Concat,Twox128,Twox256,Blake2_128,Blake2_256,Blake2_128Concat), multi-key maps and maps keyed by a tuple;query,query_map(paged, pinned to one block, keys decoded back) andconstant. An absent value isNonefor anOptionalitem and the declared default otherwise.New errors:
MetadataError,NoSuchPallet,NoSuchStorage,NoSuchConstant,EncodeError,DecodeError.RobonomicsClient, an asyncio client over one multiplexed WebSocket: endpoints in priority order (e.g. a LAN node first, the public node as fallback), a node is used only if its genesis hash matches Robonomics Polkadot and it is neither syncing nor without peers, failback to a preferred endpoint, a timeout on every request, automatic retry of reads on another endpoint (retry=Falsefor requests with side effects), subscriptions, and runtime-upgrade tracking throughstate_subscribeRuntimeVersion.query,query_mapandconstanton the client.Transport errors, all
TransportError(retryable):ConnectionFailed,ConnectionLost,RequestTimeout,AllEndpointsFailed(with the reason for each endpoint).RpcErrorfor errors returned by the node.Extrinsics:
compose_callchecks arguments against the metadata and takes natural values (bytes,Keypair, nestedCall, a plain list forBoundedVec— no more[[a, b]]forRWS.set_devices); signed extensions come from the metadata, in its order, and an unknown one that carries data is refused (UnsupportedExtension); mortal era by default (Era);sign,validate(the pool’s own check viastate_call),submit(waits for the block and reads its events) andsubmit_nowait. One submission per account at a time, so nonces never collide.ExtrinsicResultwith the block, index and events of the extrinsic.Transaction errors, all
TransactionError:InvalidTransaction(kind plus a plain explanation —Paymentsays the account does not exist on chain),ExtrinsicFailed(pallet error name and docs, e.g.RWS.FreeWeightIsNotEnough),ExtrinsicDropped,ExtrinsicOutcomeUnknown(with the hash to look up).Pallet helpers on the client:
client.datalog:index,item(slot 0 is slot 0 — in 2.xget_item(index=0)meant “latest”),latest(also correct after the ring buffer wraps to 0, where 2.x returnedNone),items(all live records in one request),record(bytes or UTF-8 text, size checked, optionally through an RWS subscription),erase. Records come back asbytes(DatalogItem), never as text-or-hex.client.rws:ledger(Ledgerwithis_active,days_left,expires_at),devices,is_device,max_devices,set_devices(plain list, checked and de-duplicated,TooManyDevicespast the limit),add_devices,remove_devices,call,bid, auction reads.client.system(account→AccountInfowithexists,next_nonce),client.balances(existential_deposit,transfer_keep_alive,transfer_allow_death),client.chain(block hashes and numbers, runtime version).XRT = 10**9.
RobonomicsSync, a blocking wrapper for scripts and cron jobs: the async client on an event loop in a background thread, with the same methods, arguments, errors and timeouts (a test keeps the two APIs in step).query_mapbecomes a plain iterator. Calling it from inside a running event loop raisesRuntimeErrorrather than stalling the loop; closing it stops every thread it started.Tests: offline suites on recorded mainnet data and local fake nodes; integration tests against a development node running the mainnet runtime (
scripts/devchain.sh), covering transfers, datalog, sudo, RWS subscriptions and their failures; a read-only mainnet smoke test.py.typed.
Changed¶
Python 3.12+; built with hatchling.
Core dependencies are
pynacl,scalecodec,websocketsandxxhashonly; every one installs from a wheel or as pure Python on musl/aarch64.ED25519 is the only key type. sr25519 returns as an optional extra in a later release.
Extrinsic failures raise instead of returning a hash: inclusion in a block is checked against the block’s events.
Keypair.sign()signs astras its UTF-8 bytes. substrate-interface decoded astrstarting with0xas hex first; passbytes.fromhex(...)for that.
Removed¶
The dependency on
substrate-interfaceand, with it,ecdsa, the Ethereum libraries,smoldot-lightand the Rust bindings.The 2.x API:
Account,ServiceFunctions,BaseClass,ChainUtils,CommonFunctions, the per-pallet classes,Subscriber/SubEvent,TYPE_REGISTRY, and therobonomics_interfaceCLI.PubSubandReqRes: the node RPCs behind them are gone since collators moved topolkadot-omni-node.IPFS helpers (
web_3_auth,ipfs_32_bytes_to_qm_hash,ipfs_qm_hash_to_32_bytes).