Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import type { LinksFunction } from "@remix-run/node";
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react";
import "./tailwind.css";
import { DAppProvider, Group } from "dappkit";
import Footer from "src/components/layout/Footer";
import { DAppProvider } from "dappkit";
// import Footer from "src/components/layout/Footer";
// import Header from "src/components/layout/Header";
import { http, createConfig } from "wagmi";
import { mainnet, sepolia } from "wagmi/chains";
import { coinbaseWallet, walletConnect } from "wagmi/connectors";
import Header from "../src/components/layout/Header";
import styles from "./tailwind.css?url";

export const config = createConfig({
Expand Down
3 changes: 1 addition & 2 deletions app/routes/_merkl.(home).(opportunities).tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import OpportunityLibrary from "src/components/element/opportunity/OpportunityLi

export async function loader({ request }: LoaderFunctionArgs) {
const { data: opportunities, ...res } = await fetchOpportunities(request);

console.log(opportunities, res);
console.log("RES", res);

return json({ opportunities });
}
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_merkl.action.$action.(opportunities).tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type LoaderFunctionArgs, json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Space } from "dappkit/src";
import { Space } from "dappkit";
import { fetchOpportunities } from "src/api/opportunity/opportunity";
import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary";
import { getAction } from "src/config/actions";
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_merkl.campaign.$id.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Group } from "dappkit/src";
import { Group } from "dappkit";

