@merkl/api 0.21.32 → 0.21.34

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.
Files changed (51) hide show
  1. package/dist/database/api/.generated/drizzle/schema.d.ts +7 -7
  2. package/dist/database/api/.generated/drizzle/schema.js +1 -1
  3. package/dist/database/api/.generated/drizzle/schema.ts +1 -1
  4. package/dist/database/api/.generated/edge.js +5 -4
  5. package/dist/database/api/.generated/index-browser.js +2 -1
  6. package/dist/database/api/.generated/index.d.ts +2 -1
  7. package/dist/database/api/.generated/index.js +5 -4
  8. package/dist/database/api/.generated/package.json +1 -1
  9. package/dist/database/api/.generated/schema.prisma +1 -0
  10. package/dist/database/api/.generated/wasm.js +2 -1
  11. package/dist/src/eden/index.d.ts +185 -3
  12. package/dist/src/engine/deprecated/erc20SubTypeProcessors/helpers/factoryFinder.js +1 -1
  13. package/dist/src/engine/deprecated/erc20SubTypeProcessors/implementations/curveProcessor.js +6 -2
  14. package/dist/src/engine/deprecated/erc20SubTypeProcessors/implementations/processorMapping.js +1 -0
  15. package/dist/src/engine/deprecated/erc20SubTypeProcessors/tokenTypeToProtocolAndAction.js +4 -0
  16. package/dist/src/engine/implementations/Erc20/subTypes/implementations/euler/tvl.js +5 -1
  17. package/dist/src/engine/implementations/Erc20/subTypes/index.d.ts +2 -1
  18. package/dist/src/engine/implementations/Erc20/subTypes/index.js +1 -0
  19. package/dist/src/guards/BackOffice.guard.d.ts +1 -1
  20. package/dist/src/guards/BackOffice.guard.js +1 -1
  21. package/dist/src/guards/Engine.guard.d.ts +1 -1
  22. package/dist/src/guards/Engine.guard.js +2 -3
  23. package/dist/src/guards/VerifyJwt.guard.d.ts +10 -0
  24. package/dist/src/guards/VerifyJwt.guard.js +13 -0
  25. package/dist/src/index.d.ts +73 -1
  26. package/dist/src/index.js +2 -0
  27. package/dist/src/modules/v4/accounting/accounting.controller.js +7 -13
  28. package/dist/src/modules/v4/authentication/authentication.controller.d.ts +52 -0
  29. package/dist/src/modules/v4/authentication/authentication.controller.js +23 -0
  30. package/dist/src/modules/v4/authentication/authentication.model.d.ts +10 -0
  31. package/dist/src/modules/v4/authentication/authentication.model.js +6 -0
  32. package/dist/src/modules/v4/authentication/authentication.service.d.ts +10 -0
  33. package/dist/src/modules/v4/authentication/authentication.service.js +31 -0
  34. package/dist/src/modules/v4/blacklist/blacklist.controller.js +2 -2
  35. package/dist/src/modules/v4/cache/cache.repository.d.ts +3 -0
  36. package/dist/src/modules/v4/cache/cache.repository.js +9 -0
  37. package/dist/src/modules/v4/cache/cache.service.d.ts +3 -0
  38. package/dist/src/modules/v4/cache/cache.service.js +9 -0
  39. package/dist/src/modules/v4/opportunity/opportunity.controller.d.ts +44 -2
  40. package/dist/src/modules/v4/opportunity/opportunity.controller.js +6 -6
  41. package/dist/src/modules/v4/opportunity/opportunity.model.d.ts +5 -0
  42. package/dist/src/modules/v4/opportunity/opportunity.model.js +4 -0
  43. package/dist/src/modules/v4/reward/reward.controller.js +13 -4
  44. package/dist/src/modules/v4/router.d.ts +73 -1
  45. package/dist/src/modules/v4/router.js +3 -1
  46. package/dist/src/modules/v4/token/token.controller.js +1 -1
  47. package/dist/src/modules/v4/uniswap/uniswap.controller.js +1 -1
  48. package/dist/src/utils/decodeCalls.js +15 -5
  49. package/dist/src/utils/generateCardName.js +1 -0
  50. package/dist/tsconfig.package.tsbuildinfo +1 -1
  51. package/package.json +4 -3
