Signing Orders

πŸ“˜

Note

As a measure to counter replay attacks, we are adding the timestamp field for order signing. Presently, this field is optional.

Starting from 21 August 2023 00:00 UTC, the timestamp field will become mandatory, ensuring enhanced security and preventing potential replay attacks.

To create an order, a signature needs to be generated. This signature allows for the gasless trading experience in Aevo. The signature generation used by Aevo follows the guideline laid out in the EIP-712 (https://eips.ethereum.org/EIPS/eip-712) . This signing method is widely used and supported in most wallets.

🚧

Important!

The signature generated for order submission is different from the signature for authentication.

Method


  • Signature is generated by signing the Order payload using the account's Signing Key
  • Signing Key is generated during Enable Trading.

Example


from random import randint
from eip712_structs import EIP712Struct, Address, Uint, Boolean, make_domain
from web3 import Web3
from eth_account import Account

# Generate Salt
salt = randint(0, 10**6)

# Limit price and amount is in 6 decimal places
decimals = 10**6
limit_price = int(100 * decimals)  # Limit price of $100
amount = int(2 * decimals)  # Size of 2 contracts

# Current timestamp in UNIX seconds
timestamp = 1690434000 

# instrument_id from /options-chain
instrument = 1

class Order(EIP712Struct):
    maker = Address()
    isBuy = Boolean()
    limitPrice = Uint(256)
    amount = Uint(256)
    salt = Uint(256)
    instrument = Uint(256)
    timestamp = Uint(256)

order_struct = Order(maker="your_address", # The wallet's main address
                    isBuy=True, # True if buy, False if sell
                    limitPrice=limit_price,
                    amount=amount,
                    salt=salt,
                    instrument=instrument,
                    timestamp=timestamp)

# Get bytes
domain = make_domain(name="Aevo Mainnet", version="1", chainId=1)
# Testnet Domain
# domain = make_domain(name='Aevo Testnet', version='1', chainId=11155111)
signable_bytes = Web3.keccak(order_struct.signable_bytes(domain=domain))

# Sign with key
key = "your_signing_key"
signature = Account._sign_hash(signable_bytes, key).signature.hex()
// Get signing keys, and sign message
const signer = new ethers.Wallet(signingKey);

const orderMessage = {
  maker: "your_wallet_address,
  isBuy: true,  // true if buy, false if sell
  instrument: "ETH-24AUG22-1850-C",
  
  // Limit price is in 6 decimal places. 
  // Eg. $10.00 = "10000000"
  limitPrice: ethers.utils.parseUnits(10, 6).toString(),

  // This is the number of contracts
  amount: 10,
    
  // Timestamp in UNIX seconds
	timestamp: 1690434000, 

  // Random number
  salt: Math.floor(Math.random() * 100000).toString(),
}

// Get the order signature
const orderSignature = await signer._signTypedData(
  {
    name: "Aevo Mainnet",
    version: "1",
    chainId: 1,
  },
  { 
    Order: [
      { name: "maker", type: "address" },
      { name: "isBuy", type: "bool" },
      { name: "limitPrice", type: "uint256" },
      { name: "amount", type: "uint256" },
      { name: "salt", type: "uint256" },
      { name: "instrument", type: "uint256" },
      { name: "timestamp", type:"uint256" },
    ]
  },
  orderMessage
);