Skip to main content
The easiest way to begin signing is to either use the SDKs directly. Continue reading for a deep dive into the signing scheme, its parameters, and how to debug signature issues.

Why sign actions?

Every state-changing action — placing an order, transferring spot, withdrawing, creating a session key — carries its own EIP-712 signature over an Action struct. This ensures the protocol is self-custodial.
Action signing is not session login. Login (EIP-191) authenticates a connection; it does not authorize actions. Each action is signed and verified on its own. Keep the two layers distinct.

Debugging signature issues

If a signature is rejected, use the signing-preview helpers to byte-compare each stage (encoded data, hashes, digest) against what the server computes. Each returns the encoded_data, action_hash, and typed_data_hash of the rebuilt action. These are a debugging aid, not a required step:
  • private/order_debug
  • private/transfer_positions_debug
  • private/transfer_spot_debug
  • private/transfer_spot_external_debug
  • private/update_whitelisted_recipients_debug
  • private/set_session_key_debug
  • public/send_quote_debug
  • public/execute_quote_debug
  • public/withdraw_debug

Constants

The module field names the contract whose ABI layout data follows. Module addresses are fixed protocol constants — identical across every deployment, safe to hardcode:

owner vs signer

owner is always the wallet that owns the subaccount. signer is whoever produced the signature — the wallet itself (owner == signer) or a delegated session key, in which case signer is the key’s address and owner stays the wallet. The protocol recovers the ECDSA signer and requires it to equal signer; if signer != owner, it loads the session key and checks its scopes cover the action.

Nonce and expiry

uint256
The nonce param (decoded as a UTC timestamp in nanoseconds * 6-digit suffix) has some special rules depending on the action.
uint256
The Action’s expiry, in unix seconds; rejected once now > expiry. The exchange enforces certain minimums depending on the action type to ensure the action is valid long enough.

Worked example: a buy order

An option buy order signed by the wallet directly (owner == signer). The SDK ABI-encodes the payload, builds and signs the EIP-712 digest, and submits it in a single call — amounts and prices are plain decimals, with e18 scaling handled internally:
The instrument name above is an option, named <CURRENCY>-<YYYYMMDD>-<STRIKE>-<C|P> (perps are <CURRENCY>-PERP). See Instrument names for the full grammar.