From ef9f0ac2e4fcef3eda88797dea00ae6def30be71 Mon Sep 17 00:00:00 2001 From: sheykei Date: Thu, 5 Dec 2024 17:51:41 +0100 Subject: [PATCH 01/34] fix: some type errors --- merkl.config.ts | 58 ++++++++++++++-------------- package.json | 4 +- packages/dappkit | 2 +- src/api/services/campaign.service.ts | 6 +-- src/components/element/Tag.tsx | 9 +++-- vite.config.ts | 8 ++-- 6 files changed, 43 insertions(+), 44 deletions(-) diff --git a/merkl.config.ts b/merkl.config.ts index a58c552a..0048cec1 100644 --- a/merkl.config.ts +++ b/merkl.config.ts @@ -1,43 +1,43 @@ import { createColoring } from "dappkit"; import { createConfig } from "src/config/type"; -import { createClient, custom, http } from "viem"; +import hero from "src/customer/assets/images/hero.jpg?url"; +import { http, createClient, custom } from "viem"; import { - mainnet, - optimism, - rootstock, - bsc, - gnosis, - thunderCore, - fuse, - polygon, - manta, - xLayer, - fantom, - fraxtal, - filecoin, - zksync, - worldchain, + arbitrum, astar, - polygonZkEvm, - coreDao, - moonbeam, - sei, astarZkEVM, - mantle, + avalanche, base, + blast, + bob, + bsc, + coreDao, + fantom, + filecoin, + fraxtal, + fuse, + gnosis, immutableZkEvm, - mode, - arbitrum, - avalanche, linea, - bob, - blast, - taiko, + mainnet, + manta, + mantle, + mode, + moonbeam, + optimism, + polygon, + polygonZkEvm, + rootstock, scroll, + sei, + taiko, + thunderCore, + worldchain, + xLayer, + zksync, } from "viem/chains"; -import { coinbaseWallet, walletConnect } from "wagmi/connectors"; -import hero from "src/customer/assets/images/hero.jpg?url"; import { eip712WalletActions } from "viem/zksync"; +import { coinbaseWallet, walletConnect } from "wagmi/connectors"; export default createConfig({ appName: "Merkl", diff --git a/package.json b/package.json index dd25aa41..ad139c4a 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "start": "bun run scripts/start.ts", "build": "remix vite:build", "dev": "remix vite:dev --host", - "lint": "biome check --fix ./src", - "lint:ci": "biome check --diagnostic-level error ./src", + "lint": "biome check --fix ./src ./*.ts", + "lint:ci": "biome check --diagnostic-level error ./src ./*.ts", "serve": "remix-serve ./build/server/index.js", "typecheck": "tsc" }, diff --git a/packages/dappkit b/packages/dappkit index 8679ff3d..c22e874c 160000 --- a/packages/dappkit +++ b/packages/dappkit @@ -1 +1 @@ -Subproject commit 8679ff3d88f5882944c364467b6dbda0705bb56a +Subproject commit c22e874cf4876b51e8ee58121bb8ab6469c48de6 diff --git a/src/api/services/campaign.service.ts b/src/api/services/campaign.service.ts index 00604e36..be1fe136 100644 --- a/src/api/services/campaign.service.ts +++ b/src/api/services/campaign.service.ts @@ -1,4 +1,4 @@ -import type { Campaign } from "@angleprotocol/merkl-api"; +import type { Campaign } from "@merkl/api"; import { api } from "../index.server"; export abstract class CampaignService { @@ -36,13 +36,13 @@ export abstract class CampaignService { } // ------ Fetch all campaigns - static async get(): Promise { + static async get() { const { data } = await api.v4.campaigns.index.get({ query: {} }); return data; } - static async getByParams(query: Parameters[0]["query"]): Promise { + static async getByParams(query: Parameters[0]["query"]) { const { data } = await api.v4.campaigns.index.get({ query }); return data; } diff --git a/src/components/element/Tag.tsx b/src/components/element/Tag.tsx index 6dccedff..ce647f6d 100644 --- a/src/components/element/Tag.tsx +++ b/src/components/element/Tag.tsx @@ -1,7 +1,7 @@ import type { Opportunity, Token } from "@merkl/api"; import type { Chain } from "@merkl/api"; import { Button, Divider, Dropdown, Group, Hash, Icon, PrimitiveTag, Text } from "dappkit"; -import type { ButtonProps } from "dappkit"; +import type { Component, PrimitiveTagProps } from "dappkit"; import { useWalletContext } from "packages/dappkit/src/context/Wallet.context"; import { type Action, actions } from "src/config/actions"; import type { Protocol } from "src/config/protocols"; @@ -20,12 +20,13 @@ export type TagType = { type: T; value: TagTypes[T]; }; -export type TagProps = ButtonProps & { +export type TagProps = { type: T; value: TagTypes[T]; + size?: PrimitiveTagProps["size"]; }; -export default function Tag({ type, value, ...props }: TagProps) { +export default function Tag({ type, value, ...props }: Component>) { const { chains } = useWalletContext(); switch (type) { @@ -55,7 +56,7 @@ export default function Tag({ type, value, ...props }: }> - + {status?.label} diff --git a/vite.config.ts b/vite.config.ts index d9e4450e..06d7190c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,10 @@ +import { ecsstatic } from "@acab/ecsstatic/vite"; import { vitePlugin as remix } from "@remix-run/dev"; +import svgr from "@svgr/rollup"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; -import { ecsstatic } from '@acab/ecsstatic/vite'; -import svgr from "@svgr/rollup"; export default defineConfig({ - plugins: [ svgr(), remix({ @@ -15,9 +14,8 @@ export default defineConfig({ v3_relativeSplatPath: true, v3_throwAbortReason: true, }, - }), tsconfigPaths(), - ecsstatic() + ecsstatic(), ], }); From 69eccd9d8264379cb1b25c655e74458108a5e645 Mon Sep 17 00:00:00 2001 From: sheykei Date: Fri, 6 Dec 2024 11:22:42 +0100 Subject: [PATCH 02/34] add: services model draft --- bun.lockb | Bin 827766 -> 829328 bytes package.json | 2 +- packages/dappkit | 2 +- src/api/services/campaigns/campaign.model.ts | 4 ++++ .../{ => campaigns}/campaign.service.ts | 0 .../services/opportunity/opportunity.model.ts | 6 ++++++ .../{ => opportunity}/opportunity.service.ts | 4 ++-- src/api/types.ts | 7 +++++++ src/components/composite/Hero.tsx | 2 +- src/components/element/Tag.tsx | 10 +++++----- .../element/campaign/CampaignLibrary.tsx | 4 ++-- .../element/campaign/CampaignTableRow.tsx | 2 +- .../opportunity/OpportunityLibrary.tsx | 5 +++-- .../opportunity/OpportunityTableRow.tsx | 2 +- .../element/protocol/ProtocolTableRow.tsx | 2 +- .../rewards/ClaimRewardsChainTableRow.tsx | 4 ++-- .../rewards/ClaimRewardsTokenTablePrice.tsx | 4 ++-- .../rewards/ClaimRewardsTokenTableRow.tsx | 9 ++++----- src/config/actions.ts | 5 +++++ src/config/type.ts | 3 --- src/hooks/resources/useCampaign.tsx | 3 ++- src/hooks/resources/useOpportunity.tsx | 4 ++-- src/routes/_merkl.(home).(opportunities).tsx | 2 +- ..._merkl.actions.$action.(opportunities).tsx | 2 +- .../_merkl.chains.$id.(opportunities).tsx | 2 +- src/routes/_merkl.chains.$id.tsx | 15 +-------------- ...rtunities.$chain.$type.$id.leaderboard.tsx | 2 +- .../_merkl.opportunities.$chain.$type.$id.tsx | 17 +++++++++++++---- .../_merkl.protocols.$id.(opportunities).tsx | 2 +- .../_merkl.status.$status.(opportunities).tsx | 2 +- .../_merkl.tokens.$symbol.(opportunities).tsx | 8 ++++++-- 31 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 src/api/services/campaigns/campaign.model.ts rename src/api/services/{ => campaigns}/campaign.service.ts (100%) create mode 100644 src/api/services/opportunity/opportunity.model.ts rename src/api/services/{ => opportunity}/opportunity.service.ts (97%) diff --git a/bun.lockb b/bun.lockb index c62d379d3f296f956cdb6e7eff47e35ddafb932b..d4617d1f5b857f754cbd7e844bc87a93dcba21fe 100755 GIT binary patch delta 29950 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 delta 30936 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 kdkf`kbHf@|J+1J|oW&-mg(v6oFHg^k = Fetched>; \ No newline at end of file diff --git a/src/api/services/campaign.service.ts b/src/api/services/campaigns/campaign.service.ts similarity index 100% rename from src/api/services/campaign.service.ts rename to src/api/services/campaigns/campaign.service.ts diff --git a/src/api/services/opportunity/opportunity.model.ts b/src/api/services/opportunity/opportunity.model.ts new file mode 100644 index 00000000..ac43f277 --- /dev/null +++ b/src/api/services/opportunity/opportunity.model.ts @@ -0,0 +1,6 @@ +import type { Opportunity as OpportunityFromApi } from "@merkl/api"; +import type { Fetched } from "src/api/types"; +import type { Campaign } from "../campaigns/campaign.model"; + +export type Opportunity = Fetched; +export type OpportunityWithCampaigns = Fetched; \ No newline at end of file diff --git a/src/api/services/opportunity.service.ts b/src/api/services/opportunity/opportunity.service.ts similarity index 97% rename from src/api/services/opportunity.service.ts rename to src/api/services/opportunity/opportunity.service.ts index 974f5623..813a6eed 100644 --- a/src/api/services/opportunity.service.ts +++ b/src/api/services/opportunity/opportunity.service.ts @@ -1,7 +1,7 @@ import type { Opportunity } from "@merkl/api"; import config from "merkl.config"; -import { api } from "../index.server"; -import { fetchWithLogs } from "../utils"; +import { api } from "../../index.server"; +import { fetchWithLogs } from "../../utils"; export abstract class OpportunityService { static async #fetch( diff --git a/src/api/types.ts b/src/api/types.ts index 6b369f0a..cd455fca 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -1,3 +1,10 @@ import type { MerklApi } from "@merkl/api"; +import type { SerializeFrom, TypedResponse } from "@remix-run/node"; export type Api = ReturnType; + +/** + * Type returned through a loader + * @description helps with inconsistencies of the implicit type when returned through the remix json() loader + */ +export type Fetched = SerializeFrom<() => TypedResponse> \ No newline at end of file diff --git a/src/components/composite/Hero.tsx b/src/components/composite/Hero.tsx index d3d89753..c634c208 100644 --- a/src/components/composite/Hero.tsx +++ b/src/components/composite/Hero.tsx @@ -1,9 +1,9 @@ -import type { Opportunity } from "@merkl/api"; import { useLocation } from "@remix-run/react"; import { Box, Container, Divider, Group, Icon, type IconProps, Icons, Text, Title } from "dappkit"; import { Button } from "dappkit"; import config from "merkl.config"; import type { PropsWithChildren, ReactNode } from "react"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; export type HeroProps = PropsWithChildren<{ icons?: IconProps[]; diff --git a/src/components/element/Tag.tsx b/src/components/element/Tag.tsx index ce647f6d..8a7d07d1 100644 --- a/src/components/element/Tag.tsx +++ b/src/components/element/Tag.tsx @@ -1,18 +1,18 @@ -import type { Opportunity, Token } from "@merkl/api"; +import type { Token } from "@merkl/api"; import type { Chain } from "@merkl/api"; import { Button, Divider, Dropdown, Group, Hash, Icon, PrimitiveTag, Text } from "dappkit"; import type { Component, PrimitiveTagProps } from "dappkit"; import { useWalletContext } from "packages/dappkit/src/context/Wallet.context"; -import { type Action, actions } from "src/config/actions"; -import type { Protocol } from "src/config/protocols"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; +import { actions } from "src/config/actions"; import { statuses } from "src/config/status"; export type TagTypes = { chain: Opportunity["chain"]; token: Token; tokenChain: Token & { chain?: Chain }; - protocol: Protocol; - action: Action; + protocol: Opportunity["protocol"] | undefined; + action: Opportunity["action"]; status: Opportunity["status"]; }; diff --git a/src/components/element/campaign/CampaignLibrary.tsx b/src/components/element/campaign/CampaignLibrary.tsx index 66dffcd8..493d35f0 100644 --- a/src/components/element/campaign/CampaignLibrary.tsx +++ b/src/components/element/campaign/CampaignLibrary.tsx @@ -1,12 +1,12 @@ -import type { Opportunity } from "@merkl/api"; import { Button, Group, Icon, Text } from "dappkit"; import moment from "moment"; import { useMemo, useState } from "react"; import { CampaignTable } from "./CampaignTable"; import CampaignTableRow from "./CampaignTableRow"; +import type { OpportunityWithCampaigns } from "src/api/services/opportunity/opportunity.model"; export type IProps = { - opportunity: Opportunity; + opportunity: OpportunityWithCampaigns; }; export default function CampaignLibrary(props: IProps) { diff --git a/src/components/element/campaign/CampaignTableRow.tsx b/src/components/element/campaign/CampaignTableRow.tsx index 35cfc0c2..f9bc17b4 100644 --- a/src/components/element/campaign/CampaignTableRow.tsx +++ b/src/components/element/campaign/CampaignTableRow.tsx @@ -1,4 +1,3 @@ -import type { Campaign } from "@merkl/api"; import { type Component, Group, Hash, Icon, OverrideTheme, Text, Value, mergeClass } from "dappkit"; import moment from "moment"; import Tooltip from "packages/dappkit/src/components/primitives/Tooltip"; @@ -9,6 +8,7 @@ import Chain from "../chain/Chain"; import Token from "../token/Token"; import { CampaignRow } from "./CampaignTable"; import RestrictionsCollumn from "./tableCollumns/RestrictionsCollumn"; +import type { Campaign } from "src/api/services/campaigns/campaign.model"; export type CampaignTableRowProps = Component<{ campaign: Campaign; diff --git a/src/components/element/opportunity/OpportunityLibrary.tsx b/src/components/element/opportunity/OpportunityLibrary.tsx index 72eef6e6..329decfd 100644 --- a/src/components/element/opportunity/OpportunityLibrary.tsx +++ b/src/components/element/opportunity/OpportunityLibrary.tsx @@ -1,4 +1,4 @@ -import type { Chain, Opportunity } from "@merkl/api"; +import type { Chain } from "@merkl/api"; import { Group, type Order } from "dappkit"; import { useMemo } from "react"; import useSearchParamState from "src/hooks/filtering/useSearchParamState"; @@ -6,6 +6,7 @@ import OpportunityFilters, { type OpportunityFilterProps } from "./OpportunityFi import OpportunityPagination from "./OpportunityPagination"; import { OpportunityTable, type opportunityColumns } from "./OpportunityTable"; import OpportunityTableRow from "./OpportunityTableRow"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; export type OpportunityLibrary = { opportunities: Opportunity[]; @@ -22,7 +23,7 @@ export default function OpportunityLibrary({ opportunities, count, only, exclude [opportunities], ); - const sortable = ["apr", "tvl", "rewards"] as const satisfies typeof opportunityColumns; + const sortable = ["apy", "tvl", "rewards"] as const satisfies typeof opportunityColumns; const [sortIdAndOrder, setSortIdAndOrder] = useSearchParamState<[id: (typeof sortable)[number], order: Order]>( "sort", diff --git a/src/components/element/opportunity/OpportunityTableRow.tsx b/src/components/element/opportunity/OpportunityTableRow.tsx index 1b6960d0..4141b24d 100644 --- a/src/components/element/opportunity/OpportunityTableRow.tsx +++ b/src/components/element/opportunity/OpportunityTableRow.tsx @@ -1,4 +1,3 @@ -import type { Opportunity } from "@merkl/api"; import { Link } from "@remix-run/react"; import { Group } from "dappkit"; import { Icons } from "dappkit"; @@ -10,6 +9,7 @@ import { mergeClass } from "dappkit"; import useOpportunity from "src/hooks/resources/useOpportunity"; import Tag, { type TagTypes } from "../Tag"; import { OpportunityRow } from "./OpportunityTable"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; export type OpportunityTableRowProps = { hideTags?: (keyof TagTypes)[]; diff --git a/src/components/element/protocol/ProtocolTableRow.tsx b/src/components/element/protocol/ProtocolTableRow.tsx index 84560370..526f4e1f 100644 --- a/src/components/element/protocol/ProtocolTableRow.tsx +++ b/src/components/element/protocol/ProtocolTableRow.tsx @@ -12,7 +12,7 @@ export type ProtocolTableRowProps = { protocol: Protocol; } & BoxProps; -export default function ProtocolTableRow({ hideTags, protocol, className, ...props }: OpportunityTableRowProps) { +export default function ProtocolTableRow({ hideTags, protocol, className, ...props }: ProtocolTableRowProps) { return ( { return reward.rewards.reduce( (sum, { amount, claimed, token: { decimals, price } }) => - sum + Number.parseFloat(formatUnits(amount - claimed, decimals)) * price, + sum + Number.parseFloat(formatUnits(amount - claimed, decimals)) * (price ?? 0), 0, ); }, [reward]); const claimed = useMemo(() => { return reward.rewards.reduce( - (sum, { claimed, token: { decimals, price } }) => sum + Number.parseFloat(formatUnits(claimed, decimals)) * price, + (sum, { claimed, token: { decimals, price } }) => sum + Number.parseFloat(formatUnits(claimed, decimals)) * (price ?? 0), 0, ); }, [reward]); diff --git a/src/components/element/rewards/ClaimRewardsTokenTablePrice.tsx b/src/components/element/rewards/ClaimRewardsTokenTablePrice.tsx index 9a0e8fa3..a8af568f 100644 --- a/src/components/element/rewards/ClaimRewardsTokenTablePrice.tsx +++ b/src/components/element/rewards/ClaimRewardsTokenTablePrice.tsx @@ -3,7 +3,7 @@ import type { PropsWithChildren } from "react"; import { formatUnits } from "viem"; export type ClaimRewardsTokenTablePriceProps = PropsWithChildren & { - price: number; + price: number | null; amount: bigint; decimals: number; }; @@ -28,7 +28,7 @@ export default function ClaimRewardsTokenTablePrice({ amount, price, decimals }: className="text-right" look={"soft"} format="$0,0.#"> - {Number.parseFloat(value) * price} + {Number.parseFloat(value) * (price ?? 0)} ); diff --git a/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx b/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx index cf53310c..816f2ce1 100644 --- a/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx +++ b/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx @@ -1,16 +1,16 @@ import type { Reward } from "@merkl/api"; -import { Checkbox, Divider, type GetSet, Group, Icon, Space } from "dappkit"; +import { Checkbox, type Component, Divider, type GetSet, Group, Icon, Space } from "dappkit"; import Collapsible from "packages/dappkit/src/components/primitives/Collapsible"; -import { type PropsWithChildren, useMemo, useState } from "react"; +import { useMemo, useState } from "react"; import Tag from "../Tag"; import OpportuntiyButton from "../opportunity/OpportunityButton"; import { ClaimRewardsTokenRow } from "./ClaimRewardsTokenTable"; import ClaimRewardsTokenTablePrice from "./ClaimRewardsTokenTablePrice"; -export type ClaimRewardsTokenTableRowProps = PropsWithChildren & { +export type ClaimRewardsTokenTableRowProps = Component<{ reward: Reward["rewards"][number]; checkedState?: GetSet; -}; +}>; export default function ClaimRewardsTokenTableRow({ reward, checkedState, ...props }: ClaimRewardsTokenTableRowProps) { const [open, setOpen] = useState(false); @@ -19,7 +19,6 @@ export default function ClaimRewardsTokenTableRow({ reward, checkedState, ...pro return ( setOpen(o => !o)} tokenColumn={ diff --git a/src/config/actions.ts b/src/config/actions.ts index 9d4481c1..c09b46fc 100644 --- a/src/config/actions.ts +++ b/src/config/actions.ts @@ -2,6 +2,11 @@ import type { Opportunity } from "@merkl/api"; import type { IconProps } from "dappkit"; export const actions = { + INVALID: { + label: "Invalid", + description: "Invalid", + icon: { remix: "RiFileWarningLine" } + }, POOL: { label: "Provide Liquidity", description: "Earn rewards by depositiong liquidity in this pool.", diff --git a/src/config/type.ts b/src/config/type.ts index b3eb4056..ae4b3b4c 100644 --- a/src/config/type.ts +++ b/src/config/type.ts @@ -32,9 +32,6 @@ export type MerklConfig = { links: { [key: string]: string; }; - images: { - hero: string; - }; }; export function createConfig({ wagmi, ...config }: MerklConfig) { diff --git a/src/hooks/resources/useCampaign.tsx b/src/hooks/resources/useCampaign.tsx index dcae2f51..97e30241 100644 --- a/src/hooks/resources/useCampaign.tsx +++ b/src/hooks/resources/useCampaign.tsx @@ -1,9 +1,10 @@ -import type { Campaign, Opportunity } from "@merkl/api"; import { Bar } from "dappkit"; import moment from "moment"; import { Group, Text, Value } from "packages/dappkit/src"; import Time from "packages/dappkit/src/components/primitives/Time"; import { type ReactNode, useMemo } from "react"; +import type { Campaign } from "src/api/services/campaigns/campaign.model"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; import { formatUnits } from "viem"; export default function useCampaign(campaign: Campaign) { diff --git a/src/hooks/resources/useOpportunity.tsx b/src/hooks/resources/useOpportunity.tsx index ef6f311e..696d84a3 100644 --- a/src/hooks/resources/useOpportunity.tsx +++ b/src/hooks/resources/useOpportunity.tsx @@ -1,13 +1,13 @@ -import type { Opportunity } from "@merkl/api"; import { Icon } from "dappkit"; import { useMemo } from "react"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; import type { TagType } from "src/components/element/Tag"; export default function useOpportunity(opportunity: Opportunity) { const tags = useMemo(() => { const tokens: TagType<"token">[] = opportunity.tokens.map(t => ({ type: "token", value: t })); const action: TagType<"action"> = { type: "action", value: opportunity.action }; - const protocol: TagType<"protocol"> = opportunity?.protocol && { type: "protocol", value: opportunity?.protocol }; + const protocol: TagType<"protocol"> = { type: "protocol", value: opportunity.protocol }; const chain: TagType<"chain"> = { type: "chain", value: opportunity?.chain }; const status: TagType<"status"> = { type: "status", value: opportunity?.status }; diff --git a/src/routes/_merkl.(home).(opportunities).tsx b/src/routes/_merkl.(home).(opportunities).tsx index b641a275..ad71f9d8 100644 --- a/src/routes/_merkl.(home).(opportunities).tsx +++ b/src/routes/_merkl.(home).(opportunities).tsx @@ -2,7 +2,7 @@ import { type LoaderFunctionArgs, json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Container, Space } from "dappkit"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary"; import { ErrorContent } from "src/components/layout/ErrorContent"; diff --git a/src/routes/_merkl.actions.$action.(opportunities).tsx b/src/routes/_merkl.actions.$action.(opportunities).tsx index 853d999b..26ba4675 100644 --- a/src/routes/_merkl.actions.$action.(opportunities).tsx +++ b/src/routes/_merkl.actions.$action.(opportunities).tsx @@ -2,7 +2,7 @@ import { type LoaderFunctionArgs, json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Container, Space } from "dappkit"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary"; import { getAction } from "src/config/actions"; diff --git a/src/routes/_merkl.chains.$id.(opportunities).tsx b/src/routes/_merkl.chains.$id.(opportunities).tsx index 1f144482..2cf91e00 100644 --- a/src/routes/_merkl.chains.$id.(opportunities).tsx +++ b/src/routes/_merkl.chains.$id.(opportunities).tsx @@ -2,7 +2,7 @@ import { type LoaderFunctionArgs, json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Container, Space } from "dappkit"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary"; export async function loader({ params: { id: chainId }, request }: LoaderFunctionArgs) { diff --git a/src/routes/_merkl.chains.$id.tsx b/src/routes/_merkl.chains.$id.tsx index b8def26a..b953056f 100644 --- a/src/routes/_merkl.chains.$id.tsx +++ b/src/routes/_merkl.chains.$id.tsx @@ -42,17 +42,4 @@ export default function Index() { ); -} - -export function ErrorBoundary() { - const error = useRouteError(); - - return ( - <> - - {error?.message ?? "Error"} - {/* We don't support this chain */} - - - ); -} +} \ No newline at end of file diff --git a/src/routes/_merkl.opportunities.$chain.$type.$id.leaderboard.tsx b/src/routes/_merkl.opportunities.$chain.$type.$id.leaderboard.tsx index a4eab1e3..be760f77 100644 --- a/src/routes/_merkl.opportunities.$chain.$type.$id.leaderboard.tsx +++ b/src/routes/_merkl.opportunities.$chain.$type.$id.leaderboard.tsx @@ -4,7 +4,7 @@ import { Container, Group, Space, Text, Value } from "packages/dappkit/src"; import Tooltip from "packages/dappkit/src/components/primitives/Tooltip"; import { useMemo } from "react"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import { RewardService } from "src/api/services/reward.service"; import LeaderboardLibrary from "src/components/element/leaderboard/LeaderboardLibrary"; import { formatUnits, parseUnits } from "viem"; diff --git a/src/routes/_merkl.opportunities.$chain.$type.$id.tsx b/src/routes/_merkl.opportunities.$chain.$type.$id.tsx index 06f1c62e..6a8c8b7b 100644 --- a/src/routes/_merkl.opportunities.$chain.$type.$id.tsx +++ b/src/routes/_merkl.opportunities.$chain.$type.$id.tsx @@ -1,9 +1,9 @@ -import type { Opportunity } from "@angleprotocol/merkl-api"; import { type LoaderFunctionArgs, type MetaFunction, json } from "@remix-run/node"; import { Meta, Outlet, useLoaderData } from "@remix-run/react"; import { useMemo } from "react"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import type { OpportunityWithCampaigns } from "src/api/services/opportunity/opportunity.model"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import Hero from "src/components/composite/Hero"; import Tag from "src/components/element/Tag"; import { ErrorHeading } from "src/components/layout/ErrorHeading"; @@ -29,7 +29,7 @@ export const meta: MetaFunction = ({ data, error }) => { }; export type OutletContextOpportunity = { - opportunity: Opportunity; + opportunity: OpportunityWithCampaigns; }; export default function Index() { @@ -76,7 +76,16 @@ export default function Index() { { label: "Overview", link }, { label: "Leaderboard", link: `${link}/leaderboard` }, ]} - tags={tags.map(tag => )} + tags={tags.map(tag => ( + + ))} opportunity={opportunity}> diff --git a/src/routes/_merkl.protocols.$id.(opportunities).tsx b/src/routes/_merkl.protocols.$id.(opportunities).tsx index 21e8e827..6fbf9358 100644 --- a/src/routes/_merkl.protocols.$id.(opportunities).tsx +++ b/src/routes/_merkl.protocols.$id.(opportunities).tsx @@ -2,7 +2,7 @@ import { type LoaderFunctionArgs, json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Container, Space } from "dappkit/src"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import { ProtocolService } from "src/api/services/protocol.service"; import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary"; diff --git a/src/routes/_merkl.status.$status.(opportunities).tsx b/src/routes/_merkl.status.$status.(opportunities).tsx index 0b274ac3..075faa85 100644 --- a/src/routes/_merkl.status.$status.(opportunities).tsx +++ b/src/routes/_merkl.status.$status.(opportunities).tsx @@ -2,7 +2,7 @@ import { type LoaderFunctionArgs, json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Container, Space } from "dappkit"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary"; import { getStatus } from "src/config/status"; diff --git a/src/routes/_merkl.tokens.$symbol.(opportunities).tsx b/src/routes/_merkl.tokens.$symbol.(opportunities).tsx index a0b04ac9..0fa0e51b 100644 --- a/src/routes/_merkl.tokens.$symbol.(opportunities).tsx +++ b/src/routes/_merkl.tokens.$symbol.(opportunities).tsx @@ -2,7 +2,7 @@ import { type LoaderFunctionArgs, json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { Container, Space } from "dappkit"; import { ChainService } from "src/api/services/chain.service"; -import { OpportunityService } from "src/api/services/opportunity.service"; +import { OpportunityService } from "src/api/services/opportunity/opportunity.service"; import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary"; export async function loader({ params: { symbol } }: LoaderFunctionArgs) { @@ -18,7 +18,11 @@ export default function Index() { return ( - + ); } From 910b806c8523ef5be47c571ddee3b6069d1af050 Mon Sep 17 00:00:00 2001 From: sheykei Date: Fri, 6 Dec 2024 11:38:22 +0100 Subject: [PATCH 03/34] change: more opportunity types --- src/components/element/opportunity/OpportunityButton.tsx | 2 +- src/components/element/opportunity/OpportunityFilters.tsx | 2 +- src/components/element/rewards/ClaimRewardsTokenTableRow.tsx | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/element/opportunity/OpportunityButton.tsx b/src/components/element/opportunity/OpportunityButton.tsx index 3789558f..c4c43b34 100644 --- a/src/components/element/opportunity/OpportunityButton.tsx +++ b/src/components/element/opportunity/OpportunityButton.tsx @@ -1,6 +1,6 @@ -import type { Opportunity } from "@merkl/api"; import { Button, Icons } from "dappkit"; import { blockEvent } from "packages/dappkit/src/utils/event"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; import useOpportunity from "src/hooks/resources/useOpportunity"; export type OpportuntiyButtonProps = { diff --git a/src/components/element/opportunity/OpportunityFilters.tsx b/src/components/element/opportunity/OpportunityFilters.tsx index 82e38c2f..c497667f 100644 --- a/src/components/element/opportunity/OpportunityFilters.tsx +++ b/src/components/element/opportunity/OpportunityFilters.tsx @@ -101,7 +101,7 @@ export default function OpportunityFilters({ only, exclude, chains }: Opportunit setInnerSearch(v)]} suffix={} onClick={onSearchSubmit} placeholder="Search" diff --git a/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx b/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx index 816f2ce1..200f84d4 100644 --- a/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx +++ b/src/components/element/rewards/ClaimRewardsTokenTableRow.tsx @@ -93,7 +93,6 @@ export default function ClaimRewardsTokenTableRow({ reward, checkedState, ...pro decimals={reward.token.decimals} /> } - claimColumn={null} /> ); From d14a6e8deca69c932a4c11769624a4d5bdcafad3 Mon Sep 17 00:00:00 2001 From: sheykei Date: Fri, 6 Dec 2024 11:50:25 +0100 Subject: [PATCH 04/34] fix: lint --- bun.lockb | Bin 829328 -> 827807 bytes src/api/services/campaigns/campaign.model.ts | 2 +- .../services/campaigns/campaign.service.ts | 4 ++-- .../services/opportunity/opportunity.model.ts | 2 +- src/api/types.ts | 2 +- src/components/element/Tag.tsx | 2 +- .../element/campaign/CampaignLibrary.tsx | 2 +- .../element/campaign/CampaignTableRow.tsx | 2 +- src/components/element/chain/ChainLibrary.tsx | 2 +- .../opportunity/OpportunityLibrary.tsx | 2 +- .../opportunity/OpportunityTableRow.tsx | 2 +- .../rewards/ClaimRewardsChainTableRow.tsx | 3 ++- src/config/actions.ts | 2 +- src/routes/_merkl.chains.$id.tsx | 5 ++--- src/routes/_merkl.chains.(all).(chains).tsx | 2 +- .../_merkl.protocols.(all).(protocols).tsx | 2 +- .../_merkl.tokens.$symbol.(opportunities).tsx | 6 +----- src/routes/_merkl.tokens.(all).(tokens).tsx | 2 +- 18 files changed, 20 insertions(+), 24 deletions(-) diff --git a/bun.lockb b/bun.lockb index d4617d1f5b857f754cbd7e844bc87a93dcba21fe..796bc6ad0317938d36009a264bb3010cd8a169af 100755 GIT binary patch delta 14613 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 delta 12957 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 = Fetched>; \ No newline at end of file +export type Campaign = Fetched>; diff --git a/src/api/services/campaigns/campaign.service.ts b/src/api/services/campaigns/campaign.service.ts index be1fe136..bd563d02 100644 --- a/src/api/services/campaigns/campaign.service.ts +++ b/src/api/services/campaigns/campaign.service.ts @@ -1,5 +1,5 @@ import type { Campaign } from "@merkl/api"; -import { api } from "../index.server"; +import { api } from "../../index.server"; export abstract class CampaignService { /** @@ -48,7 +48,7 @@ export abstract class CampaignService { } // ------ Fetch a campaign by ID - static async getByID(Id: string): Promise { + static async getByID(_Id: string): Promise { return null; } } diff --git a/src/api/services/opportunity/opportunity.model.ts b/src/api/services/opportunity/opportunity.model.ts index ac43f277..84e4bef7 100644 --- a/src/api/services/opportunity/opportunity.model.ts +++ b/src/api/services/opportunity/opportunity.model.ts @@ -3,4 +3,4 @@ import type { Fetched } from "src/api/types"; import type { Campaign } from "../campaigns/campaign.model"; export type Opportunity = Fetched; -export type OpportunityWithCampaigns = Fetched; \ No newline at end of file +export type OpportunityWithCampaigns = Fetched; diff --git a/src/api/types.ts b/src/api/types.ts index cd455fca..61557367 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -7,4 +7,4 @@ export type Api = ReturnType; * Type returned through a loader * @description helps with inconsistencies of the implicit type when returned through the remix json() loader */ -export type Fetched = SerializeFrom<() => TypedResponse> \ No newline at end of file +export type Fetched = SerializeFrom<() => TypedResponse>; diff --git a/src/components/element/Tag.tsx b/src/components/element/Tag.tsx index 8a7d07d1..6b28c973 100644 --- a/src/components/element/Tag.tsx +++ b/src/components/element/Tag.tsx @@ -1,4 +1,4 @@ -import type { Token } from "@merkl/api"; +import type { Token } from "@merkl/api"; import type { Chain } from "@merkl/api"; import { Button, Divider, Dropdown, Group, Hash, Icon, PrimitiveTag, Text } from "dappkit"; import type { Component, PrimitiveTagProps } from "dappkit"; diff --git a/src/components/element/campaign/CampaignLibrary.tsx b/src/components/element/campaign/CampaignLibrary.tsx index 493d35f0..10e6a335 100644 --- a/src/components/element/campaign/CampaignLibrary.tsx +++ b/src/components/element/campaign/CampaignLibrary.tsx @@ -1,9 +1,9 @@ import { Button, Group, Icon, Text } from "dappkit"; import moment from "moment"; import { useMemo, useState } from "react"; +import type { OpportunityWithCampaigns } from "src/api/services/opportunity/opportunity.model"; import { CampaignTable } from "./CampaignTable"; import CampaignTableRow from "./CampaignTableRow"; -import type { OpportunityWithCampaigns } from "src/api/services/opportunity/opportunity.model"; export type IProps = { opportunity: OpportunityWithCampaigns; diff --git a/src/components/element/campaign/CampaignTableRow.tsx b/src/components/element/campaign/CampaignTableRow.tsx index f9bc17b4..3c047776 100644 --- a/src/components/element/campaign/CampaignTableRow.tsx +++ b/src/components/element/campaign/CampaignTableRow.tsx @@ -2,13 +2,13 @@ import { type Component, Group, Hash, Icon, OverrideTheme, Text, Value, mergeCla import moment from "moment"; import Tooltip from "packages/dappkit/src/components/primitives/Tooltip"; import { useCallback, useMemo, useState } from "react"; +import type { Campaign } from "src/api/services/campaigns/campaign.model"; import useCampaign from "src/hooks/resources/useCampaign"; import { formatUnits, parseUnits } from "viem"; import Chain from "../chain/Chain"; import Token from "../token/Token"; import { CampaignRow } from "./CampaignTable"; import RestrictionsCollumn from "./tableCollumns/RestrictionsCollumn"; -import type { Campaign } from "src/api/services/campaigns/campaign.model"; export type CampaignTableRowProps = Component<{ campaign: Campaign; diff --git a/src/components/element/chain/ChainLibrary.tsx b/src/components/element/chain/ChainLibrary.tsx index 3b5a49d5..24c8d9cb 100644 --- a/src/components/element/chain/ChainLibrary.tsx +++ b/src/components/element/chain/ChainLibrary.tsx @@ -8,7 +8,7 @@ export type ChainLibraryProps = { count?: number; }; -export default function ChainLibrary({ chains, count }: ChainLibraryProps) { +export default function ChainLibrary({ chains }: ChainLibraryProps) { const rows = useMemo(() => chains?.map(c => ), [chains]); return {rows}; diff --git a/src/components/element/opportunity/OpportunityLibrary.tsx b/src/components/element/opportunity/OpportunityLibrary.tsx index 329decfd..94a04c83 100644 --- a/src/components/element/opportunity/OpportunityLibrary.tsx +++ b/src/components/element/opportunity/OpportunityLibrary.tsx @@ -1,12 +1,12 @@ import type { Chain } from "@merkl/api"; import { Group, type Order } from "dappkit"; import { useMemo } from "react"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; import useSearchParamState from "src/hooks/filtering/useSearchParamState"; import OpportunityFilters, { type OpportunityFilterProps } from "./OpportunityFilters"; import OpportunityPagination from "./OpportunityPagination"; import { OpportunityTable, type opportunityColumns } from "./OpportunityTable"; import OpportunityTableRow from "./OpportunityTableRow"; -import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; export type OpportunityLibrary = { opportunities: Opportunity[]; diff --git a/src/components/element/opportunity/OpportunityTableRow.tsx b/src/components/element/opportunity/OpportunityTableRow.tsx index 4141b24d..1f57d5a7 100644 --- a/src/components/element/opportunity/OpportunityTableRow.tsx +++ b/src/components/element/opportunity/OpportunityTableRow.tsx @@ -6,10 +6,10 @@ import { Title } from "dappkit"; import { Value } from "dappkit"; import { Button } from "dappkit"; import { mergeClass } from "dappkit"; +import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; import useOpportunity from "src/hooks/resources/useOpportunity"; import Tag, { type TagTypes } from "../Tag"; import { OpportunityRow } from "./OpportunityTable"; -import type { Opportunity } from "src/api/services/opportunity/opportunity.model"; export type OpportunityTableRowProps = { hideTags?: (keyof TagTypes)[]; diff --git a/src/components/element/rewards/ClaimRewardsChainTableRow.tsx b/src/components/element/rewards/ClaimRewardsChainTableRow.tsx index a9669c88..aa923f0e 100644 --- a/src/components/element/rewards/ClaimRewardsChainTableRow.tsx +++ b/src/components/element/rewards/ClaimRewardsChainTableRow.tsx @@ -61,7 +61,8 @@ export default function ClaimRewardsChainTableRow({ const claimed = useMemo(() => { return reward.rewards.reduce( - (sum, { claimed, token: { decimals, price } }) => sum + Number.parseFloat(formatUnits(claimed, decimals)) * (price ?? 0), + (sum, { claimed, token: { decimals, price } }) => + sum + Number.parseFloat(formatUnits(claimed, decimals)) * (price ?? 0), 0, ); }, [reward]); diff --git a/src/config/actions.ts b/src/config/actions.ts index c09b46fc..3c146e9e 100644 --- a/src/config/actions.ts +++ b/src/config/actions.ts @@ -5,7 +5,7 @@ export const actions = { INVALID: { label: "Invalid", description: "Invalid", - icon: { remix: "RiFileWarningLine" } + icon: { remix: "RiFileWarningLine" }, }, POOL: { label: "Provide Liquidity", diff --git a/src/routes/_merkl.chains.$id.tsx b/src/routes/_merkl.chains.$id.tsx index b953056f..19329e1b 100644 --- a/src/routes/_merkl.chains.$id.tsx +++ b/src/routes/_merkl.chains.$id.tsx @@ -1,6 +1,5 @@ import { type LoaderFunctionArgs, type MetaFunction, json } from "@remix-run/node"; -import { Outlet, useLoaderData, useRouteError } from "@remix-run/react"; -import { Group, Title } from "dappkit"; +import { Outlet, useLoaderData } from "@remix-run/react"; import { ChainService } from "src/api/services/chain.service"; import Hero from "src/components/composite/Hero"; @@ -42,4 +41,4 @@ export default function Index() { ); -} \ No newline at end of file +} diff --git a/src/routes/_merkl.chains.(all).(chains).tsx b/src/routes/_merkl.chains.(all).(chains).tsx index 1d034ed9..f4698272 100644 --- a/src/routes/_merkl.chains.(all).(chains).tsx +++ b/src/routes/_merkl.chains.(all).(chains).tsx @@ -4,7 +4,7 @@ import { Container, Space } from "packages/dappkit/src"; import { ChainService } from "src/api/services/chain.service"; import ChainLibrary from "src/components/element/chain/ChainLibrary"; -export async function loader({ params: { id }, request }: LoaderFunctionArgs) { +export async function loader(_args: LoaderFunctionArgs) { const chains = await ChainService.getAll(); return json({ chains, count: chains.length }); diff --git a/src/routes/_merkl.protocols.(all).(protocols).tsx b/src/routes/_merkl.protocols.(all).(protocols).tsx index 694977ea..090552da 100644 --- a/src/routes/_merkl.protocols.(all).(protocols).tsx +++ b/src/routes/_merkl.protocols.(all).(protocols).tsx @@ -4,7 +4,7 @@ import { Container, Space } from "packages/dappkit/src"; import { ProtocolService } from "src/api/services/protocol.service"; import ProtocolLibrary from "src/components/element/protocol/ProtocolLibrary"; -export async function loader({ params: { id }, request }: LoaderFunctionArgs) { +export async function loader({ request }: LoaderFunctionArgs) { const { protocols, count } = await ProtocolService.getManyFromRequest(request); return json({ protocols, count }); diff --git a/src/routes/_merkl.tokens.$symbol.(opportunities).tsx b/src/routes/_merkl.tokens.$symbol.(opportunities).tsx index 0fa0e51b..3b726d26 100644 --- a/src/routes/_merkl.tokens.$symbol.(opportunities).tsx +++ b/src/routes/_merkl.tokens.$symbol.(opportunities).tsx @@ -18,11 +18,7 @@ export default function Index() { return ( - + ); } diff --git a/src/routes/_merkl.tokens.(all).(tokens).tsx b/src/routes/_merkl.tokens.(all).(tokens).tsx index a18e00ce..e30fb549 100644 --- a/src/routes/_merkl.tokens.(all).(tokens).tsx +++ b/src/routes/_merkl.tokens.(all).(tokens).tsx @@ -4,7 +4,7 @@ import { Container, Space } from "packages/dappkit/src"; import { TokenService } from "src/api/services/token.service"; import TokenLibrary from "src/components/element/token/TokenLibrary"; -export async function loader({ params: { id }, request }: LoaderFunctionArgs) { +export async function loader({ request }: LoaderFunctionArgs) { const { tokens, count } = await TokenService.getManyFromRequest(request); return json({ tokens, count }); From f3c7aa1af37f9290a9fc9eb09476feff357783bc Mon Sep 17 00:00:00 2001 From: sheykei <47207681+clement4saunier@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:25:29 +0100 Subject: [PATCH 05/34] add: themes and theme switcher in dev mode (#4) * add: theme selector when in dev mode * add: theme switcher in dev mode * fix: protocol empty tag * fix: lint error --- merkl.config.ts | 25 ++++++++++++++++++++-- src/components/element/SwitchMode.tsx | 29 +++++++++++++++++++------- src/hooks/resources/useOpportunity.tsx | 5 ++++- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/merkl.config.ts b/merkl.config.ts index 0048cec1..98b4e999 100644 --- a/merkl.config.ts +++ b/merkl.config.ts @@ -41,9 +41,16 @@ import { coinbaseWallet, walletConnect } from "wagmi/connectors"; export default createConfig({ appName: "Merkl", - modes: ["dark"], - defaultTheme: "merkl", + modes: ["dark", "light"], + defaultTheme: "ignite", themes: { + ignite: { + base: createColoring(["#1755F4", "#FF7900", "#0D1530"], ["#1755F4", "#FF7900", "#FFFFFF"]), + info: createColoring(["#2ABDFF", "#2ABDFF", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + good: createColoring(["#40B66B", "#40B66B", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + warn: createColoring(["#ff9600", "#ff9600", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + harm: createColoring(["#d22e14", "#d22e14", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + }, merkl: { base: createColoring(["#1F2333", "#B8AAFD", "#131620"], ["#FCF8F5", "#B8AAFD", "white"]), info: createColoring(["#2ABDFF", "#2ABDFF", "#131620"], ["#FFFFFF", "#40B66B", "white"]), @@ -51,6 +58,20 @@ export default createConfig({ warn: createColoring(["#ff9600", "#ff9600", "#131620"], ["#FFFFFF", "#40B66B", "white"]), harm: createColoring(["#d22e14", "#d22e14", "#131620"], ["#FFFFFF", "#40B66B", "white"]), }, + backoffice: { + base: createColoring(["#8B8D98", "#9984D2", "#000000"], ["#8B8D98", "#9984D2", "#FFFFFF"]), + info: createColoring(["#2ABDFF", "#2ABDFF", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + good: createColoring(["#40B66B", "#40B66B", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + warn: createColoring(["#ff9600", "#ff9600", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + harm: createColoring(["#d22e14", "#d22e14", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + }, + puffer: { + base: createColoring(["#2A35BD", "#3D3D3D", "#0E1035"], ["#2A35BD", "#F5F9FF", "#FFFFFF"]), + info: createColoring(["#2ABDFF", "#2ABDFF", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + good: createColoring(["#40B66B", "#40B66B", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + warn: createColoring(["#ff9600", "#ff9600", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + harm: createColoring(["#d22e14", "#d22e14", "#131620"], ["#FFFFFF", "#40B66B", "white"]), + }, }, sizing: { width: { xs: 14, sm: 16, md: 18, lg: 20, xl: 24 }, diff --git a/src/components/element/SwitchMode.tsx b/src/components/element/SwitchMode.tsx index 1379ae9d..2ad8e7a3 100644 --- a/src/components/element/SwitchMode.tsx +++ b/src/components/element/SwitchMode.tsx @@ -1,16 +1,31 @@ +import { Button, Icon, Select, useTheme } from "dappkit"; import config from "merkl.config"; -import { Button, Icon, useTheme } from "packages/dappkit/src"; import { useMemo } from "react"; export default function SwitchMode() { - const { mode, toggleMode } = useTheme(); + const { mode, toggleMode, themes, theme, setTheme } = useTheme(); const canSwitchModes = useMemo(() => !(!config.modes || config.modes?.length === 1), []); + const themeOptions = useMemo(() => { + return Object.keys(themes).reduce( + (obj, name) => + Object.assign(obj, { + [name]: name, + }), + {}, + ); + }, [themes]); + return ( - canSwitchModes && ( - - ) + <> + {process.env.NODE_ENV !== "production" && Object.keys(themeOptions)?.length > 1 && ( + + + + ); +} diff --git a/src/components/element/Socials.tsx b/src/components/element/Socials.tsx index 2ea6204c..b045d7d5 100644 --- a/src/components/element/Socials.tsx +++ b/src/components/element/Socials.tsx @@ -24,6 +24,11 @@ export default function Socials() { )} + {!!config.socials.medium && ( + + )} ); } diff --git a/src/components/element/Tag.tsx b/src/components/element/Tag.tsx index 6b28c973..e8db5510 100644 --- a/src/components/element/Tag.tsx +++ b/src/components/element/Tag.tsx @@ -270,7 +270,7 @@ export default function Tag({ type, value, ...props }: }> - + {value?.name} diff --git a/src/components/element/chain/ChainTable.tsx b/src/components/element/chain/ChainTable.tsx index 854384b0..6511a27b 100644 --- a/src/components/element/chain/ChainTable.tsx +++ b/src/components/element/chain/ChainTable.tsx @@ -2,7 +2,7 @@ import { createTable } from "dappkit"; export const [ChainTable, ChainRow, chainColumns] = createTable({ chain: { - name: "CHAIN", + name: "Chain", size: "minmax(350px,1fr)", compact: "1fr", className: "justify-start", diff --git a/src/components/element/opportunity/OpportunityTable.tsx b/src/components/element/opportunity/OpportunityTable.tsx index 704d99c3..0ad21996 100644 --- a/src/components/element/opportunity/OpportunityTable.tsx +++ b/src/components/element/opportunity/OpportunityTable.tsx @@ -15,7 +15,7 @@ export const [OpportunityTable, OpportunityRow, opportunityColumns] = createTabl className: "justify-center", }, apy: { - name: "APR", + name: "APY", size: "minmax(min-content,150px)", compactSize: "minmax(min-content,1fr)", className: "justify-center", diff --git a/src/components/element/opportunity/OpportunityTableRow.tsx b/src/components/element/opportunity/OpportunityTableRow.tsx index 1f57d5a7..f5bd0888 100644 --- a/src/components/element/opportunity/OpportunityTableRow.tsx +++ b/src/components/element/opportunity/OpportunityTableRow.tsx @@ -37,7 +37,8 @@ export default function OpportunityTableRow({ hideTags, opportunity, className, } apyColumn={ - - diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index e8f854ad..e6ba0dd3 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -86,7 +86,7 @@ export default function Header() { {Object.entries(routes) - .filter(([key]) => !["homepage", "privacy", "terms"].includes(key)) + .filter(([key]) => !["homepage"].includes(key)) .map(([key, { route }]) => { return ( + + } breadcrumbs={[ { link: "/protocols", name: "Protocols" }, { link: `/protocols/${protocol.name}`, name: protocol.name }, @@ -31,6 +40,7 @@ export default function Index() { { label: "Opportunities", link: `/protocols/${protocol.name?.toLowerCase()}`, + key: crypto.randomUUID(), }, ]}> diff --git a/src/routes/_merkl.status.$status.tsx b/src/routes/_merkl.status.$status.tsx index 0884490a..c0eb67a2 100644 --- a/src/routes/_merkl.status.$status.tsx +++ b/src/routes/_merkl.status.$status.tsx @@ -36,6 +36,7 @@ export default function Index() { { label: "Opportunities", link: `/status/${status.label?.toLowerCase()}`, + key: crypto.randomUUID(), }, ]}> diff --git a/src/routes/_merkl.tokens.$symbol.tsx b/src/routes/_merkl.tokens.$symbol.tsx index 60c7f08d..c53b00a8 100644 --- a/src/routes/_merkl.tokens.$symbol.tsx +++ b/src/routes/_merkl.tokens.$symbol.tsx @@ -64,6 +64,7 @@ export default function Index() { { label: "Opportunities", link: `/tokens/${token.symbol?.toLowerCase()}`, + key: crypto.randomUUID(), }, ]} tags={tags.map(tag => )}> diff --git a/src/routes/_merkl.tokens.(all).tsx b/src/routes/_merkl.tokens.(all).tsx index 08306789..1c7704ba 100644 --- a/src/routes/_merkl.tokens.(all).tsx +++ b/src/routes/_merkl.tokens.(all).tsx @@ -12,7 +12,11 @@ export default function Index() { icons={[{ remix: "RiCoinFill" }]} title={"Tokens"} breadcrumbs={[{ link: "/tokens", name: "Tokens" }]} - description={"Tokens indexed by Merkl"}> + description={"Tokens indexed by Merkl"} + sideDatas={[ + { data: "8%", label: "Total opportunities", key: crypto.randomUUID() }, + { data: "99.999", label: "Price", key: crypto.randomUUID() }, + ]}> ); diff --git a/src/routes/_merkl.tsx b/src/routes/_merkl.tsx index 4dc1b725..b20574f5 100644 --- a/src/routes/_merkl.tsx +++ b/src/routes/_merkl.tsx @@ -5,14 +5,12 @@ import Header from "src/components/layout/Header"; export default function Index() { return ( - <> - -
-
- -
-