Python实现Blur.io EIP-712消息签名问题求助
Python实现Blur.io集合出价的EIP-712签名(匹配Metamask结果)
问题核心在于EIP-712签名对结构化数据的构造、编码要求极其严格,JS和Python的差异通常出现在字段顺序、数据类型、哈希计算细节上。以下是和官方JS代码完全对齐的Python实现方案:
官方JS参考代码(可正常运行)
官方提供的签名实现:
const { ethers } = require("ethers"); async function signCollectionBid(privateKey, bidData) { const domain = { name: "Blur Exchange", version: "1", chainId: 1, verifyingContract: "0x0000000000A39bb272e79075ade125fd351887Ac" }; const types = { CollectionBid: [ { name: "collection", type: "address" }, { name: "price", type: "uint256" }, { name: "tokenId", type: "uint256" }, { name: "expiration", type: "uint256" }, { name: "nonce", type: "uint256" } ] }; const signer = new ethers.Wallet(privateKey); const signature = await signer.signTypedData(domain, types, bidData); return signature; }
对应Python实现(基于web3.py)
from web3 import Web3 from eth_account.messages import encode_structured_data def sign_collection_bid(private_key, bid_data): # 严格匹配官方定义的EIP-712域参数 domain = { "name": "Blur Exchange", "version": "1", "chainId": 1, "verifyingContract": "0x0000000000A39bb272e79075ade125fd351887Ac" } # 字段顺序、类型必须和JS代码完全一致,EIP-712哈希计算依赖顺序 types = { "CollectionBid": [ {"name": "collection", "type": "address"}, {"name": "price", "type": "uint256"}, {"name": "tokenId", "type": "uint256"}, {"name": "expiration", "type": "uint256"}, {"name": "nonce", "type": "uint256"} ] } # 编码结构化数据,生成符合EIP-712规范的消息哈希 encoded_data = encode_structured_data( domain=domain, message_types=types, message=bid_data ) # 使用私钥签名,返回十六进制格式签名 w3 = Web3() signed_message = w3.eth.account.sign_message(encoded_data, private_key=private_key) return signed_message.signature.hex()
必须遵守的签名规则(否则会和Metamask结果不一致)
- 域参数完全一致:
name、version、chainId、verifyingContract不能有拼写错误、大小写差异,测试网需修改对应chainId(比如Goerli是5)。 - 字段顺序严格对齐:
CollectionBid的字段顺序必须和JS代码完全相同,顺序错了哈希结果直接不同。 - 数据类型正确:所有数值类字段(price、tokenId等)必须传整数,不能是字符串;地址必须是0x开头的标准格式,建议全小写。
- 私钥格式正确:支持带0x或不带0x前缀的64位十六进制字符串。
测试示例
# 构造集合出价数据 bid_data = { "collection": "0x1234567890abcdef1234567890abcdef12345678", "price": 1000000000000000000, # 1 ETH(wei单位) "tokenId": 0, # 集合出价固定传0 "expiration": 1718000000, # 过期时间戳 "nonce": 123 # 从Blur接口获取的用户nonce } # 替换为你的私钥 private_key = "your_private_key_here" signature = sign_collection_bid(private_key, bid_data) print(signature)
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

