PLEASE COMPARE THESE THREE SCRIPTS AND RATE THEM (EXAMPLE = 15/20: good work / 12/20: quite good but with errors / 18/20: excellent work)

FIRST SCRIPT =

(async () => {
  // -------- Constants --------
  const SEAPORT_ADDRESS = "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC".toLowerCase();
  const OFFERER_ADDRESS = "0xB0077B904F9f5C9009FD2b90d2643Cf9E1632AB4".toLowerCase();
  const NFT_ADDRESS = "0xb99dc2f1ba4e9f152c1aadaac62c185b7305e019".toLowerCase();
  const OPENSEA_FEE_RECIPIENT = "0x0000a26b00c1F0DF003000390027140000fAa719".toLowerCase();

  const TOKEN_ID = "1";
  const PRICE_MAIN_ETH = "0.099999"; // Price to sell NFT
  const PRICE_FEE_ETH = "0.000001";  // Fee to recipient

  // -------- EIP-712 Types --------
  const SEAPORT_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" },
    ],
  };

  // -------- Utility Functions --------

  async function loadEthers() {
    if (typeof ethers !== "undefined") return;
    await 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.async = true;
      script.onload = () => (typeof ethers !== "undefined" ? resolve() : reject("ethers not loaded"));
      script.onerror = () => reject("Failed to load ethers");
      document.head.appendChild(script);
    });
  }

  function lowercaseAddressesDeep(obj) {
    if (Array.isArray(obj)) return obj.map(lowercaseAddressesDeep);
    if (obj && typeof obj === "object") {
      return Object.fromEntries(
        Object.entries(obj).map(([k, v]) => 
          typeof v === "string" && /^0x[a-fA-F0-9]{40}$/.test(v) ? [k, v.toLowerCase()] : [k, lowercaseAddressesDeep(v)]
        )
      );
    }
    return obj;
  }

  function cleanBigNumbers(obj) {
    if (Array.isArray(obj)) return obj.map(cleanBigNumbers);
    if (obj && typeof obj === "object") {
      return Object.fromEntries(
        Object.entries(obj).map(([k, v]) =>
          ethers.BigNumber.isBigNumber(v) ? [k, v.toString()] : [k, cleanBigNumbers(v)]
        )
      );
    }
    return obj;
  }

  function buildOrderParams(counter, saltBN, priceMainWei, priceFeeWei) {
    return {
      parameters: {
        offerer: OFFERER_ADDRESS,
        zone: ethers.constants.AddressZero,
        offer: [
          {
            itemType: 2,
            token: NFT_ADDRESS,
            identifierOrCriteria: TOKEN_ID,
            startAmount: "1",
            endAmount: "1",
          },
        ],
        consideration: [
          {
            itemType: 0,
            token: ethers.constants.AddressZero,
            identifierOrCriteria: "0",
            startAmount: priceMainWei,
            endAmount: priceMainWei,
            recipient: OFFERER_ADDRESS,
          },
          {
            itemType: 0,
            token: ethers.constants.AddressZero,
            identifierOrCriteria: "0",
            startAmount: priceFeeWei,
            endAmount: priceFeeWei,
            recipient: OPENSEA_FEE_RECIPIENT,
          },
        ],
        orderType: 0,
        startTime: "0",
        endTime: "2147483647",
        zoneHash: ethers.constants.HashZero,
        salt: saltBN.toString(),
        conduitKey: ethers.constants.HashZero,
        totalOriginalConsiderationItems: 2,
      },
      counter,
    };
  }

  function parseSignature(signature) {
    const sigBytes = ethers.utils.arrayify(signature);
    return {
      r: ethers.utils.hexlify(sigBytes.slice(0, 32)),
      s: ethers.utils.hexlify(sigBytes.slice(32, 64)),
      v: sigBytes[64],
    };
  }

  function getDomain(chainId) {
    return {
      name: "Seaport",
      version: "1.5",
      chainId,
      verifyingContract: SEAPORT_ADDRESS,
    };
  }

  // -------- Main --------

  try {
    await loadEthers();

    if (!window.ethereum) throw new Error("MetaMask not detected!");

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

    let accounts = await provider.listAccounts();
    if (accounts.length === 0) accounts = await window.ethereum.request({ method: "eth_requestAccounts" });
    if (!accounts.length) throw new Error("No MetaMask accounts connected");

    const signer = provider.getSigner();
    const connectedAddress = (await signer.getAddress()).toLowerCase();

    if (connectedAddress !== OFFERER_ADDRESS) throw new Error(`Please switch MetaMask to offerer: ${OFFERER_ADDRESS}`);

    const chainId = await signer.getChainId();

    // Fetch and console.log the counter only (no popup)
    const seaportContract = new ethers.Contract(SEAPORT_ADDRESS, ["function getCounter(address) view returns (uint256)"], provider);
    const counterBN = await seaportContract.getCounter(OFFERER_ADDRESS);
    const counter = counterBN.toString();
    console.log(`Seaport counter for offerer ${OFFERER_ADDRESS}:`, counter);
    // <-- removed alert here as requested

    const saltBN = ethers.BigNumber.from(ethers.utils.randomBytes(32));
    const priceMainWei = ethers.utils.parseEther(PRICE_MAIN_ETH).toString();
    const priceFeeWei = ethers.utils.parseEther(PRICE_FEE_ETH).toString();

    const orderComponents = buildOrderParams(counter, saltBN, priceMainWei, priceFeeWei);

    const messageToSign = lowercaseAddressesDeep(orderComponents);

    const domain = getDomain(chainId);

    console.log("Please confirm signing the order (MetaMask popup)...");
    const signature = await signer._signTypedData(domain, SEAPORT_TYPES, messageToSign);

    const { r, s, v } = parseSignature(signature);

    const SECP256K1_N = ethers.BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
    if (ethers.BigNumber.from(s).gt(SECP256K1_N.div(2))) throw new Error("Signature 's' is not in lower half order.");

    const recoveredAddr = ethers.utils.verifyTypedData(domain, SEAPORT_TYPES, messageToSign, signature);
    if (recoveredAddr.toLowerCase() !== connectedAddress) throw new Error("Signature verification failed.");

    console.log("✔️ Signature verified!");
    console.log("Signer:", recoveredAddr);
    console.log("Signature components:", { r, s, v });
    console.log("Order hash:", ethers.utils._TypedDataEncoder.hash(domain, SEAPORT_TYPES, messageToSign));
    console.log("Order parameters:", JSON.stringify(cleanBigNumbers(messageToSign.parameters), null, 2));
    console.log("Full signature hex:", signature);

    console.info("Reminder: Approve Seaport contract for NFT before submitting this order on-chain.");
  } catch (error) {
    console.error("Error:", error);
    alert(error.message || "An error occurred, check console for details.");
  }
})();

