From 66554e0b1893d0029ab8118105e10d41ce4a80c1 Mon Sep 17 00:00:00 2001 From: tre Date: Tue, 5 Nov 2024 10:50:13 -0800 Subject: [PATCH] feat(ci): add ci checks (#38) --- .github/actions/setup/action.yaml | 18 +++ .github/actions/supersim/action.yaml | 8 ++ .github/workflows/main.yaml | 81 +++++++++++ package.json | 5 +- packages/e2e-test/package.json | 4 +- packages/e2e-test/src/envVars.ts | 4 +- packages/frontend/.gitignore | 2 + packages/frontend/package.json | 6 +- packages/frontend/src/App.tsx | 50 +++---- packages/frontend/src/Bridge.tsx | 94 +++++++++---- packages/frontend/src/Faucet.tsx | 129 ++++++++++++------ packages/frontend/src/Providers.tsx | 22 ++- packages/frontend/src/TokenSupply.tsx | 52 ++++--- .../src/components/RecentActivity.tsx | 32 ++--- .../src/components/TokenAggregateSupply.tsx | 60 ++++---- .../frontend/src/components/TokenInfo.tsx | 54 +++----- .../frontend/src/components/WalletBalance.tsx | 81 ++++++----- .../connect-wallet/ConnectWalletButton.tsx | 47 ++++--- packages/frontend/src/components/ui/alert.tsx | 26 ++-- .../src/components/ui/badge-variants.tsx | 21 +++ packages/frontend/src/components/ui/badge.tsx | 29 +--- .../src/components/ui/button-variants.tsx | 31 +++++ .../frontend/src/components/ui/button.tsx | 48 ++----- packages/frontend/src/components/ui/card.tsx | 30 ++-- .../frontend/src/components/ui/checkbox.tsx | 14 +- .../frontend/src/components/ui/dialog.tsx | 34 ++--- .../src/components/ui/dropdown-menu.tsx | 50 +++---- packages/frontend/src/components/ui/input.tsx | 40 +++--- packages/frontend/src/components/ui/label.tsx | 10 +- .../frontend/src/components/ui/progress.tsx | 10 +- .../src/components/ui/scroll-area.tsx | 24 ++-- .../frontend/src/components/ui/select.tsx | 44 +++--- .../frontend/src/components/ui/separator.tsx | 18 +-- packages/frontend/src/components/ui/table.tsx | 44 +++--- packages/frontend/src/components/ui/tabs.tsx | 20 +-- packages/frontend/src/components/ui/toast.tsx | 36 ++--- .../frontend/src/components/ui/toaster.tsx | 4 +- .../frontend/src/components/ui/tooltip.tsx | 10 +- .../frontend/src/connectors/devAccount.ts | 16 ++- packages/frontend/src/hooks/use-toast.ts | 59 ++++---- packages/frontend/src/hooks/useIndexer.ts | 2 +- packages/frontend/src/hooks/useTokenInfo.ts | 34 +++++ packages/frontend/src/lib/utils.ts | 4 +- packages/frontend/vite.config.ts | 12 +- 44 files changed, 830 insertions(+), 589 deletions(-) create mode 100644 .github/actions/setup/action.yaml create mode 100644 .github/actions/supersim/action.yaml create mode 100644 .github/workflows/main.yaml create mode 100644 packages/frontend/src/components/ui/badge-variants.tsx create mode 100644 packages/frontend/src/components/ui/button-variants.tsx create mode 100644 packages/frontend/src/hooks/useTokenInfo.ts 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..82a9b9b --- /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 & + pnpm deploy:contracts:ci + pnpm e2e-test:ci diff --git a/package.json b/package.json index d2a9e37..369d963 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 && cd packages/contracts && forge install && forge script 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..b0f2745 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("0xe20d8C366AE0716ca88384feCbcbf8179581157D"), + 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 ( -

SuperchainERC20 Dev Tools

- +
@@ -58,7 +57,7 @@ function App() {
- + Faucet @@ -68,7 +67,7 @@ function App() {
- +
@@ -78,16 +77,19 @@ function App() { {/* Add Contract Deployment interface */} -
Contract deployment interface coming soon...
+
+ Contract deployment interface coming soon... +
{/* Add Contract Verification interface */} -
Contract verification interface coming soon...
+
+ Contract verification interface coming soon... +
-
@@ -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)} />
- +
- @@ -99,10 +133,10 @@ export const Bridge = () => {
- +
- - ) - } -) -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 +})