@@ -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,6 @@
1
+ import { t } from "elysia";
2
+ export const LoginDto = t.Object({
3
+ address: t.String({ pattern: "^(0x)?[0-9a-fA-F]{40}$" }),
4
+ message: t.String(),
5
+ signature: t.String({ pattern: "^(0x)?[0-9a-fA-F]{130}$" }),
6
+ });
@@ -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
- await BackOfficeGuard({ headers });
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
- await BackOfficeGuard({ headers });
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
  }
@@ -10,4 +10,13 @@ export class CacheRepository {
10
10
  static async get(key) {
11
11
  return await withRetry(withTimeout, [redisClient.get(key), REDIS_READ_TIMEOUT], REDIS_RETRIES);
12
12
  }
13
+ static async sAdd(sName, sValue) {
14
+ await withRetry(withTimeout, [redisClient.sAdd(sName, sValue), REDIS_WRITE_TIMEOUT], REDIS_RETRIES);
15
+ }
16
+ static async sRem(sName, sValue) {
17
+ await withRetry(withTimeout, [redisClient.sRem(sName, sValue), REDIS_WRITE_TIMEOUT], REDIS_RETRIES);
18
+ }
19
+ static async sIsMember(sName, sValue) {
20
+ return await withRetry(withTimeout, [redisClient.sIsMember(sName, sValue), REDIS_READ_TIMEOUT], REDIS_RETRIES);
21
+ }
13
22
  }
@@ -6,4 +6,7 @@ export declare abstract class CacheService {
6
6
  static keyAndTTL<Fn extends (...args: Args) => Promise<unknown>, Args extends unknown[]>(fn: Fn, ...args: Args): Promise<[string, number]>;
7
7
  static set<Fn extends (...args: Args) => Promise<unknown>, Args extends unknown[], T extends Awaited<ReturnType<Fn>>>(ttl: number, fn: Fn, ...args: Args): Promise<T>;
8
8
  static get<Fn extends (...args: Args) => Promise<unknown>, Args extends unknown[], T extends Awaited<ReturnType<Fn>>>(fn: Fn, args: Args): Promise<T | null>;
9
+ static sAdd(sName: string, sValue: string): Promise<void>;
10
+ static sRem(sName: string, sValue: string): Promise<void>;
11
+ static sIsMember(sName: string, sValue: string): Promise<any>;
9
12
  }
@@ -47,4 +47,13 @@ export class CacheService {
47
47
  return null;
48
48
  return CacheService.#uncompress(cached);
49
49
  }
50
+ static async sAdd(sName, sValue) {
51
+ return CacheRepository.sAdd(sName, sValue);
52
+ }
53
+ static async sRem(sName, sValue) {
54
+ return CacheRepository.sRem(sName, sValue);
55
+ }
56
+ static async sIsMember(sName, sValue) {
57
+ return await CacheRepository.sIsMember(sName, sValue);
58
+ }
50
59
  }
@@ -1135,6 +1135,45 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
1135
1135
  };
1136
1136
  };
1137
1137
  };
