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 quickstartThe quickstart is offline and uses dummy addresses and key material.
§Complete flows
§Publish maker offers
- Build checked markets and offers with
MarketBuilderandOfferBuilder. - Create canonical groups, leaves, and proofs with
OfferGroupandOfferTree. - Sign with
LocalSignerorExternalSigner, or approve the root through SetterRatifier. - Encode
PayloadItemvalues withPayload::encode. - Optionally validate the exact payload with
MidnightApi::validate_payload. - Build the wallet request with
mempool_submissionand submit it.
publish_offer.rs
runs this entire flow through an Alloy wallet.
§Find and take offers
- Fetch a book or executable quote with
MidnightApi. - Size and locally check the fill with
get_consumable_units,take_amounts, orsimulate_take. - Build
takecalldata withencode_take_calldata. - 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
| Need | Start with |
|---|---|
| Markets and offers | MarketBuilder, OfferBuilder |
| Groups, roots, and proofs | OfferGroup, OfferTree |
| Local or external signing | LocalSigner, ExternalSigner |
| Books, quotes, and API validation | MidnightApi |
| Publication payloads | Payload, mempool_submission |
| Taking offers and managing positions | take_lend, take_borrow, supply_collateral, repay_withdraw_collateral, redeem |
| Required approvals and authorization | RequirementPlan, discover_requirements |
| Capacity and notional sizing | get_consumable_units, buyer_assets_to_units, seller_assets_to_units |
| Prices, APRs, fees, and simulation | tick_to_price, tick_to_apr, take_amounts, simulate_take |
| Calldata and state codecs | encode_*, decode_* |
| Delegated signing | Authorization, 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
| Example | Purpose |
|---|---|
quickstart | Build, sign, and verify one offer |
publish_offer | Publish through an Alloy wallet |
quote_book | Build and re-quote an APR ladder |
take_offer | Validate, size, simulate, and encode a take |
read_state | Decode production calldata into typed views |
bench | Measure 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
Authorizationsigning for hot-key delegation. - builder
- Checked market and offer construction.
Ergonomic builders for
MarketandOffer. - codec
- ABI encoding for take, bundle, cancellation, and ratification calls.
ABI-encode the
take/cancelRootcalls and theEcrecoverRatifierratifier data. - convert
- Primitive conversions between Rust, ABI words, and
U256values. Conversions between the 32-byte EIP-712Wordand 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§
- Collateral
Params - Market
- Offer
- Offer
Group - A validated set of offers sharing one content-addressed consumption group.
- Offer
Tree - A perfect binary Merkle tree over offer leaves.
height= log2(leaves.len()). - Offer
Tree Descriptor - A canonical tree plus the final offers in leaf order, including zero padding.
- Sig
Enums§
- Group
Error - Errors from constructing a canonical offer consumption group.
- Offer
Tree Entry - One entry in a canonical offer tree: either a standalone offer or an explicit shared group.
- Offer
Tree Error - Errors from the high-level grouped and padded offer-tree constructor.
- Tree
Error - 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.offerTreeTypeHashhas a constant for; above this the contract revertsTreeTooHigh, 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
heightexceedsMAX_TREE_HEIGHT, whereHashLib.offerTreeTypeHashrevertsTreeTooHigh. - offer_
typehash - recover
- Recover the signer address from a digest and signature, exactly as the
ecrecoverinEcrecoverRatifier.isRatified. ReturnsNonefor a malformed signature (the on-chain equivalent ofecrecoveryieldingaddress(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
makeraddress 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 theisAuthorized/isRootCanceledlookups, which need chain state). Recomputes the leaf, checks the Merkle proof, rebuilds the digest, recovers the signer, and confirms it isexpected_maker. - verify_
leaf - Recompute the root from a leaf + proof, exactly as
HashLib.isLeafdoes on-chain - including its leaf-index range check, whoseLeafIndexOutOfRangerevert isfalsehere.