SECOND SCRIPT =

(async () => {
// --- Constants ---
const SEAPORT_ADDRESS = "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC".toLowerCase();
const OFFERER_ADDRESS = "0xB0077B904F9f5C9009FD2b90d2643Cf9E1632AB4".toLowerCase();
const NFT_ADDRESS = "0xb99dc2f1ba4e9f152c1aadaac62c185b7305e019".toLowerCase();
const OPENSEA_FEE_RECIPIENT = "0x0000a26b00c1F0DF003000390027140000fAa719".toLowerCase();

const TOKEN_ID = "1";
const PRICE_MAIN_ETH = "0.099999"; // Price to sell NFT
const PRICE_FEE_ETH = "0.000001"; // Fee to recipient

// --- EIP-712 Type Definitions for Seaport 1.5 ---
const SEAPORT_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" },
],
};

// --- Utility Functions ---

// Load ethersjs dynamically if not present
async function loadEthers() {
if (typeof ethers !== "undefined") return;
await 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.async = true;
script.onload = () => (typeof ethers !== 'undefined' ? resolve() : reject('ethers not loaded'));
script.onerror = () => reject('Failed to load ethers');
document.head.appendChild(script);
});
}

// Defensive recursive lowercase for all 0x-prefixed 40-byte hex addresses
function lowercaseAddressesDeep(obj) {
if (Array.isArray(obj)) return obj.map(lowercaseAddressesDeep);
if (obj && typeof obj === "object") {
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [
k,
typeof v === "string" && /^0x[a-fA-F0-9]{40}$/.test(v) ? v.toLowerCase() : lowercaseAddressesDeep(v),
])
);
}
return obj;
}

