From 0b3bfe342ba468838501258362888a1930f3727c Mon Sep 17 00:00:00 2001 From: 49659410+tx0c <> Date: Wed, 27 Dec 2023 04:56:37 +0000 Subject: [PATCH] feat(qf-funding-score): to calculate score for each project from past donations for thematters/developer-resource#350 & #103 --- bin/qf-calculate.ts | 19 + handlers/qf-calculate.ts | 53 ++ lib/bigint-math.ts | 77 +++ lib/polygonscan.ts | 30 + lib/qf-calculate.ts | 934 ++++++++++++++++++++++++++++++ package-lock.json | 1188 ++++++++++++++++++++++++++++++++++---- package.json | 10 +- tsconfig.json | 2 +- 8 files changed, 2199 insertions(+), 114 deletions(-) create mode 100644 bin/qf-calculate.ts create mode 100644 handlers/qf-calculate.ts create mode 100644 lib/bigint-math.ts create mode 100644 lib/polygonscan.ts create mode 100644 lib/qf-calculate.ts diff --git a/bin/qf-calculate.ts b/bin/qf-calculate.ts new file mode 100644 index 0000000..a6a9237 --- /dev/null +++ b/bin/qf-calculate.ts @@ -0,0 +1,19 @@ +#!/usr/bin/env -S node --trace-warnings --loader ts-node/esm + +import { calculateQFScore } from "../lib/qf-calculate.js"; + +async function main() { + const args = process.argv.slice(2); + const amount = BigInt(+(args?.[0] || 500) * 1e6); + const fromTime = args?.[1] || "2023-12-31"; + const toTime = args?.[2] || "2024-12-31T23:59:59.999Z"; + + const res = await calculateQFScore({ + fromTime, // : "2023-12-31", + toTime, // : "2024-12-31T23:59:59.999Z", + amount, + }); + console.log(new Date(), "res:", res); +} + +main().catch((err) => console.error(new Date(), "ERROR:", err)); diff --git a/handlers/qf-calculate.ts b/handlers/qf-calculate.ts new file mode 100644 index 0000000..eb9eeb2 --- /dev/null +++ b/handlers/qf-calculate.ts @@ -0,0 +1,53 @@ +import { Context, APIGatewayProxyResult, APIGatewayEvent } from "aws-lambda"; +import { calculateQFScore } from "../lib/qf-calculate.js"; + +export const handler = async ( + event: APIGatewayEvent & { + fromTime?: string; + toTime?: string; + amount?: string; + forceRun?: boolean; + }, + context: Context +): Promise => { + console.log(`Event: ${JSON.stringify(event, null, 2)}`); + console.log(`Context: ${JSON.stringify(context, null, 2)}`); + + const { method, path } = ((event?.requestContext as any)?.http as any) || {}; + const forceRun = !!("forceRun" in (event?.queryStringParameters as any)); + const { accept, origin }: { accept?: string; origin?: string } = + event?.headers || {}; + if ( + !( + event?.forceRun || + (path === "/qf-calculator" && accept?.includes("application/json")) + ) + ) { + return { + statusCode: 400, + body: JSON.stringify({ + error: + "input error, call with POST /qf-calculator with accept: application/json", + }), + }; + } + + const { fromTime, toTime, amount } = event?.forceRun + ? event + : event?.queryStringParameters || {}; + + const { root, gist_url } = await calculateQFScore({ + fromTime, + toTime, + amount: BigInt(+(amount || 500) * 1e6), + }); + + return { + statusCode: 200, + body: JSON.stringify({ + message: "done.", + root, // tree + gist_url, + }), + }; +}; diff --git a/lib/bigint-math.ts b/lib/bigint-math.ts new file mode 100644 index 0000000..c1fa1f1 --- /dev/null +++ b/lib/bigint-math.ts @@ -0,0 +1,77 @@ +// https://golb.hplar.ch/2018/09/javascript-bigint.html +export class BigIntMath { + static max(...values: Array) { + if (values.length === 0) { + return null; + } + + if (values.length === 1) { + return values[0]; + } + + let max = values[0]; + for (let i = 1; i < values.length; i++) { + if (values[i] > max) { + max = values[i]; + } + } + return max; + } + + static min(...values: Array) { + if (values.length === 0) { + return null; + } + + if (values.length === 1) { + return values[0]; + } + + let min = values[0]; + for (let i = 1; i < values.length; i++) { + if (values[i] < min) { + min = values[i]; + } + } + return min; + } + + static sign(value: bigint | number) { + if (value > 0n) { + return 1n; + } + if (value < 0n) { + return -1n; + } + return 0n; + } + + static abs(value: bigint | number) { + if (this.sign(value) === -1n) { + return -value; + } + return value; + } + + // https://stackoverflow.com/questions/53683995/javascript-big-integer-square-root/58863398#58863398 + static rootNth(value: bigint, k: bigint = 2n) { + if (value < 0n) { + throw "negative number is not supported"; + } + + let o = 0n; + let x = value; + let limit = 100; + + while (x ** k !== k && x !== o && --limit) { + o = x; + x = ((k - 1n) * x + value / x ** (k - 1n)) / k; + } + + return x; + } + + static sqrt(value: bigint) { + return BigIntMath.rootNth(value); + } +} diff --git a/lib/polygonscan.ts b/lib/polygonscan.ts new file mode 100644 index 0000000..98a91c0 --- /dev/null +++ b/lib/polygonscan.ts @@ -0,0 +1,30 @@ +const PolygonScanAPIKEY = process.env.MATTERS_POLYGONSCANAPIKEY || ""; +// https://api.polygonscan.com/api?module=block&action=getblocknobytime×tamp=1704184772&closest=before&apikey={key} + +export class PolygonScanAPI { + static async getBlockFromTimestamp({ + timestamp, + closest, + }: { + timestamp: number; // Date | string | number; + closest: "before" | "after"; + }) { + const nowTs = Math.floor(+Date.now() / 1e3); + const params = new URLSearchParams({ + module: "block", + action: "getblocknobytime", + timestamp: Math.min(nowTs, timestamp).toString(), + closest: timestamp >= nowTs ? "before" : closest, // override to before if pass now or future timestamp + apikey: PolygonScanAPIKEY, + }); + const u = new URL(`https://api.polygonscan.com/api?${params}`); + console.log(new Date(), `get with:`, { params, u }); + const res = await fetch(u).then((res) => res.json()); + + // {"status":"1","message":"OK","result":"51846093"} + if (!(res?.status === "1" && res?.message === "OK")) + console.error(new Date(), `non-ok result:`, res); + + return BigInt(res?.result); + } +} diff --git a/lib/qf-calculate.ts b/lib/qf-calculate.ts new file mode 100644 index 0000000..960eb52 --- /dev/null +++ b/lib/qf-calculate.ts @@ -0,0 +1,934 @@ +// import fs from "fs"; + +import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; +import { createPublicClient, http, fallback, getContract } from "viem"; +import { polygon } from "viem/chains"; + +import * as d3 from "d3-array"; + +import { sqlRO } from "../lib/db.js"; +import { BigIntMath } from "../lib/bigint-math.js"; +import { PolygonScanAPI } from "../lib/polygonscan.js"; + +const MATTERS_ALCHEMY_KEY = process.env.MATTERS_ALCHEMY_KEY || ""; +const GITHUB_TOKEN = process.env.GITHUB_TOKEN || ""; + +const alchemy = http( + `https://polygon-mainnet.g.alchemy.com/v2/${MATTERS_ALCHEMY_KEY}` +); + +const publicClient = createPublicClient({ + chain: polygon, + transport: fallback([ + alchemy, // infura + ]), // http(), +}); + +// const blockNumber = await publicClient.getBlockNumber(); +// console.log(new Date(), "blockNumber:", blockNumber); + +const curationContractAddress = "0x5edebbdae7b5c79a69aacf7873796bb1ec664db8"; +const abi = [ + { inputs: [], name: "InvalidURI", type: "error" }, + { inputs: [], name: "SelfCuration", type: "error" }, + { inputs: [], name: "TransferFailed", type: "error" }, + { inputs: [], name: "ZeroAddress", type: "error" }, + { inputs: [], name: "ZeroAmount", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: true, + internalType: "contract IERC20", + name: "token", + type: "address", + }, + { indexed: false, internalType: "string", name: "uri", type: "string" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Curation", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { indexed: false, internalType: "string", name: "uri", type: "string" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Curation", + type: "event", + }, + { + inputs: [ + { internalType: "address", name: "to_", type: "address" }, + { internalType: "contract IERC20", name: "token_", type: "address" }, + { internalType: "uint256", name: "amount_", type: "uint256" }, + { internalType: "string", name: "uri_", type: "string" }, + ], + name: "curate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to_", type: "address" }, + { internalType: "string", name: "uri_", type: "string" }, + ], + name: "curate", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId_", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, +] as const; + +export const POINTS = { + mattersFollowers: 4.0, // need numFollowers >= 5 + mattersAgeBefore: 3.0, // need userRegistraiton time < period beginning + mattersBadges: 6.0, // need hold badges >= 1 + mattersTravloggHolders: 6.0, // need hold TravloggNFT >= 1 + + gitcoinActivities: 3.0, // gitcoin donations >= 1 + + socialTwitter: 3.0, + socialGoogle: 1.0, + + ethENS: 2.0, + ethNFTs: 1.0, // any other NFTs on ETH mainnet +} as const; + +export async function calculateQFScore({ + // between = ["2023-12-01", "2023-12-31T23:59:59.999Z"], + fromTime, + toTime, + amount = 500_000_000n, // 500 USDT +}: { + // between: string[]; + fromTime?: string; + toTime?: string; + amount?: bigint; +}) { + const started = new Date(); + const fromTimestamp = Date.parse(fromTime!); + let toTimestamp = Date.parse(toTime!); // , +started); + if (toTimestamp > +started) { + toTimestamp = +started; + toTime = started.toISOString(); + } + + const [fromBlock, toBlock] = await Promise.all( + // between.map(time => + [ + PolygonScanAPI.getBlockFromTimestamp({ + timestamp: Math.floor(fromTimestamp / 1e3), + closest: "before", + }), + PolygonScanAPI.getBlockFromTimestamp({ + timestamp: Math.ceil(toTimestamp / 1e3), + closest: toTimestamp >= +started ? "before" : "after", + }), + ] + ); + console.log(new Date(), `find out events between:`, { + fromTime, + toTime, + fromBlock, + toBlock, + }); + + const logs = (await publicClient.getContractEvents({ + address: curationContractAddress, + abi, + eventName: "Curation", + // fromBlock: 50735950n, // 34564355n is the creation block of the contract at Oct-20-2022 04:52:52 AM +UTC; + fromBlock, // : 34000000n, + // toBlock: 51484855n, + toBlock, + })) as any[]; + logs.reverse(); // get from latest to earliest + + const seqs = logs.map( + ({ + blockNumber, + transactionHash, + args: { from, to, token, uri, amount }, + eventName, + }) => ({ + blockNumber, + transactionHash, + eventName, + from, + to, + token, + uri, + amount, + // dataHash: uri?.match(/^ipfs:\/\/(Qm[A-Za-z0-9]{44})$/)?.[1] || null, + dataHash: uri?.match(/^ipfs:\/\/(Qm[A-Za-z0-9]{44})$/)?.[1], + // uri?.startsWith("ipfs://") ? uri.substring(7) : null, + }) + ); + + // console.log("contract logs: %o", logs); + const stats = { + blockNumber: new Set(), + transactionHash: new Set(), + fromAddresses: new Set(), + toAddresses: new Set(), + allAddresses: new Set(), + token: new Set(), + uri: new Set(), + amount: [] as bigint[], + eventName: new Set(), + }; + logs.forEach((log: any) => { + stats.blockNumber.add(log.blockNumber); + stats.transactionHash.add(log.transactionHash); + stats.fromAddresses.add(log.args.from); + stats.toAddresses.add(log.args.to); + stats.allAddresses.add(log.args.from); + stats.allAddresses.add(log.args.to); + stats.token.add(log.args.token); + stats.uri.add(log.args.uri); + stats.amount.push(log.args.amount); + stats.eventName.add(log.eventName); + }); + stats.amount.sort( + ascending //(a, b) => + // https://github.com/d3/d3-array/blob/main/src/ascending.js + // a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN + ); + + const statsAmount = { + length: stats.amount.length, + min: stats.amount[0], + max: stats.amount[stats.amount.length - 1], + // d3.sum(stats.amount), // stats.amount.reduce((acc, amount) => acc + amount, 0n), + sum: stats.amount.reduce((acc, amount) => acc + amount), + // d3.median(stats.amount), + median: + stats.amount.length % 2 === 1 + ? stats.amount[stats.amount.length >>> 1] + : (stats.amount[stats.amount.length >>> 1] + + stats.amount[(stats.amount.length >>> 1) - 1]) >> + 1n, + // p75: stats.amount.length % 4 === 0 ? ? stats.amount[(stats.amount.length >>> 2) *3] + quantiles: [ + stats.amount[0], + quantileSorted(stats.amount, "p25"), + quantileSorted(stats.amount, "p50"), + quantileSorted(stats.amount, "p75"), + stats.amount[stats.amount.length - 1], + ], + }; + const ipfsArticleHashes = + await sqlRO`-- get de-duplicated donation records from darft data_hash +SELECT article.id ::int, article.title, article.summary, article.created_at, article.data_hash, draft.data_hash AS draft_data_hash, + lower(author.eth_address) AS eth_address, + concat('https://matters.town/@', user_name, '/', article.id, '-', article.slug) AS url +FROM public.draft LEFT JOIN public.article ON article_id=article.id +LEFT JOIN public.user author ON article.author_id=author.id +WHERE draft.data_hash =ANY(${Array.from( + new Set(seqs.map(({ dataHash }) => dataHash).filter(Boolean)) + )}) +ORDER BY article.id DESC ; `; + const dataHashMappings = new Map( + ipfsArticleHashes.map(({ draftDataHash, ...rest }) => [draftDataHash, rest]) + ); + + const usdtDonationsStats = ( + await sqlRO`--get stats of all USDT transactions; +SELECT COUNT(*) ::int AS num_transactions, + COUNT(DISTINCT sender_id) ::int AS num_senders, + COUNT(DISTINCT recipient_id) ::int AS num_recipients, + COUNT(DISTINCT target_id) ::int AS num_targets, + jsonb_build_object( + 'min', MIN(amount), + 'max', MAX(amount), + 'sum', SUM(amount), + 'avg', ROUND(AVG(amount), 6), + 'p25', percentile_cont(0.25) within group (order by amount asc), + 'p50', percentile_cont(0.5) within group (order by amount asc), + 'p75', percentile_cont(0.75) within group (order by amount asc) + ) AS amount_stats +FROM public.transaction +WHERE purpose='donation' AND state='succeeded' + AND currency='USDT' + AND target_type=4 -- for articles; + AND created_at BETWEEN ${fromTime!} AND ${toTime!} ;` + )?.[0]; + + const statsSummary = { + blockNumber: stats.blockNumber.size, + transactionHash: stats.transactionHash.size, + fromAddresses: stats.fromAddresses.size, + toAddresses: stats.toAddresses.size, + allAddresses: stats.allAddresses.size, + token: stats.token.size === 1 ? Array.from(stats.token) : stats.token.size, + eventName: + stats.eventName.size === 1 + ? Array.from(stats.eventName) + : stats.eventName.size, + uri: stats.uri.size, + amount: { + ...statsAmount, + sum_usdt: +(Number(statsAmount.sum) / 1e6).toFixed(6), + avg_usdt: +(Number(statsAmount.sum) / 1e6 / stats.amount.length).toFixed( + 6 + ), + }, + }; + console.log("stats:", statsSummary, { + ipfsArticleHashes: ipfsArticleHashes.length, + ...usdtDonationsStats, + }); + + const gist: any = { + description: `quadratic-funding score for MattersCuration contract`, + public: false, + files: { + "README.md": { + content: `During MattersCuration contract runtime between ...`, + }, + }, + }; + + // output senders.tsv + const sendersOut = new Map(); + + { + const aggPerFromAddress = d3.rollup( + seqs, + (g) => ({ + amounts: g.map((d) => d.amount).sort(d3.ascending), + latestBlockNumber: BigIntMath.max(...g.map((d) => d.blockNumber)), + // number_donations + number_contributions: g.length, + // .sort( d3.ascending // (a, b) => a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN , // https://github.com/d3/d3-array/blob/main/src/ascending.js + sum: g.reduce((acc, b) => acc + b.amount, 0n), + }), + (d) => d.from.toLowerCase() // lower + // (d) => d.uri, + ); + console.log(new Date(), "aggPerFromAddress:", aggPerFromAddress); + const addresses: string[] = Array.from(aggPerFromAddress.keys()); + + const senders = await sqlRO`-- get all sender's social +SELECT sender.user_name, display_name, to_jsonb(sag.*) AS sag, to_jsonb(sat.*) AS sat, + lower(sender.eth_address) AS eth_address, + sender.created_at AS user_created_at, + num_articles, earliest_article_published_at, ub.count AS num_badges, num_followers, + last_donat.created_at AS earliest_donated_at, + last_donat.title, all_donates.titles, last_donat.target_url -- , last_donat.created_at +FROM public.user sender +LEFT JOIN social_account sag ON sag.user_id=sender.id AND sag.type='Google' +LEFT JOIN social_account sat ON sat.user_id=sender.id AND sag.type='Twitter' +LEFT JOIN ( + SELECT author_id, COUNT(*) ::int AS num_articles, MIN(created_at) AS earliest_article_published_at + FROM public.article + GROUP BY 1 +) articles ON articles.author_id=sender.id +LEFT JOIN ( + SELECT DISTINCT ON (sender_id) sender_id ::int, tr.created_at, title, + concat('https://matters.town/@', '/', target_id, '-', slug) AS target_url + FROM transaction tr + LEFT JOIN public.article ON target_id=article.id AND target_type=4 + WHERE tr.purpose='donation' AND tr.state='succeeded' + AND tr.currency='USDT' + -- AND tr.created_at >= $ {fromTime!} + AND tr.created_at BETWEEN ${fromTime!} AND ${toTime!} + -- AND target_type=4 -- AND target_id IN ( SELECT id FROM all_applicant_articles ) + ORDER BY sender_id, tr.created_at ASC +) last_donat ON last_donat.sender_id=sender.id +LEFT JOIN ( + SELECT sender_id ::int, ARRAY_AGG(DISTINCT concat(article.id, '-', article.slug)) AS titles + -- concat('https://matters.town/@', '/', target_id, '-', slug) AS target_url + FROM ( + SELECT DISTINCT ON (sender_id, target_id) sender_id, target_id, tr.created_at + FROM transaction tr + WHERE tr.purpose='donation' AND tr.state='succeeded' + AND tr.currency='USDT' + AND tr.created_at BETWEEN ${fromTime!} AND ${toTime!} + AND target_type=4 -- AND target_id IN ( SELECT id FROM all_applicant_articles ) + ORDER BY sender_id, target_id, created_at ASC + ) t + LEFT JOIN public.article ON target_id=article.id + GROUP BY 1 + -- ORDER BY sender_id, tr.created_at ASC +) all_donates ON all_donates.sender_id=sender.id +LEFT JOIN ( + SELECT target_id, COUNT(*) ::int AS num_followers + FROM public.action_user + GROUP BY 1 +) actions ON actions.target_id=sender.id +LEFT JOIN ( + SELECT user_id, COUNT(*) ::int + FROM public.user_badge + WHERE enabled + GROUP BY 1 +) ub ON ub.user_id=sender.id +-- LEFT JOIN public.user_badge ub ON ub.user_id=sender.id AND ub.type='seed' AND ub.enabled +WHERE lower(sender.eth_address) =ANY(${addresses!}) +-- ORDER BY sender.id DESC ;`; + + const sendersMap = new Map(senders.map((u) => [u.ethAddress, u])); + + aggPerFromAddress.forEach((v, k) => { + const obj = { + userName: sendersMap.get(k)?.userName, + displayName: sendersMap.get(k)?.displayName, + ethAddress: k, + trustPoints: 0.0, + count: v.number_contributions, + sum: v.sum, + GoogleAccount: !!sendersMap.get(k)?.sag?.email, // check is valid + TwitterAccount: !!sendersMap.get(k)?.sat?.userName, // check twitter history length; + numBadges: sendersMap.get(k)?.numBadges, + numArticles: sendersMap.get(k)?.numArticles, + numFollowers: sendersMap.get(k)?.numFollowers, + isRegisteredBefore: sendersMap.get(k)?.userCreatedAt < fromTimestamp, + userCreatedAt: sendersMap.get(k)?.userCreatedAt, + earliestArticlePublishedAt: + sendersMap.get(k)?.earliestArticlePublishedAt, + earliestDonatedAt: sendersMap.get(k)?.earliestDonatedAt?.toISOString(), + // "title (earliest)", + titles: + // "url", + // csvEscape(sendersMap.get(k)?.title), + sendersMap.get(k)?.titles, // Array.isArray(sendersMap.get(k)?.titles) ? JSON.stringify(sendersMap.get(k)?.titles) : null, + // sendersMap.get(k)?.targetUrl, + amounts: v.amounts, + trustExpr: "", + }; + const points = [ + obj.numFollowers >= 5 ? POINTS.mattersFollowers : 0.0, // mattersFollowers: 4.0, // need numFollowers >= 5 + obj.isRegisteredBefore ? POINTS.mattersAgeBefore : 0.0, // need userRegistraiton time < period beginning + obj.numBadges >= 1 ? POINTS.mattersBadges : 0.0, // need hold badges >= 1 + // mattersTravloggHolders: 6.0, // need hold TravloggNFT >= 1 + + // gitcoinActivities: 3.0, // gitcoin donations >= 1 + + obj.GoogleAccount ? POINTS.socialGoogle : 0.0, + obj.TwitterAccount ? POINTS.socialTwitter : 0.0, + // ethENS: 2.0, + // ethNFTs: 1.0, // any other NFTs on ETH mainnet + ]; + obj.trustPoints = d3.sum(points); + obj.trustExpr = `(${points.join(" + ")})`; + sendersOut.set(k, obj); + // if (!headers) headers = Object.keys(obj); + }); + + if (sendersOut.size >= 1) { + const [first] = sendersOut.values(); + const headers = Object.keys(first); + const bufs = []; + // const headers = Object.keys(values[0]); + bufs.push(headers.join("\t")); + + sendersOut.forEach((row, k) => { + bufs.push( + headers + .map((k) => csvEscape(row[k], k)) + /* [ + sendersMap.get(k)?.userName, + sendersMap.get(k)?.displayName, + k, + v.number_contributions, + v.sum, + sendersMap.get(k)?.sag?.email, + sendersMap.get(k)?.sat?.userName, + sendersMap.get(k)?.numBadges, + sendersMap.get(k)?.numArticles, + sendersMap.get(k)?.numFollowers, + sendersMap.get(k)?.userCreatedAt < fromTimestamp ? "Y" : "", + sendersMap.get(k)?.userCreatedAt?.toISOString(), + sendersMap.get(k)?.earliestArticlePublishedAt?.toISOString(), + sendersMap.get(k)?.earliestDonatedAt?.toISOString(), + // csvEscape(sendersMap.get(k)?.title), + sendersMap.get(k)?.titles, // Array.isArray(sendersMap.get(k)?.titles) ? JSON.stringify(sendersMap.get(k)?.titles) : null, + // sendersMap.get(k)?.targetUrl, + v.amounts, + ] */ .join("\t") + // .trimEnd(), + ); + }); + const sendersContent = (gist.files[`senders.tsv`] = { + content: bufs.join("\n"), + }); + console.log(sendersContent.content); + } + } + + const aggPerProj = d3.rollup( + seqs, + (g) => ({ + amounts: g.map((d) => d.amount).sort(ascending), + to: Array.from(new Set(g.map((d) => d.to))), + latestBlockNumber: BigIntMath.max( + ...g.map((d) => d.blockNumber) + ) as bigint, + // number_donations + number_contributions: g.length, + number_contribution_addresses: new Set(g.map((d) => d.from)).size, + // .sort( d3.ascending // (a, b) => a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN , // https://github.com/d3/d3-array/blob/main/src/ascending.js + sum: g.reduce((acc, b) => acc + b.amount, 0n), + latestTimestamp: undefined as Date | undefined, + }), // d3.sum(g, (d) => d.amount), + (d) => (dataHashMappings.get(d.dataHash)?.dataHash ?? d.dataHash) || d.uri // d.dataHash || d.uri + ); + for (const [proj, data] of aggPerProj.entries()) { + if (!data.latestBlockNumber) continue; + const block = await publicClient.getBlock({ + blockNumber: data.latestBlockNumber, + }); + // console.log(`get block:`, data.latestBlockNumber, block); + data.latestTimestamp = new Date(Number(block.timestamp) * 1e3); + } + console.log("for seqs contrib:", aggPerProj); + + const aggPerProjFrom = d3.rollup( + seqs.filter( + // filter out non-ipfs url + ({ from, dataHash }) => + dataHash && sendersOut.get(from.toLowerCase()).trustPoints > 0 // && from address is not too low trust-score + ), + (g) => ({ + amounts: g.map((d) => d.amount), + sum: g.reduce((acc, b) => acc + b.amount, 0n), // d3.sum(g, (d) => d.amount), + }), + (d) => + // dataHashMappings.has(d.dataHash) + (dataHashMappings.get(d.dataHash)?.dataHash ?? d.dataHash) || d.uri, + (d) => d.from + ); + + console.log("for seqs contrib:", aggPerProjFrom); + const pair_totals = get_totals_by_pair(aggPerProjFrom); + console.log("for seqs contrib pairs:", pair_totals); + + console.log( + "for seqs contrib pairs JSON:", + JSON.stringify( + Object.fromEntries( + Array.from(pair_totals.entries()).map(([k, m]) => [ + k, + Object.fromEntries(m.entries()), + ]) + ), + replacer, + 2 + ) + ); + + // const totAmount = BigInt(amount ?? 500_000_000n); + const clrs = calculate_clr(aggPerProjFrom, pair_totals, amount); + console.log("for seqs contrib pairs clrs:", clrs); + + // (1) + // [cid, address, amount] + const treeValues = clrs + .filter( + (clr) => clr.clr_amount_orig > 0n && clr.author_eth?.length === 42 // check it looks like a ethAddress + ) + .map(({ id, author_eth, clr_amount_orig }) => [ + id, + // to_address?.[0] || author_eth, + aggPerProj.get(id)?.to?.[0] || + dataHashMappings.get(id)?.ethAddress || + author_eth, + clr_amount_orig.toString(), + ]); + + // (2) + const tree = StandardMerkleTree.of(treeValues, [ + "string", + "address", + "uint256", + ]); + + // (3) + console.log("Merkle Root:", tree.root); + + gist.files[ + "README.md" + ].content = `During MattersCuration contract runtime between \`${fromTime}\` ~ \`${toTime}\`, +\`\`\`json +from Polygon onChain: ${JSON.stringify( + statsSummary, // replacer + (_, v) => (typeof v === "bigint" ? +Number(v) : v), + 2 + )} +from MattersDB: ${JSON.stringify( + { + ipfsArticleHashes: ipfsArticleHashes.length, + ...usdtDonationsStats, + }, + null, + 2 + )} +\`\`\` + +Merkle Tree Root: \`${tree.root}\` + +this is analyzing results with [Quadratic Funding score calcuation with Pairwise Mechanism](https://github.com/gitcoinco/quadratic-funding?tab=readme-ov-file#implementation-upgrade-the-pairwise-mechanism)`; + + // output distrib + { + const values = [] as any[]; + const clrsMap = new Map(clrs.map((r) => [r.id, r])); + aggPerProj.forEach((v, proj) => { + const { + // number_contributions, + // number_contribution_addresses, + // contribution_amount, // clr_amount, + clr_amount_pairw, + clr_percent_pairw, + clr_amount_orig, + clr_percent_orig, + // url, created_at, author_eth, // tot, _q_summed, + } = clrsMap.get(proj) || {}; + values.push({ + id: proj, + title: dataHashMappings.get(proj)?.title, + number_contributions: aggPerProj.get(proj)?.number_contributions, + number_contribution_addresses: + aggPerProj.get(proj)?.number_contribution_addresses, + contribution_amount: aggPerProj.get(proj)?.sum, + clr_amount_pairw, + clr_percent_pairw, + clr_amount_orig, + clr_percent_orig, + url: dataHashMappings.get(proj)?.url || proj, + created_at: dataHashMappings.get(proj)?.createdAt, + author_eth: dataHashMappings.get(proj)?.ethAddress, + to_address: aggPerProj.get(proj)?.to, + // created_at, + // author_eth, // tot, _q_summed, + amounts: aggPerProj.get(proj)?.amounts, + }); + }); + const headers = Object.keys(values[0]); + const bufs = []; + bufs.push( + headers.join("\t") + // "id title number_contributions contribution_amount_USDT clr_amount_USDT url created_at author_eth" + ); + values.forEach((row: any) => + bufs.push(headers.map((k) => csvEscape(row[k], k)).join("\t")) + ); + // gist.files["distrib.tsv"] = { content: bufs.join("\n") }; + const distrib = (gist.files[`distrib.tsv`] = { + content: bufs.join("\n"), + }); + console.log(distrib.content); + const distribJSON = (gist.files[`distrib.json`] = { + content: + "[ " + + values + .filter(({ clr_amount_orig }) => clr_amount_orig > 0n) + .map( + ({ + id, + title, + clr_amount_orig, + url, + created_at, + author_eth, + to_address, + }) => + JSON.stringify( + { + id, + title, + clr_amount: clr_amount_orig, + url, + created_at, + eth_address: + aggPerProj.get(id)?.to?.[0] || + dataHashMappings.get(id)?.ethAddress || + author_eth, + }, + replacer + ) + ) + .join(",\n") + + " ]", + }); + } + + // (4) // write out to somewhere S3 bucket? + // fs.writeFileSync("out/tree.json", JSON.stringify(tree.dump(), null, 2)); + // console.log("Merkle-Tree Dump:", JSON.stringify(tree.dump(), null, 2)); + gist.files[`treedump.json`] = { + content: JSON.stringify(tree.dump(), null, 2), + }; + + let gist_url: any = undefined; + await fetch("https://api.github.com/gists", { + method: "POST", + headers: { + Accept: "application/vnd.github+json", + Authorization: `Bearer ${GITHUB_TOKEN}`, + "X-GitHub-Api-Version": "2022-11-28", + }, + body: JSON.stringify(gist), + }) + .then((res) => res.json()) + .then((data) => { + console.log(data); + gist_url = data?.html_url; + }); + + return { root: tree.root, gist_url }; + + /* + * calculates the clr amount at the given threshold and total pot + **/ + function calculate_clr( + aggregated_contributions: Map< + string, + Map + >, // : PairNumber, // Map> + pair_totals: PairNumber, + // threshold: number, + total_pot: bigint, + { + M = 25_000_000n, // 25 USDT Dollars + N = 1_000n, // median is $0.1 USDT Dollar + } = {} + ) { + let bigtot = 0n; + let _q_bigsummed = 0.0; + const totals = []; + for (const [proj, contribz] of aggregated_contributions.entries()) { + let tot = 0n; + let _num = 0, + _sum = 0n, + _q_summed = 0.0; + // const _amounts = []; + + // pairwise match + for (const [k1, v1] of contribz.entries()) { + _num++; + _sum += v1.sum; + // _amounts.push(...v1.amounts); + _q_summed += Math.sqrt(Number(v1.sum)); + + for (const [k2, v2] of contribz.entries()) { + if (k2 > k1) { + // quadratic formula + tot += + (BigIntMath.sqrt(v1.sum * v2.sum) * // k(i,j) below + M) / + ((pair_totals.get(k1)?.get(k2) ?? 0n) + M); + } + } + + if (tot === 0n && contribz.size === 1) + tot += N * BigIntMath.sqrt(Array.from(contribz.values())[0].sum); + } + + bigtot += tot; + _q_bigsummed += _q_summed; + + totals.push({ + id: proj, + // title: dataHashMappings.get(proj)?.title || "", + // number_contributions: aggPerProj.get(proj)?.number_contributions ?? _num, + // number_contribution_addresses: _num, + // contribution_amount: _sum, + clr_amount: tot, + clr_amount_pairw: 0n, + clr_percent_pairw: 0.0, + clr_amount_orig: 0n, + clr_percent_orig: 0.0, + // url: dataHashMappings.get(proj)?.url || proj, + created_at: dataHashMappings.get(proj)?.createdAt, + author_eth: dataHashMappings.get(proj)?.ethAddress, + tot, + _q_summed, + // amounts: _amounts.sort(ascending), + }); + } + + for (const proj of totals) { + proj.clr_percent_pairw = Number(proj.tot) / Number(bigtot); + proj.clr_amount_pairw = + (total_pot * BigInt(Math.round(proj.clr_percent_pairw * 1e18))) / + BigInt(1e18); + proj.clr_percent_orig = proj._q_summed / _q_bigsummed; + proj.clr_amount_orig = + BigInt(Math.round(Number(total_pot) * proj.clr_percent_orig * 1e6)) / + 1_000_000n; + } + if (totals.length >= 2) { + // recalculate if totals not match'ing + let rem = total_pot; + let firstNonZero = totals.findIndex((p) => p.clr_amount_pairw > 0n); + + for (let i = firstNonZero + 1; i < totals.length; i++) { + rem -= totals[i].clr_amount_pairw; + } + totals[firstNonZero].clr_amount_pairw = rem; + + rem = total_pot; + firstNonZero = totals.findIndex((p) => p.clr_amount_orig > 0n); + for (let i = firstNonZero + 1; i < totals.length; i++) { + rem -= totals[i].clr_amount_orig; + } + totals[firstNonZero].clr_amount_orig = rem; + } + + console.log( + `calculate_clr: ${bigtot} distributed to ${totals.length} projects`, + { bigtot } + ); + + return totals; + } +} + +export function quantileSorted( + values: bigint[], + p: "median" | "p50" | "p75" | "p25" +) { + if (!(n = values.length)) return; + if (n < 2) return BigInt(values[0]); + // if (p >= 1) return BigInt(values[n - 1]); + switch (p) { + case "median": + case "p50": + i = (n - 1) * 0.5; + i0 = Math.floor(i); + break; + case "p25": + i = (n - 1) * 0.25; + i0 = Math.floor(i); + break; + case "p75": + i = (n - 1) * 0.75; + i0 = Math.floor(i); + break; + } + // eslint-disable-next-line no-var + var n, + i, // = (n - 1) * p, + i0, // = Math.floor(i), + value0 = BigInt(values[i0]), + value1 = BigInt(values[i0 + 1]); + console.log("quantile:", { p, [i0]: value0, [i0 + 1]: value1 }); + return ( + value0 + + (p === "median" || p === "p50" + ? BigInt(value1 - value0) >> 1n + : p === "p25" + ? BigInt(value1 - value0) >> 2n + : p === "p75" + ? (BigInt(value1 - value0) >> 2n) * 3n + : 0n) + ); +} + +/* translates django grant data structure to a list of lists + * returns: + list of lists of grant data + [[grant_id (str), user_id (str), contribution_amount (float)]] + * */ +function translate_data( + grants_data: Array<{ + id: string; + contributions: Array<{ [key: string]: string }>; + }> +) { + return grants_data + .map(({ id, contributions }) => + contributions.map((obj) => [ + id, + Object.keys(obj)[0], // user_id, + Object.values(obj)[0], // amount, + ]) + ) + .flat(1); +} + +type PairNumber = Map>; + +export // get pair totals +function get_totals_by_pair( + contrib_dict: Map> +) { + const tot_overlap: PairNumber = new Map(); + for (const [_, contribz] of contrib_dict.entries()) { + for (const [k1, v1] of contribz.entries()) { + // if (!tot_overlap.has(k1)) tot_overlap.set(k1, new Map()); + const tm = tot_overlap.get(k1) || new Map(); + for (const [k2, v2] of contribz.entries()) { + tm.set(k2, BigIntMath.sqrt(v1.sum * v2.sum) + (tm.get(k2) ?? 0n)); + } + if (!tot_overlap.has(k1)) tot_overlap.set(k1, tm); + } + } + + return tot_overlap; +} + +export function replacer(_: string, v: any) { + switch (typeof v) { + case "bigint": + return v.toString(); + default: + return v; + } +} + +// https://github.com/d3/d3-array/blob/main/src/ascending.js +function ascending(a: any, b: any) { + // prettier-ignore + return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +} + +function csvEscape(v: any, k: string) { + // const v = row[k]; + if (v == null || v === "") return ""; + if (v instanceof Date) return v.toISOString(); + // if (k.startsWith("clr_amount")) { console.log("clr_amount:", k, v); return +(Number(v) / 1e6).toFixed(6); } + switch (typeof v) { + case "boolean": + return v ? "Y" : ""; + case "bigint": + return +(Number(v) / 1e6).toFixed(6); + case "string": + if (k === "title" || v?.includes(",")) { + // return csvEscape(v.trim()); + const str = (v as string).trim(); + // prettier-ignore + return !str ? "" : (str.includes('\t') || str.match(/["\t]/)) ? `"${str.replace('"', '""')}"` : str; + } + + // eslint-disable-next-line no-fallthrough + default: + return v; + } + // return !str ? "" : str.match(/["\t]/) ? `"${str.replace('"', '""')}"` : str; +} diff --git a/package-lock.json b/package-lock.json index 1170dbd..8e8eba4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,13 @@ "@matters/apollo-response-cache": "^1.4.0-rc.0", "@matters/ipns-site-generator": "^0.1.5", "@matters/slugify": "^0.7.3", + "@openzeppelin/merkle-tree": "^1.0.5", "@sendgrid/helpers": "^7.7.0", "@sendgrid/mail": "^7.7.0", "@slack/web-api": "^6.8.1", "axios": "^1.3.2", "cheerio": "^1.0.0-rc.12", + "d3-array": "^3.2.4", "debug": "^4.3.4", "gw3-sdk": "^0.3.0", "ioredis": "^5.2.4", @@ -36,17 +38,19 @@ "pg": "^8.8.0", "postgres": "^3.3.2", "stripe": "^11.10.0", - "uuid": "^9.0.0" + "uuid": "^9.0.0", + "viem": "^1.21.4" }, "devDependencies": { "@tsconfig/node18": "^1.0.1", "@types/aws-lambda": "^8.10.109", + "@types/d3-array": "^3.2.1", "@types/debug": "^4.1.7", "@types/jest": "^29.2.5", "@types/lodash.uniqby": "^4.7.7", "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", + "@typescript-eslint/eslint-plugin": "^6.19.0", + "@typescript-eslint/parser": "^6.19.0", "bcrypt": "^5.1.0", "dotenv": "^16.0.3", "eslint": "^8.29.0", @@ -57,6 +61,11 @@ "typescript": "^5.3.3" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", + "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -3717,6 +3726,380 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, "node_modules/@google-analytics/data": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@google-analytics/data/-/data-4.0.1.tgz", @@ -4633,6 +5016,50 @@ "npm": ">=7.0.0" } }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4668,6 +5095,15 @@ "node": ">= 8" } }, + "node_modules/@openzeppelin/merkle-tree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@openzeppelin/merkle-tree/-/merkle-tree-1.0.5.tgz", + "integrity": "sha512-JkwG2ysdHeIphrScNxYagPy6jZeNONgDRyqU6lbFgE8HKCZFSkcP8r6AjZs+3HZk4uRNV0kNBBzuWhKQ3YV7Kw==", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "ethereum-cryptography": "^1.1.2" + } + }, "node_modules/@peculiar/asn1-schema": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz", @@ -4768,6 +5204,45 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@scure/base": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", + "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, "node_modules/@sendgrid/client": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.7.0.tgz", @@ -5011,6 +5486,12 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "dev": true + }, "node_modules/@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -5158,16 +5639,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", - "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz", + "integrity": "sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/type-utils": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/type-utils": "6.19.0", + "@typescript-eslint/utils": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -5193,15 +5674,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", - "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.0.tgz", + "integrity": "sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4" }, "engines": { @@ -5221,13 +5702,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", + "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -5238,13 +5719,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", - "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz", + "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/utils": "6.19.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -5265,9 +5746,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", + "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -5278,13 +5759,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", + "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -5330,17 +5811,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", + "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", "semver": "^7.5.4" }, "engines": { @@ -5355,12 +5836,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", + "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.19.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -5381,6 +5862,29 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "node_modules/abitype": { + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.9.8.tgz", + "integrity": "sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.19.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -6589,6 +7093,17 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/dag-jose": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dag-jose/-/dag-jose-3.0.1.tgz", @@ -7266,6 +7781,17 @@ "node": ">=0.10.0" } }, + "node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -7552,20 +8078,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -8235,6 +8747,14 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -8734,6 +9254,20 @@ "whatwg-fetch": "^3.4.1" } }, + "node_modules/isows": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", + "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "peerDependencies": { + "ws": "*" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -9468,6 +10002,11 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -12181,7 +12720,7 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12341,6 +12880,71 @@ "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" }, + "node_modules/viem": { + "version": "1.21.4", + "resolved": "https://registry.npmjs.org/viem/-/viem-1.21.4.tgz", + "integrity": "sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@scure/bip32": "1.3.2", + "@scure/bip39": "1.2.1", + "abitype": "0.9.8", + "isows": "1.0.3", + "ws": "8.13.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@scure/bip32": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", + "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", + "dependencies": { + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -12486,6 +13090,26 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -12555,6 +13179,11 @@ } }, "dependencies": { + "@adraffy/ens-normalize": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", + "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + }, "@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -15766,6 +16395,200 @@ "strip-json-comments": "^3.1.1" } }, + "@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "requires": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "requires": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "requires": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "requires": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "requires": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==" + }, + "@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "requires": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "requires": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, "@google-analytics/data": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@google-analytics/data/-/data-4.0.1.tgz", @@ -16471,6 +17294,31 @@ "@multiformats/multiaddr": "^11.0.0" } }, + "@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "requires": { + "@noble/hashes": "1.3.2" + }, + "dependencies": { + "@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" + } + } + }, + "@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==" + }, + "@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -16497,6 +17345,15 @@ "fastq": "^1.6.0" } }, + "@openzeppelin/merkle-tree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@openzeppelin/merkle-tree/-/merkle-tree-1.0.5.tgz", + "integrity": "sha512-JkwG2ysdHeIphrScNxYagPy6jZeNONgDRyqU6lbFgE8HKCZFSkcP8r6AjZs+3HZk4uRNV0kNBBzuWhKQ3YV7Kw==", + "requires": { + "@ethersproject/abi": "^5.7.0", + "ethereum-cryptography": "^1.1.2" + } + }, "@peculiar/asn1-schema": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz", @@ -16595,6 +17452,30 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@scure/base": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", + "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==" + }, + "@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "requires": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "requires": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, "@sendgrid/client": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.7.0.tgz", @@ -16811,6 +17692,12 @@ "@babel/types": "^7.3.0" } }, + "@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "dev": true + }, "@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -16958,16 +17845,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz", - "integrity": "sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz", + "integrity": "sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/type-utils": "6.18.0", - "@typescript-eslint/utils": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/type-utils": "6.19.0", + "@typescript-eslint/utils": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -16977,54 +17864,54 @@ } }, "@typescript-eslint/parser": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz", - "integrity": "sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.0.tgz", + "integrity": "sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", + "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0" } }, "@typescript-eslint/type-utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz", - "integrity": "sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz", + "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.18.0", - "@typescript-eslint/utils": "6.18.0", + "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/utils": "6.19.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", + "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", + "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -17054,27 +17941,27 @@ } }, "@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", + "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", + "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", "dev": true, "requires": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.19.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -17088,6 +17975,12 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "abitype": { + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.9.8.tgz", + "integrity": "sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==", + "requires": {} + }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -17986,6 +18879,14 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" }, + "d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "requires": { + "internmap": "1 - 2" + } + }, "dag-jose": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dag-jose/-/dag-jose-3.0.1.tgz", @@ -18503,6 +19404,17 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "requires": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -18727,13 +19639,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -19217,6 +20122,11 @@ "side-channel": "^1.0.4" } }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, "interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -19576,6 +20486,12 @@ "whatwg-fetch": "^3.4.1" } }, + "isows": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", + "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", + "requires": {} + }, "istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -20133,6 +21049,11 @@ "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", "dev": true }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -22165,7 +23086,7 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true + "devOptional": true }, "uint8arraylist": { "version": "2.4.3", @@ -22279,6 +23200,47 @@ "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" }, + "viem": { + "version": "1.21.4", + "resolved": "https://registry.npmjs.org/viem/-/viem-1.21.4.tgz", + "integrity": "sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ==", + "requires": { + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@scure/bip32": "1.3.2", + "@scure/bip39": "1.2.1", + "abitype": "0.9.8", + "isows": "1.0.3", + "ws": "8.13.0" + }, + "dependencies": { + "@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" + }, + "@scure/bip32": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", + "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", + "requires": { + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" + } + }, + "@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "requires": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + } + } + }, "walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -22399,6 +23361,12 @@ "signal-exit": "^3.0.7" } }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "requires": {} + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 9743dd3..2870cc2 100644 --- a/package.json +++ b/package.json @@ -13,12 +13,13 @@ "devDependencies": { "@tsconfig/node18": "^1.0.1", "@types/aws-lambda": "^8.10.109", + "@types/d3-array": "^3.2.1", "@types/debug": "^4.1.7", "@types/jest": "^29.2.5", "@types/lodash.uniqby": "^4.7.7", "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", + "@typescript-eslint/eslint-plugin": "^6.19.0", + "@typescript-eslint/parser": "^6.19.0", "bcrypt": "^5.1.0", "dotenv": "^16.0.3", "eslint": "^8.29.0", @@ -36,11 +37,13 @@ "@matters/apollo-response-cache": "^1.4.0-rc.0", "@matters/ipns-site-generator": "^0.1.5", "@matters/slugify": "^0.7.3", + "@openzeppelin/merkle-tree": "^1.0.5", "@sendgrid/helpers": "^7.7.0", "@sendgrid/mail": "^7.7.0", "@slack/web-api": "^6.8.1", "axios": "^1.3.2", "cheerio": "^1.0.0-rc.12", + "d3-array": "^3.2.4", "debug": "^4.3.4", "gw3-sdk": "^0.3.0", "ioredis": "^5.2.4", @@ -57,6 +60,7 @@ "pg": "^8.8.0", "postgres": "^3.3.2", "stripe": "^11.10.0", - "uuid": "^9.0.0" + "uuid": "^9.0.0", + "viem": "^1.21.4" } } diff --git a/tsconfig.json b/tsconfig.json index 0b54578..770ba06 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@tsconfig/node18/tsconfig.json", + "extends": "./node_modules/@tsconfig/node18/tsconfig.json", "compilerOptions": { "outDir": "./dist", "module": "esnext",