diff --git a/apps/playground-web/package.json b/apps/playground-web/package.json index 932e46c168c..ddd23b9b550 100644 --- a/apps/playground-web/package.json +++ b/apps/playground-web/package.json @@ -28,6 +28,7 @@ "@radix-ui/react-tabs": "^1.1.1", "@radix-ui/react-tooltip": "1.1.4", "@tanstack/react-query": "5.61.4", + "@thirdweb-dev/engine": "^0.0.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "0.461.0", @@ -41,6 +42,7 @@ "shiki": "1.22.2", "tailwind-merge": "^2.5.5", "thirdweb": "workspace:*", + "timeago.js": "^4.0.2", "use-debounce": "^10.0.4" }, "devDependencies": { diff --git a/apps/playground-web/public/BaseSep.png b/apps/playground-web/public/BaseSep.png new file mode 100644 index 00000000000..2b3765ad5c6 Binary files /dev/null and b/apps/playground-web/public/BaseSep.png differ diff --git a/apps/playground-web/public/Ethereum.png b/apps/playground-web/public/Ethereum.png new file mode 100644 index 00000000000..3c2c3640661 Binary files /dev/null and b/apps/playground-web/public/Ethereum.png differ diff --git a/apps/playground-web/public/airdrop.avif b/apps/playground-web/public/airdrop.avif new file mode 100644 index 00000000000..51492b89e12 Binary files /dev/null and b/apps/playground-web/public/airdrop.avif differ diff --git a/apps/playground-web/public/minting.avif b/apps/playground-web/public/minting.avif new file mode 100644 index 00000000000..5120ea713ba Binary files /dev/null and b/apps/playground-web/public/minting.avif differ diff --git a/apps/playground-web/public/webhooks.avif b/apps/playground-web/public/webhooks.avif new file mode 100644 index 00000000000..ec7a2144522 Binary files /dev/null and b/apps/playground-web/public/webhooks.avif differ diff --git a/apps/playground-web/src/app/api/airdrop/route.ts b/apps/playground-web/src/app/api/airdrop/route.ts new file mode 100644 index 00000000000..6fca6a8e9c2 --- /dev/null +++ b/apps/playground-web/src/app/api/airdrop/route.ts @@ -0,0 +1,155 @@ +import { Engine } from "@thirdweb-dev/engine"; +import * as dotenv from "dotenv"; +import type { NextRequest } from "next/server"; +import { NextResponse } from "next/server"; + +dotenv.config(); + +const CHAIN_ID = "84532"; +const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_WALLET as string; + +console.log("Environment Variables:"); +console.log("CHAIN_ID:", CHAIN_ID); +console.log("BACKEND_WALLET_ADDRESS:", BACKEND_WALLET_ADDRESS); +console.log("ENGINE_URL:", process.env.ENGINE_URL); +console.log( + "ACCESS_TOKEN:", + process.env.ENGINE_ACCESS_TOKEN ? "Set" : "Not Set", +); + +const engine = new Engine({ + url: process.env.ENGINE_URL as string, + accessToken: process.env.ENGINE_ACCESS_TOKEN as string, +}); + +interface MintResult { + queueId: string; + status: "Queued" | "Sent" | "Mined" | "error"; + transactionHash?: string; + blockExplorerUrl?: string; + errorMessage?: string; + toAddress: string; + amount: string; + chainId: number; + network: "Base Sep"; +} + +export async function POST(req: NextRequest) { + try { + const body = await req.json(); + console.log("Request body:", body); + + const { contractAddress, data } = body; + if (!Array.isArray(data)) { + return NextResponse.json( + { error: "Invalid data format" }, + { status: 400 }, + ); + } + + if (data.length === 0) { + return NextResponse.json({ error: "Empty data array" }, { status: 400 }); + } + + console.log(`Attempting to mint batch to ${data.length} receivers`); + console.log("Using CONTRACT_ADDRESS:", contractAddress); + + const res = await engine.erc20.mintBatchTo( + CHAIN_ID, + contractAddress, + BACKEND_WALLET_ADDRESS, + { + data: data.map((item) => ({ + toAddress: item.toAddress, + amount: item.amount, + })), + }, + ); + + console.log("Mint batch initiated, queue ID:", res.result.queueId); + const result = await pollToMine(res.result.queueId, data[0]); + return NextResponse.json([result]); + } catch (error: unknown) { + console.error("Error minting ERC20 tokens", error); + return NextResponse.json( + [ + { + queueId: "", + status: "error", + errorMessage: + error instanceof Error + ? error.message + : "An unknown error occurred", + toAddress: "", + amount: "", + chainId: Number.parseInt(CHAIN_ID), + network: "Base Sep", + }, + ], + { status: 500 }, + ); + } +} + +async function pollToMine( + queueId: string, + firstItem: { toAddress: string; amount: string }, +): Promise { + let attempts = 0; + const maxAttempts = 10; + + while (attempts < maxAttempts) { + try { + const status = await engine.transaction.status(queueId); + + if (status.result.status === "mined") { + console.log( + "Transaction mined! 🥳 ERC20 tokens have been minted", + queueId, + ); + const transactionHash = status.result.transactionHash; + const blockExplorerUrl = `https://base-sepolia.blockscout.com/tx/${transactionHash}`; + console.log("View transaction on the blockexplorer:", blockExplorerUrl); + return { + queueId, + status: "Mined", + transactionHash: transactionHash ?? undefined, + blockExplorerUrl: blockExplorerUrl, + toAddress: firstItem.toAddress, + amount: firstItem.amount, + chainId: Number.parseInt(CHAIN_ID), + network: "Base Sep", + }; + } + + if (status.result.status === "errored") { + console.error("Mint failed", queueId); + console.error(status.result.errorMessage); + return { + queueId, + status: "error", + errorMessage: status.result.errorMessage ?? "Unknown error occurred", + toAddress: firstItem.toAddress, + amount: firstItem.amount, + chainId: Number.parseInt(CHAIN_ID), + network: "Base Sep", + }; + } + } catch (error) { + console.error("Error checking transaction status:", error); + } + + attempts++; + await new Promise((resolve) => setTimeout(resolve, 5000)); + } + + return { + queueId, + status: "error", + errorMessage: "Transaction did not mine within the expected time", + toAddress: firstItem.toAddress, + amount: firstItem.amount, + chainId: Number.parseInt(CHAIN_ID), + network: "Base Sep", + }; +} diff --git a/apps/playground-web/src/app/api/claimTo/route.ts b/apps/playground-web/src/app/api/claimTo/route.ts new file mode 100644 index 00000000000..3bfe7476a3f --- /dev/null +++ b/apps/playground-web/src/app/api/claimTo/route.ts @@ -0,0 +1,226 @@ +import { Engine } from "@thirdweb-dev/engine"; +import * as dotenv from "dotenv"; +import type { NextRequest } from "next/server"; +import { NextResponse } from "next/server"; + +dotenv.config(); + +const BASESEP_CHAIN_ID = "84532"; +const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_WALLET as string; + +console.log("Environment Variables:"); +console.log("CHAIN_ID:", BASESEP_CHAIN_ID); +console.log("BACKEND_WALLET_ADDRESS:", BACKEND_WALLET_ADDRESS); +console.log("ENGINE_URL:", process.env.ENGINE_URL); +console.log( + "ACCESS_TOKEN:", + process.env.ENGINE_ACCESS_TOKEN ? "Set" : "Not Set", +); + +const engine = new Engine({ + url: process.env.ENGINE_URL as string, + accessToken: process.env.ENGINE_ACCESS_TOKEN as string, +}); + +type TransactionStatus = "Queued" | "Sent" | "Mined" | "error"; + +interface ClaimResult { + queueId: string; + status: TransactionStatus; + transactionHash?: string | undefined | null; + blockExplorerUrl?: string | undefined | null; + errorMessage?: string; + toAddress?: string; + amount?: string; + chainId?: string; + timestamp?: number; +} + +// Store ongoing polling processes +const pollingProcesses = new Map(); + +// Helper function to make a single claim +async function makeClaimRequest( + chainId: string, + contractAddress: string, + data: { + recipient: string; + quantity: number; + }, +): Promise { + try { + // Validate the recipient address format + if (!data.recipient.match(/^0x[a-fA-F0-9]{40}$/)) { + throw new Error("Invalid wallet address format"); + } + + const res = await engine.erc721.claimTo( + chainId, + contractAddress, + BACKEND_WALLET_ADDRESS, + { + receiver: data.recipient.toString(), + quantity: data.quantity.toString(), + txOverrides: { + gas: "530000", + maxFeePerGas: "1000000000", + maxPriorityFeePerGas: "1000000000", + }, + }, + ); + + const initialResponse: ClaimResult = { + queueId: res.result.queueId, + status: "Queued", + toAddress: data.recipient, + amount: data.quantity.toString(), + chainId, + timestamp: Date.now(), + }; + + startPolling(res.result.queueId); + return initialResponse; + } catch (error) { + console.error("Claim request error:", error); + throw error; + } +} + +export async function POST(req: NextRequest) { + try { + const body = await req.json(); + + if (!body.receiver || !body.quantity || !body.contractAddress) { + return NextResponse.json( + { error: "Missing receiver, quantity, or contract address" }, + { status: 400 }, + ); + } + + // Validate contract address format + if (!body.contractAddress.match(/^0x[a-fA-F0-9]{40}$/)) { + return NextResponse.json( + { error: "Invalid contract address format" }, + { status: 400 }, + ); + } + + const result = await makeClaimRequest( + BASESEP_CHAIN_ID, + body.contractAddress, + { + recipient: body.receiver, + quantity: Number.parseInt(body.quantity), + }, + ); + + return NextResponse.json({ result }); + } catch (error) { + console.error("API Error:", error); + return NextResponse.json( + { + error: + error instanceof Error ? error.message : "Unknown error occurred", + details: error instanceof Error ? error.stack : undefined, + }, + { status: 400 }, + ); + } +} + +function startPolling(queueId: string) { + const maxPollingTime = 5 * 60 * 1000; // 5 minutes timeout + const startTime = Date.now(); + + const pollingInterval = setInterval(async () => { + try { + // Check if we've exceeded the maximum polling time + if (Date.now() - startTime > maxPollingTime) { + clearInterval(pollingInterval); + pollingProcesses.delete(queueId); + console.log(`Polling timeout for queue ID: ${queueId}`); + return; + } + + const result = await pollToMine(queueId); + if (result.status === "Mined" || result.status === "error") { + clearInterval(pollingInterval); + pollingProcesses.delete(queueId); + console.log("Final result:", result); + } + } catch (error) { + console.error("Error in polling process:", error); + clearInterval(pollingInterval); + pollingProcesses.delete(queueId); + } + }, 1500); + + pollingProcesses.set(queueId, pollingInterval); +} + +async function pollToMine(queueId: string): Promise { + console.log(`Polling for queue ID: ${queueId}`); + const status = await engine.transaction.status(queueId); + console.log(`Current status: ${status.result.status}`); + + switch (status.result.status) { + case "queued": + console.log("Transaction is queued"); + return { queueId, status: "Queued" }; + case "sent": + console.log("Transaction is submitted to the network"); + return { queueId, status: "Sent" }; + case "mined": { + console.log( + "Transaction mined! 🥳 ERC721 token has been claimed", + queueId, + ); + const transactionHash = status.result.transactionHash; + const blockExplorerUrl = + status.result.chainId === BASESEP_CHAIN_ID + ? `https://base-sepolia.blockscout.com/tx/${transactionHash}` + : ""; + console.log("View transaction on the blockexplorer:", blockExplorerUrl); + return { + queueId, + status: "Mined", + transactionHash: transactionHash ?? undefined, + blockExplorerUrl: blockExplorerUrl, + }; + } + case "errored": + console.error("Claim failed", queueId); + console.error(status.result.errorMessage); + return { + queueId, + status: "error", + errorMessage: status.result.errorMessage || "Transaction failed", + }; + default: + return { queueId, status: "Queued" }; + } +} + +// Add a new endpoint to check the status +export async function GET(req: NextRequest) { + const { searchParams } = new URL(req.url); + const queueId = searchParams.get("queueId"); + + if (!queueId) { + return NextResponse.json({ error: "Missing queueId" }, { status: 400 }); + } + + try { + const result = await pollToMine(queueId); + return NextResponse.json(result); + } catch (error) { + console.error("Error checking transaction status:", error); + return NextResponse.json( + { + status: "error" as TransactionStatus, + error: "Failed to check transaction status", + }, + { status: 500 }, + ); + } +} diff --git a/apps/playground-web/src/app/api/erc20BatchMintTo/route.ts b/apps/playground-web/src/app/api/erc20BatchMintTo/route.ts new file mode 100644 index 00000000000..276bf896759 --- /dev/null +++ b/apps/playground-web/src/app/api/erc20BatchMintTo/route.ts @@ -0,0 +1,125 @@ +import { Engine } from "@thirdweb-dev/engine"; +import * as dotenv from "dotenv"; +import type { NextRequest } from "next/server"; +import { NextResponse } from "next/server"; +import type { Address } from "thirdweb"; + +dotenv.config(); + +const BASESEP_CHAIN_ID = "84532"; +const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_WALLET as string; + +console.log("Environment Variables:"); +console.log("CHAIN_ID:", BASESEP_CHAIN_ID); +console.log("BACKEND_WALLET_ADDRESS:", BACKEND_WALLET_ADDRESS); +console.log("ENGINE_URL:", process.env.ENGINE_URL); +console.log( + "ACCESS_TOKEN:", + process.env.ENGINE_ACCESS_TOKEN ? "Set" : "Not Set", +); + +const engine = new Engine({ + url: process.env.ENGINE_URL as string, + accessToken: process.env.ENGINE_ACCESS_TOKEN as string, +}); + +const chain = "84532"; + +type Receiver = { + toAddress: Address; + amount: string; +}; + +type DataEntry = { + toAddress: string; + amount: string; +}; + +export async function POST(req: NextRequest) { + try { + const { data, contractAddress } = await req.json(); + + console.log("Received request with:", { + contractAddress, + dataLength: data.length, + sampleData: data[0], + }); + + const receivers: Receiver[] = data.map((entry: DataEntry) => ({ + toAddress: entry.toAddress as Address, + amount: entry.amount, + })); + + const chunks: Receiver[][] = []; + const chunkSize = 10; + for (let i = 0; i < receivers.length; i += chunkSize) { + chunks.push(receivers.slice(i, i + chunkSize)); + } + + // Process first chunk and return immediately with queued status + const firstChunk = chunks[0]; + const res = await engine.erc20.mintBatchTo( + chain, + contractAddress, + BACKEND_WALLET_ADDRESS, + { + data: firstChunk, + }, + ); + + // Return initial queued status + const initialResult = { + queueId: res.result.queueId, + status: "queued" as const, + addresses: firstChunk.map((r) => r.toAddress), + amounts: firstChunk.map((r) => r.amount), + timestamp: Date.now(), + chainId: Number.parseInt(chain), + network: "Base Sep" as const, + }; + + // Start polling in the background + pollToMine(res.result.queueId).then((pollResult) => { + console.log("Transaction completed:", pollResult); + }); + + return NextResponse.json([initialResult]); + } catch (error: unknown) { + console.error("Detailed error:", error); + const errorMessage = + error instanceof Error ? error.message : "Unknown error occurred"; + return NextResponse.json( + { + error: "Transfer failed", + details: errorMessage, + }, + { status: 500 }, + ); + } +} + +async function pollToMine(queueId: string) { + try { + const status = await engine.transaction.status(queueId); + + if (status.result.status === "mined") { + const transactionHash = status.result.transactionHash; + const blockExplorerUrl = `https://base-sepolia.blockscout.com/tx/${transactionHash}`; + return { status: "Mined", queueId, transactionHash, blockExplorerUrl }; + } + + return { + status: + status.result.status.charAt(0).toUpperCase() + + status.result.status.slice(1), + queueId, + }; + } catch (error) { + console.error("Error checking transaction status:", error); + return { + status: "error", + queueId, + errorMessage: "Failed to check transaction status", + }; + } +} diff --git a/apps/playground-web/src/app/api/mintTo/route.ts b/apps/playground-web/src/app/api/mintTo/route.ts new file mode 100644 index 00000000000..b3f4767ac2b --- /dev/null +++ b/apps/playground-web/src/app/api/mintTo/route.ts @@ -0,0 +1,105 @@ +import { Engine } from "@thirdweb-dev/engine"; +import * as dotenv from "dotenv"; +import { type NextRequest, NextResponse } from "next/server"; + +dotenv.config(); + +const CHAIN_ID = "84532"; +const CONTRACT_ADDRESS = "0x8CD193648f5D4E8CD9fD0f8d3865052790A680f6"; +const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_WALLET as string; + +// Add logging for environment variables +console.log("Environment Variables:"); +console.log("CHAIN_ID:", CHAIN_ID); +console.log("BACKEND_WALLET_ADDRESS:", BACKEND_WALLET_ADDRESS); +console.log("CONTRACT_ADDRESS:", CONTRACT_ADDRESS); +console.log("ENGINE_URL:", process.env.ENGINE_URL); +console.log( + "ACCESS_TOKEN:", + process.env.ENGINE_ACCESS_TOKEN ? "Set" : "Not Set", +); + +const engine = new Engine({ + url: process.env.ENGINE_URL as string, + accessToken: process.env.ENGINE_ACCESS_TOKEN as string, +}); + +export async function POST(req: NextRequest) { + try { + const body = await req.json(); + console.log("Request body:", body); + + const receiver = body.receiver || body.toAddress; + const metadataWithSupply = body.metadataWithSupply; + + if (!receiver || !metadataWithSupply) { + return NextResponse.json( + { error: "Missing receiver or metadataWithSupply" }, + { status: 400 }, + ); + } + + console.log( + `Attempting to mint for receiver: ${receiver}, metadataWithSupply:`, + metadataWithSupply, + ); + console.log("Using CONTRACT_ADDRESS:", CONTRACT_ADDRESS); + + const res = await engine.erc1155.mintTo( + CHAIN_ID, + CONTRACT_ADDRESS, + BACKEND_WALLET_ADDRESS, + { + receiver, + metadataWithSupply, + }, + ); + + // Return immediately with queued status + const initialResult = { + queueId: res.result.queueId, + status: "Queued" as const, + toAddress: receiver, + amount: metadataWithSupply.supply || "1", + timestamp: Date.now(), + chainId: Number.parseInt(CHAIN_ID), + network: "Base Sep" as const, + }; + + // Start polling in the background + pollToMine(res.result.queueId).then((pollResult) => { + // This will be handled by the frontend polling + console.log("Transaction completed:", pollResult); + }); + + return NextResponse.json(initialResult); + } catch (error: unknown) { + console.error("Error minting ERC1155 tokens", error); + if (error instanceof Error) { + return NextResponse.json( + { error: "Error minting ERC1155 tokens", details: error.message }, + { status: 500 }, + ); + } + } +} + +async function pollToMine(queueId: string) { + try { + const status = await engine.transaction.status(queueId); + + if (status.result.status === "mined") { + const transactionHash = status.result.transactionHash; + const blockExplorerUrl = `https://base-sepolia.blockscout.com/tx/${transactionHash}`; + return { status: "Mined", transactionHash, blockExplorerUrl }; + } + + return { status: status.result.status }; + } catch (error) { + console.error("Error checking transaction status:", error); + return { + status: "error", + errorMessage: "Failed to check transaction status", + }; + } +} diff --git a/apps/playground-web/src/app/api/transaction-status/route.ts b/apps/playground-web/src/app/api/transaction-status/route.ts new file mode 100644 index 00000000000..b52823f4bf2 --- /dev/null +++ b/apps/playground-web/src/app/api/transaction-status/route.ts @@ -0,0 +1,41 @@ +import { Engine } from "@thirdweb-dev/engine"; +import { type NextRequest, NextResponse } from "next/server"; + +const engine = new Engine({ + url: process.env.ENGINE_URL as string, + accessToken: process.env.ACCESS_TOKEN as string, +}); + +export async function GET(req: NextRequest) { + const searchParams = req.nextUrl.searchParams; + const queueId = searchParams.get("queueId"); + + if (!queueId) { + return NextResponse.json({ error: "Missing queueId" }, { status: 400 }); + } + + try { + const status = await engine.transaction.status(queueId); + + if (status.result.status === "mined") { + const transactionHash = status.result.transactionHash; + const blockExplorerUrl = `https://base-sepolia.blockscout.com/tx/${transactionHash}`; + return NextResponse.json({ + status: "Mined", + transactionHash, + blockExplorerUrl, + }); + } + + return NextResponse.json({ + status: status.result.status, + errorMessage: status.result.errorMessage, + }); + } catch (error) { + console.error("Error checking transaction status:", error); + return NextResponse.json( + { error: "Failed to check transaction status" }, + { status: 500 }, + ); + } +} diff --git a/apps/playground-web/src/app/engine/airdrop/page.tsx b/apps/playground-web/src/app/engine/airdrop/page.tsx new file mode 100644 index 00000000000..3fb8d20433a --- /dev/null +++ b/apps/playground-web/src/app/engine/airdrop/page.tsx @@ -0,0 +1,45 @@ +import { AirdropERC20 } from "@/components/engine/airdrop/airdrop-erc20"; +import ThirdwebProvider from "@/components/thirdweb-provider"; +import { EngineAPIHeader } from "../../../components/blocks/EngineAPIHeader"; +// TODO: Get updated banner image and description. +export default function Page() { + return ( + +
+ + Engine makes it effortless for any developer to airdrop tokens at + scale. You sponsor the gas so your users only need a wallet + address! + + } + docsLink="https://thirdweb-engine.apidocumentation.com/reference#tag/erc20/POST/contract/{chain}/{contractAddress}/erc20/mint-batch-to?utm_source=playground" + heroLink="/airdrop.avif" + /> + +
+ +
+
+
+ ); +} + +function InGameCurrency() { + return ( + <> +
+

+ Airdrop +

+

+ Use Engine to Airdrop in-game currency to a list of players in one + transaction. +

+
+ + + ); +} diff --git a/apps/playground-web/src/app/engine/minting/page.tsx b/apps/playground-web/src/app/engine/minting/page.tsx new file mode 100644 index 00000000000..3c8a9930fba --- /dev/null +++ b/apps/playground-web/src/app/engine/minting/page.tsx @@ -0,0 +1,44 @@ +import { ERC1155MintTo } from "@/components/engine/minting/erc1155-mint-to"; +import ThirdwebProvider from "@/components/thirdweb-provider"; +import { EngineAPIHeader } from "../../../components/blocks/EngineAPIHeader"; +// TODO: Get updated banner image and description. +export default function Page() { + return ( + +
+ + Allow your users to mint new tokens into any given contract. You + sponsor the gas so your users only need a wallet address! + + } + docsLink="https://thirdweb-engine.apidocumentation.com/reference#tag/erc1155/POST/contract/{chain}/{contractAddress}/erc1155/mint-to?utm_source=playground" + heroLink="/minting.avif" + /> + +
+ +
+
+
+ ); +} + +function Minting() { + return ( + <> +
+

+ Minting +

+

+ Allow your users to mint new tokens into any given contract. You + sponsor the gas so your users only need a wallet address! +

+
+ + + ); +} diff --git a/apps/playground-web/src/app/engine/webhooks/page.tsx b/apps/playground-web/src/app/engine/webhooks/page.tsx new file mode 100644 index 00000000000..af146ca17b6 --- /dev/null +++ b/apps/playground-web/src/app/engine/webhooks/page.tsx @@ -0,0 +1,44 @@ +import { Sponsorship } from "@/components/engine/gasless/Sponsorship"; +import ThirdwebProvider from "@/components/thirdweb-provider"; +import { EngineAPIHeader } from "../../../components/blocks/EngineAPIHeader"; +// TODO: Get updated banner image and description. +export default function Page() { + return ( + +
+ + Configure webhooks in Engine to notify your backend server of + transaction or backend wallet events. + + } + docsLink="https://portal.thirdweb.com/engine/features/webhooks?utm_source=playground" + heroLink="/webhooks.avif" + /> + +
+ +
+
+
+ ); +} + +function Webhooks() { + return ( + <> +
+

+ Webhooks +

+

+ Configure webhooks in Engine to notify your backend server of + transaction or backend wallet events. +

+
+ + + ); +} diff --git a/apps/playground-web/src/app/navLinks.ts b/apps/playground-web/src/app/navLinks.ts index d870b0e4707..8b42463b616 100644 --- a/apps/playground-web/src/app/navLinks.ts +++ b/apps/playground-web/src/app/navLinks.ts @@ -21,7 +21,7 @@ export const navLinks: SidebarLink[] = [ }, { name: "Account Abstraction", - expanded: true, + expanded: false, links: [ { name: "Connect", @@ -39,7 +39,7 @@ export const navLinks: SidebarLink[] = [ }, { name: "In-App Wallet", - expanded: true, + expanded: false, links: [ { name: "Any Auth", @@ -57,7 +57,7 @@ export const navLinks: SidebarLink[] = [ }, { name: "Pay", - expanded: true, + expanded: false, links: [ { name: "Top up", @@ -73,6 +73,32 @@ export const navLinks: SidebarLink[] = [ }, ], }, + { + name: "Engine", + expanded: false, + links: [ + { + name: "Airdrop", + href: "/engine/airdrop", + }, + { + name: "Minting", + href: "/engine/minting", + }, + { + name: "Webhooks", + href: "/engine/webhooks", + }, + // { + // name: "Session Keys", + // href: "/engine/account-abstraction/session-keys", + // }, + // { + // name: "Smart Backend Wallets", + // href: "/engine/account-abstraction/smart-backend-wallets", + // }, + ], + }, { name: "Auth", href: "/connect/auth", diff --git a/apps/playground-web/src/components/blocks/EngineAPIHeader.tsx b/apps/playground-web/src/components/blocks/EngineAPIHeader.tsx new file mode 100644 index 00000000000..16b20f4eda9 --- /dev/null +++ b/apps/playground-web/src/components/blocks/EngineAPIHeader.tsx @@ -0,0 +1,64 @@ +import Image from "next/image"; +import Link from "next/link"; +import { Button } from "../ui/button"; + +export function EngineAPIHeader(props: { + title: string; + description: React.ReactNode; + docsLink: string; + heroLink: string; +}) { + return ( +
+ {/* Left */} +
+

+ {props.title} +

+

+ {props.description} +

+ +
+ + + +
+
+ + {/* Right */} + +
+ ); +} diff --git a/apps/playground-web/src/components/engine/airdrop/TransactionResults.tsx b/apps/playground-web/src/components/engine/airdrop/TransactionResults.tsx new file mode 100644 index 00000000000..a6bc3acef77 --- /dev/null +++ b/apps/playground-web/src/components/engine/airdrop/TransactionResults.tsx @@ -0,0 +1,278 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardFooter, + CardHeader, +} from "@/components/ui/card"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import type React from "react"; +import { useState } from "react"; +import { format } from "timeago.js"; + +interface ClaimTransactionResults { + queueId: string; + status: "Queued" | "Sent" | "Mined" | "error"; + transactionHash?: string; + blockExplorerUrl?: string; + errorMessage: "Error" | undefined; + toAddress: string; + amount: string; + timestamp?: number; + chainId: number; + network: "Ethereum" | "Base Sep" | "OP Sep"; +} + +interface ClaimTransactionResultsProps { + results: ClaimTransactionResults[]; +} +// I did have one component of this, but it was causing weird queuing issues when shared among multiple components. So just created one for each instead. +export function ClaimTransactionResults({ + results, +}: ClaimTransactionResultsProps) { + const [currentPage, setCurrentPage] = useState(1); + const [showLeftGradient, setShowLeftGradient] = useState(false); + const [showRightGradient, setShowRightGradient] = useState(true); + const itemsPerPage = 2; + // Added dummy transactions so the table doesn't look empty. + const dummyTransaction1: ClaimTransactionResults = { + queueId: "0x1234567890abcdef", + status: "Mined", + transactionHash: "0xabcdef1234567890", + blockExplorerUrl: "https://etherscan.io/tx/0xabcdef1234567890", + toAddress: "0x1234567890abcdef", + amount: "1.0", + timestamp: Date.now() - 15 * 60 * 1000, + chainId: 1, + network: "Ethereum", + errorMessage: undefined, + }; + + const dummyTransaction2: ClaimTransactionResults = { + queueId: "0x9876543210fedcba", + status: "Mined", + transactionHash: "0x1234567890abcdef", + blockExplorerUrl: "https://etherscan.io/tx/0x1234567890abcdef", + toAddress: "0xabcdef1234567890", + amount: "0.5", + timestamp: Date.now() - 30 * 60 * 1000, + chainId: 1, + network: "Base Sep", + errorMessage: undefined, + }; + + const sortedResults = [...results].reverse(); + const sortedResultsWithDummy = [ + ...sortedResults, + dummyTransaction1, + dummyTransaction2, + ]; + + const indexOfLastItem = currentPage * itemsPerPage; + const indexOfFirstItem = indexOfLastItem - itemsPerPage; + const currentItems = sortedResultsWithDummy.slice( + indexOfFirstItem, + indexOfLastItem, + ); + const totalPages = Math.ceil(sortedResultsWithDummy.length / itemsPerPage); + + const handleNextPage = () => { + setCurrentPage((prev) => Math.min(prev + 1, totalPages)); + }; + + const handlePrevPage = () => { + setCurrentPage((prev) => Math.max(prev - 1, 1)); + }; + + const getDisplayStatus = (result: ClaimTransactionResults) => { + if (result.status === "Mined" && !result.transactionHash) { + return "Pending"; + } + return result.status; + }; + + const getStatusColor = (status: string) => { + switch (status) { + case "Mined": + return "bg-green-500/20 text-green-400"; + case "Queued": + case "Pending": + return "bg-yellow-500/20 text-yellow-400"; + case "Sent": + return "bg-blue-500/20 text-blue-400"; + default: + return "bg-red-500/20 text-red-400"; + } + }; + + const handleScroll = (e: React.UIEvent) => { + const target = e.currentTarget; + const isAtStart = target.scrollLeft === 0; + const isAtEnd = + target.scrollLeft + target.clientWidth >= target.scrollWidth - 1; // -1 for rounding errors + + setShowLeftGradient(!isAtStart); + setShowRightGradient(!isAtEnd); + }; + + return ( + + +

+ Transaction Results +

+ + Last 24 hours • {sortedResultsWithDummy.length} transactions + +
+ +
+ + + + Queue ID + Network + From + Queued + Status + Tx Hash + + + + {currentItems.map((result, index) => ( + + + {result.queueId + ? `${result.queueId.substring(0, 6)}...${result.queueId.substring( + result.queueId.length - 4, + )}` + : "----"} + + + + {result.network === "Base Sep" && ( + Base + )} + {result.network === "OP Sep" && ( + Optimism Sep + )} + {result.network === "Ethereum" && ( + Ethereum + )} + {result.network} + + + + {(() => { + if (!result.toAddress) return "----"; + + const addressDisplay = `${result.toAddress.substring(0, 6)}...${result.toAddress.substring( + result.toAddress.length - 4, + )}`; + // Keeping OP here for consistency. Will be adding a component for Optimism soon. + const getExplorerUrl = () => { + switch (result.network) { + case "Base Sep": + return `https://base-sepolia.blockscout.com/address/${result.toAddress}?tab=tokens`; + case "OP Sep": + return `https://optimism-sepolia.blockscout.com/address/${result.toAddress}?tab=tokens`; + case "Ethereum": + return `https://etherscan.io/address/${result.toAddress}?tab=tokens`; + default: + return null; + } + }; + + const explorerUrl = getExplorerUrl(); + + return explorerUrl ? ( + + {addressDisplay} + + ) : ( + addressDisplay + ); + })()} + + + {result.timestamp ? format(result.timestamp) : "Just now"} + + + + {getDisplayStatus(result)} + + + + {result.transactionHash && result.blockExplorerUrl ? ( + + {`${result.transactionHash.substring(0, 6)}...${result.transactionHash.substring( + result.transactionHash.length - 4, + )}`} + + ) : result.errorMessage ? ( + + {result.errorMessage} + + ) : ( + "----" + )} + + + ))} + +
+
+ {showLeftGradient && ( +
+ )} + {showRightGradient && ( +
+ )} + + + + + Page {currentPage} of {totalPages} + + + + + ); +} diff --git a/apps/playground-web/src/components/engine/airdrop/airdrop-erc20.tsx b/apps/playground-web/src/components/engine/airdrop/airdrop-erc20.tsx new file mode 100644 index 00000000000..93a2556fa2f --- /dev/null +++ b/apps/playground-web/src/components/engine/airdrop/airdrop-erc20.tsx @@ -0,0 +1,223 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { useState } from "react"; +import { ClaimTransactionResults as ClaimTransactionResultsComponent } from "./TransactionResults"; + +interface ClaimTransactionResults { + queueId: string; + status: "Queued" | "Sent" | "Mined" | "error"; + transactionHash?: string; + blockExplorerUrl?: string; + errorMessage: "Error" | undefined; + toAddress: string; + amount: string; + timestamp?: number; + chainId: number; + network: "Ethereum" | "Base Sep" | "OP Sep"; +} + +interface CsvRow { + toAddress: string; + amount: string; +} + +interface BatchResult { + queueId: string; + addresses: string[]; + amounts: string[]; + status: "Queued" | "Sent" | "Mined" | "error"; + timestamp: number; + chainId: number; + network: "Ethereum" | "Base Sep" | "OP Sep"; +} + +// Setting dummy addresses so no one gets spammed. +export function AirdropERC20() { + const [csvData] = useState([ + { toAddress: "0x1f91EB653116A43413930c1df0CF5794fCc2D611", amount: "1" }, + { toAddress: "0xA707E9650631800a635c629e9C8E5937b7277a08", amount: "1" }, + { toAddress: "0xF1f466c973C197e5D9318F6241C2da31742d3d03", amount: "1" }, + { toAddress: "0x56671F2cb5d401f989Df5d3B4f8C814E6A022bf7", amount: "1" }, + { toAddress: "0x5F0633eD9c359C84F9A7B4A898DA6864893fe943", amount: "1" }, + { toAddress: "0x626522375a0F448fc7B87055f83a0402b89D06Eb", amount: "1" }, + { toAddress: "0x4D9c3Ae6ce7751616cB29E2bcF972357f28924E0", amount: "1" }, + { toAddress: "0xc4757A402F4c5a447B2b20670ADd10A042f1142D", amount: "1" }, + { toAddress: "0x9244B15679F4d4e1CEE0Ef6401A59b3d302c8Fca", amount: "1" }, + { toAddress: "0xF7DB7C0205f5Bf2E32F55A633703da1d075036A7", amount: "1" }, + ]); + + const [currentPage, setCurrentPage] = useState(0); + const rowsPerPage = 5; + + const paginatedData = csvData.slice( + currentPage * rowsPerPage, + (currentPage + 1) * rowsPerPage, + ); + + const totalPages = Math.ceil(csvData.length / rowsPerPage); + + const [isSubmitting, setIsSubmitting] = useState(false); + const [results, setResults] = useState([]); + + const pollTransactionStatus = async (queueId: string) => { + const pollInterval = setInterval(async () => { + try { + const response = await fetch( + `/api/transaction-status?queueId=${queueId}`, + ); + const status = await response.json(); + + setResults((prevResults) => + prevResults.map((result) => { + if (result.queueId === queueId) { + return { + ...result, + ...status, + status: status.status === "mined" ? "Mined" : status.status, + }; + } + return result; + }), + ); + + if (status.status === "Mined" || status.status === "error") { + clearInterval(pollInterval); + } + } catch (error) { + console.error("Error polling status:", error); + clearInterval(pollInterval); + } + }, 2000); + + setTimeout(() => clearInterval(pollInterval), 5 * 60 * 1000); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSubmitting(true); + setResults([]); + + try { + const response = await fetch("/api/erc20BatchMintTo", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + contractAddress: "0xcB30dB8FB977e8b27ae34c86aF16C4F5E428c0bE", + data: csvData.map((row) => ({ + toAddress: row.toAddress, + amount: row.amount, + })), + }), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + + // Transform the initial queued results + const transformedResults = result.flatMap((batch: BatchResult) => + batch.addresses.map((address: string, index: number) => ({ + queueId: batch.queueId, + status: batch.status, + toAddress: address, + amount: batch.amounts[index], + timestamp: batch.timestamp, + chainId: batch.chainId, + network: batch.network, + })), + ); + + setResults(transformedResults); + + // Start polling for each batch + for (const batch of result) { + pollTransactionStatus(batch.queueId); + } + } catch (error) { + console.error("Error:", error); + setResults([ + { + queueId: "", + status: "error", + errorMessage: "Error", + toAddress: "", + amount: "", + chainId: 84532, + network: "Base Sep", + }, + ]); + } finally { + setIsSubmitting(false); + } + }; + + return ( +
+
+ +
+
+ + + + Address + Amount + + + + {paginatedData.map((row) => ( + + {row.toAddress} + {row.amount} + + ))} + +
+
+ + + Page {currentPage + 1} of {totalPages} + + +
+
+
+
+
+ + +
+ ); +} diff --git a/apps/playground-web/src/components/engine/gasless/Sponsorship.tsx b/apps/playground-web/src/components/engine/gasless/Sponsorship.tsx new file mode 100644 index 00000000000..decd575a5ae --- /dev/null +++ b/apps/playground-web/src/components/engine/gasless/Sponsorship.tsx @@ -0,0 +1,181 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { THIRDWEB_CLIENT } from "@/lib/client"; +import { useState } from "react"; +import { baseSepolia } from "thirdweb/chains"; +import { ConnectButton, useActiveAccount } from "thirdweb/react"; +import { Webhook } from "./Webhook"; + +interface ClaimTransactionResults { + queueId: string; + status: string; + toAddress: string; + amount: string; + timestamp?: number; + chainId: number; + network: string; + errorMessage?: string; +} + +// This says Sponsorship, but it's actually just displaying a dummy webhook + +export function Sponsorship() { + const [contractAddress, setContractAddress] = useState(""); + const [quantity, setQuantity] = useState("1"); + const [isLoading, setIsLoading] = useState(false); + const [queueId, setQueueId] = useState(null); + const [transactions, setTransactions] = useState( + [], + ); + const [selectedContract, setSelectedContract] = useState(""); + const account = useActiveAccount(); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsLoading(true); + + try { + if (!contractAddress.match(/^0x[a-fA-F0-9]{40}$/)) { + throw new Error("Invalid contract address format"); + } + + const response = await fetch("/api/claimTo", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + receiver: account?.address, + quantity: quantity, + contractAddress, + }), + }); + + const data = await response.json(); + const { result } = data; + setQueueId(result.queueId); + + const newTransaction: ClaimTransactionResults = { + queueId: result.queueId, + status: "Queued", + toAddress: account?.address || "", + amount: quantity, + chainId: 84532, + network: "Base Sep", + }; + setTransactions((prev) => [...prev, newTransaction]); + + if (result.queueId) { + const pollInterval = setInterval(async () => { + const statusResponse = await fetch( + `/api/claimTo?queueId=${result.queueId}`, + ); + const statusData = await statusResponse.json(); + + setTransactions((prev) => + prev.map((tx) => + tx.queueId === result.queueId + ? { + ...tx, + status: statusData.status, + errorMessage: statusData.errorMessage, + } + : tx, + ), + ); + + if (statusData.status === "Mined") { + clearInterval(pollInterval); + setIsLoading(false); + } else if (statusData.status === "error") { + clearInterval(pollInterval); + setIsLoading(false); + throw new Error(statusData.errorMessage || "Failed to mint NFT"); + } + }, 2000); + } + } catch (error) { + console.error("Error details:", error); + setIsLoading(false); + } + }; + + // 2 contracts here to show engine claim good, and engine claim bad. One has tokens, and the other doesnt so itll fail + return ( +
+
+
+
+ +
+
    Select an NFT Contract to mint
+
+ +
+
    Select the quantity of NFTs to mint
+
+ setQuantity(e.target.value)} + required + className="text-sm sm:text-base" + /> + +
+
+ + +
+ {transactions.map((tx) => ( +
+ Status: {tx.status} - Amount: {tx.amount} +
+ ))} +
+
+ ); +} diff --git a/apps/playground-web/src/components/engine/gasless/Webhook.tsx b/apps/playground-web/src/components/engine/gasless/Webhook.tsx new file mode 100644 index 00000000000..dbd3340678a --- /dev/null +++ b/apps/playground-web/src/components/engine/gasless/Webhook.tsx @@ -0,0 +1,77 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { useEffect, useState } from "react"; + +// This says Webhook, but it's actually just displaying a dummy webhook + +interface WebhookData { + queueId?: string; + status?: string; +} + +export function Webhook({ queueId }: { queueId: string }) { + const [data, setData] = useState(null); + const [loading, setLoading] = useState(false); + + useEffect(() => { + if (!queueId) return; + + const fetchData = async () => { + try { + const response = await fetch(`/api/claimTo?queueId=${queueId}`); + const jsonData = await response.json(); + setData(jsonData); + + // Continue polling if not in a final state + if (jsonData.status !== "Mined" && jsonData.status !== "error") { + setTimeout(fetchData, 1500); // Match the backend polling interval + } + } catch (error) { + console.error("Error fetching data:", error); + } + }; + + setLoading(true); + fetchData(); + + // Cleanup polling on unmount or queueId change + return () => { + setData(null); + setLoading(false); + }; + }, [queueId]); + + return ( + + + Webhook Response + {data?.status || "Initializing..."} + + +
+ {loading && !data ? ( +

Loading...

+ ) : ( +
+              
+                {JSON.stringify(
+                  {
+                    queueId: data?.queueId,
+                    status: data?.status,
+                  },
+                  null,
+                  2,
+                )}
+              
+            
+ )} +
+
+
+ ); +} diff --git a/apps/playground-web/src/components/engine/minting/TransactionResults.tsx b/apps/playground-web/src/components/engine/minting/TransactionResults.tsx new file mode 100644 index 00000000000..4576c300481 --- /dev/null +++ b/apps/playground-web/src/components/engine/minting/TransactionResults.tsx @@ -0,0 +1,276 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardFooter, + CardHeader, +} from "@/components/ui/card"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import type React from "react"; +import { useState } from "react"; +import { format } from "timeago.js"; + +interface ClaimTransactionResults { + queueId: string; + status: "Queued" | "Sent" | "Mined" | "error"; + transactionHash?: string; + blockExplorerUrl?: string; + errorMessage: "Error" | undefined; + toAddress: string; + amount: string; + timestamp?: number; + chainId: number; + network: "Ethereum" | "Base Sep" | "OP Sep"; +} + +interface ClaimTransactionResultsProps { + results: ClaimTransactionResults[]; +} +// I did have one component of this, but it was causing weird queuing issues when shared among multiple components. So just created one for each instead. +export function ClaimTransactionResults({ + results, +}: ClaimTransactionResultsProps) { + const [currentPage, setCurrentPage] = useState(1); + const [showLeftGradient, setShowLeftGradient] = useState(false); + const [showRightGradient, setShowRightGradient] = useState(true); + const itemsPerPage = 2; + // Added dummy transactions so the table doesn't look empty. + const dummyTransaction1: ClaimTransactionResults = { + queueId: "0x1234567890abcdef", + status: "Mined", + transactionHash: "0xabcdef1234567890", + blockExplorerUrl: "https://etherscan.io/tx/0xabcdef1234567890", + toAddress: "0x1234567890abcdef", + amount: "1.0", + timestamp: Date.now() - 15 * 60 * 1000, + chainId: 1, + network: "Ethereum", + errorMessage: undefined, + }; + + const dummyTransaction2: ClaimTransactionResults = { + queueId: "0x9876543210fedcba", + status: "Mined", + transactionHash: "0x1234567890abcdef", + blockExplorerUrl: "https://etherscan.io/tx/0x1234567890abcdef", + toAddress: "0xabcdef1234567890", + amount: "0.5", + timestamp: Date.now() - 30 * 60 * 1000, + chainId: 1, + network: "Base Sep", + errorMessage: undefined, + }; + + const sortedResults = [...results].reverse(); + const sortedResultsWithDummy = [ + ...sortedResults, + dummyTransaction1, + dummyTransaction2, + ]; + + const indexOfLastItem = currentPage * itemsPerPage; + const indexOfFirstItem = indexOfLastItem - itemsPerPage; + const currentItems = sortedResultsWithDummy.slice( + indexOfFirstItem, + indexOfLastItem, + ); + const totalPages = Math.ceil(sortedResultsWithDummy.length / itemsPerPage); + + const handleNextPage = () => { + setCurrentPage((prev) => Math.min(prev + 1, totalPages)); + }; + + const handlePrevPage = () => { + setCurrentPage((prev) => Math.max(prev - 1, 1)); + }; + + const getDisplayStatus = (result: ClaimTransactionResults) => { + if (result.status === "Mined" && !result.transactionHash) { + return "Pending"; + } + return result.status; + }; + + const getStatusColor = (status: string) => { + switch (status) { + case "Mined": + return "bg-green-500/20 text-green-400"; + case "Queued": + case "Pending": + return "bg-yellow-500/20 text-yellow-400"; + default: + return "bg-red-500/20 text-red-400"; + } + }; + + const handleScroll = (e: React.UIEvent) => { + const target = e.currentTarget; + const isAtStart = target.scrollLeft === 0; + const isAtEnd = + target.scrollLeft + target.clientWidth >= target.scrollWidth - 1; // -1 for rounding errors + + setShowLeftGradient(!isAtStart); + setShowRightGradient(!isAtEnd); + }; + + return ( + + +

+ Transaction Results +

+ + Last 24 hours • {sortedResultsWithDummy.length} transactions + +
+ +
+ + + + Queue ID + Network + From + Queued + Status + Tx Hash + + + + {currentItems.map((result, index) => ( + + + {result.queueId + ? `${result.queueId.substring(0, 6)}...${result.queueId.substring( + result.queueId.length - 4, + )}` + : "----"} + + + + {result.network === "Base Sep" && ( + Base + )} + {result.network === "OP Sep" && ( + Optimism Sep + )} + {result.network === "Ethereum" && ( + Ethereum + )} + {result.network} + + + + {(() => { + if (!result.toAddress) return "----"; + + const addressDisplay = `${result.toAddress.substring(0, 6)}...${result.toAddress.substring( + result.toAddress.length - 4, + )}`; + // Keeping OP here for consistency. Will be adding a component for Optimism soon. + const getExplorerUrl = () => { + switch (result.network) { + case "Base Sep": + return `https://base-sepolia.blockscout.com/address/${result.toAddress}?tab=tokens`; + case "OP Sep": + return `https://optimism-sepolia.blockscout.com/address/${result.toAddress}?tab=tokens`; + case "Ethereum": + return `https://etherscan.io/address/${result.toAddress}?tab=tokens`; + default: + return null; + } + }; + + const explorerUrl = getExplorerUrl(); + + return explorerUrl ? ( + + {addressDisplay} + + ) : ( + addressDisplay + ); + })()} + + + {result.timestamp ? format(result.timestamp) : "Just now"} + + + + {getDisplayStatus(result)} + + + + {result.transactionHash && result.blockExplorerUrl ? ( + + {`${result.transactionHash.substring(0, 6)}...${result.transactionHash.substring( + result.transactionHash.length - 4, + )}`} + + ) : result.errorMessage ? ( + + {result.errorMessage} + + ) : ( + "----" + )} + + + ))} + +
+
+ {showLeftGradient && ( +
+ )} + {showRightGradient && ( +
+ )} + + + + + Page {currentPage} of {totalPages} + + + + + ); +} diff --git a/apps/playground-web/src/components/engine/minting/erc1155-mint-to.tsx b/apps/playground-web/src/components/engine/minting/erc1155-mint-to.tsx new file mode 100644 index 00000000000..92d33956fac --- /dev/null +++ b/apps/playground-web/src/components/engine/minting/erc1155-mint-to.tsx @@ -0,0 +1,301 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { THIRDWEB_CLIENT } from "@/lib/client"; +import { useState } from "react"; +import { baseSepolia } from "thirdweb/chains"; +import { ConnectButton, useActiveAccount } from "thirdweb/react"; +import { upload } from "thirdweb/storage"; +import { ClaimTransactionResults as ClaimTransactionResultsComponent } from "./TransactionResults"; + +interface ClaimTransactionResults { + queueId: string; + status: "Queued" | "Sent" | "Mined" | "error"; + transactionHash?: string; + blockExplorerUrl?: string; + errorMessage: "Error" | undefined; + toAddress: string; + amount: string; + timestamp?: number; + chainId: number; + network: "Ethereum" | "Base Sep" | "OP Sep"; +} +// Wasn't sure if this was needed, but added just in case. +const resolveIpfsUrl = (ipfsUrl: string) => { + if (!ipfsUrl) return ""; + if (ipfsUrl.startsWith("ipfs://")) { + return ipfsUrl.replace("ipfs://", "https://ipfs.io/ipfs/"); + } + return ipfsUrl; +}; + +export function ERC1155MintTo() { + const [isSubmitting, setIsSubmitting] = useState(false); + const [results, setResults] = useState([]); + + const [name, setName] = useState(""); + const [description, setDescription] = useState(""); + const [image, setImage] = useState(""); + const [supply, setSupply] = useState("1"); + const [imageFile, setImageFile] = useState(null); + const [isUploading, setIsUploading] = useState(false); + + const account = useActiveAccount(); + + const pollTransactionStatus = async (queueId: string) => { + const pollInterval = setInterval(async () => { + try { + const response = await fetch( + `/api/transaction-status?queueId=${queueId}`, + ); + const status = await response.json(); + + setResults((prevResults) => + prevResults.map((result) => + result.queueId === queueId + ? { + ...result, + ...status, + status: status.status === "mined" ? "Mined" : status.status, + } + : result, + ), + ); + + if (status.status === "Mined" || status.status === "error") { + clearInterval(pollInterval); + } + } catch (error) { + console.error("Error polling status:", error); + clearInterval(pollInterval); + } + }, 2000); + + setTimeout(() => clearInterval(pollInterval), 5 * 60 * 1000); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!account || !name || !description || !image || !supply) { + alert("Please fill in all fields."); + return; + } + + const supplyNum = Number.parseInt(supply); + if (Number.isNaN(supplyNum) || supplyNum < 1) { + alert("Supply must be a positive number."); + return; + } + + setIsSubmitting(true); + + try { + const response = await fetch("/api/mintTo", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + receiver: account.address, + metadataWithSupply: { + metadata: { + name, + description, + image, + }, + supply, + }, + }), + }); + + if (!response.ok) { + throw new Error("Network response was not ok"); + } + + const result = await response.json(); + + // Add the initial queued transaction to results + setResults((prevResults) => [...prevResults, result]); + + // Start polling for status updates + pollTransactionStatus(result.queueId); + } catch (error) { + console.error("Error:", error); + setResults([ + { + queueId: "", + status: "error", + errorMessage: "Error", + toAddress: "", + amount: "", + chainId: 84532, + network: "Base Sep", + }, + ]); + } finally { + setIsSubmitting(false); + } + }; + + const handleImageUpload = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + setIsUploading(true); + try { + const uploadResult = await upload({ + client: THIRDWEB_CLIENT, + files: [file], + }); + setImage(uploadResult); + setImageFile(file); + } catch (error) { + console.error("Error uploading file:", error); + alert("Error uploading file"); + } finally { + setIsUploading(false); + } + }; + + return ( +
+
+ {/* Form Section */} +
+ + {account && ( +
+
+
+ + +
+
+
+ + setName(e.target.value)} + required + /> +
+
+ + setDescription(e.target.value)} + required + /> +
+
+
+
+ +
+ + {imageFile && ( +
+ Selected: {imageFile.name} +
+ )} + {isUploading && ( +
+ Uploading... +
+ )} +
+
+
+ + setSupply(e.target.value)} + required + /> +
+
+
+ +

+ thirdweb Engine Playground{" "} + + Minting Contract + +

+
+ )} +
+ + {/* Image Preview Section */} + {account && ( +
+ {image ? ( + NFT Preview { + console.error("Error loading image:", image); + const target = e.target as HTMLImageElement; + target.src = + 'data:image/svg+xml,'; + }} + /> + ) : ( +
+

+ Upload an image to see preview +

+
+ )} + {name && ( +
+

{name}

+ {description && ( +

+ {description} +

+ )} +
+ )} +
+ )} +
+ +
+ ); +} diff --git a/apps/playground-web/src/components/ui/card.tsx b/apps/playground-web/src/components/ui/card.tsx new file mode 100644 index 00000000000..5a90768a118 --- /dev/null +++ b/apps/playground-web/src/components/ui/card.tsx @@ -0,0 +1,86 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +Card.displayName = "Card"; + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardHeader.displayName = "CardHeader"; + +const CardTitle = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardTitle.displayName = "CardTitle"; + +const CardDescription = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardDescription.displayName = "CardDescription"; + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardContent.displayName = "CardContent"; + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardFooter.displayName = "CardFooter"; + +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardDescription, + CardContent, +}; diff --git a/apps/playground-web/src/components/ui/table.tsx b/apps/playground-web/src/components/ui/table.tsx new file mode 100644 index 00000000000..14567a0d653 --- /dev/null +++ b/apps/playground-web/src/components/ui/table.tsx @@ -0,0 +1,117 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)); +Table.displayName = "Table"; + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableHeader.displayName = "TableHeader"; + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableBody.displayName = "TableBody"; + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className, + )} + {...props} + /> +)); +TableFooter.displayName = "TableFooter"; + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableRow.displayName = "TableRow"; + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableHead.displayName = "TableHead"; + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableCell.displayName = "TableCell"; + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableCaption.displayName = "TableCaption"; + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ed231dd906f..314f7aef501 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -139,7 +139,7 @@ importers: version: 1.1.4(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(types-react-dom@19.0.0-rc.1)(types-react@19.0.0-rc.1) '@sentry/nextjs': specifier: 8.40.0 - version: 8.40.0(@opentelemetry/core@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.54.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.28.0(@opentelemetry/api@1.9.0))(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + version: 8.40.0(@opentelemetry/core@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.54.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.28.0(@opentelemetry/api@1.9.0))(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) '@shazow/whatsabi': specifier: ^0.17.0 version: 0.17.0(@noble/hashes@1.6.1)(typescript@5.7.2)(zod@3.23.8) @@ -154,7 +154,7 @@ importers: version: link:../../packages/service-utils '@vercel/functions': specifier: ^1.4.2 - version: 1.5.0(@aws-sdk/credential-provider-web-identity@3.696.0(@aws-sdk/client-sts@3.699.0)) + version: 1.5.0(@aws-sdk/credential-provider-web-identity@3.696.0) '@vercel/og': specifier: ^0.6.4 version: 0.6.4 @@ -283,7 +283,7 @@ importers: version: 2.5.5 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2))) + version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2))) thirdweb: specifier: workspace:* version: link:../../packages/thirdweb @@ -332,7 +332,7 @@ importers: version: 8.4.5(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)) '@storybook/nextjs': specifier: 8.4.5 - version: 8.4.5(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(type-fest@4.28.1)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + version: 8.4.5(@swc/core@1.9.3)(esbuild@0.24.0)(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(type-fest@4.28.1)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) '@storybook/react': specifier: 8.4.5 version: 8.4.5(@storybook/test@8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)))(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2) @@ -380,7 +380,7 @@ importers: version: 10.4.20(postcss@8.4.49) checkly: specifier: ^4.11.0 - version: 4.11.0(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(bufferutil@4.0.8)(typescript@5.7.2)(utf-8-validate@5.0.10) + version: 4.11.0(@swc/core@1.9.3)(@types/node@22.10.0)(bufferutil@4.0.8)(typescript@5.7.2)(utf-8-validate@5.0.10) eslint: specifier: 8.57.0 version: 8.57.0 @@ -407,7 +407,7 @@ importers: version: 8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10) tailwindcss: specifier: 3.4.15 - version: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)) + version: 3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)) typescript: specifier: 5.7.2 version: 5.7.2 @@ -459,6 +459,9 @@ importers: '@tanstack/react-query': specifier: 5.61.4 version: 5.61.4(react@19.0.0-rc-69d4b800-20241021) + '@thirdweb-dev/engine': + specifier: ^0.0.16 + version: 0.0.16 class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -498,6 +501,9 @@ importers: thirdweb: specifier: workspace:* version: link:../../packages/thirdweb + timeago.js: + specifier: ^4.0.2 + version: 4.0.2 use-debounce: specifier: ^10.0.4 version: 10.0.4(react@19.0.0-rc-69d4b800-20241021) @@ -525,10 +531,10 @@ importers: version: 8.4.49 tailwindcss: specifier: 3.4.15 - version: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)) + version: 3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)) tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2))) + version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2))) typescript: specifier: 5.7.2 version: 5.7.2 @@ -540,13 +546,13 @@ importers: version: 1.0.5(react@19.0.0-rc-69d4b800-20241021) '@mdx-js/loader': specifier: ^2.3.0 - version: 2.3.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))) + version: 2.3.0(webpack@5.96.1) '@mdx-js/react': specifier: ^2.3.0 version: 2.3.0(react@19.0.0-rc-69d4b800-20241021) '@next/mdx': specifier: 15.0.3 - version: 15.0.3(@mdx-js/loader@2.3.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))))(@mdx-js/react@2.3.0(react@19.0.0-rc-69d4b800-20241021)) + version: 15.0.3(@mdx-js/loader@2.3.0(webpack@5.96.1))(@mdx-js/react@2.3.0(react@19.0.0-rc-69d4b800-20241021)) '@radix-ui/react-dialog': specifier: 1.1.2 version: 1.1.2(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(types-react-dom@19.0.0-rc.1)(types-react@19.0.0-rc.1) @@ -627,7 +633,7 @@ importers: version: 2.5.5 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2))) + version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2))) thirdweb: specifier: workspace:* version: link:../../packages/thirdweb @@ -685,7 +691,7 @@ importers: version: 1.2.4 eslint-plugin-tailwindcss: specifier: ^3.17.5 - version: 3.17.5(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2))) + version: 3.17.5(tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2))) next-sitemap: specifier: ^4.2.3 version: 4.2.3(next@15.0.3(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)) @@ -694,7 +700,7 @@ importers: version: 8.4.49 tailwindcss: specifier: 3.4.15 - version: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)) + version: 3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)) tsx: specifier: 4.19.2 version: 4.19.2 @@ -763,7 +769,7 @@ importers: version: 2.5.5 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2))) + version: 1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2))) thirdweb: specifier: workspace:* version: link:../../packages/thirdweb @@ -812,7 +818,7 @@ importers: version: 6.0.1(jiti@2.4.0)(postcss@8.4.49)(tsx@4.19.2)(yaml@2.6.1) tailwindcss: specifier: 3.4.15 - version: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)) + version: 3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)) typescript: specifier: 5.7.2 version: 5.7.2 @@ -5367,9 +5373,6 @@ packages: '@swc/helpers@0.5.13': resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@swc/types@0.1.17': resolution: {integrity: sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==} @@ -5429,6 +5432,9 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' + '@thirdweb-dev/engine@0.0.16': + resolution: {integrity: sha512-UJ+MIdKYGBhUUEOkbYJy3T7AAkdIRh3xJ7dtilqgnqP6IvIloTZ23jctBWQ3e5kuQFuK88DmwhMhzZSGbXjJTg==} + '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} @@ -12815,6 +12821,9 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + timeago.js@4.0.2: + resolution: {integrity: sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w==} + timers-browserify@2.0.12: resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} engines: {node: '>=0.6.0'} @@ -16977,11 +16986,11 @@ snapshots: react: 19.0.0-rc-69d4b800-20241021 react-dom: 19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021) - '@mdx-js/loader@2.3.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15)))': + '@mdx-js/loader@2.3.0(webpack@5.96.1)': dependencies: '@mdx-js/mdx': 2.3.0 source-map: 0.7.4 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15)) + webpack: 5.96.1 transitivePeerDependencies: - supports-color @@ -17121,11 +17130,11 @@ snapshots: dependencies: fast-glob: 3.3.1 - '@next/mdx@15.0.3(@mdx-js/loader@2.3.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))))(@mdx-js/react@2.3.0(react@19.0.0-rc-69d4b800-20241021))': + '@next/mdx@15.0.3(@mdx-js/loader@2.3.0(webpack@5.96.1))(@mdx-js/react@2.3.0(react@19.0.0-rc-69d4b800-20241021))': dependencies: source-map: 0.7.4 optionalDependencies: - '@mdx-js/loader': 2.3.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))) + '@mdx-js/loader': 2.3.0(webpack@5.96.1) '@mdx-js/react': 2.3.0(react@19.0.0-rc-69d4b800-20241021) '@next/swc-darwin-arm64@15.0.3': @@ -17283,7 +17292,7 @@ snapshots: widest-line: 3.1.0 wrap-ansi: 7.0.0 - '@oclif/core@2.8.11(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)': + '@oclif/core@2.8.11(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2)': dependencies: '@types/cli-progress': 3.11.6 ansi-escapes: 4.3.2 @@ -17309,7 +17318,7 @@ snapshots: strip-ansi: 6.0.1 supports-color: 8.1.1 supports-hyperlinks: 2.3.0 - ts-node: 10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2) + ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2) tslib: 2.8.1 widest-line: 3.1.0 wordwrap: 1.0.0 @@ -17347,10 +17356,10 @@ snapshots: dependencies: '@oclif/core': 1.26.2 - '@oclif/plugin-not-found@2.3.23(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)': + '@oclif/plugin-not-found@2.3.23(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2)': dependencies: '@oclif/color': 1.0.13 - '@oclif/core': 2.8.11(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2) + '@oclif/core': 2.8.11(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2) fast-levenshtein: 3.0.0 lodash: 4.17.21 transitivePeerDependencies: @@ -17375,9 +17384,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@oclif/plugin-warn-if-update-available@2.0.24(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)': + '@oclif/plugin-warn-if-update-available@2.0.24(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2)': dependencies: - '@oclif/core': 2.8.11(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2) + '@oclif/core': 2.8.11(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2) chalk: 4.1.2 debug: 4.3.7(supports-color@8.1.1) fs-extra: 9.1.0 @@ -17768,7 +17777,7 @@ snapshots: dependencies: playwright: 1.49.0 - '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.14.2)(type-fest@4.28.1)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.14.2)(type-fest@4.28.1)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0))': dependencies: ansi-html: 0.0.9 core-js-pure: 3.39.0 @@ -17778,7 +17787,7 @@ snapshots: react-refresh: 0.14.2 schema-utils: 4.2.0 source-map: 0.7.4 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) optionalDependencies: type-fest: 4.28.1 webpack-hot-middleware: 2.26.1 @@ -18786,7 +18795,7 @@ snapshots: dependencies: '@sentry/types': 8.40.0 - '@sentry/nextjs@8.40.0(@opentelemetry/core@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.54.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.28.0(@opentelemetry/api@1.9.0))(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0))': + '@sentry/nextjs@8.40.0(@opentelemetry/core@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.54.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.28.0(@opentelemetry/api@1.9.0))(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0))': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation-http': 0.53.0(@opentelemetry/api@1.9.0) @@ -18799,7 +18808,7 @@ snapshots: '@sentry/react': 8.40.0(react@19.0.0-rc-69d4b800-20241021) '@sentry/types': 8.40.0 '@sentry/vercel-edge': 8.40.0 - '@sentry/webpack-plugin': 2.22.6(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + '@sentry/webpack-plugin': 2.22.6(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) chalk: 3.0.0 next: 15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021) resolve: 1.22.8 @@ -18881,12 +18890,12 @@ snapshots: '@sentry/core': 8.40.0 '@sentry/types': 8.40.0 - '@sentry/webpack-plugin@2.22.6(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0))': + '@sentry/webpack-plugin@2.22.6(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0))': dependencies: '@sentry/bundler-plugin-core': 2.22.6 unplugin: 1.0.1 uuid: 9.0.1 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) transitivePeerDependencies: - encoding - supports-color @@ -19621,7 +19630,7 @@ snapshots: ts-dedent: 2.2.0 vite: 6.0.0(@types/node@22.10.0)(jiti@2.4.0)(lightningcss@1.28.2)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) - '@storybook/builder-webpack5@8.4.5(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2)': + '@storybook/builder-webpack5@8.4.5(@swc/core@1.9.3)(esbuild@0.24.0)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2)': dependencies: '@storybook/core-webpack': 8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)) '@types/node': 22.10.0 @@ -19630,23 +19639,23 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.4.1 constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + css-loader: 6.11.0(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) es-module-lexer: 1.5.4 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) - html-webpack-plugin: 5.6.3(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) + html-webpack-plugin: 5.6.3(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) magic-string: 0.30.14 path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 storybook: 8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10) - style-loader: 3.3.4(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) - terser-webpack-plugin: 5.3.10(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + style-loader: 3.3.4(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) + terser-webpack-plugin: 5.3.10(@swc/core@1.9.3)(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) ts-dedent: 2.2.0 url: 0.11.4 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) - webpack-dev-middleware: 6.1.3(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) + webpack-dev-middleware: 6.1.3(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.6.2 optionalDependencies: @@ -19758,7 +19767,7 @@ snapshots: dependencies: storybook: 8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10) - '@storybook/nextjs@8.4.5(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(type-fest@4.28.1)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0))': + '@storybook/nextjs@8.4.5(@swc/core@1.9.3)(esbuild@0.24.0)(next@15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021))(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(type-fest@4.28.1)(typescript@5.7.2)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) @@ -19773,31 +19782,31 @@ snapshots: '@babel/preset-react': 7.25.9(@babel/core@7.26.0) '@babel/preset-typescript': 7.26.0(@babel/core@7.26.0) '@babel/runtime': 7.26.0 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@4.28.1)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) - '@storybook/builder-webpack5': 8.4.5(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2) - '@storybook/preset-react-webpack': 8.4.5(@storybook/test@8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)))(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@4.28.1)(webpack-hot-middleware@2.26.1)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) + '@storybook/builder-webpack5': 8.4.5(@swc/core@1.9.3)(esbuild@0.24.0)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2) + '@storybook/preset-react-webpack': 8.4.5(@storybook/test@8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)))(@swc/core@1.9.3)(esbuild@0.24.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2) '@storybook/react': 8.4.5(@storybook/test@8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)))(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2) '@storybook/test': 8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)) '@types/node': 22.10.0 '@types/semver': 7.5.8 - babel-loader: 9.2.1(@babel/core@7.26.0)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) - css-loader: 6.11.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + babel-loader: 9.2.1(@babel/core@7.26.0)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) + css-loader: 6.11.0(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) find-up: 5.0.0 image-size: 1.1.1 loader-utils: 3.3.1 next: 15.0.3(@babel/core@7.26.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.49.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021) - node-polyfill-webpack-plugin: 2.0.1(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + node-polyfill-webpack-plugin: 2.0.1(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) pnp-webpack-plugin: 1.7.0(typescript@5.7.2) postcss: 8.4.49 - postcss-loader: 8.1.1(postcss@8.4.49)(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + postcss-loader: 8.1.1(postcss@8.4.49)(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) react: 19.0.0-rc-69d4b800-20241021 react-dom: 19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021) react-refresh: 0.14.2 resolve-url-loader: 5.0.0 - sass-loader: 13.3.3(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + sass-loader: 13.3.3(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) semver: 7.6.3 storybook: 8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10) - style-loader: 3.3.4(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + style-loader: 3.3.4(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) styled-jsx: 5.1.6(@babel/core@7.26.0)(react@19.0.0-rc-69d4b800-20241021) ts-dedent: 2.2.0 tsconfig-paths: 4.2.0 @@ -19805,7 +19814,7 @@ snapshots: optionalDependencies: sharp: 0.33.5 typescript: 5.7.2 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) transitivePeerDependencies: - '@rspack/core' - '@swc/core' @@ -19825,11 +19834,11 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@8.4.5(@storybook/test@8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)))(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2)': + '@storybook/preset-react-webpack@8.4.5(@storybook/test@8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)))(@swc/core@1.9.3)(esbuild@0.24.0)(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2)': dependencies: '@storybook/core-webpack': 8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)) '@storybook/react': 8.4.5(@storybook/test@8.4.5(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10)))(react-dom@19.0.0-rc-69d4b800-20241021(react@19.0.0-rc-69d4b800-20241021))(react@19.0.0-rc-69d4b800-20241021)(storybook@8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10))(typescript@5.7.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) '@types/node': 22.10.0 '@types/semver': 7.5.8 find-up: 5.0.0 @@ -19841,7 +19850,7 @@ snapshots: semver: 7.6.3 storybook: 8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10) tsconfig-paths: 4.2.0 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -19860,7 +19869,7 @@ snapshots: dependencies: storybook: 8.4.5(bufferutil@4.0.8)(prettier@3.4.1)(utf-8-validate@5.0.10) - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0))': dependencies: debug: 4.3.7(supports-color@8.1.1) endent: 2.1.0 @@ -19870,7 +19879,7 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.7.2) tslib: 2.8.1 typescript: 5.7.2 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) transitivePeerDependencies: - supports-color @@ -20358,7 +20367,7 @@ snapshots: '@swc/core-win32-x64-msvc@1.9.3': optional: true - '@swc/core@1.9.3(@swc/helpers@0.5.15)': + '@swc/core@1.9.3': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.17 @@ -20373,7 +20382,6 @@ snapshots: '@swc/core-win32-arm64-msvc': 1.9.3 '@swc/core-win32-ia32-msvc': 1.9.3 '@swc/core-win32-x64-msvc': 1.9.3 - '@swc/helpers': 0.5.15 optional: true '@swc/counter@0.1.3': {} @@ -20382,11 +20390,6 @@ snapshots: dependencies: tslib: 2.8.1 - '@swc/helpers@0.5.15': - dependencies: - tslib: 2.8.1 - optional: true - '@swc/types@0.1.17': dependencies: '@swc/counter': 0.1.3 @@ -20455,6 +20458,8 @@ snapshots: dependencies: '@testing-library/dom': 10.4.0 + '@thirdweb-dev/engine@0.0.16': {} + '@tootallnate/quickjs-emscripten@0.23.0': {} '@tree-sitter-grammars/tree-sitter-yaml@0.6.1(tree-sitter@0.21.1)': @@ -20899,7 +20904,7 @@ snapshots: '@urql/core': 5.0.8(graphql@16.9.0) wonka: 6.3.4 - '@vercel/functions@1.5.0(@aws-sdk/credential-provider-web-identity@3.696.0(@aws-sdk/client-sts@3.699.0))': + '@vercel/functions@1.5.0(@aws-sdk/credential-provider-web-identity@3.696.0)': optionalDependencies: '@aws-sdk/credential-provider-web-identity': 3.696.0(@aws-sdk/client-sts@3.699.0) @@ -21783,12 +21788,12 @@ snapshots: transitivePeerDependencies: - supports-color - babel-loader@9.2.1(@babel/core@7.26.0)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + babel-loader@9.2.1(@babel/core@7.26.0)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: '@babel/core': 7.26.0 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) babel-plugin-istanbul@6.1.1: dependencies: @@ -22249,13 +22254,13 @@ snapshots: check-error@2.1.1: {} - checkly@4.11.0(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(bufferutil@4.0.8)(typescript@5.7.2)(utf-8-validate@5.0.10): + checkly@4.11.0(@swc/core@1.9.3)(@types/node@22.10.0)(bufferutil@4.0.8)(typescript@5.7.2)(utf-8-validate@5.0.10): dependencies: - '@oclif/core': 2.8.11(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2) + '@oclif/core': 2.8.11(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2) '@oclif/plugin-help': 5.1.20 - '@oclif/plugin-not-found': 2.3.23(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2) + '@oclif/plugin-not-found': 2.3.23(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2) '@oclif/plugin-plugins': 5.4.4 - '@oclif/plugin-warn-if-update-available': 2.0.24(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2) + '@oclif/plugin-warn-if-update-available': 2.0.24(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2) '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.2) acorn: 8.8.1 acorn-walk: 8.2.0 @@ -22701,7 +22706,7 @@ snapshots: css-gradient-parser@0.0.16: {} - css-loader@6.11.0(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + css-loader@6.11.0(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: icss-utils: 5.1.0(postcss@8.4.49) postcss: 8.4.49 @@ -22712,7 +22717,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) css-select@4.3.0: dependencies: @@ -23382,8 +23387,8 @@ snapshots: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.7.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) eslint-plugin-react: 7.37.2(eslint@8.57.0) eslint-plugin-react-hooks: 5.0.0(eslint@8.57.0) @@ -23402,19 +23407,19 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7(supports-color@8.1.1) enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node @@ -23442,18 +23447,18 @@ snapshots: - bluebird - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.7.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -23464,7 +23469,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -23573,11 +23578,11 @@ snapshots: eslint-plugin-svg-jsx@1.2.4: {} - eslint-plugin-tailwindcss@3.17.5(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2))): + eslint-plugin-tailwindcss@3.17.5(tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2))): dependencies: fast-glob: 3.3.2 postcss: 8.4.49 - tailwindcss: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)) + tailwindcss: 3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)) eslint-scope@5.1.1: dependencies: @@ -24255,7 +24260,7 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: '@babel/code-frame': 7.26.2 chalk: 4.1.2 @@ -24270,7 +24275,7 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.7.2 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) form-data-encoder@2.1.4: {} @@ -24741,7 +24746,7 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.3(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + html-webpack-plugin@5.6.3(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -24749,7 +24754,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) htmlparser2@3.10.1: dependencies: @@ -27233,7 +27238,7 @@ snapshots: node-int64@0.4.0: {} - node-polyfill-webpack-plugin@2.0.1(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + node-polyfill-webpack-plugin@2.0.1(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -27260,7 +27265,7 @@ snapshots: url: 0.11.4 util: 0.12.5 vm-browserify: 1.1.2 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) node-releases@2.0.18: {} @@ -27883,13 +27888,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.49 - postcss-load-config@4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)): + postcss-load-config@4.0.2(postcss@8.4.49)(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)): dependencies: lilconfig: 3.1.2 yaml: 2.6.1 optionalDependencies: postcss: 8.4.49 - ts-node: 10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2) + ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2) postcss-load-config@6.0.1(jiti@2.4.0)(postcss@8.4.49)(tsx@4.19.2)(yaml@2.6.1): dependencies: @@ -27900,14 +27905,14 @@ snapshots: tsx: 4.19.2 yaml: 2.6.1 - postcss-loader@8.1.1(postcss@8.4.49)(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + postcss-loader@8.1.1(postcss@8.4.49)(typescript@5.7.2)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: cosmiconfig: 9.0.0(typescript@5.7.2) jiti: 1.21.6 postcss: 8.4.49 semver: 7.6.3 optionalDependencies: - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) transitivePeerDependencies: - typescript @@ -29064,10 +29069,10 @@ snapshots: safer-buffer@2.1.2: {} - sass-loader@13.3.3(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + sass-loader@13.3.3(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: neo-async: 2.6.2 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) satori@0.12.0: dependencies: @@ -29592,9 +29597,9 @@ snapshots: structured-headers@0.4.1: {} - style-loader@3.3.4(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + style-loader@3.3.4(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) style-to-object@0.4.4: dependencies: @@ -29739,11 +29744,11 @@ snapshots: tailwind-merge@2.5.5: {} - tailwindcss-animate@1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2))): + tailwindcss-animate@1.0.7(tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2))): dependencies: - tailwindcss: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)) + tailwindcss: 3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)) - tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)): + tailwindcss@3.4.15(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -29762,7 +29767,7 @@ snapshots: postcss: 8.4.49 postcss-import: 15.1.0(postcss@8.4.49) postcss-js: 4.0.1(postcss@8.4.49) - postcss-load-config: 4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2)) + postcss-load-config: 4.0.2(postcss@8.4.49)(ts-node@10.9.2(@types/node@22.10.0)(typescript@5.7.2)) postcss-nested: 6.2.0(postcss@8.4.49) postcss-selector-parser: 6.1.2 resolve: 1.22.8 @@ -29824,29 +29829,18 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.10(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + terser-webpack-plugin@5.3.10(@swc/core@1.9.3)(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.36.0 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) optionalDependencies: - '@swc/core': 1.9.3(@swc/helpers@0.5.15) + '@swc/core': 1.9.3 esbuild: 0.24.0 - terser-webpack-plugin@5.3.10(@swc/core@1.9.3(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))): - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.36.0 - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15)) - optionalDependencies: - '@swc/core': 1.9.3(@swc/helpers@0.5.15) - terser-webpack-plugin@5.3.10(webpack@5.96.1): dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -29904,6 +29898,8 @@ snapshots: through@2.3.8: {} + timeago.js@4.0.2: {} + timers-browserify@2.0.12: dependencies: setimmediate: 1.0.5 @@ -29982,7 +29978,7 @@ snapshots: ts-mixer@6.0.4: {} - ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.0)(typescript@5.7.2): + ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.0)(typescript@5.7.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -30000,7 +29996,7 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.9.3(@swc/helpers@0.5.15) + '@swc/core': 1.9.3 ts-pnp@1.2.0(typescript@5.7.2): optionalDependencies: @@ -30754,7 +30750,7 @@ snapshots: - bufferutil - utf-8-validate - webpack-dev-middleware@6.1.3(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)): + webpack-dev-middleware@6.1.3(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -30762,7 +30758,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0) + webpack: 5.96.1(@swc/core@1.9.3)(esbuild@0.24.0) webpack-hot-middleware@2.26.1: dependencies: @@ -30806,37 +30802,7 @@ snapshots: - esbuild - uglify-js - webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15)): - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.6 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.14.0 - browserslist: 4.24.2 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.17.1 - es-module-lexer: 1.5.4 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.9.3(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))) - watchpack: 2.4.2 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0): + webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.6 @@ -30858,7 +30824,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(esbuild@0.24.0)) + terser-webpack-plugin: 5.3.10(@swc/core@1.9.3)(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.24.0)) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: diff --git a/turbo.json b/turbo.json index 310bbbd1796..735b2de5d6a 100644 --- a/turbo.json +++ b/turbo.json @@ -70,6 +70,7 @@ "dependsOn": ["^build", "thirdweb#typedoc"] }, "playground-web#build": { + "env": ["ENGINE_ACCESS_TOKEN", "ENGINE_BACKEND_WALLET", "ENGINE_URL"], "outputs": [".next/**", "!.next/cache/**"], "dependsOn": ["^build"] },