All notable changes to aptos-sdk will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
-
The
keylessfeature and the entire keyless (OIDC) account surface have been removed because the previous implementation was chain-incompatible on every axis. Removed items:- the
keylessCargo feature (and its entry in thefullfeature set), plus the now-unusedjsonwebtokendependency; - the
account::keylessmodule and everything it re-exported:KeylessAccount,KeylessSignature,EphemeralKeyPair,EphemeralKeyPairSnapshot,HttpPepperService,HttpProverService,PepperService,ProverService,Pepper,OidcProvider,JwkSet, andZkProof; - the
AnyAccount::Keylessvariant and itsFrom<KeylessAccount>conversion; crypto::KEYLESS_SCHEME(the constant was wrong -- aptos-core has no auth-key scheme5; scheme5isAbstraction);- the
AccountAuthenticator::Keylessvariant (it used variant tag5, which the chain parses asAbstraction) and itsAccountAuthenticator::keylessconstructor; Network::pepper_urlandNetwork::prover_url;- the
keyless_accountexample.
Rationale: the implementation used a non-existent auth-key scheme byte (
5instead of the SingleKey scheme2), a wrong top-level authenticator variant tag, a non-AIP-61 address derivation, an incorrect on-chainKeylessSignaturestruct, and pepper/prover service request/response shapes that did not match the real Aptos services. None of it could have produced transactions the chain would accept. Keyless will be re-added correctly per the re-implementation guide incrates/aptos-sdk/feature-plans/09-keyless-accounts.md. The protocol-levelAnyPublicKey::Keylesstag (variant3), used only for MultiKey parsing, is retained and unaffected. - the
AptosError::sanitized_message()now redacts all URLs carrying query strings in an error message, not just the first per scheme. A second URL with a query string (e.g.?api_key=...) was previously left unredacted and could leak credentials into logs.FaucetClient::fundnow bounds the error-response body read (8 KiB cap), matching the success path and the fullnode client. Previously a misbehaving or malicious faucet could return an unbounded error body and exhaust client memory.
Secp256r1PrivateKey::sign_prehashed/Secp256r1PublicKey::verify_prehasheddouble-hashed their input: they went throughp256's ordinarySigner/Verifier, which applies SHA-256 internally, so a signature was produced overSHA-256(digest)rather than over the supplied 32-bytedigest. Such signatures never verified against the digest by any external or on-chain verifier (only the SDK's own equally-wrong verifier accepted them). Both now use thePrehashSigner/PrehashVerifierhazmat API and operate on the digest directly, matching thesecp256k1equivalents.crypto::signing_messageproduced a chain-incompatible message: it hashedSHA3-256(domain || bcs_bytes)(a single digest returning[u8; 32]) instead of the real Aptos constructionSHA3-256(domain) || bcs_bytes. Signing with the old output would have been rejected on-chain withINVALID_SIGNATURE. The helper now returns the correctVec<u8>message.- The simulate-endpoint authenticator rewrite (
for_simulate_endpoint) now produces node-parseable BCS for MultiEd25519 and MultiKey authenticators. Previously the entire signature blob was zeroed, destroying the MultiEd25519 bitmap and the MultiKey signature count / per-signature variant tags /BitVecframing, so/transactions/simulaterequests were rejected at deserialization instead of being accepted as an invalid signature. Signature bytes are now zeroed while the signer count and bitmap framing are preserved. types::resourcesandtypes::eventsnow deserialize real Aptos fullnode (REST) JSON. Deserializing an account/coin-store resource or event previously failed withinvalid type: string "42", expected u64because the API encodes every u64/u128 as a JSON string; these fields now parse the string shape (and a plain number) and round-trip back to strings. The on-chain event-handle GUID is now read from its actual{"id":{"addr","creation_num"}}shape.TypeTag::from_str_strictnow rejects malformed generic type arguments (<>,<,>,0x1::a::B<u8,,u16>, leading/trailing commas) which previously parsed successfully with the empty arguments silently dropped. Whitespace inside generics andvector<...>is now trimmed consistently.- BLS12-381 private keys now clear their secret on
Zeroize::zeroize()(the innerblst::SecretKeyfield was previously#[zeroize(skip)], making.zeroize()a silent no-op). SponsoredTransactionBuilder::expiration_from_nownow uses saturating addition, matchingTransactionBuilderand avoiding a potential debug-mode overflow panic.- Code generation (
ModuleGeneratorand theaptos-codegenCLI) now emits compilable bindings for generic Move structs (adds a skippedPhantomDatamarker instead of leaving type parameters unused, which failed with E0392), escapes theself/Self/crate/superkeywords with a trailing underscore (previously emitted the invalidr#self), and fully-qualifies BCS calls through::aptos_sdk::aptos_bcsso generated code compiles in downstream crates. - Move
u256in generated bindings now maps toMoveU256(round-trips as a 32-byte little-endian value in BCS and as a decimal string in JSON) instead of the nonexistentaptos_sdk::types::U256(which did not compile) or a plainString(which produced wrong on-wire bytes foru256entry-function arguments). - Documentation: corrected the MIGRATION.md BCS example (public
aptos_sdk::typesimport path) and indexer example (IndexerClient::query(&str, Option<Value>)arity), theFullnodeClient::get_transactionsordering note (ascending ledger-version order), theAnyAccountandSecp256r1Accountdocs, and the staleSecp256r1Accountmigration guidance (now points atWebAuthnAccount).
MoveU256now implementsDeserializeandDisplay, itsparseaccepts the full unsigned 256-bit range (previously only values up tou128), andto_decimal_stringreturns the canonical decimal form.Serialize/Deserializeare format-aware: 32-byte little-endian in BCS, decimal string in JSON.
AccountAddressnow treats the zero address (0x0) as a special address per AIP-40:is_special()returnstruefor it andDisplay/to_standard_stringrender it as"0x0"(short form) instead of the full 64-character long form. This matches aptos-core'sAccountAddress::is_specialand the TypeScript SDK. BCS and JSON serialization are unchanged (JSON still uses the long hex form).RetryExtis now a usable extension trait: a blanket impl forFn() -> Future<Output = AptosResult<T>>operation factories was added, so.with_retry(&config)actually runs the operation under the retry executor. Previously the trait had no implementations and could not be called.AptosConfig::with_max_retriesnow modifies onlymax_retries, preserving any customizedretryable_status_codesandjitter_factor. Previously it silently reset those fields to defaults.- Corrected numerous
cryptodoc comments to match behaviour (key-material zeroization guarantees, Secp256k1/Secp256r1from_bytesaccepted encodings, Multi* bitmap bit-order,SECP256K1_SIGNATURE_LENGTH,MultiKeySignatureminimum length,LENGTH = 0variable-length sentinel, Ed25519from_byteslength-only validation, the BLS aggregate note, and the SHA2/SHA3 comments) and varioustypesdocs (AccountAddress::is_special, signed-integerTypeTagvariants, identifier/type-tag length units,ChainIdknown-network values). aptos-codegendocs: removed the nonexistent--input-dirflag (directory generation isbuild_helper::generate_from_directory);--builderis documented as not-yet-implemented. README/lib.rs/REQUIRED_FEATURES.mdupdated for the previously-omitted examples, theclifeature, theconfig/error/retrymodules, and the orderlessTransactionPayload::Payloadvariant.Aptos::chain_id/Aptos::ensure_chain_iddocs corrected: devnet does not have a fixed, immediately-known chain ID (it is0until resolved from the node, like a custom network), because devnet is re-genesised regularly. Only mainnet (1), testnet (2), and local (4) return their chain ID without a network request.
0.6.0 - 2026-07-08
- Bumped transitive dependencies to clear
cargo auditadvisories:quinn-proto(RUSTSEC-2026-0185, remote memory exhaustion),anyhow(RUSTSEC-2026-0190, unsoundError::downcast_mut()), andrand0.9.x (RUSTSEC-2026-0097, unsound with custom loggers).
- Object & digital-asset (NFT) write helpers for TypeScript-SDK parity:
InputEntryFunctionData::transfer_object(0x1::object::transfer_call),transfer_digital_asset,create_collection(with aCollectionConfigbuilder),mint_digital_asset,mint_soul_bound_digital_asset,burn_digital_asset,freeze_digital_asset_transfer,unfreeze_digital_asset_transfer, plus the high-levelAptos::transfer_objectandAptos::transfer_digital_asset. - Staking (delegation pool) payload builders:
InputEntryFunctionData::{delegation_add_stake, delegation_unlock, delegation_reactivate_stake, delegation_withdraw}(0x1::delegation_pool::*). - Account Abstraction (AIP-113) payload builders:
InputEntryFunctionData::{add_authentication_function, remove_authentication_function, remove_authenticator}(0x1::account_abstraction::*). - Authentication-key rotation:
account::RotationProofChallenge(BCS layout pinned to0x1::account::RotationProofChallenge),account::build_rotate_auth_key_payload(signs the challenge with both the current and new keys), and the high-levelAptos::rotate_auth_key. Also addedEd25519Account::with_addressto build a signer for an account whose on-chain address no longer matches its key (e.g. after a rotation). - Fullnode table-item reads:
FullnodeClient::get_table_item(handle, key_type, value_type, key)and the convenience wrapperAptos::get_table_item(...)callPOST /tables/{handle}/item, matching the TypeScript SDK'sgetTableItem. This unblocks reading MoveTablestate, which is not exposed as a normal account resource. - Additional fullnode read endpoints for TypeScript-SDK parity:
FullnodeClient::get_transaction_by_version(version),get_transactions(start, limit)(list committed transactions),get_account_transactions(address, start, limit), andget_events_by_creation_number(address, creation_number, start, limit)(getAccountEventsByCreationNumber). - Fungible Asset (FA standard) transfers:
InputEntryFunctionData::transfer_fungible_asset(metadata, recipient, amount)(payload builder for0x1::primary_fungible_store::transfer) and the high-levelAptos::transfer_fungible_asset(sender, metadata, recipient, amount), the current-standard counterpart totransfer_coinand match for the TypeScript SDK'stransferFungibleAsset. - Chain-compatible orderless transactions (replay protection via a nonce
instead of a sequence number). New
TransactionPayload::Payloadvariant (BCS index 4) withTransactionPayloadInner,TransactionExecutable, andTransactionExtraConfig, plusTransactionPayload::into_orderless(nonce)and theAptoshelpersbuild_orderless_transaction,sign_and_submit_orderless, andsign_submit_and_wait_orderless. These produce an ordinaryRawTransactionwithsequence_number = u64::MAXand aTransactionExtraConfig::V1 { replay_protection_nonce: Some(nonce), .. }, matching aptos-core's on-wire format (pinned by a BCS wire-format test). - Keyless (OIDC) documentation: expanded module-level docs on
account::keyless, akeyless_accountexample, and [Network::pepper_url] / [Network::prover_url] helpers that return the default Aptos-hosted service endpoints (matching the TypeScript SDK). Added [EphemeralKeyPairSnapshot] with [EphemeralKeyPair::to_snapshot], [EphemeralKeyPair::from_snapshot], [EphemeralKeyPair::save_to_file], and [EphemeralKeyPair::load_from_file] for persisting ephemeral keys across an OAuth redirect. Corrected the outdatedKeylessAccount::newsnippet inMIGRATION.md. api::AnsClientis now a working Aptos Names Service client instead of a scaffold. It talks to the on-chainroutermodule on mainnet / testnet / localnet (router contract addresses are built in; useAnsClient::with_router_addressfor devnet, custom, or privately deployed ANS). New surface:- Reads:
get_target_address(name),get_owner_address(name),get_primary_name(address),get_expiration(name)(epoch seconds), plus the convenience wrapperslookup(name)(errors withAptosError::NotFoundwhen a name does not resolve) andreverse_lookup(address). Previouslylookup/reverse_lookupalways returnedAptosError::Internal("...not yet implemented..."). - Entry-function payload builders:
register_domain_payload,set_primary_name_payload,clear_primary_name_payload,set_target_address_payload,clear_target_address_payload. api::ans::AnsName-- parses and validates.aptnames (domain + optional subdomain) per the ANS naming rules.Aptos::ans()returns anAnsClientbound to the client's fullnode and network.
- Reads:
FullnodeClient::view_bcs_args(function, type_args, args)-- calls a view function whose arguments are supplied as real BCS bytes (serialized as an on-wireViewRequest, like the TypeScript SDK'sview) and returns the JSON-decoded result values. Unlikeview_bcs, this round-trips non-trivial Move argument types such asOption<String>correctly, not just addresses.FullnodeClient::config()-- exposes theAptosConfigbacking the client.
transaction::RawTransactionOrderlessandtransaction::SignedTransactionOrderlessare deprecated. They are a non-standard, homegrown orderless representation (32-byte nonce plus anAPTOS::RawTransactionOrderlesssigning-domain separator) that the Aptos fullnode does not accept, so any transaction built with them would be rejected. Use the chain-compatible orderless support added in this release:TransactionPayload::into_orderlessor theAptos::*_orderlesshelpers.
0.5.0 - 2026-05-21
api::AnsClientscaffold (api/ans.rs) -- exposeslookup(name)andreverse_lookup(address)method signatures so future ANS work has an obvious landing spot. Both methods currently returnAptosError::Internal("...not yet implemented...")so callers fail fast rather than silently treating placeholder addresses as real. Reconciles the previousAGENTS.mdreference toapi/ans.rswith reality (the file did not exist before this commit).- New behavioral test module
tests/behavioral/wire_format.rs-- pins the exact BCS / signing-message byte layout forRawTransaction(sequenced full-hex pin and orderless prefix),AccountAuthenticator::Ed25519,AccountAuthenticator::SingleKey(AnyPublicKey::Ed25519),AccountAuthenticator::MultiEd25519(variant 1, with bitmap layout),AccountAuthenticator::MultiKey(variant 3, mixed Ed25519+Secp256k1 with BitVec bitmap), and a nested genericTypeTag. Inputs are fully deterministic (fixed Ed25519 / Secp256k1 keys, fixed expiration, fixed nonce) so the resulting bytes can be cross-checked against the TypeScript SDK constructed with identical inputs. FullnodeClient::get_account_resources_paginated(address, start, limit)andFullnodeClient::get_account_modules_paginated(address, start, limit)-- forwardstart/limitquery parameters to the REST API so callers can page through accounts that publish more resources / modules than the default page size.startisOption<&str>so opaque cursor tokens surfaced through thex-aptos-cursorheader (AptosResponse::cursor) round-trip losslessly. The previous one-shotget_account_resources/get_account_modulesmethods are preserved and delegate to the new pagination methods withNonefor both arguments.account::DerivationPathandaccount::PathComponent-- parse BIP-32 / BIP-44 derivation path strings (m/44'/637'/0'/0/0, lowercasehalso accepted as a hardened marker) and exposeaptos_ed25519(address_index) -> AptosResult<Self>/aptos_secp256k1(address_index) -> AptosResult<Self>builders for the canonical Aptos paths.address_indexlives in the BIP-44 5th component to match the pre-existingMnemonic::derive_ed25519_keybehavior; callers needing TS-SDK-style account-level indexing must build the path explicitly viaDerivationPath::from_str.PathComponentfields are private; construct viaPathComponent::try_new(index, hardened)which rejectsindex >= 2^31(the BIP-32 hardened bit).Mnemonic::derive_secp256k1_key(index)— derives an Aptos Secp256k1 private key via BIP-32 along the canonical Aptos path. Cross-validated against the Bitcoin reference vector for theabandon × 11 aboutmnemonic atm/44'/0'/0'/0/0so hardened + non-hardened child derivation are both exercised by tests.Mnemonic::derive_ed25519_key_at_path(&path)andMnemonic::derive_secp256k1_key_at_path(&path)— derive at a caller-supplied derivation path. Ed25519 paths must be fully hardened (SLIP-0010) and a non-hardened component returnsAptosError::KeyDerivationinstead of producing an invalid key.FullnodeClient::simulate_transaction_with_options— simulate with optional query parameters (estimate_max_gas_amount,estimate_gas_unit_price,estimate_prioritized_gas_unit_price). Existingsimulate_transactionis unchanged (single-arg) and delegates to the new method withNonefor backward compatibility.Aptos::simulate_signed_with_options, plus option-aware multi-signer simulation (Aptos::simulate_multi_agent,Aptos::simulate_fee_payer) for consistent high-level simulation APIs while preserving no-options usage.build_simulation_signed_multi_agentandbuild_simulation_signed_fee_payerfor constructing simulation-only signed transactions usingNoAccountAuthenticatorplaceholders.SignedTransaction::for_simulate_endpoint,TransactionAuthenticator::for_simulate_endpoint, andAccountAuthenticator::for_simulate_endpoint— strip signing material for/transactions/simulatewhen serializing manually;FullnodeClient::simulate_transaction/simulate_transaction_with_optionsapply the same transform automatically.AnyPublicKey::from_bcs_bytesandAnySignature::from_bcs_bytes— parse raw BCSAnyPublicKey/AnySignaturebytes forSingleKeyvalidation,AccountAuthenticator::verify, and related builder paths.WebAuthnAccountfor on-chainsecp256r1transaction signing. Wraps aSecp256r1PrivateKeyand emits the on-chainAnySignature::WebAuthnenvelope (syntheticPartialAuthenticatorAssertionResponsecarryingSHA3-256(signing_message)as the base64url challenge, a configurablerp_id/origin, and a 37-byteauthenticatorData). End-to-end verified against devnet viae2e_webauthn_account_transfer.DEFAULT_WEBAUTHN_RP_ID/DEFAULT_WEBAUTHN_ORIGINconstants andWebAuthnAccount::from_parts(...)for callers that need to pin the relying-party identity for off-chain auditing.Secp256k1PublicKey::to_raw_bytes()andSecp256r1PublicKey::to_raw_bytes()return the 64-byte raw(X || Y)encoding thataptos-stdlib::secp256k1::ecdsa_raw_public_key_from_64_bytesexpects (in addition to the existing 65-byte SEC1 uncompressed form).- New end-to-end tests in
tests/e2e/: real transfer flows forEd25519SingleKeyAccount,Secp256k1Account,WebAuthnAccount,MultiEd25519Account, andMultiKeyAccount; gas-estimation tests; sponsored-builder transfer; sequence-number progression; batch submission; and ane2e_account_not_foundregression test that pins the AIP-42 implicit-account contract. - New regression unit tests pin the on-chain BCS wire layout of
TransactionAuthenticator::SingleSender(AccountAuthenticator::SingleKey)andAccountAuthenticator::MultiKey, plus the per-scheme behaviour of the zero-signed authenticator built byAptos::simulate.
- MSRV bumped from 1.90 to 1.95. Both
rust-toolchain.tomland the workspacerust-version = "1.95.0"field in the rootCargo.tomlnow require Rust 1.95+; every CI job (Test, Lint, MSRV, Format, Documentation, Security Audit, Code Coverage) is pinned to 1.95. Downstream consumers building against the SDK need at least Rust 1.95.0 -- released 2026-04-14, well under the typical "last six months" support window. - Cargo manifest modernised. Switched from
resolver = "2"toresolver = "3"(the recommended resolver for edition-2024 packages, with tighter--no-default-featuresunification). Lint configuration moved into[workspace.lints]in the rootCargo.toml(stabilised in Rust 1.74); both member crates now declare[lints] workspace = true. The previous per-crate#![warn(...)]/#![allow(...)]block incrates/aptos-sdk/src/lib.rshas been retired -- workspace lints cover the same surface and additionally apply to examples, tests, and the proc-macros crate. - Increased default max gas amount from 200,000 to 2,000,000 (10x).
Aptos::fund_accountnow keeps issuing faucet requests until the on-chain balance has grown by the requested amount (max 16 attempts), so devnet -- whose/mintendpoint caps each response at 1 APT -- actually delivers the requested amount instead of silently short-funding the caller.Aptos::simulateandAptos::estimate_gasnow build a zero-signedSignedTransactionwhose authenticator shape matches the account's signature scheme (Ed25519, MultiEd25519, SingleKey, MultiKey). The simulation endpoint rejects valid signatures since it is a gas-estimation tool, not an execution tool; previously the helper only worked forEd25519Account.Network::Devnet.chain_id()now returns0("unknown") instead of a hardcoded value. TheAptosclient treats0as a signal to fetch the live chain ID from the configured fullnode viaAptos::ensure_chain_id, so devnet transactions automatically pick up the correct chain ID across devnet resets.- All
examples/*.rsprograms switched fromAptosConfig::testnet()toAptosConfig::devnet(). The Aptos testnet faucet now requires a JWT-authenticated API key (x-is-jwt: true) and rejects unauthenticated requests with HTTP 500. Secp256k1PublicKey::from_bytesandSecp256r1PublicKey::from_bytesnow also accept the 64-byte raw(X || Y)encoding (in addition to the SEC1 compressed/uncompressed forms).- Published crate excludes precompiled Move bytecode under
tests/e2e/move/**/*.mv.
Secp256r1Accountfor on-chain transaction signing. The on-chainAnySignaturevariant 2 isWebAuthn(aPartialAuthenticatorAssertionResponse), not bareSecp256r1Ecdsa, so transactions signed bySecp256r1Accountare rejected by every Aptos validator with a deserialization-level error. UseWebAuthnAccountinstead.Secp256r1Accountis retained for off-chain P-256 sign/verify and as a public-key source forMultiKeyAccount.
- Simulate endpoint —
FullnodeClient::simulate_transaction/simulate_transaction_with_optionsnow serializesigned_txn.for_simulate_endpoint()so authenticators are rewritten client-side (e.g.SingleKey→NoAccountAuthenticator, legacyEd25519signatures zeroed) before calling/transactions/simulate, avoiding the fullnode 400 "Simulated transactions must not have a valid signature" when passing a normally signed transaction toAptos::simulate_signedor the raw client. - BCS wire format of
AccountAuthenticator::{SingleKey, MultiKey, Keyless}. Previously the derivedSerializeimpl added a ULEB128 length prefix in front of each pre-BCS-encoded inner field, so the chain'sbcs::from_bytes::<MultiKeyAuthenticator>rejected the bytes withDeserializationError. The hand-rolledSerializenow emits theAnyPublicKey/AnySignaturepayloads inline after the variant tag, matching the on-chainSingleKeyAuthenticator/MultiKeyAuthenticatorstruct layout. Secp256k1PrivateKey::signno longer double-hashes. The previous implementation pre-hashed the message with SHA-256 and then calledk256::ecdsa::SigningKey::sign, which also applies SHA-256 internally, producing a signature overSHA-256(SHA-256(msg)). Sign and verify both double-hashed so unit tests passed, but the chain'saptos-crypto::secp256k1_ecdsa::Signature::verifyhashes the signing message with SHA-3-256 -- so every transaction was rejected withINVALID_SIGNATURE.signandverifynow compute the SHA-3-256 digest themselves and route throughsignature::hazmat::PrehashSigner/PrehashVerifier.Ed25519SingleKeyAccount/Secp256k1Account/Secp256r1Account/WebAuthnAccount--Account::signnow wraps the produced signature in the BCS-encodedAnySignature::*framing expected by the on-chainSingleKeyAuthenticator.signaturefield. Previously the bare 64-byte signature was emitted, which the chain rejected.MultiEd25519SignatureandMultiKeySignaturesigner-bitmaps are now MSB-first within each byte (matchesaptos-crypto::multi_ed25519::bitmap_set_bit--128u8 >> bucket_pos-- andaptos_bitvec::BitVec::set). The SDK was LSB-first, so the chain looked up the wrong public key for each signature and rejected every multi-signature transaction withINVALID_SIGNATURE.MultiKeySignature::to_bytesnow emits the BCSBitVecULEB128 length prefix in front of the 4-byte bitmap, matching the on-chainBCS((Vec<AnySignature>, BitVec))layout. Previously the bitmap was appended raw and the chain's deserializer rejected the bytes.Secp256k1PublicKey::to_addressandSecp256r1PublicKey::to_addressnow derive the auth key from 65-byte SEC1 uncompressed encoding (matching the chain's canonicalisation throughlibsecp256k1::PublicKey::serialize()/p256::ecdsa::VerifyingKey::to_sec1_bytes()). Previously the SDK and the chain disagreed on the address for the same key, so a SDK-derived address could not actually receive funds the chain would let the same key spend.- Devnet end-to-end submission. The combination of the
fund_accountlooping, the devnet chain-ID auto-resolve, the zero-signed simulator, the deprecation ofSecp256r1Account, and the on-wire fixes above means every account type the SDK can sign for (Ed25519, Ed25519SingleKey, Secp256k1, MultiEd25519, MultiKey, WebAuthn) now successfully submits transactions on devnet. - Script payload BCS — Reordered
ScriptArgumentenum variants to match chain/TS SDK (ScriptTransactionArgumentVariants), and addedSerializedplus signed-integer variants (I8–I256). Script transactions now serialize correctly and can be submitted successfully. SignedTransaction::verify_signaturenow rejectsMultiAgent/FeePayerauthenticators whensecondary_signer_addresses.len() != secondary_signers.len()(previousziptruncation could hide missing or extra signers).- no-default-features feature-combination compatibility: verification/parsing paths are now correctly gated so
ed25519-disabled builds do not reference unavailable Ed25519 types.
- New 2026-05 security review (
SECURITY_REVIEW_2026-05.md) confirms every Feb-2026 finding remains remediated. Three new informational / low-severity items are tracked (S-23 example prints private key, S-24 fuzz targets still missing, S-25secp256r1S == ORDER_HALFregression test). The audit's correctness fixes either preserve or improve the prior security posture (e.g.secp256k1SHA-3-256 alignment improves domain separation from other ECDSA-over-SHA-256 protocols;Aptos::simulateno longer routes private-key material through the gas-estimation path). - BIP-32 secp256k1 derivation now zeroizes the per-step HMAC input buffer
for hardened components, which transiently contains the parent private
key (
0x00 || ser_256(k_par) || ser_32(i)). Previously that buffer was dropped without scrubbing, leaving secret material on the heap until reused. - Documented the deliberate deviation from BIP-32's "advance to index
i+1" retry rule when an intermediate
I_Lis>= nor the derived child scalar is0. We return an error instead of silently producing a key at a different path; the failure probability per component is ~2^-127. - Hardened MultiKey decoding:
MultiKeyPublicKey,MultiKeySignature,AnyPublicKey, andAnySignaturenow enforce bounded element counts and exact key/signature length checks during deserialization to reduce memory-amplification DoS risk. - Hardened authenticator address checks: multi-agent and fee-payer verification now enforces sender, secondary signer, and fee payer derived-address consistency.
- Keyless variants continue to be rejected from MultiKey-only decoding paths (
AnyPublicKey/AnySignature) where they are not valid inputs. - Patched five RUSTSEC advisories surfaced by
cargo audit:aws-lc-sys < 0.39.0: RUSTSEC-2026-0044 (X.509 name-constraints bypass via wildcard / Unicode CN) and RUSTSEC-2026-0048 (CRL distribution-point scope-check logic error). Bumped to 0.41.0.rustls-webpki < 0.103.13: RUSTSEC-2026-0098 (URI-name name constraints incorrectly accepted), RUSTSEC-2026-0099 (name constraints accepted for wildcard certificates), and RUSTSEC-2026-0104 (reachable panic in CRL parsing). Bumped to 0.103.13.
0.4.1 - 2026-03-04
- Upgraded
aws-lc-sysfrom 0.37.1 to 0.38.0 (pinned as direct dependency) - Upgraded
aws-lc-rsfrom 1.16.0 to 1.16.1
0.4.0 - 2026-02-25
- Comprehensive security audit remediating 21 findings across the SDK
- Second-pass audit fixes across crypto, keyless, and API client modules
- Enforced low-S normalization for ECDSA (secp256k1/secp256r1) signatures to match aptos-core
- Hardened keyless account JWT verification
- Improved input validation across API clients and codegen
- Upgraded
reqwestfrom v0.12 to v0.13 - Replaced
hexcrate withconst-hexfor improved performance - Removed
async-traitdependency in favor of native async trait support - Audited and cleaned up dependency tree
- Bumped
keccakfrom 0.1.5 to 0.1.6 - Improved dependency feature selection for reduced compile times
- Configured
docs.rsmetadata for release builds
- Resolved rustdoc warnings breaking CI documentation check
- Fixed clippy
needless_borrows_for_generic_argswarnings
- Reduced allocations and lock overhead in hot paths
- Unnecessary feature-flags
0.1.0 - 2026-01-06
AccountAddress- 32-byte account addresses with hex parsing/formattingChainId- Network chain identifiers (mainnet, testnet, devnet, custom)HashValue- 32-byte hashes with SHA3-256 computationTypeTag- Move type representations for generics
- Ed25519 (
ed25519feature, default): Standard Ed25519 signatures - Secp256k1 (
secp256k1feature, default): Bitcoin-style ECDSA signatures - Secp256r1 (
secp256r1feature): P-256/WebAuthn/Passkey support - BLS12-381 (
blsfeature): Aggregate signature support - Multi-Ed25519 and Multi-Key support for M-of-N multisig
Ed25519Account- Single-key Ed25519 accountsSecp256k1Account- Single-key Secp256k1 accountsSecp256r1Account- Passkey/WebAuthn accountsMultiEd25519Account- M-of-N Ed25519 multisigMultiKeyAccount- M-of-N mixed key typesKeylessAccount(keylessfeature) - OIDC-based authentication- BIP-39 mnemonic phrase support
- BIP-44 HD derivation paths
TransactionBuilder- Fluent API for constructing transactionsEntryFunctionpayloads for Move entry function calls- Multi-agent transaction support
- Fee payer (sponsored) transaction support
InputEntryFunctionData- Type-safe entry function builders
FullnodeClient- REST API for blockchain interactionFaucetClient(faucetfeature) - Testnet account fundingIndexerClient(indexerfeature) - GraphQL queries for indexed dataAnsClient- Aptos Names Service integration
Aptos- Unified client combining all APIsAptosConfig- Network configuration with presets- Automatic retry with exponential backoff
- Connection pooling for improved performance
- Local transaction simulation
- Transaction batching for multiple transactions
- Sponsored transaction helpers
- Gas estimation with safety margins
ModuleGenerator- Generate Rust code from Move ABIsMoveSourceParser- Extract parameter names from Move source- Type-safe contract bindings via proc macros (
macrosfeature) - CLI tool for code generation (
clifeature)
- Comprehensive Rustdoc documentation
- Working examples for common use cases
- Unit, behavioral, and E2E test suites
- GitHub Actions CI/CD pipeline
- Code coverage with tarpaulin
- Private keys are zeroized on drop
- No unsafe code (
#![forbid(unsafe_code)]) - Feature-gated cryptographic implementations
- This SDK is independent of
aptos-corefor faster compilation - Minimum Supported Rust Version (MSRV): 1.90