Skip to main content

Crate nocturne

Crate nocturne 

Source
Expand description

§nocturne

Rust SDK for building, signing, publishing, discovering, simulating, and taking Morpho Midnight offers.

§Install

The crates.io package is nocturne-midnight; Rust imports it as nocturne:

[dependencies]
nocturne = { package = "nocturne-midnight", version = "0.1.0" }

Add features = ["alloy-wallet"] when converting publication requests directly into Alloy transactions.

§Quickstart

Build one lend offer, sign its Merkle tree, and verify it locally:

use nocturne::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let signer = LocalSigner::from_bytes(&[0x42; 32])?;
    let maker = signer.address();
    let ratifier = [0xbb; 20];
    let chain_id = word_from_u64(1);

    let market = MarketBuilder::new(1, [0x11; 20], [0x22; 20])
        .collateral(
            [0x33; 20],
            U256::from(770_000_000_000_000_000u64),
            U256::from(1u64),
            [0x44; 20],
        )
        .maturity(2_000_000_000)
        .build_checked()?;

    let offer = OfferBuilder::new(market, maker)
        .lend()
        .apr(7.2, 1_700_000_000)
        .expiry(2_000_000_000)
        .ratifier(ratifier)
        .max_units(1_000_000)
        .build_checked()?;

    let descriptor = OfferTree::from_entries([offer])?;
    let offer = &descriptor.offers[0];
    let tree = descriptor.tree;
    let digest = tree_digest(tree.root(), tree.height(), chain_id, &ratifier);
    let signature = signer.sign_digest(&digest)?;

    assert!(verify(
        offer,
        &tree.root(),
        0,
        &tree.proof(0)?,
        &signature,
        chain_id,
        &ratifier,
        &maker,
    ));
    Ok(())
}

Run the same example from this repository:

cargo run -p nocturne-midnight --example quickstart

The quickstart is offline and uses dummy addresses and key material.

§Complete flows

§Publish maker offers

  1. Build checked markets and offers with MarketBuilder and OfferBuilder.
  2. Create canonical groups, leaves, and proofs with OfferGroup and OfferTree.
  3. Sign with LocalSigner or ExternalSigner, or approve the root through SetterRatifier.
  4. Encode PayloadItem values with Payload::encode.
  5. Optionally validate the exact payload with MidnightApi::validate_payload.
  6. Build the wallet request with mempool_submission and submit it.

publish_offer.rs runs this entire flow through an Alloy wallet.

§Find and take offers

  1. Fetch a book or executable quote with MidnightApi.
  2. Size and locally check the fill with get_consumable_units, take_amounts, or simulate_take.
  3. Build take calldata with encode_take_calldata.
  4. Submit the calldata through the Rust wallet client of your choice.

take_offer.rs shows validation, sizing, simulation, and encoding.

§Manage a position

Use supply_collateral, take_lend, take_borrow, supply_collateral_take_borrow, repay_withdraw_collateral, and redeem to build wallet-ready transactions. Before bundle calls, build a RequirementPlan and call discover_requirements to resolve only the ERC-20 approvals and Midnight authorization that are still missing. This RPC-backed helper requires the alloy-wallet feature; the transaction builders themselves are wallet-agnostic.

§Main APIs

NeedStart with
Markets and offersMarketBuilder, OfferBuilder
Groups, roots, and proofsOfferGroup, OfferTree
Local or external signingLocalSigner, ExternalSigner
Books, quotes, and API validationMidnightApi
Publication payloadsPayload, mempool_submission
Taking offers and managing positionstake_lend, take_borrow, supply_collateral, repay_withdraw_collateral, redeem
Required approvals and authorizationRequirementPlan, discover_requirements
Capacity and notional sizingget_consumable_units, buyer_assets_to_units, seller_assets_to_units
Prices, APRs, fees, and simulationtick_to_price, tick_to_apr, take_amounts, simulate_take
Calldata and state codecsencode_*, decode_*
Delegated signingAuthorization, authorization_digest

The complete API is organized into modules by role. Raw hashing, EIP-712, ABI, conversion, and recovery functions remain available for custom infrastructure.

§Examples

ExamplePurpose
quickstartBuild, sign, and verify one offer
publish_offerPublish through an Alloy wallet
quote_bookBuild and re-quote an APR ladder
take_offerValidate, size, simulate, and encode a take
read_stateDecode production calldata into typed views
benchMeasure the local re-quote pipeline

The examples index contains exact commands and network requirements.

§Security

Nocturne can produce signatures and calldata that move real value. It is an early v0.1.0 release and has not been independently audited. Review wallet requests, keep mutable chain state current, and read the repository’s security policy.

§License

MIT OR Apache-2.0.

Re-exports§

