diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/examples/staking-sdk-nextjs/src/components/Stake.tsx b/examples/staking-sdk-nextjs/src/components/Stake.tsx index 8a0e73a..f4056c3 100644 --- a/examples/staking-sdk-nextjs/src/components/Stake.tsx +++ b/examples/staking-sdk-nextjs/src/components/Stake.tsx @@ -154,6 +154,36 @@ export function Stake() { > Stake Now + { + const fromUserAddress = await connectWallet(contract.chain); + if (!fromUserAddress) return; + + setIsLoading(true); + + const params = { + amount: "1", + fromChain: contract.chain.slug, + fromToken: contract.inputToken.symbol, + fromUserAddress, + toChain: contract.chain.slug, + toToken: contract.outputToken?.symbol, + toUserAddress: fromUserAddress, + type: "withdraw", + }; + setTransferParams(params); + + const quoteResponse = await swingSDK.getQuote(params); + + setQuote(quoteResponse); + setIsLoading(false); + }} + > + Withdraw + ); }) diff --git a/examples/swaps-api-nextjs-evm-gasless/.eslintrc.js b/examples/swaps-api-nextjs-evm-gasless/.eslintrc.js new file mode 100644 index 0000000..ea43de2 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/.eslintrc.js @@ -0,0 +1,8 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + extends: ["eslint-config-examples/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, +}; diff --git a/examples/swaps-api-nextjs-evm-gasless/.gitignore b/examples/swaps-api-nextjs-evm-gasless/.gitignore new file mode 100644 index 0000000..55175ef --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/.gitignore @@ -0,0 +1,32 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +# vercel +.vercel diff --git a/examples/swaps-api-nextjs-evm-gasless/README.md b/examples/swaps-api-nextjs-evm-gasless/README.md new file mode 100644 index 0000000..0598d33 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/README.md @@ -0,0 +1,370 @@ +# Gasless Cross-chain Swaps using the Swing API in Next.js + +This example demonstrates how to perform **gasless cross-chain transactions** using Swing's API, built with: + +- [@thirdweb-dev/react](https://portal.thirdweb.com/react) +- [@thirdweb-dev/sdk](https://portal.thirdweb.com/typescript) +- [Next.js App Router](https://nextjs.org) +- [Tailwind CSS](https://tailwindcss.com) + +## Demo + +View the live demo [https://swaps-api-nextjs-evm-gasless.vercel.app](https://swaps-api-nextjs-evm-gasless.vercel.app/) + +## Gasless Transactions Overview + +Gasless transactions allow users to perform cross-chain swaps without paying gas fees upfront. Instead of sending a traditional transaction, users sign an [EIP-712](https://eips.ethereum.org/EIPS/eip-712) typed data message that gets executed on their behalf. + +For more detailed information about gasless transactions, visit the [Swing Gasless Transactions Documentation](https://docs-git-feat-gasless-trans-update-swing-xyz.vercel.app/gasless-transactions). + +### Key Benefits: + +- No upfront gas fees for users +- Enhanced user experience +- Seamless cross-chain swaps +- EIP-712 signature-based execution + +## Swing Integration + +> The implementation of Swing's [Cross-chain API](https://developers.swing.xyz/reference/api) for gasless transactions can be found in [src/components/Swap.tsx](./src/components/Swap.tsx). + +This example demonstrates how you can perform gasless cross-chain transactions between different chains. The process for performing a gasless transaction includes: + +- Getting a [gasless quote](https://developers.swing.xyz/reference/api/cross-chain/1169f8cbb6937-request-a-transfer-quote) with `mode: "gasless"` +- Checking token allowance (if needed) +- Approving token spending (if needed) +- Sending a [gasless transaction](https://developers.swing.xyz/reference/api/cross-chain/d83d0d65028dc-send-transfer) with EIP-712 signature + +> For gasless transactions, real-time updates via the [status](https://developers.swing.xyz/reference/api/cross-chain/6b61efd1b798a-transfer-status) endpoint are essential for tracking transaction progress. + +## Getting started + +To get started with this template, first install the required npm dependencies: + +```bash +yarn install +``` + +Next, launch the development server by running the following command: + +```bash +yarn dev --filter=swaps-api-nextjs-evm-gasless +``` + +Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website. + +## Getting a Gasless Quote + +To perform a gasless swap, we first need to get a gasless quote from Swing's Cross-Chain API by including the **`mode: "gasless"`** parameter. + +URL: [https://swap.prod.swing.xyz/v0/transfer/quote](https://swap.prod.swing.xyz/v0/transfer/quote) + +**Parameters**: + +| Property | Example | Description | +| ------------------ | -------------------------------------------- | ------------------------------------------------------- | +| `tokenAmount` | 1000000000000000000 | Amount of the source token being sent (in wei for ETH). | +| `fromChain` | `base` | Source Chain slug | +| `fromUserAddress` | 0x018c15DA1239B84b08283799B89045CD476BBbBb | Sender's wallet address | +| `fromTokenAddress` | 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 | Source Token Address | +| `tokenSymbol` | `USDC` | Source Token slug | +| `toTokenAddress` | `0x3c499c542cef5e3811e1192ce70d8cc03d5c3359` | Destination Token Address | +| `toTokenSymbol` | `USDC` | Destination Token slug | +| `toChain` | `polygon` | Destination Chain slug | +| `toUserAddress` | 0x018c15DA1239B84b08283799B89045CD476BBbBb | Receiver's wallet address | +| `mode` | `gasless` | **Required for gasless transactions** | +| `projectId` | `replug` | [Your project's ID](https://platform.swing.xyz/) | + +Navigating to our `src/services/requests.ts` file, you will find our method for getting a gasless quote called `getQuoteRequest()`: + +```typescript +export const getQuoteRequest = async ( + queryParams: QuoteQueryParams, +): Promise => { + try { + const response = await axios.get( + `${baseUrl}/transfer/quote`, + { params: { ...queryParams, projectId, mode: "gasless", debug: true } }, + ); + return response.data; + } catch (error) { + console.error("Error fetching quote:", error); + throw error; + } +}; +``` + +The response provides gasless-compatible routes with fee structures optimized for signature-based execution. + +## Allowance and Approval (ERC-20 Tokens) + +For ERC-20 tokens, you may need to check and approve token spending before executing the gasless transaction. + +### Check Allowance + +URL: [https://swap.prod.swing.xyz/v0/transfer/allowance](https://swap.prod.swing.xyz/v0/transfer/allowance) + +```typescript +export const getAllowanceRequest = async ( + queryParams: AllowanceQueryParams, +): Promise => { + try { + const response = await axios.get( + `${baseUrl}/transfer/allowance`, + { params: { ...queryParams, projectId } }, + ); + return response.data; + } catch (error) { + console.error("Error fetching allowance:", error); + throw error; + } +}; +``` + +### Get Approval Transaction + +URL: [https://swap.prod.swing.xyz/v0/transfer/approve](https://swap.prod.swing.xyz/v0/transfer/approve) + +```typescript +export const getApproveRequest = async ( + queryParams: ApproveQueryParams, +): Promise => { + try { + const response = await axios.get( + `${baseUrl}/transfer/approve`, + { params: { ...queryParams, projectId } }, + ); + return response.data; + } catch (error) { + console.error("Error fetching approve transaction:", error); + throw error; + } +}; +``` + +## Sending a Gasless Transaction + +After getting a gasless quote and handling approvals, you'll send a gasless transaction to Swing's API. + +### Making a `/send` Request for Gasless + +The `/send` endpoint for gasless transactions returns EIP-712 typed data instead of regular transaction data: + +```typescript +export const sendTransactionRequest = async ( + payload: SendTransactionPayload, +): Promise => { + try { + const response = await axios.post( + `${baseUrl}/transfer/send`, + { ...payload, projectId, mode: "gasless" }, + { + headers: { + "Content-Type": "application/json", + }, + }, + ); + return response.data; + } catch (error) { + console.error("Error sending transaction:", error); + throw error; + } +}; +``` + +### EIP-712 Signature Flow + +For gasless transactions, instead of sending a regular transaction, you sign EIP-712 typed data: + +```typescript +// src/components/Swap.tsx + +const transfer = await sendTransactionRequest({ + fromChain: transferParams.fromChain, + fromTokenAddress: transferParams.fromTokenAddress, + fromUserAddress: transferParams.fromUserAddress, + tokenSymbol: transferParams.tokenSymbol, + toTokenAddress: transferParams.toTokenAddress!, + toChain: transferParams.toChain, + toTokenAmount: transferRoute.quote.amount, + toTokenSymbol: transferParams.toTokenSymbol!, + toUserAddress: transferParams.toUserAddress!, + tokenAmount: tokenAmount, + route: transferRoute.route, + type: "swap", +}); + +if (transfer?.tx.meta) { + // For gasless transactions, extract EIP-712 data from meta + const tx = JSON.stringify(transfer.tx); + const txInfo = JSON.parse(tx); + const txObj = txInfo.meta; + + const JAM_DOMAIN = txObj.domain; + const JAM_ORDER_TYPES = txObj.types; + const toSign = txObj.value; + + const types = { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { name: "chainId", type: "uint256" }, + { name: "verifyingContract", type: "address" }, + ], + ...JAM_ORDER_TYPES, + }; + + const message = toSign; + const msgParams = JSON.stringify({ + domain: JAM_DOMAIN, + primaryType: Object.keys(JAM_ORDER_TYPES)[0], + message, + types, + }); + + // Sign the EIP-712 typed data + const account = (window as any).ethereum.selectedAddress; + const signature = await(window as any).ethereum.request({ + method: "eth_signTypedData_v4", + params: [account, msgParams], + }); + + console.log("EIP-712 Signature:", signature); + + // Poll transaction status with the signature + pollTransactionStatus(transfer.id.toString(), signature); +} +``` + +## Complete Gasless Transaction Flow + +Here's the complete flow for a gasless transaction: + +```typescript +async function startTransfer() { + // 1. Switch to correct chain + const chainIdMap = { + polygon: "0x89", + base: "0x2105", + }; + + await window.ethereum.request({ + method: "wallet_switchEthereumChain", + params: [{ chainId: chainIdMap[transferParams.fromChain] }], + }); + + // 2. Check allowance (for ERC-20 tokens) + const checkAllowance = await getAllowanceRequest({ + bridge: transferRoute.quote.integration, + fromAddress: transferParams.fromUserAddress, + fromChain: transferParams.fromChain, + tokenAddress: transferParams.fromTokenAddress, + tokenSymbol: transferParams.tokenSymbol, + toChain: transferParams.toChain, + toTokenAddress: transferParams.toTokenAddress!, + toTokenSymbol: transferParams.toTokenSymbol!, + contractCall: false, + }); + + // 3. Approve if needed + if (Number(checkAllowance?.allowance || "0") <= 0) { + const getApprovalTxData = await getApproveRequest({ + tokenAmount: tokenAmount, + bridge: transferRoute.quote.integration, + fromAddress: transferParams.fromUserAddress, + fromChain: transferParams.fromChain, + tokenAddress: transferParams.fromTokenAddress, + tokenSymbol: transferParams.tokenSymbol, + toChain: transferParams.toChain, + toTokenAddress: transferParams.toTokenAddress!, + toTokenSymbol: transferParams.toTokenSymbol!, + contractCall: false, + }); + + const txData = { + data: getApprovalTxData?.tx?.at(0)?.data!, + from: getApprovalTxData?.tx?.at(0)?.from!, + to: getApprovalTxData?.tx?.at(0)?.to!, + }; + + const txResponse = await signer?.sendTransaction(txData); + await txResponse?.wait(); + } + + // 4. Execute gasless transaction with EIP-712 signature + const transfer = await sendTransactionRequest({ + // ... transaction parameters + mode: "gasless", + }); + + // 5. Sign EIP-712 typed data (as shown above) + // 6. Poll for transaction status +} +``` + +## API Restrictions for Gasless Transactions + +When using gasless transactions, be aware of the following API restrictions: + +- **Mode Parameter**: Always include `mode: "gasless"` in quote and send requests +- **EIP-712 Signatures**: Only EIP-712 signatures are supported, not regular transactions +- **Chain Support**: Gasless transactions are available on supported EVM chains +- **Token Approvals**: Standard ERC-20 approvals may still be required before gasless execution + +## Polling Transaction Status + +After signing the EIP-712 typed data, poll the transaction status using the signature: + +```typescript +async function pollTransactionStatus(transId: string, signature: string) { + const transactionStatus = await getTransationStatus({ + id: transId, + txHash: signature, // Use signature as txHash for gasless transactions + }); + + setTransStatus(transactionStatus); + + if (pendingStatuses.includes(transactionStatus?.status)) { + setTimeout( + () => pollTransactionStatus(transId, signature), + transactionPollingDuration, + ); + } else { + setTransferRoute(null); + toast({ + title: "Transaction Successful", + description: "Gasless bridge completed successfully", + }); + } +} +``` + +## Default Configuration + +Here's the default configuration for Base → Polygon USDC gasless transfers: + +```typescript +const defaultTransferParams: TranferParams = { + tokenAmount: "1", + fromChain: "base", + fromUserAddress: "0xE1e0992Be9902E92460AC0Ff625Dcc1c485FCF6b", + fromTokenAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", + fromTokenIconUrl: + "https://raw.githubusercontent.com/Pymmdrza/Cryptocurrency_Logos/mainx/PNG/usdc.png", + fromChainDecimal: 6, + tokenSymbol: "USDC", + toTokenAddress: "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359", + toTokenSymbol: "USDC", + toChain: "polygon", + toTokenIconUrl: + "https://raw.githubusercontent.com/Pymmdrza/Cryptocurrency_Logos/mainx/PNG/usdc.png", + toUserAddress: "0xE1e0992Be9902E92460AC0Ff625Dcc1c485FCF6b", + toChainDecimal: 6, +}; +``` + +## Customizing + +You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files. + +For more information about gasless transactions and advanced configuration, visit the [Swing Gasless Documentation](https://docs-git-feat-gasless-trans-update-swing-xyz.vercel.app/gasless-transactions). diff --git a/examples/swaps-api-nextjs-evm-gasless/components.json b/examples/swaps-api-nextjs-evm-gasless/components.json new file mode 100644 index 0000000..44d0040 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "styles/globals.css", + "baseColor": "zinc", + "cssVariables": false, + "prefix": "" + }, + "aliases": { + "components": "components", + "utils": "lib" + } +} \ No newline at end of file diff --git a/examples/swaps-api-nextjs-evm-gasless/next-env.d.ts b/examples/swaps-api-nextjs-evm-gasless/next-env.d.ts new file mode 100644 index 0000000..4f11a03 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/swaps-api-nextjs-evm-gasless/next.config.mjs b/examples/swaps-api-nextjs-evm-gasless/next.config.mjs new file mode 100644 index 0000000..d5456a1 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/next.config.mjs @@ -0,0 +1,6 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, +}; + +export default nextConfig; diff --git a/examples/swaps-api-nextjs-evm-gasless/package.json b/examples/swaps-api-nextjs-evm-gasless/package.json new file mode 100644 index 0000000..dfed2a8 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/package.json @@ -0,0 +1,58 @@ +{ + "name": "swaps-api-nextjs-evm-gasless", + "demo": "https://swaps-api-nextjs-evm-gasless.vercel.app/", + "keywords": [ + "api", + "swaps", + "nextjs", + "thirdweb" + ], + "license": "MIT", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "next dev", + "lint": "eslint src", + "build": "next build", + "start": "next start", + "clean": "rm -rf .next node_modules" + }, + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.5.1", + "@fortawesome/free-brands-svg-icons": "^6.5.1", + "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", + "@headlessui/react": "^1.7.18", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-toast": "^1.1.5", + "@tailwindcss/forms": "^0.5.7", + "@thirdweb-dev/react": "^4.4.17", + "@thirdweb-dev/sdk": "^4.0.44", + "axios": "^1.6.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "framer-motion": "^6.5.1", + "lucide-react": "^0.368.0", + "next": "14.1.3", + "react": "18.2.0", + "react-dom": "18.2.0", + "tailwind-merge": "^2.2.2", + "tailwindcss-animate": "^1.0.7", + "thirdweb": "^5.105.37", + "use-debounce": "^10.0.0" + }, + "devDependencies": { + "@types/node": "20.11.26", + "@types/react": "18.2.65", + "@types/react-dom": "18.2.22", + "autoprefixer": "^10.4.18", + "eslint": "^8.57.0", + "eslint-config-examples": "workspace:*", + "pino-pretty": "^10.3.1", + "postcss": "^8.4.35", + "tailwindcss": "^3.4.1", + "typescript": "^5.4.2", + "typescript-config": "workspace:*" + } +} diff --git a/examples/swaps-api-nextjs-evm-gasless/postcss.config.js b/examples/swaps-api-nextjs-evm-gasless/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/examples/swaps-api-nextjs-evm-gasless/public/favicon.ico b/examples/swaps-api-nextjs-evm-gasless/public/favicon.ico new file mode 100644 index 0000000..88b1f7a Binary files /dev/null and b/examples/swaps-api-nextjs-evm-gasless/public/favicon.ico differ diff --git a/examples/swaps-api-nextjs-evm-gasless/public/fonts/Inter-italic.var.woff2 b/examples/swaps-api-nextjs-evm-gasless/public/fonts/Inter-italic.var.woff2 new file mode 100644 index 0000000..b826d5a Binary files /dev/null and b/examples/swaps-api-nextjs-evm-gasless/public/fonts/Inter-italic.var.woff2 differ diff --git a/examples/swaps-api-nextjs-evm-gasless/public/fonts/Inter-roman.var.woff2 b/examples/swaps-api-nextjs-evm-gasless/public/fonts/Inter-roman.var.woff2 new file mode 100644 index 0000000..6a256a0 Binary files /dev/null and b/examples/swaps-api-nextjs-evm-gasless/public/fonts/Inter-roman.var.woff2 differ diff --git a/examples/swaps-api-nextjs-evm-gasless/src/app/layout.tsx b/examples/swaps-api-nextjs-evm-gasless/src/app/layout.tsx new file mode 100644 index 0000000..cbbe21e --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/app/layout.tsx @@ -0,0 +1,23 @@ +import "styles/globals.css"; +import "@fortawesome/fontawesome-svg-core/styles.css"; + +import { Header } from "../components/ui/Header"; +import { Footer } from "../components/ui/Footer"; + +import { Toaster } from "components/ui/toaster"; + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + {children} + + + + + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/app/page.tsx b/examples/swaps-api-nextjs-evm-gasless/src/app/page.tsx new file mode 100644 index 0000000..e844cb6 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/app/page.tsx @@ -0,0 +1,10 @@ +import { Hero } from "../components/ui/Hero"; +import { ThirdwebProvider } from "../components/ThirdwebProvider"; + +export default function Home() { + return ( + + + + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/Swap.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/Swap.tsx new file mode 100644 index 0000000..54ab4e7 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/Swap.tsx @@ -0,0 +1,899 @@ +"use client"; + +import { faCircleNotch } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import clsx from "clsx"; +import { useEffect, useRef, useState } from "react"; +import { Button } from "./ui/Button"; +import { useConnect } from "@thirdweb-dev/react"; +import { + useConnectionStatus, + useAddress, + useSigner, + useBalance, +} from "@thirdweb-dev/react"; +import { LiaExchangeAltSolid } from "react-icons/lia"; +import { QuoteQueryParams, Route } from "interfaces/quote.interface"; +import { + getAllowanceRequest, + getApproveRequest, + getQuoteRequest, + getTransationStatus, + sendTransactionRequest, +} from "services/requests"; +import { convertEthToWei, convertWeiToEth } from "utils/ethToWei"; +import { Popover, PopoverContent, PopoverTrigger } from "components/ui/popover"; + +import { Label } from "./ui/label"; +import { Input } from "./ui/input"; +import { useToast } from "components/ui/use-toast"; +import { TransactionStatusAPIResponse } from "interfaces/status.interface"; +import { AxiosError } from "axios"; + +import { metamaskWallet } from "@thirdweb-dev/react"; +const walletConfig = metamaskWallet(); + +interface ChainDecimals { + fromChainDecimal?: number; + toChainDecimal?: number; +} + +interface ChainIcons { + fromTokenIconUrl?: string; + toTokenIconUrl?: string; +} + +type TranferParams = QuoteQueryParams & ChainDecimals & ChainIcons; + +const defaultTransferParams: TranferParams = { + tokenAmount: "1", + fromChain: "base", + fromUserAddress: "0xE1e0992Be9902E92460AC0Ff625Dcc1c485FCF6b", + fromTokenAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", + fromTokenIconUrl: + "https://raw.githubusercontent.com/Pymmdrza/Cryptocurrency_Logos/mainx/PNG/usdc.png", + fromChainDecimal: 6, + tokenSymbol: "USDC", + toTokenAddress: "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359", + toTokenSymbol: "USDC", + toChain: "polygon", + toTokenIconUrl: + "https://raw.githubusercontent.com/Pymmdrza/Cryptocurrency_Logos/mainx/PNG/usdc.png", + toUserAddress: "0xE1e0992Be9902E92460AC0Ff625Dcc1c485FCF6b", + toChainDecimal: 6, +}; + +const pendingStatuses = [ + "Submitted", + "Not Sent", + "Pending Source Chain", + "Pending Destination Chain", +]; + +const transactionPollingDuration = 10000; + +const Swap = () => { + const [isLoading, setIsLoading] = useState(false); + // const [error, setError] = useState(""); + const [transferParams, setTransferParams] = useState( + defaultTransferParams, + ); + + const [recipientAddress] = useState(""); + + const [transferRoute, setTransferRoute] = useState(null); + const [availableRoutes, setAvailableRoutes] = useState([]); + const [selectedRouteIndex, setSelectedRouteIndex] = useState(0); + const [transStatus, setTransStatus] = + useState(); + + const connect = useConnect(); + const address = useAddress(); + + const connectionStatus = useConnectionStatus(); + const walletAddress = useAddress(); + const signer = useSigner(); + + const { toast } = useToast(); + + const sendInputRef = useRef(null); + + // Get token balance for the connected wallet + const { data: tokenBalance } = useBalance(transferParams.fromTokenAddress); + + // Format balance with appropriate decimals + const formatBalance = (balance: string, decimals: number) => { + const balanceNum = parseFloat(balance) / Math.pow(10, decimals); + return balanceNum.toFixed(4); + }; + + useEffect(() => { + setTransferParams((prev) => { + return { + ...prev, + fromUserAddress: walletAddress!, + }; + }); + }, [walletAddress]); + + useEffect(() => { + setTransferParams((prev) => { + return { + ...prev, + toUserAddress: recipientAddress.length + ? recipientAddress + : transferParams.toUserAddress, + }; + }); + }, [recipientAddress]); + + useEffect(() => { + if (!walletConfig?.isInstalled!()) { + console.log("not installed"); + toast({ + variant: "destructive", + title: "MetaMask Wallet not installed", + description: "Please install xDefi wallet in your browser", + }); + } + }, []); + + async function connectWallet(chainId?: number) { + try { + // Connect to xDefiConfig + await connect(walletConfig, { chainId }); + + // Connect wallet signer to Swing SDK + const walletAddress = address; + + setTransferParams((prev) => { + return { + ...prev, + fromUserAddress: walletAddress!, + toUserAddress: walletAddress!, + }; + }); + } catch (error) { + console.error("Connect Wallet Error:", error); + toast({ + variant: "destructive", + title: "Wallet connection error", + description: (error as Error).message, + }); + } + } + + async function getTransStatus( + transId: string, + txHash: string, + ): Promise { + try { + const transactionStatus = await getTransationStatus({ + id: transId, + txHash, + }); + + setTransStatus(transactionStatus); + + return transactionStatus!; + } catch (e) { + return { status: "Submitted" }; + } + } + + async function pollTransactionStatus(transId: string, txHash: string) { + const transactionStatus = await getTransStatus(transId, txHash); + + if (pendingStatuses.includes(transactionStatus?.status)) { + setTimeout( + () => pollTransactionStatus(transId, txHash), + transactionPollingDuration, + ); + } else { + setTransferRoute(null); + toast({ + title: "Transaction Successful", + description: `Bridge Successful`, + }); + } + + (sendInputRef.current as HTMLInputElement).value = "0.000"; + } + + function switchTransferParams() { + const tempTransferParams: TranferParams = Object.create(transferParams); + + const newTransferParams: TranferParams = { + tokenAmount: "0", + fromChain: tempTransferParams.toChain, + tokenSymbol: tempTransferParams.toTokenSymbol!, + fromUserAddress: walletAddress!, + fromTokenAddress: tempTransferParams.toTokenAddress!, + fromTokenIconUrl: tempTransferParams.toTokenIconUrl, + fromChainDecimal: tempTransferParams.toChainDecimal, + toTokenAddress: tempTransferParams.fromTokenAddress, + toTokenSymbol: tempTransferParams.tokenSymbol, + toChain: tempTransferParams.fromChain, + toTokenIconUrl: tempTransferParams.fromTokenIconUrl!, + toUserAddress: walletAddress!, + toChainDecimal: tempTransferParams.fromChainDecimal, + }; + + setTransferRoute(null); + setTransferParams(newTransferParams); + + (sendInputRef.current as HTMLInputElement).value = "0.000"; + } + + async function getQuote() { + setIsLoading(true); + + try { + // Get a quote from the Swing API + const quotes = await getQuoteRequest({ + fromChain: transferParams.fromChain, + fromTokenAddress: transferParams.fromTokenAddress, + fromUserAddress: transferParams.fromUserAddress, + toChain: transferParams.toChain, + tokenSymbol: transferParams.tokenSymbol, + toTokenAddress: transferParams.toTokenAddress, + toTokenSymbol: transferParams.toTokenSymbol, + toUserAddress: transferParams.fromUserAddress, + tokenAmount: convertEthToWei( + transferParams.tokenAmount, + transferParams.fromChainDecimal, + ), + }); + + if (!quotes?.routes.length) { + // setError(""); + toast({ + variant: "destructive", + title: "No routes found", + description: "No routes available. Try increasing the send amount.", + }); + setIsLoading(false); + return; + } + + // Store all available routes + setAvailableRoutes(quotes.routes); + + // Find best route (lowest gas cost) or default to first route + const bestRouteIndex = quotes.routes.reduce( + (bestIdx, route, currentIdx) => { + const currentGasUSD = parseFloat(route.gasUSD || "0"); + const bestGasUSD = parseFloat(quotes.routes[bestIdx]?.gasUSD || "0"); + return currentGasUSD < bestGasUSD ? currentIdx : bestIdx; + }, + 0, + ); + const defaultRouteIndex = bestRouteIndex; + + setSelectedRouteIndex(defaultRouteIndex); + setTransferRoute(quotes.routes[defaultRouteIndex]!); + + console.log("Available routes:", quotes.routes.length); + console.log("Selected route:", quotes.routes[defaultRouteIndex]); + } catch (error) { + console.error("Quote Error:", error); + toast({ + variant: "destructive", + title: "Something went wrong!", + description: (error as Error).message, + }); + } + + setIsLoading(false); + } + + function handleRouteSelection(routeIndex: number) { + setSelectedRouteIndex(routeIndex); + setTransferRoute(availableRoutes[routeIndex]!); + console.log("Selected route:", availableRoutes[routeIndex]); + } + + async function startTransfer() { + if (!transferRoute) { + toast({ + variant: "destructive", + title: "Something went wrong!", + description: "Please get a route first before attempting a transaction", + }); + return; + } + + console.log(transferParams.toUserAddress); + + transferParams.toUserAddress = walletAddress!; + transferParams.fromUserAddress = walletAddress!; + + setIsLoading(true); + + const tokenAmount = convertEthToWei( + transferParams.tokenAmount, + transferParams.fromChainDecimal, + ); + + // Chain ID mapping + const chainIdMap: { [key: string]: string } = { + polygon: "0x89", // 137 in hex + base: "0x2105", // 8453 in hex + }; + + try { + // Switch to correct chain (MetaMask will handle if already on correct chain) + const targetChainId = chainIdMap[transferParams.fromChain]; + if (targetChainId) { + setTransStatus({ status: "Ensuring correct network..." }); + + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await (window as any).ethereum.request({ + method: "wallet_switchEthereumChain", + params: [{ chainId: targetChainId }], + }); + + console.log("Network ensured for chain:", transferParams.fromChain); + + // Brief wait for any network state changes + await new Promise((resolve) => setTimeout(resolve, 500)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (switchError: any) { + console.error("Chain switch error:", switchError); + toast({ + variant: "destructive", + title: "Network switch failed!", + description: `Please manually switch to ${transferParams.fromChain} network`, + }); + setIsLoading(false); + setTransStatus(null); + return; + } + } + + // Check allowance and approve if needed + const checkAllowance = await getAllowanceRequest({ + bridge: transferRoute.quote.integration, + fromAddress: transferParams.fromUserAddress, + fromChain: transferParams.fromChain, + tokenAddress: transferParams.fromTokenAddress, + tokenSymbol: transferParams.tokenSymbol, + toChain: transferParams.toChain, + toTokenAddress: transferParams.toTokenAddress!, + toTokenSymbol: transferParams.toTokenSymbol!, + contractCall: false, + }); + + if (Number(checkAllowance?.allowance || "0") <= 0) { + setTransStatus({ + status: "Wallet Interaction Required: Approval Token", + }); + + const getApprovalTxData = await getApproveRequest({ + tokenAmount: tokenAmount, + bridge: transferRoute.quote.integration, + fromAddress: transferParams.fromUserAddress, + fromChain: transferParams.fromChain, + tokenAddress: transferParams.fromTokenAddress, + tokenSymbol: transferParams.tokenSymbol, + toChain: transferParams.toChain, + toTokenAddress: transferParams.toTokenAddress!, + toTokenSymbol: transferParams.toTokenSymbol!, + contractCall: false, + }); + + const txData = { + data: getApprovalTxData?.tx?.at(0)?.data!, + from: getApprovalTxData?.tx?.at(0)?.from!, + to: getApprovalTxData?.tx?.at(0)?.to!, + }; + + const txResponse = await signer?.sendTransaction(txData); + const receipt = await txResponse?.wait(); + console.log("Approval transaction receipt:", receipt); + + setTransStatus({ status: "Token allowance approved" }); + + // Wait a moment for blockchain state to update + await new Promise((resolve) => setTimeout(resolve, 2000)); + + // Verify approval went through + const verifyAllowance = await getAllowanceRequest({ + bridge: transferRoute.quote.integration, + fromAddress: transferParams.fromUserAddress, + fromChain: transferParams.fromChain, + tokenAddress: transferParams.fromTokenAddress, + tokenSymbol: transferParams.tokenSymbol, + toChain: transferParams.toChain, + toTokenAddress: transferParams.toTokenAddress!, + toTokenSymbol: transferParams.toTokenSymbol!, + contractCall: false, + }); + + console.log("Verified allowance:", verifyAllowance?.allowance); + } + + setTransStatus({ status: "Preparing transfer..." }); + + const transfer = await sendTransactionRequest({ + fromChain: transferParams.fromChain, + fromTokenAddress: transferParams.fromTokenAddress, + fromUserAddress: transferParams.fromUserAddress, + tokenSymbol: transferParams.tokenSymbol, + + toTokenAddress: transferParams.toTokenAddress!, + toChain: transferParams.toChain, + toTokenAmount: transferRoute.quote.amount, + toTokenSymbol: transferParams.toTokenSymbol!, + toUserAddress: transferParams.toUserAddress!, + + tokenAmount: tokenAmount, + route: transferRoute.route, + type: "swap", + }); + + /*** + * GASLESS TRANSACTION FLOW + * + * For gasless transactions, we use EIP-712 typed data signing + * instead of sending a regular transaction + */ + + setTransStatus({ status: "Wallet Interaction Required" }); + + let txResponse; + + if ( + transfer?.tx?.meta && + "domain" in transfer.tx.meta && + transfer.tx.meta.domain && + "types" in transfer.tx.meta && + transfer.tx.meta.types && + "value" in transfer.tx.meta && + transfer.tx.meta.value + ) { + // For gasless transactions, the send endpoint returns EIP-712 typed data in meta + const tx = JSON.stringify(transfer.tx!); + const txInfo = JSON.parse(tx); + const txObj = txInfo.meta; + + console.log("txObj:", txObj); + + const JAM_DOMAIN = txObj.domain; + const JAM_ORDER_TYPES = txObj.types; + const toSign = txObj.value; + const domain = JAM_DOMAIN; + + const types = { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { name: "chainId", type: "uint256" }, + { name: "verifyingContract", type: "address" }, + ], + ...JAM_ORDER_TYPES, // e.g. { JamOrder: [...] } + }; + + console.log("domain:", domain); + console.log("types:", types); + console.log("toSign:", toSign); + + const message = toSign; // The actual object being signed + const msgParams = JSON.stringify({ + domain, + primaryType: Object.keys(JAM_ORDER_TYPES)[0], // e.g., "JamOrder" + message, + types, + }); + + console.log("msgParams:", msgParams); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const account = (window as any).ethereum.selectedAddress; + + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const signature = await (window as any).ethereum.request({ + method: "eth_signTypedData_v4", + params: [account, msgParams], + }); + + txResponse = signature; + console.log("EIP-712 Signature:", signature); + + // Poll transaction status with the signature + pollTransactionStatus(transfer.id.toString(), signature); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (signError: any) { + console.error("Signing error:", signError); + + // Handle specific JSON-RPC errors + if (signError.code === -32603) { + toast({ + variant: "destructive", + title: "Transaction failed!", + description: + "JSON-RPC error occurred. Please try again or switch networks.", + }); + } else if (signError.code === 4001) { + toast({ + variant: "destructive", + title: "Transaction rejected!", + description: "User rejected the signature request", + }); + } else { + toast({ + variant: "destructive", + title: "Signing failed!", + description: + signError.message || "Unknown error occurred during signing", + }); + } + + setIsLoading(false); + setTransStatus(null); + return; + } + } else { + // Fallback to regular transaction if no meta (shouldn't happen for gasless) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const txData: any = { + data: transfer?.tx.data, + from: transfer?.tx.from, + to: transfer?.tx.to, + value: transfer?.tx.value, + gasLimit: transfer?.tx.gas, + }; + + txResponse = await signer?.sendTransaction(txData); + pollTransactionStatus(transfer?.id?.toString()!, txResponse?.hash!); + const receipt = await txResponse?.wait(); + console.log("Transaction receipt:", receipt); + } + + // Wait for the transaction to be mined + } catch (error) { + console.error("Transfer Error:", error); + toast({ + variant: "destructive", + title: "Something went wrong!", + description: + // eslint-disable-next-line @typescript-eslint/no-explicit-any + `${(error as AxiosError & any)?.response?.data?.error} : ${(error as AxiosError & any)?.response?.data?.message}` ?? + (error as Error).message ?? + "Something went wrong", + }); + } + + setIsLoading(false); + } + + return ( + + {/* Animated background glow */} + + + + + + + + + + + 💰 SEND + + {tokenBalance && ( + + Balance:{" "} + {formatBalance( + tokenBalance.value.toString(), + tokenBalance.decimals, + )} + + )} + + + { + setTransferRoute(null); // Reset transfer route + setTransferParams((prev) => ({ + ...prev, + tokenAmount: e.target.value, + })); + }} + type="number" + /> + + + + + {transferParams.fromChain} + + + + + + + + + switchTransferParams()} + /> + + + + + + + + + {transferParams.toChain} + + + + + 💎 RECEIVE + + + { + setTransferRoute(null); // Reset transfer route + setTransferParams((prev) => ({ + ...prev, + amount: e.target.value, + })); + }} + type="number" + /> + + + + + + + + {connectionStatus === "connected" ? ( + <> + {transferRoute ? ( + + + {transStatus?.status + ? "⚡ Track Mission" + : "🚀 Initiate Swap"} + + + + + + 🎯 Target {transferParams.toChain} Address + + { + setTransferParams((prev) => ({ + ...prev, + toUserAddress: walletAddress!, + })); + }} + /> + {transStatus ? ( + + + 🔄 Mission Status + + + {transStatus.status}{" "} + {transStatus.status !== "Completed" ? ( + + ) : ( + <>> + )} + + + ) : ( + <>> + )} + startTransfer()} + > + 🚀 Execute + {isLoading && ( + + )} + + + + + + ) : ( + getQuote()} + > + ⚡ Get Quote + {isLoading && ( + + )} + + )} + > + ) : ( + connectWallet()} + > + 🔗 Link Wallet + + )} + + + {/* Route Selection - Vertical Layout */} + {availableRoutes.length > 1 && transferRoute && ( + + + + + 🛣️ ROUTE OPTIONS + + + {availableRoutes.length} available + + + + handleRouteSelection(Number(e.target.value))} + className="w-full rounded-lg bg-gray-800/60 border border-purple-400/20 text-white px-3 py-3 text-sm focus:border-purple-400 focus:ring-1 focus:ring-purple-400/20 transition-all duration-300" + > + {availableRoutes.map((route, index) => { + const bridge = + route.route[0]?.bridge || route.quote.integration; + const gasUSD = parseFloat(route.gasUSD || "0"); + const duration = route.duration; + + return ( + + {bridge.toUpperCase()} • ${gasUSD.toFixed(4)} gas •{" "} + {duration}min + + ); + })} + + + + + Gas Cost: $ + {parseFloat(transferRoute.gasUSD || "0").toFixed(4)} + + + Duration: ~{transferRoute.duration}min + + + + + )} + + + + + + 🌟 ORIGIN + + + {transferParams.fromChain} / {transferParams.tokenSymbol} + + + + + + 🎯 DESTINATION + + + {transferParams.toChain} / {transferParams.toTokenSymbol} + + + + + + ⚡ GAS COST + + + {formatUSD(transferRoute?.gasUSD! ?? 0)} + + + + + + 💰 VALUE + + + {formatUSD(transferRoute?.quote?.amountUSD! ?? 0)} + + + + + + + ); +}; + +function formatUSD(amount: string) { + return new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + currencyDisplay: "narrowSymbol", + }).format(Number(amount)); +} + +export default Swap; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ThirdwebProvider.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ThirdwebProvider.tsx new file mode 100644 index 0000000..b420a91 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ThirdwebProvider.tsx @@ -0,0 +1,3 @@ +"use client"; + +export { ThirdwebProvider } from "@thirdweb-dev/react"; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Button.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Button.tsx new file mode 100644 index 0000000..251668b --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Button.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import Link from "next/link"; +import clsx from "clsx"; + +const baseStyles = { + solid: + "inline-flex justify-center rounded-2xl py-2 px-3 text-sm font-semibold outline-2 outline-offset-2 transition-colors", + outline: + "inline-flex justify-center rounded-2xl border py-[calc(theme(spacing.2)-1px)] px-[calc(theme(spacing.3)-1px)] text-sm outline-2 outline-offset-2 transition-colors", +}; + +const variantStyles = { + solid: { + cyan: "relative overflow-hidden bg-cyan-500 text-white before:absolute before:inset-0 active:before:bg-transparent hover:before:bg-white/10 active:bg-cyan-600 active:text-white/80 before:transition-colors", + white: + "bg-white text-cyan-900 hover:bg-white/90 active:bg-white/90 active:text-cyan-900/70", + gray: "bg-gray-800 text-white hover:bg-gray-900 active:bg-gray-800 active:text-white/80", + }, + outline: { + gray: "border-gray-300 text-gray-700 hover:border-gray-400 active:bg-gray-100 active:text-gray-700/80", + }, +}; + +export const Button = function Button({ + variant = "solid", + color = "gray", + className, + href, + ...props +}: { + variant?: "solid" | "outline"; + color?: "cyan" | "white" | "gray"; + className?: string; + href?: string; +} & React.InputHTMLAttributes) { + const styles = variantStyles[variant]; + + className = clsx( + baseStyles[variant], + color in styles ? styles[color as keyof typeof styles] : {}, + className, + ); + + const isExternalLink = href?.startsWith("http"); + + return href ? ( + + ) : ( + + ); +}; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Container.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Container.tsx new file mode 100644 index 0000000..690b83a --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Container.tsx @@ -0,0 +1,15 @@ +import clsx from "clsx"; + +export function Container({ + className, + children, +}: { + className?: string; + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Footer.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Footer.tsx new file mode 100644 index 0000000..76f039c --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Footer.tsx @@ -0,0 +1,20 @@ +"use client"; + +import { Container } from "./Container"; + +export function Footer() { + return ( + + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Header.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Header.tsx new file mode 100644 index 0000000..a2ce77f --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Header.tsx @@ -0,0 +1,162 @@ +"use client"; + +import Link from "next/link"; +import { Popover } from "@headlessui/react"; +import { AnimatePresence, motion } from "framer-motion"; + +import { Button } from "./Button"; +import { Container } from "./Container"; +import { NavLinks } from "./NavLinks"; +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faGithub } from "@fortawesome/free-brands-svg-icons"; + +function MenuIcon({ className }: { className?: string }) { + return ( + + + + ); +} + +function ChevronUpIcon({ className }: { className?: string }) { + return ( + + + + ); +} + +function MobileNavLink({ + children, + href, +}: { + children: React.ReactNode; + href: string; +}) { + return ( + + {children} + + ); +} + +export function Header() { + return ( + + + + + + + 🚀 Swing + + Bridge + + + + + + + + + + {({ open }) => ( + <> + + {({ open }) => + open ? ( + + ) : ( + + ) + } + + + {open && ( + <> + + + + Swap + API + Docs + + + + + + Fork on Github + + + + > + )} + + > + )} + + + + + Fork on Github + + + + + + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Hero.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Hero.tsx new file mode 100644 index 0000000..09443bc --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/Hero.tsx @@ -0,0 +1,64 @@ +"use client"; + +import React from "react"; +import { Container } from "./Container"; + +import logoCnn from "images/logos/cnn.svg"; +import logoForbes from "images/logos/forbes.svg"; +import logoTechcrunch from "images/logos/techcrunch.svg"; +import logoWired from "images/logos/wired.svg"; + +import SwapSDK from "../Swap"; +import Image from "next/image"; +import clsx from "clsx"; + +export function Hero() { + return ( + + + + + + + Gasless Cross-Chain Crypto{" "} + + Swapping + + + + + ⚡ Experience the future of DeFi with seamless cross-chain swaps. + + Bridge assets across multiple blockchains with zero hassle. + + + + + + + + + + + 🌟 Powered By Leading Bridges + + + {[ + ["Forbes", logoForbes], + ["TechCrunch", logoTechcrunch], + ["Wired", logoWired], + ["CNN", logoCnn, "hidden xl:block"], + ].map(([name, logo, className]) => ( + + + + ))} + + + + + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/NavLinks.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/NavLinks.tsx new file mode 100644 index 0000000..f11b44c --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/NavLinks.tsx @@ -0,0 +1,41 @@ +import { useState } from "react"; +import Link from "next/link"; +import { AnimatePresence, motion } from "framer-motion"; + +export function NavLinks() { + const [hoveredIndex, setHoveredIndex] = useState(null); + + return ( + <> + {[ + ["Swap", "#"], + ["API", "#"], + ["Docs", "#"], + ].map(([label, href], index) => ( + setHoveredIndex(index)} + onMouseLeave={() => setHoveredIndex(null)} + > + + {hoveredIndex === index && ( + + )} + + {label} + + ))} + > + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/input.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/input.tsx new file mode 100644 index 0000000..433ae98 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; + +import { cn } from "lib"; + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/label.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/label.tsx new file mode 100644 index 0000000..644132e --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/label.tsx @@ -0,0 +1,26 @@ +"use client"; + +import * as React from "react"; +import * as LabelPrimitive from "@radix-ui/react-label"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "lib"; + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", +); + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/popover.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/popover.tsx new file mode 100644 index 0000000..efbc6cf --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/popover.tsx @@ -0,0 +1,31 @@ +"use client"; + +import * as React from "react"; +import * as PopoverPrimitive from "@radix-ui/react-popover"; + +import { cn } from "lib"; + +const Popover = PopoverPrimitive.Root; + +const PopoverTrigger = PopoverPrimitive.Trigger; + +const PopoverContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( + + + +)); +PopoverContent.displayName = PopoverPrimitive.Content.displayName; + +export { Popover, PopoverTrigger, PopoverContent }; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/toast.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/toast.tsx new file mode 100644 index 0000000..3b7c84a --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/toast.tsx @@ -0,0 +1,130 @@ +"use client"; + +import * as React from "react"; +import * as ToastPrimitives from "@radix-ui/react-toast"; +import { cva, type VariantProps } from "class-variance-authority"; +import { X } from "lucide-react"; + +import { cn } from "lib"; + +const ToastProvider = ToastPrimitives.Provider; + +const ToastViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ToastViewport.displayName = ToastPrimitives.Viewport.displayName; + +const toastVariants = cva( + "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border border-zinc-200 p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full dark:border-zinc-800", + { + variants: { + variant: { + default: + "border bg-white text-zinc-950 dark:bg-zinc-950 dark:text-zinc-50", + destructive: + "destructive group border-red-500 bg-red-500 text-zinc-50 dark:border-red-900 dark:bg-red-900 dark:text-zinc-50", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +const Toast = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, ...props }, ref) => { + return ( + + ); +}); +Toast.displayName = ToastPrimitives.Root.displayName; + +const ToastAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ToastAction.displayName = ToastPrimitives.Action.displayName; + +const ToastClose = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +ToastClose.displayName = ToastPrimitives.Close.displayName; + +const ToastTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ToastTitle.displayName = ToastPrimitives.Title.displayName; + +const ToastDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ToastDescription.displayName = ToastPrimitives.Description.displayName; + +type ToastProps = React.ComponentPropsWithoutRef; + +type ToastActionElement = React.ReactElement; + +export { + type ToastProps, + type ToastActionElement, + ToastProvider, + ToastViewport, + Toast, + ToastTitle, + ToastDescription, + ToastClose, + ToastAction, +}; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/toaster.tsx b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/toaster.tsx new file mode 100644 index 0000000..32376bc --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/toaster.tsx @@ -0,0 +1,35 @@ +"use client"; + +import { + Toast, + ToastClose, + ToastDescription, + ToastProvider, + ToastTitle, + ToastViewport, +} from "components/ui/toast"; +import { useToast } from "components/ui/use-toast"; + +export function Toaster() { + const { toasts } = useToast(); + + return ( + + {toasts.map(function ({ id, title, description, action, ...props }) { + return ( + + + {title && {title}} + {description && ( + {description} + )} + + {action} + + + ); + })} + + + ); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/components/ui/use-toast.ts b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/use-toast.ts new file mode 100644 index 0000000..7bb041c --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/components/ui/use-toast.ts @@ -0,0 +1,191 @@ +"use client"; + +// Inspired by react-hot-toast library +import * as React from "react"; + +import type { ToastActionElement, ToastProps } from "components/ui/toast"; + +const TOAST_LIMIT = 1; +const TOAST_REMOVE_DELAY = 1000000; + +type ToasterToast = ToastProps & { + id: string; + title?: React.ReactNode; + description?: React.ReactNode; + action?: ToastActionElement; +}; + +const actionTypes = { + ADD_TOAST: "ADD_TOAST", + UPDATE_TOAST: "UPDATE_TOAST", + DISMISS_TOAST: "DISMISS_TOAST", + REMOVE_TOAST: "REMOVE_TOAST", +} as const; + +let count = 0; + +function genId() { + count = (count + 1) % Number.MAX_SAFE_INTEGER; + return count.toString(); +} + +type ActionType = typeof actionTypes; + +type Action = + | { + type: ActionType["ADD_TOAST"]; + toast: ToasterToast; + } + | { + type: ActionType["UPDATE_TOAST"]; + toast: Partial; + } + | { + type: ActionType["DISMISS_TOAST"]; + toastId?: ToasterToast["id"]; + } + | { + type: ActionType["REMOVE_TOAST"]; + toastId?: ToasterToast["id"]; + }; + +interface State { + toasts: ToasterToast[]; +} + +const toastTimeouts = new Map>(); + +const addToRemoveQueue = (toastId: string) => { + if (toastTimeouts.has(toastId)) { + return; + } + + const timeout = setTimeout(() => { + toastTimeouts.delete(toastId); + dispatch({ + type: "REMOVE_TOAST", + toastId: toastId, + }); + }, TOAST_REMOVE_DELAY); + + toastTimeouts.set(toastId, timeout); +}; + +export const reducer = (state: State, action: Action): State => { + switch (action.type) { + case "ADD_TOAST": + return { + ...state, + toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), + }; + + case "UPDATE_TOAST": + return { + ...state, + toasts: state.toasts.map((t) => + t.id === action.toast.id ? { ...t, ...action.toast } : t, + ), + }; + + case "DISMISS_TOAST": { + const { toastId } = action; + + // ! Side effects ! - This could be extracted into a dismissToast() action, + // but I'll keep it here for simplicity + if (toastId) { + addToRemoveQueue(toastId); + } else { + state.toasts.forEach((toast) => { + addToRemoveQueue(toast.id); + }); + } + + return { + ...state, + toasts: state.toasts.map((t) => + t.id === toastId || toastId === undefined + ? { + ...t, + open: false, + } + : t, + ), + }; + } + case "REMOVE_TOAST": + if (action.toastId === undefined) { + return { + ...state, + toasts: [], + }; + } + return { + ...state, + toasts: state.toasts.filter((t) => t.id !== action.toastId), + }; + } +}; + +const listeners: Array<(state: State) => void> = []; + +let memoryState: State = { toasts: [] }; + +function dispatch(action: Action) { + memoryState = reducer(memoryState, action); + listeners.forEach((listener) => { + listener(memoryState); + }); +} + +type Toast = Omit; + +function toast({ ...props }: Toast) { + const id = genId(); + + const update = (props: ToasterToast) => + dispatch({ + type: "UPDATE_TOAST", + toast: { ...props, id }, + }); + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); + + dispatch({ + type: "ADD_TOAST", + toast: { + ...props, + id, + open: true, + onOpenChange: (open) => { + if (!open) dismiss(); + }, + }, + }); + + return { + id: id, + dismiss, + update, + }; +} + +function useToast() { + const [state, setState] = React.useState(memoryState); + + React.useEffect(() => { + listeners.push(setState); + return () => { + const index = listeners.indexOf(setState); + if (index > -1) { + listeners.splice(index, 1); + } + }; + }, [state]); + + return { + ...state, + toast, + dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), + }; +} + +export { useToast, toast }; diff --git a/examples/swaps-api-nextjs-evm-gasless/src/images/logos/cnn.svg b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/cnn.svg new file mode 100644 index 0000000..a640727 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/cnn.svg @@ -0,0 +1,11 @@ + + + + + diff --git a/examples/swaps-api-nextjs-evm-gasless/src/images/logos/forbes.svg b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/forbes.svg new file mode 100644 index 0000000..f3929e8 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/forbes.svg @@ -0,0 +1,5 @@ + + + diff --git a/examples/swaps-api-nextjs-evm-gasless/src/images/logos/techcrunch.svg b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/techcrunch.svg new file mode 100644 index 0000000..de91f48 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/techcrunch.svg @@ -0,0 +1,5 @@ + + + diff --git a/examples/swaps-api-nextjs-evm-gasless/src/images/logos/wired.svg b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/wired.svg new file mode 100644 index 0000000..e76e50b --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/images/logos/wired.svg @@ -0,0 +1,5 @@ + + + diff --git a/examples/swaps-api-nextjs-evm-gasless/src/interfaces/allowance.interface.ts b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/allowance.interface.ts new file mode 100644 index 0000000..6c6d8b9 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/allowance.interface.ts @@ -0,0 +1,41 @@ +import { Chain } from "./quote.interface"; + +export interface AllowanceQueryParams { + bridge: string; + fromAddress: string; + fromChain: string; + toChain: string; + tokenAddress: string; + tokenSymbol: string; + toTokenSymbol: string; + toTokenAddress: string; + contractCall: boolean; + } + + export interface AllowanceAPIResponse { + allowance: string; + } + + export interface ApproveQueryParams { + bridge: string; + fromAddress: string; + fromChain: string; + toChain: string; + tokenAddress: string; + tokenSymbol: string; + tokenAmount: string; + toTokenSymbol: string; + toTokenAddress: string; + contractCall: boolean; + } + + export interface ApproveAPIResponse { + tx: ApproveTransaction[]; + fromChain: Chain; + } + + interface ApproveTransaction { + data: string; + from: string; + to: string; + } \ No newline at end of file diff --git a/examples/swaps-api-nextjs-evm-gasless/src/interfaces/quote.interface.ts b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/quote.interface.ts new file mode 100644 index 0000000..6da8701 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/quote.interface.ts @@ -0,0 +1,75 @@ +export interface QuoteQueryParams { + fromChain: string; + tokenSymbol: string; + fromTokenAddress: string; + fromUserAddress: string; + toChain: string; + toTokenSymbol?: string; + toTokenAddress?: string; + toUserAddress?: string; + tokenAmount: string; +} + +export interface QuoteAPIResponse { + routes: Route[]; + fromToken: Token; + fromChain: Chain; + toToken: Token; + toChain: Chain; +} + +export interface Route { + duration: number; + gas: string; + quote: Quote; + route: RouteStep[]; + distribution: { [key: string]: number }; + gasUSD: string; +} + +interface Quote { + integration: string; + type: string; + bridgeFee: string; + bridgeFeeInNativeToken: string; + amount: string; + decimals: number; + amountUSD: string; + bridgeFeeUSD: string; + bridgeFeeInNativeTokenUSD: string; + fees: Fee[]; +} + +interface Fee { + type: string; + amount: string; + amountUSD: string; + chainSlug: string; + tokenSymbol: string; + tokenAddress: string; + decimals: number; + deductedFromSourceToken: boolean; +} + +interface RouteStep { + bridge: string; + bridgeTokenAddress: string; + steps: string[]; + name: string; + part: number; +} + +interface Token { + address: string; + symbol: string; + name: string; + decimals: number; + logoURI: string; +} + +export interface Chain { + chainId: number; + name: string; + slug: string; + protocolType: string; +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/interfaces/send.interface.ts b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/send.interface.ts new file mode 100644 index 0000000..7b7a359 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/send.interface.ts @@ -0,0 +1,79 @@ +export interface SendTransactionApiResponse { + id: number; + fromToken: Token; + toToken: Token; + fromChain: Chain; + toChain: Chain; + route: Route[]; + tx: TransactionDetails; +} + +interface Token { + address: string; + symbol: string; + name: string; + decimals: number; + logoURI: string; +} + +interface Chain { + chainId: number; + name: string; + slug: string; + protocolType: string; +} + +interface Route { + bridge: string; + bridgeTokenAddress: string; + steps: string[]; + name: string; + part: number; +} + +interface TransactionDetails { + from: string; + to: string; + data: string; + value: string; + gas: string; + meta: Meta; +} + +interface Meta { + from: string; + recipient: string; + amount: Amount; + memo: string; + slippage: number; +} + +interface Amount { + amount: string; + decimals: number; +} + +export interface SendTransactionPayload { + fromUserAddress: string; + toUserAddress: string; + tokenSymbol: string; + fromTokenAddress: string; + fromChain: string; + toTokenSymbol: string; + toTokenAddress: string; + toChain: string; + tokenAmount: string; + toTokenAmount: string; + route: Route[]; + projectId?: string; + type?: string; + integration?: string; +} + +interface Route { + bridge: string; + bridgeTokenAddress: string; + steps: string[]; + name: string; + part: number; +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/interfaces/status.interface.ts b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/status.interface.ts new file mode 100644 index 0000000..d51db60 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/interfaces/status.interface.ts @@ -0,0 +1,54 @@ +export interface TransactionStatusAPIResponse { + status: string; + refundReason?: string; + errorReason?: string | null; + needClaim?: boolean; + bridge?: string; + txId?: string; + txStartedTimestamp?: number; + txCompletedTimestamp?: number; + fromUserAddress?: string; + toUserAddress?: string; + fromTokenAddress?: string; + fromAmount?: string; + fromAmountUsdValue?: string; + fromChainId?: number; + fromChainSlug?: string; + fromChainTxHash?: string; + toTokenAddress?: string; + toAmount?: string; + toAmountUsdValue?: string; + toChainId?: number; + toChainSlug?: string; + toChainTxHash?: string; + updatedAt?: string; + createdAt?: string; + fromTokenSymbol?: string; + toTokenSymbol?: string; + transferStep?: string | null; + transferStatus?: string | null; + fallbackTokenAddress?: string | null; + contractCall?: boolean; + toContractCallAddress?: string | null; + toContractCallData?: string | null; + toContractCallTokenAddress?: string | null; + toContractCallApprovalAddress?: string | null; + toContractCallGasLimit?: string | null; + integration?: string; + type?: string; + bridgeFeeUsdValue?: string; + bridgeFeeInNativeTokenUsdValue?: string | null; + destinationTxFeeUsdValue?: string | null; + gasUsage?: string; + gasUsageUsdValue?: string; + partnerShare?: string; + partnerShareUsdValue?: string; + swingShare?: string; + swingShareUsdValue?: string; + id?: number; +} + +export interface TransactionStatusParams { + id: string; + txHash?: string; +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/lib.ts b/examples/swaps-api-nextjs-evm-gasless/src/lib.ts new file mode 100644 index 0000000..365058c --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/lib.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/examples/swaps-api-nextjs-evm-gasless/src/services/requests.ts b/examples/swaps-api-nextjs-evm-gasless/src/services/requests.ts new file mode 100644 index 0000000..4f6cd11 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/services/requests.ts @@ -0,0 +1,101 @@ +import axios from "axios"; +import { QuoteAPIResponse, QuoteQueryParams } from "interfaces/quote.interface"; +import { + SendTransactionApiResponse, + SendTransactionPayload, +} from "interfaces/send.interface"; +import { + TransactionStatusAPIResponse, + TransactionStatusParams, +} from "interfaces/status.interface"; +import { + AllowanceQueryParams, + AllowanceAPIResponse, + ApproveQueryParams, + ApproveAPIResponse, +} from "interfaces/allowance.interface"; + +const baseUrl = "https://swap.prod.swing.xyz/v0"; +const projectId = "replug"; + +export const getQuoteRequest = async ( + queryParams: QuoteQueryParams, +): Promise => { + try { + const response = await axios.get( + `${baseUrl}/transfer/quote`, + { params: { ...queryParams, projectId, mode: "gasless", debug: true } }, + ); + return response.data; + } catch (error) { + console.error("Error fetching quote:", error); + throw error; + } +}; + +export const getTransationStatus = async ( + statusParams: TransactionStatusParams, +): Promise => { + try { + const response = await axios.get( + `${baseUrl}/transfer/status`, + { params: { ...statusParams, projectId } }, + ); + + return response.data; + } catch (error) { + console.error("Error fetching transaction status:", error); + + throw error; + } +}; + +export const sendTransactionRequest = async ( + payload: SendTransactionPayload, +): Promise => { + try { + const response = await axios.post( + `${baseUrl}/transfer/send`, + { ...payload, projectId, mode: "gasless" }, + { + headers: { + "Content-Type": "application/json", + }, + }, + ); + return response.data; + } catch (error) { + console.error("Error sending transaction:", error); + throw error; + } +}; + +export const getAllowanceRequest = async ( + queryParams: AllowanceQueryParams, +): Promise => { + try { + const response = await axios.get( + `${baseUrl}/transfer/allowance`, + { params: { ...queryParams, projectId } }, + ); + return response.data; + } catch (error) { + console.error("Error fetching allowance:", error); + throw error; + } +}; + +export const getApproveRequest = async ( + queryParams: ApproveQueryParams, +): Promise => { + try { + const response = await axios.get( + `${baseUrl}/transfer/approve`, + { params: { ...queryParams, projectId } }, + ); + return response.data; + } catch (error) { + console.error("Error fetching approve transaction:", error); + throw error; + } +}; \ No newline at end of file diff --git a/examples/swaps-api-nextjs-evm-gasless/src/styles/globals.css b/examples/swaps-api-nextjs-evm-gasless/src/styles/globals.css new file mode 100644 index 0000000..ef08ebd --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/styles/globals.css @@ -0,0 +1,12 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + + +@layer base { + input[type="number"]::-webkit-inner-spin-button, + input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; + } +} \ No newline at end of file diff --git a/examples/swaps-api-nextjs-evm-gasless/src/utils/ethToWei.ts b/examples/swaps-api-nextjs-evm-gasless/src/utils/ethToWei.ts new file mode 100644 index 0000000..d2e6101 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/src/utils/ethToWei.ts @@ -0,0 +1,19 @@ +import { ethers } from "ethers"; + +/** + * Converts ETH to Wei. + * + * @param {string | number} ethAmount The amount in ETH to convert. + * @returns {string} The amount in Wei as a string. + */ +export const convertEthToWei = (ethAmount: string, decimals = 18) => { + // Convert the amount to a string to handle both string and number inputs + const weiAmount = ethers.utils.parseUnits(ethAmount.toString(), decimals); + return weiAmount.toString(); +}; + +export const convertWeiToEth = (weiAmount: string, decimals = 18) => { + // Convert the amount to a string to handle both string and number inputs + const ethAmount = ethers.utils.formatUnits(weiAmount.toString(), decimals); + return Number(ethAmount.toString()).toFixed(4); +}; diff --git a/examples/swaps-api-nextjs-evm-gasless/styles/globals.css b/examples/swaps-api-nextjs-evm-gasless/styles/globals.css new file mode 100644 index 0000000..91f55f0 --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/styles/globals.css @@ -0,0 +1,4 @@ +@tailwind base; + @tailwind components; + @tailwind utilities; + \ No newline at end of file diff --git a/examples/swaps-api-nextjs-evm-gasless/tailwind.config.js b/examples/swaps-api-nextjs-evm-gasless/tailwind.config.js new file mode 100644 index 0000000..afa115d --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/tailwind.config.js @@ -0,0 +1,127 @@ +const defaultTheme = require('tailwindcss/defaultTheme'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ['class'], + content: ['./pages/**/*.{ts,tsx}', './components/**/*.{ts,tsx}', './app/**/*.{ts,tsx}', './src/**/*.{ts,tsx}'], + prefix: '', + theme: { + container: { + center: true, + padding: '2rem', + screens: { + '2xl': '1400px', + }, + }, + fontSize: { + xs: ['0.75rem', { lineHeight: '1rem' }], + sm: ['0.875rem', { lineHeight: '1.5rem' }], + base: ['1rem', { lineHeight: '1.5rem' }], + lg: ['1.125rem', { lineHeight: '2rem' }], + xl: ['1.25rem', { lineHeight: '1.75rem' }], + '2xl': ['1.5rem', { lineHeight: '2rem' }], + '3xl': ['2rem', { lineHeight: '3rem' }], + '4xl': ['2.5rem', { lineHeight: '3rem' }], + '5xl': ['3rem', { lineHeight: '1' }], + '6xl': ['3.75rem', { lineHeight: '1' }], + '7xl': ['4.5rem', { lineHeight: '1' }], + '8xl': ['6rem', { lineHeight: '1' }], + '9xl': ['8rem', { lineHeight: '1' }], + }, + extend: { + colors: ({ colors }) => ({ + gray: colors.neutral, + }), + fontFamily: { + sans: ['Inter', ...defaultTheme.fontFamily.sans], + }, + keyframes: { + 'fade-in': { + from: { + opacity: 0, + }, + to: { + opacity: 1, + }, + }, + marquee: { + '100%': { + transform: 'translateY(-50%)', + }, + }, + 'spin-reverse': { + to: { + transform: 'rotate(-360deg)', + }, + }, + }, + maxWidth: { + '2xl': '40rem', + }, + colors: { + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))', + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))', + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))', + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))', + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))', + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))', + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))', + }, + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', + '4xl': '2rem', + '5xl': '2.5rem', + }, + keyframes: { + 'accordion-down': { + from: { height: '0' }, + to: { height: 'var(--radix-accordion-content-height)' }, + }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: '0' }, + }, + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out', + 'fade-in': 'fade-in 0.5s linear forwards', + marquee: 'marquee var(--marquee-duration) linear infinite', + 'spin-slow': 'spin 4s linear infinite', + 'spin-slower': 'spin 6s linear infinite', + 'spin-reverse': 'spin-reverse 1s linear infinite', + 'spin-reverse-slow': 'spin-reverse 4s linear infinite', + 'spin-reverse-slower': 'spin-reverse 6s linear infinite', + }, + }, + }, + plugins: [require('tailwindcss-animate'), require('@tailwindcss/forms')], +}; diff --git a/examples/swaps-api-nextjs-evm-gasless/tsconfig.json b/examples/swaps-api-nextjs-evm-gasless/tsconfig.json new file mode 100644 index 0000000..0bf84cb --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/tsconfig.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "typescript-config/nextjs.json", + "compilerOptions": { + "rootDir": ".", + "baseUrl": "./src", + "plugins": [ + { + "name": "next" + } + ] + }, + "include": ["next-env.d.ts", "src", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/examples/swaps-api-nextjs-evm-gasless/turbo.json b/examples/swaps-api-nextjs-evm-gasless/turbo.json new file mode 100644 index 0000000..1dbe6de --- /dev/null +++ b/examples/swaps-api-nextjs-evm-gasless/turbo.json @@ -0,0 +1,11 @@ +{ + "extends": ["//"], + "$schema": "https://turbo.build/schema.json", + "pipeline": { + "build": { + "outputs": [".next/**", "!.next/cache/**"], + "env": ["NEXT_PUBLIC_THIRD_WEB_CLIENT_ID", "THIRD_WEB_SECRET_KEY"], + "outputMode": "new-only" + } + } +} diff --git a/examples/swaps-api-nextjs-ton/README.md b/examples/swaps-api-nextjs-ton/README.md index bb7691b..199f2ff 100644 --- a/examples/swaps-api-nextjs-ton/README.md +++ b/examples/swaps-api-nextjs-ton/README.md @@ -5,27 +5,27 @@ This example is built with: - [@swing.xyz/sdk](https://developers.swing.xyz/reference/sdk) - [@thirdweb-dev/react](https://portal.thirdweb.com/react) - [@thirdweb-dev/sdk](https://portal.thirdweb.com/typescript) -- [TronLink Wallet Adapter](https://github.com/tronprotocol/tronwallet-adapter?tab=readme-ov-file#adapters) -- [Tron React Hooks](https://github.com/web3-geek/tronwallet-adapter) +- [@tonconnect/ui-react](https://github.com/ton-connect/sdk) +- [Ton Core](https://github.com/ton-core/ton) - [Next.js App Router](https://nextjs.org) - [Tailwind CSS](https://tailwindcss.com) ## Demo -View the live demo [https://swaps-api-nextjs-tron.vercel.app](https://swaps-api-nextjs-tron.vercel.app/) +View the live demo [https://swaps-api-nextjs-ton.vercel.app](https://swaps-api-nextjs-ton.vercel.app/) ## Swing Integration > The implementation of Swing's [Cross-chain API](https://developers.swing.xyz/reference/api) and [Platform API](https://developers.swing.xyz/reference/api/platform/a2glq2e1w44ad-project-configuration) can be found in [src/components/Swap.tsx](./src/components/Swap.tsx) -This example demonstrates how you can perform a cross-chain transaction between the Tron and Ethereum chains using Swing's Cross-Chain and Platform APIs via Swing's SDK. +This example demonstrates how you can perform a cross-chain transaction between the Ton and Ethereum chains using Swing's Cross-Chain and Platform APIs via Swing's SDK. -In this example, we will be using thirdweb's SDK and **TronLink's Wallet Adapter** connector to connect to a user's Ethereum and Tron wallets, respectively. We will also demonstrate how to utilize Swing's SDK exported API functions, namely `crossChainAPI` and `platformAPI`, to build out a fully functionaly cross-chain application. +In this example, we will be using thirdweb's SDK and **Ton Connect React** connector to connect to a user's Ethereum and Ton wallets, respectively. We will also demonstrate how to utilize Swing's SDK exported API functions, namely `crossChainAPI` and `platformAPI`, to build out a fully functionaly cross-chain application. The process/steps for performing a TRX to ETH transaction, and vice versa, are as follows: - Getting a [quote](https://developers.swing.xyz/reference/api/cross-chain/1169f8cbb6937-request-a-transfer-quote) and selecting the best route -- Sending a [token approval](https://developers.swing.xyz/reference/api/contract-calls/approval) request for ERC20 Tokens. (Optional for TRON > EVM Route) +- Sending a [token approval](https://developers.swing.xyz/reference/api/contract-calls/approval) request for ERC20 Tokens. (Optional for TON > EVM Route) - Sending a [transaction](https://developers.swing.xyz/reference/api/cross-chain/d83d0d65028dc-send-transfer) > Although not essential for performing a swap transaction, providing your users with real-time updates on the transaction's status by polling the [status](https://developers.swing.xyz/reference/api/cross-chain/6b61efd1b798a-transfer-status) can significantly enhance the user experience. @@ -41,7 +41,7 @@ yarn install Next, launch the development server by running the following command: ```bash -yarn dev --filter=swaps-api-nextjs-tron +yarn dev --filter=swaps-api-nextjs-ton ``` Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website. @@ -88,18 +88,18 @@ URL: [https://swap.prod.swing.xyz/v0/transfer/quote](https://swap.prod.swing.xyz **Parameters**: -| Property | Example | Description | -| ------------------ | ------------------------------------------ | ------------------------------------------------------- | -| `tokenAmount` | 1000000000000000000 | Amount of the source token being sent (in wei for ETH). | -| `fromChain` | `ethereum` | Source Chain slug | -| `fromUserAddress` | 0x018c15DA1239B84b08283799B89045CD476BBbBb | Sender's wallet address | -| `fromTokenAddress` | 0x0000000000000000000000000000000000000000 | Source Token Address | -| `tokenSymbol` | `ETH` | Source Token slug | -| `toTokenAddress` | 0x0000000000000000000000000000000000000000 | Destination Token Address. | -| `toTokenSymbol` | `TRX` | Destination Token slug | -| `toChain` | `tron` | Destination Chain slug | -| `toUserAddress` | TV6ybRmqiUK6a7JVMRwPg2cDDkLqgR5MaZ | Receiver's wallet address | -| `projectId` | `replug` | [Your project's ID](https://platform.swing.xyz/) | +| Property | Example | Description | +| ------------------ | ------------------------------------------------ | ------------------------------------------------------- | +| `tokenAmount` | 1000000000000000000 | Amount of the source token being sent (in wei for ETH). | +| `fromChain` | `ethereum` | Source Chain slug | +| `fromUserAddress` | 0x018c15DA1239B84b08283799B89045CD476BBbBb | Sender's wallet address | +| `fromTokenAddress` | 0x0000000000000000000000000000000000000000 | Source Token Address | +| `tokenSymbol` | `ETH` | Source Token slug | +| `toTokenAddress` | 0x0000000000000000000000000000000000000000 | Destination Token Address. | +| `toTokenSymbol` | `TON` | Destination Token slug | +| `toChain` | `ton` | Destination Chain slug | +| `toUserAddress` | UQC1MtPyfhfFRtWBgZpATMo07mSlwzT8F0W2_RUKiOVCK9_d | Receiver's wallet address | +| `projectId` | `replug` | [Your project's ID](https://platform.swing.xyz/) | Navigating to our `src/services/requests.ts` file, you will find our method for getting a quote from Swing's Cross-Chain API called `getQuoteRequest()`. @@ -143,62 +143,70 @@ Each `Route` contains a `gasFee`, `bridgeFee` and the amount of tokens the desti Here's an example response that contains the route data: ```json -"routes": [ +{ + "routes": [ + { + "duration": 1, + "gas": "8213770000000", + "quote": { + "integration": "orbiter", + "type": "swap", + "bridgeFee": "1842845", + "bridgeFeeInNativeToken": "0", + "amount": "48157155", + "decimals": 6, + "amountUSD": "48.157", + "bridgeFeeUSD": "1.842", + "bridgeFeeInNativeTokenUSD": "0", + "fees": [ + { + "type": "bridge", + "amount": "1842845", + "amountUSD": "1.842", + "chainSlug": "ton", + "tokenSymbol": "jUSDC", + "tokenAddress": "EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728", + "decimals": 6, + "deductedFromSourceToken": true + }, + { + "type": "gas", + "amount": "8213770000000", + "amountUSD": "0.02138", + "chainSlug": "arbitrum", + "tokenSymbol": "ETH", + "tokenAddress": "0x0000000000000000000000000000000000000000", + "decimals": 18, + "deductedFromSourceToken": false + }, + { + "type": "partner", + "amount": "0", + "amountUSD": "0", + "chainSlug": "arbitrum", + "tokenSymbol": "USDC.e", + "tokenAddress": "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8", + "decimals": 6, + "deductedFromSourceToken": true + } + ] + }, + "route": [ { - "duration": 1, - "gas": "1260090989371730", - "quote": { - "integration": "symbiosis", - "type": "swap", - "bridgeFee": "125402496", - "bridgeFeeInNativeToken": "0", - "amount": "60720124077", - "decimals": 6, - "amountUSD": "9296.676", - "bridgeFeeUSD": "19.199", - "bridgeFeeInNativeTokenUSD": "0", - "fees": [ - { - "type": "bridge", - "amount": "125402496", - "amountUSD": "19.199", - "chainSlug": "tron", - "tokenSymbol": "TRX", - "tokenAddress": "0x0000000000000000000000000000000000000000", - "decimals": 6, - "deductedFromSourceToken": true - }, - { - "type": "gas", - "amount": "1260090989371730", - "amountUSD": "2.954", - "chainSlug": "ethereum", - "tokenSymbol": "ETH", - "tokenAddress": "0x0000000000000000000000000000000000000000", - "decimals": 18, - "deductedFromSourceToken": false - } - ] - }, - "route": [ - { - "bridge": "symbiosis", - "bridgeTokenAddress": "0x0000000000000000000000000000000000000000", - "steps": [ - "allowance", - "approve", - "send" - ], - "name": "ETH", - "part": 100 - } - ], - "distribution": { - "symbiosis": 1 - }, - "gasUSD": "2.954" + "bridge": "orbiter", + "bridgeTokenAddress": "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8", + "steps": ["allowance", "approve", "send"], + "name": "USDC.e", + "part": 100 } - ] + ], + "distribution": { + "orbiter": 1 + }, + "gasUSD": "0.02138" + } + ] +} ``` Navigating to our `src/components/Swap.tsx` file, you'll find our `defaultTransferParams` object which will store the default transaction config for our example: @@ -219,31 +227,31 @@ const defaultTransferParams: TransferParams = { toTokenAddress: "11111111111111111111111111111111", toTokenSymbol: "TRX", toNativeTokenSymbol: "TRX", - toChain: "tron", + toChain: "ton", toTokenIconUrl: "https://raw.githubusercontent.com/Pymmdrza/Cryptocurrency_Logos/mainx/SVG/sol.svg", toChainIconUrl: "https://raw.githubusercontent.com/Pymmdrza/Cryptocurrency_Logos/mainx/SVG/sol.svg", - toUserAddress: "", //tron wallet address + toUserAddress: "", //ton wallet address toChainDecimal: 9, }; ``` -## Sending a Token Approval Request for ERC20 Tokens (Optional for TRON > EVM Route) +## Sending a Token Approval Request for ERC20 Tokens (Optional for TON > EVM Route) -If you're attempting to bridge an ERC20 token from a user's wallet to Tron, you need to prompt the user to approve the required amount of tokens to be bridged. +If you're attempting to bridge an ERC20 token from a user's wallet to TON, you need to prompt the user to approve the required amount of tokens to be bridged. Navigating to our `src/components/Swap.tsx` file, inside our `startTransfer()` method, you will find our implementation of the `getAllowanceRequest()` and `getApprovalTxDataRequest()` methods. Before approving, you have to perform two checks: - First, we will check if we're performing a native currency swap by comparing the values of `tokenSymbol` and `fromNativeTokenSymbol` on the source chain. If we're not dealing with a native currency swap, we then proceed to ask for an allowance. - Next, we will check if an allowance has already been made by Swing on a user's wallet by calling the `getAllowanceRequest()` method. If no approved allowance is found, we will then proceed to make an approval request by calling the `getApprovalTxDataRequest()` method. -Since the `/approval` and `/approve` endpoints are specific to EVM chains, we have to check that source chain via `fromChain` is anything but `tron`. Skipping this check will result in the `/approval` endpoint returning an error to the user: +Since the `/approval` and `/approve` endpoints are specific to EVM chains, we have to check that source chain via `fromChain` is anything but `ton`. Skipping this check will result in the `/approval` endpoint returning an error to the user: ```json { "statusCode": 400, - "message": "Non-evm is not supported for approval method: tron", + "message": "Non-evm is not supported for approval method: ton", "error": "Bad Request" } ``` @@ -253,7 +261,7 @@ Let's execute these steps: ```typescript if ( transferParams.tokenSymbol !== transferParams.fromNativeTokenSymbol && - transferParams.fromChain !== "tron" + transferParams.fromChain !== "ton" ) { const checkAllowance = await getAllowanceRequest({ bridge: transferRoute.quote.integration, @@ -346,9 +354,9 @@ URL: [https://swap.prod.swing.xyz/v0/transfer/send](https://swap.prod.swing.xyz/ | `fromUserAddress` | 0x018c15DA1239B84b08283799B89045CD476BBbBb | Sender's wallet address | | `tokenSymbol` | ETH | Source Token slug | | `toTokenAddress` | 0x0000000000000000000000000000000000000000 | Destination Token Address. | -| `toChain` | tron | Destination Source slug | +| `toChain` | ton | Destination Source slug | | `toTokenAmount` | 4000000 | Amount of the destination token being received. | -| `toTokenSymbol` | TRX | Destination Chain slug | +| `toTokenSymbol` | TON | Destination Chain slug | | `toUserAddress` | TV6ybRmqiUK6a7JVMRwPg2cDDkLqgR5MaZ | Receiver's wallet address | | `tokenAmount` | 1000000000000000000 | Amount of the source token being sent (in wei for ETH). | | `type` | swap | Type of transaction. | @@ -442,13 +450,13 @@ export interface SendTransactionApiResponse { > The `sendTransactionRequest` will return and `id` whilst the `txResponse` will contain a `txHash` which we will need later for checking the status of a transaction. -### Sending a Tron Transaction to the Tron Network +### Sending a Ton Transaction to the Ton Network -If you've decided to perform a cross chain swap using Tron as the source chain, you'll have to sign the transaction using a wallet provider that supports the Tron Network like [TronLink](https://www.tronlink.org/). +If you've decided to perform a cross chain swap using Ton as the source chain, you'll have to sign the transaction using a wallet provider that supports the Ton Network like [Ton Keeper](https://tonkeeper.com/). > Remember, you'll have to call the `/send` endpoint via `sendTransactionRequest` before signing the transaction. -We will sign the `txData` returned from the `/send` endpoint using the **Tronlink Wallet React Hooks** library and then broadcast the transaction to the rest of the network using the **Tronlink Wallet Adapter** that comes installed with TronLink in your browser. +We will sign the `txData` returned from the `/send` endpoint using the **Ton Connect React** library. As a reminder, the `txData` from the `sendTransactionRequest` will look something like this: @@ -473,7 +481,7 @@ As a reminder, the `txData` from the `sendTransactionRequest` will look somethin > Note: You're only interested in the `meta` object in our `txData`. -To sign a callData, you have to make a request to your TronLink Wallet and pass the `meta` object to the signer function. The `meta` object contains the necessary smart contract callData to be executed. +To sign a callData, you have to make a request to your Ton Wallet and pass the `meta` object to the signer function. The `meta` object contains the necessary smart contract callData to be executed. ```typescript // Create and sign the transaction @@ -492,7 +500,7 @@ const broadcast = Putting it all together: ```typescript -// Update the sendTronTrans function +// Update the sendTonTrans function async function sendTronTrans( txData: TransactionData, ): Promise { diff --git a/examples/swaps-api-nextjs-ton/package.json b/examples/swaps-api-nextjs-ton/package.json index 9b7cd9e..097a318 100644 --- a/examples/swaps-api-nextjs-ton/package.json +++ b/examples/swaps-api-nextjs-ton/package.json @@ -31,9 +31,6 @@ "@thirdweb-dev/react": "^4.4.17", "@thirdweb-dev/sdk": "^4.0.44", "@tonconnect/ui-react": "^2.0.9", - "@tronweb3/tronwallet-adapter-react-hooks": "^1.1.7", - "@tronweb3/tronwallet-adapter-react-ui": "^1.1.8", - "@tronweb3/tronwallet-adapters": "^1.2.3", "axios": "^1.6.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", diff --git a/examples/swaps-api-nextjs-ton/src/components/ui/Hero.tsx b/examples/swaps-api-nextjs-ton/src/components/ui/Hero.tsx index 7957100..e96dfd8 100644 --- a/examples/swaps-api-nextjs-ton/src/components/ui/Hero.tsx +++ b/examples/swaps-api-nextjs-ton/src/components/ui/Hero.tsx @@ -4,21 +4,15 @@ import React from "react"; import { Container } from "./Container"; import SwapSDK from "../Swap"; -import { TronLinkAdapter } from "@tronweb3/tronwallet-adapters"; -import { WalletProvider } from "@tronweb3/tronwallet-adapter-react-hooks"; export function Hero() { - const adapters = [new TronLinkAdapter()]; - return ( - - - - - - - - - + + + + + + + ); } diff --git a/yarn.lock b/yarn.lock index 867c29a..e85af4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -58,6 +58,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:^1.10.1, @adraffy/ens-normalize@npm:^1.11.0": + version: 1.11.0 + resolution: "@adraffy/ens-normalize@npm:1.11.0" + checksum: 10/abef75f21470ea43dd6071168e092d2d13e38067e349e76186c78838ae174a46c3e18ca50921d05bea6ec3203074147c9e271f8cb6531d1c2c0e146f3199ddcb + languageName: node + linkType: hard + "@alloc/quick-lru@npm:^5.2.0": version: 5.2.0 resolution: "@alloc/quick-lru@npm:5.2.0" @@ -3578,6 +3585,18 @@ __metadata: languageName: node linkType: hard +"@coinbase/wallet-sdk@npm:4.3.0": + version: 4.3.0 + resolution: "@coinbase/wallet-sdk@npm:4.3.0" + dependencies: + "@noble/hashes": "npm:^1.4.0" + clsx: "npm:^1.2.1" + eventemitter3: "npm:^5.0.1" + preact: "npm:^10.24.2" + checksum: 10/56d24aaf5170d05fafe4cdafa06a000e259f3f9f3eae7879bcb5e1c316e5e3d85754639f31d3e366ed208f1667cb7d10d3c7bcae8e40cb5f46bea7c291d7c2bf + languageName: node + linkType: hard + "@coinbase/wallet-sdk@npm:^3.6.6, @coinbase/wallet-sdk@npm:^3.7.2": version: 3.9.3 resolution: "@coinbase/wallet-sdk@npm:3.9.3" @@ -4119,6 +4138,25 @@ __metadata: languageName: node linkType: hard +"@emotion/babel-plugin@npm:^11.13.5": + version: 11.13.5 + resolution: "@emotion/babel-plugin@npm:11.13.5" + dependencies: + "@babel/helper-module-imports": "npm:^7.16.7" + "@babel/runtime": "npm:^7.18.3" + "@emotion/hash": "npm:^0.9.2" + "@emotion/memoize": "npm:^0.9.0" + "@emotion/serialize": "npm:^1.3.3" + babel-plugin-macros: "npm:^3.1.0" + convert-source-map: "npm:^1.5.0" + escape-string-regexp: "npm:^4.0.0" + find-root: "npm:^1.1.0" + source-map: "npm:^0.5.7" + stylis: "npm:4.2.0" + checksum: 10/cd310568314d886ca328e504f84c4f7f9c7f092ea34a2b43fdb61f84665bf301ba2ef49e0fd1e7ded3d81363d9bbefbb32674ce88b317cfb64db2b65e5ff423f + languageName: node + linkType: hard + "@emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/cache@npm:11.11.0" @@ -4132,6 +4170,19 @@ __metadata: languageName: node linkType: hard +"@emotion/cache@npm:^11.14.0": + version: 11.14.0 + resolution: "@emotion/cache@npm:11.14.0" + dependencies: + "@emotion/memoize": "npm:^0.9.0" + "@emotion/sheet": "npm:^1.4.0" + "@emotion/utils": "npm:^1.4.2" + "@emotion/weak-memoize": "npm:^0.4.0" + stylis: "npm:4.2.0" + checksum: 10/52336b28a27b07dde8fcdfd80851cbd1487672bbd4db1e24cca1440c95d8a6a968c57b0453c2b7c88d9b432b717f99554dbecc05b5cdef27933299827e69fd8e + languageName: node + linkType: hard + "@emotion/css@npm:11.10.5": version: 11.10.5 resolution: "@emotion/css@npm:11.10.5" @@ -4157,6 +4208,13 @@ __metadata: languageName: node linkType: hard +"@emotion/hash@npm:^0.9.2": + version: 0.9.2 + resolution: "@emotion/hash@npm:0.9.2" + checksum: 10/379bde2830ccb0328c2617ec009642321c0e009a46aa383dfbe75b679c6aea977ca698c832d225a893901f29d7b3eef0e38cf341f560f6b2b56f1ff23c172387 + languageName: node + linkType: hard + "@emotion/is-prop-valid@npm:^0.8.2": version: 0.8.8 resolution: "@emotion/is-prop-valid@npm:0.8.8" @@ -4175,6 +4233,15 @@ __metadata: languageName: node linkType: hard +"@emotion/is-prop-valid@npm:^1.3.0": + version: 1.3.1 + resolution: "@emotion/is-prop-valid@npm:1.3.1" + dependencies: + "@emotion/memoize": "npm:^0.9.0" + checksum: 10/abbc5c7bf4017415da5b06067fc0b4771d1f22cf94ec37fd54c07b3bd1bcffbda2405ca686e7ee64a9cfc51461262b712f724850e838775347a949f72949ad03 + languageName: node + linkType: hard + "@emotion/memoize@npm:0.7.4": version: 0.7.4 resolution: "@emotion/memoize@npm:0.7.4" @@ -4189,6 +4256,34 @@ __metadata: languageName: node linkType: hard +"@emotion/memoize@npm:^0.9.0": + version: 0.9.0 + resolution: "@emotion/memoize@npm:0.9.0" + checksum: 10/038132359397348e378c593a773b1148cd0cf0a2285ffd067a0f63447b945f5278860d9de718f906a74c7c940ba1783ac2ca18f1c06a307b01cc0e3944e783b1 + languageName: node + linkType: hard + +"@emotion/react@npm:11.14.0": + version: 11.14.0 + resolution: "@emotion/react@npm:11.14.0" + dependencies: + "@babel/runtime": "npm:^7.18.3" + "@emotion/babel-plugin": "npm:^11.13.5" + "@emotion/cache": "npm:^11.14.0" + "@emotion/serialize": "npm:^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.2.0" + "@emotion/utils": "npm:^1.4.2" + "@emotion/weak-memoize": "npm:^0.4.0" + hoist-non-react-statics: "npm:^3.3.1" + peerDependencies: + react: ">=16.8.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/3356c1d66f37f4e7abf88a2be843f6023b794b286c9c99a0aaf1cd1b2b7c50f8d80a2ef77183da737de70150f638e698ff4a2a38ab2d922f868615f1d5761c37 + languageName: node + linkType: hard + "@emotion/react@npm:^11.10.6, @emotion/react@npm:^11.11.4": version: 11.11.4 resolution: "@emotion/react@npm:11.11.4" @@ -4223,6 +4318,19 @@ __metadata: languageName: node linkType: hard +"@emotion/serialize@npm:^1.3.3": + version: 1.3.3 + resolution: "@emotion/serialize@npm:1.3.3" + dependencies: + "@emotion/hash": "npm:^0.9.2" + "@emotion/memoize": "npm:^0.9.0" + "@emotion/unitless": "npm:^0.10.0" + "@emotion/utils": "npm:^1.4.2" + csstype: "npm:^3.0.2" + checksum: 10/44a2e06fc52dba177d9cf720f7b2c5d45ee4c0d9c09b78302d9a625e758d728ef3ae26f849237fec6f70e9eeb7d87e45a65028e944dc1f877df97c599f1cdaee + languageName: node + linkType: hard + "@emotion/sheet@npm:^1.2.1, @emotion/sheet@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/sheet@npm:1.2.2" @@ -4230,6 +4338,13 @@ __metadata: languageName: node linkType: hard +"@emotion/sheet@npm:^1.4.0": + version: 1.4.0 + resolution: "@emotion/sheet@npm:1.4.0" + checksum: 10/8ac6e9bf6b373a648f26ae7f1c24041038524f4c72f436f4f8c4761c665e58880c3229d8d89b1f7a4815dd8e5b49634d03e60187cb6f93097d7f7c1859e869d5 + languageName: node + linkType: hard + "@emotion/styled@npm:11.11.0, @emotion/styled@npm:^11.10.6, @emotion/styled@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/styled@npm:11.11.0" @@ -4250,6 +4365,33 @@ __metadata: languageName: node linkType: hard +"@emotion/styled@npm:11.14.1": + version: 11.14.1 + resolution: "@emotion/styled@npm:11.14.1" + dependencies: + "@babel/runtime": "npm:^7.18.3" + "@emotion/babel-plugin": "npm:^11.13.5" + "@emotion/is-prop-valid": "npm:^1.3.0" + "@emotion/serialize": "npm:^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.2.0" + "@emotion/utils": "npm:^1.4.2" + peerDependencies: + "@emotion/react": ^11.0.0-rc.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/b20ffaaac76e16538051da8d417f1da75f47f0974000edf0999f39f309b23ee0a91ba7dc1d5f60c4017d29fadfed48631ae4a8f697e3662a88318c667d072117 + languageName: node + linkType: hard + +"@emotion/unitless@npm:^0.10.0": + version: 0.10.0 + resolution: "@emotion/unitless@npm:0.10.0" + checksum: 10/6851c16edce01c494305f43b2cad7a26b939a821131b7c354e49b8e3b012c8810024755b0f4a03ef51117750309e55339825a97bd10411fb3687e68904769106 + languageName: node + linkType: hard + "@emotion/unitless@npm:^0.8.1": version: 0.8.1 resolution: "@emotion/unitless@npm:0.8.1" @@ -4266,6 +4408,15 @@ __metadata: languageName: node linkType: hard +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.2.0" + peerDependencies: + react: ">=16.8.0" + checksum: 10/2374999db8d53ef661d61ed1026c42a849632e4f03826f7eba0314c1d92ae342161d737f5045453aa46dd4008e13ccefeba68d3165b667dfad8e5784fcb0c643 + languageName: node + linkType: hard + "@emotion/utils@npm:^1.2.0, @emotion/utils@npm:^1.2.1": version: 1.2.1 resolution: "@emotion/utils@npm:1.2.1" @@ -4273,6 +4424,13 @@ __metadata: languageName: node linkType: hard +"@emotion/utils@npm:^1.4.2": + version: 1.4.2 + resolution: "@emotion/utils@npm:1.4.2" + checksum: 10/e5f3b8bca066b3361a7ad9064baeb9d01ed1bf51d98416a67359b62cb3affec6bb0249802c4ed11f4f8030f93cc4b67506909420bdb110adec6983d712897208 + languageName: node + linkType: hard + "@emotion/weak-memoize@npm:^0.3.1": version: 0.3.1 resolution: "@emotion/weak-memoize@npm:0.3.1" @@ -4280,6 +4438,13 @@ __metadata: languageName: node linkType: hard +"@emotion/weak-memoize@npm:^0.4.0": + version: 0.4.0 + resolution: "@emotion/weak-memoize@npm:0.4.0" + checksum: 10/db5da0e89bd752c78b6bd65a1e56231f0abebe2f71c0bd8fc47dff96408f7065b02e214080f99924f6a3bfe7ee15afc48dad999d76df86b39b16e513f7a94f52 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.17.8": version: 0.17.8 resolution: "@esbuild/android-arm64@npm:0.17.8" @@ -5337,6 +5502,15 @@ __metadata: languageName: node linkType: hard +"@hey-api/client-fetch@npm:0.10.0": + version: 0.10.0 + resolution: "@hey-api/client-fetch@npm:0.10.0" + peerDependencies: + "@hey-api/openapi-ts": < 2 + checksum: 10/f77dc512047f2fcbba4a1be079020c6c821391b34da426079e1e306ee2ee9f83e7f1130ad7a697a340f2e29bde1e0ce8af3b88a4f8631b849426bd7b2cc24fb9 + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" @@ -6272,6 +6446,13 @@ __metadata: languageName: node linkType: hard +"@msgpack/msgpack@npm:3.1.2": + version: 3.1.2 + resolution: "@msgpack/msgpack@npm:3.1.2" + checksum: 10/e04ff37d7c89ffdd6b4fbcd1770af60b16c98afdf1c3c16190170dfe34764048eb45e3654016ac62cc616c7e4b09e611f8863317ca5f18b3a72974fb131e562e + languageName: node + linkType: hard + "@multiformats/base-x@npm:^4.0.1": version: 4.0.1 resolution: "@multiformats/base-x@npm:4.0.1" @@ -6575,6 +6756,20 @@ __metadata: languageName: node linkType: hard +"@noble/ciphers@npm:1.2.1": + version: 1.2.1 + resolution: "@noble/ciphers@npm:1.2.1" + checksum: 10/7fa0d32529d8da6323b08afec97218f6d6bc0d1e135243bf10f7587a2819495c3f3f4a5af1f41045501bb1ade94238c76960366a5d6441970e49ba9cacb88740 + languageName: node + linkType: hard + +"@noble/ciphers@npm:1.3.0, @noble/ciphers@npm:^1.3.0": + version: 1.3.0 + resolution: "@noble/ciphers@npm:1.3.0" + checksum: 10/051660051e3e9e2ca5fb9dece2885532b56b7e62946f89afa7284a0fb8bc02e2bd1c06554dba68162ff42d295b54026456084198610f63c296873b2f1cd7a586 + languageName: node + linkType: hard + "@noble/curves@npm:1.0.0, @noble/curves@npm:~1.0.0": version: 1.0.0 resolution: "@noble/curves@npm:1.0.0" @@ -6611,7 +6806,52 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:^1.1.0, @noble/curves@npm:~1.9.0": +"@noble/curves@npm:1.8.0": + version: 1.8.0 + resolution: "@noble/curves@npm:1.8.0" + dependencies: + "@noble/hashes": "npm:1.7.0" + checksum: 10/c54ce84cf54b8bda1a37a10dfae2e49e5b6cdf5dd98b399efa8b8a80a286b3f8f27bde53202cb308353bfd98719938991a78bed6e43f81f13b17f8181b7b82eb + languageName: node + linkType: hard + +"@noble/curves@npm:1.8.1": + version: 1.8.1 + resolution: "@noble/curves@npm:1.8.1" + dependencies: + "@noble/hashes": "npm:1.7.1" + checksum: 10/e861db372cc0734b02a4c61c0f5a6688d4a7555edca3d8a9e7c846c9aa103ca52d3c3818e8bc333a1a95b5be7f370ff344668d5d759471b11c2d14c7f24b3984 + languageName: node + linkType: hard + +"@noble/curves@npm:1.8.2, @noble/curves@npm:~1.8.1": + version: 1.8.2 + resolution: "@noble/curves@npm:1.8.2" + dependencies: + "@noble/hashes": "npm:1.7.2" + checksum: 10/540e7b7a8fe92ecd5cef846f84d07180662eb7fd7d8e9172b8960c31827e74f148fe4630da962138a6be093ae9f8992d14ab23d3682a2cc32be839aa57c03a46 + languageName: node + linkType: hard + +"@noble/curves@npm:1.9.1": + version: 1.9.1 + resolution: "@noble/curves@npm:1.9.1" + dependencies: + "@noble/hashes": "npm:1.8.0" + checksum: 10/5c82ec828ca4a4218b1666ba0ddffde17afd224d0bd5e07b64c2a0c83a3362483387f55c11cfd8db0fc046605394fe4e2c67fe024628a713e864acb541a7d2bb + languageName: node + linkType: hard + +"@noble/curves@npm:1.9.2": + version: 1.9.2 + resolution: "@noble/curves@npm:1.9.2" + dependencies: + "@noble/hashes": "npm:1.8.0" + checksum: 10/f60f00ad86296054566b67be08fd659999bb64b692bfbf11dbe3be1f422ad4d826bf5ebb2015ce2e246538eab2b677707e0a46ffa8323a6fae7a9a30ec1fe318 + languageName: node + linkType: hard + +"@noble/curves@npm:^1.1.0, @noble/curves@npm:^1.6.0, @noble/curves@npm:^1.9.1, @noble/curves@npm:~1.9.0": version: 1.9.7 resolution: "@noble/curves@npm:1.9.7" dependencies: @@ -6666,7 +6906,28 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.3.0, @noble/hashes@npm:~1.8.0": +"@noble/hashes@npm:1.7.0": + version: 1.7.0 + resolution: "@noble/hashes@npm:1.7.0" + checksum: 10/ab038a816c8c9bb986e92797e3d9c5a5b37c020e0c3edc55bcae5061dbdd457f1f0a22787f83f4787c17415ba0282a20a1e455d36ed0cdcace4ce21ef1869f60 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.7.1": + version: 1.7.1 + resolution: "@noble/hashes@npm:1.7.1" + checksum: 10/ca3120da0c3e7881d6a481e9667465cc9ebbee1329124fb0de442e56d63fef9870f8cc96f264ebdb18096e0e36cebc0e6e979a872d545deb0a6fed9353f17e05 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.7.2, @noble/hashes@npm:~1.7.1": + version: 1.7.2 + resolution: "@noble/hashes@npm:1.7.2" + checksum: 10/b5af9e4b91543dcc46a811b5b2c57bfdeb41728361979a19d6110a743e2cb0459872553f68d3a46326d21959964db2776b8c8b4db85ac1d9f63ebcaddf7d59b6 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.3.0, @noble/hashes@npm:^1.5.0, @noble/hashes@npm:^1.8.0, @noble/hashes@npm:~1.8.0": version: 1.8.0 resolution: "@noble/hashes@npm:1.8.0" checksum: 10/474b7f56bc6fb2d5b3a42132561e221b0ea4f91e590f4655312ca13667840896b34195e2b53b7f097ec080a1fdd3b58d902c2a8d0fbdf51d2e238b53808a177e @@ -6992,6 +7253,13 @@ __metadata: languageName: node linkType: hard +"@passwordless-id/webauthn@npm:^2.1.2": + version: 2.3.1 + resolution: "@passwordless-id/webauthn@npm:2.3.1" + checksum: 10/c7043a3e5296145e9cd95d1f8aaed991a2bc4c27e642a23033c5881fb10273ca7c96f318e13df31c00c7b342b11c1ab9240aaafe57c6bc72da4fc31f59eb7747 + languageName: node + linkType: hard + "@peculiar/asn1-schema@npm:^2.3.13, @peculiar/asn1-schema@npm:^2.3.8": version: 2.3.13 resolution: "@peculiar/asn1-schema@npm:2.3.13" @@ -7185,6 +7453,13 @@ __metadata: languageName: node linkType: hard +"@radix-ui/primitive@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/primitive@npm:1.1.2" + checksum: 10/6cb2ac097faf77b7288bdfd87d92e983e357252d00ee0d2b51ad8e7897bf9f51ec53eafd7dd64c613671a2b02cb8166177bc3de444a6560ec60835c363321c18 + languageName: node + linkType: hard + "@radix-ui/primitive@npm:1.1.3": version: 1.1.3 resolution: "@radix-ui/primitive@npm:1.1.3" @@ -7253,6 +7528,25 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-arrow@npm:1.1.7": + version: 1.1.7 + resolution: "@radix-ui/react-arrow@npm:1.1.7" + dependencies: + "@radix-ui/react-primitive": "npm:2.1.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/6cdf74f06090f8994cdf6d3935a44ea3ac309163a4f59c476482c4907e8e0775f224045030abf10fa4f9e1cb7743db034429249b9e59354988e247eeb0f4fdcf + languageName: node + linkType: hard + "@radix-ui/react-avatar@npm:^1.0.4": version: 1.0.4 resolution: "@radix-ui/react-avatar@npm:1.0.4" @@ -7447,6 +7741,38 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-dialog@npm:1.1.14": + version: 1.1.14 + resolution: "@radix-ui/react-dialog@npm:1.1.14" + dependencies: + "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-dismissable-layer": "npm:1.1.10" + "@radix-ui/react-focus-guards": "npm:1.1.2" + "@radix-ui/react-focus-scope": "npm:1.1.7" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-portal": "npm:1.1.9" + "@radix-ui/react-presence": "npm:1.1.4" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-slot": "npm:1.2.3" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + aria-hidden: "npm:^1.2.4" + react-remove-scroll: "npm:^2.6.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/b87f8a4cec795cb7f956eec669c9452ac33a3c1a77b2872193b0feb231e10c00640bc734ba4209ac1f6bbf29d2e619828834fd208179619a8e1317ff87cb6e71 + languageName: node + linkType: hard + "@radix-ui/react-dialog@npm:^1.0.2": version: 1.1.15 resolution: "@radix-ui/react-dialog@npm:1.1.15" @@ -7579,6 +7905,29 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-dismissable-layer@npm:1.1.10": + version: 1.1.10 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.10" + dependencies: + "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-escape-keydown": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/e08733ee345521a09100f922191302960d87a723d3bebb804f5659ff37f2fae57e335b2debad5ac17cb929be6b1fa8bc092c016723665ea8c90f7cf396c92d3b + languageName: node + linkType: hard + "@radix-ui/react-dismissable-layer@npm:1.1.11": version: 1.1.11 resolution: "@radix-ui/react-dismissable-layer@npm:1.1.11" @@ -7647,6 +7996,19 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-focus-guards@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-focus-guards@npm:1.1.2" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/618658e2b98575198b94ccfdd27f41beb37f83721c9a04617e848afbc47461124ae008d703d713b9644771d96d4852e49de322cf4be3b5f10a4f94d200db5248 + languageName: node + linkType: hard + "@radix-ui/react-focus-guards@npm:1.1.3": version: 1.1.3 resolution: "@radix-ui/react-focus-guards@npm:1.1.3" @@ -7727,6 +8089,15 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-icons@npm:1.3.2": + version: 1.3.2 + resolution: "@radix-ui/react-icons@npm:1.3.2" + peerDependencies: + react: ^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc + checksum: 10/cf6c694a400677890d0d83cd30ac01fa638c04eefe6194cd4e3c9edff49269e97dccc01e7bb480e2dcc249b27ee4eafa5d82d72d15c5119d66f4c26db6128f36 + languageName: node + linkType: hard + "@radix-ui/react-id@npm:1.0.0": version: 1.0.0 resolution: "@radix-ui/react-id@npm:1.0.0" @@ -7904,6 +8275,34 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-popper@npm:1.2.7": + version: 1.2.7 + resolution: "@radix-ui/react-popper@npm:1.2.7" + dependencies: + "@floating-ui/react-dom": "npm:^2.0.0" + "@radix-ui/react-arrow": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + "@radix-ui/react-use-rect": "npm:1.1.1" + "@radix-ui/react-use-size": "npm:1.1.1" + "@radix-ui/rect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/1d1bcb679f914cd01649fdd5106b3a845d9f68cf0660c209e29baf95e92f9ac8a97e5bb8b56911b11b0291db8d4b6c8adc4040af23e0149e4235e669f5f4703b + languageName: node + linkType: hard + "@radix-ui/react-portal@npm:1.0.0": version: 1.0.0 resolution: "@radix-ui/react-portal@npm:1.0.0" @@ -7992,6 +8391,26 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-presence@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-presence@npm:1.1.4" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/ba01f385f6beedba7bf50ffd4aca8091554a67aee2b7252605876136155ceb2fcf1b627dccaf2e49032231eda271fe0e8915040729da9d1f95d08b854d815305 + languageName: node + linkType: hard + "@radix-ui/react-presence@npm:1.1.5": version: 1.1.5 resolution: "@radix-ui/react-presence@npm:1.1.5" @@ -8282,6 +8701,36 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-tooltip@npm:1.2.7": + version: 1.2.7 + resolution: "@radix-ui/react-tooltip@npm:1.2.7" + dependencies: + "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-dismissable-layer": "npm:1.1.10" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-popper": "npm:1.2.7" + "@radix-ui/react-portal": "npm:1.1.9" + "@radix-ui/react-presence": "npm:1.1.4" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-slot": "npm:1.2.3" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + "@radix-ui/react-visually-hidden": "npm:1.2.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/c52f46592ee4f2239d87f41de5d9bc3e788095968da65e759f51a75de10401c76daa6a4ec034158f130da779e149989d2e01560793bc17ac79b09d575e30b0e7 + languageName: node + linkType: hard + "@radix-ui/react-tooltip@npm:^1.0.7": version: 1.0.7 resolution: "@radix-ui/react-tooltip@npm:1.0.7" @@ -8536,6 +8985,21 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-use-rect@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-use-rect@npm:1.1.1" + dependencies: + "@radix-ui/rect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/116461bebc49472f7497e66a9bd413541181b3d00c5e0aaeef45d790dc1fbd7c8dcea80b169ea273306228b9a3c2b70067e902d1fd5004b3057e3bbe35b9d55d + languageName: node + linkType: hard + "@radix-ui/react-use-size@npm:1.0.0": version: 1.0.0 resolution: "@radix-ui/react-use-size@npm:1.0.0" @@ -8564,6 +9028,21 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-use-size@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-use-size@npm:1.1.1" + dependencies: + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/64e61f65feb67ffc80e1fc4a8d5e32480fb6d68475e2640377e021178dead101568cba5f936c9c33e6c142c7cf2fb5d76ad7b23ef80e556ba142d56cf306147b + languageName: node + linkType: hard + "@radix-ui/react-visually-hidden@npm:1.0.3": version: 1.0.3 resolution: "@radix-ui/react-visually-hidden@npm:1.0.3" @@ -8584,6 +9063,25 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-visually-hidden@npm:1.2.3": + version: 1.2.3 + resolution: "@radix-ui/react-visually-hidden@npm:1.2.3" + dependencies: + "@radix-ui/react-primitive": "npm:2.1.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/42296bde1ddf4af4e7445e914c35d6bc8406d6ede49f0a959a553e75b3ed21da09fda80a81c48d8ec058ed8129ce7137499d02ee26f90f0d3eaa2417922d6509 + languageName: node + linkType: hard + "@radix-ui/rect@npm:1.0.0": version: 1.0.0 resolution: "@radix-ui/rect@npm:1.0.0" @@ -8602,6 +9100,13 @@ __metadata: languageName: node linkType: hard +"@radix-ui/rect@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/rect@npm:1.1.1" + checksum: 10/b6c5eb787640775b53dd52fa47218a089f0a0d8220d3ebff079c0b754e1fb82d89b6bdf08a82fd0d59549bdeb52678c0cca091c302da49dcf74c3c989cb55678 + languageName: node + linkType: hard + "@react-native-async-storage/async-storage@npm:^1.17.11": version: 1.22.3 resolution: "@react-native-async-storage/async-storage@npm:1.22.3" @@ -8823,6 +9328,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:1.2.6, @scure/base@npm:~1.2.2, @scure/base@npm:~1.2.4, @scure/base@npm:~1.2.5": + version: 1.2.6 + resolution: "@scure/base@npm:1.2.6" + checksum: 10/c1a7bd5e0b0c8f94c36fbc220f4a67cc832b00e2d2065c7d8a404ed81ab1c94c5443def6d361a70fc382db3496e9487fb9941728f0584782b274c18a4bed4187 + languageName: node + linkType: hard + "@scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2": version: 1.1.5 resolution: "@scure/base@npm:1.1.5" @@ -8844,13 +9356,6 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:~1.2.5": - version: 1.2.6 - resolution: "@scure/base@npm:1.2.6" - checksum: 10/c1a7bd5e0b0c8f94c36fbc220f4a67cc832b00e2d2065c7d8a404ed81ab1c94c5443def6d361a70fc382db3496e9487fb9941728f0584782b274c18a4bed4187 - languageName: node - linkType: hard - "@scure/bip32@npm:1.3.0": version: 1.3.0 resolution: "@scure/bip32@npm:1.3.0" @@ -8895,7 +9400,18 @@ __metadata: languageName: node linkType: hard -"@scure/bip32@npm:^1.3.1": +"@scure/bip32@npm:1.6.2": + version: 1.6.2 + resolution: "@scure/bip32@npm:1.6.2" + dependencies: + "@noble/curves": "npm:~1.8.1" + "@noble/hashes": "npm:~1.7.1" + "@scure/base": "npm:~1.2.2" + checksum: 10/474ee315a8631aa1a7d378b0521b4494e09a231519ec53d879088cb88c8ff644a89b27a02a8bf0b5a9b1c4c0417acc70636ccdb121b800c34594ae53c723f8d7 + languageName: node + linkType: hard + +"@scure/bip32@npm:1.7.0, @scure/bip32@npm:^1.3.1, @scure/bip32@npm:^1.5.0, @scure/bip32@npm:^1.7.0": version: 1.7.0 resolution: "@scure/bip32@npm:1.7.0" dependencies: @@ -8936,7 +9452,17 @@ __metadata: languageName: node linkType: hard -"@scure/bip39@npm:^1.2.1": +"@scure/bip39@npm:1.5.4": + version: 1.5.4 + resolution: "@scure/bip39@npm:1.5.4" + dependencies: + "@noble/hashes": "npm:~1.7.1" + "@scure/base": "npm:~1.2.4" + checksum: 10/9f08b433511d7637bc48c51aa411457d5f33da5a85bd03370bf394822b0ea8c007ceb17247a3790c28237303d8fc20c4e7725765940cd47e1365a88319ad0d5c + languageName: node + linkType: hard + +"@scure/bip39@npm:1.6.0, @scure/bip39@npm:^1.2.1, @scure/bip39@npm:^1.4.0, @scure/bip39@npm:^1.6.0": version: 1.6.0 resolution: "@scure/bip39@npm:1.6.0" dependencies: @@ -9437,6 +9963,42 @@ __metadata: languageName: node linkType: hard +"@storybook/global@npm:^5.0.0": + version: 5.0.0 + resolution: "@storybook/global@npm:5.0.0" + checksum: 10/0e7b495f4fe7f36447e793926f1c0460ec07fd66f0da68e3150da5878f6043c9eeb9b41614a45c5ec0d48d5d383c59ca8f88b6dc7882a2a784ac9b20375d8edb + languageName: node + linkType: hard + +"@storybook/react-dom-shim@npm:9.0.15": + version: 9.0.15 + resolution: "@storybook/react-dom-shim@npm:9.0.15" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^9.0.15 + checksum: 10/f83d768ac21b9eb91e8e92a4c67a7757de49f3cc27d31e89ac165e47c6876dc309b12a2be3a545665c17622435a10688e7cf709b163aeb251eea8902bde3e428 + languageName: node + linkType: hard + +"@storybook/react@npm:9.0.15": + version: 9.0.15 + resolution: "@storybook/react@npm:9.0.15" + dependencies: + "@storybook/global": "npm:^5.0.0" + "@storybook/react-dom-shim": "npm:9.0.15" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^9.0.15 + typescript: ">= 4.9.x" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/3a4c2a4a52d12c78787f5c67812d5d0f91accb9cbe88d935dcd5997a47c5221ad2dd5ec958dd7fdf8db71628e3a4cb65b13dbfa83b4f195c85c1cf9f8341831f + languageName: node + linkType: hard + "@suchipi/femver@npm:^1.0.0": version: 1.0.0 resolution: "@suchipi/femver@npm:1.0.0" @@ -9979,6 +10541,24 @@ __metadata: languageName: node linkType: hard +"@tanstack/query-core@npm:5.81.5": + version: 5.81.5 + resolution: "@tanstack/query-core@npm:5.81.5" + checksum: 10/a324ab3380c1c282b95520de8b74af537cfe6b44ae06b6639b3e7a70757c81c2db03f765c27aa770d6c44ef8e1f7cbba243863021ded53fff965a522d1e5f698 + languageName: node + linkType: hard + +"@tanstack/react-query@npm:5.81.5": + version: 5.81.5 + resolution: "@tanstack/react-query@npm:5.81.5" + dependencies: + "@tanstack/query-core": "npm:5.81.5" + peerDependencies: + react: ^18 || ^19 + checksum: 10/35c75cf902938a76d468c0e1f08d738afc989ddc3728c4d2c00b16975870500da98aea21c1a682726abb3ef5f6348cb739335e3b940224ccc527b27dddc20fd4 + languageName: node + linkType: hard + "@tanstack/react-query@npm:^4.36.1": version: 4.36.1 resolution: "@tanstack/react-query@npm:4.36.1" @@ -10213,6 +10793,20 @@ __metadata: languageName: node linkType: hard +"@thirdweb-dev/engine@npm:3.2.1": + version: 3.2.1 + resolution: "@thirdweb-dev/engine@npm:3.2.1" + dependencies: + "@hey-api/client-fetch": "npm:0.10.0" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/71175d133232e54bac54a69218c0606426e9b1eb11ee595dcc5037fa1a78e736d246943706d37382819adf0450f2304c0cb224b60ee33544423981002b983113 + languageName: node + linkType: hard + "@thirdweb-dev/generated-abis@npm:0.0.1, @thirdweb-dev/generated-abis@npm:^0.0.1": version: 0.0.1 resolution: "@thirdweb-dev/generated-abis@npm:0.0.1" @@ -10220,6 +10814,18 @@ __metadata: languageName: node linkType: hard +"@thirdweb-dev/insight@npm:1.1.1": + version: 1.1.1 + resolution: "@thirdweb-dev/insight@npm:1.1.1" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/01099a9c07ddc5ee6ba3636e1ea91214a6ba7c8f2204828857321944c48468bc4e88fc8261eef9f81ce6d0d2b92c7d07822ffd9913150d06f200c5d121c51863 + languageName: node + linkType: hard + "@thirdweb-dev/merkletree@npm:0.2.3": version: 0.2.3 resolution: "@thirdweb-dev/merkletree@npm:0.2.3" @@ -12003,6 +12609,56 @@ __metadata: languageName: node linkType: hard +"@walletconnect/core@npm:2.20.1": + version: 2.20.1 + resolution: "@walletconnect/core@npm:2.20.1" + dependencies: + "@walletconnect/heartbeat": "npm:1.2.2" + "@walletconnect/jsonrpc-provider": "npm:1.0.14" + "@walletconnect/jsonrpc-types": "npm:1.0.4" + "@walletconnect/jsonrpc-utils": "npm:1.0.8" + "@walletconnect/jsonrpc-ws-connection": "npm:1.0.16" + "@walletconnect/keyvaluestorage": "npm:1.1.1" + "@walletconnect/logger": "npm:2.1.2" + "@walletconnect/relay-api": "npm:1.0.11" + "@walletconnect/relay-auth": "npm:1.1.0" + "@walletconnect/safe-json": "npm:1.0.2" + "@walletconnect/time": "npm:1.0.2" + "@walletconnect/types": "npm:2.20.1" + "@walletconnect/utils": "npm:2.20.1" + "@walletconnect/window-getters": "npm:1.0.1" + es-toolkit: "npm:1.33.0" + events: "npm:3.3.0" + uint8arrays: "npm:3.1.0" + checksum: 10/8c3ec9e62afb532257a5211aad0022412592952a3d6b02341f17fd7c1f0d3b76c360e93f5071e266c5ace4ef791d7b518d5b599b65a76084009c718c6d568c66 + languageName: node + linkType: hard + +"@walletconnect/core@npm:2.21.4": + version: 2.21.4 + resolution: "@walletconnect/core@npm:2.21.4" + dependencies: + "@walletconnect/heartbeat": "npm:1.2.2" + "@walletconnect/jsonrpc-provider": "npm:1.0.14" + "@walletconnect/jsonrpc-types": "npm:1.0.4" + "@walletconnect/jsonrpc-utils": "npm:1.0.8" + "@walletconnect/jsonrpc-ws-connection": "npm:1.0.16" + "@walletconnect/keyvaluestorage": "npm:1.1.1" + "@walletconnect/logger": "npm:2.1.2" + "@walletconnect/relay-api": "npm:1.0.11" + "@walletconnect/relay-auth": "npm:1.1.0" + "@walletconnect/safe-json": "npm:1.0.2" + "@walletconnect/time": "npm:1.0.2" + "@walletconnect/types": "npm:2.21.4" + "@walletconnect/utils": "npm:2.21.4" + "@walletconnect/window-getters": "npm:1.0.1" + es-toolkit: "npm:1.39.3" + events: "npm:3.3.0" + uint8arrays: "npm:3.1.1" + checksum: 10/3f206088b06c34fc6fe71c9a8463d9e6f0d123d99c8b9d74d449c7a70e58ea28b15ca109b7d79742a0e424db02b27f15c466e623138902ee9d776cd07c5f31bf + languageName: node + linkType: hard + "@walletconnect/core@npm:^2.10.1, @walletconnect/core@npm:^2.11.3": version: 2.12.0 resolution: "@walletconnect/core@npm:2.12.0" @@ -12255,6 +12911,18 @@ __metadata: languageName: node linkType: hard +"@walletconnect/jsonrpc-ws-connection@npm:1.0.16": + version: 1.0.16 + resolution: "@walletconnect/jsonrpc-ws-connection@npm:1.0.16" + dependencies: + "@walletconnect/jsonrpc-utils": "npm:^1.0.6" + "@walletconnect/safe-json": "npm:^1.0.2" + events: "npm:^3.3.0" + ws: "npm:^7.5.1" + checksum: 10/98e06097588f895c4ba14b6feb64ed9b5c125d57a4ea3ad3fa6f52fd090fccce60808252c8cefaddc022cfa7fde7551a3aec3bb36e6b08c622207d7554d93e40 + languageName: node + linkType: hard + "@walletconnect/keyvaluestorage@npm:1.1.1, @walletconnect/keyvaluestorage@npm:^1.1.1": version: 1.1.1 resolution: "@walletconnect/keyvaluestorage@npm:1.1.1" @@ -12456,6 +13124,19 @@ __metadata: languageName: node linkType: hard +"@walletconnect/relay-auth@npm:1.1.0": + version: 1.1.0 + resolution: "@walletconnect/relay-auth@npm:1.1.0" + dependencies: + "@noble/curves": "npm:1.8.0" + "@noble/hashes": "npm:1.7.0" + "@walletconnect/safe-json": "npm:^1.0.1" + "@walletconnect/time": "npm:^1.0.2" + uint8arrays: "npm:^3.0.0" + checksum: 10/0fd6c2e05ced76fbc8e6a84c0a8e73458779662aea55568f51cd9066c337d8a12f2869f0bd717024bbe5955cc605241e68505ebac40406ed2a1bdacba42431b1 + languageName: node + linkType: hard + "@walletconnect/safe-json@npm:1.0.2, @walletconnect/safe-json@npm:^1.0.1, @walletconnect/safe-json@npm:^1.0.2": version: 1.0.2 resolution: "@walletconnect/safe-json@npm:1.0.2" @@ -12533,6 +13214,40 @@ __metadata: languageName: node linkType: hard +"@walletconnect/sign-client@npm:2.20.1": + version: 2.20.1 + resolution: "@walletconnect/sign-client@npm:2.20.1" + dependencies: + "@walletconnect/core": "npm:2.20.1" + "@walletconnect/events": "npm:1.0.1" + "@walletconnect/heartbeat": "npm:1.2.2" + "@walletconnect/jsonrpc-utils": "npm:1.0.8" + "@walletconnect/logger": "npm:2.1.2" + "@walletconnect/time": "npm:1.0.2" + "@walletconnect/types": "npm:2.20.1" + "@walletconnect/utils": "npm:2.20.1" + events: "npm:3.3.0" + checksum: 10/bada361cd34dbedd6f183f702a2e1ca7df7dbd438b6849dff9277995dd8620e9e51ebe151758234ccd99f20b481f16420e534ddeb4f7820a1c3b4bb18a756b71 + languageName: node + linkType: hard + +"@walletconnect/sign-client@npm:2.21.4": + version: 2.21.4 + resolution: "@walletconnect/sign-client@npm:2.21.4" + dependencies: + "@walletconnect/core": "npm:2.21.4" + "@walletconnect/events": "npm:1.0.1" + "@walletconnect/heartbeat": "npm:1.2.2" + "@walletconnect/jsonrpc-utils": "npm:1.0.8" + "@walletconnect/logger": "npm:2.1.2" + "@walletconnect/time": "npm:1.0.2" + "@walletconnect/types": "npm:2.21.4" + "@walletconnect/utils": "npm:2.21.4" + events: "npm:3.3.0" + checksum: 10/189ac608a36b0be0f967e97c9857619557f4772d8cf989ebd9f37cb94f00d6d10344d0320f9c041bbdbd15940ff7964f7202b15cb8e6c3f7a015e37578649cbd + languageName: node + linkType: hard + "@walletconnect/sign-client@npm:^2.1.3, @walletconnect/sign-client@npm:^2.1.4": version: 2.16.2 resolution: "@walletconnect/sign-client@npm:2.16.2" @@ -12643,6 +13358,34 @@ __metadata: languageName: node linkType: hard +"@walletconnect/types@npm:2.20.1": + version: 2.20.1 + resolution: "@walletconnect/types@npm:2.20.1" + dependencies: + "@walletconnect/events": "npm:1.0.1" + "@walletconnect/heartbeat": "npm:1.2.2" + "@walletconnect/jsonrpc-types": "npm:1.0.4" + "@walletconnect/keyvaluestorage": "npm:1.1.1" + "@walletconnect/logger": "npm:2.1.2" + events: "npm:3.3.0" + checksum: 10/e52abee367195688587bf6a7bedef570b75fe52ac820b79e8d72d49f5b07ab58fad7991a0a6cdd1c6d5ae34641d37b38013b6f63cb9041015f592a24534cd942 + languageName: node + linkType: hard + +"@walletconnect/types@npm:2.21.4": + version: 2.21.4 + resolution: "@walletconnect/types@npm:2.21.4" + dependencies: + "@walletconnect/events": "npm:1.0.1" + "@walletconnect/heartbeat": "npm:1.2.2" + "@walletconnect/jsonrpc-types": "npm:1.0.4" + "@walletconnect/keyvaluestorage": "npm:1.1.1" + "@walletconnect/logger": "npm:2.1.2" + events: "npm:3.3.0" + checksum: 10/fdd0e121beac8bf97b436b79d533d2324727637345a11f6fc90ef424f212a0610cf8b371e72f63364f82cb6ccf53a75cefa1e316e846f52c6bedb89bccd893b5 + languageName: node + linkType: hard + "@walletconnect/universal-provider@npm:2.11.0": version: 2.11.0 resolution: "@walletconnect/universal-provider@npm:2.11.0" @@ -12711,6 +13454,26 @@ __metadata: languageName: node linkType: hard +"@walletconnect/universal-provider@npm:2.21.4": + version: 2.21.4 + resolution: "@walletconnect/universal-provider@npm:2.21.4" + dependencies: + "@walletconnect/events": "npm:1.0.1" + "@walletconnect/jsonrpc-http-connection": "npm:1.0.8" + "@walletconnect/jsonrpc-provider": "npm:1.0.14" + "@walletconnect/jsonrpc-types": "npm:1.0.4" + "@walletconnect/jsonrpc-utils": "npm:1.0.8" + "@walletconnect/keyvaluestorage": "npm:1.1.1" + "@walletconnect/logger": "npm:2.1.2" + "@walletconnect/sign-client": "npm:2.21.4" + "@walletconnect/types": "npm:2.21.4" + "@walletconnect/utils": "npm:2.21.4" + es-toolkit: "npm:1.39.3" + events: "npm:3.3.0" + checksum: 10/4863c0af383992dfa21e56844e906f52cfab807a86e2c83d1137e25f103f2a1dec168a6f3a8073ba46718bb1afe421d76462c81821f6a7f1ddd3b400af3f1637 + languageName: node + linkType: hard + "@walletconnect/utils@npm:2.11.0": version: 2.11.0 resolution: "@walletconnect/utils@npm:2.11.0" @@ -12845,6 +13608,59 @@ __metadata: languageName: node linkType: hard +"@walletconnect/utils@npm:2.20.1": + version: 2.20.1 + resolution: "@walletconnect/utils@npm:2.20.1" + dependencies: + "@noble/ciphers": "npm:1.2.1" + "@noble/curves": "npm:1.8.1" + "@noble/hashes": "npm:1.7.1" + "@walletconnect/jsonrpc-utils": "npm:1.0.8" + "@walletconnect/keyvaluestorage": "npm:1.1.1" + "@walletconnect/relay-api": "npm:1.0.11" + "@walletconnect/relay-auth": "npm:1.1.0" + "@walletconnect/safe-json": "npm:1.0.2" + "@walletconnect/time": "npm:1.0.2" + "@walletconnect/types": "npm:2.20.1" + "@walletconnect/window-getters": "npm:1.0.1" + "@walletconnect/window-metadata": "npm:1.0.1" + bs58: "npm:6.0.0" + detect-browser: "npm:5.3.0" + query-string: "npm:7.1.3" + uint8arrays: "npm:3.1.0" + viem: "npm:2.23.2" + checksum: 10/1d8c7d39d7ed014b8d4f29847ac7c5daa16780c597798b9354a479bbdcac121a6d8d9541e512536ca93930e6e7b6b5bfab86e8d0122a12659f38d96bb422793a + languageName: node + linkType: hard + +"@walletconnect/utils@npm:2.21.4": + version: 2.21.4 + resolution: "@walletconnect/utils@npm:2.21.4" + dependencies: + "@msgpack/msgpack": "npm:3.1.2" + "@noble/ciphers": "npm:1.3.0" + "@noble/curves": "npm:1.9.2" + "@noble/hashes": "npm:1.8.0" + "@scure/base": "npm:1.2.6" + "@walletconnect/jsonrpc-utils": "npm:1.0.8" + "@walletconnect/keyvaluestorage": "npm:1.1.1" + "@walletconnect/relay-api": "npm:1.0.11" + "@walletconnect/relay-auth": "npm:1.1.0" + "@walletconnect/safe-json": "npm:1.0.2" + "@walletconnect/time": "npm:1.0.2" + "@walletconnect/types": "npm:2.21.4" + "@walletconnect/window-getters": "npm:1.0.1" + "@walletconnect/window-metadata": "npm:1.0.1" + blakejs: "npm:1.2.1" + bs58: "npm:6.0.0" + detect-browser: "npm:5.3.0" + query-string: "npm:7.1.3" + uint8arrays: "npm:3.1.1" + viem: "npm:2.31.0" + checksum: 10/937cb5c6c3a68e973eedbfe3686a9a9d419da84c4670b9b00b64122539fbca0d4a693c4157895297ecb5c1b1ea0d9227bdb05590371c8a6aa4c509480976cc73 + languageName: node + linkType: hard + "@walletconnect/web3wallet@npm:^1.10.3": version: 1.10.3 resolution: "@walletconnect/web3wallet@npm:1.10.3" @@ -13373,6 +14189,36 @@ __metadata: languageName: node linkType: hard +"abitype@npm:1.0.8": + version: 1.0.8 + resolution: "abitype@npm:1.0.8" + peerDependencies: + typescript: ">=5.0.4" + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + checksum: 10/878e74fbac6a971953649b6216950437aa5834a604e9fa833a5b275a6967cff59857c7e43594ae906387d2fb7cad9370138dec4298eb8814815a3ffb6365902c + languageName: node + linkType: hard + +"abitype@npm:^1.0.6, abitype@npm:^1.0.8": + version: 1.0.9 + resolution: "abitype@npm:1.0.9" + peerDependencies: + typescript: ">=5.0.4" + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + checksum: 10/12749b9bd378c8703707be67540e7ccde0f3f3dd89249b2e1bf143f833d01e6e752f81687294319897c7a8f87676bfe1908a4b680619c3895996755659af71f3 + languageName: node + linkType: hard + "abort-controller@npm:^3.0.0": version: 3.0.0 resolution: "abort-controller@npm:3.0.0" @@ -14433,6 +15279,13 @@ __metadata: languageName: node linkType: hard +"base-x@npm:^5.0.0": + version: 5.0.1 + resolution: "base-x@npm:5.0.1" + checksum: 10/6e4f847ef842e0a71c6b6020a6ec482a2a5e727f5a98534dbfd5d5a4e8afbc0d1bdf1fd57174b3f0455d107f10a932c3c7710bec07e2878f80178607f8f605c8 + languageName: node + linkType: hard + "base64-js@npm:*, base64-js@npm:^1.2.0, base64-js@npm:^1.3.0, base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -14574,7 +15427,7 @@ __metadata: languageName: node linkType: hard -"blakejs@npm:^1.1.0": +"blakejs@npm:1.2.1, blakejs@npm:^1.1.0": version: 1.2.1 resolution: "blakejs@npm:1.2.1" checksum: 10/0638b1bd058b21892633929c43005aa6a4cc4b2ac5b338a146c3c076622f1b360795bd7a4d1f077c9b01863ed2df0c1504a81c5b520d164179120434847e6cd7 @@ -14800,6 +15653,15 @@ __metadata: languageName: node linkType: hard +"bs58@npm:6.0.0": + version: 6.0.0 + resolution: "bs58@npm:6.0.0" + dependencies: + base-x: "npm:^5.0.0" + checksum: 10/7c9bb2b2d93d997a8c652de3510d89772007ac64ee913dc4e16ba7ff47624caad3128dcc7f360763eb6308760c300b3e9fd91b8bcbd489acd1a13278e7949c4e + languageName: node + linkType: hard + "bs58@npm:^4.0.0, bs58@npm:^4.0.1": version: 4.0.1 resolution: "bs58@npm:4.0.1" @@ -14917,6 +15779,15 @@ __metadata: languageName: node linkType: hard +"bundle-name@npm:^4.1.0": + version: 4.1.0 + resolution: "bundle-name@npm:4.1.0" + dependencies: + run-applescript: "npm:^7.0.0" + checksum: 10/1d966c8d2dbf4d9d394e53b724ac756c2414c45c01340b37743621f59cc565a435024b394ddcb62b9b335d1c9a31f4640eb648c3fec7f97ee74dc0694c9beb6c + languageName: node + linkType: hard + "busboy@npm:1.6.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" @@ -15183,6 +16054,13 @@ __metadata: languageName: node linkType: hard +"chalk@npm:^5.3.0": + version: 5.6.0 + resolution: "chalk@npm:5.6.0" + checksum: 10/f0e0646a72adbd0f6e73441d3872d7f2f40ba98052924f08a30c10634ec6b1e2cd19cc3c40cc21081dad640e2a1a2749030418571690b89bd7782babf7f89866 + languageName: node + linkType: hard + "chardet@npm:^0.7.0": version: 0.7.0 resolution: "chardet@npm:0.7.0" @@ -15335,6 +16213,15 @@ __metadata: languageName: node linkType: hard +"cli-cursor@npm:^5.0.0": + version: 5.0.0 + resolution: "cli-cursor@npm:5.0.0" + dependencies: + restore-cursor: "npm:^5.0.0" + checksum: 10/1eb9a3f878b31addfe8d82c6d915ec2330cec8447ab1f117f4aa34f0137fbb3137ec3466e1c9a65bcb7557f6e486d343f2da57f253a2f668d691372dfa15c090 + languageName: node + linkType: hard + "cli-spinners@npm:^2.5.0": version: 2.9.1 resolution: "cli-spinners@npm:2.9.1" @@ -15342,6 +16229,13 @@ __metadata: languageName: node linkType: hard +"cli-spinners@npm:^2.9.2": + version: 2.9.2 + resolution: "cli-spinners@npm:2.9.2" + checksum: 10/a0a863f442df35ed7294424f5491fa1756bd8d2e4ff0c8736531d886cec0ece4d85e8663b77a5afaf1d296e3cbbebff92e2e99f52bbea89b667cbe789b994794 + languageName: node + linkType: hard + "cli-width@npm:^3.0.0": version: 3.0.0 resolution: "cli-width@npm:3.0.0" @@ -15907,6 +16801,17 @@ __metadata: languageName: node linkType: hard +"cross-spawn@npm:7.0.6": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10/0d52657d7ae36eb130999dffff1168ec348687b48dd38e2ff59992ed916c88d328cf1d07ff4a4a10bc78de5e1c23f04b306d569e42f7a2293915c081e4dfee86 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -16381,6 +17286,23 @@ __metadata: languageName: node linkType: hard +"default-browser-id@npm:^5.0.0": + version: 5.0.0 + resolution: "default-browser-id@npm:5.0.0" + checksum: 10/185bfaecec2c75fa423544af722a3469b20704c8d1942794a86e4364fe7d9e8e9f63241a5b769d61c8151993bc65833a5b959026fa1ccea343b3db0a33aa6deb + languageName: node + linkType: hard + +"default-browser@npm:^5.2.1": + version: 5.2.1 + resolution: "default-browser@npm:5.2.1" + dependencies: + bundle-name: "npm:^4.1.0" + default-browser-id: "npm:^5.0.0" + checksum: 10/afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 + languageName: node + linkType: hard + "default-gateway@npm:^6.0.3": version: 6.0.3 resolution: "default-gateway@npm:6.0.3" @@ -16417,6 +17339,13 @@ __metadata: languageName: node linkType: hard +"define-lazy-prop@npm:^3.0.0": + version: 3.0.0 + resolution: "define-lazy-prop@npm:3.0.0" + checksum: 10/f28421cf9ee86eecaf5f3b8fe875f13d7009c2625e97645bfff7a2a49aca678270b86c39f9c32939e5ca7ab96b551377ed4139558c795e076774287ad3af1aa4 + languageName: node + linkType: hard + "define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" @@ -16907,6 +17836,13 @@ __metadata: languageName: node linkType: hard +"emoji-regex@npm:^10.3.0": + version: 10.4.0 + resolution: "emoji-regex@npm:10.4.0" + checksum: 10/76bb92c5bcf0b6980d37e535156231e4a9d0aa6ab3b9f5eabf7690231d5aa5d5b8e516f36e6804cbdd0f1c23dfef2a60c40ab7bb8aedd890584281a565b97c50 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -17207,6 +18143,30 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:1.33.0": + version: 1.33.0 + resolution: "es-toolkit@npm:1.33.0" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + checksum: 10/db613d885c407dc3b84b3939b8b0c9976f658bfb03fa0f9cd3a3fe8383a60a75e1e4f34584e86c3fbf00def50ea0ca5f1a5264a1014018286dedbed08426b5f0 + languageName: node + linkType: hard + +"es-toolkit@npm:1.39.3": + version: 1.39.3 + resolution: "es-toolkit@npm:1.39.3" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + checksum: 10/18cf6dee69170f802a50d447cac3af0026c199b501fe9a151633a402ea0523463b73aacbde53072cc610914d68031e2856fbb8a305b020e34bd7f6ac24d37e6d + languageName: node + linkType: hard + "es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50": version: 0.10.62 resolution: "es5-ext@npm:0.10.62" @@ -18799,6 +19759,13 @@ __metadata: languageName: node linkType: hard +"fuse.js@npm:7.1.0": + version: 7.1.0 + resolution: "fuse.js@npm:7.1.0" + checksum: 10/9f9105e54372897a46cb3e04074f0db5bd0a428320d4618276a57e6142d7502235a556f05cf87aa3c5d6d9c6fdfa06b901b78379c48aa0951672ccbc4a1bfe70 + languageName: node + linkType: hard + "fuse.js@npm:^7.0.0": version: 7.0.0 resolution: "fuse.js@npm:7.0.0" @@ -18924,6 +19891,13 @@ __metadata: languageName: node linkType: hard +"get-east-asian-width@npm:^1.0.0": + version: 1.3.0 + resolution: "get-east-asian-width@npm:1.3.0" + checksum: 10/8e8e779eb28701db7fdb1c8cab879e39e6ae23f52dadd89c8aed05869671cee611a65d4f8557b83e981428623247d8bc5d0c7a4ef3ea7a41d826e73600112ad8 + languageName: node + linkType: hard + "get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": version: 2.0.2 resolution: "get-func-name@npm:2.0.2" @@ -20017,6 +20991,16 @@ __metadata: languageName: node linkType: hard +"input-otp@npm:^1.4.1": + version: 1.4.2 + resolution: "input-otp@npm:1.4.2" + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + checksum: 10/7dfaa30ecda1640a1e6f78be05c52de58e35134f34684709b065abb47cae23c054cb4d87df8af317f8ecb4ef384167f3237aa31cd2601bed5f8ca88ed93b7452 + languageName: node + linkType: hard + "inquirer@npm:8.2.4": version: 8.2.4 resolution: "inquirer@npm:8.2.4" @@ -20221,6 +21205,15 @@ __metadata: languageName: node linkType: hard +"is-docker@npm:^3.0.0": + version: 3.0.0 + resolution: "is-docker@npm:3.0.0" + bin: + is-docker: cli.js + checksum: 10/b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90 + languageName: node + linkType: hard + "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -20276,6 +21269,17 @@ __metadata: languageName: node linkType: hard +"is-inside-container@npm:^1.0.0": + version: 1.0.0 + resolution: "is-inside-container@npm:1.0.0" + dependencies: + is-docker: "npm:^3.0.0" + bin: + is-inside-container: cli.js + checksum: 10/c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03 + languageName: node + linkType: hard + "is-interactive@npm:^1.0.0": version: 1.0.0 resolution: "is-interactive@npm:1.0.0" @@ -20283,6 +21287,13 @@ __metadata: languageName: node linkType: hard +"is-interactive@npm:^2.0.0": + version: 2.0.0 + resolution: "is-interactive@npm:2.0.0" + checksum: 10/e8d52ad490bed7ae665032c7675ec07732bbfe25808b0efbc4d5a76b1a1f01c165f332775c63e25e9a03d319ebb6b24f571a9e902669fc1e40b0a60b5be6e26c + languageName: node + linkType: hard + "is-lambda@npm:^1.0.1": version: 1.0.1 resolution: "is-lambda@npm:1.0.1" @@ -20477,10 +21488,24 @@ __metadata: languageName: node linkType: hard -"is-unicode-supported@npm:^0.1.0": - version: 0.1.0 - resolution: "is-unicode-supported@npm:0.1.0" - checksum: 10/a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 +"is-unicode-supported@npm:^0.1.0": + version: 0.1.0 + resolution: "is-unicode-supported@npm:0.1.0" + checksum: 10/a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 + languageName: node + linkType: hard + +"is-unicode-supported@npm:^1.3.0": + version: 1.3.0 + resolution: "is-unicode-supported@npm:1.3.0" + checksum: 10/20a1fc161afafaf49243551a5ac33b6c4cf0bbcce369fcd8f2951fbdd000c30698ce320de3ee6830497310a8f41880f8066d440aa3eb0a853e2aa4836dd89abc + languageName: node + linkType: hard + +"is-unicode-supported@npm:^2.0.0": + version: 2.1.0 + resolution: "is-unicode-supported@npm:2.1.0" + checksum: 10/f254e3da6b0ab1a57a94f7273a7798dd35d1d45b227759f600d0fa9d5649f9c07fa8d3c8a6360b0e376adf916d151ec24fc9a50c5295c58bae7ca54a76a063f9 languageName: node linkType: hard @@ -20526,6 +21551,15 @@ __metadata: languageName: node linkType: hard +"is-wsl@npm:^3.1.0": + version: 3.1.0 + resolution: "is-wsl@npm:3.1.0" + dependencies: + is-inside-container: "npm:^1.0.0" + checksum: 10/f9734c81f2f9cf9877c5db8356bfe1ff61680f1f4c1011e91278a9c0564b395ae796addb4bf33956871041476ec82c3e5260ed57b22ac91794d4ae70a1d2f0a9 + languageName: node + linkType: hard + "isarray@npm:0.0.1": version: 0.0.1 resolution: "isarray@npm:0.0.1" @@ -20642,6 +21676,24 @@ __metadata: languageName: node linkType: hard +"isows@npm:1.0.6": + version: 1.0.6 + resolution: "isows@npm:1.0.6" + peerDependencies: + ws: "*" + checksum: 10/ab9e85b50bcc3d70aa5ec875aa2746c5daf9321cb376ed4e5434d3c2643c5d62b1f466d93a05cd2ad0ead5297224922748c31707cb4fbd68f5d05d0479dce99c + languageName: node + linkType: hard + +"isows@npm:1.0.7": + version: 1.0.7 + resolution: "isows@npm:1.0.7" + peerDependencies: + ws: "*" + checksum: 10/044b949b369872882af07b60b613b5801ae01b01a23b5b72b78af80c8103bbeed38352c3e8ceff13a7834bc91fd2eb41cf91ec01d59a041d8705680e6b0ec546 + languageName: node + linkType: hard + "isstream@npm:~0.1.2": version: 0.1.2 resolution: "isstream@npm:0.1.2" @@ -21699,6 +22751,16 @@ __metadata: languageName: node linkType: hard +"log-symbols@npm:^6.0.0": + version: 6.0.0 + resolution: "log-symbols@npm:6.0.0" + dependencies: + chalk: "npm:^5.3.0" + is-unicode-supported: "npm:^1.3.0" + checksum: 10/510cdda36700cbcd87a2a691ea08d310a6c6b449084018f7f2ec4f732ca5e51b301ff1327aadd96f53c08318e616276c65f7fe22f2a16704fb0715d788bc3c33 + languageName: node + linkType: hard + "long@npm:^4.0.0": version: 4.0.0 resolution: "long@npm:4.0.0" @@ -22130,6 +23192,13 @@ __metadata: languageName: node linkType: hard +"mimic-function@npm:^5.0.0": + version: 5.0.1 + resolution: "mimic-function@npm:5.0.1" + checksum: 10/eb5893c99e902ccebbc267c6c6b83092966af84682957f79313311edb95e8bb5f39fb048d77132b700474d1c86d90ccc211e99bae0935447a4834eb4c882982c + languageName: node + linkType: hard + "mimic-response@npm:^1.0.0": version: 1.0.1 resolution: "mimic-response@npm:1.0.1" @@ -22356,6 +23425,18 @@ __metadata: languageName: node linkType: hard +"mipd@npm:0.0.7": + version: 0.0.7 + resolution: "mipd@npm:0.0.7" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/c14dffef0ef7a3e71469aee553f5735f4a6a9f9a2b47ca02798040f2e006261c2e7e8b26ee0dc56a815c04d5612eb4be1eed474e7bb4e496eb0f5ada2fe1d2e7 + languageName: node + linkType: hard + "mitt@npm:^3.0.0, mitt@npm:^3.0.1": version: 3.0.1 resolution: "mitt@npm:3.0.1" @@ -23283,6 +24364,27 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^7.0.0": + version: 7.0.0 + resolution: "onetime@npm:7.0.0" + dependencies: + mimic-function: "npm:^5.0.0" + checksum: 10/eb08d2da9339819e2f9d52cab9caf2557d80e9af8c7d1ae86e1a0fef027d00a88e9f5bd67494d350df360f7c559fbb44e800b32f310fb989c860214eacbb561c + languageName: node + linkType: hard + +"open@npm:10.1.1": + version: 10.1.1 + resolution: "open@npm:10.1.1" + dependencies: + default-browser: "npm:^5.2.1" + define-lazy-prop: "npm:^3.0.0" + is-inside-container: "npm:^1.0.0" + is-wsl: "npm:^3.1.0" + checksum: 10/911f8c3214a74e5adb6bae4cbb93112f66f776c9b042bd62914f8765621377cfea8b7dd0a9ef8430900e658c5eac61626f6c4672c5f5819cbfe450215e8f9d8f + languageName: node + linkType: hard + "open@npm:8.4.1": version: 8.4.1 resolution: "open@npm:8.4.1" @@ -23350,6 +24452,23 @@ __metadata: languageName: node linkType: hard +"ora@npm:8.2.0": + version: 8.2.0 + resolution: "ora@npm:8.2.0" + dependencies: + chalk: "npm:^5.3.0" + cli-cursor: "npm:^5.0.0" + cli-spinners: "npm:^2.9.2" + is-interactive: "npm:^2.0.0" + is-unicode-supported: "npm:^2.0.0" + log-symbols: "npm:^6.0.0" + stdin-discarder: "npm:^0.2.2" + string-width: "npm:^7.2.0" + strip-ansi: "npm:^7.1.0" + checksum: 10/cea932fdcb29549cd7b5af81f427760986429cadc752b1dd4bf31bc6821f5ba137e1ef9a18cde7bdfbe5b4e3d3201e76b048765c51a27b15d18c57ac0e0a909a + languageName: node + linkType: hard + "os-tmpdir@npm:~1.0.1, os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -23357,6 +24476,88 @@ __metadata: languageName: node linkType: hard +"ox@npm:0.6.7": + version: 0.6.7 + resolution: "ox@npm:0.6.7" + dependencies: + "@adraffy/ens-normalize": "npm:^1.10.1" + "@noble/curves": "npm:^1.6.0" + "@noble/hashes": "npm:^1.5.0" + "@scure/bip32": "npm:^1.5.0" + "@scure/bip39": "npm:^1.4.0" + abitype: "npm:^1.0.6" + eventemitter3: "npm:5.0.1" + peerDependencies: + typescript: ">=5.4.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/442fb31e1afb68922bf942025930d8cd6d8c677696e9a6de308008b3608669f22127cadbc0f77181e012d23d7b74318e5f85e63b06b16eecbc887d7fac32a6dc + languageName: node + linkType: hard + +"ox@npm:0.7.0": + version: 0.7.0 + resolution: "ox@npm:0.7.0" + dependencies: + "@adraffy/ens-normalize": "npm:^1.10.1" + "@noble/curves": "npm:^1.6.0" + "@noble/hashes": "npm:^1.5.0" + "@scure/bip32": "npm:^1.5.0" + "@scure/bip39": "npm:^1.4.0" + abitype: "npm:^1.0.6" + eventemitter3: "npm:5.0.1" + peerDependencies: + typescript: ">=5.4.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/68fd45cc04ef8dfeb8ae896b9709e81f85cd362cbc955c71f4e6d10d206be3523a4000ba9c9520a5333f7822be9707889391da86eff5d72a42e68e211ed75783 + languageName: node + linkType: hard + +"ox@npm:0.7.1": + version: 0.7.1 + resolution: "ox@npm:0.7.1" + dependencies: + "@adraffy/ens-normalize": "npm:^1.10.1" + "@noble/ciphers": "npm:^1.3.0" + "@noble/curves": "npm:^1.6.0" + "@noble/hashes": "npm:^1.5.0" + "@scure/bip32": "npm:^1.5.0" + "@scure/bip39": "npm:^1.4.0" + abitype: "npm:^1.0.6" + eventemitter3: "npm:5.0.1" + peerDependencies: + typescript: ">=5.4.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/761e941b6ca6d3a84235bb19a7e1f282e54a8cbc1374aaf4ce0232de50d42cd351074ef3e83d09af71f7522b085cfa92168adb19744dac2556fe83b3bba46f71 + languageName: node + linkType: hard + +"ox@npm:0.8.6": + version: 0.8.6 + resolution: "ox@npm:0.8.6" + dependencies: + "@adraffy/ens-normalize": "npm:^1.11.0" + "@noble/ciphers": "npm:^1.3.0" + "@noble/curves": "npm:^1.9.1" + "@noble/hashes": "npm:^1.8.0" + "@scure/bip32": "npm:^1.7.0" + "@scure/bip39": "npm:^1.6.0" + abitype: "npm:^1.0.8" + eventemitter3: "npm:5.0.1" + peerDependencies: + typescript: ">=5.4.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/815071018061dfa0bd797eb430f785e252ab499d3f7d0a93063f514cd0688f07faa6652f41d3226b8a9fa327e3682f1f616c69123405043df6492f7ba7fd50fe + languageName: node + linkType: hard + "p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -24796,6 +25997,13 @@ __metadata: languageName: node linkType: hard +"preact@npm:^10.24.2": + version: 10.27.1 + resolution: "preact@npm:10.27.1" + checksum: 10/c667d7c96c7cd0104aa91282153052aaabc097d985185f19fef61028d859d7de2b6826caaabb32e2b20d543a219597fa86949527be882cb0a87662ded47ad8c2 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -24943,7 +26151,7 @@ __metadata: languageName: node linkType: hard -"prompts@npm:^2.4.2": +"prompts@npm:2.4.2, prompts@npm:^2.4.2": version: 2.4.2 resolution: "prompts@npm:2.4.2" dependencies: @@ -26214,6 +27422,16 @@ __metadata: languageName: node linkType: hard +"restore-cursor@npm:^5.0.0": + version: 5.1.0 + resolution: "restore-cursor@npm:5.1.0" + dependencies: + onetime: "npm:^7.0.0" + signal-exit: "npm:^4.1.0" + checksum: 10/838dd54e458d89cfbc1a923b343c1b0f170a04100b4ce1733e97531842d7b440463967e521216e8ab6c6f8e89df877acc7b7f4c18ec76e99fb9bf5a60d358d2c + languageName: node + linkType: hard + "retry-request@npm:^5.0.0": version: 5.0.2 resolution: "retry-request@npm:5.0.2" @@ -26386,6 +27604,13 @@ __metadata: languageName: node linkType: hard +"run-applescript@npm:^7.0.0": + version: 7.0.0 + resolution: "run-applescript@npm:7.0.0" + checksum: 10/b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c + languageName: node + linkType: hard + "run-async@npm:^2.4.0": version: 2.4.1 resolution: "run-async@npm:2.4.1" @@ -26913,7 +28138,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.0.1": +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 10/c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f @@ -27413,6 +28638,13 @@ __metadata: languageName: node linkType: hard +"stdin-discarder@npm:^0.2.2": + version: 0.2.2 + resolution: "stdin-discarder@npm:0.2.2" + checksum: 10/642ffd05bd5b100819d6b24a613d83c6e3857c6de74eb02fc51506fa61dc1b0034665163831873868157c4538d71e31762bcf319be86cea04c3aba5336470478 + languageName: node + linkType: hard + "str2buf@npm:^1.3.0": version: 1.3.0 resolution: "str2buf@npm:1.3.0" @@ -27479,6 +28711,17 @@ __metadata: languageName: node linkType: hard +"string-width@npm:^7.2.0": + version: 7.2.0 + resolution: "string-width@npm:7.2.0" + dependencies: + emoji-regex: "npm:^10.3.0" + get-east-asian-width: "npm:^1.0.0" + strip-ansi: "npm:^7.1.0" + checksum: 10/42f9e82f61314904a81393f6ef75b832c39f39761797250de68c041d8ba4df2ef80db49ab6cd3a292923a6f0f409b8c9980d120f7d32c820b4a8a84a2598a295 + languageName: node + linkType: hard + "string.prototype.matchall@npm:^4.0.10, string.prototype.matchall@npm:^4.0.6": version: 4.0.10 resolution: "string.prototype.matchall@npm:4.0.10" @@ -27592,7 +28835,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1": +"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": version: 7.1.0 resolution: "strip-ansi@npm:7.1.0" dependencies: @@ -27866,6 +29109,47 @@ __metadata: languageName: unknown linkType: soft +"swaps-api-nextjs-evm-gasless@workspace:examples/swaps-api-nextjs-evm-gasless": + version: 0.0.0-use.local + resolution: "swaps-api-nextjs-evm-gasless@workspace:examples/swaps-api-nextjs-evm-gasless" + dependencies: + "@fortawesome/fontawesome-svg-core": "npm:^6.5.1" + "@fortawesome/free-brands-svg-icons": "npm:^6.5.1" + "@fortawesome/free-solid-svg-icons": "npm:^6.5.1" + "@fortawesome/react-fontawesome": "npm:^0.2.0" + "@headlessui/react": "npm:^1.7.18" + "@radix-ui/react-label": "npm:^2.0.2" + "@radix-ui/react-popover": "npm:^1.0.7" + "@radix-ui/react-toast": "npm:^1.1.5" + "@tailwindcss/forms": "npm:^0.5.7" + "@thirdweb-dev/react": "npm:^4.4.17" + "@thirdweb-dev/sdk": "npm:^4.0.44" + "@types/node": "npm:20.11.26" + "@types/react": "npm:18.2.65" + "@types/react-dom": "npm:18.2.22" + autoprefixer: "npm:^10.4.18" + axios: "npm:^1.6.0" + class-variance-authority: "npm:^0.7.0" + clsx: "npm:^2.1.0" + eslint: "npm:^8.57.0" + eslint-config-examples: "workspace:*" + framer-motion: "npm:^6.5.1" + lucide-react: "npm:^0.368.0" + next: "npm:14.1.3" + pino-pretty: "npm:^10.3.1" + postcss: "npm:^8.4.35" + react: "npm:18.2.0" + react-dom: "npm:18.2.0" + tailwind-merge: "npm:^2.2.2" + tailwindcss: "npm:^3.4.1" + tailwindcss-animate: "npm:^1.0.7" + thirdweb: "npm:^5.105.37" + typescript: "npm:^5.4.2" + typescript-config: "workspace:*" + use-debounce: "npm:^10.0.0" + languageName: unknown + linkType: soft + "swaps-api-nextjs-solana@workspace:examples/swaps-api-nextjs-solana": version: 0.0.0-use.local resolution: "swaps-api-nextjs-solana@workspace:examples/swaps-api-nextjs-solana" @@ -27968,9 +29252,6 @@ __metadata: "@thirdweb-dev/react": "npm:^4.4.17" "@thirdweb-dev/sdk": "npm:^4.0.44" "@tonconnect/ui-react": "npm:^2.0.9" - "@tronweb3/tronwallet-adapter-react-hooks": "npm:^1.1.7" - "@tronweb3/tronwallet-adapter-react-ui": "npm:^1.1.8" - "@tronweb3/tronwallet-adapters": "npm:^1.2.3" "@types/node": "npm:20.11.26" "@types/react": "npm:18.2.65" "@types/react-dom": "npm:18.2.22" @@ -28584,6 +29865,96 @@ __metadata: languageName: node linkType: hard +"thirdweb@npm:^5.105.37": + version: 5.105.37 + resolution: "thirdweb@npm:5.105.37" + dependencies: + "@coinbase/wallet-sdk": "npm:4.3.0" + "@emotion/react": "npm:11.14.0" + "@emotion/styled": "npm:11.14.1" + "@noble/curves": "npm:1.8.2" + "@noble/hashes": "npm:1.7.2" + "@passwordless-id/webauthn": "npm:^2.1.2" + "@radix-ui/react-dialog": "npm:1.1.14" + "@radix-ui/react-focus-scope": "npm:1.1.7" + "@radix-ui/react-icons": "npm:1.3.2" + "@radix-ui/react-tooltip": "npm:1.2.7" + "@storybook/react": "npm:9.0.15" + "@tanstack/react-query": "npm:5.81.5" + "@thirdweb-dev/engine": "npm:3.2.1" + "@thirdweb-dev/insight": "npm:1.1.1" + "@walletconnect/sign-client": "npm:2.20.1" + "@walletconnect/universal-provider": "npm:2.21.4" + abitype: "npm:1.0.8" + cross-spawn: "npm:7.0.6" + fuse.js: "npm:7.1.0" + input-otp: "npm:^1.4.1" + mipd: "npm:0.0.7" + open: "npm:10.1.1" + ora: "npm:8.2.0" + ox: "npm:0.7.0" + prompts: "npm:2.4.2" + qrcode: "npm:1.5.3" + toml: "npm:3.0.0" + uqr: "npm:0.1.2" + viem: "npm:2.33.2" + zod: "npm:3.25.75" + peerDependencies: + "@aws-sdk/client-lambda": ^3 + "@aws-sdk/credential-providers": ^3 + "@coinbase/wallet-mobile-sdk": ^1 + "@mobile-wallet-protocol/client": ^1 + "@react-native-async-storage/async-storage": ^1 || ^2 + ethers: ^5 || ^6 + expo-linking: ^6 || ^7 + expo-web-browser: ^13 || ^14 + react: ^18 || ^19 + react-native: "*" + react-native-aes-gcm-crypto: ^0.2 + react-native-passkey: ^3 + react-native-quick-crypto: ">=0.7.0-rc.6 || >=0.7" + react-native-svg: ^15 + typescript: ">=5.0.4" + peerDependenciesMeta: + "@aws-sdk/client-kms": + optional: true + "@aws-sdk/client-lambda": + optional: true + "@aws-sdk/credential-providers": + optional: true + "@coinbase/wallet-mobile-sdk": + optional: true + "@mobile-wallet-protocol/client": + optional: true + "@react-native-async-storage/async-storage": + optional: true + ethers: + optional: true + expo-linking: + optional: true + expo-web-browser: + optional: true + react: + optional: true + react-native: + optional: true + react-native-aes-gcm-crypto: + optional: true + react-native-passkey: + optional: true + react-native-quick-crypto: + optional: true + react-native-svg: + optional: true + typescript: + optional: true + bin: + thirdweb: dist/esm/cli/bin.js + thirdweb-cli: dist/esm/cli/bin.js + checksum: 10/16bfda05b430f2d01f9f05547e38318055686d0f5e61a1c29fb04525703f19261481827dab7bd39d8aefa1979b474220d24f7f6834156fed6faac96b9db90dcf + languageName: node + linkType: hard + "thread-stream@npm:^0.15.1": version: 0.15.2 resolution: "thread-stream@npm:0.15.2" @@ -28695,6 +30066,13 @@ __metadata: languageName: node linkType: hard +"toml@npm:3.0.0": + version: 3.0.0 + resolution: "toml@npm:3.0.0" + checksum: 10/cfef0966868d552bd02e741f30945a611f70841b7cddb07ea2b17441fe32543985bc0a7c0dcf7971af26fcaf8a17712a485d911f46bfe28644536e9a71a2bd09 + languageName: node + linkType: hard + "ton-core@npm:^0.53.0": version: 0.53.0 resolution: "ton-core@npm:0.53.0" @@ -29202,21 +30580,21 @@ __metadata: languageName: node linkType: hard -"uint8arrays@npm:^2.1.3": - version: 2.1.10 - resolution: "uint8arrays@npm:2.1.10" +"uint8arrays@npm:3.1.1, uint8arrays@npm:^3.0.0, uint8arrays@npm:^3.1.0": + version: 3.1.1 + resolution: "uint8arrays@npm:3.1.1" dependencies: multiformats: "npm:^9.4.2" - checksum: 10/63ceb5fecc09de69641531c847e0b435d15a73587e40d4db23ed9b8a1ebbe839ae39fe81a15ea6079cdf642fcf2583983f9a5d32726edc4bc5e87634f34e3bd5 + checksum: 10/536e70273c040484aa7d522031a9dbca1fe8c06eb58a3ace1064ba68825b4e2764d4a0b604a1c451e7b8be0986dc94f23a419cfe9334bd116716074a2d29b33d languageName: node linkType: hard -"uint8arrays@npm:^3.0.0, uint8arrays@npm:^3.1.0": - version: 3.1.1 - resolution: "uint8arrays@npm:3.1.1" +"uint8arrays@npm:^2.1.3": + version: 2.1.10 + resolution: "uint8arrays@npm:2.1.10" dependencies: multiformats: "npm:^9.4.2" - checksum: 10/536e70273c040484aa7d522031a9dbca1fe8c06eb58a3ace1064ba68825b4e2764d4a0b604a1c451e7b8be0986dc94f23a419cfe9334bd116716074a2d29b33d + checksum: 10/63ceb5fecc09de69641531c847e0b435d15a73587e40d4db23ed9b8a1ebbe839ae39fe81a15ea6079cdf642fcf2583983f9a5d32726edc4bc5e87634f34e3bd5 languageName: node linkType: hard @@ -29499,7 +30877,7 @@ __metadata: languageName: node linkType: hard -"uqr@npm:^0.1.2": +"uqr@npm:0.1.2, uqr@npm:^0.1.2": version: 0.1.2 resolution: "uqr@npm:0.1.2" checksum: 10/31f1fe7d7a8121a2670712234524763160985b053e7eb8af7925a131bcde0df11641e15129d988358032da603185456d08dd72b26b507897272eb9640273bfa6 @@ -29842,6 +31220,69 @@ __metadata: languageName: node linkType: hard +"viem@npm:2.23.2": + version: 2.23.2 + resolution: "viem@npm:2.23.2" + dependencies: + "@noble/curves": "npm:1.8.1" + "@noble/hashes": "npm:1.7.1" + "@scure/bip32": "npm:1.6.2" + "@scure/bip39": "npm:1.5.4" + abitype: "npm:1.0.8" + isows: "npm:1.0.6" + ox: "npm:0.6.7" + ws: "npm:8.18.0" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/847fdb57a6941f67c4ff97c79d99368c48e78b9c070df8fb3f3310d58bbd075fd78e9a506abccb82fcdbcf0c6c13aba7cfb021e37fda0777ea1eb0ccecf25fe1 + languageName: node + linkType: hard + +"viem@npm:2.31.0": + version: 2.31.0 + resolution: "viem@npm:2.31.0" + dependencies: + "@noble/curves": "npm:1.9.1" + "@noble/hashes": "npm:1.8.0" + "@scure/bip32": "npm:1.7.0" + "@scure/bip39": "npm:1.6.0" + abitype: "npm:1.0.8" + isows: "npm:1.0.7" + ox: "npm:0.7.1" + ws: "npm:8.18.2" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/960ef6578fc91903f7c99b548af6fa0b56b5776bbd949b687834e0184ccab66a806da08fd87230a6ea1af35477c9bd5e086c308668ec178567bf9ba9eb78d44d + languageName: node + linkType: hard + +"viem@npm:2.33.2": + version: 2.33.2 + resolution: "viem@npm:2.33.2" + dependencies: + "@noble/curves": "npm:1.9.2" + "@noble/hashes": "npm:1.8.0" + "@scure/bip32": "npm:1.7.0" + "@scure/bip39": "npm:1.6.0" + abitype: "npm:1.0.8" + isows: "npm:1.0.7" + ox: "npm:0.8.6" + ws: "npm:8.18.2" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/4256557e8656e7d32d47012277a361d77d9de10fecd6e738799b25c2e05e2dfcc94bb50026db33b7b1e90211d22395e3049dd004b77d27fd161af563a86b57c3 + languageName: node + linkType: hard + "viem@npm:^0.3.50": version: 0.3.50 resolution: "viem@npm:0.3.50" @@ -31185,6 +32626,36 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.18.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + languageName: node + linkType: hard + +"ws@npm:8.18.2": + version: 8.18.2 + resolution: "ws@npm:8.18.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/018e04ec95561d88248d53a2eaf094b4ae131e9b062f2679e6e8a62f04649bc543448f1e038125225ac6bbb25f54c1e65d7a2cc9dbc1e28b43e5e6b7162ad88e + languageName: node + linkType: hard + "ws@npm:8.9.0": version: 8.9.0 resolution: "ws@npm:8.9.0" @@ -31524,6 +32995,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:3.25.75": + version: 3.25.75 + resolution: "zod@npm:3.25.75" + checksum: 10/ac5bfd290e81a7954079a99c8ec27c2653af5c3842eaeddda06becb415b1d3887c1b06d6cbe8d52fde08f50e958643966ab0bf585a8e432d53b83ddb8e274d10 + languageName: node + linkType: hard + "zod@npm:^3.21.4": version: 3.23.8 resolution: "zod@npm:3.23.8"
+ ⚡ Experience the future of DeFi with seamless cross-chain swaps. + + Bridge assets across multiple blockchains with zero hassle. +
+ 🌟 Powered By Leading Bridges +