auth

package
v0.23.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 17, 2026 License: MIT Imports: 18 Imported by: 0

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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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

Constants

This section is empty.

Variables

View Source
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

func HTTPHeaders(ctx context.Context, signer Signer, now time.Time) (http.Header, error)

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

func (s *LocalSigner) SignAuthHeader(_ context.Context, ts time.Time) (Signature, error)

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

func (g *NonceGen) Next() uint64

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

func (s *SessionKeySigner) SignAuthHeader(ctx context.Context, ts time.Time) (Signature, error)

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).

func (Signature) Hex

func (s Signature) Hex() string

Hex returns the canonical 0x-prefixed lowercase-hex representation. Length is always 132 characters (2 prefix + 65 bytes × 2).

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL