@merkl/api 0.18.6 → 0.18.8

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.
@@ -616,13 +616,6 @@ declare const eden: {
616
616
  price?: number | null | undefined;
617
617
  })[];
618
618
  chain: {
619
- Explorer: {
620
- id: string;
621
- type: import("@db/api").$Enums.ExplorerType;
622
- url: string;
623
- chainId: number;
624
- }[];
625
- } & {
626
619
  id: number;
627
620
  name: string;
628
621
  icon: string;
@@ -4075,13 +4068,6 @@ declare const eden: {
4075
4068
  price?: number | null | undefined;
4076
4069
  })[];
4077
4070
  chain: {
4078
- Explorer: {
4079
- id: string;
4080
- type: import("@db/api").$Enums.ExplorerType;
4081
- url: string;
4082
- chainId: number;
4083
- }[];
4084
- } & {
4085
4071
  id: number;
4086
4072
  name: string;
4087
4073
  icon: string;
@@ -8000,13 +7986,6 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
8000
7986
  price?: number | null | undefined;
8001
7987
  })[];
8002
7988
  chain: {
8003
- Explorer: {
8004
- id: string;
8005
- type: import("@db/api").$Enums.ExplorerType;
8006
- url: string;
8007
- chainId: number;
8008
- }[];
8009
- } & {
8010
7989
  id: number;
8011
7990
  name: string;
8012
7991
  icon: string;
@@ -13291,13 +13270,6 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
13291
13270
  price?: number | null | undefined;
13292
13271
  })[];
13293
13272
  chain: {
13294
- Explorer: {
13295
- id: string;
13296
- type: import("@db/api").$Enums.ExplorerType;
13297
- url: string;
13298
- chainId: number;
13299
- }[];
13300
- } & {
13301
13273
  id: number;
13302
13274
  name: string;
13303
13275
  icon: string;
@@ -16750,13 +16722,6 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
16750
16722
  price?: number | null | undefined;
16751
16723
  })[];