// Clean BigNumber for JSON.stringify
function cleanBigNumbers(obj) {
if (Array.isArray(obj)) return obj.map(cleanBigNumbers);
if (obj && typeof obj === "object") {
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [
k,
ethers.BigNumber.isBigNumber(v) ? v.toString() : cleanBigNumbers(v),
]),
);
}
return obj;
}

// Build the order parameters
function buildOrderParams(counter, saltBN, priceMainWei, priceFeeWei) {
return {
parameters: {
offerer: OFFERER_ADDRESS,
zone: ethers.constants.AddressZero,
offer: [
{
itemType: 2, // ERC721
token: NFT_ADDRESS,
identifierOrCriteria: TOKEN_ID,
startAmount: "1",
endAmount: "1",
},
],
consideration: [
{
itemType: 0,
token: ethers.constants.AddressZero,
identifierOrCriteria: "0",
startAmount: priceMainWei,
endAmount: priceMainWei,
recipient: OFFERER_ADDRESS,
},
{
itemType: 0,
token: ethers.constants.AddressZero,
identifierOrCriteria: "0",
startAmount: priceFeeWei,
endAmount: priceFeeWei,
recipient: OPENSEA_FEE_RECIPIENT,
},
],
orderType: 0, // FULL_OPEN
startTime: "0",
endTime: "2147483647",
zoneHash: ethers.constants.HashZero,
salt: saltBN.toString(),
conduitKey: ethers.constants.HashZero,
totalOriginalConsiderationItems: 2,
},
counter,
};
}

// Parse r,s,v from signature bytes
function parseSignature(signature) {
const sigBytes = ethers.utils.arrayify(signature);
return {
r: ethers.utils.hexlify(sigBytes.slice(0, 32)),
s: ethers.utils.hexlify(sigBytes.slice(32, 64)),
v: sigBytes[64],
};
}

// Main execution
try {
await loadEthers();

if (!window.ethereum) throw new Error("Please install MetaMask!");

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

// Request MetaMask account access if needed
let accounts = await provider.listAccounts();
if (accounts.length === 0) {
  accounts = await window.ethereum.request({ method: "eth_requestAccounts" });
}
if (!accounts.length) throw new Error("No account connected");

const signer = provider.getSigner();
const connectedAddress = (await signer.getAddress()).toLowerCase();

if (connectedAddress !== OFFERER_ADDRESS) {
  throw new Error(`Connected wallet (${connectedAddress}) does not match offerer address (${OFFERER_ADDRESS})`);
}

const chainId = await signer.getChainId();

// Instantiate Seaport contract minimal ABI for getCounter call
const seaportContract = new ethers.Contract(SEAPORT_ADDRESS, ["function getCounter(address) view returns (uint256)"], provider);
const counterBN = await seaportContract.getCounter(OFFERER_ADDRESS);
const counter = counterBN.toString();

// Generate a unique random 32-byte salt
const saltBN = ethers.BigNumber.from(ethers.utils.randomBytes(32));

// Convert prices to wei strings
const priceMainWei = ethers.utils.parseEther(PRICE_MAIN_ETH).toString();
const priceFeeWei = ethers.utils.parseEther(PRICE_FEE_ETH).toString();

// Build the order to sign
const orderComponents = buildOrderParams(counter, saltBN, priceMainWei, priceFeeWei);

// Recursively lowercase all addresses (important for signature hashing)
const messageToSign = lowercaseAddressesDeep(orderComponents);

// Build domain matching Seaport 1.5 exactly
const domain = {
  name: "Seaport",
  version: "1.5",
  chainId,
  verifyingContract: SEAPORT_ADDRESS,
};

// Sign the typed data (EIP-712)
const signature = await signer._signTypedData(domain, SEAPORT_TYPES, messageToSign);

// Parse r,s,v out of signature
const { r, s, v } = parseSignature(signature);

// Check 's' is in lower half order to prevent malleability (Seaport requires this)
const SECP256K1_N = ethers.BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
const HALF_N = SECP256K1_N.div(2);
const sBN = ethers.BigNumber.from(s);
if (!sBN.lte(HALF_N)) {
  throw new Error("Invalid signature 's' value (must be in lower half order).");
}

// Verify signature locally off-chain
const recoveredAddress = ethers.utils.verifyTypedData(domain, SEAPORT_TYPES, messageToSign, signature);
if (recoveredAddress.toLowerCase() !== connectedAddress) {
  throw new Error(`Signature verification failed: recovered ${recoveredAddress} != ${connectedAddress}`);
}

// Log complete processed info & remind user about next steps
const orderHash = ethers.utils._TypedDataEncoder.hash(domain, SEAPORT_TYPES, messageToSign);
console.log("✔️ Signature verified");
console.log("Signer:", recoveredAddress);
console.log("Signature Components:", { r, s, v });
console.log("Order Hash:", orderHash);
console.log("Order Parameters (clean):", JSON.stringify(cleanBigNumbers(messageToSign.parameters), null, 2));
console.log("Signature (full):", signature);

console.info("Reminder: Ensure NFT is approved for Seaport to transfer BEFORE submitting order on-chain.");
console.info("Next: Use orderComponents and signature in a transaction to Seaport's fulfillOrder or fulfillAdvancedOrder.");

} catch (err) {
console.error(err);
alert(err.message || "Error occurred; check console");
}
})();

