使用@opensea/seaport-js在OpenSea创建NFT挂单遇400错误求助
解决Polygon Mumbai测试网Seaport-JS挂单OpenSea API 400错误的问题
一、核心问题排查与修复
1. startTime/endTime类型错误
你的代码将startTime和endTime转为字符串,但Seaport订单要求这两个字段是数字类型(Unix时间戳),类型不匹配会触发API校验失败。
修复:移除.toString(),直接使用数字值:
startTime: Math.floor(new Date().getTime() / 1000), endTime: Math.floor(new Date().getTime() / 1000 + 90 * 90),
2. Consideration缺失itemType字段
consideration数组中的对象必须指定itemType(ETH支付对应itemType: 0),缺失该字段会导致API拒绝请求。
修复:为每个consideration项添加itemType:
consideration: [ { itemType: 0, amount: '975000000000000', recipient: '0x6928C327bf8....27150A7Dc0dAE672', }, { itemType: 0, amount: '25000000000000', recipient: "0x0000a26b00c1F0DF003000390027140000fAa719", }, ],
3. Counter值硬编码错误
counter是offerer的链上订单计数器,必须与当前链上值一致,硬设为0会导致订单签名无效。
修复:动态获取counter值:
const offererAddress = '0x6928C327bf8B6...7Dc0dAE672'; const counter = await seaport.getCounter(offererAddress); // 在createOrder参数中使用该值 counter: counter,
4. 冗余字段与参数问题
- 手动添加的
protocol_address属于冗余字段,seaport-js生成的订单已包含合约地址信息,删除该行可避免格式冲突。 createOrder的第二个offerer地址参数重复,已在第一个参数的offerer字段指定,直接移除即可。
二、修复后的完整代码示例
const provider = new ethers.providers.JsonRpcProvider('ALCHEMY_PROVIDER'); const signer = new ethers.Wallet('MY_PK', provider); const seaport = new Seaport(signer, {seaportVersion: '1.4'}); try { const offererAddress = '0x6928C327bf8B6...7Dc0dAE672'; const counter = await seaport.getCounter(offererAddress); const {executeAllActions} = await seaport.createOrder({ offerer: offererAddress, zone: "0x0000000000000000000000000000000000000000", zoneHash: "0x0000000000000000000000000000000000000000000000000000000000000000", startTime: Math.floor(new Date().getTime() / 1000), endTime: Math.floor(new Date().getTime() / 1000 + 90 * 90), orderType: 1, offer: [ { itemType: 3, token: '0x28f43DebFfA....f08113ac10cf6BF0a897', identifier: '4', }, ], consideration: [ { itemType: 0, amount: '975000000000000', recipient: offererAddress, }, { itemType: 0, amount: '25000000000000', recipient: "0x0000a26b00c1F0DF003000390027140000fAa719", }, ], counter: counter, }); const order = await executeAllActions(); const options = { method: "POST", url: "https://testnets-api.opensea.io/v2/orders/mumbai/seaport/listings", headers: { accept: "application/json", "X-API-KEY": "OPENSEA-API-KEY", // 测试网可省略 "content-type": "application/json", }, data: order, }; const response = await axios.request(options); console.log("挂单成功:", response.data); } catch (error) { // 打印完整错误详情,API通常会返回具体原因 console.error("错误详情:", error.response?.data || error.message); }
三、替代方案:直接链上签名挂单
若OpenSea API仍有问题,可跳过API直接生成签名订单,用户可在OpenSea界面看到该订单(OpenSea会自动索引链上订单):
- 生成并签名订单后,可将订单信息存储到自己的数据库或链上。
- 也可调用Seaport合约的
validateOrder方法验证订单有效性,确保签名正确。
四、额外调试建议
- 确保offerer拥有目标NFT,并已授权Seaport合约(Mumbai测试网地址:
0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC)转移该NFT。 - 捕获axios错误时打印
error.response.data,OpenSea API会在返回体中给出具体错误提示。
内容的提问来源于stack exchange,提问作者longleilei
相关产品推荐
相关产品推荐

