EIP-712 Order Signature
Overview
Before creating an order, Makers need to sign the order data using the EIP-712 standard. EIP-712 is Ethereum's structured data signing standard that allows users to clearly see the data being signed.
Contract Addresses
Multi-Chain Support
The platform supports multiple blockchain networks. Please refer to the Multi-Chain Support documentation for:
- All supported chains and their chain_id
- RFQSettlement and StockTokenManager contract addresses on each chain
- How to obtain and use Chain ID
EIP-712 Domain
The Domain defines the signing context, including contract name, version, chain ID, and verifying contract address.
javascript
const domain = {
name: "RFQSettlement",
version: "1",
chainId: "<Chain ID>",
verifyingContract: "<RFQSettlement Contract Address>"
}Order Type Definition
The order data structure contains the following fields:
javascript
const types = {
Order: [
{ name: "maker", type: "address" },
{ name: "principal", type: "address" },
{ name: "isBuy", type: "bool" },
{ name: "ticker", type: "string" },
{ name: "exchange", type: "uint16" },
{ name: "asset", type: "address" },
{ name: "price", type: "uint256" },
{ name: "quantity", type: "uint256" },
{ name: "incentive", type: "uint256" },
{ name: "deadline", type: "uint256" },
{ name: "nonce", type: "uint256" }
]
}Field Description
For detailed field descriptions, please refer to Create Order - Request Parameters
Complete Example
javascript
import { ethers } from 'ethers'
// 1. Connect wallet
const provider = new ethers.BrowserProvider(window.ethereum)
const signer = await provider.getSigner()
const userAddress = await signer.getAddress()
// 2. Get chain ID
const network = await provider.getNetwork()
const chainId = Number(network.chainId)
// 3. API Authentication setup
const crypto = require('crypto')
const apiKey = "YOUR_API_KEY"
const apiSecret = "YOUR_API_SECRET"
const makerAddr = "YOUR_MAKER_ADDRESS"
function signRequest(method, path, body = '') {
const timestamp = Date.now()
const signatureString = `${method}|${path}|${makerAddr}|${timestamp}|${body}`
const signature = crypto.createHmac('sha256', apiSecret).update(signatureString).digest('base64')
return {
'X-API-Key': apiKey,
'X-Maker-Addr': makerAddr,
'X-API-Timestamp': timestamp.toString(),
'X-API-Signature': signature,
'Content-Type': 'application/json'
}
}
// 4. Get nonce and maker address from backend API
const nonceResponse = await fetch('/api/v1/orders/maker/next-nonce', {
headers: signRequest('GET', '/api/v1/orders/maker/next-nonce')
})
const { maker, next_nonce } = (await nonceResponse.json()).data
// 5. Define Domain
const domain = {
name: "RFQSettlement",
version: "1",
chainId: "<Chain ID>",
verifyingContract: "<RFQSettlement Contract Address>"
}
// 6. Define order types
const types = {
Order: [
{ name: "maker", type: "address" },
{ name: "principal", type: "address" },
{ name: "isBuy", type: "bool" },
{ name: "ticker", type: "string" },
{ name: "exchange", type: "uint16" },
{ name: "asset", type: "address" },
{ name: "price", type: "uint256" },
{ name: "quantity", type: "uint256" },
{ name: "incentive", type: "uint256" },
{ name: "deadline", type: "uint256" },
{ name: "nonce", type: "uint256" }
]
}
// 7. Build order data
const order = {
maker: maker,
principal: userAddress,
isBuy: true,
ticker: "AAPLs",
exchange: 0,
asset: "<USDT Contract Address>",
price: ethers.parseUnits("150.5", 18), // 18 decimals
quantity: "100", // Integer
incentive: ethers.parseUnits("1.0", 18), // 18 decimals
deadline: Math.floor(Date.now() / 1000) + 86400 * 30, // Expires in 30 days
nonce: next_nonce
}
// 8. Sign
const signature = await signer.signTypedData(domain, types, order)
// 9. Submit order
const orderBody = JSON.stringify({
order: {
maker: order.maker,
principal: order.principal,
is_buy: order.isBuy,
ticker: order.ticker,
exchange: order.exchange,
asset: order.asset,
price: order.price.toString(),
quantity: order.quantity,
incentive: order.incentive.toString(),
deadline: order.deadline,
nonce: order.nonce
},
signature: signature
})
const response = await fetch('/api/v1/orders', {
method: 'POST',
headers: signRequest('POST', '/api/v1/orders', orderBody),
body: orderBody
})
const result = await response.json()
console.log('Order created successfully:', result)Complete JSON Examples
Request Examples
json
{
"order": {
"maker": "0x1234567890123456789012345678901234567890",
"principal": "0x1234567890123456789012345678901234567890",
"is_buy": true,
"ticker": "AAPLs",
"exchange": 0,
"asset": "<USDT Contract Address>",
"price": "150500000000000000000",
"quantity": "100",
"incentive": "1000000000000000000",
"deadline": 1735689600,
"nonce": 1
},
"signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12"
}Response Example
json
{
"code": 0,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"maker": "0x1234567890123456789012345678901234567890",
"principal": "0x1234567890123456789012345678901234567890",
"is_buy": true,
"ticker": "AAPLs",
"exchange": 0,
"asset": "<USDT Contract Address>",
"price": "150500000000000000000",
"quantity": "100",
"incentive": "1000000000000000000",
"deadline": 1735689600,
"nonce": 1,
"signature": "0x1234567890abcdef...",
"order_hash": "0xabcdef1234567890...",
"status": "pending",
"filled_quantity": "0",
"created_at": "2025-01-17T03:00:24Z",
"updated_at": "2025-01-17T03:00:24Z"
}
}Important Notes
1. Nonce Management
- Each order must use a unique nonce
- Must be obtained from the backend API, see Query Nonce
- Nonce is used to prevent replay attacks
2. Authorization Check
Token authorization is required before creating orders:
javascript
// Buy order: Authorize USDT/USDC
await usdtContract.approve(rfqSettlementAddress, ethers.MaxUint256)3. Deadline Setting
- Deadline must be at least current time + 720 hours (30 days)
- Recommend setting longer validity for limit orders to ensure sufficient time for execution
- Use Unix timestamp (seconds)
javascript
const deadline = Math.floor(Date.now() / 1000) + 86400 * 30 // 30 days later4. Price and Fees
- Use Estimate Order Fee endpoint to get accurate price and fees
- Price needs to consider exchange rate conversion
- incentive (fee) must be >= estimated fee, otherwise the order will not be executed
- For sell orders, the fee is deducted from the stablecoin proceeds; no separate USDT/USDC approval is required for the fee
Related Endpoints
- Get Nonce - Get the next available nonce
- Estimate Order Fee - Get order price and fee estimation
- Create Order - Submit signed order