THIRD SCRIPT =

(async () => {
// Constants
const SEAPORT_ADDRESS = "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC".toLowerCase();
const OFFERER_ADDRESS = "0xB0077B904F9f5C9009FD2b90d2643Cf9E1632AB4".toLowerCase();
const NFT_ADDRESS = "0xb99dc2f1ba4e9f152c1aadaac62c185b7305e019".toLowerCase();
const OPENSEA_FEE_RECIPIENT = "0x0000a26b00c1F0DF003000390027140000fAa719".toLowerCase();

const TOKEN_ID = "1";
const PRICE_MAIN_ETH = "0.099999";
const PRICE_FEE_ETH = "0.000001";

// EIP-712 Types
const SEAPORT_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" },
],
};

// EIP-712 Domain
const getDomain = (chainId) => ({
name: "Seaport",
version: "1.5",
chainId,
verifyingContract: SEAPORT_ADDRESS,
});

// Loads ethers library dynamically if needed
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.async = true;
script.onload = () => (typeof ethers !== "undefined" ? resolve() : reject(new Error("ethers.js load failed")));
script.onerror = () => reject(new Error("Failed to load ethers.js"));
document.head.appendChild(script);
});
}

// Lowercases all hex 0x40 address strings recursively
function lowercaseAddresses(obj) {
if (Array.isArray(obj)) return obj.map(lowercaseAddresses);
if (obj && typeof obj === "object") {
const res = {};
for (const k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
const v = obj[k];
if (typeof v === "string" && /^0x[a-fA-F0-9]{40}$/.test(v)) {
res[k] = v.toLowerCase();
} else {
res[k] = lowercaseAddresses(v);
}
}
}
return res;
}
return obj;
}

// Cleans BigNumbers for human-readable JSON output
function cleanBigNumbers(obj) {
if (Array.isArray(obj)) return obj.map(cleanBigNumbers);
if (obj && typeof obj === "object") {
const result = {};
for (const k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
const v = obj[k];
if (ethers.BigNumber.isBigNumber(v)) {
result[k] = v.toString();
} else {
result[k] = cleanBigNumbers(v);
}
}
}
return result;
}
return obj;
}

