Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update: merkl-app #54

Open
wants to merge 96 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
ef9f0ac
fix: some type errors
clmntsnr Dec 5, 2024
69eccd9
add: services model draft
clmntsnr Dec 6, 2024
910b806
change: more opportunity types
clmntsnr Dec 6, 2024
1586467
Merge remote-tracking branch 'merkl-lite/fix-errors-update-dappkit' i…
clmntsnr Dec 6, 2024
d14a6e8
fix: lint
clmntsnr Dec 6, 2024
8550018
Merge pull request #1 from AngleProtocol/sync-merkl-lite-chores
clmntsnr Dec 6, 2024
f3c7aa1
add: themes and theme switcher in dev mode (#4)
clmntsnr Dec 6, 2024
48bb14f
Tabs sync (#5)
indaviande Dec 6, 2024
6f6f09a
feat: re add CI (#6)
Picodes Dec 6, 2024
e2ce35f
Feat/leaderboard display (#7)
hugolxt Dec 9, 2024
4a37697
update: dashboard styling (#8)
clmntsnr Dec 9, 2024
473343a
add(front): modal, hero, select, tabs/tags, pagination (#9)
indaviande Dec 9, 2024
08ad823
update: opportunity campaigns/leaderboard view (#11)
clmntsnr Dec 9, 2024
33d71cf
feat: add APR modal and table components for opportunity details on h…
hugolxt Dec 10, 2024
1d89597
Feat Hero campaign and protocol (#13)
hugolxt Dec 11, 2024
1c7f143
feat(opportunity): new hero, tableRow, OpportunityFilters (#15)
indaviande Dec 11, 2024
2b5d86f
:sparkles: sum daily rewards fora protocol (#16)
hugolxt Dec 11, 2024
831344e
Fix/campaign page (#17)
hugolxt Dec 11, 2024
f768483
update: opportunities pages (#14)
clmntsnr Dec 11, 2024
2f57dcf
apr (#18)
indaviande Dec 11, 2024
d777c3f
Fix/campaign page (#20)
hugolxt Dec 13, 2024
b7f1feb
add lastSnapshot
hugolxt Dec 13, 2024
f19898d
add lastSnapshot (#21)
hugolxt Dec 13, 2024
21e1cee
Merge branch 'main' of https://github.com/AngleProtocol/merkl-app
hugolxt Dec 13, 2024
97552af
fixes: feedback, mainly opportunities & dashboard (#22)
clmntsnr Dec 13, 2024
8114fd1
add: cache on static resoruces (#23)
clmntsnr Dec 13, 2024
81ed915
Enhance opportunity data retrieval with APR and daily rewards metrics…
hugolxt Dec 13, 2024
0123bd9
fix: pagination defaulting & cache (#25)
clmntsnr Dec 13, 2024
50cd360
clean wip: comment out static sideDatas for dynamic implementation (#26)
hugolxt Dec 13, 2024
8cc70a9
fix: protocl filter (#27)
clmntsnr Dec 13, 2024
e32b466
fix: protocol desc (#28)
clmntsnr Dec 13, 2024
6e1438e
token stats + cleaning (#29)
hugolxt Dec 13, 2024
d942f68
Small APR Fix (#19)
indaviande Dec 16, 2024
39be322
Fixes on protocol, chain, token and campaign pages (#30)
hugolxt Dec 16, 2024
2d0abd2
add: depositor (#31)
clmntsnr Dec 16, 2024
d319b3f
update: dappkit (#33)
clmntsnr Dec 16, 2024
86c043e
feat(front): apr modal, layermenu, issues !!! (#32)
indaviande Dec 16, 2024
6d5358f
rename homepage to home (#34)
indaviande Dec 16, 2024
cf2ead8
feat(front): change header logo & selects (#35)
indaviande Dec 16, 2024
03337fe
fix: update Dropdown component to use onHover for APR and TVL columns…
hugolxt Dec 16, 2024
7506e2d
add: fonts config (#37)
clmntsnr Dec 16, 2024
cacc837
feat: icons & uuid (#41)
indaviande Dec 18, 2024
66cc17e
chore: add test filter (#38)
Picodes Dec 18, 2024
37ddfa0
add: deposit modal (#42)
clmntsnr Dec 18, 2024
7a12049
wip display zk rewards (#39)
hugolxt Dec 18, 2024
1f66aa4
feat(api): enhance ProtocolService to include tags from config in API…
hugolxt Dec 18, 2024
b1e0465
update: dappkit
clmntsnr Dec 18, 2024
6f3921d
fix(campaign): update chain reference in CampaignTableRow component (…
hugolxt Dec 18, 2024
3308e7f
feat(rewards): add rewards navigation mode configuration and update C…
hugolxt Dec 18, 2024
37e807b
chore: historical claim tab
Picodes Dec 18, 2024
e6f329e
chore: historical claims
Picodes Dec 18, 2024
48ebc22
chore: lint
Picodes Dec 19, 2024
5158f72
fix: add auto linting
Picodes Dec 19, 2024
7c274a8
chore: remove useless type
Picodes Dec 19, 2024
a3f3a46
fix: lint
Picodes Dec 19, 2024
de6c327
feat: position route (#47)
Picodes Dec 19, 2024
181c9c1
introduction of I18n and fixes (#49)
hugolxt Dec 19, 2024
e93e127
feat(front): first round of feedbacks (#50)
indaviande Dec 20, 2024
2cc8a24
update: participation (#52)
clmntsnr Dec 20, 2024
22304dc
Feat/lifi (#53)
hugolxt Dec 23, 2024
f1d9fd8
feat: update LiFiWidget to use native tokens for fromToken and toToke…
hugolxt Dec 23, 2024
1596ba2
fix: opportunity fetch (#55)
Picodes Dec 23, 2024
84309b1
fixes
hugolxt Dec 23, 2024
6c48486
Merge branch 'main' of https://github.com/AngleProtocol/merkl-app
hugolxt Dec 23, 2024
fe39a2f
Revert "fix: opportunity fetch (#55)" (#56)
Picodes Dec 23, 2024
b24d9b2
remove bridge wording
hugolxt Dec 23, 2024
9e457c4
Merge branch 'main' of https://github.com/AngleProtocol/merkl-app
hugolxt Dec 23, 2024
7a1844d
update: wagmi (#58)
clmntsnr Dec 24, 2024
f871e26
update
clmntsnr Dec 24, 2024
3f1d920
wrap: root in client
clmntsnr Dec 24, 2024
2e8e8a9
refactor: enhance Position and ClaimRewards components for improved U…
hugolxt Dec 24, 2024
69cffc5
Fix/preprod (#57)
hugolxt Dec 24, 2024
36ec94e
fix: update Dropdown component to use state for open/close management…
hugolxt Dec 24, 2024
e866fd5
refactor: improve claimed handling (#61)
hugolxt Dec 24, 2024
d5cd317
add: single chain option & cleanup (#60)
clmntsnr Dec 26, 2024
01c9c3d
feat: add chains configuration to merkl.config and update reward serv…
hugolxt Dec 26, 2024
7793f02
fix header on resize (#64)
hugolxt Dec 27, 2024
c90258d
feat: integrate chain IDs into claims and rewards queries (#66)
hugolxt Dec 27, 2024
64aa2dd
refactor: update PositionTable layout and improve PositionTableRow re…
hugolxt Dec 27, 2024
d95b49e
chore: update subproject commit reference in dappkit (#68)
hugolxt Dec 27, 2024
d03ee49
chore: update subproject commit reference in dappkit (#69)
hugolxt Dec 27, 2024
bc8fcb9
add: zyfi supply transactions (#70)
clmntsnr Dec 27, 2024
2d8e892
feat: enhance PositionTable with collapsible sub-positions and improv…
hugolxt Dec 30, 2024
ea39298
Fixes/preprod (#73)
hugolxt Dec 30, 2024
afd28f1
fix array displaying btw claimed and positions (#75)
hugolxt Dec 31, 2024
9c7c3bb
Feat/opportunity card list (#74)
hugolxt Dec 31, 2024
3e129a9
Fixes/preprod (#76)
hugolxt Dec 31, 2024
8136e56
feat(front): zksync feedbacks before launch (#77)
indaviande Jan 2, 2025
50f504b
Feat/liquidity (#78)
hugolxt Jan 2, 2025
654a5fb
feat(bridge): add helper link and update opportunity settings removed…
hugolxt Jan 2, 2025
78d4b68
add opportunity tags on protocol page (#79)
hugolxt Jan 2, 2025
11c26ef
add: cells configuration (#71)
clmntsnr Jan 2, 2025
07f3652
feat(front): modal & other (#80)
indaviande Jan 2, 2025
c3d45cc
update: transaction notifications & balance refetch (#82)
clmntsnr Jan 2, 2025
00dd0e0
Merge remote-tracking branch 'merkl-app/main' into sync-merkl-app-cha…
clmntsnr Jan 2, 2025
4927a2f
fix: merge
clmntsnr Jan 2, 2025
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
60 changes: 45 additions & 15 deletions merkl.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,30 @@ export default createConfig({
appName: "Merkl",
modes: ["dark", "light"],
defaultTheme: "ignite",
tags: [],
opportunityNavigationMode: "direct",
opportunityNavigationMode: "supply",
opportunityCellHideTags: ["token", "action"],
rewardsNavigationMode: "chain",
opportunityLibraryDefaultView: "cells",
opprtunityPercentage: true,
hideLayerMenuHomePage: false,
deposit: true,
walletOptions: {
sponsorTransactions: true,
client(c) {
if (c.chain?.id === zksync.id) return c.extend(eip712WalletActions());
},
},
chains: [],
tags: [],
opportunity: {
featured: {
enabled: false,
length: 6,
},
},
bridge: {
helperLink: "",
},
themes: {
ignite: {
base: createColoring(["#1755F4", "#FF7900", "#0D1530"], ["#1755F4", "#FF7900", "#FFFFFF"]),
Expand Down Expand Up @@ -95,21 +115,16 @@ export default createConfig({
route: "/",
key: uuidv4(),
},
opportunities: {
icon: "RiPlanetFill",
route: "/opportunities",
protocols: {
icon: "RiVipCrown2Fill",
route: "/protocols",
key: uuidv4(),
},
bridge: {
icon: "RiCompassesLine",
route: "/bridge",
key: uuidv4(),
},
// protocols: {
// icon: "RiVipCrown2Fill",
// route: "/protocols",
// key: uuidv4(),
// },
// bridge: {
// icon: "RiCompassesLine",
// route: "/bridge",
// key: uuidv4(),
// },
docs: {
icon: "RiFile4Fill",
external: true,
Expand All @@ -132,6 +147,21 @@ export default createConfig({
// key: uuidv4(),
// },
},
header: {
searchbar: {
enabled: true,
},
// terms: {
// icon: "RiCompassesLine",
// route: "/terms",
// key: uuidv4(),
// },
// privacy: {
// icon: "RiInformationFill",
// route: "/privacy",
// key: uuidv4(),
// },
},
socials: {
discord: "",
telegram: "https://t.me/+2T0RNabX2ANkMzAx",
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"@ariakit/react": "^0.4.12",
"@elysiajs/eden": "^1.1.3",
"@emotion/css": "^11.13.4",
"@merkl/api": "0.10.188",
"@lifi/widget": "^3.13.1",
"@merkl/api": "0.10.222",
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-scroll-area": "^1.2.0",
"@remix-run/dev": "^2.11.2",
Expand All @@ -42,15 +43,16 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-responsive": "^10.0.0",
"react-toastify": "^11.0.2",
"remix-utils": "^7.7.0",
"save": "^2.9.0",
"tailwindcss": "^3.4.12",
"tailwindcss-animate": "^1.0.7",
"typedoc": "^0.26.7",
"uuid": "^11.0.3",
"viem": "2.21.54",
"viem": "2.21.33",
"vite-plugin-dts": "^4.2.1",
"wagmi": "^2.12.29",
"wagmi": "^2.14.6",
"zustand": "^5.0.0-rc.2"
},
"devDependencies": {
Expand Down
20 changes: 20 additions & 0 deletions src/I18n/en.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const en = {
pages: {
home: {
depositInformation: "",
},
opportunities: {
title: "Explore opportunities",
description: "Browse opportunities, compare rewards, and earn tokens",
},
campaings: {
title: "Explore opportunities",
description: "Browse opportunities, compare rewards, and earn tokens",
},
bridge: {
helper: "",
},
},
};

export default en;
34 changes: 34 additions & 0 deletions src/I18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import en from "./en";

type LanguageFiles = typeof en;

/**
* I18n class to handle translations
*/
export class I18n {
public static readonly trad: I18n = new I18n(en);

private primary: LanguageFiles;
// private secondary: LanguageFiles;

public get: LanguageFiles;

constructor(primary: LanguageFiles) {
this.primary = primary;
// this.secondary = secondary;
this.get = this.createProxy(this.primary);
}

// proxy to handle typing autocompletion
private createProxy<T extends object>(obj: T): T {
return new Proxy(obj, {
get: (target, prop) => {
const value = target[prop as keyof T];
if (typeof value === "object" && value !== null) {
return this.createProxy(value as object);
}
return value;
},
});
}
}
7 changes: 6 additions & 1 deletion src/api/services/claims.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import config from "merkl.config";
import { api } from "../index.server";
import { fetchWithLogs } from "../utils";

Expand All @@ -14,7 +15,11 @@ export abstract class ClaimsService {
return data;
}

// should be paginated
static async getForUser(address: string) {
return await ClaimsService.#fetch(async () => api.v4.claims({ address }).get());
const chainIds = config.chains?.map(({ id }) => id).join(",");
const query: Record<string, string> = {};
if (chainIds) query.chainIds = chainIds;
return await ClaimsService.#fetch(async () => api.v4.claims({ address }).get({ query }));
}
}
38 changes: 35 additions & 3 deletions src/api/services/interaction.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { api as clientApi } from "src/api/index.client";
import { fetchWithLogs } from "../utils";
import { ZyfiService } from "./zyfi.service";

export abstract class InteractionService {
static async #fetch<R, T extends { data: R; status: number; response: Response }>(
Expand All @@ -14,33 +15,64 @@ export abstract class InteractionService {
return data;
}

static async get(
//TODO: template type the transaction
name: "supply",
payload: Parameters<typeof clientApi.v4.interaction.transaction.get>[0]["query"],
options?: { sponsor?: boolean },
) {
const response = await fetch(`/transaction/${name}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ ...payload, ...options }),
});

//TODO: use template type to get correct response type
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
return (await response.json()) as any;
}

/**
* Client side
* @param chainId
* @param protocolId
* @param identifier
*/
static async getTarget(chainId: number, protocolId: string, identifier: string) {
static async getTargets(chainId: number, protocolId: string, identifier: string) {
const targets = await InteractionService.#fetch(() =>
clientApi.v4.interaction.targets.get({
query: { chainId, protocolId, identifier },
}),
);

//TODO: opportunity/:id/target instead of taking the first result and expecting unique
return targets?.[0];
return targets;
}

/**
* Client side
*/
static async getTransaction(payload: Parameters<typeof clientApi.v4.interaction.transaction.get>[0]["query"]) {
static async getTransaction(
payload: Parameters<typeof clientApi.v4.interaction.transaction.get>[0]["query"],
sponsor?: boolean,
) {
const transaction = await InteractionService.#fetch(() =>
clientApi.v4.interaction.transaction.get({
query: payload,
}),
);

if (sponsor && !transaction.approved) {
transaction.approval = await ZyfiService.wrapAndPrepareTx({ ...transaction.approval, from: payload.userAddress });
} else if (sponsor) {
transaction.transaction = await ZyfiService.wrapAndPrepareTx({
...transaction.transaction,
from: payload.userAddress,
});
}

return transaction;
}

Expand Down
10 changes: 10 additions & 0 deletions src/api/services/opportunity/opportunity.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ export abstract class OpportunityService {
return { opportunities: opportunities.filter(o => o !== null), count };
}

// ─── Get Featured opportunities ──────────────────────────────────────────────

static async getFeatured(
overrides?: Parameters<typeof api.v4.opportunities.index.get>[0]["query"],
): Promise<{ opportunities: Opportunity[]; count: number }> {
if (config.opportunity.featured.enabled)
return await OpportunityService.getMany({ items: config.opportunity.featured.length, ...overrides });
return { opportunities: [], count: 0 };
}

// ─── Get Opportunities with campaign ──────────────────────────────────────────────

static async getCampaignsByParams(query: {
Expand Down
16 changes: 14 additions & 2 deletions src/api/services/protocol.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,31 @@ export abstract class ProtocolService {
);
}

// ─── Get First Protocol ──────────────────────────────────────────────

static async getById(id: string) {
return await ProtocolService.#fetch(async () =>
api.v4
.protocols({
id,
})
.get(),
);
}

// ─── Get Many Protocols from request ──────────────────────────────────

static async getManyFromRequest(request: Request) {
const query: Parameters<typeof api.v4.protocols.index.get>[0]["query"] =
ProtocolService.#getQueryFromRequest(request);
const protocols = await ProtocolService.#fetch(async () =>
api.v4.protocols.index.get({
query: Object.assign({ ...query }, config.tags?.[0] ? { tags: config.tags?.[0] } : {}),
query: Object.assign({ ...query }, config.tags?.[0] ? { opportunityTag: config.tags?.[0] } : {}),
}),
);
const count = await ProtocolService.#fetch(async () =>
api.v4.protocols.count.get({
query: Object.assign({ ...query }, config.tags?.[0] ? { tags: config.tags?.[0] } : {}),
query: Object.assign({ ...query }, config.tags?.[0] ? { opportunityTag: config.tags?.[0] } : {}),
}),
);

Expand Down
6 changes: 5 additions & 1 deletion src/api/services/reward.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import config from "merkl.config";
import { api } from "../index.server";
import { fetchWithLogs } from "../utils";

Expand Down Expand Up @@ -44,9 +45,12 @@ export abstract class RewardService {
}

static async getForUser(address: string, chainId: number) {
const chainIds = config.chains?.map(({ id }) => id).join(",");
const query: Record<string, string> = { chainId };
if (chainIds) query.chainIds = chainIds;
return await RewardService.#fetch(async () =>
api.v4.users({ address }).rewards.breakdowns.get({
query: { chainId },
query,
}),
);
}
Expand Down
Loading
Loading