export default function Index() {
return (
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_merkl.chain.$id.(opportunities).tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type LoaderFunctionArgs, json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Space } from "dappkit/src";
import { Space } from "dappkit";
import { fetchOpportunities } from "src/api/opportunity/opportunity";
import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary";
import { getChainId } from "src/config/chains";
Expand Down
27 changes: 15 additions & 12 deletions app/routes/_merkl.chain.$id.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
import { type LoaderFunctionArgs, json } from "@remix-run/node";
import { Outlet, useLoaderData, useNavigate, useRouteError } from "@remix-run/react";
import { Group, Icon, Select, Title } from "dappkit/src";
import { Group, Icon, Select, Title } from "dappkit";
import { type ReactNode, useMemo } from "react";
import { api } from "src/api";
import Heading from "src/components/composite/Heading";
import Page from "src/components/composite/layout/Page";
import { type ChainId, chains, getChainId } from "src/config/chains";
import { type ChainId, chains } from "src/config/chains";

export async function loader({ params: { id } }: LoaderFunctionArgs) {
const chainId = getChainId(id ?? "");
const { data: chains } = await api.v4.chain.get({ query: { search: id } });
const chain = chains?.[0];

if (!chainId) throw new Error("Unsupported Chain");
if (!chain) throw new Error("Unsupported Chain");
if (chains?.length > 1 || chain.name.toLowerCase() !== id?.toLowerCase()) throw new Error("Unsupported Chain");

return json({ chainId });
return json({ chain });
}

export default function Index() {
const { chainId } = useLoaderData<typeof loader>();
const chain = chains[chainId];
const { chain } = useLoaderData<typeof loader>();
const label = chain.name.toLowerCase();

return (
<Page>
<Heading
icons={[{ chain: chainId }]}
icons={[{ src: chain.icon }]}
navigation={{ label: "Back to opportunities", link: "/" }}
title={chain.label}
title={chain.name}
description={"Lorem ipsum something cool about the chain"}
tabs={[
{ label: "Opportunities", link: `/chain/${chain.label?.toLowerCase()}` },
{ label: "Leaderboard", link: `/chain/${chain.label?.toLowerCase()}/leaderboard` },
{ label: "Analytics", link: `/chain/${chain.label?.toLowerCase()}/analytics` },
{ label: "Opportunities", link: `/chain/${label?.toLowerCase()}` },
{ label: "Leaderboard", link: `/chain/${label?.toLowerCase()}/leaderboard` },
{ label: "Analytics", link: `/chain/${label?.toLowerCase()}/analytics` },
]}>
<Outlet />
</Heading>
Expand Down
42 changes: 42 additions & 0 deletions app/routes/_merkl.opportunity.$chain.$type.$id.(overview).tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { Campaign, Opportunity } from "@angleprotocol/merkl-api";
import { Group } from "@ariakit/react";
import { type LoaderFunctionArgs, json } from "@remix-run/node";
import { useLoaderData, useParams } from "@remix-run/react";
import { Space } from "packages/dappkit/src";
import { api } from "src/api";
import CampaignLibrary from "src/components/element/campaign/CampaignLibrary";
import Participate from "src/components/element/participate/Participate";
import { getChainId } from "src/config/chains";
import useOpportunity from "src/hooks/resources/useOpportunity";

export async function loader({ params: { id, type, chain } }: LoaderFunctionArgs) {
const chainId = getChainId(chain ?? "");

if (!chainId || !id || !type) throw "";

const { data: opportunity, ...res } = await api.v4.opportunity({ chainId })({ type })({ id }).get();
const { data: campaigns } = await api.v4.campaign.opportunity({ chainId })({ type })({ id }).get();

if (!opportunity || !campaigns) throw "";

return json({ opportunity, campaigns });
}

export default function Index() {
const { opportunity, campaigns } = useLoaderData<typeof loader>();
const { chain, id } = useParams();

const { tags, description, link } = useOpportunity(opportunity as Opportunity);

return (
<Group>
<Space size="md" />
<Group className="grid grid-cols-1 gap-md md:grid-cols-[1fr,300px]">
<CampaignLibrary campaigns={campaigns as Campaign[]} />
<Group className="flex-col">
<Participate opportunity={opportunity as Opportunity} />
</Group>
</Group>
</Group>
);
}
10 changes: 6 additions & 4 deletions app/routes/_merkl.opportunity.$chain.$type.$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export async function loader({ params: { id, type, chain } }: LoaderFunctionArgs

if (!opportunity) throw "";

console.log("OPPO", res, opportunity);

return json(opportunity);
}

Expand All @@ -29,7 +31,7 @@ export default function Index() {
const opportunity = useLoaderData<typeof loader>();
const { chain, id } = useParams();

const { tags, description } = useOpportunity(opportunity as Opportunity);
const { tags, description, link } = useOpportunity(opportunity as Opportunity);

return (
<Page>
Expand All @@ -40,9 +42,9 @@ export default function Index() {
title={opportunity.name}
description={description}
tabs={[
{ label: "Overview", link: `/opportunity/${chain}/${id}` },
{ label: "Leaderboard", link: `/opportunity/${chain}/${id}/leaderboard` },
{ label: "Analytics", link: `/opportunity/${chain}/${id}/analytics` },
{ label: "Overview", link },
{ label: "Leaderboard", link: `${link}/leaderboard` },
{ label: "Analytics", link: `${link}/analytics` },
]}
tags={tags.map(tag => (
<Tag key={`${tag.type}_${tag.value?.address ?? tag.value}`} {...tag} size="sm" look="bold" />
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_merkl.status.$status.(opportunities).tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type LoaderFunctionArgs, json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Space } from "dappkit/src";
import { Space } from "dappkit";
import { fetchOpportunities } from "src/api/opportunity/opportunity";
import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary";
import { getStatus } from "src/config/status";
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_merkl.token.$symbol.(opportunities).tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type LoaderFunctionArgs, json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Space } from "dappkit/src";
import { Space } from "dappkit";
import { fetchOpportunities } from "src/api/opportunity/opportunity";
import OpportunityLibrary from "src/components/element/opportunity/OpportunityLibrary";

Expand Down
19 changes: 12 additions & 7 deletions app/routes/_merkl.token.$symbol.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,31 @@ import Tag, { type TagType } from "src/components/element/Tag";

export async function loader({ params: { symbol } }: LoaderFunctionArgs) {
const { data: tokens, ...res } = await api.v4.token.get({ query: { symbol } });
const { data: chains } = await api.v4.chain.get({ query: {} });

if (!tokens?.length) throw new Error("Unknown token");

return json({ tokens });
return json({ tokens, chains });
}

export default function Index() {
const { tokens } = useLoaderData<typeof loader>();
const { tokens, chains } = useLoaderData<typeof loader>();
const token = tokens?.[0];

const tags = useMemo(() => {
console.log(tokens.filter(c => c.chainId === 167000));

return tokens.map(t => ({ type: "tokenChain", value: t }) satisfies TagType<"tokenChain">);
}, [tokens]);
return tokens.map(
t =>
({
type: "tokenChain",
value: { ...t, chain: chains?.find(c => c.id === t.chainId) },
}) satisfies TagType<"tokenChain">,
);
}, [tokens, chains]);

return (
<Page>
<Heading
icons={[token?.icon]}
icons={[{ src: tokens.find(t => t.icon && t.icon !== "")?.icon }]}
navigation={{ label: "Back to opportunities", link: "/" }}
title={
<>
Expand Down
2 changes: 1 addition & 1 deletion app/routes/_merkl.user.$address.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Outlet, useParams } from "@remix-run/react";
import { Hash, Icon } from "dappkit/src";
import { Hash, Icon } from "dappkit";
import Heading from "src/components/composite/Heading";
import Page from "src/components/composite/layout/Page";

Expand Down
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"workspaces": ["packages/*"],
"dependencies": {
"@angleprotocol/merkl-api": "0.9.92",
"@angleprotocol/merkl-api": "0.9.101",
"@ariakit/react": "^0.4.12",
"@elysiajs/eden": "^1.1.3",
"@radix-ui/react-scroll-area": "^1.2.0",
Expand All @@ -29,6 +29,7 @@
"isbot": "^4.1.0",
"lucide-react": "^0.439.0",
"match-sorter": "^6.3.4",
"moment": "^2.30.1",
"qs": "^6.13.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
2 changes: 0 additions & 2 deletions src/api/fetch/fetchOpportunities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ export const fetchOpportunities = createCall<
};
},
reducer(fetched, { chainId }) {
console.log("opps", fetched);

return fetched;
},
});
7 changes: 5 additions & 2 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { MerklApi } from "@angleprotocol/merkl-api";

const endpoint = "https://api.merkl.xyz";
const api = MerklApi(endpoint);
const local = "http://localhost:6007";
const production = "https://api.merkl.xyz";
const staging = "https://api-staging.merkl.xyz";

const api = MerklApi(staging);

export { api };
2 changes: 1 addition & 1 deletion src/components/composite/Heading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function Heading({ navigation, icons, title, description, tags, t
<Text>{description}</Text>
<Group className="mt-xl*2">
{tabs?.map(tab => (
<Button look={location.pathname === tab.link ? "hype" : "base"} to={tab.link} key={tab.link}>
<Button look={location.pathname === tab.link ? "hype" : "soft"} to={tab.link} key={tab.link}>
{tab.label}
</Button>
))}
Expand Down
32 changes: 15 additions & 17 deletions src/components/element/Tag.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import type { Opportunity } from "@angleprotocol/merkl-api";
import type { Chain, Opportunity } from "@angleprotocol/merkl-api";
import { Button, Divider, Dropdown, Group, Hash, Icon, Text, Title } from "dappkit";
import type { ButtonProps } from "dappkit";
import type { Token } from "src/api/fetch/fetchTokens";
import { type Action, actions } from "src/config/actions";
import { type ChainId, chains } from "src/config/chains";
import { chains } from "src/config/chains";
import type { Protocol } from "src/config/protocols";
import { statuses } from "src/config/status";

export type TagTypes = {
chain: ChainId;
chain: Opportunity["chain"];
token: Token;
tokenChain: Token;
tokenChain: Token & { chain: Chain };
protocol: Protocol;
action: Action;
status: Opportunity["status"];
Expand Down Expand Up @@ -52,7 +52,7 @@ export default function Tag<T extends keyof TagTypes>({ type, value, ...props }:
);
}
case "chain": {
const chain = chains[value as TagTypes["chain"]];
const chain = value as TagTypes["chain"];

return (
<Dropdown
Expand All @@ -61,22 +61,22 @@ export default function Tag<T extends keyof TagTypes>({ type, value, ...props }:
<Group size="xs" className="flex-col">
<Group className="justify-between">
<Text size="xs">Chain</Text>
<Text size="xs">id: {value}</Text>
<Text size="xs">id: {chain?.id}</Text>
</Group>
<Group size="sm">
<Icon size={props?.size} chain={value} />
<Title h={4}>{chain?.label}</Title>
<Icon size={props?.size} src={chain?.icon} />
<Title h={4}>{chain?.name}</Title>
</Group>
</Group>
<Divider className="border-main-6" horizontal />
<Button to={`/chain/${chain?.label}`} size="sm" look="bold">
<Button to={`/chain/${chain?.name}`} size="sm" look="bold">
Open
</Button>
</>
}>
<Button key={value} {...props}>
<Icon size={props?.size} chain={value} />
{chain?.label}
<Icon size={props?.size} src={chain?.icon} />
{chain?.name}
</Button>
</Dropdown>
);
Expand Down Expand Up @@ -131,7 +131,7 @@ export default function Tag<T extends keyof TagTypes>({ type, value, ...props }:
</Hash>
</Group>
<Group size="sm">
<Icon size={props?.size} src={token.logoURI} />
<Icon size={props?.size} src={token.icon} />
<Title h={4}>{token?.name}</Title>
</Group>
</Group>
Expand All @@ -148,15 +148,15 @@ export default function Tag<T extends keyof TagTypes>({ type, value, ...props }:
</>
}>
<Button key={value} {...props}>
<Icon size={props?.size} src={token.logoURI} />
<Icon size={props?.size} src={token.icon} />
{token?.symbol}
</Button>
</Dropdown>
);
}

case "tokenChain": {
const token = value as TagTypes["token"];
const token = value as TagTypes["tokenChain"];

if (!token) return <Button {...props}>{value}</Button>;

Expand Down Expand Up @@ -189,7 +189,7 @@ export default function Tag<T extends keyof TagTypes>({ type, value, ...props }:
</>
}>
<Button key={value} {...props}>
<Icon size={props?.size} chain={token.chainId} />
<Icon size={props?.size} src={token.chain.icon} />
{chains[token.chainId]?.label}
</Button>
</Dropdown>
Expand All @@ -199,8 +199,6 @@ export default function Tag<T extends keyof TagTypes>({ type, value, ...props }:
case "protocol": {
const protocol = value;

console.log(protocol);

if (!protocol) return <Button {...props}>{value}</Button>;

return (
Expand Down
Loading