pub use convert::*;
pub use builder::*;
pub use validate::*;
pub use sim::*;
pub use decode::*;
pub use codec::*;
pub use signer::*;
pub use authorize::*;
pub use sizing::*;
pub use payload::*;
pub use submission::*;
pub use actions::*;
pub use requirements::*;
pub use api::*;

Modules§

actions
Wallet-agnostic collateral, take, repayment, redemption, and authorization actions. Wallet-agnostic transaction builders for complete Midnight position workflows.
api
Async Midnight order-book, quote, maker-offer, and validation client. Async client for the Midnight order-book and mempool-validation API.
authorize
EIP-712 signing for delegated Midnight authorization. EIP-712 Authorization signing for hot-key delegation.
builder
Checked market and offer construction. Ergonomic builders for Market and Offer.
codec
ABI encoding for take, bundle, cancellation, and ratification calls. ABI-encode the take / cancelRoot calls and the EcrecoverRatifier ratifier data.
convert
Primitive conversions between Rust, ABI words, and U256 values. Conversions between the 32-byte EIP-712 Word and typed integers.
decode
Typed decoding for Midnight state, calldata, ratifiers, and bundles. Decode Midnight offers and on-chain state into typed Rust.
payload
Versioned maker-offer mempool payload encoding and decoding. Midnight maker-mempool payload framing and ABI codec.
requirements
Approval and Midnight-authorization requirement planning and discovery. Approval and Midnight-authorization requirement planning and discovery.
signer
Local and external signing backends. Signer abstraction with a vendor-agnostic KMS/HSM path.
sim
Tick, APR, fee, amount, and take-execution simulation. Local take simulation - “if a taker lifts this offer for N units, what executes?”
sizing
Offer capacity and asset-to-unit sizing helpers. assets<->units sizing and consumable-units helpers.
submission
Wallet-agnostic maker-offer publication transactions. Wallet-agnostic transaction construction for maker-offer publication.
validate
Local offer validation and consumption-cap checks. Policy validation - “will the router accept this offer?”

Structs§

CollateralParams
Market
Offer
OfferGroup
A validated set of offers sharing one content-addressed consumption group.
OfferTree
A perfect binary Merkle tree over offer leaves. height = log2(leaves.len()).
OfferTreeDescriptor
A canonical tree plus the final offers in leaf order, including zero padding.
Sig

Enums§

GroupError
Errors from constructing a canonical offer consumption group.
OfferTreeEntry
One entry in a canonical offer tree: either a standalone offer or an explicit shared group.
OfferTreeError
Errors from the high-level grouped and padded offer-tree constructor.
TreeError
Errors from constructing a Merkle tree over offer leaves.

Constants§

COLLATERAL_PARAMS_TYPE
EIP712_DOMAIN_TYPE
MARKET_TYPE
MAX_TREE_HEIGHT
The tallest offer tree HashLib.offerTreeTypeHash has a constant for; above this the contract reverts TreeTooHigh, so no taller tree can ever ratify.
OFFER_TYPE

Functions§

canonical_market
Return a market with collateral parameters in canonical ascending token order.
collateral_params_typehash
domain_separator
empty_offer
The protocol-zero offer used to pad non-power-of-two Merkle trees.
hash_collateral_params
hash_market
hash_node
hash_offer
EIP-712 struct hash of an Offer - this is the Merkle leaf. Mirrors HashLib.hashOffer.
keccak
market_id
Compute the deterministic Midnight market id (IdLib.toId).
market_typehash
offer_group_id
Hash offers with group = 0, sort those hashes, and hash their concatenation.
offer_tree_typehash
Panics if height exceeds MAX_TREE_HEIGHT, where HashLib.offerTreeTypeHash reverts TreeTooHigh.
offer_typehash
recover
Recover the signer address from a digest and signature, exactly as the ecrecover in EcrecoverRatifier.isRatified. Returns None for a malformed signature (the on-chain equivalent of ecrecover yielding address(0)).
sign_digest
Sign the tree digest with the maker’s key (secp256k1, in-process - no wallet round-trip).
signer_address
The Ethereum address controlled by a signing key - the maker address to put in offers.
tree_digest
The digest the maker signs for a whole tree (one signature covers every offer in it).
verify
Full off-chain mirror of EcrecoverRatifier.isRatified (minus the isAuthorized / isRootCanceled lookups, which need chain state). Recomputes the leaf, checks the Merkle proof, rebuilds the digest, recovers the signer, and confirms it is expected_maker.
verify_leaf
Recompute the root from a leaf + proof, exactly as HashLib.isLeaf does on-chain - including its leaf-index range check, whose LeafIndexOutOfRange revert is false here.

Type Aliases§

Address
Word