身份验证 (Authentication)
ZTDX API 使用 EIP-712 结构化签名进行身份验证。所有需要认证的接口都需要使用用户的以太坊私钥对 EIP-712 类型化数据进行签名。
EIP-712 签名标准
ZTDX 使用 EIP-712 (Ethereum Typed Structured Data Hashing and Signing) 标准进行签名验证。这是一种更加安全和用户友好的签名方式,钱包会清晰地显示签名的内容。
Domain Configuration
所有 EIP-712 签名使用以下 Domain 配置:
{
"name": "ZTDX",
"version": "1",
"chainId": <network_chain_id>,
"verifyingContract": "<vault_contract_address>"
}
参数说明:
chainId: 网络链 ID(如 Arbitrum Sepolia: 421614)verifyingContract: ZTDX Vault 合约地址
重要
不同的网络环境(测试网/主网)使用不同的 chainId 和 verifyingContract。请从服务器配置或前端环境变量中获取正确的值。
登录流程 (Login Flow)
登录流程分为两步:1) 获取 Nonce,2) 签名登录
1. 获取 Nonce
在登录前,必须先获取用户的当前 nonce 值和用于签名的 EIP-712 typed data。
请求
- Method:
GET - Path:
/api/v1/auth/nonce/:address - Authentication: 不需要
路径参数
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| address | string | 是 | 以太坊地址(0x开头,42字符) |
响应示例
{
"nonce": 1,
"typed_data": {
"types": {
"EIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" },
{ "name": "verifyingContract", "type": "address" }
],
"Login": [
{ "name": "wallet", "type": "address" },
{ "name": "nonce", "type": "uint256" },
{ "name": "timestamp", "type": "uint256" }
]
},
"primaryType": "Login",
"domain": {
"name": "ZTDX",
"version": "1",
"chainId": 421614,
"verifyingContract": "0xYourVaultContractAddress"
},
"message": {
"wallet": "0x742d35cc6634c0532925a3b844bc9e7595f0beb",
"nonce": "1",
"timestamp": "1704067200"
}
}
}
响应字段
| 字段 | 类型 | 描述 |
|---|---|---|
| nonce | number | 当前用户的 nonce 值(每次成功登录后自增) |
| typed_data | object | EIP-712 类型化数据,可直接用于钱包签名 |
Nonce 机制说明
- Nonce 在用户首次访问时创建,初始值为 1
- 每次成功登录后,nonce 会自动加 1
- 多次调用 nonce 接口,在未登录前返回值保持不变
- Nonce 用于防止重放攻击
2. 签名并登录
使用获取到的 typed_data 进行 EIP-712 签名,然后发送登录请求。
请求
- Method:
POST - Path:
/api/v1/auth/login - Content-Type:
application/json - Authentication: 不需要
请求参数
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| address | string | 是 | 以太坊地址(小写) |
| signature | string | 是 | EIP-712 签名(0x开头) |
| timestamp | number | 是 | Unix 时间戳(秒),需在 5 分钟内有效 |
时间戳格式
timestamp 使用秒级时间戳,而不是毫秒。请确保与 typed_data 中的 timestamp 保持一致。
请求示例
{
"address": "0x742d35cc6634c0532925a3b844bc9e7595f0beb",
"signature": "0xabcdef123456...",
"timestamp": 1704067200
}