diff --git a/.github/actions/setup/action.yaml b/.github/actions/setup/action.yaml
new file mode 100644
index 0000000..9d47bf0
--- /dev/null
+++ b/.github/actions/setup/action.yaml
@@ -0,0 +1,18 @@
+name: Setup
+runs:
+ using: composite
+ steps:
+ - uses: pnpm/action-setup@v2
+
+ - name: Setup Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: pnpm install node modules
+ run: pnpm i --frozen-lockfile
+ shell: bash
+
+ - name: pnpm build
+ run: pnpm -r build
+ shell: bash
diff --git a/.github/actions/supersim/action.yaml b/.github/actions/supersim/action.yaml
new file mode 100644
index 0000000..7bbdbbf
--- /dev/null
+++ b/.github/actions/supersim/action.yaml
@@ -0,0 +1,8 @@
+name: Supersim
+runs:
+ using: composite
+ steps:
+ - name: Install Supersim
+ uses: jaxxstorm/action-install-gh-release@v1.10.0
+ with:
+ repo: ethereum-optimism/supersim
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
new file mode 100644
index 0000000..eb0880d
--- /dev/null
+++ b/.github/workflows/main.yaml
@@ -0,0 +1,81 @@
+name: Unit Tests
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+ merge_group:
+ branches:
+ - main
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ contents: 'read'
+ actions: 'read'
+
+jobs:
+ typecheck:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Setup
+ uses: ./.github/actions/setup
+ - name: Run TypeChecker
+ run: |
+ pnpm -r typecheck
+
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Setup
+ uses: ./.github/actions/setup
+ - name: Run Linters
+ run: |
+ pnpm -r lint
+
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Setup
+ uses: ./.github/actions/setup
+ - name: Supersim Setup
+ uses: ./.github/actions/supersim
+ - name: Run Tests
+ run: |
+ pnpm -r --filter '!e2e-test' test
+
+ e2e-test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Setup
+ uses: ./.github/actions/setup
+ - name: Supersim Setup
+ uses: ./.github/actions/supersim
+ - name: Run Tests
+ shell: bash
+ run: |
+ pnpm supersim --interop.autorelay &
+ pnpm deploy:contracts:ci
+ pnpm e2e-test:ci
diff --git a/package.json b/package.json
index d2a9e37..df7d084 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"name": "superchainerc20-starter",
+ "packageManager": "pnpm@9.0.2",
"description": "",
"scripts": {
"dev": "mprocs",
@@ -9,7 +10,9 @@
"contracts:deploy:singlechain": "pnpm nx run @superchainerc20-starter/contracts:deploy:singlechain",
"update:toc": "doctoc README.md",
"e2e-test": "mprocs -c mprocs-e2e-test.yaml",
- "init:env": "pnpm nx run-many --target=init:env"
+ "init:env": "pnpm nx run-many --target=init:env",
+ "deploy:contracts:ci": "wait-port http://:8420/ready && pnpm nx run @superchainerc20-starter/contracts:build && forge script packages/contracts/scripts/MultiChainSuperchainERC20Deployment.s.sol --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
+ "e2e-test:ci": "pnpm nx run @superchainerc20-starter/e2e-test:test"
},
"license": "MIT",
"devDependencies": {
diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json
index af47893..fec6021 100644
--- a/packages/e2e-test/package.json
+++ b/packages/e2e-test/package.json
@@ -1,10 +1,10 @@
{
- "name": "e2e-test",
+ "name": "@superchainerc20-starter/e2e-test",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
- "test": "vitest",
+ "test": "vitest --run",
"init:env": "cp .env.example .env"
},
"devDependencies": {
diff --git a/packages/e2e-test/src/envVars.ts b/packages/e2e-test/src/envVars.ts
index 46fd301..22ad332 100644
--- a/packages/e2e-test/src/envVars.ts
+++ b/packages/e2e-test/src/envVars.ts
@@ -2,6 +2,6 @@ import { parseEnv, z } from 'znv'
import { Address as ZodAddress } from 'abitype/zod'
export const envVars = parseEnv(import.meta.env, {
- VITE_TOKEN_CONTRACT_ADDRESS: ZodAddress,
- VITE_TOKEN_MINTER_ADDRESS: ZodAddress,
+ VITE_TOKEN_CONTRACT_ADDRESS: ZodAddress.default("0x5BCf71Ca0CE963373d917031aAFDd6D98B80B159"),
+ VITE_TOKEN_MINTER_ADDRESS: ZodAddress.default("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"),
})
diff --git a/packages/frontend/.gitignore b/packages/frontend/.gitignore
index a547bf3..ea001fc 100644
--- a/packages/frontend/.gitignore
+++ b/packages/frontend/.gitignore
@@ -11,6 +11,8 @@ node_modules
dist
dist-ssr
*.local
+tsconfig.app.tsbuildinfo
+tsconfig.node.tsbuildinfo
# Editor directories and files
.vscode/*
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index acc4676..1f98452 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -6,10 +6,12 @@
"scripts": {
"dev": "vite",
"build": "vite build",
- "lint": "eslint .",
+ "lint": "eslint \"**/*.{ts,tsx}\" && pnpm prettier --check \"**/*.{ts,tsx}\"",
+ "lint:fix": "eslint \"**/*.{ts,tsx}\" --fix --quiet && pnpm prettier \"**/*.{ts,tsx}\" --write --loglevel=warn",
"preview": "vite preview",
"shadcn:add": "pnpm dlx shadcn add",
- "init:env": "cp .env.example .env"
+ "init:env": "cp .env.example .env",
+ "typecheck": "tsc --build --noEmit"
},
"dependencies": {
"@eth-optimism/viem": "^0.0.11",
diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx
index 6ce50d0..fe68155 100644
--- a/packages/frontend/src/App.tsx
+++ b/packages/frontend/src/App.tsx
@@ -1,19 +1,19 @@
-import { ArrowLeftRight as BridgeIcon, Droplet, RefreshCw } from "lucide-react";
-import { Bridge } from "@/Bridge";
-import { Providers } from "@/Providers";
-import { WalletBalance } from "@/components/WalletBalance";
-import { Card } from "@/components/ui/card";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { Faucet } from "@/Faucet";
-import { ConnectWalletButton } from "@/components/connect-wallet/ConnectWalletButton";
-import { TokenInfo } from "@/components/TokenInfo";
-import { TokenAggregateSupply } from "@/components/TokenAggregateSupply";
-import { useStartIndexer } from "@/hooks/useIndexer";
-import { Button } from "@/components/ui/button";
-import { RecentActivity } from "@/components/RecentActivity";
+import { ArrowLeftRight as BridgeIcon, Droplet, RefreshCw } from 'lucide-react'
+import { Bridge } from '@/Bridge'
+import { Providers } from '@/Providers'
+import { WalletBalance } from '@/components/WalletBalance'
+import { Card } from '@/components/ui/card'
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
+import { Faucet } from '@/Faucet'
+import { ConnectWalletButton } from '@/components/connect-wallet/ConnectWalletButton'
+import { TokenInfo } from '@/components/TokenInfo'
+import { TokenAggregateSupply } from '@/components/TokenAggregateSupply'
+import { useStartIndexer } from '@/hooks/useIndexer'
+import { Button } from '@/components/ui/button'
+import { RecentActivity } from '@/components/RecentActivity'
const IndexerStarter = () => {
- const indexer = useStartIndexer();
+ const indexer = useStartIndexer()
return (
- );
+ )
}
function App() {
return (
-
@@ -97,7 +99,7 @@ function App() {
- );
+ )
}
-export default App;
+export default App
diff --git a/packages/frontend/src/Bridge.tsx b/packages/frontend/src/Bridge.tsx
index e2191e4..21cd33f 100644
--- a/packages/frontend/src/Bridge.tsx
+++ b/packages/frontend/src/Bridge.tsx
@@ -1,51 +1,78 @@
import { useState } from 'react'
-import { Button } from "@/components/ui/button"
-import { Input } from "@/components/ui/input"
-import { Label } from "@/components/ui/label"
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import { Label } from '@/components/ui/label'
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from '@/components/ui/select'
import { chains } from '@/config'
-import { useTokenInfo } from "@/components/TokenInfo"
+import { useTokenInfo } from '@/hooks/useTokenInfo'
import { parseUnits } from 'viem'
import { contracts } from '@eth-optimism/viem'
-import { useAccount, useSimulateContract, useSwitchChain, useWaitForTransactionReceipt, useWriteContract } from 'wagmi'
+import {
+ useAccount,
+ useSimulateContract,
+ useSwitchChain,
+ useWaitForTransactionReceipt,
+ useWriteContract,
+} from 'wagmi'
import { envVars } from '@/envVars'
import { SuperchainTokenBridgeAbi } from '@/abi/SuperchainTokenBridgeAbi'
export const Bridge = () => {
const { address } = useAccount()
- const { symbol , decimals = 18} = useTokenInfo()
+ const { symbol, decimals = 18 } = useTokenInfo()
const [amount, setAmount] = useState('')
const amountUnits = parseUnits(amount, decimals)
- const [sourceChainIdString, setSourceChain] = useState(chains[0].id.toString())
+ const [sourceChainIdString, setSourceChain] = useState(
+ chains[0].id.toString(),
+ )
const sourceChainId = parseInt(sourceChainIdString)
- const [targetChainIdString, setTargetChain] = useState(chains[1].id.toString())
+ const [targetChainIdString, setTargetChain] = useState(
+ chains[1].id.toString(),
+ )
const targetChainId = parseInt(targetChainIdString)
- const sourceChain = chains.find(chain => chain.id === sourceChainId)
- const targetChain = chains.find(chain => chain.id === targetChainId)
+ const sourceChain = chains.find((chain) => chain.id === sourceChainId)
+ const targetChain = chains.find((chain) => chain.id === targetChainId)
const { switchChain } = useSwitchChain()
-
const simulationResult = useSimulateContract({
abi: SuperchainTokenBridgeAbi,
address: contracts.superchainTokenBridge.address,
functionName: 'sendERC20',
- args: [envVars.VITE_TOKEN_CONTRACT_ADDRESS, address!, amountUnits, BigInt(targetChainId)],
+ args: [
+ envVars.VITE_TOKEN_CONTRACT_ADDRESS,
+ address!,
+ amountUnits,
+ BigInt(targetChainId),
+ ],
chainId: sourceChainId,
})
- const { data: hash, isPending: isSendPending, writeContract, reset } = useWriteContract()
+ const {
+ data: hash,
+ isPending: isSendPending,
+ writeContract,
+ reset,
+ } = useWriteContract()
const handleSourceChainChange = async (chainId: string) => {
try {
// Attempt to switch chain first
await switchChain({ chainId: parseInt(chainId) })
-
+
// Only update the state if chain switch was successful
setSourceChain(chainId)
if (chainId === targetChainIdString) {
- const availableChains = chains.filter(chain => chain.id.toString() !== chainId)
+ const availableChains = chains.filter(
+ (chain) => chain.id.toString() !== chainId,
+ )
setTargetChain(availableChains[0]?.id.toString() || '')
}
@@ -60,17 +87,21 @@ export const Bridge = () => {
hash,
})
- const isLoading = isSendPending || isReceiptLoading || !simulationResult.data?.request
+ const isLoading =
+ isSendPending || isReceiptLoading || !simulationResult.data?.request
- const isButtonDisabled = !address || !amount || !sourceChain || !targetChain || isLoading
+ const isButtonDisabled =
+ !address || !amount || !sourceChain || !targetChain || isLoading
return (
Bridge {symbol}
-
Transfer assets between networks
+
+ Transfer assets between networks
+
-
+
@@ -82,11 +113,14 @@ export const Bridge = () => {
onChange={(e) => setAmount(e.target.value)}
/>
-
+
-
-
+
- {
{chains
- .filter(chain => chain.id.toString() !== sourceChainIdString)
+ .filter(
+ (chain) => chain.id.toString() !== sourceChainIdString,
+ )
.map((chain) => (
{chain.name}
@@ -124,9 +160,9 @@ export const Bridge = () => {
-
)
-}
\ No newline at end of file
+}
diff --git a/packages/frontend/src/Faucet.tsx b/packages/frontend/src/Faucet.tsx
index 3ffc920..f2618fb 100644
--- a/packages/frontend/src/Faucet.tsx
+++ b/packages/frontend/src/Faucet.tsx
@@ -1,22 +1,34 @@
import { useState } from 'react'
-import { Button } from "@/components/ui/button"
-import { Input } from "@/components/ui/input"
-import { Label } from "@/components/ui/label"
-import { Checkbox } from "@/components/ui/checkbox"
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import { Label } from '@/components/ui/label'
+import { Checkbox } from '@/components/ui/checkbox'
import { config, defaultDevAccount } from '@/config'
import { useAccount } from 'wagmi'
-import { Address, createWalletClient, Hash, http, parseEther, parseUnits, formatUnits } from 'viem'
-import { useTokenInfo } from '@/components/TokenInfo'
+import {
+ Address,
+ createWalletClient,
+ Hash,
+ http,
+ parseUnits,
+ formatUnits,
+} from 'viem'
+import { useTokenInfo } from '@/hooks/useTokenInfo'
import { L2NativeSuperchainERC20Abi } from '@/abi/L2NativeSuperchainERC20Abi'
import { envVars } from '@/envVars'
import { waitForTransactionReceipt } from '@wagmi/core'
import { useQuery } from '@tanstack/react-query'
-import { Loader2 } from "lucide-react"
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
-import { CheckCircle2, AlertCircle } from "lucide-react"
-
-const drip = async(recipient: Address, chainId: number, amount: string, decimals: number = 18) => {
- const chain = config.chains.find(x => x.id === chainId)
+import { Loader2 } from 'lucide-react'
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { CheckCircle2, AlertCircle } from 'lucide-react'
+
+const drip = async (
+ recipient: Address,
+ chainId: number,
+ amount: string,
+ decimals: number = 18,
+) => {
+ const chain = config.chains.find((x) => x.id === chainId)
if (!chain) throw new Error(`Chain with id ${chainId} not found`)
const walletClient = createWalletClient({
@@ -35,24 +47,38 @@ const drip = async(recipient: Address, chainId: number, amount: string, decimals
return hash
}
-const dripToMany = async (recipient: Address, chainIds: number[], amount: string, decimals: number = 18) => {
- const txs = await Promise.all(chainIds.map(async chainId => {
- return {
- hash: await drip(recipient, chainId, amount, decimals),
- chainId,
- }
- }))
+const dripToMany = async (
+ recipient: Address,
+ chainIds: number[],
+ amount: string,
+ decimals: number = 18,
+) => {
+ const txs = await Promise.all(
+ chainIds.map(async (chainId) => {
+ return {
+ hash: await drip(recipient, chainId, amount, decimals),
+ chainId,
+ }
+ }),
+ )
return txs
}
-const waitForManyTx = async (txs: {hash: Hash, chainId: number}[]) => {
- return await Promise.all(txs.map(async tx => {
- // @ts-expect-error
- return await waitForTransactionReceipt(config, {hash: tx.hash, chainId: tx.chainId, timeout: 10000, pollingInterval: 1000})
- }))
+const waitForManyTx = async (txs: { hash: Hash; chainId: number }[]) => {
+ return await Promise.all(
+ txs.map(async (tx) => {
+ return await waitForTransactionReceipt(config, {
+ hash: tx.hash,
+ chainId: tx.chainId as 901 | 902,
+ timeout: 10000,
+ pollingInterval: 1000,
+ })
+ }),
+ )
}
-const useWaitForManyTx = (txs: {hash: Hash, chainId: number}[]) => {//uses tanstack query
+const useWaitForManyTx = (txs: { hash: Hash; chainId: number }[]) => {
+ //uses tanstack query
return useQuery({
queryKey: ['waitForManyTx', txs],
queryFn: () => waitForManyTx(txs),
@@ -62,24 +88,25 @@ const useWaitForManyTx = (txs: {hash: Hash, chainId: number}[]) => {//uses tanst
export const Faucet = () => {
const account = useAccount()
- const [txs, setTxs] = useState<{hash: Hash, chainId: number}[]>([])
+ const [txs, setTxs] = useState<{ hash: Hash; chainId: number }[]>([])
- const {data: receipts, isLoading, isError} = useWaitForManyTx(txs)
-
- const {symbol, decimals = 18} = useTokenInfo()
+ const { data: receipts, isLoading, isError } = useWaitForManyTx(txs)
+ const { symbol, decimals = 18 } = useTokenInfo()
const [recipient, setRecipient] = useState(account.address || '')
- const [networks, setNetworks] = useState
(config.chains.map(x => x.id.toString()))
+ const [networks, setNetworks] = useState(
+ config.chains.map((x) => x.id.toString()),
+ )
const [amount, setAmount] = useState('1000')
const [isSubmitting, setIsSubmitting] = useState(false)
const handleNetworkToggle = (networkId: string) => {
- setNetworks(current =>
+ setNetworks((current) =>
current.includes(networkId)
- ? current.filter(id => id !== networkId)
- : [...current, networkId]
+ ? current.filter((id) => id !== networkId)
+ : [...current, networkId],
)
}
@@ -87,7 +114,9 @@ export const Faucet = () => {
Faucet
-
Drip {symbol} tokens on multiple networks
+
+ Drip {symbol} tokens on multiple networks
+
@@ -118,7 +147,9 @@ export const Faucet = () => {
handleNetworkToggle(chain.id.toString())}
+ onCheckedChange={() =>
+ handleNetworkToggle(chain.id.toString())
+ }
/>
-
@@ -168,15 +206,20 @@ export const Faucet = () => {
)}
{receipts && receipts.length > 0 && (
-
+
Success!
- Successfully dripped {formatUnits(parseUnits(amount, decimals), decimals)} {symbol} tokens on {receipts.length} networks.
+ Successfully dripped{' '}
+ {formatUnits(parseUnits(amount, decimals), decimals)} {symbol}{' '}
+ tokens on {receipts.length} networks.
)}
)
-}
\ No newline at end of file
+}
diff --git a/packages/frontend/src/Providers.tsx b/packages/frontend/src/Providers.tsx
index 0e9ab40..ebc73a7 100644
--- a/packages/frontend/src/Providers.tsx
+++ b/packages/frontend/src/Providers.tsx
@@ -1,22 +1,18 @@
-import { WagmiProvider } from 'wagmi';
-import {
- QueryClientProvider,
- QueryClient,
-} from "@tanstack/react-query";
+import { WagmiProvider } from 'wagmi'
+import { QueryClientProvider, QueryClient } from '@tanstack/react-query'
-import { config } from '@/config';
-import { Toaster } from '@/components/ui/toaster';
+import { config } from '@/config'
+import { Toaster } from '@/components/ui/toaster'
-
-const queryClient = new QueryClient();
+const queryClient = new QueryClient()
export const Providers = ({ children }: { children: React.ReactNode }) => {
return (
-
- {children}
+
+ {children}
- );
-};
+ )
+}
diff --git a/packages/frontend/src/TokenSupply.tsx b/packages/frontend/src/TokenSupply.tsx
index 089022b..f6877b7 100644
--- a/packages/frontend/src/TokenSupply.tsx
+++ b/packages/frontend/src/TokenSupply.tsx
@@ -4,26 +4,31 @@ import {
CardDescription,
CardHeader,
CardTitle,
-} from "@/components/ui/card"
-import { useIndexerStore } from "@/indexer/indexer"
-import { chains } from "@/config"
-import { useTokenInfo } from "@/components/TokenInfo"
+} from '@/components/ui/card'
+import { useIndexerStore } from '@/indexer/indexer'
+import { chains } from '@/config'
+import { useTokenInfo } from '@/hooks/useTokenInfo'
export const TokenSupply = () => {
const totalSupply = useIndexerStore((state) => state.totalSupply)
const { symbol, decimals } = useTokenInfo()
- const chainSupplies = chains.map(chain => ({
+ const chainSupplies = chains.map((chain) => ({
chainId: chain.id,
chainName: chain.name,
- symbol: symbol ?? "TOKEN",
- totalSupply: totalSupply[chain.id]?.toString() ?? "0",
+ symbol: symbol ?? 'TOKEN',
+ totalSupply: totalSupply[chain.id]?.toString() ?? '0',
decimals: decimals ?? 18,
- initials: chain.name.split(' ').map(word => word[0]).join('').toUpperCase()
+ initials: chain.name
+ .split(' ')
+ .map((word) => word[0])
+ .join('')
+ .toUpperCase(),
}))
- const aggregateSupply = chainSupplies.reduce((acc, chain) =>
- acc + (Number(chain.totalSupply) / 10 ** chain.decimals), 0
+ const aggregateSupply = chainSupplies.reduce(
+ (acc, chain) => acc + Number(chain.totalSupply) / 10 ** chain.decimals,
+ 0,
)
return (
@@ -35,15 +40,14 @@ export const TokenSupply = () => {
{chainSupplies.map((chain) => {
- const supply = Number(chain.totalSupply) / 10 ** chain.decimals;
- const percentage = aggregateSupply > 0 ? (supply / aggregateSupply) * 100 : 0;
+ const supply = Number(chain.totalSupply) / 10 ** chain.decimals
+ const percentage =
+ aggregateSupply > 0 ? (supply / aggregateSupply) * 100 : 0
return (
-
+
{chain.initials}
@@ -55,23 +59,27 @@ export const TokenSupply = () => {
-
{supply.toLocaleString()}
-
{chain.symbol}
+
+ {supply.toLocaleString()}
+
+
+ {chain.symbol}
+
- );
+ )
})}
- );
-}
\ No newline at end of file
+ )
+}
diff --git a/packages/frontend/src/components/RecentActivity.tsx b/packages/frontend/src/components/RecentActivity.tsx
index 4a6e215..53b0ff6 100644
--- a/packages/frontend/src/components/RecentActivity.tsx
+++ b/packages/frontend/src/components/RecentActivity.tsx
@@ -1,10 +1,9 @@
-import { Card } from "@/components/ui/card"
-import { useIndexerStore } from "@/indexer/indexer"
-import { ArrowDownIcon, ArrowUpIcon } from "lucide-react"
-import { zeroAddress, formatUnits } from "viem"
-import { chains } from "@/config"
-import { useTokenInfo } from "./TokenInfo"
-
+import { Card } from '@/components/ui/card'
+import { useIndexerStore } from '@/indexer/indexer'
+import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react'
+import { zeroAddress, formatUnits } from 'viem'
+import { chains } from '@/config'
+import { useTokenInfo } from '@/hooks/useTokenInfo'
// Simple utility function
const formatAddress = (address: string) => {
@@ -28,7 +27,7 @@ export const RecentActivity = () => {
Recent Activity
-
+
{recentTransfers.length === 0 ? (
No recent activity
) : (
@@ -52,10 +51,10 @@ export const RecentActivity = () => {
{transfer.from === zeroAddress
- ? "Mint"
+ ? 'Mint'
: transfer.to === zeroAddress
- ? "Burn"
- : "Transfer"}
+ ? 'Burn'
+ : 'Transfer'}
{decimals && symbol
@@ -67,12 +66,13 @@ export const RecentActivity = () => {
{transfer.from === zeroAddress
? `To: ${formatAddress(transfer.to)}`
: transfer.to === zeroAddress
- ? `From: ${formatAddress(transfer.from)}`
- : `${formatAddress(transfer.from)} → ${formatAddress(transfer.to)}`}
+ ? `From: ${formatAddress(transfer.from)}`
+ : `${formatAddress(transfer.from)} → ${formatAddress(transfer.to)}`}
- {chains.find(chain => chain.id === transfer.chainId)?.name || 'Unknown Chain'} •
- Block #{transfer.blockNumber.toString()}
+ {chains.find((chain) => chain.id === transfer.chainId)
+ ?.name || 'Unknown Chain'}{' '}
+ • Block #{transfer.blockNumber.toString()}
@@ -82,4 +82,4 @@ export const RecentActivity = () => {
)}
)
-}
\ No newline at end of file
+}
diff --git a/packages/frontend/src/components/TokenAggregateSupply.tsx b/packages/frontend/src/components/TokenAggregateSupply.tsx
index f6e3d10..477acd9 100644
--- a/packages/frontend/src/components/TokenAggregateSupply.tsx
+++ b/packages/frontend/src/components/TokenAggregateSupply.tsx
@@ -1,48 +1,56 @@
-import { Card } from "@/components/ui/card"
-import { useIndexerStore } from "@/indexer/indexer"
-import { formatUnits } from "viem"
-import { chains } from "@/config"
-import { useTokenInfo } from "@/components/TokenInfo"
-import { truncateDecimals } from "@/lib/truncateDecimals"
-
+import { Card } from '@/components/ui/card'
+import { useIndexerStore } from '@/indexer/indexer'
+import { formatUnits } from 'viem'
+import { chains } from '@/config'
+import { useTokenInfo } from '@/hooks/useTokenInfo'
+import { truncateDecimals } from '@/lib/truncateDecimals'
export const TokenAggregateSupply = () => {
const totalSupply = useIndexerStore((state) => state.totalSupply)
const { symbol, decimals } = useTokenInfo()
-
- const chainSupplies = chains.map(chain => ({
+
+ const chainSupplies = chains.map((chain) => ({
chainId: chain.id,
chainName: chain.name,
- symbol: symbol ?? "TOKEN",
+ symbol: symbol ?? 'TOKEN',
totalSupply: totalSupply[chain.id] ?? BigInt(0),
decimals: decimals ?? 18,
- initials: chain.name.split(' ').map(word => word[0]).join('').toUpperCase()
+ initials: chain.name
+ .split(' ')
+ .map((word) => word[0])
+ .join('')
+ .toUpperCase(),
}))
// Sum up total supply across all chains and format it
const aggregateSupply = Object.values(totalSupply).reduce(
(sum, chainSupply) => sum + chainSupply,
- BigInt(0)
+ BigInt(0),
)
-
+
const formattedSupply = formatUnits(aggregateSupply, 18)
return (
-
Total Supply
+
+ Total Supply
+
{truncateDecimals(Number(formattedSupply), 6)}
-
+
{chainSupplies.map((chain) => {
- const supply = Number(formatUnits(chain.totalSupply, chain.decimals));
- const percentage = Number(formattedSupply) > 0
- ? (supply / Number(formattedSupply)) * 100
- : 0;
+ const supply = Number(
+ formatUnits(chain.totalSupply, chain.decimals),
+ )
+ const percentage =
+ Number(formattedSupply) > 0
+ ? (supply / Number(formattedSupply)) * 100
+ : 0
return (
@@ -53,7 +61,9 @@ export const TokenAggregateSupply = () => {
-
{chain.chainName}
+
+ {chain.chainName}
+
{percentage.toFixed(1)}% of total
@@ -62,19 +72,21 @@ export const TokenAggregateSupply = () => {
{truncateDecimals(supply, 6)}
-
{chain.symbol}
+
+ {chain.symbol}
+
- );
+ )
})}
diff --git a/packages/frontend/src/components/TokenInfo.tsx b/packages/frontend/src/components/TokenInfo.tsx
index 2ff220c..9e6b344 100644
--- a/packages/frontend/src/components/TokenInfo.tsx
+++ b/packages/frontend/src/components/TokenInfo.tsx
@@ -1,49 +1,25 @@
-import { L2NativeSuperchainERC20Abi } from "@/abi/L2NativeSuperchainERC20Abi";
-import { Card } from "@/components/ui/card";
-import { envVars } from "@/envVars";
-import {useReadContracts} from 'wagmi'
-import { Copy } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { useToast } from "@/hooks/use-toast";
+import { L2NativeSuperchainERC20Abi } from '@/abi/L2NativeSuperchainERC20Abi'
+import { Card } from '@/components/ui/card'
+import { envVars } from '@/envVars'
+import { Copy } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { useToast } from '@/hooks/use-toast'
+import { useTokenInfo } from '@/hooks/useTokenInfo'
const tokenContract = {
address: envVars.VITE_TOKEN_CONTRACT_ADDRESS,
abi: L2NativeSuperchainERC20Abi,
}
-export const useTokenInfo = () => {
- const result = useReadContracts({
- contracts: [
- {
- ...tokenContract,
- functionName: 'symbol',
- },
- {
- ...tokenContract,
- functionName: 'decimals',
- },
- {
- ...tokenContract,
- functionName: 'name',
- },
- ],
- })
- const [symbol, decimals, name] = result.data || []
-
- return {
- symbol: symbol?.result,
- decimals: decimals?.result,
- name: name?.result,
- }
-}
-
export function TokenInfo() {
const { symbol, decimals, name } = useTokenInfo()
const { toast } = useToast()
return (
- Token Info
+
+ Token Info
+
{symbol}
@@ -53,7 +29,9 @@ export function TokenInfo() {
Address:
- {tokenContract.address}
+
+ {tokenContract.address}
+
- );
-}
\ No newline at end of file
+ )
+}
diff --git a/packages/frontend/src/components/WalletBalance.tsx b/packages/frontend/src/components/WalletBalance.tsx
index 56e739d..7d9c597 100644
--- a/packages/frontend/src/components/WalletBalance.tsx
+++ b/packages/frontend/src/components/WalletBalance.tsx
@@ -1,12 +1,12 @@
-import { Card } from "@/components/ui/card"
-import { useIndexerStore } from "@/indexer/indexer"
-import { formatUnits } from "viem"
-import { chains } from "@/config"
-import { useTokenInfo } from "@/components/TokenInfo"
-import { useAccount } from "wagmi"
-import { truncateDecimals } from "@/lib/truncateDecimals"
-import { Copy } from "lucide-react"
-import { useToast } from "@/hooks/use-toast"
+import { Card } from '@/components/ui/card'
+import { useIndexerStore } from '@/indexer/indexer'
+import { formatUnits } from 'viem'
+import { chains } from '@/config'
+import { useTokenInfo } from '@/hooks/useTokenInfo'
+import { useAccount } from 'wagmi'
+import { truncateDecimals } from '@/lib/truncateDecimals'
+import { Copy } from 'lucide-react'
+import { useToast } from '@/hooks/use-toast'
export const WalletBalance = () => {
const { address } = useAccount()
@@ -19,7 +19,7 @@ export const WalletBalance = () => {
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text)
toast({
- description: "Address copied to clipboard",
+ description: 'Address copied to clipboard',
duration: 2000,
})
}
@@ -27,24 +27,28 @@ export const WalletBalance = () => {
const balances = useIndexerStore((state) => state.balances)
const { symbol, decimals } = useTokenInfo()
- // Return early if no address is connected
- if (!address) {
- return (
-
-
- Connect your wallet to view balances
-
-
- )
- }
+ // Return early if no address is connected
+ if (!address) {
+ return (
+
+
+ Connect your wallet to view balances
+
+
+ )
+ }
- const chainBalances = chains.map(chain => ({
+ const chainBalances = chains.map((chain) => ({
chainId: chain.id,
chainName: chain.name,
- symbol: symbol ?? "TOKEN",
+ symbol: symbol ?? 'TOKEN',
balance: balances.perChain[chain.id]?.[address] ?? BigInt(0),
decimals: decimals ?? 18,
- initials: chain.name.split(' ').map(word => word[0]).join('').toUpperCase()
+ initials: chain.name
+ .split(' ')
+ .map((word) => word[0])
+ .join('')
+ .toUpperCase(),
}))
// Calculate total balance across all chains
@@ -56,9 +60,11 @@ export const WalletBalance = () => {
-
Wallet Balance
+
+ Wallet Balance
+
{address && (
-
copyToClipboard(address)}
>
@@ -71,13 +77,14 @@ export const WalletBalance = () => {
{truncateDecimals(Number(formattedTotal), 6)}
-
+
{chainBalances.map((chain) => {
- const balance = Number(formatUnits(chain.balance, chain.decimals));
- const percentage = Number(formattedTotal) > 0
- ? (balance / Number(formattedTotal)) * 100
- : 0;
+ const balance = Number(formatUnits(chain.balance, chain.decimals))
+ const percentage =
+ Number(formattedTotal) > 0
+ ? (balance / Number(formattedTotal)) * 100
+ : 0
return (
@@ -88,7 +95,9 @@ export const WalletBalance = () => {
-
{chain.chainName}
+
+ {chain.chainName}
+
{percentage.toFixed(1)}% of total
@@ -97,19 +106,21 @@ export const WalletBalance = () => {
{truncateDecimals(balance, 6)}
-
{chain.symbol}
+
+ {chain.symbol}
+
- );
+ )
})}
diff --git a/packages/frontend/src/components/connect-wallet/ConnectWalletButton.tsx b/packages/frontend/src/components/connect-wallet/ConnectWalletButton.tsx
index 569c2db..e0813c4 100644
--- a/packages/frontend/src/components/connect-wallet/ConnectWalletButton.tsx
+++ b/packages/frontend/src/components/connect-wallet/ConnectWalletButton.tsx
@@ -1,9 +1,9 @@
import { useAccount, useDisconnect } from 'wagmi'
import * as React from 'react'
import { Connector, useConnect } from 'wagmi'
-import { Button } from "@/components/ui/button"
-import { Card } from "@/components/ui/card"
-import { WalletIcon } from "lucide-react"
+import { Button } from '@/components/ui/button'
+import { Card } from '@/components/ui/card'
+import { WalletIcon } from 'lucide-react'
import {
Dialog,
DialogContent,
@@ -11,10 +11,10 @@ import {
DialogTitle,
DialogTrigger,
DialogDescription,
-} from "@/components/ui/dialog"
+} from '@/components/ui/dialog'
-import { Badge } from "@/components/ui/badge"
-import { ChevronRight, ArrowRight, Copy, Activity, Power } from "lucide-react"
+import { Badge } from '@/components/ui/badge'
+import { ChevronRight, ArrowRight, Copy, Activity, Power } from 'lucide-react'
import {
DropdownMenu,
DropdownMenuContent,
@@ -22,8 +22,8 @@ import {
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu"
-import { useToast } from "@/hooks/use-toast"
+} from '@/components/ui/dropdown-menu'
+import { useToast } from '@/hooks/use-toast'
function WalletOptions() {
const { connectors, connect } = useConnect()
@@ -33,7 +33,7 @@ function WalletOptions() {
Choose your preferred wallet to connect.
-
+
{connectors.map((connector) => (
{
navigator.clipboard.writeText(address || '')
toast({
- description: "Address copied to clipboard",
+ description: 'Address copied to clipboard',
duration: 2000,
})
}
@@ -116,7 +116,11 @@ export function Account() {
{connector?.icon ? (
-
+
) : (
)}
@@ -124,9 +128,7 @@ export function Account() {
{address?.slice(0, 6)}...{address?.slice(-4)}
-
- {address?.slice(0, 4)}...
-
+
{address?.slice(0, 4)}...
@@ -134,12 +136,15 @@ export function Account() {
{connector?.name || 'Wallet'}
-
+
Copy Address
- disconnect()}
+ disconnect()}
className="gap-2 text-destructive focus:text-destructive cursor-pointer"
>
@@ -152,9 +157,9 @@ export function Account() {
export const ConnectWalletButton = () => {
const { isConnected } = useAccount()
-
+
if (isConnected) return
-
+
return (
)
-}
\ No newline at end of file
+}
diff --git a/packages/frontend/src/components/ui/alert.tsx b/packages/frontend/src/components/ui/alert.tsx
index 5afd41d..467e32a 100644
--- a/packages/frontend/src/components/ui/alert.tsx
+++ b/packages/frontend/src/components/ui/alert.tsx
@@ -1,22 +1,22 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from 'react'
+import { cva, type VariantProps } from 'class-variance-authority'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const alertVariants = cva(
- "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
+ 'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7',
{
variants: {
variant: {
- default: "bg-background text-foreground",
+ default: 'bg-background text-foreground',
destructive:
- "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
+ 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
},
},
defaultVariants: {
- variant: "default",
+ variant: 'default',
},
- }
+ },
)
const Alert = React.forwardRef<
@@ -30,7 +30,7 @@ const Alert = React.forwardRef<
{...props}
/>
))
-Alert.displayName = "Alert"
+Alert.displayName = 'Alert'
const AlertTitle = React.forwardRef<
HTMLParagraphElement,
@@ -38,11 +38,11 @@ const AlertTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-AlertTitle.displayName = "AlertTitle"
+AlertTitle.displayName = 'AlertTitle'
const AlertDescription = React.forwardRef<
HTMLParagraphElement,
@@ -50,10 +50,10 @@ const AlertDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-AlertDescription.displayName = "AlertDescription"
+AlertDescription.displayName = 'AlertDescription'
export { Alert, AlertTitle, AlertDescription }
diff --git a/packages/frontend/src/components/ui/badge-variants.tsx b/packages/frontend/src/components/ui/badge-variants.tsx
new file mode 100644
index 0000000..283694b
--- /dev/null
+++ b/packages/frontend/src/components/ui/badge-variants.tsx
@@ -0,0 +1,21 @@
+import { cva } from 'class-variance-authority'
+
+export const badgeVariants = cva(
+ 'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
+ {
+ variants: {
+ variant: {
+ default:
+ 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
+ secondary:
+ 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
+ destructive:
+ 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
+ outline: 'text-foreground',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ },
+ },
+)
diff --git a/packages/frontend/src/components/ui/badge.tsx b/packages/frontend/src/components/ui/badge.tsx
index e87d62b..217d719 100644
--- a/packages/frontend/src/components/ui/badge.tsx
+++ b/packages/frontend/src/components/ui/badge.tsx
@@ -1,27 +1,8 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from 'react'
+import { type VariantProps } from 'class-variance-authority'
+import { badgeVariants } from './badge-variants'
-import { cn } from "@/lib/utils"
-
-const badgeVariants = cva(
- "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
- {
- variants: {
- variant: {
- default:
- "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
- secondary:
- "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
- destructive:
- "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
- outline: "text-foreground",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-)
+import { cn } from '@/lib/utils'
export interface BadgeProps
extends React.HTMLAttributes,
@@ -33,4 +14,4 @@ function Badge({ className, variant, ...props }: BadgeProps) {
)
}
-export { Badge, badgeVariants }
+export { Badge }
diff --git a/packages/frontend/src/components/ui/button-variants.tsx b/packages/frontend/src/components/ui/button-variants.tsx
new file mode 100644
index 0000000..ccebfdf
--- /dev/null
+++ b/packages/frontend/src/components/ui/button-variants.tsx
@@ -0,0 +1,31 @@
+import { cva } from 'class-variance-authority'
+
+export const buttonVariants = cva(
+ 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
+ {
+ variants: {
+ variant: {
+ default:
+ 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
+ destructive:
+ 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
+ outline:
+ 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
+ secondary:
+ 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
+ link: 'text-primary underline-offset-4 hover:underline',
+ },
+ size: {
+ default: 'h-9 px-4 py-2',
+ sm: 'h-8 rounded-md px-3 text-xs',
+ lg: 'h-10 rounded-md px-8',
+ icon: 'h-9 w-9',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default',
+ },
+ },
+)
diff --git a/packages/frontend/src/components/ui/button.tsx b/packages/frontend/src/components/ui/button.tsx
index 65d4fcd..69407af 100644
--- a/packages/frontend/src/components/ui/button.tsx
+++ b/packages/frontend/src/components/ui/button.tsx
@@ -1,38 +1,8 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
- {
- variants: {
- variant: {
- default:
- "bg-primary text-primary-foreground shadow hover:bg-primary/90",
- destructive:
- "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
- outline:
- "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
- secondary:
- "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
- ghost: "hover:bg-accent hover:text-accent-foreground",
- link: "text-primary underline-offset-4 hover:underline",
- },
- size: {
- default: "h-9 px-4 py-2",
- sm: "h-8 rounded-md px-3 text-xs",
- lg: "h-10 rounded-md px-8",
- icon: "h-9 w-9",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- }
-)
+import * as React from 'react'
+import { Slot } from '@radix-ui/react-slot'
+import { type VariantProps } from 'class-variance-authority'
+import { buttonVariants } from './button-variants'
+import { cn } from '@/lib/utils'
export interface ButtonProps
extends React.ButtonHTMLAttributes,
@@ -42,7 +12,7 @@ export interface ButtonProps
const Button = React.forwardRef(
({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button"
+ const Comp = asChild ? Slot : 'button'
return (
(
{...props}
/>
)
- }
+ },
)
-Button.displayName = "Button"
+Button.displayName = 'Button'
-export { Button, buttonVariants }
+export { Button }
diff --git a/packages/frontend/src/components/ui/card.tsx b/packages/frontend/src/components/ui/card.tsx
index 77e9fb7..69cca19 100644
--- a/packages/frontend/src/components/ui/card.tsx
+++ b/packages/frontend/src/components/ui/card.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
+import * as React from 'react'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Card = React.forwardRef<
HTMLDivElement,
@@ -9,13 +9,13 @@ const Card = React.forwardRef<
))
-Card.displayName = "Card"
+Card.displayName = 'Card'
const CardHeader = React.forwardRef<
HTMLDivElement,
@@ -23,11 +23,11 @@ const CardHeader = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-CardHeader.displayName = "CardHeader"
+CardHeader.displayName = 'CardHeader'
const CardTitle = React.forwardRef<
HTMLParagraphElement,
@@ -35,11 +35,11 @@ const CardTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-CardTitle.displayName = "CardTitle"
+CardTitle.displayName = 'CardTitle'
const CardDescription = React.forwardRef<
HTMLParagraphElement,
@@ -47,19 +47,19 @@ const CardDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-CardDescription.displayName = "CardDescription"
+CardDescription.displayName = 'CardDescription'
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => (
-
+
))
-CardContent.displayName = "CardContent"
+CardContent.displayName = 'CardContent'
const CardFooter = React.forwardRef<
HTMLDivElement,
@@ -67,10 +67,10 @@ const CardFooter = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-CardFooter.displayName = "CardFooter"
+CardFooter.displayName = 'CardFooter'
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/packages/frontend/src/components/ui/checkbox.tsx b/packages/frontend/src/components/ui/checkbox.tsx
index f831532..3d6f7bc 100644
--- a/packages/frontend/src/components/ui/checkbox.tsx
+++ b/packages/frontend/src/components/ui/checkbox.tsx
@@ -1,8 +1,8 @@
-import * as React from "react"
-import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
-import { CheckIcon } from "@radix-ui/react-icons"
+import * as React from 'react'
+import * as CheckboxPrimitive from '@radix-ui/react-checkbox'
+import { CheckIcon } from '@radix-ui/react-icons'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Checkbox = React.forwardRef<
React.ElementRef,
@@ -11,13 +11,13 @@ const Checkbox = React.forwardRef<
diff --git a/packages/frontend/src/components/ui/dialog.tsx b/packages/frontend/src/components/ui/dialog.tsx
index 5d16351..05f69eb 100644
--- a/packages/frontend/src/components/ui/dialog.tsx
+++ b/packages/frontend/src/components/ui/dialog.tsx
@@ -1,8 +1,8 @@
-import * as React from "react"
-import * as DialogPrimitive from "@radix-ui/react-dialog"
-import { Cross2Icon } from "@radix-ui/react-icons"
+import * as React from 'react'
+import * as DialogPrimitive from '@radix-ui/react-dialog'
+import { Cross2Icon } from '@radix-ui/react-icons'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Dialog = DialogPrimitive.Root
@@ -19,8 +19,8 @@ const DialogOverlay = React.forwardRef<
@@ -36,8 +36,8 @@ const DialogContent = React.forwardRef<
@@ -57,13 +57,13 @@ const DialogHeader = ({
}: React.HTMLAttributes) => (
)
-DialogHeader.displayName = "DialogHeader"
+DialogHeader.displayName = 'DialogHeader'
const DialogFooter = ({
className,
@@ -71,13 +71,13 @@ const DialogFooter = ({
}: React.HTMLAttributes) => (
)
-DialogFooter.displayName = "DialogFooter"
+DialogFooter.displayName = 'DialogFooter'
const DialogTitle = React.forwardRef<
React.ElementRef,
@@ -86,8 +86,8 @@ const DialogTitle = React.forwardRef<
@@ -100,7 +100,7 @@ const DialogDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
))
diff --git a/packages/frontend/src/components/ui/dropdown-menu.tsx b/packages/frontend/src/components/ui/dropdown-menu.tsx
index 61eadd5..4c071c4 100644
--- a/packages/frontend/src/components/ui/dropdown-menu.tsx
+++ b/packages/frontend/src/components/ui/dropdown-menu.tsx
@@ -1,12 +1,12 @@
-import * as React from "react"
-import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
+import * as React from 'react'
+import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
import {
CheckIcon,
ChevronRightIcon,
DotFilledIcon,
-} from "@radix-ui/react-icons"
+} from '@radix-ui/react-icons'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const DropdownMenu = DropdownMenuPrimitive.Root
@@ -29,9 +29,9 @@ const DropdownMenuSubTrigger = React.forwardRef<
@@ -49,8 +49,8 @@ const DropdownMenuSubContent = React.forwardRef<
@@ -67,9 +67,9 @@ const DropdownMenuContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
- "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
- className
+ 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
+ className,
)}
{...props}
/>
@@ -86,9 +86,9 @@ const DropdownMenuItem = React.forwardRef<
svg]:size-4 [&>svg]:shrink-0",
- inset && "pl-8",
- className
+ 'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
+ inset && 'pl-8',
+ className,
)}
{...props}
/>
@@ -102,8 +102,8 @@ const DropdownMenuCheckboxItem = React.forwardRef<
@@ -150,9 +150,9 @@ const DropdownMenuLabel = React.forwardRef<
@@ -165,7 +165,7 @@ const DropdownMenuSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
))
@@ -177,12 +177,12 @@ const DropdownMenuShortcut = ({
}: React.HTMLAttributes) => {
return (
)
}
-DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
+DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'
export {
DropdownMenu,
diff --git a/packages/frontend/src/components/ui/input.tsx b/packages/frontend/src/components/ui/input.tsx
index 5af26b2..fe57bee 100644
--- a/packages/frontend/src/components/ui/input.tsx
+++ b/packages/frontend/src/components/ui/input.tsx
@@ -1,25 +1,23 @@
-import * as React from "react"
+import * as React from 'react'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
-export interface InputProps
- extends React.InputHTMLAttributes {}
-
-const Input = React.forwardRef(
- ({ className, type, ...props }, ref) => {
- return (
-
- )
- }
-)
-Input.displayName = "Input"
+const Input = React.forwardRef<
+ HTMLInputElement,
+ React.InputHTMLAttributes
+>(({ className, type, ...props }, ref) => {
+ return (
+
+ )
+})
+Input.displayName = 'Input'
export { Input }
diff --git a/packages/frontend/src/components/ui/label.tsx b/packages/frontend/src/components/ui/label.tsx
index 683faa7..586e08e 100644
--- a/packages/frontend/src/components/ui/label.tsx
+++ b/packages/frontend/src/components/ui/label.tsx
@@ -1,11 +1,11 @@
-import * as React from "react"
-import * as LabelPrimitive from "@radix-ui/react-label"
-import { cva, type VariantProps } from "class-variance-authority"
+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/utils"
+import { cn } from '@/lib/utils'
const labelVariants = cva(
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
+ 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
)
const Label = React.forwardRef<
diff --git a/packages/frontend/src/components/ui/progress.tsx b/packages/frontend/src/components/ui/progress.tsx
index 3fd47ad..362579c 100644
--- a/packages/frontend/src/components/ui/progress.tsx
+++ b/packages/frontend/src/components/ui/progress.tsx
@@ -1,7 +1,7 @@
-import * as React from "react"
-import * as ProgressPrimitive from "@radix-ui/react-progress"
+import * as React from 'react'
+import * as ProgressPrimitive from '@radix-ui/react-progress'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Progress = React.forwardRef<
React.ElementRef,
@@ -10,8 +10,8 @@ const Progress = React.forwardRef<
diff --git a/packages/frontend/src/components/ui/scroll-area.tsx b/packages/frontend/src/components/ui/scroll-area.tsx
index 0b4a48d..69f1f4e 100644
--- a/packages/frontend/src/components/ui/scroll-area.tsx
+++ b/packages/frontend/src/components/ui/scroll-area.tsx
@@ -1,9 +1,9 @@
-"use client"
+'use client'
-import * as React from "react"
-import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
+import * as React from 'react'
+import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const ScrollArea = React.forwardRef<
React.ElementRef,
@@ -11,7 +11,7 @@ const ScrollArea = React.forwardRef<
>(({ className, children, ...props }, ref) => (
@@ -26,17 +26,17 @@ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
const ScrollBar = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
->(({ className, orientation = "vertical", ...props }, ref) => (
+>(({ className, orientation = 'vertical', ...props }, ref) => (
diff --git a/packages/frontend/src/components/ui/select.tsx b/packages/frontend/src/components/ui/select.tsx
index cdfb8ce..b24841d 100644
--- a/packages/frontend/src/components/ui/select.tsx
+++ b/packages/frontend/src/components/ui/select.tsx
@@ -1,13 +1,13 @@
-import * as React from "react"
+import * as React from 'react'
import {
CaretSortIcon,
CheckIcon,
ChevronDownIcon,
ChevronUpIcon,
-} from "@radix-ui/react-icons"
-import * as SelectPrimitive from "@radix-ui/react-select"
+} from '@radix-ui/react-icons'
+import * as SelectPrimitive from '@radix-ui/react-select'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Select = SelectPrimitive.Root
@@ -22,8 +22,8 @@ const SelectTrigger = React.forwardRef<
span]:line-clamp-1",
- className
+ 'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
+ className,
)}
{...props}
>
@@ -42,8 +42,8 @@ const SelectScrollUpButton = React.forwardRef<
@@ -59,8 +59,8 @@ const SelectScrollDownButton = React.forwardRef<
@@ -73,15 +73,15 @@ SelectScrollDownButton.displayName =
const SelectContent = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
->(({ className, children, position = "popper", ...props }, ref) => (
+>(({ className, children, position = 'popper', ...props }, ref) => (
{children}
@@ -108,7 +108,7 @@ const SelectLabel = React.forwardRef<
>(({ className, ...props }, ref) => (
))
@@ -121,8 +121,8 @@ const SelectItem = React.forwardRef<
@@ -142,7 +142,7 @@ const SelectSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
))
diff --git a/packages/frontend/src/components/ui/separator.tsx b/packages/frontend/src/components/ui/separator.tsx
index 6d7f122..86b2aa2 100644
--- a/packages/frontend/src/components/ui/separator.tsx
+++ b/packages/frontend/src/components/ui/separator.tsx
@@ -1,28 +1,28 @@
-import * as React from "react"
-import * as SeparatorPrimitive from "@radix-ui/react-separator"
+import * as React from 'react'
+import * as SeparatorPrimitive from '@radix-ui/react-separator'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Separator = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
>(
(
- { className, orientation = "horizontal", decorative = true, ...props },
- ref
+ { className, orientation = 'horizontal', decorative = true, ...props },
+ ref,
) => (
- )
+ ),
)
Separator.displayName = SeparatorPrimitive.Root.displayName
diff --git a/packages/frontend/src/components/ui/table.tsx b/packages/frontend/src/components/ui/table.tsx
index c0df655..084ecec 100644
--- a/packages/frontend/src/components/ui/table.tsx
+++ b/packages/frontend/src/components/ui/table.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
+import * as React from 'react'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Table = React.forwardRef<
HTMLTableElement,
@@ -9,20 +9,20 @@ const Table = React.forwardRef<
))
-Table.displayName = "Table"
+Table.displayName = 'Table'
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => (
-
+
))
-TableHeader.displayName = "TableHeader"
+TableHeader.displayName = 'TableHeader'
const TableBody = React.forwardRef<
HTMLTableSectionElement,
@@ -30,11 +30,11 @@ const TableBody = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-TableBody.displayName = "TableBody"
+TableBody.displayName = 'TableBody'
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
@@ -43,13 +43,13 @@ const TableFooter = React.forwardRef<
tr]:last:border-b-0",
- className
+ 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',
+ className,
)}
{...props}
/>
))
-TableFooter.displayName = "TableFooter"
+TableFooter.displayName = 'TableFooter'
const TableRow = React.forwardRef<
HTMLTableRowElement,
@@ -58,13 +58,13 @@ const TableRow = React.forwardRef<
))
-TableRow.displayName = "TableRow"
+TableRow.displayName = 'TableRow'
const TableHead = React.forwardRef<
HTMLTableCellElement,
@@ -73,13 +73,13 @@ const TableHead = React.forwardRef<
[role=checkbox]]:translate-y-[2px]",
- className
+ 'h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
+ className,
)}
{...props}
/>
))
-TableHead.displayName = "TableHead"
+TableHead.displayName = 'TableHead'
const TableCell = React.forwardRef<
HTMLTableCellElement,
@@ -88,13 +88,13 @@ const TableCell = React.forwardRef<
| [role=checkbox]]:translate-y-[2px]",
- className
+ 'p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
+ className,
)}
{...props}
/>
))
-TableCell.displayName = "TableCell"
+TableCell.displayName = 'TableCell'
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
@@ -102,11 +102,11 @@ const TableCaption = React.forwardRef<
>(({ className, ...props }, ref) => (
))
-TableCaption.displayName = "TableCaption"
+TableCaption.displayName = 'TableCaption'
export {
Table,
diff --git a/packages/frontend/src/components/ui/tabs.tsx b/packages/frontend/src/components/ui/tabs.tsx
index 0f4caeb..00852fa 100644
--- a/packages/frontend/src/components/ui/tabs.tsx
+++ b/packages/frontend/src/components/ui/tabs.tsx
@@ -1,9 +1,9 @@
-"use client"
+'use client'
-import * as React from "react"
-import * as TabsPrimitive from "@radix-ui/react-tabs"
+import * as React from 'react'
+import * as TabsPrimitive from '@radix-ui/react-tabs'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const Tabs = TabsPrimitive.Root
@@ -14,8 +14,8 @@ const TabsList = React.forwardRef<
@@ -29,8 +29,8 @@ const TabsTrigger = React.forwardRef<
@@ -44,8 +44,8 @@ const TabsContent = React.forwardRef<
diff --git a/packages/frontend/src/components/ui/toast.tsx b/packages/frontend/src/components/ui/toast.tsx
index f79747a..59abcd0 100644
--- a/packages/frontend/src/components/ui/toast.tsx
+++ b/packages/frontend/src/components/ui/toast.tsx
@@ -1,9 +1,9 @@
-import * as React from "react"
-import { Cross2Icon } from "@radix-ui/react-icons"
-import * as ToastPrimitives from "@radix-ui/react-toast"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from 'react'
+import { Cross2Icon } from '@radix-ui/react-icons'
+import * as ToastPrimitives from '@radix-ui/react-toast'
+import { cva, type VariantProps } from 'class-variance-authority'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const ToastProvider = ToastPrimitives.Provider
@@ -14,8 +14,8 @@ const ToastViewport = React.forwardRef<
@@ -23,19 +23,19 @@ const ToastViewport = React.forwardRef<
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
const toastVariants = cva(
- "group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 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",
+ 'group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 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',
{
variants: {
variant: {
- default: "border bg-background text-foreground",
+ default: 'border bg-background text-foreground',
destructive:
- "destructive group border-destructive bg-destructive text-destructive-foreground",
+ 'destructive group border-destructive bg-destructive text-destructive-foreground',
},
},
defaultVariants: {
- variant: "default",
+ variant: 'default',
},
- }
+ },
)
const Toast = React.forwardRef<
@@ -60,8 +60,8 @@ const ToastAction = React.forwardRef<
@@ -75,8 +75,8 @@ const ToastClose = React.forwardRef<
(({ className, ...props }, ref) => (
))
@@ -104,7 +104,7 @@ const ToastDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
))
diff --git a/packages/frontend/src/components/ui/toaster.tsx b/packages/frontend/src/components/ui/toaster.tsx
index 6c67edf..daef121 100644
--- a/packages/frontend/src/components/ui/toaster.tsx
+++ b/packages/frontend/src/components/ui/toaster.tsx
@@ -1,4 +1,4 @@
-import { useToast } from "@/hooks/use-toast"
+import { useToast } from '@/hooks/use-toast'
import {
Toast,
ToastClose,
@@ -6,7 +6,7 @@ import {
ToastProvider,
ToastTitle,
ToastViewport,
-} from "@/components/ui/toast"
+} from '@/components/ui/toast'
export function Toaster() {
const { toasts } = useToast()
diff --git a/packages/frontend/src/components/ui/tooltip.tsx b/packages/frontend/src/components/ui/tooltip.tsx
index 218d183..24efa26 100644
--- a/packages/frontend/src/components/ui/tooltip.tsx
+++ b/packages/frontend/src/components/ui/tooltip.tsx
@@ -1,7 +1,7 @@
-import * as React from "react"
-import * as TooltipPrimitive from "@radix-ui/react-tooltip"
+import * as React from 'react'
+import * as TooltipPrimitive from '@radix-ui/react-tooltip'
-import { cn } from "@/lib/utils"
+import { cn } from '@/lib/utils'
const TooltipProvider = TooltipPrimitive.Provider
@@ -18,8 +18,8 @@ const TooltipContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
- "z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
- className
+ 'z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
+ className,
)}
{...props}
/>
diff --git a/packages/frontend/src/connectors/devAccount.ts b/packages/frontend/src/connectors/devAccount.ts
index c262d55..c3843b0 100644
--- a/packages/frontend/src/connectors/devAccount.ts
+++ b/packages/frontend/src/connectors/devAccount.ts
@@ -1,5 +1,5 @@
import { createConnector, http } from 'wagmi'
-import { Account, Chain, createWalletClient, EIP1193Provider } from 'viem'
+import { Account, Chain, createWalletClient } from 'viem'
const createProvider = (chain: Chain, account: Account) => {
const accountClient = createWalletClient({
@@ -8,11 +8,14 @@ const createProvider = (chain: Chain, account: Account) => {
transport: http(),
})
- const request = async ({ method, params }: any) => {
+ const request = async ({
+ method,
+ params,
+ }: Parameters) => {
return accountClient.request({ method, params })
}
- return { request } as EIP1193Provider
+ return { request }
}
// A connector that allows you to connect to a specific account on every chain
@@ -20,12 +23,15 @@ export const devAccount = (account: Account) => {
return createConnector((config) => {
let currentChain = config.chains[0]
- let providerByChainId = new Map()
+ const providerByChainId = new Map<
+ number,
+ ReturnType
+ >()
config.chains.forEach((chain) => {
providerByChainId.set(chain.id, createProvider(chain, account))
})
- let chainById = new Map()
+ const chainById = new Map()
config.chains.forEach((chain) => {
chainById.set(chain.id, chain)
})
diff --git a/packages/frontend/src/hooks/use-toast.ts b/packages/frontend/src/hooks/use-toast.ts
index 02e111d..e5e3db2 100644
--- a/packages/frontend/src/hooks/use-toast.ts
+++ b/packages/frontend/src/hooks/use-toast.ts
@@ -1,12 +1,9 @@
-"use client"
+'use client'
// Inspired by react-hot-toast library
-import * as React from "react"
+import * as React from 'react'
-import type {
- ToastActionElement,
- ToastProps,
-} from "@/components/ui/toast"
+import type { ToastActionElement, ToastProps } from '@/components/ui/toast'
const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000
@@ -18,12 +15,12 @@ type ToasterToast = ToastProps & {
action?: ToastActionElement
}
-const actionTypes = {
- ADD_TOAST: "ADD_TOAST",
- UPDATE_TOAST: "UPDATE_TOAST",
- DISMISS_TOAST: "DISMISS_TOAST",
- REMOVE_TOAST: "REMOVE_TOAST",
-} as const
+type ActionType = {
+ ADD_TOAST: 'ADD_TOAST'
+ UPDATE_TOAST: 'UPDATE_TOAST'
+ DISMISS_TOAST: 'DISMISS_TOAST'
+ REMOVE_TOAST: 'REMOVE_TOAST'
+}
let count = 0
@@ -32,24 +29,22 @@ function genId() {
return count.toString()
}
-type ActionType = typeof actionTypes
-
type Action =
| {
- type: ActionType["ADD_TOAST"]
+ type: ActionType['ADD_TOAST']
toast: ToasterToast
}
| {
- type: ActionType["UPDATE_TOAST"]
+ type: ActionType['UPDATE_TOAST']
toast: Partial
}
| {
- type: ActionType["DISMISS_TOAST"]
- toastId?: ToasterToast["id"]
+ type: ActionType['DISMISS_TOAST']
+ toastId?: ToasterToast['id']
}
| {
- type: ActionType["REMOVE_TOAST"]
- toastId?: ToasterToast["id"]
+ type: ActionType['REMOVE_TOAST']
+ toastId?: ToasterToast['id']
}
interface State {
@@ -66,7 +61,7 @@ const addToRemoveQueue = (toastId: string) => {
const timeout = setTimeout(() => {
toastTimeouts.delete(toastId)
dispatch({
- type: "REMOVE_TOAST",
+ type: 'REMOVE_TOAST',
toastId: toastId,
})
}, TOAST_REMOVE_DELAY)
@@ -76,21 +71,21 @@ const addToRemoveQueue = (toastId: string) => {
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
- case "ADD_TOAST":
+ case 'ADD_TOAST':
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
}
- case "UPDATE_TOAST":
+ case 'UPDATE_TOAST':
return {
...state,
toasts: state.toasts.map((t) =>
- t.id === action.toast.id ? { ...t, ...action.toast } : t
+ t.id === action.toast.id ? { ...t, ...action.toast } : t,
),
}
- case "DISMISS_TOAST": {
+ case 'DISMISS_TOAST': {
const { toastId } = action
// ! Side effects ! - This could be extracted into a dismissToast() action,
@@ -111,11 +106,11 @@ export const reducer = (state: State, action: Action): State => {
...t,
open: false,
}
- : t
+ : t,
),
}
}
- case "REMOVE_TOAST":
+ case 'REMOVE_TOAST':
if (action.toastId === undefined) {
return {
...state,
@@ -140,20 +135,20 @@ function dispatch(action: Action) {
})
}
-type Toast = Omit
+type Toast = Omit
function toast({ ...props }: Toast) {
const id = genId()
const update = (props: ToasterToast) =>
dispatch({
- type: "UPDATE_TOAST",
+ type: 'UPDATE_TOAST',
toast: { ...props, id },
})
- const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
+ const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id })
dispatch({
- type: "ADD_TOAST",
+ type: 'ADD_TOAST',
toast: {
...props,
id,
@@ -187,7 +182,7 @@ function useToast() {
return {
...state,
toast,
- dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
+ dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
}
}
diff --git a/packages/frontend/src/hooks/useIndexer.ts b/packages/frontend/src/hooks/useIndexer.ts
index 63a51f5..4586333 100644
--- a/packages/frontend/src/hooks/useIndexer.ts
+++ b/packages/frontend/src/hooks/useIndexer.ts
@@ -25,7 +25,7 @@ export function useStartIndexer() {
createPublicClient({
chain,
transport: transports[chain.id],
- }),
+ }) as ReturnType,
]),
)
diff --git a/packages/frontend/src/hooks/useTokenInfo.ts b/packages/frontend/src/hooks/useTokenInfo.ts
new file mode 100644
index 0000000..af6843d
--- /dev/null
+++ b/packages/frontend/src/hooks/useTokenInfo.ts
@@ -0,0 +1,34 @@
+import { L2NativeSuperchainERC20Abi } from '@/abi/L2NativeSuperchainERC20Abi'
+import { envVars } from '@/envVars'
+import { useReadContracts } from 'wagmi'
+
+const tokenContract = {
+ address: envVars.VITE_TOKEN_CONTRACT_ADDRESS,
+ abi: L2NativeSuperchainERC20Abi,
+}
+
+export const useTokenInfo = () => {
+ const result = useReadContracts({
+ contracts: [
+ {
+ ...tokenContract,
+ functionName: 'symbol',
+ },
+ {
+ ...tokenContract,
+ functionName: 'decimals',
+ },
+ {
+ ...tokenContract,
+ functionName: 'name',
+ },
+ ],
+ })
+ const [symbol, decimals, name] = result.data || []
+
+ return {
+ symbol: symbol?.result,
+ decimals: decimals?.result,
+ name: name?.result,
+ }
+}
diff --git a/packages/frontend/src/lib/utils.ts b/packages/frontend/src/lib/utils.ts
index bd0c391..fed2fe9 100644
--- a/packages/frontend/src/lib/utils.ts
+++ b/packages/frontend/src/lib/utils.ts
@@ -1,5 +1,5 @@
-import { clsx, type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
+import { clsx, type ClassValue } from 'clsx'
+import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts
index d36c010..be139b4 100644
--- a/packages/frontend/vite.config.ts
+++ b/packages/frontend/vite.config.ts
@@ -1,12 +1,12 @@
-import path from "path"
-import react from "@vitejs/plugin-react"
-import { defineConfig } from "vite"
-
+import path from 'path'
+import react from '@vitejs/plugin-react'
+import { defineConfig } from 'vite'
+
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
- "@": path.resolve(__dirname, "./src"),
+ '@': path.resolve(__dirname, './src'),
},
},
-})
\ No newline at end of file
+})
|