You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 14:02:22