16752
16724
  chain: {
16753
- Explorer: {
16754
- id: string;
16755
- type: import("@db/api").$Enums.ExplorerType;
16756
- url: string;
16757
- chainId: number;
16758
- }[];
16759
- } & {
16760
16725
  id: number;
16761
16726
  name: string;
16762
16727
  icon: string;
@@ -3,7 +3,7 @@ import { OpportunityAction } from "@db/api";
3
3
  export class AjnaMetadata {
4
4
  async build(computeChainId, params, subType) {
5
5
  try {
6
- const [collateral, quote] = await TokenService.getManyOrCreate([
6
+ const [collateral, quote] = await TokenService.findManyOrCreate([
7
7
  {
8
8
  chainId: computeChainId,
9
9
  address: params.collateralToken,
@@ -3,7 +3,7 @@ import { OpportunityAction } from "@db/api";
3
3
  export class BadgerMetadata {
4
4
  async build(computeChainId, params) {
5
5
  try {
6
- const [token] = await TokenService.getManyOrCreate([{ chainId: computeChainId, address: params.targetToken }]);
6
+ const [token] = await TokenService.findManyOrCreate([{ chainId: computeChainId, address: params.targetToken }]);
7
7
  if (!token)
8
8
  throw new Error("Failed to fetch tokens");
9
9
  return {
@@ -408,13 +408,6 @@ declare const app: Elysia<"", false, {
408
408
  price?: number | null | undefined;
409
409
  })[];
410
410
  chain: {
411
- Explorer: {
412
- id: string;
413
- type: import("@db/api").$Enums.ExplorerType;
414
- url: string;
415
- chainId: number;
416
- }[];
417
- } & {
418
411
  id: number;
419
412
  name: string;
420
413
  icon: string;
@@ -23,14 +23,16 @@ export async function getUniswapV4Pools() {
23
23
  log.info(`found ${storedPoolsPerChain.length} already stored pools on ${NETWORK_LABELS[chainId]}`);
24
24
  let fromBlock;
25
25
  if (storedPoolsPerChain.length > 0) {
26
- fromBlock = Math.max(...storedPools.map(x => x.fetchAtBlock)) + 1;
26
+ fromBlock = Math.max(...storedPoolsPerChain.map(x => x.fetchAtBlock)) + 1;
27
27
  }
28
28
  else {
29
29
  fromBlock = await getContractCreationBlock(poolManagerAddress, jsonRPCprovider);
30
30
  }
31
31
  const toBlock = await jsonRPCprovider.getBlockNumber();
32
32
  const logs = await safeFetchLogs(chainId, // TODO: rm type enforcing
33
- [UniswapV4PoolManagerInterface.getEventTopic("Initialize")], [poolManagerAddress], fromBlock, toBlock);
33
+ [UniswapV4PoolManagerInterface.getEventTopic("Initialize")], [poolManagerAddress], fromBlock, toBlock
34
+ // fromBlock + 10_000
35
+ );
34
36
  const decodedPools = await Promise.all(logs.map(async (log) => {
35
37
  const [id, currency0, currency1, fee, tickSpacing, hooks] = UniswapV4PoolManagerInterface.decodeEventLog("Initialize", log.data, log.topics);
36
38
  // Respect typing
@@ -78,6 +80,9 @@ export async function getUniswapV4Pools() {
78
80
  if (pool.currency0 !== NULL_ADDRESS) {
79
81
  try {
80
82
  symbolCurrency0 = ERC20Interface.decodeFunctionResult("symbol", resCurrencies[index].returnData)[0];
83
+ if (symbolCurrency0.includes("/") || symbolCurrency0.includes("\u0000")) {
84
+ symbolCurrency0 = "INVALID";
85
+ }
81
86
  decimalsCurrency0 = ERC20Interface.decodeFunctionResult("decimals", resCurrencies[index + 1].returnData)[0];
82
87
  }
83
88
  catch {
@@ -94,6 +99,9 @@ export async function getUniswapV4Pools() {
94
99
  if (pool.currency1 !== NULL_ADDRESS) {
95
100
  try {
96
101
  symbolCurrency1 = ERC20Interface.decodeFunctionResult("symbol", resCurrencies[index + 2].returnData)[0];
102
+ if (symbolCurrency1.includes("/") || symbolCurrency1.includes("\u0000")) {
103
+ symbolCurrency1 = "INVALID";
104
+ }
97
105
  decimalsCurrency1 = ERC20Interface.decodeFunctionResult("decimals", resCurrencies[index + 3].returnData)[0];
98
106
  }
99
107
  catch {
@@ -135,24 +143,27 @@ export async function getUniswapV4Pools() {
135
143
  });
136
144
  // Update the API database
137
145
  const tableData = Object.values(pools).flatMap(pools => Object.values(pools));
138
- if (Object.values(pools).length > 0) {
139
- try {
140
- await apiDbClient.logged.createMany({
141
- data: tableData.map(pool => ({
142
- fetchAtBlock: pool.fetchedAtBlock,
143
- caughtFromAddress: UniswapV4Addresses[pool.chainId]?.PoolManager ?? NULL_ADDRESS,
144
- chainId: pool.chainId,
145
- entityData: pool,
146
- id: Bun.hash(`${pool.poolId}-${pool.chainId}`).toString(),
147
- type: LoggedEntityType.UNISWAP_V4,
148
- })),
149
- });
150
- log.info("✅ successfully saved vaults to API database (`Logged` table)");
151
- // }
152
- }
153
- catch (e) {
154
- log.error("getUniswapV4Pools/LoggedTableUpdate", e);
155
- throw new Error("Error while saving UniV4 pools to API database (`Logged` table)");
146
+ for (const chainId of UNIV4_CHAINIDS) {
147
+ if (tableData.filter(p => p.chainId === chainId).length > 0) {
148
+ try {
149
+ await apiDbClient.logged.createMany({
150
+ data: tableData
151
+ .filter(point => point.chainId === chainId)
152
+ .map(pool => ({
153
+ fetchAtBlock: pool.fetchedAtBlock,
154
+ caughtFromAddress: UniswapV4Addresses[pool.chainId]?.PoolManager ?? NULL_ADDRESS,
155
+ chainId: pool.chainId,
156
+ entityData: pool,
157
+ id: Bun.hash(`${pool.poolId}-${pool.chainId}`).toString(),
158
+ type: LoggedEntityType.UNISWAP_V4,
159
+ })),
160
+ });
161
+ log.info(`✅ successfully saved vaults to API database ('Logged' table) on ${NETWORK_LABELS[chainId]}`);
162
+ }
163
+ catch (e) {
164
+ log.error("getUniswapV4Pools/LoggedTableUpdate", e);
165
+ throw new Error(`Error while saving UniV4 pools to API database ('Logged' table) on ${NETWORK_LABELS[chainId]}`);
166
+ }
156
167
  }
157
168
  }
158
169
  log.info(`✅ successfully fetched ${tableData.length} new pool(s) on UniswapV4`);
@@ -183,7 +183,7 @@ export class CampaignRepository {
183
183
  static async upsert(campaign) {
184
184
  const campaignType = CampaignService.getTypeFromV3(campaign.type);
185
185
  try {
186
- const [rewardToken] = await TokenService.getManyOrCreate([
186
+ const [rewardToken] = await TokenService.findManyOrCreate([
187
187
  { chainId: campaign.chainId, address: campaign.rewardTokenAddress },
188
188
  ]);
189
189
  if (!rewardToken) {
@@ -51,8 +51,8 @@ export class EnsoService {
51
51
  return await Promise.all(route.map(async (r) => {
52
52
  switch (r.action) {
53
53
  case "deposit": {
54
- const tokensIn = await TokenService.getManyOrCreate(r.tokenIn.map(t => ({ address: t, chainId })));
55
- const [tokenOut] = await TokenService.getManyOrCreate(r.tokenOut.map(t => ({ address: t, chainId })));
54
+ const tokensIn = await TokenService.findManyOrCreate(r.tokenIn.map(t => ({ address: t, chainId })));
55
+ const [tokenOut] = await TokenService.findManyOrCreate(r.tokenOut.map(t => ({ address: t, chainId })));
56
56
  return {
57
57
  action: "deposit",
58
58
  tokens: tokensIn.filter(a => !!a),
@@ -60,8 +60,8 @@ export class EnsoService {
60
60
  };
61
61
  }
62
62
  case "swap": {
63
- const [from] = await TokenService.getManyOrCreate(r.tokenIn.map(t => ({ address: t, chainId })));
64
- const [to] = await TokenService.getManyOrCreate(r.tokenOut.map(t => ({ address: t, chainId })));
63
+ const [from] = await TokenService.findManyOrCreate(r.tokenIn.map(t => ({ address: t, chainId })));
64
+ const [to] = await TokenService.findManyOrCreate(r.tokenOut.map(t => ({ address: t, chainId })));
65
65
  return { action: "swap", from: from, to: to };
66
66
  }
67
67
  }
@@ -106,7 +106,7 @@ export class EnsoService {
106
106
  amountIn: [fromTokenAmount.toString()],
107
107
  slippage: options.slippage?.toString(),
108
108
  });
109
- const [LpToken] = await TokenService.getManyOrCreate([{ address: identifier, chainId }]);
109
+ const [LpToken] = await TokenService.findManyOrCreate([{ address: identifier, chainId }]);
110
110
  const depositValue = await TokenService.getValue([{ ...LpToken, amount: BigInt(quote.amountOut) }]);
111
111
  const actions = await EnsoService.getActions(chainId, quote.route, BigInt(quote.amountOut));
112
112
  return { transaction: tx, depositValue: depositValue, actions };
@@ -54,7 +54,7 @@ export class KyberZapService {
54
54
  const actions = [];
55
55
  const processors = {
56
56
  ACTION_TYPE_PROTOCOL_FEE: async ({ protocolFee: { tokens: zapTokens } }) => {
57
- const tokens = await TokenService.getManyOrCreate(zapTokens.map(({ address }) => ({ address, chainId })));
57
+ const tokens = await TokenService.findManyOrCreate(zapTokens.map(({ address }) => ({ address, chainId })));
58
58
  return [
59
59
  {
60
60
  action: "fee",
@@ -65,7 +65,7 @@ export class KyberZapService {
65
65
  ACTION_TYPE_AGGREGATOR_SWAP: async ({ aggregatorSwap: { swaps } }) => {
66
66
  const swapActions = [];
67
67
  for (const { tokenIn, tokenOut } of swaps) {
68
- const [from, to] = await TokenService.getManyOrCreate([
68
+ const [from, to] = await TokenService.findManyOrCreate([
69
69
  { address: tokenIn.address, chainId },
70
70
  { address: tokenOut.address, chainId },
71
71
  ]);
@@ -80,7 +80,7 @@ export class KyberZapService {
80
80
  ACTION_TYPE_POOL_SWAP: async ({ poolSwap: { swaps } }) => {
81
81
  const swapActions = [];
82
82
  for (const { tokenIn, tokenOut } of swaps) {
83
- const [from, to] = await TokenService.getManyOrCreate([
83
+ const [from, to] = await TokenService.findManyOrCreate([
84
84
  { address: tokenIn.address, chainId },
85
85
  { address: tokenOut.address, chainId },
86
86
  ]);
@@ -93,7 +93,7 @@ export class KyberZapService {
93
93
  return swapActions;
94
94
  },
95
95
  ACTION_TYPE_ADD_LIQUIDITY: async ({ addLiquidity: { tokens: zapTokens } }) => {
96
- const tokens = await TokenService.getManyOrCreate(zapTokens.map(({ address }) => ({ address, chainId })));
96
+ const tokens = await TokenService.findManyOrCreate(zapTokens.map(({ address }) => ({ address, chainId })));
97
97
  return [
98
98
  {
99
99
  action: "deposit",
@@ -124,7 +124,7 @@ export class KyberZapService {
124
124
  chainId,
125
125
  });
126
126
  const actions = await KyberZapService.getActions(chainId, route.zapDetails.actions);
127
- const [tokenIn] = await TokenService.getManyOrCreate([{ address: fromTokenAddress, chainId }]);
127
+ const [tokenIn] = await TokenService.findManyOrCreate([{ address: fromTokenAddress, chainId }]);
128
128
  const deposit = actions.findLast(({ action }) => action === "deposit");
129
129
  const tokenInValue = await TokenService.getValue([{ ...tokenIn, amount: fromTokenAmount }]);
130
130
  const depositValue = await TokenService.getValue(deposit.tokens);
@@ -263,13 +263,6 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
263
263
  price?: number | null | undefined;
264
264
  })[];
265
265
  chain: {
266
- Explorer: {
267
- id: string;
268
- type: import("@db/api").$Enums.ExplorerType;
269
- url: string;
270
- chainId: number;
271
- }[];
272
- } & {
273
266
  id: number;
274
267
  name: string;
275
268
  icon: string;
@@ -175,13 +175,6 @@ export declare abstract class OpportunityRepository {
175
175
  }) | null>;
176
176
  static findUniqueOrThrow(id: string, withTest?: boolean, withCampaigns?: boolean): Promise<{
177
177
  Chain: {
178
- Explorer: {
179
- id: string;
180
- type: import("@db/api").$Enums.ExplorerType;
181
- url: string;
182
- chainId: number;
183
- }[];
184
- } & {
185
178
  id: number;
186
179
  name: string;
187
180
  icon: string;
@@ -551,13 +551,6 @@ export declare abstract class OpportunityService {
551
551
  price?: number | null | undefined;
552
552
  })[];
553
553
  chain: {
554
- Explorer: {
555
- id: string;
556
- type: import("@db/api").$Enums.ExplorerType;
557
- url: string;
558
- chainId: number;
559
- }[];
560
- } & {
561
554
  id: number;
562
555
  name: string;
563
556
  icon: string;
@@ -723,13 +716,6 @@ export declare abstract class OpportunityService {
723
716
  price?: number | null | undefined;
724
717
  })[];
725
718
  chain: {
726
- Explorer: {
727
- id: string;
728
- type: import("@db/api").$Enums.ExplorerType;
729
- url: string;
730
- chainId: number;
731
- }[];
732
- } & {
733
719
  id: number;
734
720
  name: string;
735
721
  icon: string;
@@ -891,13 +877,6 @@ export declare abstract class OpportunityService {
891
877
  price?: number | null | undefined;
892
878
  })[];
893
879
  chain: {
894
- Explorer: {
895
- id: string;
896
- type: import("@db/api").$Enums.ExplorerType;
897
- url: string;
898
- chainId: number;
899
- }[];
900
- } & {
901
880
  id: number;
902
881
  name: string;
903
882
  icon: string;
@@ -938,13 +917,6 @@ export declare abstract class OpportunityService {
938
917
  price?: number | null | undefined;
939
918
  })[];
940
919
  chain: {
941
- Explorer: {
942
- id: string;
943
- type: import("@db/api").$Enums.ExplorerType;
944
- url: string;
945
- chainId: number;
946
- }[];
947
- } & {
948
920
  id: number;
949
921
  name: string;
950
922
  icon: string;
@@ -69,7 +69,7 @@ export class OpportunityService {
69
69
  identifier: campaign.opportunityIdentifier,
70
70
  type: campaignType,
71
71
  });
72
- const tokens = (await TokenService.getManyOrCreate(metadata.tokens)).filter(t => t !== undefined);
72
+ const tokens = (await TokenService.findManyOrCreate(metadata.tokens)).filter(t => t !== undefined);
73
73
  const params = JSON.parse(campaign.params);
74
74
  const now = moment().unix();
75
75
  const opportunity = {
@@ -6,7 +6,7 @@ export class PriceRepository {
6
6
  static async findManyPriceSources(query) {
7
7
  return await apiDbClient.priceSource.findMany({
8
8
  where: {
9
- method: query.method ?? undefined,
9
+ method: query?.method ?? undefined,
10
10
  },
11
11
  });
12
12
  }
@@ -321,7 +321,7 @@ export class RewardService {
321
321
  token = await TokenService.findUniqueOrThrow({ address: rewardToken, chainId });
322
322
  }
323
323
  catch {
324
- await TokenService.create(await TokenService.fetchOnChain({ address: rewardToken, chainId }));
324
+ await TokenService.findManyOrCreate([{ address: rewardToken, chainId }]);
325
325
  token = await TokenService.findUniqueOrThrow({ address: rewardToken, chainId });
326
326
  }
327
327
  const campaignDailyValue = await TokenService.getValueByTokenId(tokenToAmount);
@@ -278,13 +278,6 @@ export declare const v4: Elysia<"/v4", false, {
278
278
  price?: number | null | undefined;
279
279
  })[];
280
280
  chain: {
281
- Explorer: {
282
- id: string;
283
- type: import("@db/api").$Enums.ExplorerType;
284
- url: string;
285
- chainId: number;
286
- }[];
287
- } & {
288
281
  id: number;
289
282
  name: string;
290
283
  icon: string;
@@ -77,6 +77,8 @@ export declare abstract class TokenRepository {
77
77
  * @param chainId
78
78
  */
79
79
  static updateAddressPrices(address: string, price: number, chainId?: number): Promise<import("database/api/.generated/runtime/library").GetBatchResult>;
80
+ static updateMissingIconsPerSymbol(symbol: string, icon: string): Promise<import("database/api/.generated/runtime/library").GetBatchResult>;
81
+ static fetchIconFromCoingeckoTicker(coingeckoTicker: string): Promise<any>;
80
82
  static findChains(): Promise<Record<string, ChainId>>;
81
83
  /**
82
84
  * create a token on database
@@ -2,6 +2,7 @@ import { getTokenInfo } from "@/libs/tokens/tokenInfo";
2
2
  import { executeSimple } from "@/utils/execute";
3
3
  import { apiDbClient } from "@/utils/prisma";
4
4
  import { NETWORK_LABELS } from "@sdk";
5
+ import axios from "axios";
5
6
  export class TokenRepository {
6
7
  static #transformQueryToPrismaFilters(query) {
7
8
  const ids = query.id ? query.id.map(id => ({ id })) : [];
@@ -129,6 +130,18 @@ export class TokenRepository {
129
130
  },
130
131
  });
131
132
  }
133
+ static async updateMissingIconsPerSymbol(symbol, icon) {
134
+ return await apiDbClient.token.updateMany({
135
+ data: { icon },
136
+ where: {
137
+ symbol: symbol,
138
+ icon: "",
139
+ },
140
+ });
141
+ }
142
+ static async fetchIconFromCoingeckoTicker(coingeckoTicker) {
143
+ return (await axios.get(`https://api.coingecko.com/api/v3/coins/${coingeckoTicker}`)).data.image.small;
144
+ }
132
145
  static async findChains() {
133
146
  const tokens = await apiDbClient.token.findMany({
134
147
  select: { chainId: true, id: true },
@@ -1,7 +1,7 @@
1
1
  import type { Pricer } from "@/utils/pricer";
2
2
  import { type ChainId } from "@sdk";
3
- import type { NotionWebhookModel } from "./token.model";
4
- import type { CreateTokenModel, GetTokenQueryModel, Token, TokenModel, TokenUnique, UpdateTokenModel } from "./token.model";
3
+ import type { CreateTokenModel, NotionWebhookModel } from "./token.model";
4
+ import type { GetTokenQueryModel, Token, TokenModel, TokenUnique, UpdateTokenModel } from "./token.model";
5
5
  import { TokenRepository } from "./token.repository";
6
6
  export declare abstract class TokenService {
7
7
  static hashId(token: TokenUnique): string;
@@ -92,44 +92,6 @@ export declare abstract class TokenService {
92
92
  * @param excludeAddresses to not update symbols that defined using addresses
93
93
  */
94
94
  static updatePrices(pricer: Pricer): Promise<void>;
95
- /**
96
- * Create token on database
97
- * @param chainId
98
- * @param address
99
- */
100
- static create(token: Omit<Token["model"], "id">): Promise<({
101
- symbol: string;
102
- id: string;
103
- name: string | null;
104
- icon: string;
105
- chainId: number;
106
- address: string;
107
- decimals: number;
108
- verified: boolean;
109
- isTest: boolean;
110
- isNative: boolean;
111
- } & {
112
- price?: number | null | undefined;
113
- }) | undefined>;
114
- /**
115
- * Fetches symbol, address, decimals and creates token on database
116
- * @param chainId
117
- * @param address
118
- */
119
- static fillAndCreate(token: CreateTokenModel): Promise<({
120
- symbol: string;
121
- id: string;
122
- name: string | null;
123
- icon: string;
124
- chainId: number;
125
- address: string;
126
- decimals: number;
127
- verified: boolean;
128
- isTest: boolean;
129
- isNative: boolean;
130
- } & {
131
- price?: number | null | undefined;
132
- }) | undefined>;
133
95
  /**
134
96
  * Read token from database
135
97
  * @param chainId
@@ -206,7 +168,7 @@ export declare abstract class TokenService {
206
168
  * @param chainId
207
169
  * @param address
208
170
  */
209
- static getManyOrCreate(tokens: TokenModel[]): Promise<(Token["model"] | undefined)[]>;
171
+ static findManyOrCreate(tokens: TokenModel[]): Promise<(Token["model"] | undefined)[]>;
210
172
  static getValidRewardTokens(chainId: number): Promise<{
211
173
  minimumAmountPerHour: any;
212
174
  symbol: string;
@@ -251,9 +213,28 @@ export declare abstract class TokenService {
251
213
  price: number | null;
252
214
  }>;
253
215
  /**
216
+ * Fetches symbol, address, decimals and creates token on database
217
+ * @param chainId
218
+ * @param address
219
+ */
220
+ static fillAndCreate(token: CreateTokenModel): Promise<({
221
+ symbol: string;
222
+ id: string;
223
+ name: string | null;
224
+ icon: string;
225
+ chainId: number;
226
+ address: string;
227
+ decimals: number;
228
+ verified: boolean;
229
+ isTest: boolean;
230
+ isNative: boolean;
231
+ } & {
232
+ price?: number | null | undefined;
233
+ }) | undefined>;
234
+ /**
235
+ * @deprecated Should be useless now that the token list is not used anymore
254
236
  * Get all tokens from https://github.com/AngleProtocol/angle-token-list and override icons from it
255
237
  * TODO: use the bucket
256
- * @deprecated Should be useless now that the token list is not used anymore
257
238
  */
258
239
  static fillTokenAndIconsFromTokenList(): Promise<void>;
259
240
  }