Session Signatures

Session signatures allow traders to interact with Odyssey without signing messages in their wallet for every interaction.

Signing messages for every trade, transfer, and withdrawal makes the experience of using most DEXs much worse than using centralized equivalents. To solve this problem, Odyssey has introduced session signatures, which allow a user to grant their browser or device access to their account for a fixed period.

Session signatures are implemented when interacting with Odyssey via Hook's site (see Official Links for a list of official frontends). Developers can also utilize session signatures if it is helpful for their use case.

When to use session signatures

  • You're operating a trading bot, but do not have secure secret storage or the ability to quickly sign messages with your keys.

  • You expect traders to interact with your app

  • Multiple bots to need access to a shared account, with the ability to soft-revoke that access.

What actions on Hook can be signed by a session signature

  • Transferring collateral between margin accounts

  • Placing market & limit orders

  • Changing subaccount margin mode

  • Requesting deposits and withdrawals from Hook's Perps Liquidity Pools.

What actions require signatures from the account owner's wallet

  • Withdrawals from the protocol

  • Ragequitting a Perp Liquidity Pool

Using Session Signatures

To use a session signature, a payload must be signed and then delivered.

The payload has several key inputs:

  • signer is the public key of the delegated wallet to sign messges.

  • authorizor is the public key of the account owner.

  • expiration is the UNIX timestamp when this session signature expires

  • chainId is the chain used by the wallet signing the signature (in the EIP-712 Header)

The first 3 of these parameters must be hashed and signed into an EIP-712 payload, which is passed to the API. The EIP712 typehash is SigningKey(address signer,address authorizer,uint256 validUntil) After this payload is signed by the authorizor private key, it can be submitted to the GraphQL api.

The following API endpoints are used to create and revoke Session Signatures (f.k.a signing keys):

input SigningKeyInput {
  signer: Address!
  authorizer: Address!
  expiration: DateTime!
  chainId: Number!
} 

type Mutation {
  """
  Signing keys allow alternative private keys instead of the primary accounts to
  be used to sign orders. Use this mutation to submit a signing key.
  """
  registerSigningKey(signingKey: SigningKeyInput!, signature: String!): ID!
  
  
  """
  Once a signing key is used, you may revoke it with this mutation. No orders
  submitted after the revoke will be usable with the signing key. If a signing
  key is believed to be compromised, the nonce should be incremented on the 
  protocol.
  """
  revokeSigningKey(signingKeyHash: String!, authorizer: String!): Boolean!
}

First, call registerSigningKey with the signingKey input created above and the string-encoded signature.

This mutation returns an ID if the signing key is accepted. This ID can be used in future requests where the signing key is used as a signer.

Other signed mutations include a parameter for a Signature. when using a Signing key, fill the signature struct as follows:

### input SignatureInput 
{
  signatureType: SignatureType.SIGNING_KEY,
  signature: <string encoded signature of payload, signed by the signer>
  signingKeyID: <ID Returned by the registerSigningKeyMutation>
}    

Signing without session signatures

If your use-case doesn't need a signing key, you may populate the SignatureInput as follows:

### input SignatureInput 
{
  signatureType: SignatureType.DIRECT,
  signature: <string encoded signature of payload, signed by the owner's private key>
}   

Last updated