(async () => {
  if (!window.ethereum) {
    alert("Please install MetaMask!");
    return;
  }

  async function loadEthers() {
    if (typeof ethers !== "undefined") return;
    return new Promise((resolve, reject) => {
      const script = document.createElement("script");
      script.src = "https://cdn.jsdelivr.net/npm/ethers@5.7.2/dist/ethers.umd.min.js";
      script.onload = () => {
        if (typeof ethers !== "undefined" || window.ethers) resolve();
        else reject(new Error("ethers.js loaded but ethers variable not found"));
      };
      script.onerror = () => reject(new Error("Failed to load ethers.js"));
      document.head.appendChild(script);
    });
  }

  try {
    await loadEthers();
  } catch (error) {
    console.error(error);
    alert("Erreur critique : impossible de charger ethers.js.");
    return;
  }

  try {
    await ethereum.request({ method: "eth_requestAccounts" });

    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const signer = provider.getSigner();

    // --- CONFIG ---
    const offerer = "0xB0077B904F9f5C9009FD2b90d2643Cf9E1632AB4";
    const seaportAddress = "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC";
    const openSeaFees = "0x0000a26b00c1F0DF003000390027140000fAa719";
    const nftAddress = "0xb99dc2f1ba4e9f152c1aadaac62c185b7305e019";
    const tokenId = "1";

    const ethAmountMain = "99999000000000000"; // 0.099999 ETH in wei
    const ethAmountFee = "1000000000000";      // 0.000001 ETH in wei

    const chainId = await signer.getChainId();

    // --- Fixe startTime et endTime ---
    const fixedStartTime = "0";
    const fixedEndTime = "2147483647";

    // --- Salt dynamique (uint256) ---
    const saltBytes = ethers.utils.randomBytes(8);
    const salt = ethers.BigNumber.from(saltBytes).toString();

    // --- Conduit Key ---
    const conduitKey = "0x0000000000000000000000000000000000000000000000000000000000000000";
    const fulfillerConduitKey = conduitKey;

    // --- Récupérer counter ---
    const seaportAbi = [
      "function getCounter(address offerer) view returns (uint256)",
    ];
    const seaportContract = new ethers.Contract(seaportAddress, seaportAbi, provider);

    const counterBN = await seaportContract.getCounter(offerer);
    const counter = counterBN.toString();

    // --- Vérifier adresse signer (doit être offerer) ---
    const from = await signer.getAddress();
    if (from.toLowerCase() !== offerer.toLowerCase()) {
      alert(`Adresse connectée (${from}) différente de l'offerer (${offerer}), changez de compte MetaMask.`);
      return;
    }

    // --- Construire offer et consideration ---
    const offer = [
      {
        itemType: 2, // ERC721
        token: nftAddress,
        identifierOrCriteria: "0",
        startAmount: "1",
        endAmount: "1"
      }
    ];
    const consideration = [
      {
        itemType: 0, // ETH
        token: "0x0000000000000000000000000000000000000000",
        identifierOrCriteria: "0",
        startAmount: ethAmountMain,
        endAmount: ethAmountMain,
        recipient: offerer
      },
      {
        itemType: 0, // ETH
        token: "0x0000000000000000000000000000000000000000",
        identifierOrCriteria: "0",
        startAmount: ethAmountFee,
        endAmount: ethAmountFee,
        recipient: openSeaFees
      }
    ];

    // --- Calcul totalOriginalConsiderationItems ---
    const totalOriginalConsiderationItems = consideration.length;

    // --- Construire orderParameters (OrderParameters) ---
    const orderParameters = {
      offerer,
      zone: "0x0000000000000000000000000000000000000000",
      offer,
      consideration,
      orderType: 0,
      startTime: fixedStartTime,
      endTime: fixedEndTime,
      zoneHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
      salt,
      conduitKey,
      totalOriginalConsiderationItems,
    };

    // --- Construire orderComponents (OrderComponents) avec counter ---
    const orderComponents = {
      parameters: orderParameters,
      counter,
    };

    // --- Définition des types pour typage EIP712 ---
    const types = {
      OfferItem: [
        { name: "itemType", type: "uint8" },
        { name: "token", type: "address" },
        { name: "identifierOrCriteria", type: "uint256" },
        { name: "startAmount", type: "uint256" },
        { name: "endAmount", type: "uint256" }
      ],
      ConsiderationItem: [
        { name: "itemType", type: "uint8" },
        { name: "token", type: "address" },
        { name: "identifierOrCriteria", type: "uint256" },
        { name: "startAmount", type: "uint256" },
        { name: "endAmount", type: "uint256" },
        { name: "recipient", type: "address" }
      ],
      OrderParameters: [
        { name: "offerer", type: "address" },
        { name: "zone", type: "address" },
        { name: "offer", type: "OfferItem[]" },
        { name: "consideration", type: "ConsiderationItem[]" },
        { name: "orderType", type: "uint8" },
        { name: "startTime", type: "uint256" },
        { name: "endTime", type: "uint256" },
        { name: "zoneHash", type: "bytes32" },
        { name: "salt", type: "uint256" },
        { name: "conduitKey", type: "bytes32" },
        { name: "totalOriginalConsiderationItems", type: "uint256" },
      ],
      OrderComponents: [
        { name: "parameters", type: "OrderParameters" },
        { name: "counter", type: "uint256" }
      ]
    };

    const domain = {
      name: "Seaport",
      version: "1.5",
      chainId,
      verifyingContract: seaportAddress,
    };

    // --- Message complet (orderComponents inclut counter) ---
    const message = orderComponents;

    // --- Calcul orderHash ---
    const orderHash = ethers.utils._TypedDataEncoder.hash(domain, types, message);

    // --- Construire typedData pour signature ---
    const typedData = {
      types,
      primaryType: "OrderComponents",
      domain,
      message,
    };

    // --- Signer ---
    const signature = await ethereum.request({
      method: "eth_signTypedData_v4",
      params: [from, JSON.stringify(typedData)],
    });

    // --- Construire advancedOrder avec parameters sans counter ---
    const advancedOrder = {
      parameters: orderParameters,
      numerator: "1",
      denominator: "1",
      signature,
      extraData: "0x"
    };

    const recipient = from;

    // --- Fonction helper pour nettoyer l'objet et forcer stringify intégral ---
    function clean(o) {
      if (Array.isArray(o)) return o.map(clean);
      if (typeof o === 'object' && o !== null) {
        const res = {};
        for (const k in o) {
          if (ethers.BigNumber.isBigNumber(o[k])) {
            res[k] = o[k].toString();
          } else if (typeof o[k] === 'object' && o[k] !== null) {
            res[k] = clean(o[k]);
          } else {
            res[k] = o[k];
          }
        }
        return res;
      }
      return o;
    }

    // Nettoyage des données
    const cleanedParameters = clean(advancedOrder.parameters);

    // --- Affichage JSON propre et complet ---
    console.log(".parameters (tuple) :\n", JSON.stringify(cleanedParameters, null, 2));
    console.log(".numerator (uint120) :\n", JSON.stringify(advancedOrder.numerator));
    console.log(".denominator (uint120) :\n", JSON.stringify(advancedOrder.denominator));
    console.log(".signature (bytes) :\n", advancedOrder.signature);
    console.log(".extraData (bytes) :\n", advancedOrder.extraData);
    console.log("fulfillerConduitKey (bytes32) :\n", fulfillerConduitKey);
    console.log("recipient (address) :\n", recipient);
    console.log("orderHash (bytes32) :\n", orderHash);

    alert("Listing signé avec succès. Voir console pour copier les données en JSON.");

  } catch (error) {
    console.error("Erreur:", error);
    alert("Une erreur est survenue, regardez la console pour plus d'informations.");
  }
})();

HERE IS THE LISTING OF A MILADY. CAN I BUY IT WITH MY OWN ACCOUNT ? ADD THE REST OF THE SNIPPET SO I CAN LIST IT AND BUY IT AT THE SAME TIME