Documentation
¶
Overview ¶
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
This file holds the RFQ module payloads — the per-quote and per-execute structures whose ABI-encoded keccak digests become `Action.Data` when the SDK signs `private/send_quote`, `private/replace_quote` and `private/execute_quote`.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Package auth implements the two cryptographic signing flows Derive's API requires.
Two flows, one Signer ¶
Every authenticated Derive request involves cryptography in one of two places:
Per-request authentication of the caller. Sent as REST headers (X-LyraWallet, X-LyraTimestamp, X-LyraSignature) or as a one-shot `public/login` RPC over WebSocket. The signature is an EIP-191 personal-sign over the millisecond timestamp.
Per-action authorisation of order placement, cancels, transfers and RFQ flows. The signature is an EIP-712 typed-data hash over an `Action` struct whose `data` field is the keccak256 of an ABI-encoded module-specific payload.
Both flows go through the same Signer interface; concrete implementations include LocalSigner (owner key in process) and SessionKeySigner (session key delegating from a separate owner address).
Production setup ¶
Derive deployments use session keys. The owner is a smart-account on Derive Chain; the session key is a hot key registered on-chain as authorised to sign on its behalf. Use NewSessionKeySigner for production trading so the long-lived owner key never sits in the trading process's memory.
Test fixtures ¶
All signing test vectors live in pkg/auth/*_test.go. The tests verify that Derive's expected signature bytes can be reproduced from a known secp256k1 key — they're the canary for any future change to EIP-712 hashing here or upstream in go-ethereum.
Index ¶
- Variables
- func HTTPHeaders(ctx context.Context, signer Signer, now time.Time) (http.Header, error)
- type ActionData
- type LocalSigner
- func (s *LocalSigner) OwnerAddress() common.Address
- func (s *LocalSigner) SessionAddress() common.Address
- func (s *LocalSigner) SignAction(_ context.Context, domain netconf.Domain, action ActionData) (Signature, error)
- func (s *LocalSigner) SignAuthHeader(_ context.Context, ts time.Time) (Signature, error)
- type NonceGen
- type RFQExecuteModuleData
- type RFQQuoteLeg
- type RFQQuoteModuleData
- type SessionKeySigner
- func (s *SessionKeySigner) OwnerAddress() common.Address
- func (s *SessionKeySigner) SessionAddress() common.Address
- func (s *SessionKeySigner) SignAction(ctx context.Context, domain netconf.Domain, action ActionData) (Signature, error)
- func (s *SessionKeySigner) SignAuthHeader(ctx context.Context, ts time.Time) (Signature, error)
- type Signature
- type Signer
- type TradeModuleData
- type TransferModuleData
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidInput = errors.New("auth: invalid input")
ErrInvalidInput is the sentinel returned by every input-DTO Validate method in this package. Wrap with errors.Is.
Functions ¶
func HTTPHeaders ¶
HTTPHeaders builds the per-request authentication headers Derive expects on every REST call:
X-LyraWallet — the owner address as 0x-prefixed hex X-LyraTimestamp — the current time as milliseconds since the Unix epoch X-LyraSignature — the EIP-191 signature over the timestamp string
Despite the rename to "Derive", the header names retain their "Lyra" prefix server-side.
If signer is nil, HTTPHeaders returns (nil, nil) — used by the public-only path of the HTTP transport. Errors from [Signer.SignAuthHeader] are propagated unmodified.
Types ¶
type ActionData ¶
type ActionData struct {
// SubaccountID is the placing subaccount id.
SubaccountID int64
// Nonce is a strictly-increasing per-subaccount nonce.
// Use [NonceGen] to source these.
Nonce uint64
// Module is the on-chain Derive module contract this action targets
// (e.g. the TradeModule for orders, TransferModule for transfers).
Module common.Address
// Data is keccak256 of the module-specific ABI-encoded payload.
Data [32]byte
// Expiry is the Unix timestamp (seconds) after which the signature is
// no longer valid.
Expiry int64
// Owner is the smart-account owner address.
Owner common.Address
// Signer is the session-key (or owner) address that signed.
Signer common.Address
}
ActionData is the input to Derive's order/cancel/transfer signing flow.
It mirrors Solidity's `Action` struct field-for-field. The Data field is the keccak256 of the ABI-encoded module-specific payload — for trades that's TradeModuleData.Hash, for transfers it's TransferModuleData.Hash, and so on.
Use ActionData.Hash to compute the EIP-712 struct hash; in normal use [Signer.SignAction] does that for you and returns the Signature.
func (ActionData) Hash ¶
func (a ActionData) Hash() []byte
Hash returns the EIP-712 hashStruct of the ActionData, suitable for passing into the EIP-712 envelope alongside the network's domain separator.
The output is exactly 32 bytes.
func (ActionData) Validate ¶
func (a ActionData) Validate() error
Validate performs schema-level checks on the receiver: addresses must be non-zero, expiry must be in the future, subaccount id must be non-negative. Nonce and Data are not validated — uint64 zero and a zero-bytes32 are legal pre-fill states the signing path overwrites.
type LocalSigner ¶
type LocalSigner struct {
// contains filtered or unexported fields
}
LocalSigner holds an owner private key in process. It is the simplest Signer implementation; for production market-making prefer SessionKeySigner so the long-lived owner key never touches the process.
func NewLocalSigner ¶
func NewLocalSigner(hexKey string) (*LocalSigner, error)
NewLocalSigner parses a hex-encoded secp256k1 private key (with or without the 0x prefix) into a Signer.
func (*LocalSigner) OwnerAddress ¶ added in v0.17.0
func (s *LocalSigner) OwnerAddress() common.Address
OwnerAddress returns the same address as SessionAddress — a LocalSigner has no separate owner.
func (*LocalSigner) SessionAddress ¶ added in v0.17.0
func (s *LocalSigner) SessionAddress() common.Address
SessionAddress returns the signer's public address.
func (*LocalSigner) SignAction ¶
func (s *LocalSigner) SignAction(_ context.Context, domain netconf.Domain, action ActionData) (Signature, error)
SignAction signs Derive's EIP-712 Action struct.
func (*LocalSigner) SignAuthHeader ¶
SignAuthHeader signs the millisecond timestamp string Derive expects.
type NonceGen ¶
type NonceGen struct{}
NonceGen produces nonces in the format Derive's engine documents:
nonce = (UTC milliseconds since epoch) * 1000 + random[0..999]
That format keeps every nonce inside JSON's safe-integer range (2^53, the IEEE-754 double's max precise integer), so the engine's JSON parser doesn't truncate the value when it recomputes the EIP-712 digest server-side. Any wider format silently breaks signature verification with a 14014 error.
The shape and meaning match the official Python reference at derivexyz/v2-action-signing-python (utils.get_action_nonce) exactly.
The engine only requires uniqueness, not strict monotonicity. The 1000-bucket random suffix gives ample collision headroom — birthday-paradox 50% probability at ~37 calls per millisecond, well above any non-HFT workload.
The zero value is usable. NewNonceGen is kept for source compatibility with prior versions.
func NewNonceGen ¶
func NewNonceGen() *NonceGen
NewNonceGen returns a generator. The returned value is safe for concurrent use; crypto/rand.Read is goroutine-safe.
func (*NonceGen) Next ¶
Next returns a fresh nonce in the documented format, unix_ms*1000 + suffix where suffix ∈ [0, 999]. The engine only requires uniqueness, not cryptographic secrecy — but the repo precedent (see internal/retry/backoff.go) is to source randomness from crypto/rand everywhere to satisfy the security linters without per-call nolint directives. The cost is one OS RNG read of 2 bytes per call, negligible relative to the network round-trip every signed action does anyway.
type RFQExecuteModuleData ¶ added in v0.13.0
type RFQExecuteModuleData struct {
// GlobalDirection is the taker's intended direction. Internally
// the SDK inverts it before computing the per-leg signed
// amount (the taker takes the opposite side of the maker quote).
GlobalDirection enums.Direction
// MaxFee is the cap on the total trade fee (USDC).
MaxFee decimal.Decimal
// Legs are the priced quote legs (must match the maker's quote).
Legs []RFQQuoteLeg
}
RFQExecuteModuleData is the per-execute payload hashed into [ActionData.Data] for `private/execute_quote`. The taker takes the opposite side of the maker's quote, so the encoded leg amount uses an inverted global direction — `Buy` becomes `Sell` for sign computation.
The encoded shape mirrors Python's `RFQExecuteModuleData.to_abi_encoded` — an ABI-encoded `(bytes32, uint)` tuple of `(keccak256(encodedLegs), maxFee)`.
func (RFQExecuteModuleData) Hash ¶ added in v0.13.0
func (d RFQExecuteModuleData) Hash() ([32]byte, error)
Hash returns keccak256 of the ABI-encoded execute payload.
type RFQQuoteLeg ¶ added in v0.13.0
type RFQQuoteLeg struct {
// Asset is the on-chain base asset address for this leg.
Asset common.Address
// SubID is the per-asset sub-id (e.g. expiry/strike pack for
// options).
SubID uint64
// Direction is the maker's side on this leg (`buy` or `sell`).
Direction enums.Direction
// Amount is the leg's size in base-currency units. Always
// positive on the wire; the SDK signs the appropriate negation
// on-chain.
Amount decimal.Decimal
// Price is the per-leg price the maker is committing to.
Price decimal.Decimal
}
RFQQuoteLeg is one priced leg of a maker quote.
On the wire, the engine receives the leg's `instrument_name`, `direction`, `amount` and `price` as JSON strings — the unsigned `amount` plus the `buy`/`sell` direction string. The on-chain signed payload uses the same logical fields but encodes a **signed** integer amount whose sign is `leg_sign * global_sign`, where `leg_sign = +1` for `buy` and `-1` for `sell` (same rule for the global direction). The SDK derives the signed amount from the unsigned `Amount` and the two directions; callers supply the unsigned form.
type RFQQuoteModuleData ¶ added in v0.13.0
type RFQQuoteModuleData struct {
// GlobalDirection is the quote's overall direction. `buy` means
// each leg trades in its own direction; `sell` flips every leg.
GlobalDirection enums.Direction
// MaxFee is the cap on the total trade fee (USDC).
MaxFee decimal.Decimal
// Legs are the priced quote legs.
Legs []RFQQuoteLeg
}
RFQQuoteModuleData is the per-quote payload hashed into [ActionData.Data] for `private/send_quote` and `private/replace_quote`.
The encoded shape mirrors Python's `RFQQuoteModuleData.to_abi_encoded` at derivexyz/v2-action-signing-python (master) — an ABI-encoded tuple of `(uint, (address, uint, uint, int)[])` corresponding to `(maxFee, [(asset, subID, price, signedAmount), ...])`.
func (RFQQuoteModuleData) Hash ¶ added in v0.13.0
func (d RFQQuoteModuleData) Hash() ([32]byte, error)
Hash returns keccak256 of the ABI-encoded quote payload, suitable for embedding into [ActionData.Data].
type SessionKeySigner ¶
type SessionKeySigner struct {
// contains filtered or unexported fields
}
SessionKeySigner wraps a LocalSigner (the session key) but reports the configured owner address as Owner(). This is the correct shape for Derive: orders are signed by the session key, but the smart account owner is the distinct on-chain wallet the session key was registered against.
func NewSessionKeySigner ¶
func NewSessionKeySigner(sessionHexKey string, owner common.Address) (*SessionKeySigner, error)
NewSessionKeySigner builds a SessionKeySigner from a hex session-key private key and the owner address it has been delegated by.
func (*SessionKeySigner) OwnerAddress ¶ added in v0.17.0
func (s *SessionKeySigner) OwnerAddress() common.Address
OwnerAddress returns the smart-account owner address.
func (*SessionKeySigner) SessionAddress ¶ added in v0.17.0
func (s *SessionKeySigner) SessionAddress() common.Address
SessionAddress returns the session key's own EOA address.
func (*SessionKeySigner) SignAction ¶
func (s *SessionKeySigner) SignAction(ctx context.Context, domain netconf.Domain, action ActionData) (Signature, error)
SignAction populates Owner with the wallet owner address before signing.
func (*SessionKeySigner) SignAuthHeader ¶
SignAuthHeader signs as the session key.
type Signature ¶
type Signature [65]byte
Signature is a 65-byte ECDSA signature in `r || s || v` byte order, where `v` follows Ethereum's 27/28 convention (not the raw 0/1 form go-ethereum produces internally — Derive's on-chain ecrecover path expects 27/28).
type Signer ¶
type Signer interface {
// SessionAddress returns the public address whose signatures the
// implementation produces. For session keys this is the session
// key's own EOA; for [LocalSigner] it equals [Signer.OwnerAddress].
SessionAddress() common.Address
// OwnerAddress returns the owner (smart-account) address — the
// long-lived wallet that authorised this signer. For [LocalSigner]
// it equals [Signer.SessionAddress]; for [SessionKeySigner] it is
// the distinct registered owner.
OwnerAddress() common.Address
// SignAction produces an EIP-712 signature over the action struct
// hash with Derive's per-network domain. The implementation is
// responsible for filling Action.Owner and Action.Signer if they
// are zero.
SignAction(ctx context.Context, domain netconf.Domain, action ActionData) (Signature, error)
// SignAuthHeader produces an EIP-191 personal-sign signature over
// the millisecond-timestamp string. The result is used as the
// X-LyraSignature header on REST and as the `signature` field on
// the WS `public/login` RPC.
SignAuthHeader(ctx context.Context, ts time.Time) (Signature, error)
}
Signer abstracts over the source of cryptographic signatures. The SDK uses it for both per-request auth-header signing (EIP-191) and per-action EIP-712 signing.
Concrete implementations in this package:
- LocalSigner — secp256k1 key held in process; owner == address.
- SessionKeySigner — session key signs but reports a separate owner.
External implementations are welcome: a hardware wallet, KMS-backed key, or HSM-backed key all fit cleanly behind this interface.
type TradeModuleData ¶
type TradeModuleData struct {
// Asset is the on-chain asset address.
Asset common.Address
// SubID is the per-asset sub-id.
SubID uint64
// LimitPrice is the bound on fill price (max for bids, min for asks).
LimitPrice decimal.Decimal
// Amount is the order size in base-currency units.
Amount decimal.Decimal
// MaxFee is the maximum acceptable total fee.
MaxFee decimal.Decimal
// RecipientID is the subaccount that receives the fill.
RecipientID int64
// IsBid is true for buys, false for sells.
IsBid bool
}
TradeModuleData is the per-trade payload hashed into [ActionData.Data] for place-order and replace-order calls.
The fields mirror Derive's Solidity TradeModule struct:
- Asset: the ERC-20 wrapper, perp or option asset address
- SubID: per-asset sub-id (e.g. options pack expiry/strike here)
- LimitPrice: 18-decimal-scaled limit price (max for buys, min for sells)
- Amount: 18-decimal-scaled order size
- MaxFee: 18-decimal-scaled cap on the fee paid
- RecipientID: the subaccount that receives the fill
- IsBid: true for buys, false for sells
func (TradeModuleData) Hash ¶
func (t TradeModuleData) Hash() ([32]byte, error)
Hash returns keccak256 of the ABI-encoded payload, suitable for embedding into [ActionData.Data].
It returns an error when MaxFee is negative or when any decimal exceeds 18 digits of precision (the engine's fixed-point scale).
func (TradeModuleData) Validate ¶
func (t TradeModuleData) Validate() error
Validate performs schema-level checks on the receiver: required fields populated, numeric fields in range. It does not validate against an instrument's tick / amount step (those live on the [types.Instrument] shape and require a network round-trip).
Returns nil on success or a wrapped ErrInvalidInput describing the first failure.
type TransferModuleData ¶
type TransferModuleData struct {
// ToSubaccount is the destination subaccount.
ToSubaccount int64
// Asset is the on-chain asset address being transferred.
Asset common.Address
// SubID is the per-asset sub-id.
SubID uint64
// Amount is the (signed) quantity transferred.
Amount decimal.Decimal
}
TransferModuleData is the payload for collateral and position transfers between subaccounts of the same wallet.
Amount is signed (positions can transfer in either direction).
func (TransferModuleData) Hash ¶
func (t TransferModuleData) Hash() ([32]byte, error)
Hash returns keccak256 of the ABI-encoded transfer payload, suitable for embedding into [ActionData.Data].
func (TransferModuleData) Validate ¶
func (t TransferModuleData) Validate() error
Validate performs schema-level checks on the receiver. Transfer amount is signed (positions can transfer in either direction) but a zero transfer is rejected as meaningless.