@merkl/api 0.21.31 → 0.21.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/eden/index.d.ts +89 -9
- package/dist/src/engine/deprecated/erc20SubTypeProcessors/helpers/factoryFinder.js +1 -1
- package/dist/src/engine/deprecated/erc20SubTypeProcessors/implementations/curveProcessor.js +6 -2
- package/dist/src/engine/deprecated/erc20SubTypeProcessors/implementations/processorMapping.js +1 -0
- package/dist/src/engine/deprecated/erc20SubTypeProcessors/tokenTypeToProtocolAndAction.js +4 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/euler/tvl.js +5 -1
- package/dist/src/engine/implementations/Erc20/subTypes/index.d.ts +2 -1
- package/dist/src/engine/implementations/Erc20/subTypes/index.js +1 -0
- package/dist/src/guards/BackOffice.guard.d.ts +1 -1
- package/dist/src/guards/BackOffice.guard.js +1 -1
- package/dist/src/guards/Engine.guard.d.ts +1 -1
- package/dist/src/guards/Engine.guard.js +2 -3
- package/dist/src/guards/VerifyJwt.guard.d.ts +10 -0
- package/dist/src/guards/VerifyJwt.guard.js +13 -0
- package/dist/src/index.d.ts +35 -3
- package/dist/src/index.js +2 -0
- package/dist/src/modules/v4/accounting/accounting.controller.js +7 -13
- package/dist/src/modules/v4/authentication/authentication.controller.d.ts +52 -0
- package/dist/src/modules/v4/authentication/authentication.controller.js +23 -0
- package/dist/src/modules/v4/authentication/authentication.model.d.ts +10 -0
- package/dist/src/modules/v4/authentication/authentication.model.js +6 -0
- package/dist/src/modules/v4/authentication/authentication.service.d.ts +10 -0
- package/dist/src/modules/v4/authentication/authentication.service.js +31 -0
- package/dist/src/modules/v4/blacklist/blacklist.controller.js +2 -2
- package/dist/src/modules/v4/cache/cache.repository.d.ts +3 -0
- package/dist/src/modules/v4/cache/cache.repository.js +9 -0
- package/dist/src/modules/v4/cache/cache.service.d.ts +3 -0
- package/dist/src/modules/v4/cache/cache.service.js +9 -0
- package/dist/src/modules/v4/opportunity/opportunity.controller.js +1 -3
- package/dist/src/modules/v4/reward/reward.controller.d.ts +3 -3
- package/dist/src/modules/v4/reward/reward.controller.js +14 -5
- package/dist/src/modules/v4/reward/reward.model.d.ts +1 -1
- package/dist/src/modules/v4/reward/reward.model.js +1 -1
- package/dist/src/modules/v4/router.d.ts +35 -3
- package/dist/src/modules/v4/router.js +3 -1
- package/dist/src/modules/v4/token/token.controller.js +1 -1
- package/dist/src/modules/v4/uniswap/uniswap.controller.js +1 -1
- package/dist/src/utils/decodeCalls.js +15 -5
- package/dist/src/utils/generateCardName.js +1 -0
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +4 -3
package/dist/src/eden/index.d.ts
CHANGED
@@ -2906,9 +2906,9 @@ declare const eden: {
|
|
2906
2906
|
query: {
|
2907
2907
|
items?: number | undefined;
|
2908
2908
|
page?: number | undefined;
|
2909
|
+
campaignIds?: string[] | undefined;
|
2909
2910
|
address: string;
|
2910
2911
|
chainId: number;
|
2911
|
-
campaignIds: string[];
|
2912
2912
|
};
|
2913
2913
|
fetch?: RequestInit | undefined;
|
2914
2914
|
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
@@ -2926,9 +2926,9 @@ declare const eden: {
|
|
2926
2926
|
query: {
|
2927
2927
|
items?: number | undefined;
|
2928
2928
|
page?: number | undefined;
|
2929
|
+
campaignIds?: string[] | undefined;
|
2929
2930
|
address: string;
|
2930
2931
|
chainId: number;
|
2931
|
-
campaignIds: string[];
|
2932
2932
|
};
|
2933
2933
|
fetch?: RequestInit | undefined;
|
2934
2934
|
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
@@ -2944,9 +2944,9 @@ declare const eden: {
|
|
2944
2944
|
query: {
|
2945
2945
|
items?: number | undefined;
|
2946
2946
|
page?: number | undefined;
|
2947
|
+
campaignIds?: string[] | undefined;
|
2947
2948
|
address: string;
|
2948
2949
|
chainId: number;
|
2949
|
-
campaignIds: string[];
|
2950
2950
|
};
|
2951
2951
|
fetch?: RequestInit | undefined;
|
2952
2952
|
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
@@ -4951,6 +4951,30 @@ declare const eden: {
|
|
4951
4951
|
};
|
4952
4952
|
};
|
4953
4953
|
};
|
4954
|
+
authlogin: {
|
4955
|
+
post: (body: {
|
4956
|
+
message: string;
|
4957
|
+
address: string;
|
4958
|
+
signature: string;
|
4959
|
+
}, options?: {
|
4960
|
+
headers?: Record<string, unknown> | undefined;
|
4961
|
+
query?: Record<string, unknown> | undefined;
|
4962
|
+
fetch?: RequestInit | undefined;
|
4963
|
+
} | undefined) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
4964
|
+
200: void;
|
4965
|
+
}>>;
|
4966
|
+
};
|
4967
|
+
auth: {
|
4968
|
+
revoke: {
|
4969
|
+
delete: (body?: unknown, options?: {
|
4970
|
+
headers?: Record<string, unknown> | undefined;
|
4971
|
+
query?: Record<string, unknown> | undefined;
|
4972
|
+
fetch?: RequestInit | undefined;
|
4973
|
+
} | undefined) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
4974
|
+
200: void;
|
4975
|
+
}>>;
|
4976
|
+
};
|
4977
|
+
};
|
4954
4978
|
};
|
4955
4979
|
v3: {
|
4956
4980
|
app: {
|
@@ -8919,9 +8943,9 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
8919
8943
|
query: {
|
8920
8944
|
items?: number | undefined;
|
8921
8945
|
page?: number | undefined;
|
8946
|
+
campaignIds?: string[] | undefined;
|
8922
8947
|
address: string;
|
8923
8948
|
chainId: number;
|
8924
|
-
campaignIds: string[];
|
8925
8949
|
};
|
8926
8950
|
headers: unknown;
|
8927
8951
|
response: {
|
@@ -8944,9 +8968,9 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
8944
8968
|
query: {
|
8945
8969
|
items?: number | undefined;
|
8946
8970
|
page?: number | undefined;
|
8971
|
+
campaignIds?: string[] | undefined;
|
8947
8972
|
address: string;
|
8948
8973
|
chainId: number;
|
8949
|
-
campaignIds: string[];
|
8950
8974
|
};
|
8951
8975
|
headers: unknown;
|
8952
8976
|
response: {
|
@@ -8967,9 +8991,9 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
8967
8991
|
query: {
|
8968
8992
|
items?: number | undefined;
|
8969
8993
|
page?: number | undefined;
|
8994
|
+
campaignIds?: string[] | undefined;
|
8970
8995
|
address: string;
|
8971
8996
|
chainId: number;
|
8972
|
-
campaignIds: string[];
|
8973
8997
|
};
|
8974
8998
|
headers: unknown;
|
8975
8999
|
response: {
|
@@ -11623,6 +11647,38 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
11623
11647
|
};
|
11624
11648
|
};
|
11625
11649
|
};
|
11650
|
+
} & {
|
11651
|
+
v4: {
|
11652
|
+
authlogin: {
|
11653
|
+
post: {
|
11654
|
+
body: {
|
11655
|
+
message: string;
|
11656
|
+
address: string;
|
11657
|
+
signature: string;
|
11658
|
+
};
|
11659
|
+
params: {};
|
11660
|
+
query: unknown;
|
11661
|
+
headers: unknown;
|
11662
|
+
response: {
|
11663
|
+
200: void;
|
11664
|
+
};
|
11665
|
+
};
|
11666
|
+
};
|
11667
|
+
} & {
|
11668
|
+
auth: {
|
11669
|
+
revoke: {
|
11670
|
+
delete: {
|
11671
|
+
body: unknown;
|
11672
|
+
params: {};
|
11673
|
+
query: unknown;
|
11674
|
+
headers: unknown;
|
11675
|
+
response: {
|
11676
|
+
200: void;
|
11677
|
+
};
|
11678
|
+
};
|
11679
|
+
};
|
11680
|
+
};
|
11681
|
+
};
|
11626
11682
|
} & {
|
11627
11683
|
v3: {
|
11628
11684
|
app: {
|
@@ -15342,9 +15398,9 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
15342
15398
|
query: {
|
15343
15399
|
items?: number | undefined;
|
15344
15400
|
page?: number | undefined;
|
15401
|
+
campaignIds?: string[] | undefined;
|
15345
15402
|
address: string;
|
15346
15403
|
chainId: number;
|
15347
|
-
campaignIds: string[];
|
15348
15404
|
};
|
15349
15405
|
fetch?: RequestInit | undefined;
|
15350
15406
|
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
@@ -15362,9 +15418,9 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
15362
15418
|
query: {
|
15363
15419
|
items?: number | undefined;
|
15364
15420
|
page?: number | undefined;
|
15421
|
+
campaignIds?: string[] | undefined;
|
15365
15422
|
address: string;
|
15366
15423
|
chainId: number;
|
15367
|
-
campaignIds: string[];
|
15368
15424
|
};
|
15369
15425
|
fetch?: RequestInit | undefined;
|
15370
15426
|
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
@@ -15380,9 +15436,9 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
15380
15436
|
query: {
|
15381
15437
|
items?: number | undefined;
|
15382
15438
|
page?: number | undefined;
|
15439
|
+
campaignIds?: string[] | undefined;
|
15383
15440
|
address: string;
|
15384
15441
|
chainId: number;
|
15385
|
-
campaignIds: string[];
|
15386
15442
|
};
|
15387
15443
|
fetch?: RequestInit | undefined;
|
15388
15444
|
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
@@ -17387,6 +17443,30 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
17387
17443
|
};
|
17388
17444
|
};
|
17389
17445
|
};
|
17446
|
+
authlogin: {
|
17447
|
+
post: (body: {
|
17448
|
+
message: string;
|
17449
|
+
address: string;
|
17450
|
+
signature: string;
|
17451
|
+
}, options?: {
|
17452
|
+
headers?: Record<string, unknown> | undefined;
|
17453
|
+
query?: Record<string, unknown> | undefined;
|
17454
|
+
fetch?: RequestInit | undefined;
|
17455
|
+
} | undefined) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
17456
|
+
200: void;
|
17457
|
+
}>>;
|
17458
|
+
};
|
17459
|
+
auth: {
|
17460
|
+
revoke: {
|
17461
|
+
delete: (body?: unknown, options?: {
|
17462
|
+
headers?: Record<string, unknown> | undefined;
|
17463
|
+
query?: Record<string, unknown> | undefined;
|
17464
|
+
fetch?: RequestInit | undefined;
|
17465
|
+
} | undefined) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
17466
|
+
200: void;
|
17467
|
+
}>>;
|
17468
|
+
};
|
17469
|
+
};
|
17390
17470
|
};
|
17391
17471
|
v3: {
|
17392
17472
|
app: {
|
@@ -26,7 +26,7 @@ const factoryAddresses = {
|
|
26
26
|
"0x5Ea9DD3b6f042A34Df818C6c1324BC5A7c61427a": Erc20SubType.curve, // Curve Corn 2crypto Factory
|
27
27
|
"0xd7E72f3615aa65b92A4DBdC211E296a35512988B": Erc20SubType.curveNPool, // Curve Corn Stableswap Factory
|
28
28
|
"0x7Ca46A636b02D4aBC66883D7FF164bDE506DC66a": Erc20SubType.curveNPool, // Curve Corn 3crypto Factory
|
29
|
-
"0xbC0797015fcFc47d9C1856639CaE50D0e69FbEE8": Erc20SubType.
|
29
|
+
"0xbC0797015fcFc47d9C1856639CaE50D0e69FbEE8": Erc20SubType.curveTricrypto, // Curve Arbitrum 3crypto Factory
|
30
30
|
"0xA5961898870943c68037F6848d2D866Ed2016bcB": Erc20SubType.curveNPool, // Curve Base
|
31
31
|
"0xB255D6A720BB7c39fee173cE22113397119cB930": Erc20SubType.katana, // Katana Ronin
|
32
32
|
"0x29372c22459a4e373851798bFd6808e71EA34A71": Erc20SubType.punchswap, // Punchswap Flow EVM
|
@@ -2,6 +2,7 @@ import { Erc20SubType } from "@/engine/implementations/Erc20/subTypes";
|
|
2
2
|
import { generateCardName } from "@/utils/generateCardName";
|
3
3
|
import { BN2Number } from "@sdk";
|
4
4
|
import { GenericProcessor } from "../GenericProcessor";
|
5
|
+
import { getCrossCurveTokenPrice } from "../helpers/getCrossCurveTokenPrice";
|
5
6
|
export class CurveProcessor extends GenericProcessor {
|
6
7
|
rounds = {
|
7
8
|
round1: [
|
@@ -50,8 +51,11 @@ export class CurveProcessor extends GenericProcessor {
|
|
50
51
|
}
|
51
52
|
if (type === Erc20SubType.curve_2) {
|
52
53
|
const prices = [];
|
53
|
-
for (const symbol of Object.
|
54
|
-
|
54
|
+
for (const [address, symbol] of Object.entries(typeInfo.poolTokens)) {
|
55
|
+
let price = (await pricer.get({ symbol: symbol })) ?? 0;
|
56
|
+
if (price === 0) {
|
57
|
+
price = await getCrossCurveTokenPrice(address);
|
58
|
+
}
|
55
59
|
prices.push(price);
|
56
60
|
}
|
57
61
|
let minPrice = Math.min(...prices);
|
@@ -128,6 +128,10 @@ export const tokenTypeToProtocolAndAction = {
|
|
128
128
|
protocol: "curve",
|
129
129
|
action: OpportunityAction.POOL,
|
130
130
|
},
|
131
|
+
[Erc20SubType.curveTricrypto]: {
|
132
|
+
protocol: "curve",
|
133
|
+
action: OpportunityAction.POOL,
|
134
|
+
},
|
131
135
|
[Erc20SubType.sake_borrowing]: {
|
132
136
|
protocol: "sake",
|
133
137
|
action: OpportunityAction.BORROW,
|
@@ -37,7 +37,11 @@ export class EulerTVLBuilder {
|
|
37
37
|
if (!underlyingToken.decimals || !underlyingToken.price) {
|
38
38
|
throw new Error(`Missing decimals or price for token ${underlylingTokenAddress}`);
|
39
39
|
}
|
40
|
-
|
40
|
+
let tvl = bigIntToNumber(totalAssets, underlyingToken.decimals) * underlyingToken.price;
|
41
|
+
// If TVL is zero, set to 0.01
|
42
|
+
if (tvl === 0) {
|
43
|
+
tvl = 0.01;
|
44
|
+
}
|
41
45
|
tvls.push({
|
42
46
|
campaign,
|
43
47
|
tvl,
|
@@ -113,4 +113,5 @@ export var Erc20SubType;
|
|
113
113
|
Erc20SubType["lendle_vaults"] = "lendle_vaults";
|
114
114
|
Erc20SubType["termmax"] = "termmax";
|
115
115
|
Erc20SubType["hyperswap"] = "hyperswap";
|
116
|
+
Erc20SubType["curveTricrypto"] = "curveTricrypto";
|
116
117
|
})(Erc20SubType || (Erc20SubType = {}));
|
@@ -4,4 +4,4 @@ export declare const AuthorizationHeadersDto: import("@sinclair/typebox").TObjec
|
|
4
4
|
export type AuthorizationHeaders = typeof AuthorizationHeadersDto.static;
|
5
5
|
export declare function BackOfficeGuard({ headers }: {
|
6
6
|
headers: AuthorizationHeaders;
|
7
|
-
}):
|
7
|
+
}): void;
|
@@ -3,7 +3,7 @@ import { t } from "elysia";
|
|
3
3
|
export const AuthorizationHeadersDto = t.Object({
|
4
4
|
authorization: t.String(),
|
5
5
|
});
|
6
|
-
export
|
6
|
+
export function BackOfficeGuard({ headers }) {
|
7
7
|
if (headers.authorization !== `Bearer ${process.env.BACKOFFICE_SECRET}`) {
|
8
8
|
throw new UnauthorizedError();
|
9
9
|
}
|
@@ -4,4 +4,4 @@ export declare const AuthorizationHeadersDto: import("@sinclair/typebox").TObjec
|
|
4
4
|
export type AuthorizationHeaders = typeof AuthorizationHeadersDto.static;
|
5
5
|
export declare function EngineGuard({ headers }: {
|
6
6
|
headers: AuthorizationHeaders;
|
7
|
-
}):
|
7
|
+
}): void;
|
@@ -3,8 +3,7 @@ import { t } from "elysia";
|
|
3
3
|
export const AuthorizationHeadersDto = t.Object({
|
4
4
|
authorization: t.String(),
|
5
5
|
});
|
6
|
-
export
|
7
|
-
if (headers.authorization !== `Bearer ${process.env.ENGINE_SECRET}`)
|
6
|
+
export function EngineGuard({ headers }) {
|
7
|
+
if (headers.authorization !== `Bearer ${process.env.ENGINE_SECRET}`)
|
8
8
|
throw new UnauthorizedError();
|
9
|
-
}
|
10
9
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { UnauthorizedError } from "@/errors";
|
2
|
+
import { CacheService } from "@/modules/v4/cache/cache.service";
|
3
|
+
import { t } from "elysia";
|
4
|
+
import { jwtVerify } from "jose";
|
5
|
+
export const JwtCookieDto = t.Cookie({
|
6
|
+
jwt: t.String(),
|
7
|
+
});
|
8
|
+
const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
|
9
|
+
export async function VerifyJwtGuard({ cookie }) {
|
10
|
+
const decodedJwt = await jwtVerify(cookie.jwt.value, JWT_SECRET);
|
11
|
+
if (!decodedJwt.payload.jti || (await CacheService.sIsMember("token:revoked", decodedJwt.payload.jti)))
|
12
|
+
throw new UnauthorizedError("Failed to verify JWT.");
|
13
|
+
}
|
package/dist/src/index.d.ts
CHANGED
@@ -3342,9 +3342,9 @@ declare const app: Elysia<"", false, {
|
|
3342
3342
|
query: {
|
3343
3343
|
items?: number | undefined;
|
3344
3344
|
page?: number | undefined;
|
3345
|
+
campaignIds?: string[] | undefined;
|
3345
3346
|
address: string;
|
3346
3347
|
chainId: number;
|
3347
|
-
campaignIds: string[];
|
3348
3348
|
};
|
3349
3349
|
headers: unknown;
|
3350
3350
|
response: {
|
@@ -3367,9 +3367,9 @@ declare const app: Elysia<"", false, {
|
|
3367
3367
|
query: {
|
3368
3368
|
items?: number | undefined;
|
3369
3369
|
page?: number | undefined;
|
3370
|
+
campaignIds?: string[] | undefined;
|
3370
3371
|
address: string;
|
3371
3372
|
chainId: number;
|
3372
|
-
campaignIds: string[];
|
3373
3373
|
};
|
3374
3374
|
headers: unknown;
|
3375
3375
|
response: {
|
@@ -3390,9 +3390,9 @@ declare const app: Elysia<"", false, {
|
|
3390
3390
|
query: {
|
3391
3391
|
items?: number | undefined;
|
3392
3392
|
page?: number | undefined;
|
3393
|
+
campaignIds?: string[] | undefined;
|
3393
3394
|
address: string;
|
3394
3395
|
chainId: number;
|
3395
|
-
campaignIds: string[];
|
3396
3396
|
};
|
3397
3397
|
headers: unknown;
|
3398
3398
|
response: {
|
@@ -6046,6 +6046,38 @@ declare const app: Elysia<"", false, {
|
|
6046
6046
|
};
|
6047
6047
|
};
|
6048
6048
|
};
|
6049
|
+
} & {
|
6050
|
+
v4: {
|
6051
|
+
authlogin: {
|
6052
|
+
post: {
|
6053
|
+
body: {
|
6054
|
+
message: string;
|
6055
|
+
address: string;
|
6056
|
+
signature: string;
|
6057
|
+
};
|
6058
|
+
params: {};
|
6059
|
+
query: unknown;
|
6060
|
+
headers: unknown;
|
6061
|
+
response: {
|
6062
|
+
200: void;
|
6063
|
+
};
|
6064
|
+
};
|
6065
|
+
};
|
6066
|
+
} & {
|
6067
|
+
auth: {
|
6068
|
+
revoke: {
|
6069
|
+
delete: {
|
6070
|
+
body: unknown;
|
6071
|
+
params: {};
|
6072
|
+
query: unknown;
|
6073
|
+
headers: unknown;
|
6074
|
+
response: {
|
6075
|
+
200: void;
|
6076
|
+
};
|
6077
|
+
};
|
6078
|
+
};
|
6079
|
+
};
|
6080
|
+
};
|
6049
6081
|
} & {
|
6050
6082
|
v3: {
|
6051
6083
|
app: {
|
package/dist/src/index.js
CHANGED
@@ -10,6 +10,8 @@ import { v2 } from "./routes/v2/router";
|
|
10
10
|
import { v3 } from "./routes/v3/router";
|
11
11
|
import { errorHandler } from "./utils/error";
|
12
12
|
import { log } from "./utils/logger";
|
13
|
+
if (!process.env.JWT_SECRET)
|
14
|
+
throw new Error("Environment variable JWT_SECRET is missing.");
|
13
15
|
// Axios with bun workaround
|
14
16
|
axios.defaults.headers.common["Accept-Encoding"] = "gzip";
|
15
17
|
const PORT = process.env.PORT || 3000;
|
@@ -7,30 +7,24 @@ export const AccountingController = new Elysia({ prefix: "/accounting", detail:
|
|
7
7
|
.get("/", async ({ query }) => await AccountingService.findMany(query), {
|
8
8
|
query: GetTransactionsQueryModel,
|
9
9
|
headers: AuthorizationHeadersDto,
|
10
|
-
beforeHandle:
|
11
|
-
await BackOfficeGuard({ headers });
|
12
|
-
},
|
10
|
+
beforeHandle: BackOfficeGuard,
|
13
11
|
})
|
14
12
|
.group("/revenues", app => {
|
15
13
|
return app
|
16
14
|
.get("", async () => await AccountingService.getAllRevenueBreakdownByChain(), {
|
17
15
|
headers: AuthorizationHeadersDto,
|
18
|
-
beforeHandle:
|
19
|
-
await BackOfficeGuard({ headers });
|
20
|
-
},
|
16
|
+
beforeHandle: BackOfficeGuard,
|
21
17
|
})
|
22
18
|
.get("/per-month/:year/:month", async ({ params }) => await AccountingService.getMonthlyRevenue(params.year, params.month), {
|
23
19
|
params: DateDto,
|
24
20
|
headers: AuthorizationHeadersDto,
|
25
|
-
beforeHandle:
|
26
|
-
await BackOfficeGuard({ headers });
|
27
|
-
},
|
21
|
+
beforeHandle: BackOfficeGuard,
|
28
22
|
})
|
29
23
|
.get("/chains/:chainId", async ({ params }) => await AccountingService.getRevenueByChain(params.chainId), {
|
30
24
|
params: ChainDto,
|
31
25
|
headers: AuthorizationHeadersDto,
|
32
26
|
beforeHandle: async ({ params, headers }) => {
|
33
|
-
|
27
|
+
BackOfficeGuard({ headers });
|
34
28
|
throwOnUnsupportedChainId(params.chainId);
|
35
29
|
},
|
36
30
|
})
|
@@ -38,7 +32,7 @@ export const AccountingController = new Elysia({ prefix: "/accounting", detail:
|
|
38
32
|
params: RevenuesDto,
|
39
33
|
headers: AuthorizationHeadersDto,
|
40
34
|
beforeHandle: async ({ params, headers }) => {
|
41
|
-
|
35
|
+
BackOfficeGuard({ headers });
|
42
36
|
throwOnUnsupportedChainId(params.chainId);
|
43
37
|
},
|
44
38
|
});
|
@@ -50,7 +44,7 @@ export const AccountingController = new Elysia({ prefix: "/accounting", detail:
|
|
50
44
|
params: TokensDto,
|
51
45
|
headers: AuthorizationHeadersDto,
|
52
46
|
beforeHandle: async ({ params, headers }) => {
|
53
|
-
|
47
|
+
BackOfficeGuard({ headers });
|
54
48
|
params.tokenAddress = throwOnInvalidRequiredAddress(params.tokenAddress);
|
55
49
|
throwOnUnsupportedChainId(params.chainId);
|
56
50
|
},
|
@@ -59,7 +53,7 @@ export const AccountingController = new Elysia({ prefix: "/accounting", detail:
|
|
59
53
|
params: TokensDateDto,
|
60
54
|
headers: AuthorizationHeadersDto,
|
61
55
|
beforeHandle: async ({ params, headers }) => {
|
62
|
-
|
56
|
+
BackOfficeGuard({ headers });
|
63
57
|
params.tokenAddress = throwOnInvalidRequiredAddress(params.tokenAddress);
|
64
58
|
throwOnUnsupportedChainId(params.chainId);
|
65
59
|
},
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import Elysia from "elysia";
|
2
|
+
export declare const AuthController: Elysia<"/auth", false, {
|
3
|
+
decorator: {};
|
4
|
+
store: {};
|
5
|
+
derive: {};
|
6
|
+
resolve: {};
|
7
|
+
}, {
|
8
|
+
type: {};
|
9
|
+
error: {};
|
10
|
+
}, {
|
11
|
+
schema: {};
|
12
|
+
macro: {};
|
13
|
+
macroFn: {};
|
14
|
+
}, {
|
15
|
+
authlogin: {
|
16
|
+
post: {
|
17
|
+
body: {
|
18
|
+
message: string;
|
19
|
+
address: string;
|
20
|
+
signature: string;
|
21
|
+
};
|
22
|
+
params: {};
|
23
|
+
query: unknown;
|
24
|
+
headers: unknown;
|
25
|
+
response: {
|
26
|
+
200: void;
|
27
|
+
};
|
28
|
+
};
|
29
|
+
};
|
30
|
+
} & {
|
31
|
+
auth: {
|
32
|
+
revoke: {
|
33
|
+
delete: {
|
34
|
+
body: unknown;
|
35
|
+
params: {};
|
36
|
+
query: unknown;
|
37
|
+
headers: unknown;
|
38
|
+
response: {
|
39
|
+
200: void;
|
40
|
+
};
|
41
|
+
};
|
42
|
+
};
|
43
|
+
};
|
44
|
+
}, {
|
45
|
+
derive: {};
|
46
|
+
resolve: {};
|
47
|
+
schema: {};
|
48
|
+
}, {
|
49
|
+
derive: {};
|
50
|
+
resolve: {};
|
51
|
+
schema: {};
|
52
|
+
}>;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { JwtCookieDto, VerifyJwtGuard } from "@/guards/VerifyJwt.guard";
|
2
|
+
import Elysia from "elysia";
|
3
|
+
import { LoginDto } from "./authentication.model";
|
4
|
+
import { AuthService } from "./authentication.service";
|
5
|
+
const authService = new AuthService();
|
6
|
+
export const AuthController = new Elysia({
|
7
|
+
prefix: "/auth",
|
8
|
+
detail: { tags: ["Authentication"] },
|
9
|
+
})
|
10
|
+
.post("login", async ({ body, cookie: { jwt } }) => {
|
11
|
+
jwt.value = await authService.login(body);
|
12
|
+
jwt.sameSite = true;
|
13
|
+
jwt.path = "/";
|
14
|
+
jwt.httpOnly = true;
|
15
|
+
jwt.secure = true;
|
16
|
+
jwt.maxAge = 2 * 60 * 60; // 2h
|
17
|
+
return;
|
18
|
+
}, { body: LoginDto })
|
19
|
+
.delete("/revoke", async ({ cookie: { jwt } }) => {
|
20
|
+
await authService.revokeToken(jwt.value);
|
21
|
+
jwt.remove();
|
22
|
+
return;
|
23
|
+
}, { beforeHandle: VerifyJwtGuard, cookie: JwtCookieDto });
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export declare const LoginDto: import("@sinclair/typebox").TObject<{
|
2
|
+
address: import("@sinclair/typebox").TString;
|
3
|
+
message: import("@sinclair/typebox").TString;
|
4
|
+
signature: import("@sinclair/typebox").TString;
|
5
|
+
}>;
|
6
|
+
export type MessageModel = {
|
7
|
+
address: `0x${string}`;
|
8
|
+
message: string;
|
9
|
+
signature: `0x${string}`;
|
10
|
+
};
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import type { MessageModel } from "./authentication.model";
|
2
|
+
export declare class AuthService {
|
3
|
+
#private;
|
4
|
+
login(message: MessageModel): Promise<string>;
|
5
|
+
generateJwt(user: {
|
6
|
+
address: string;
|
7
|
+
creatorId: string | null;
|
8
|
+
}): Promise<string>;
|
9
|
+
revokeToken(jwt: string): Promise<void>;
|
10
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import { UnauthorizedError } from "@/errors";
|
2
|
+
import { SignJWT, decodeJwt } from "jose";
|
3
|
+
import { http, createPublicClient } from "viem";
|
4
|
+
import { mainnet } from "viem/chains";
|
5
|
+
import { CacheService } from "../cache/cache.service";
|
6
|
+
import { UserService } from "../user/user.service";
|
7
|
+
export class AuthService {
|
8
|
+
#publicClient = createPublicClient({ chain: mainnet, transport: http() });
|
9
|
+
#encodedJwtSecret = new TextEncoder().encode(process.env.JWT_SECRET);
|
10
|
+
async login(message) {
|
11
|
+
if (!this.#publicClient.verifyMessage(message))
|
12
|
+
throw new UnauthorizedError("Failed to verify the message signature.");
|
13
|
+
let user = await UserService.findUnique(message.address);
|
14
|
+
if (!user)
|
15
|
+
user = await UserService.create({ address: message.address, tags: [] });
|
16
|
+
return await this.generateJwt(user);
|
17
|
+
}
|
18
|
+
async generateJwt(user) {
|
19
|
+
return await new SignJWT({ creator: user.creatorId })
|
20
|
+
.setProtectedHeader({ alg: "HS256" })
|
21
|
+
.setExpirationTime("2h")
|
22
|
+
.setAudience(user.address)
|
23
|
+
.setIssuer("merkl")
|
24
|
+
.setSubject("studio")
|
25
|
+
.setJti(Bun.randomUUIDv7())
|
26
|
+
.sign(this.#encodedJwtSecret);
|
27
|
+
}
|
28
|
+
async revokeToken(jwt) {
|
29
|
+
return await CacheService.sAdd("token:revoked", decodeJwt(jwt).jti);
|
30
|
+
}
|
31
|
+
}
|
@@ -23,7 +23,7 @@ export const BlacklistController = new Elysia({ prefix: "/blacklists", detail: {
|
|
23
23
|
body: AddBlacklistDto,
|
24
24
|
headers: AuthorizationHeadersDto,
|
25
25
|
beforeHandle: async ({ body, headers }) => {
|
26
|
-
|
26
|
+
BackOfficeGuard({ headers });
|
27
27
|
body.userAddress = throwOnInvalidRequiredAddress(body.userAddress);
|
28
28
|
body.poolAddress = throwOnInvalidRequiredAddress(body.poolAddress ?? NULL_ADDRESS);
|
29
29
|
throwOnUnsupportedChainId(body.chainId);
|
@@ -35,7 +35,7 @@ export const BlacklistController = new Elysia({ prefix: "/blacklists", detail: {
|
|
35
35
|
params: RemoveBlacklistDto,
|
36
36
|
headers: AuthorizationHeadersDto,
|
37
37
|
beforeHandle: async ({ headers, params }) => {
|
38
|
-
|
38
|
+
BackOfficeGuard({ headers });
|
39
39
|
params.address = throwOnInvalidRequiredAddress(params.address);
|
40
40
|
},
|
41
41
|
detail: { hide: true },
|
@@ -2,4 +2,7 @@ export declare abstract class CacheRepository {
|
|
2
2
|
static set(ttl: number, key: string, value: string): Promise<void>;
|
3
3
|
static ttl(key: string): Promise<number>;
|
4
4
|
static get(key: string): Promise<string | null>;
|
5
|
+
static sAdd(sName: string, sValue: string): Promise<void>;
|
6
|
+
static sRem(sName: string, sValue: string): Promise<void>;
|
7
|
+
static sIsMember(sName: string, sValue: string): Promise<any>;
|
5
8
|
}
|