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

NodeJS对接OpenSea NFT测试如何获取0-500区间不重复tokenId

OpenSea批量上架tokenId去重实现方案

核心实现逻辑

维护全局可用tokenId池,每次取用后直接从池中移除,从根源避免重复生成,同时处理池耗尽后的停止逻辑,避免无效请求。

修改后完整代码

const opensea = require("opensea-js");
const OpenSeaPort = opensea.OpenSeaPort;
const Network = opensea.Network;
const MnemonicWalletSubprovider = require("@0x/subproviders")
  .MnemonicWalletSubprovider;
const RPCSubprovider = require("web3-provider-engine/subproviders/rpc");
const Web3ProviderEngine = require("web3-provider-engine");

const MNEMONIC = 'SECRET';
const NODE_API_KEY = 'MyKEY';
const isInfura = true;
const FACTORY_CONTRACT_ADDRESS = '0x745e6b0CAd1eDc72647B9fFec5C69e4608f73ab2';
const NFT_CONTRACT_ADDRESS = '0x745e6b0CAd1eDc72647B9fFec5C69e4608f73ab2';
const OWNER_ADDRESS = '0xaEBB892210eB23C47b1e710561c7BC4CFA63A62e';
const NETWORK = 'rinkeby';
const API_KEY = ""; // 高频率请求建议填写API key

// 新增:全局可用tokenId池,初始填充0-499所有整数
const availableTokenIds = Array.from({length: 500}, (_, i) => i);
// 新增:定时器实例,用于控制任务启停
let publishTimer = null;

if (!MNEMONIC || !NODE_API_KEY || !NETWORK || !OWNER_ADDRESS) {
  console.error(
    "请配置助记词、Alchemy/Infura密钥、所有者地址、网络、API key、NFT合约地址和工厂合约地址"
  );
  process.exit();
}

if (!FACTORY_CONTRACT_ADDRESS && !NFT_CONTRACT_ADDRESS) {
  console.error("请配置工厂合约地址或NFT合约地址");
  process.exit();
}

const BASE_DERIVATION_PATH = `44'/60'/0'/0`;

const mnemonicWalletSubprovider = new MnemonicWalletSubprovider({
  mnemonic: MNEMONIC,
  baseDerivationPath: BASE_DERIVATION_PATH,
});
const network = 
  NETWORK === "mainnet" || NETWORK === "live" ? "mainnet" : "rinkeby";
const infuraRpcSubprovider = new RPCSubprovider({
  rpcUrl: isInfura
    ? "https://" + network + ".infura.io/v3/" + NODE_API_KEY
    : "https://eth-" + network + ".alchemyapi.io/v2/" + NODE_API_KEY,
});

const providerEngine = new Web3ProviderEngine();
providerEngine.addProvider(mnemonicWalletSubprovider);
providerEngine.addProvider(infuraRpcSubprovider);
providerEngine.start();

const seaport = new OpenSeaPort(
  providerEngine,
  {
    networkName:
      NETWORK === "mainnet" || NETWORK === "live"
        ? Network.Main
        : Network.Rinkeby,
    apiKey: API_KEY,
  },
  (arg) => console.log(arg)
);

// 新增:从未使用的tokenId池中随机取一个id,取完即移除
function getUnusedTokenId() {
  if (availableTokenIds.length === 0) return null;
  const randomIndex = Math.floor(Math.random() * availableTokenIds.length);
  return availableTokenIds.splice(randomIndex, 1)[0];
}

async function sellTheItems() {
  // 取出未使用的tokenId
  const tokenId = getUnusedTokenId();
  // 没有可用id时停止任务
  if (tokenId === null) {
    clearInterval(publishTimer);
    console.log("0-499范围内所有tokenId均已上架,任务结束");
    process.exit();
  }

  console.log("正在创建固定价格售卖订单...");
  const fixedPriceSellOrder = await seaport.createSellOrder({
    asset: {
        tokenId: tokenId.toString(),
        tokenAddress: NFT_CONTRACT_ADDRESS,
    },
    startAmount: 0.36,
    expirationTime: 0,
    accountAddress: OWNER_ADDRESS,
  });
  console.log(
    `固定价格售卖订单创建成功! ${fixedPriceSellOrder.asset.openseaLink}\n`
  );

}

async function doItAgain() {
    // 新增await避免异步并发导致的重复取值问题
    await sellTheItems();
}
// 把定时器赋值给全局变量方便控制
publishTimer = setInterval(doItAgain, 5000);

关键改动说明

  • 移除原随机生成tokenId的逻辑,改为从预先生成的可用id池中抽取,抽取后立即删除该id,保证不会重复
  • 给异步上架逻辑加了await控制执行顺序,避免并发请求导致的id重复问题
  • 新增id池耗尽后的自动停止逻辑,避免无效请求
  • 如果你需要程序重启后仍然不重复使用之前用过的id,可以把已使用的id写入本地json文件存储,启动时从可用池中过滤掉已使用的id即可。

内容的提问来源于stack exchange,提问作者Leandro Machado

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:54:03