First-party signing for Derive (Lyra v2, on Optimism).
Derive has two signature paths, both secp256k1 over a Keccak-256 digest:
- REST auth headers (every private request) — EIP-191 personal-message
signing of the millisecond timestamp. Emits the header trio:
X-LyraWallet(smart-contract wallet =credentials.api_key),X-LyraTimestamp,X-LyraSignature(session-key =credentials.secret). - Order signing (
sign_order/2) — EIP-712 typed data with a fixed domain separator. Additive on order endpoints only: when:orderis in params, the packed signature is injected into the JSON body under"signature". Never a precondition for private reads.
Both produce Derive's 65-byte packed signature (0x ‖ r ‖ s ‖ v).
Credentials
credentials.api_key— Derive smart-contract wallet address (X-LyraWallet). Not the owner EOA unless that address is also a registered session key.credentials.secret— private key of a registered session key (or the wallet itself when it signs). Edge proxy verifies recovered signer against the wallet / session-key registry before the app runs; owner EOA is not auto-registered on UI onboarding.
Summary
Functions
Computes the EIP-191 personal-message hash (hashMessage) for message.
Computes the 32-byte order hash (hashOrderMessage).
Signs message with EIP-191 personal signing, returning the packed
0x ‖ r ‖ s ‖ v signature string. Options: :private_key (required).
Signs an order, returning Derive's packed 0x ‖ r ‖ s ‖ v signature string.
Derives the session-key EOA address used by Derive's order envelope.
Hashes Derive's trade-module tuple for an EIP-712 order signature.
Functions
Computes the EIP-191 personal-message hash (hashMessage) for message.
Computes the 32-byte order hash (hashOrderMessage).
order is the eight-element list of field values in Derive order:
[action_typehash, subaccount_id, nonce, trade_module_address, trade_module_data_hash, signature_expiry, derive_wallet_address, wallet_address].
Options: :testnet selects the sandbox domain separator (default false).
@spec sign(Bourse.Signing.request(), Bourse.Credentials.t(), Bourse.Signing.config()) :: Bourse.Signing.signed_request()
Bourse.Signing.Behaviour entry point.
Always emits the REST auth-header trio (X-LyraWallet / X-LyraTimestamp /
X-LyraSignature) for private requests. When :order (or "order") is
present in params, also injects the EIP-712 packed order signature into the
JSON body under "signature" and drops the order tuple. Order signing is
additive — private reads with only a JSON body (or empty params) succeed
without an :order precondition.
Signs message with EIP-191 personal signing, returning the packed
0x ‖ r ‖ s ‖ v signature string. Options: :private_key (required).
Signs an order, returning Derive's packed 0x ‖ r ‖ s ‖ v signature string.
Options: :private_key (required), :testnet (default false).
Derives the session-key EOA address used by Derive's order envelope.
@spec trade_module_data_hash( String.t(), integer(), String.t(), String.t(), String.t(), integer(), boolean() ) :: binary()
Hashes Derive's trade-module tuple for an EIP-712 order signature.