1138
+ } & {
1139
+ opportunities: {
1140
+ ":id": {
1141
+ patch: {
1142
+ body: {
1143
+ tags?: string[] | undefined;
1144
+ };
1145
+ params: {
1146
+ id: string;
1147
+ };
1148
+ query: unknown;
1149
+ headers: {
1150
+ authorization: string;
1151
+ };
1152
+ response: {
1153
+ 200: {
1154
+ status: import("@db/api").$Enums.Status;
1155
+ type: string;
1156
+ name: string;
1157
+ description: string;
1158
+ id: string;
1159
+ tags: string[];
1160
+ identifier: string;
1161
+ action: import("@db/api").$Enums.OpportunityAction;
1162
+ manualOverrides: import("@db/api").$Enums.OpportunityManualOverride[];
1163
+ chainId: number;
1164
+ howToSteps: string[];
1165
+ depositUrl: string | null;
1166
+ explorerAddress: string | null;
1167
+ mainProtocolId: string | null;
1168
+ tvl: number;
1169
+ apr: number;
1170
+ dailyRewards: number;
1171
+ lastCampaignCreatedAt: Date;
1172
+ };
1173
+ };
1174
+ };
1175
+ };
1176
+ };
1138
1177
  } & {
1139
1178
  opportunities: {
1140
1179
  ":id": {
@@ -1147,6 +1186,7 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
1147
1186
  howToSteps?: string[] | undefined;
1148
1187
  depositUrl?: string | undefined;
1149
1188
  explorerAddress?: string | undefined;
1189
+ mainProtocolId?: string | undefined;
1150
1190
  };
1151
1191
  params: {
1152
1192
  id: string;
@@ -1186,7 +1226,7 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
1186
1226
  ":id": {
1187
1227
  override: {
1188
1228
  delete: {
1189
- body: ("name" | "description" | "action" | "howToSteps" | "depositUrl" | "explorerAddress")[];
1229
+ body: ("name" | "description" | "action" | "howToSteps" | "depositUrl" | "explorerAddress" | "mainProtocolId")[];
1190
1230
  params: {
1191
1231
  id: string;
1192
1232
  };
@@ -1287,7 +1327,9 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
1287
1327
  authorization: string;
1288
1328
  };
1289
1329
  query: unknown;
1290
- params: unknown;
1330
+ params: {
1331
+ id: string;
1332
+ };
1291
1333
  cookie: unknown;
1292
1334
  response: {};
1293
1335
  };
@@ -6,16 +6,14 @@ import { log } from "@/utils/logger";
6
6
  import { throwOnUnsupportedActionList } from "@/utils/throw";
7
7
  import { ChainId } from "@sdk";
8
8
  import Elysia, { t } from "elysia";
9
- import { CreateOpportunityDto, GetOpportunitiesQueryDto, GetOpportunityQueryDto, OpportunityAggregateFieldDto, OpportunityDeleteOverrideDto, OpportunityOverrideDto, OpportunityResourceDto, OpportunityUniqueDto, OpportunityUniqueUpdateDto, OpportunityWithCampaignsResourceDto, } from "./opportunity.model";
9
+ import { CreateOpportunityDto, GetOpportunitiesQueryDto, GetOpportunityQueryDto, OpportunityAggregateFieldDto, OpportunityDeleteOverrideDto, OpportunityOverrideDto, OpportunityResourceDto, OpportunityUniqueDto, OpportunityUniqueUpdateDto, OpportunityWithCampaignsResourceDto, UpdateOpportunityDto, } from "./opportunity.model";
10
10
  import { OpportunityService } from "./opportunity.service";
11
11
  import { transformId } from "./transform-id.pipe";
12
12
  import { validateId } from "./validate-id.pipe";
13
13
  // ─── Opportunities Controller ────────────────────────────────────────────────
14
14
  export const OpportunityController = new Elysia({
15
15
  prefix: "/opportunities",
16
- detail: {
17
- tags: ["Opportunities"],
18
- },
16
+ detail: { tags: ["Opportunities"] },
19
17
  })
20
18
  // ─── Get All Opportunities ───────────────────────────────────────────
21
19
  .get("/", async ({ query }) => OpportunityService.findMany(query), {
@@ -179,11 +177,13 @@ export const OpportunityController = new Elysia({
179
177
  }
180
178
  }, { params: OpportunityUniqueUpdateDto })
181
179
  // ─── Override An Opportunity Field ───────────────────────────────────
180
+ .guard({ params: OpportunityUniqueDto })
181
+ .patch("/:id", async ({ params, body }) => await OpportunityService.update(params.id, body), {
182
+ body: UpdateOpportunityDto,
183
+ })
182
184
  .patch("/:id/override", async ({ params, body }) => await OpportunityService.override(params.id, body), {
183
- params: OpportunityUniqueDto,
184
185
  body: OpportunityOverrideDto,
185
186
  })
186
187
  .delete("/:id/override", async ({ params, body }) => await OpportunityService.deleteOverrides(params.id, body), {
187
- params: OpportunityUniqueDto,
188
188
  body: OpportunityDeleteOverrideDto,
189
189
  });
@@ -388,6 +388,7 @@ export declare const OpportunityOverrideDto: import("@sinclair/typebox").TObject
388
388
  SWAP: "SWAP";
389
389
  INVALID: "INVALID";
390
390
  }>>;
391
+ mainProtocolId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
391
392
  }>;
392
393
  export declare const OpportunityDeleteOverrideDto: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TEnum<{
393
394
  name: "name";
@@ -396,7 +397,11 @@ export declare const OpportunityDeleteOverrideDto: import("@sinclair/typebox").T
396
397
  action: "action";
397
398
  description: "description";
398
399
  howToSteps: "howToSteps";
400
+ mainProtocolId: "mainProtocolId";
399
401
  }>>;
402
+ export declare const UpdateOpportunityDto: import("@sinclair/typebox").TObject<{
403
+ tags: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
404
+ }>;
400
405
  export type GetOpportunitiesQueryModel = typeof GetOpportunitiesQueryDto.static;
401
406
  export type GetOpportunityQueryModel = typeof GetOpportunityQueryDto.static;
402
407
  export type CreateOpportunityModel = typeof CreateOpportunityDto.static;
@@ -124,5 +124,9 @@ export const OpportunityOverrideDto = t.Object({
124
124
  depositUrl: t.Optional(t.String({ format: "uri" })),
125
125
  explorerAddress: t.Optional(t.String({ format: "uri" })),
126
126
  action: t.Optional(t.Enum(OpportunityAction)),
127
+ mainProtocolId: t.Optional(t.String()),
127
128
  });
128
129
  export const OpportunityDeleteOverrideDto = t.Array(t.Enum(OpportunityManualOverride));
130
+ export const UpdateOpportunityDto = t.Object({
131
+ tags: t.Optional(t.Array(t.String())),
132
+ });
@@ -68,11 +68,20 @@ export const RewardController = new Elysia({ prefix: "/rewards", detail: { tags:
68
68
  query.campaignIds = query?.campaignIds?.flatMap(x => x.split(","));
69
69
  throwOnUnsupportedChainId(query.chainId);
70
70
  },
71
- detail: { hide: true },
72
71
  })
73
- .get("/", async ({ query }) => await RewardService.breakdownForToken(query))
74
- .get("/total", async ({ query }) => await RewardService.totalForToken(query))
75
- .get("/count", async ({ query }) => await RewardService.countForToken(query));
72
+ .get("/", async ({ query }) => await RewardService.breakdownForToken(query), {
73
+ detail: {
74
+ description: "Returns the all the address that received rewards of a given token, sorted by descending amounts",
75
+ },
76
+ })
77
+ .get("/total", async ({ query }) => await RewardService.totalForToken(query), {
78
+ detail: { description: "Returns the total amount distributed for a given token" },
79
+ })
80
+ .get("/count", async ({ query }) => await RewardService.countForToken(query), {
81
+ detail: {
82
+ description: "Returns the number of recipients that earned rewards in a given token",
83
+ },
84
+ });
76
85
  })
77
86
  .group("/engine", {
78
87
  headers: AuthorizationHeadersDto,
@@ -1150,6 +1150,45 @@ export declare const v4: Elysia<"/v4", false, {
1150
1150
  };
1151
1151
  };
1152
1152
  };
1153
+ } & {
1154
+ opportunities: {
1155
+ ":id": {
1156
+ patch: {
1157
+ body: {
1158
+ tags?: string[] | undefined;
1159
+ };
1160
+ params: {
1161
+ id: string;
1162
+ };
1163
+ query: unknown;
1164
+ headers: {
1165
+ authorization: string;
1166
+ };
1167
+ response: {
1168
+ 200: {
1169
+ status: import("@db/api").$Enums.Status;
1170
+ type: string;
1171
+ name: string;
1172
+ description: string;
1173
+ id: string;
1174
+ tags: string[];
1175
+ identifier: string;
1176
+ action: import("@db/api").$Enums.OpportunityAction;
1177
+ manualOverrides: import("@db/api").$Enums.OpportunityManualOverride[];
1178
+ chainId: number;
1179
+ howToSteps: string[];
1180
+ depositUrl: string | null;
1181
+ explorerAddress: string | null;
1182
+ mainProtocolId: string | null;
1183
+ tvl: number;
1184
+ apr: number;
1185
+ dailyRewards: number;
1186
+ lastCampaignCreatedAt: Date;
1187
+ };
1188
+ };
1189
+ };
1190
+ };
1191
+ };
1153
1192
  } & {
1154
1193
  opportunities: {
1155
1194
  ":id": {
@@ -1162,6 +1201,7 @@ export declare const v4: Elysia<"/v4", false, {
1162
1201
  howToSteps?: string[] | undefined;
1163
1202
  depositUrl?: string | undefined;
1164
1203
  explorerAddress?: string | undefined;
1204
+ mainProtocolId?: string | undefined;
1165
1205
  };
1166
1206
  params: {
1167
1207
  id: string;
@@ -1201,7 +1241,7 @@ export declare const v4: Elysia<"/v4", false, {
1201
1241
  ":id": {
1202
1242
  override: {
1203
1243
  delete: {
1204
- body: ("name" | "description" | "action" | "howToSteps" | "depositUrl" | "explorerAddress")[];
1244
+ body: ("name" | "description" | "action" | "howToSteps" | "depositUrl" | "explorerAddress" | "mainProtocolId")[];
1205
1245
  params: {
1206
1246
  id: string;
1207
1247
  };
@@ -5916,6 +5956,38 @@ export declare const v4: Elysia<"/v4", false, {
5916
5956
  };
5917
5957
  };
5918
5958
  };
5959
+ } & {
5960
+ v4: {
5961
+ authlogin: {
5962
+ post: {
5963
+ body: {
5964
+ message: string;
5965
+ address: string;
5966
+ signature: string;
5967
+ };
5968
+ params: {};
5969
+ query: unknown;
5970
+ headers: unknown;
5971
+ response: {
5972
+ 200: void;
5973
+ };
5974
+ };
5975
+ };
5976
+ } & {
5977
+ auth: {
5978
+ revoke: {
5979
+ delete: {
5980
+ body: unknown;
5981
+ params: {};
5982
+ query: unknown;
5983
+ headers: unknown;
5984
+ response: {
5985
+ 200: void;
5986
+ };
5987
+ };
5988
+ };
5989
+ };
5990
+ };
5919
5991
  }, {
5920
5992
  derive: {};
5921
5993
  resolve: {};
@@ -30,6 +30,7 @@ import { RedisInstrumentation } from "@opentelemetry/instrumentation-redis-4";
30
30
  import { AlwaysOffSampler, BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";
31
31
  import { PrismaInstrumentation } from "@prisma/instrumentation";
32
32
  import Elysia from "elysia";
33
+ import { AuthController } from "./authentication/authentication.controller";
33
34
  import { ReferralController } from "./referral/referral.controller";
34
35
  import { TurtleController } from "./turtle/turtle.controller";
35
36
  // ─── V4 Router ───────────────────────────────────────────────────────────────
@@ -88,4 +89,5 @@ export const v4 = new Elysia({ tags: ["v4"], prefix: "/v4" })
88
89
  .use(CreatorController)
89
90
  .use(ReferralController)
90
91
  .use(UniswapController)
91
- .use(TurtleController);
92
+ .use(TurtleController)
93
+ .use(AuthController);
@@ -94,7 +94,7 @@ export const TokenController = new Elysia({ prefix: "/tokens", detail: { tags: [
94
94
  body: CreateTokenDto,
95
95
  headers: AuthorizationHeadersDto,
96
96
  beforeHandle: async ({ headers, body }) => {
97
- await BackOfficeGuard({ headers });
97
+ BackOfficeGuard({ headers });
98
98
  body.address = throwOnInvalidRequiredAddress(body.address);
99
99
  throwOnUnsupportedChainId(body.chainId);
100
100
  },
@@ -91,7 +91,7 @@ export const UniswapController = new Elysia({
91
91
  params: ChainUniqueDto,
92
92
  headers: AuthorizationHeadersDto,
93
93
  beforeHandle: async ({ params, headers }) => {
94
- await BackOfficeGuard({ headers });
94
+ BackOfficeGuard({ headers });
95
95
  if (!UniV4ChainIdArray.includes(params.chainId))
96
96
  throw new UnsupportedNetwork(params.chainId);
97
97
  },
@@ -193,11 +193,21 @@ export function decodeReturnValue(returnData, key, type) {
193
193
  case "coin2":
194
194
  return CurveInterface.decodeFunctionResult("coins", returnData)[0];
195
195
  case "N_COINS":
196
- try {
197
- return CurveStableSwapNGInterface.decodeFunctionResult("N_COINS", returnData)[0];
198
- }
199
- catch (e) {
200
- return 2;
196
+ switch (type) {
197
+ case Erc20SubType.curveTricrypto:
198
+ try {
199
+ return CurveStableSwapNGInterface.decodeFunctionResult("N_COINS", returnData)[0];
200
+ }
201
+ catch (e) {
202
+ return 3;
203
+ }
204
+ default:
205
+ try {
206
+ return CurveStableSwapNGInterface.decodeFunctionResult("N_COINS", returnData)[0];
207
+ }
208
+ catch (e) {
209
+ return 2;
210
+ }
201
211
  }
202
212
  case "balances":
203
213
  return CurveStableSwapNGInterface.decodeFunctionResult("balances", returnData)[0];
@@ -160,6 +160,7 @@ export function generateCardName(type, typeInfo, campaign, symbols = [""], displ
160
160
  }
161
161
  return `${typeInfo.name}`;
162
162
  case Erc20SubType.curveNPool:
163
+ case Erc20SubType.curveTricrypto:
163
164
  return `Curve ${typeInfo.name}`;
164
165
  case Erc20SubType.vicuna: {
165
166
  const parsedName = typeInfo.name.split(" ");