From 8c00ec7eef5df8866c4033c7b92c99c17d400f74 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 21 Apr 2026 15:11:28 +0900 Subject: [PATCH 1/5] [#893] Add finalize script (TWAP, Merkle tree) and MerkleClaim contract Co-Authored-By: Claude Opus 4.6 (1M context) --- contracts/MerkleClaim.sol | 36 +++++ package-lock.json | 129 ++++++++++++++---- package.json | 2 + scripts/airdrop-finalize.ts | 265 ++++++++++++++++++++++++++++++++++++ 4 files changed, 404 insertions(+), 28 deletions(-) create mode 100644 contracts/MerkleClaim.sol create mode 100644 scripts/airdrop-finalize.ts diff --git a/contracts/MerkleClaim.sol b/contracts/MerkleClaim.sol new file mode 100644 index 00000000..0f5416c2 --- /dev/null +++ b/contracts/MerkleClaim.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/** + * @title PLOTAirdrop + * @notice Merkle-tree based airdrop claim contract for PLOT tokens. + * @dev Standard OpenZeppelin MerkleProof-based contract. + * Deploy with the PLOT token address and Merkle root from the finalize script. + */ +contract PLOTAirdrop { + IERC20 public immutable PLOT; + bytes32 public immutable merkleRoot; + mapping(address => bool) public claimed; + + event Claimed(address indexed account, uint256 amount); + + constructor(address _plot, bytes32 _merkleRoot) { + PLOT = IERC20(_plot); + merkleRoot = _merkleRoot; + } + + function claim(uint256 amount, bytes32[] calldata proof) external { + require(!claimed[msg.sender], "Already claimed"); + + bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(msg.sender, amount)))); + require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof"); + + claimed[msg.sender] = true; + require(PLOT.transfer(msg.sender, amount), "Transfer failed"); + + emit Claimed(msg.sender, amount); + } +} diff --git a/package-lock.json b/package-lock.json index 7d1be824..79485311 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@farcaster/miniapp-node": "^0.1.13", "@farcaster/miniapp-sdk": "^0.3.0", "@farcaster/miniapp-wagmi-connector": "^2.0.0", + "@openzeppelin/merkle-tree": "^1.0.8", "@rainbow-me/rainbowkit": "^2.2.10", "@supabase/supabase-js": "^2.99.1", "@tanstack/react-query": "^5.90.21", @@ -3186,6 +3187,64 @@ "@lit-labs/ssr-dom-shim": "^1.5.0" } }, + "node_modules/@metamask/abi-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@metamask/abi-utils/-/abi-utils-2.0.4.tgz", + "integrity": "sha512-StnIgUB75x7a7AgUhiaUZDpCsqGp7VkNnZh2XivXkJ6mPkE83U8ARGQj5MbRis7VJY8BC5V1AbB1fjdh0hupPQ==", + "license": "(Apache-2.0 AND MIT)", + "dependencies": { + "@metamask/superstruct": "^3.1.0", + "@metamask/utils": "^9.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/abi-utils/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/abi-utils/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@metamask/abi-utils/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@metamask/eth-json-rpc-provider": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", @@ -4052,6 +4111,48 @@ "node": ">=12.4.0" } }, + "node_modules/@openzeppelin/merkle-tree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@openzeppelin/merkle-tree/-/merkle-tree-1.0.8.tgz", + "integrity": "sha512-E2c9/Y3vjZXwVvPZKqCKUn7upnvam1P1ZhowJyZVQSkzZm5WhumtaRr+wkUXrZVfkIc7Gfrl7xzabElqDL09ow==", + "license": "MIT", + "dependencies": { + "@metamask/abi-utils": "^2.0.4", + "ethereum-cryptography": "^3.0.0" + } + }, + "node_modules/@openzeppelin/merkle-tree/node_modules/@noble/curves": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz", + "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@openzeppelin/merkle-tree/node_modules/ethereum-cryptography": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-3.2.0.tgz", + "integrity": "sha512-Urr5YVsalH+Jo0sYkTkv1MyI9bLYZwW8BENZCeE1QYaTHETEYx0Nv/SVsWkSqpYrzweg6d8KMY1wTjH/1m/BIg==", + "license": "MIT", + "dependencies": { + "@noble/ciphers": "1.3.0", + "@noble/curves": "1.9.0", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0" + }, + "engines": { + "node": "^14.21.3 || >=16", + "npm": ">=9" + } + }, "node_modules/@paulmillr/qr": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@paulmillr/qr/-/qr-0.2.1.tgz", @@ -10370,20 +10471,6 @@ "ws": "^7.5.1" } }, - "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "extraneous": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -14914,20 +15001,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, - "node_modules/jayson/node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "extraneous": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/jayson/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", diff --git a/package.json b/package.json index 7a46968b..28f75863 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@farcaster/miniapp-node": "^0.1.13", "@farcaster/miniapp-sdk": "^0.3.0", "@farcaster/miniapp-wagmi-connector": "^2.0.0", + "@openzeppelin/merkle-tree": "^1.0.8", "@rainbow-me/rainbowkit": "^2.2.10", "@supabase/supabase-js": "^2.99.1", "@tanstack/react-query": "^5.90.21", @@ -32,6 +33,7 @@ "rehype-sanitize": "^6.0.0", "remark-breaks": "^4.0.0", "remark-gfm": "^4.0.1", + "utf-8-validate": "^6.0.6", "viem": "^2.47.2", "wagmi": "^2.19.5" }, diff --git a/scripts/airdrop-finalize.ts b/scripts/airdrop-finalize.ts new file mode 100644 index 00000000..d31f0d73 --- /dev/null +++ b/scripts/airdrop-finalize.ts @@ -0,0 +1,265 @@ +#!/usr/bin/env npx tsx +/** + * Airdrop finalize script (#893) + * + * 1. Compute 7-day TWAP from pl_daily_prices + * 2. Determine milestone tier + * 3. Calculate per-user distribution + * 4. Generate Merkle tree + proofs + * 5. Output root hash + proof JSON for claim contract deployment + * + * Usage: + * npx tsx scripts/airdrop-finalize.ts + * + * Requires: NEXT_PUBLIC_SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY + */ + +import { createClient } from "@supabase/supabase-js"; +import { parseUnits } from "viem"; +import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; +import { writeFileSync } from "fs"; +import { AIRDROP_CONFIG } from "../lib/airdrop/config"; + +const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL || ""; +const SUPABASE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || ""; + +if (!SUPABASE_URL || !SUPABASE_KEY) { + console.error("Missing SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY"); + process.exit(1); +} + +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +// --------------------------------------------------------------------------- +// Step 1: TWAP Calculation +// --------------------------------------------------------------------------- + +async function computeTwap(): Promise { + const endDate = AIRDROP_CONFIG.CAMPAIGN_END; + const startDate = new Date(endDate.getTime() - 7 * 86400000); + + const { data, error } = await supabase + .from("pl_daily_prices") + .select("mcap_usd") + .gte("recorded_at", startDate.toISOString().slice(0, 10)) + .lte("recorded_at", endDate.toISOString().slice(0, 10)); + + if (error) { + throw new Error(`Failed to fetch daily prices: ${error.message}`); + } + + if (!data || data.length === 0) { + throw new Error("No daily price entries found for TWAP window"); + } + + const sum = data.reduce((acc, row) => acc + Number(row.mcap_usd), 0); + const twap = sum / data.length; + + console.log(`TWAP (${data.length} days): $${twap.toLocaleString()}`); + return twap; +} + +// --------------------------------------------------------------------------- +// Step 2: Milestone Determination +// --------------------------------------------------------------------------- + +function determineMilestone(twapMcap: number): { tier: string; pct: number } { + const { MILESTONES } = AIRDROP_CONFIG; + + if (twapMcap >= MILESTONES.GOLD.mcap) { + return { tier: "Gold", pct: MILESTONES.GOLD.pct }; + } + if (twapMcap >= MILESTONES.SILVER.mcap) { + return { tier: "Silver", pct: MILESTONES.SILVER.pct }; + } + if (twapMcap >= MILESTONES.BRONZE.mcap) { + return { tier: "Bronze", pct: MILESTONES.BRONZE.pct }; + } + return { tier: "None", pct: 0 }; +} + +// --------------------------------------------------------------------------- +// Step 3: Distribution Calculation +// --------------------------------------------------------------------------- + +async function computeDistribution( + milestonePct: number, +): Promise<{ address: string; amount: bigint }[]> { + const { data, error } = await supabase + .from("pl_points") + .select("address, points"); + + if (error) { + throw new Error(`Failed to fetch points: ${error.message}`); + } + + if (!data || data.length === 0) { + console.warn("No points found — distribution is empty"); + return []; + } + + // Aggregate points by address + const pointsByAddress = new Map(); + let totalPoints = 0; + for (const row of data) { + const addr = row.address.toLowerCase(); + pointsByAddress.set(addr, (pointsByAddress.get(addr) ?? 0) + row.points); + totalPoints += row.points; + } + + if (totalPoints === 0) { + console.warn("Total points is zero — distribution is empty"); + return []; + } + + const poolAmount = AIRDROP_CONFIG.POOL_AMOUNT; + const distributablePlot = poolAmount * (milestonePct / 100); + + console.log(`Pool: ${poolAmount} PLOT, Milestone: ${milestonePct}%, Distributable: ${distributablePlot} PLOT`); + console.log(`Participants: ${pointsByAddress.size}, Total points: ${totalPoints}`); + + const distribution: { address: string; amount: bigint }[] = []; + + for (const [addr, pts] of pointsByAddress) { + const share = pts / totalPoints; + const plotAmount = share * distributablePlot; + // Convert to 18-decimal bigint + const amountWei = parseUnits(plotAmount.toFixed(18), 18); + if (amountWei > BigInt(0)) { + distribution.push({ address: addr, amount: amountWei }); + } + } + + // Sort by amount descending for easier verification + distribution.sort((a, b) => (b.amount > a.amount ? 1 : b.amount < a.amount ? -1 : 0)); + + return distribution; +} + +// --------------------------------------------------------------------------- +// Step 4: Merkle Tree Generation +// --------------------------------------------------------------------------- + +function generateMerkleTree(distribution: { address: string; amount: bigint }[]) { + if (distribution.length === 0) { + throw new Error("Cannot generate Merkle tree from empty distribution"); + } + + // StandardMerkleTree expects [address, uint256] leaf encoding + const values = distribution.map((d) => [d.address, d.amount.toString()]); + const tree = StandardMerkleTree.of(values, ["address", "uint256"]); + + console.log(`Merkle root: ${tree.root}`); + + // Build proof map + const proofs: Record = {}; + for (const [i, v] of tree.entries()) { + proofs[v[0] as string] = { + amount: v[1] as string, + proof: tree.getProof(i), + }; + } + + return { root: tree.root, proofs, tree }; +} + +// --------------------------------------------------------------------------- +// Step 5: Store Results +// --------------------------------------------------------------------------- + +async function storeProofs( + proofs: Record, + root: string, + tier: string, + twap: number, +) { + // Write to JSON file for deployment + const output = { + generatedAt: new Date().toISOString(), + twapMcap: twap, + milestone: tier, + merkleRoot: root, + totalRecipients: Object.keys(proofs).length, + proofs, + }; + + const outputPath = "scripts/airdrop-proofs.json"; + writeFileSync(outputPath, JSON.stringify(output, null, 2)); + console.log(`Proofs written to ${outputPath}`); + + // Also store proofs in DB for the claim API + const entries = Object.entries(proofs).map(([address, { amount, proof }]) => ({ + address, + amount, + proof: JSON.stringify(proof), + merkle_root: root, + })); + + // Insert in batches of 100 + for (let i = 0; i < entries.length; i += 100) { + const batch = entries.slice(i, i + 100); + const { error } = await supabase.from("pl_airdrop_proofs").upsert(batch, { + onConflict: "address", + }); + if (error) { + console.error(`Failed to store proofs batch ${i}: ${error.message}`); + } + } + + console.log(`${entries.length} proofs stored in pl_airdrop_proofs`); +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +async function main() { + console.log("=== PLOT Airdrop Finalization ===\n"); + + // Step 1: TWAP + const twap = await computeTwap(); + + // Step 2: Milestone + const { tier, pct } = determineMilestone(twap); + console.log(`\nMilestone: ${tier} (${pct}%)`); + + if (pct === 0) { + console.log("\nNo milestone reached — all PLOT will be burned."); + console.log("Burn address: 0x000000000000000000000000000000000000dEaD"); + console.log(`Burn amount: ${AIRDROP_CONFIG.POOL_AMOUNT} PLOT`); + return; + } + + // Step 3: Distribution + const distribution = await computeDistribution(pct); + if (distribution.length === 0) { + console.log("\nNo eligible participants."); + return; + } + + // Step 4: Merkle tree + const { root, proofs } = generateMerkleTree(distribution); + + // Step 5: Store + await storeProofs(proofs, root, tier, twap); + + // Summary + const burnPct = 100 - pct; + const burnAmount = AIRDROP_CONFIG.POOL_AMOUNT * (burnPct / 100); + console.log("\n=== Summary ==="); + console.log(`TWAP MCap: $${twap.toLocaleString()}`); + console.log(`Milestone: ${tier} (${pct}% distributed)`); + console.log(`Distribute: ${(AIRDROP_CONFIG.POOL_AMOUNT * pct / 100).toLocaleString()} PLOT to ${distribution.length} addresses`); + console.log(`Burn: ${burnAmount.toLocaleString()} PLOT (${burnPct}%)`); + console.log(`Merkle root: ${root}`); + console.log(`\nNext steps:`); + console.log(`1. Deploy MerkleClaim contract with root: ${root}`); + console.log(`2. Unlock PLOT from Mint Club Locker`); + console.log(`3. Transfer ${(AIRDROP_CONFIG.POOL_AMOUNT * pct / 100).toLocaleString()} PLOT to MerkleClaim contract`); + console.log(`4. Send ${burnAmount.toLocaleString()} PLOT to 0x000000000000000000000000000000000000dEaD`); +} + +main().catch((err) => { + console.error("Finalization failed:", err); + process.exit(1); +}); From c9e4cba575b7f1fd0aad0d7d34362535174aa8c3 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 21 Apr 2026 15:13:57 +0900 Subject: [PATCH 2/5] [#893] Fix distribution rounding with largest-remainder method and sync lockfile Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/airdrop-finalize.ts | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/scripts/airdrop-finalize.ts b/scripts/airdrop-finalize.ts index d31f0d73..b57ebf9a 100644 --- a/scripts/airdrop-finalize.ts +++ b/scripts/airdrop-finalize.ts @@ -118,18 +118,35 @@ async function computeDistribution( console.log(`Pool: ${poolAmount} PLOT, Milestone: ${milestonePct}%, Distributable: ${distributablePlot} PLOT`); console.log(`Participants: ${pointsByAddress.size}, Total points: ${totalPoints}`); - const distribution: { address: string; amount: bigint }[] = []; + // Exact total in wei + const totalWei = parseUnits(distributablePlot.toString(), 18); + + // Compute floor amounts and track remainders for largest-remainder allocation + const entries: { address: string; floor: bigint; remainder: number }[] = []; + let floorSum = BigInt(0); for (const [addr, pts] of pointsByAddress) { const share = pts / totalPoints; - const plotAmount = share * distributablePlot; - // Convert to 18-decimal bigint - const amountWei = parseUnits(plotAmount.toFixed(18), 18); - if (amountWei > BigInt(0)) { - distribution.push({ address: addr, amount: amountWei }); - } + const exactWei = Number(totalWei) * share; + const floor = BigInt(Math.floor(exactWei)); + const remainder = exactWei - Math.floor(exactWei); + entries.push({ address: addr, floor, remainder }); + floorSum += floor; } + // Distribute leftover wei to entries with largest remainders + let leftover = totalWei - floorSum; + entries.sort((a, b) => b.remainder - a.remainder); + for (const entry of entries) { + if (leftover <= BigInt(0)) break; + entry.floor += BigInt(1); + leftover -= BigInt(1); + } + + const distribution: { address: string; amount: bigint }[] = entries + .filter((e) => e.floor > BigInt(0)) + .map((e) => ({ address: e.address, amount: e.floor })); + // Sort by amount descending for easier verification distribution.sort((a, b) => (b.amount > a.amount ? 1 : b.amount < a.amount ? -1 : 0)); From 5311c3cda3c49901c2c1fd53e6718bb0c57d66c2 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 21 Apr 2026 15:15:36 +0900 Subject: [PATCH 3/5] [#893] Use pure bigint arithmetic for distribution precision Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/airdrop-finalize.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/scripts/airdrop-finalize.ts b/scripts/airdrop-finalize.ts index b57ebf9a..f875b488 100644 --- a/scripts/airdrop-finalize.ts +++ b/scripts/airdrop-finalize.ts @@ -122,21 +122,24 @@ async function computeDistribution( const totalWei = parseUnits(distributablePlot.toString(), 18); // Compute floor amounts and track remainders for largest-remainder allocation - const entries: { address: string; floor: bigint; remainder: number }[] = []; + // Pure bigint arithmetic to avoid Number precision loss + const totalPointsBig = BigInt(Math.round(totalPoints * 1e6)); + const entries: { address: string; floor: bigint; remainderBig: bigint }[] = []; let floorSum = BigInt(0); for (const [addr, pts] of pointsByAddress) { - const share = pts / totalPoints; - const exactWei = Number(totalWei) * share; - const floor = BigInt(Math.floor(exactWei)); - const remainder = exactWei - Math.floor(exactWei); - entries.push({ address: addr, floor, remainder }); + const ptsBig = BigInt(Math.round(pts * 1e6)); + // floor = (totalWei * pts) / totalPoints (integer division) + const floor = (totalWei * ptsBig) / totalPointsBig; + // remainder = (totalWei * pts) % totalPoints (for sorting) + const remainderBig = (totalWei * ptsBig) % totalPointsBig; + entries.push({ address: addr, floor, remainderBig }); floorSum += floor; } // Distribute leftover wei to entries with largest remainders let leftover = totalWei - floorSum; - entries.sort((a, b) => b.remainder - a.remainder); + entries.sort((a, b) => (b.remainderBig > a.remainderBig ? 1 : b.remainderBig < a.remainderBig ? -1 : 0)); for (const entry of entries) { if (leftover <= BigInt(0)) break; entry.floor += BigInt(1); From d850abbdb4c6dcf50be10d9d004607c5dff42fb7 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 21 Apr 2026 15:19:05 +0900 Subject: [PATCH 4/5] [#893] Remove stale utf-8-validate dep to fix lockfile sync Co-Authored-By: Claude Opus 4.6 (1M context) --- package-lock.json | 2 +- package.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 79485311..22223b8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,6 @@ "rehype-sanitize": "^6.0.0", "remark-breaks": "^4.0.0", "remark-gfm": "^4.0.1", - "utf-8-validate": "^6.0.6", "viem": "^2.47.2", "wagmi": "^2.19.5" }, @@ -20188,6 +20187,7 @@ "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" }, diff --git a/package.json b/package.json index 28f75863..267269fd 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "rehype-sanitize": "^6.0.0", "remark-breaks": "^4.0.0", "remark-gfm": "^4.0.1", - "utf-8-validate": "^6.0.6", "viem": "^2.47.2", "wagmi": "^2.19.5" }, From 7d27fd989b1a6554c86463077620bf40bcf0bb9f Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 21 Apr 2026 15:23:41 +0900 Subject: [PATCH 5/5] [#893] Regenerate package-lock.json to fix npm ci utf-8-validate mismatch Co-Authored-By: Claude Opus 4.6 (1M context) --- package-lock.json | 638 ++++++++++++++++++++++------------------------ 1 file changed, 308 insertions(+), 330 deletions(-) diff --git a/package-lock.json b/package-lock.json index 22223b8e..eed84bfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1045,6 +1045,16 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { "version": "7.29.1", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", @@ -1089,6 +1099,16 @@ "yallist": "^3.0.2" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -2340,6 +2360,78 @@ "node": ">=14" } }, + "node_modules/@ethereumjs/tx/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/tx/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/tx/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/tx/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/tx/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/tx/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, "node_modules/@ethereumjs/util": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", @@ -2354,6 +2446,78 @@ "node": ">=14" } }, + "node_modules/@ethereumjs/util/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, "node_modules/@exodus/bytes": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", @@ -3199,51 +3363,6 @@ "node": ">=16.0.0" } }, - "node_modules/@metamask/abi-utils/node_modules/@metamask/utils": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", - "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", - "license": "ISC", - "dependencies": { - "@ethereumjs/tx": "^4.2.0", - "@metamask/superstruct": "^3.1.0", - "@noble/hashes": "^1.3.1", - "@scure/base": "^1.1.3", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "pony-cause": "^2.1.10", - "semver": "^7.5.4", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/abi-utils/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@metamask/abi-utils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@metamask/eth-json-rpc-provider": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", @@ -3340,18 +3459,6 @@ "node": ">=14.0.0" } }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@metamask/eth-json-rpc-provider/node_modules/superstruct": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", @@ -3361,19 +3468,6 @@ "node": ">=14.0.0" } }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@metamask/json-rpc-engine": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz", @@ -3441,31 +3535,6 @@ "node": ">=16.0.0" } }, - "node_modules/@metamask/json-rpc-engine/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@metamask/json-rpc-engine/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@metamask/json-rpc-middleware-stream": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz", @@ -3501,31 +3570,6 @@ "node": ">=16.0.0" } }, - "node_modules/@metamask/json-rpc-middleware-stream/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@metamask/json-rpc-middleware-stream/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@metamask/object-multiplex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz", @@ -3624,31 +3668,6 @@ "node": ">=16.0.0" } }, - "node_modules/@metamask/providers/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@metamask/providers/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@metamask/rpc-errors": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-7.0.2.tgz", @@ -3662,6 +3681,28 @@ "node": "^18.20 || ^20.17 || >=22" } }, + "node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-11.11.0.tgz", + "integrity": "sha512-0nF2CWjWQr/m0Y2t2lJnBTU1/CZPPTvKvcESLplyWe/tyeb8zFOi/FeneDmaFnML6LYRIGZU6f+xR0jKAIUZfw==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "@types/lodash": "^4.17.20", + "debug": "^4.3.4", + "lodash": "^4.17.21", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": "^18.18 || ^20.14 || >=22" + } + }, "node_modules/@metamask/safe-event-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", @@ -3766,6 +3807,15 @@ "node": ">=6.14.2" } }, + "node_modules/@metamask/sdk-communication-layer/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@metamask/sdk-install-modal-web": { "version": "0.32.1", "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.32.1.tgz", @@ -3798,6 +3848,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "license": "MIT" }, + "node_modules/@metamask/sdk/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@metamask/superstruct": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@metamask/superstruct/-/superstruct-3.2.1.tgz", @@ -3808,9 +3867,9 @@ } }, "node_modules/@metamask/utils": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-11.11.0.tgz", - "integrity": "sha512-0nF2CWjWQr/m0Y2t2lJnBTU1/CZPPTvKvcESLplyWe/tyeb8zFOi/FeneDmaFnML6LYRIGZU6f+xR0jKAIUZfw==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", "license": "ISC", "dependencies": { "@ethereumjs/tx": "^4.2.0", @@ -3818,40 +3877,13 @@ "@noble/hashes": "^1.3.1", "@scure/base": "^1.1.3", "@types/debug": "^4.1.7", - "@types/lodash": "^4.17.20", "debug": "^4.3.4", - "lodash": "^4.17.21", "pony-cause": "^2.1.10", "semver": "^7.5.4", "uuid": "^9.0.1" }, "engines": { - "node": "^18.18 || ^20.14 || >=22" - } - }, - "node_modules/@metamask/utils/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@metamask/utils/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=16.0.0" } }, "node_modules/@napi-rs/wasm-runtime": { @@ -4120,38 +4152,6 @@ "ethereum-cryptography": "^3.0.0" } }, - "node_modules/@openzeppelin/merkle-tree/node_modules/@noble/curves": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz", - "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.8.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@openzeppelin/merkle-tree/node_modules/ethereum-cryptography": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-3.2.0.tgz", - "integrity": "sha512-Urr5YVsalH+Jo0sYkTkv1MyI9bLYZwW8BENZCeE1QYaTHETEYx0Nv/SVsWkSqpYrzweg6d8KMY1wTjH/1m/BIg==", - "license": "MIT", - "dependencies": { - "@noble/ciphers": "1.3.0", - "@noble/curves": "1.9.0", - "@noble/hashes": "1.8.0", - "@scure/bip32": "1.7.0", - "@scure/bip39": "1.6.0" - }, - "engines": { - "node": "^14.21.3 || >=16", - "npm": ">=9" - } - }, "node_modules/@paulmillr/qr": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@paulmillr/qr/-/qr-0.2.1.tgz", @@ -9678,19 +9678,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/utils": { "version": "8.59.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.0.tgz", @@ -10470,6 +10457,20 @@ "ws": "^7.5.1" } }, + "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "extraneous": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -13060,6 +13061,16 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", @@ -13153,6 +13164,16 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -13332,18 +13353,6 @@ "node": ">=14.0.0" } }, - "node_modules/eth-block-tracker/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/eth-block-tracker/node_modules/superstruct": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", @@ -13401,72 +13410,32 @@ } }, "node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/ethereum-cryptography/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-3.2.0.tgz", + "integrity": "sha512-Urr5YVsalH+Jo0sYkTkv1MyI9bLYZwW8BENZCeE1QYaTHETEYx0Nv/SVsWkSqpYrzweg6d8KMY1wTjH/1m/BIg==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "@noble/ciphers": "1.3.0", + "@noble/curves": "1.9.0", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethereum-cryptography/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" + "node": "^14.21.3 || >=16", + "npm": ">=9" } }, - "node_modules/ethereum-cryptography/node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "node_modules/ethereum-cryptography/node_modules/@noble/curves": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz", + "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==", "license": "MIT", "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" + "@noble/hashes": "1.8.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethereum-cryptography/node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -14496,19 +14465,6 @@ "semver": "^7.7.1" } }, - "node_modules/is-bun-module/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -15000,6 +14956,29 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, + "node_modules/jayson/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "extraneous": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/jayson/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/jayson/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -16906,6 +16885,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -18609,13 +18598,15 @@ "license": "MIT" }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/set-blocking": { @@ -18737,19 +18728,6 @@ "@img/sharp-win32-x64": "0.34.5" } }, - "node_modules/sharp/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -20215,9 +20193,13 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -20287,9 +20269,9 @@ } }, "node_modules/viem": { - "version": "2.48.1", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.48.1.tgz", - "integrity": "sha512-GJC3gKV1Hngeo1IB9YanJKHH2pcmoqDymyPxddmzDtG8boXA7eFw8qdnn1PSaToJ93f3LpOZPlLLJ9beAF/Lzg==", + "version": "2.48.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.48.2.tgz", + "integrity": "sha512-qRJlttIe90n1+u90xr6NhGxqA519nPpGnktFeyufT6d7t7Y2mt8tf8+mEHfN1BA945R507arwr1CL34OR8gEug==", "funding": [ { "type": "github", @@ -21146,8 +21128,6 @@ }, "packages/cli/node_modules/chokidar": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { @@ -21169,8 +21149,6 @@ }, "packages/cli/node_modules/readdirp": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", "engines": {