简而言之
Blockradar 签名 API 允许您使用钱包的私钥对纯文本消息和结构化数据(类型化数据)进行加密签名。签名可以向第三方服务证明钱包所有权,而无需转移资金或支付网络费用(Gas)。
前提条件
在使用签名 API 之前,请确保您已完成以下准备:
环境选择
选择 Testnet(测试网,用于开发)或 Mainnet(主网,用于生产)。钱包按环境隔离。
工作原理
签名 API 生成加密签名,证明您控制着特定的钱包地址。签名输出可以被任何第三方验证,而无需访问您的私钥。
消息签名
签署纯文本消息以证明钱包所有权。支持所有区块链:EVM、Tron 和 Solana。
类型化数据签名
按照 EIP-712 标准签署结构化数据。用于无 Gas 授权(EIP-2612 Permit)和委托转账(EIP-3009)。仅限 EVM。
常见使用场景
- 第三方服务注册 — 在接入 Iron、Circle 或其他 DeFi 协议等服务时,证明您拥有某个地址
- 无 Gas 代币授权 — 签署 EIP-2612 Permit 消息以授权代币支出,无需链上交易
- 委托转账 — 签署 EIP-3009 TransferWithAuthorization 消息以进行委托转账
- 链下证明 — 创建与钱包地址关联的可验证意向或协议证明
主钱包与子地址
签名 API 可在两个层级使用:
主钱包
使用主钱包的密钥进行签名。适用于资金管理级别的操作和服务商集成。
子地址
使用特定子地址的密钥进行签名。当第三方要求使用充值地址进行签名时使用。
接口端点
| 操作 | 主钱包 | 子地址 |
|---|
| 消息签名 | POST /v1/wallets/{walletId}/signing/message | POST /v1/wallets/{walletId}/addresses/{addressId}/signing/message |
| 类型化数据签名 | POST /v1/wallets/{walletId}/signing/typed-data | POST /v1/wallets/{walletId}/addresses/{addressId}/signing/typed-data |
消息签名
使用钱包的私钥签署纯文本消息。API 会签署消息、验证签名与钱包地址匹配,并返回签名和交易记录。
支持的区块链
| 区块链 | 签名标准 | 签名格式 |
|---|
| EVM (Ethereum, Polygon, BSC, Base, Arbitrum, Optimism, Celo) | EIP-191 (personal_sign) | 十六进制编码,包含 r、s、v 组件 |
| Tron | TronWeb signMessageV2 | 十六进制编码字符串 |
| Solana | Ed25519 | Base58 编码字符串 |
请求参数
| 参数 | 类型 | 必填 | 描述 |
|---|
message | string | 是 | 要签署的纯文本消息。最大 4,096 个字符。 |
reference | string | 否 | 您的内部追踪 ID。用于幂等性 — 重复的 reference 会被拒绝。 |
metadata | object | 否 | 与交易记录一起存储的自定义键值对。 |
消息签名示例
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/signing/message \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"message": "Please sign this message to verify your wallet ownership for Iron provider registration.",
"reference": "iron-verification-001",
"metadata": {
"provider": "iron",
"purpose": "wallet-verification"
}
}'
EVM 响应
{
"message": "Message signed successfully",
"statusCode": 200,
"data": {
"id": "770f9100-7338-4823-b1ce-3658fc67db09",
"hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b",
"status": "SUCCESS",
"type": "SIGNED",
"senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
"recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
"signedTransaction": {
"r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133",
"s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3",
"v": 27,
"signature": "0xdb095e6cbf...b31b"
},
"reference": "iron-verification-001",
"metadata": {
"provider": "iron",
"purpose": "wallet-verification"
},
"confirmed": true,
"createdAt": "2025-03-02T19:00:52.000Z"
}
}
Tron / Solana 响应
对于 Tron 和 Solana,signedTransaction 对象仅包含 signature 字段(没有 r、s、v 组件):
{
"message": "Message signed successfully",
"statusCode": 200,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"hash": "3xYkZ9...",
"status": "SUCCESS",
"type": "SIGNED",
"senderAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y",
"recipientAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y",
"signedTransaction": {
"signature": "3xYkZ9..."
},
"reference": "tron-verification-001",
"confirmed": true,
"createdAt": "2025-03-02T19:00:52.000Z"
}
}
响应字段
| 字段 | 描述 |
|---|
id | 签名记录的唯一交易 ID |
hash | 加密签名。EVM:十六进制字符串。Tron:十六进制字符串。Solana:Base58 字符串。 |
status | 对于已完成的签名,始终为 SUCCESS |
type | 对于签名交易,始终为 SIGNED |
senderAddress | 生成签名的钱包地址 |
signedTransaction | 签名组件。EVM 包含 r、s、v 和完整的 signature。Tron 和 Solana 仅包含 signature。 |
reference | 您提供的 reference 字符串(如有) |
metadata | 您提供的 metadata 对象(如有) |
类型化数据签名(仅限 EVM)
按照 EIP-712 标准签署结构化数据。用于无 Gas 授权、委托转账以及其他需要结构化签名的链上授权流程。
类型化数据签名仅适用于 EVM 兼容的区块链(Ethereum、Polygon、BSC、Base、Arbitrum、Optimism、Celo)。Tron 和 Solana 不支持 EIP-712。
支持的标准
| 标准 | 使用场景 |
|---|
| EIP-712 | 通用结构化数据签名 |
| EIP-2612 (Permit) | 无 Gas 代币授权 — 无需链上交易即可授权代币支出 |
| EIP-3009 (TransferWithAuthorization) | 委托转账 — 授权由第三方提交的转账 |
请求参数
| 参数 | 类型 | 必填 | 描述 |
|---|
domain | object | 是 | EIP-712 域分隔符。包括 name、version、chainId 和 verifyingContract。 |
types | object | 是 | 结构化数据的类型定义。 |
message | object | 是 | 要签署的数据,需符合类型定义。 |
EIP-2612 Permit 示例
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/signing/typed-data \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"domain": {
"name": "USD Coin",
"version": "2",
"chainId": 11155111,
"verifyingContract": "0xa0b86a33e6441b8c4c8c0c077bcdd28571685701"
},
"types": {
"Permit": [
{ "name": "owner", "type": "address" },
{ "name": "spender", "type": "address" },
{ "name": "value", "type": "uint256" },
{ "name": "nonce", "type": "uint256" },
{ "name": "deadline", "type": "uint256" }
]
},
"message": {
"owner": "0x742d35cc6634c0532925a3b8d4c9db96c4b4d8b6",
"spender": "0x8ba1f109551bd432803012645aac136c4c8c8c0c",
"value": "1000000000",
"nonce": "0",
"deadline": "1641081600"
}
}'
类型化数据响应
{
"message": "Typed data signed successfully",
"statusCode": 200,
"data": {
"id": "770f9100-7338-4823-b1ce-3658fc67db09",
"hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b",
"status": "SUCCESS",
"type": "SIGNED",
"senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
"recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
"signedTransaction": {
"r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133",
"s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3",
"v": 27,
"signature": "0xdb095e6cbf...b31b"
},
"confirmed": true,
"createdAt": "2025-03-02T19:00:52.000Z"
}
}
Domain 对象字段
| 字段 | 类型 | 必填 | 描述 |
|---|
name | string | 是 | 签名域的名称(例如代币名称或 dApp 名称) |
version | string | 是 | 域的版本 |
chainId | number | 是 | 链 ID。必须与钱包的区块链网络匹配。 |
verifyingContract | string | 是 | 将验证签名的合约地址 |
salt | string | 否 | EIP-712 v4 的可选域 salt |
链 ID 验证
域对象中的 chainId 必须与钱包所在区块链网络的链 ID 匹配。如果不匹配,API 将返回 400 Chain ID mismatch 错误。
子地址签名
使用特定子地址(而非主钱包)签署消息或类型化数据:
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/signing/message \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"message": "Verify ownership of deposit address for provider onboarding.",
"reference": "address-verify-001"
}'
子地址签名遵循与主钱包签名相同的请求和响应格式。唯一的区别是端点 URL 中包含了 addressId。
Webhook 事件
签名操作会触发一个包含交易记录的 Webhook:
| 事件 | 描述 |
|---|
signed.success | 消息或类型化数据已签署并验证 |
Webhook 载荷
{
"event": "signed.success",
"data": {
"id": "770f9100-7338-4823-b1ce-3658fc67db09",
"hash": "0xdb095e6cbf...b31b",
"status": "SUCCESS",
"type": "SIGNED",
"senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
"recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
"signedTransaction": {
"r": "0xdb095e6cbf...2133",
"s": "0x5aa3918399...89b3",
"v": 27,
"signature": "0xdb095e6cbf...b31b"
},
"reference": "iron-verification-001",
"metadata": {
"provider": "iron",
"purpose": "wallet-verification"
},
"wallet": {
"id": "d236a191-c1d4-423c-a439-54ce6542ca41",
"name": "Ethereum Master Wallet"
},
"blockchain": {
"name": "ethereum",
"network": "testnet"
},
"confirmed": true,
"createdAt": "2025-03-02T19:00:52.000Z"
}
}
完整流程示例
以下是一个完整的实现示例,演示如何签署消息并将签名提交给第三方服务商:
async function signAndVerifyWithProvider(walletId, providerMessage) {
const apiKey = process.env.BLOCKRADAR_API_KEY;
const baseUrl = 'https://api.blockradar.co/v1';
// Step 1: Sign the message
const signResponse = await fetch(
`${baseUrl}/wallets/${walletId}/signing/message`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey
},
body: JSON.stringify({
message: providerMessage,
reference: `provider-verify-${Date.now()}`
})
}
).then(r => r.json());
if (signResponse.statusCode !== 200) {
throw new Error(`Signing failed: ${signResponse.message}`);
}
const { hash, senderAddress } = signResponse.data;
// Step 2: Submit the signature to the third-party provider
// The provider can verify the signature matches the wallet address
// without accessing your private keys
return {
address: senderAddress,
signature: hash,
message: providerMessage
};
}
// Usage
signAndVerifyWithProvider(
'wallet-uuid',
'I authorize Iron to manage assets on my behalf.'
);
错误响应
{
"message": "Wallet not found",
"statusCode": 404
}
该 walletId 不存在或不属于您的业务。
{
"message": "Address not found",
"statusCode": 404
}
该 addressId 不存在或未与指定钱包关联。
{
"message": "Typed data signing is only supported for EVM blockchains",
"statusCode": 400
}
类型化数据签名(EIP-712)仅适用于 EVM 兼容链。Tron 和 Solana 请使用消息签名。
{
"message": "Chain ID mismatch",
"statusCode": 400
}
类型化数据域对象中的 chainId 与钱包的区块链网络不匹配。
{
"message": "Signature verification failed",
"statusCode": 400
}
内部往返验证失败。这表明系统出现错误 — 请联系技术支持。
最佳实践
安全性
- 使用 reference — 使用唯一的 reference ID 追踪签名操作,用于审计跟踪和幂等性
- 验证消息内容 — 签名前,确认消息内容与第三方服务预期的内容一致
- 限制消息长度 — 消息上限为 4,096 个字符。保持消息简洁明确
- 无 Gas 费用 — 签名操作在链下进行,不需要原生代币余额
- 即时响应 — 签名是同步生成的。签名本身不需要轮询或等待 Webhook
- 监听 Webhook — 使用 Webhook 维护所有签名事件的审计记录
类型化数据
- 匹配链 ID — 域中的
chainId 必须与钱包的网络匹配。测试使用沙盒(测试网)链 ID,生产使用正式(主网)链 ID
- 检查合约 —
verifyingContract 必须是将在链上验证签名的合约
API 参考
主钱包端点
| 端点 | 描述 |
|---|
| 消息签名 | 签署纯文本消息 |
| 类型化数据签名 | 签署 EIP-712 结构化数据 |
子地址端点
| 端点 | 描述 |
|---|
| 消息签名 | 从子地址签署纯文本消息 |
| 类型化数据签名 | 从子地址签署 EIP-712 结构化数据 |