EIP-712 訂單簽名
概述
在創建訂單之前,Maker需要使用EIP-712標準對訂單數據進行簽名。EIP-712是以太坊的結構化數據簽名標準,可以讓用戶在簽名時清楚地看到要簽名的數據內容。
合約地址
text
Chain ID: 97
RFQSettlement: 0xCB310C56A19078aA969A922f382613d932D89D83測試代幣
測試環境中的MOCK穩定幣地址和獲取方式請參考測試指南
EIP-712 Domain
Domain定義了簽名的上下文環境,包括合約名稱、版本、鏈ID和驗證合約地址。
javascript
const domain = {
name: "RFQSettlement",
version: "1",
chainId: "<Chain ID>",
verifyingContract: "<RFQSettlement合約地址>"
}訂單類型定義
訂單數據結構包含以下字段:
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" }
]
}字段說明
訂單字段的詳細說明請參考創建訂單 - 請求參數
完整示例
javascript
import { ethers } from 'ethers'
// 1. 連接錢包
const provider = new ethers.BrowserProvider(window.ethereum)
const signer = await provider.getSigner()
const userAddress = await signer.getAddress()
// 2. 獲取鏈ID
const network = await provider.getNetwork()
const chainId = Number(network.chainId)
// 3. 從後端API獲取nonce和maker地址
const jwtToken = "your_jwt_token"
const nonceResponse = await fetch('/api/v1/orders/maker/next-nonce', {
headers: { 'Authorization': `Bearer ${jwtToken}` }
})
const { maker, next_nonce } = (await nonceResponse.json()).data
// 4. 定義Domain
const domain = {
name: "RFQSettlement",
version: "1",
chainId: "<Chain ID>",
verifyingContract: "<RFQSettlement合約地址>"
}
// 5. 定義訂單類型
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" }
]
}
// 6. 構建訂單數據
const order = {
maker: maker,
principal: userAddress,
isBuy: true,
ticker: "AAPL",
exchange: 0,
asset: "<USDT合約地址>",
price: ethers.parseUnits("150.5", 18), // 18位精度
quantity: "100", // 整數
incentive: ethers.parseUnits("1.0", 18), // 18位精度
deadline: Math.floor(Date.now() / 1000) + 86400 * 30, // 30天後過期
nonce: next_nonce
}
// 7. 簽名
const signature = await signer.signTypedData(domain, types, order)
// 8. 提交訂單
const response = await fetch('/api/v1/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`
},
body: 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 result = await response.json()
console.log('訂單創建成功:', result)完整JSON示例
請求示例
json
{
"order": {
"maker": "0x1234567890123456789012345678901234567890",
"principal": "0x1234567890123456789012345678901234567890",
"is_buy": true,
"ticker": "AAPL",
"exchange": 0,
"asset": "<USDT合約地址>",
"price": "150500000000000000000",
"quantity": "100",
"incentive": "1000000000000000000",
"deadline": 1735689600,
"nonce": 1
},
"signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12"
}響應示例
json
{
"code": 0,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"maker": "0x1234567890123456789012345678901234567890",
"principal": "0x1234567890123456789012345678901234567890",
"is_buy": true,
"ticker": "AAPL",
"exchange": 0,
"asset": "<USDT合約地址>",
"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"
}
}重要注意事項
1. Nonce管理
- 每個訂單必須使用唯一的nonce
- 必須從後端API獲取,詳見查詢Nonce
- nonce用於防止重放攻擊
2. 授權檢查
創建訂單前需要授權代幣:
javascript
// 買入訂單:授權USDT/USDC
await usdtContract.approve(rfqSettlementAddress, ethers.MaxUint256)3. Deadline設置
- deadline必須至少為當前時間 + 720小時(30天)
- 建議限價單設置更長的有效期以確保有足夠時間成交
- 使用Unix時間戳(秒)
javascript
const deadline = Math.floor(Date.now() / 1000) + 86400 * 30 // 30天後4. 價格和手續費
- 使用預估訂單手續費接口獲取準確的價格和手續費
- 價格需要考慮匯率換算
- incentive(手續費)必須 >= 預估手續費,否則訂單不會被執行