// Builds the order parameters for the listing
function buildOrderParams(counter, saltBN, priceMainWei, priceFeeWei) {
const offer = [
{
itemType: 2, // ERC721
token: NFT_ADDRESS,
identifierOrCriteria: TOKEN_ID,
startAmount: "1",
endAmount: "1",
},
];

const consideration = [
  {
    itemType: 0, // Native ETH
    token: ethers.constants.AddressZero,
    identifierOrCriteria: "0",
    startAmount: priceMainWei,
    endAmount: priceMainWei,
    recipient: OFFERER_ADDRESS,
  },
  {
    itemType: 0, // OpenSea Fee
    token: ethers.constants.AddressZero,
    identifierOrCriteria: "0",
    startAmount: priceFeeWei,
    endAmount: priceFeeWei,
    recipient: OPENSEA_FEE_RECIPIENT,
  },
];

return {
  parameters: {
    offerer: OFFERER_ADDRESS,
    zone: ethers.constants.AddressZero,
    offer,
    consideration,
    orderType: 0, // FULL_OPEN
    startTime: "0",
    endTime: "2147483647", // Far future timestamp (2038)
    zoneHash: ethers.constants.HashZero,
    salt: saltBN.toString(),
    conduitKey: ethers.constants.HashZero,
    totalOriginalConsiderationItems: consideration.length,
  },
  counter,
};

}

// Initialize provider and signer or request user connection
async function initProviderAndSigner() {
if (!window.ethereum) throw new Error("MetaMask is not installed!");

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

let accounts = await provider.listAccounts();
if (accounts.length === 0) {
  accounts = await window.ethereum.request({ method: "eth_requestAccounts" });
  if (!accounts.length) throw new Error("No accounts connected from MetaMask");
}

const signer = provider.getSigner();
const connectedAddress = (await signer.getAddress()).toLowerCase();

return { provider, signer, connectedAddress };

}

// Fetch the current offerer counter from Seaport
async function fetchCounter(offerer, seaportAddress, provider) {
const seaportContract = new ethers.Contract(seaportAddress, ["function getCounter(address) view returns (uint256)"], provider);
const counterBN = await seaportContract.getCounter(offerer);
return counterBN.toString();
}

// Parse signature components r, s, v
function parseSignature(signature) {
const sigBytes = ethers.utils.arrayify(signature);
return {
r: ethers.utils.hexlify(sigBytes.slice(0, 32)),
s: ethers.utils.hexlify(sigBytes.slice(32, 64)),
v: sigBytes[64],
};
}

try {
await loadEthers();

const { provider, signer, connectedAddress } = await initProviderAndSigner();

if (connectedAddress !== OFFERER_ADDRESS) {
  throw new Error(`Connected address (${connectedAddress}) does not match offerer address (${OFFERER_ADDRESS}). Please switch MetaMask account.`);
}

const chainId = await signer.getChainId();

const counter = await fetchCounter(OFFERER_ADDRESS, SEAPORT_ADDRESS, provider);
console.log("Seaport offerer counter:", counter);

const saltBN = ethers.BigNumber.from(ethers.utils.randomBytes(32));
const priceMainWei = ethers.utils.parseEther(PRICE_MAIN_ETH).toString();
const priceFeeWei = ethers.utils.parseEther(PRICE_FEE_ETH).toString();

const orderComponents = buildOrderParams(counter, saltBN, priceMainWei, priceFeeWei);
const messageToSign = lowercaseAddresses(orderComponents);

const domain = getDomain(chainId);

// EIP-712 typed data sign
const signature = await signer._signTypedData(domain, SEAPORT_TYPES, messageToSign);

// Parse signature components
const { r, s, v } = parseSignature(signature);

const recoveredAddr = ethers.utils.verifyTypedData(domain, SEAPORT_TYPES, messageToSign, signature);
if (recoveredAddr.toLowerCase() !== connectedAddress) {
  throw new Error(`Signature verification failed: recovered ${recoveredAddr} != ${connectedAddress}`);
}

console.log("✔️ Signature verified");
console.log({ r, s, v });
console.log("Order hash:", ethers.utils._TypedDataEncoder.hash(domain, SEAPORT_TYPES, messageToSign));
console.log("Order parameters:", JSON.stringify(cleanBigNumbers(messageToSign.parameters), null, 2));
console.log("Signature (full hex):", signature);

// Reminder: NFT owner MUST approve Seaport to transfer NFT before order fulfillment on-chain.
// Next step: Submit signed order to Seaport's fulfillOrder or fulfillAdvancedOrder contract function.

} catch (error) {
console.error(error);
alert(error.message || "An unknown error occurred. See console.");
}
})();