From 39d889f029a45fb06b9a26712c451f415eb9f777 Mon Sep 17 00:00:00 2001 From: RedBeardEth <90423049+RedBeardEth@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:25:22 +1100 Subject: [PATCH] fix keystatic --- apps/nextjs/env.ts | 1 + .../assets/PortfolioItemsFiltersPanel.tsx | 1 - apps/nextjs/src/app/(app)/bridge/page.tsx | 6 +- apps/nextjs/src/app/(app)/page.tsx | 2 - .../src/app/(app)/staking/RealmsTable.tsx | 399 -------------- .../app/(app)/staking/StakingContainer.tsx | 499 ------------------ apps/nextjs/src/app/(app)/staking/page.tsx | 45 -- 7 files changed, 4 insertions(+), 949 deletions(-) delete mode 100644 apps/nextjs/src/app/(app)/staking/RealmsTable.tsx delete mode 100644 apps/nextjs/src/app/(app)/staking/StakingContainer.tsx delete mode 100644 apps/nextjs/src/app/(app)/staking/page.tsx diff --git a/apps/nextjs/env.ts b/apps/nextjs/env.ts index 4cd6ab3e..f37134df 100644 --- a/apps/nextjs/env.ts +++ b/apps/nextjs/env.ts @@ -44,6 +44,7 @@ export const env = createEnv({ NEXT_PUBLIC_ALCHEMY_API: z.string(), NEXT_PUBLIC_ETHPLORER_APIKEY: z.string(), // NEXT_PUBLIC_CLIENTVAR: z.string(), + NEXT_PUBLIC_GITHUB_REPO_NAME: z.string().optional(), NEXT_PUBLIC_GITHUB_REPO_OWNER: z.string().optional(), NEXT_PUBLIC_ARK_MARKETPLACE_API: z.string().url(), NEXT_PUBLIC_ARK_ORDERBOOK_API: z.string().url(), diff --git a/apps/nextjs/src/app/(app)/account/assets/PortfolioItemsFiltersPanel.tsx b/apps/nextjs/src/app/(app)/account/assets/PortfolioItemsFiltersPanel.tsx index 030303fd..abbe470f 100644 --- a/apps/nextjs/src/app/(app)/account/assets/PortfolioItemsFiltersPanel.tsx +++ b/apps/nextjs/src/app/(app)/account/assets/PortfolioItemsFiltersPanel.tsx @@ -28,7 +28,6 @@ export default function PortfolioItemsFitlersPanel({ diff --git a/apps/nextjs/src/app/(app)/bridge/page.tsx b/apps/nextjs/src/app/(app)/bridge/page.tsx index 39b1c8a2..3983d94b 100644 --- a/apps/nextjs/src/app/(app)/bridge/page.tsx +++ b/apps/nextjs/src/app/(app)/bridge/page.tsx @@ -29,15 +29,15 @@ export default function Page({ return (

The Lords Bridge

-
+
{tabs.map((tab) => ( (a: T, b: T, orderBy: keyof T) { - if (b[orderBy] < a[orderBy]) { - return -1; - } - if (b[orderBy] > a[orderBy]) { - return 1; - } - return 0; -} - -type Order = "asc" | "desc"; - -function getComparator>( - order: Order, - orderBy: Key, -): (a: Pick, b: Pick) => number { - return order === "desc" - ? (a, b) => descendingComparator(a, b, orderBy) - : (a, b) => -descendingComparator(a, b, orderBy); -} - -interface HeadCell { - disablePadding: boolean; - id: keyof Pick; - label: string; - numeric: boolean; -} - -const headCells: readonly HeadCell[] = [ - { - id: "id", - numeric: true, - disablePadding: true, - label: "Realm ID", - }, - { - id: "name", - numeric: false, - disablePadding: false, - label: "Name", - }, -]; - -interface EnhancedTableProps { - numSelected: number; - onRequestSort: ( - event: React.MouseEvent, - property: keyof Pick, - ) => void; - onSelectAllClick: (event: React.ChangeEvent) => void; - order: Order; - orderBy: keyof Pick; - rowCount: number; -} - -function EnhancedTableHead(props: EnhancedTableProps) { - const { - onSelectAllClick, - order, - orderBy, - numSelected, - rowCount, - onRequestSort, - } = props; - const createSortHandler = - (property: keyof Pick) => - (event: React.MouseEvent) => { - onRequestSort(event, property); - }; - - return ( - - - - 0 && numSelected < rowCount} - checked={rowCount > 0 && numSelected === rowCount} - onChange={onSelectAllClick} - inputProps={{ - "aria-label": "select all realms", - }} - /> - - {headCells.map((headCell, index) => ( - - - {headCell.label} - {orderBy === headCell.id ? ( - - {order === "desc" ? "sorted descending" : "sorted ascending"} - - ) : null} - - - ))} - - - ); -} - -interface EnhancedTableToolbarProps { - numSelected: number; -} - -function EnhancedTableToolbar(props: EnhancedTableToolbarProps) { - const { numSelected } = props; - - return ( - 0 && { - bgcolor: (theme) => - alpha( - theme.palette.primary.main, - theme.palette.action.activatedOpacity, - ), - }), - }} - > - {numSelected > 0 ? ( - - {numSelected} selected - - ) : ( -
- )} - {numSelected > 0 ? ( - - setSelected([])}*/> - - - - ) : ( - - - - - - )} -
- ); -} - -export default function RealmsTable({ - realms, - selectedRealms, - onSelectRealms, -}: { - realms: Pick[]; - selectedRealms: readonly string[]; - onSelectRealms: (realms: readonly string[]) => void; -}) { - const [order, setOrder] = React.useState("asc"); - const [orderBy, setOrderBy] = - React.useState>("id"); - const [page, setPage] = React.useState(0); - const [dense, setDense] = React.useState(false); - const [rowsPerPage, setRowsPerPage] = React.useState(20); - - const rows: Pick[] = realms; - - const handleRequestSort = ( - event: React.MouseEvent, - property: keyof Pick, - ) => { - const isAsc = orderBy === property && order === "asc"; - setOrder(isAsc ? "desc" : "asc"); - setOrderBy(property); - }; - - const handleSelectAllClick = (event: React.ChangeEvent) => { - if (event.target.checked) { - const newSelected = rows.map((n) => n.id); - onSelectRealms(newSelected); - return; - } - onSelectRealms([]); - }; - - const handleClick = (event: React.MouseEvent, name: string) => { - const selectedIndex = selectedRealms.indexOf(name); - let newSelected: readonly string[] = []; - - if (selectedIndex === -1) { - newSelected = newSelected.concat(selectedRealms, name); - } else if (selectedIndex === 0) { - newSelected = newSelected.concat(selectedRealms.slice(1)); - } else if (selectedIndex === selectedRealms.length - 1) { - newSelected = newSelected.concat(selectedRealms.slice(0, -1)); - } else if (selectedIndex > 0) { - newSelected = newSelected.concat( - selectedRealms.slice(0, selectedIndex), - selectedRealms.slice(selectedIndex + 1), - ); - } - - onSelectRealms(newSelected); - }; - - const handleChangePage = (event: unknown, newPage: number) => { - setPage(newPage); - }; - - const handleChangeRowsPerPage = ( - event: React.ChangeEvent, - ) => { - setRowsPerPage(parseInt(event.target.value, 10)); - setPage(0); - }; - - const handleChangeDense = (event: boolean) => { - setDense(event); - }; - - const isSelected = (name: string) => selectedRealms.indexOf(name) !== -1; - - // Avoid a layout jump when reaching the last page with empty rows. - const emptyRows = - page > 0 ? Math.max(0, (1 + page) * rowsPerPage - rows.length) : 0; - - const visibleRows = React.useMemo( - () => - rows - .sort(getComparator(order, orderBy)) - .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage), - [order, orderBy, page, rowsPerPage, rows], - ); - - return ( - - - - - - - {visibleRows.map((row, index) => { - const isItemSelected = isSelected(row.id); - const labelId = `enhanced-table-checkbox-${index}`; - - return ( - handleClick(event, row.id)} - role="checkbox" - aria-checked={isItemSelected} - tabIndex={-1} - key={row.name} - selected={isItemSelected} - sx={{ - cursor: "pointer", - "&:hover": { - backgroundColor: `rgba(158,158,158, 0.4) !important`, - }, - "&.Mui-selected": { - backgroundColor: `rgba(158,158,158, 0.25) !important`, - "&:hover": { - backgroundColor: `rgba(158,158,158, 0.4) !important`, - }, - }, - }} - > - - - - - {row.id} - - - {row.name} - - - ); - })} - {emptyRows > 0 && ( - - - - )} - -
-
-
- handleChangeDense(event)} - className="mr-2 w-[39px]" - /> - } - label="Dense view" - /> - -
-
- ); -} diff --git a/apps/nextjs/src/app/(app)/staking/StakingContainer.tsx b/apps/nextjs/src/app/(app)/staking/StakingContainer.tsx deleted file mode 100644 index c6caa0d3..00000000 --- a/apps/nextjs/src/app/(app)/staking/StakingContainer.tsx +++ /dev/null @@ -1,499 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -"use client"; - -import type { Realm } from "@/types/subgraph"; -import { useEffect, useState } from "react"; -import { ERC721 } from "@/abi/L1/ERC721"; -import { paymentPoolAbi } from "@/abi/L1/PaymentPool"; -import { GalleonStaking } from "@/abi/L1/v1GalleonStaking"; -import { CarrackStaking } from "@/abi/L1/v2CarrackStaking"; -import { NETWORK_NAME, SUPPORTED_L1_CHAIN_ID } from "@/constants/env"; -import { stakingAddresses } from "@/constants/staking"; -import Lords from "@/icons/lords.svg"; -import { useQuery } from "@tanstack/react-query"; -import { Loader, Loader2 } from "lucide-react"; -import { formatEther, parseEther } from "viem"; -import { - useAccount, - useReadContract, - useWaitForTransactionReceipt, - useWriteContract, -} from "wagmi"; - -import { Collections, getCollectionAddresses } from "@realms-world/constants"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTrigger, -} from "@realms-world/ui/components/ui/dialog"; -import { Button } from "@realms-world/ui/components/ui/button"; -import { Alert } from "@realms-world/ui/components/ui/alert"; -import { PaymentPoolV2 } from "../../_components/staking/PaymentPoolV2"; -import { EthereumLoginButton } from "../../_components/wallet/EthereumLoginButton"; -import RealmsTable from "./RealmsTable"; - -const galleonAddress = stakingAddresses[NETWORK_NAME] - .v1Galleon as `0x${string}`; -const carrackAddress = stakingAddresses[NETWORK_NAME] - .v2Carrack as `0x${string}`; -const realmsAddress = getCollectionAddresses(Collections.REALMS)?.[ - SUPPORTED_L1_CHAIN_ID -]; - -export const StakingContainer = () => { - const { address: addressL1, isConnected } = useAccount(); - const [hexProof, setHexProof] = useState<`0x${string}` | undefined>(); - const [poolTotal, setPoolTotal] = useState(); - const address = addressL1 ? addressL1.toLowerCase() : "0x"; - - const { data: realmsData, isLoading: realmsDataIsLoading } = useQuery({ - queryKey: ["UsersRealms" + address], - queryFn: async () => - await fetch(`/api/subgraph/getRealms?address=${address}`, { - method: "POST", - }) - .then((res) => res.json()) - .then((res) => { - return res.data; - }), - enabled: !!addressL1, - refetchInterval: 10000, - }); - - const { data: lordsAvailableData, isLoading: isGalleonLordsLoading } = - useReadContract({ - address: stakingAddresses[NETWORK_NAME].v1Galleon as `0x${string}`, - abi: GalleonStaking, - functionName: "lordsAvailable", - args: [address as `0x${string}`], - }); - - const { isPending: isGalleonClaimLoading, writeContract: claimGalleonLords } = - useWriteContract(); - - const { data: carrackLordsAvailableData, isLoading: isCarrackLordsLoading } = - useReadContract({ - address: stakingAddresses[NETWORK_NAME].v2Carrack as `0x${string}`, - abi: CarrackStaking, - functionName: "lordsAvailable", - args: [address as `0x${string}`], - }); - - const { isPending: isCarrackClaimLoading, writeContract: claimCarrackLords } = - useWriteContract(); - - const { - isPending: isPoolClaimLoading, - writeContract: claimPoolLords, - error: poolClaimError, - } = useWriteContract(); - - const { data: poolBalanceData, isLoading: poolBalanceLoading } = - useReadContract({ - address: stakingAddresses[NETWORK_NAME].paymentPool as `0x${string}`, - abi: paymentPoolAbi, - functionName: "balanceForProofWithAddress", - args: hexProof && - addressL1 && [addressL1.toLowerCase() as `0x${string}`, hexProof], - // query: { enabled: !!address && !!poolTotal } - }); - useEffect(() => { - const fetchStakingData = async () => { - if (addressL1) { - try { - const response = await fetch(`/api/staking/${addressL1}`); - const data: { proof: `0x${string}`; amount: number } = - await response.json(); - setHexProof(data.proof); - if (data.amount) { - setPoolTotal(parseEther(data.amount.toString())); - } else { - setPoolTotal(0n); - } - } catch (error) { - console.error("Error fetching staking data:", error); - } - } - }; - - // eslint-disable-next-line @typescript-eslint/no-floating-promises - fetchStakingData(); - }, [addressL1]); - - if (isConnected && addressL1) { - return ( -
- {poolClaimError && ( - {poolClaimError.message.toString()} - )} -
-

Your Realms

-
- {realmsDataIsLoading ? ( - "Loading" - ) : ( - <> - - {realmsData?.wallet?.realmsHeld ?? 0} - - Realms Available - - - )} -
-
-

Epoch 35-109 Rewards

- -

Galleon

-
- - Rewards: 49x $LORDS per epoch - -
- - Redemption: Claimable after each fully staked epoch (1 week) - -
-
-
- {realmsDataIsLoading ? ( - "Loading" - ) : ( - <> - - {realmsData?.wallet?.bridgedRealmsHeld ?? 0} - - Realms Staked - - - )} -
-
- Lords Available - - {!isGalleonLordsLoading && typeof lordsAvailableData == "bigint" ? ( -
- Epoch 1-10: - - - {formatEther(lordsAvailableData)} - - -
- ) : ( - "Loading" - )} - -
- Epoch 11-35: - - - {poolBalanceLoading ? ( - - ) : poolBalanceData != undefined && poolTotal ? ( - <> - {formatEther(poolBalanceData).toLocaleString()} /{" "} - {formatEther(poolTotal).toLocaleString()} - - ) : ( - 0 - )} - - {poolBalanceData != undefined && hexProof && ( - - )} -
-
-
- {realmsData?.bridgedV2Realms.length ?? - (carrackLordsAvailableData && carrackLordsAvailableData[0] > 0n) ? ( -
-

Carrack

-
- - Rewards: 49x $LORDS per epoch - -
-
- -
-
-
- {realmsDataIsLoading ? ( - "Loading" - ) : ( - <> - - {realmsData?.wallet?.bridgedV2RealmsHeld ?? 0} - - Staked Realms: - - - )} -
-
- Lords Available - - {isCarrackLordsLoading ? ( - "Loading" - ) : ( - <> - - - {formatEther(carrackLordsAvailableData?.[0] ?? 0n)} - - Epoch 35+ - - - - )} -
-
-
-
- ) : null} -
- ); - } - return ( -
-

Realms (NFT) Staking for $LORDS rewards

-

Login to your Ethereum Wallet

- -
- ); -}; - -const StakingModal = ({ - realms, - unstake, - type, -}: { - realms?: Pick[]; - unstake?: boolean; - type?: "galleon" | "carrack"; -}) => { - const [shipType, setShipType] = useState<"galleon" | "carrack">(); - const [selectedRealms, setSelectedRealms] = useState([]); - const { address } = useAccount(); - - const { writeContractAsync: boardGalleon, isPending: isBoardGalleonPending } = - useWriteContract(); - const { writeContractAsync: exitGalleon, isPending: isExitGalleonPending } = - useWriteContract(); - const { writeContractAsync: exitCarrack, isPending: isExitCarrackPending } = - useWriteContract(); - const { - writeContractAsync: approveGalleon, - isPending: isGalleonApproveLoading, - data: approveGalleonData, - } = useWriteContract(); - const { data: isGalleonApprovedData, refetch: refetchGalleonApprovedData } = - useReadContract({ - address: realmsAddress as `0x${string}`, - abi: ERC721, - functionName: "isApprovedForAll", - args: address && [address, galleonAddress], - }); - - const { isSuccess } = useWaitForTransactionReceipt({ - hash: approveGalleonData, - }); - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - refetchGalleonApprovedData(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isSuccess]); - - const isApproved = isGalleonApprovedData; - - const onApproveClick = async () => { - if (!isApproved) { - await approveGalleon({ - address: realmsAddress as `0x${string}`, - abi: ERC721, - functionName: "setApprovalForAll", - args: [galleonAddress, true], - }); - } - }; - const onButtonClick = async () => { - if (!unstake) { - await boardGalleon({ - address: galleonAddress, - abi: GalleonStaking, - functionName: "boardShip", - args: [selectedRealms.map(BigInt)], - }); - } else { - const exitFunction = - shipType === "galleon" - ? exitGalleon({ - address: galleonAddress, - abi: GalleonStaking, - functionName: "exitShip", - args: [selectedRealms.map(BigInt)], - }) - : exitCarrack({ - address: carrackAddress, - abi: CarrackStaking, - functionName: "exitShip", - args: [selectedRealms.map(BigInt)], - }); - await exitFunction; - } - setSelectedRealms([]); - }; - const isPending = - isGalleonApproveLoading || - isExitGalleonPending || - isExitCarrackPending || - isBoardGalleonPending; - - const onSelectRealms = (realms: readonly string[]) => { - setSelectedRealms(realms); - }; - useEffect(() => { - if (type) { - setShipType(type); - } - }, [type]); - return ( - - - - - - -
- {unstake ? "Exit" : "Board"} the{" "} - {shipType ?? "Ship"} -
-
- {shipType && realms ? ( - <> -
- -
- {!unstake && !isApproved ? ( - - ) : ( - - )} - - ) : ( -
-
The Galleon
-
Rewards: 49x $LORDS per epoch.
- - Lords earnt after epoch 35 are locked until the DAO approves the - migration to Starknet. - - -
- )} -
-
- ); -}; diff --git a/apps/nextjs/src/app/(app)/staking/page.tsx b/apps/nextjs/src/app/(app)/staking/page.tsx deleted file mode 100644 index 3e941dd4..00000000 --- a/apps/nextjs/src/app/(app)/staking/page.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-call */ - -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -import type { Metadata } from "next"; -import { NETWORK_NAME } from "@/constants/env"; -import { stakingAddresses } from "@/constants/staking"; -import { getWalletRealmsHeld } from "@/lib/subgraph/getWalletRealmsHeld"; - -import { StakingContainer } from "./StakingContainer"; - -export const metadata: Metadata = { - title: "Realm NFT Staking for $LORDS rewards", -}; -const galleonAddress = stakingAddresses[NETWORK_NAME].v1Galleon; -const carrackAddress = stakingAddresses[NETWORK_NAME].v2Carrack; - -export default async function Page() { - const totalStakedRealmsData = await getWalletRealmsHeld({ - addresses: [galleonAddress, carrackAddress], - }); - const totalStakedRealms = totalStakedRealmsData?.wallets?.reduce( - (total: number, wallet: { realmsHeld: string }) => { - return total + parseInt(wallet.realmsHeld, 10); - }, - 0, - ); - return ( -
- -
-

Data

-
- {/*

Current Epoch:

*/} -

Total Realms Staked: {totalStakedRealms}

-

- Galleon: {totalStakedRealmsData?.wallets[0]?.realmsHeld} / Carrack:{" "} - {totalStakedRealmsData?.wallets[1]?.realmsHeld} -

-
-
- {/*

Lords to be claimed on Starknet:

*/} -
- ); -}