@merkl/api 0.10.392 → 0.10.394

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 (34) hide show
  1. package/dist/database/api/.generated/edge.js +3 -7
  2. package/dist/database/api/.generated/index-browser.js +0 -4
  3. package/dist/database/api/.generated/index.d.ts +1 -99
  4. package/dist/database/api/.generated/index.js +3 -7
  5. package/dist/database/api/.generated/package.json +1 -1
  6. package/dist/database/api/.generated/schema.prisma +11 -13
  7. package/dist/database/api/.generated/wasm.js +0 -4
  8. package/dist/database/engine/.generated/edge.js +3 -7
  9. package/dist/database/engine/.generated/index-browser.js +0 -4
  10. package/dist/database/engine/.generated/index.d.ts +2 -218
  11. package/dist/database/engine/.generated/index.js +3 -7
  12. package/dist/database/engine/.generated/package.json +1 -1
  13. package/dist/database/engine/.generated/schema.prisma +6 -10
  14. package/dist/database/engine/.generated/wasm.js +0 -4
  15. package/dist/src/eden/index.d.ts +0 -42
  16. package/dist/src/index.d.ts +0 -14
  17. package/dist/src/jobs/etl/pendings.js +37 -37
  18. package/dist/src/jobs/etl/reward-breakdowns.js +0 -2
  19. package/dist/src/modules/v4/reward/reward.controller.d.ts +0 -4
  20. package/dist/src/modules/v4/reward/reward.model.d.ts +0 -8
  21. package/dist/src/modules/v4/reward/reward.model.js +0 -6
  22. package/dist/src/modules/v4/reward/reward.repository.d.ts +0 -8
  23. package/dist/src/modules/v4/reward/reward.repository.js +0 -4
  24. package/dist/src/modules/v4/reward/reward.service.d.ts +0 -18
  25. package/dist/src/modules/v4/reward/reward.service.js +0 -2
  26. package/dist/src/modules/v4/reward/subservices/converter.js +0 -2
  27. package/dist/src/modules/v4/router.d.ts +0 -12
  28. package/dist/src/modules/v4/user/user.controller.d.ts +0 -8
  29. package/dist/src/modules/v4/user/user.model.d.ts +0 -2
  30. package/dist/src/modules/v4/user/user.model.js +0 -2
  31. package/dist/src/routes/v3/rewards.d.ts +0 -2
  32. package/dist/src/routes/v3/router.d.ts +0 -2
  33. package/dist/tsconfig.package.tsbuildinfo +1 -1
  34. package/package.json +1 -1
@@ -1,55 +1,52 @@
1
1
  // ─── Pending Rewards Etl ─────────────────────────────────────────────────────
2
2
  if (!process.env.ENV || !process.env.FILENAME)
3
3
  throw new Error("[ENV]: missing variable");
4
- import { BucketService } from "../../modules/v4/bucket/bucket.service";
5
4
  import { RewardService } from "../../modules/v4/reward";
6
- import { withRetry } from "@sdk";
5
+ import { S3Client } from "bun";
7
6
  import moment from "moment";
8
- import { log } from "../../utils/logger";
9
7
  // ─── Constants ───────────────────────────────────────────────
10
8
  const BATCH_SIZE = 20_000;
11
9
  // ─── Global Variables ────────────────────────────────────────
12
10
  const [chainIdString, root, campaignId] = process.env.FILENAME.split("_");
13
11
  const chainId = Number.parseInt(chainIdString);
14
- const pendingsToCreate = [[]];
12
+ const gcsClient = new S3Client({
13
+ accessKeyId: process.env.GCS_ACCESS_ID,
14
+ secretAccessKey: process.env.GCS_SECRET,
15
+ endpoint: process.env.GCS_ENDPOINT,
16
+ bucket: `merkl-rewards-lake-${process.env.ENV}`,
17
+ });
18
+ const file = gcsClient.file(`pendings/${process.env.FILENAME}`);
15
19
  const failedBatches = [];
16
20
  // ─── Extract ─────────────────────────────────────────────────────────────────
17
21
  const extract = async () => {
22
+ if (!file.exists())
23
+ throw new Error("File does not exist.");
24
+ const textDecoder = new TextDecoder();
25
+ let buffer = "";
26
+ const stream = file.stream();
18
27
  let count = 0;
19
- let currentBatchIndex = 0;
20
- await BucketService.readStreamFromBucket(`pendings/${process.env.FILENAME}.gz`, `merkl-rewards-lake-${process.env.ENV}`, `merkl-data-${process.env.ENV}`, async (x) => {
21
- pendingsToCreate[currentBatchIndex].push(transform(JSON.parse(x)));
22
- if (pendingsToCreate[currentBatchIndex].length >= BATCH_SIZE) {
23
- try {
24
- count += await withRetry(load, [pendingsToCreate[currentBatchIndex]], 5, 10_000);
25
- log.info(`Successfully inserted a batch of ${count} rewards`);
28
+ const data = [];
29
+ for await (const chunk of stream) {
30
+ buffer += textDecoder.decode(chunk);
31
+ const lines = buffer.split("\n");
32
+ buffer = lines.pop() || "";
33
+ for (const line of lines) {
34
+ data.push(JSON.parse(line));
35
+ if (data.length >= BATCH_SIZE) {
36
+ try {
37
+ count += await load(data);
38
+ }
39
+ catch (err) {
40
+ console.error(`Failed to insert a batch, adding it to the fail queue.\n${err}`);
41
+ failedBatches.push(data);
42
+ data.length = 0;
43
+ }
26
44
  }
27
- catch (err) {
28
- console.error(`Failed to insert a batch, adding it to the fail queue.\n${err}`);
29
- failedBatches.push(currentBatchIndex);
30
- }
31
- currentBatchIndex++;
32
- pendingsToCreate.push([]);
33
45
  }
34
- return;
35
- });
36
- // ─── Current Batch Not In DB Yet ─────────────────────────────────────
37
- try {
38
- const count = await load(pendingsToCreate[currentBatchIndex]);
39
- if (count !== 0)
40
- log.info(`Successfully inserted a batch of ${count} rewards`);
41
- }
42
- catch (err) {
43
- console.error(`Failed to insert a batch, adding it to the fail queue.\n${err}`);
44
- failedBatches.push(currentBatchIndex);
45
46
  }
46
47
  return count;
47
48
  };
48
- // ─── Transform ───────────────────────────────────────────────────────────────
49
- const transform = (pending) => {
50
- return pending;
51
- };
52
- // ─── Load ────────────────────────────────────────────────────────────────────
49
+ // ─── Transform & Load ────────────────────────────────────────────────────────
53
50
  const load = async (pendings) => {
54
51
  const { updated, created } = await RewardService.updatePendings({
55
52
  distributionChainId: chainId,
@@ -65,11 +62,14 @@ export const main = async () => {
65
62
  const start = moment().unix();
66
63
  // ─── Start Rewards ETL ───────────────────────────────────────────────
67
64
  const count = await extract();
68
- log.info(`✅ Successfully created ${count} new records in ${moment().unix() - start} sec`);
69
- if (failedBatches.length !== 0)
70
- log.info(`${failedBatches.length}/${pendingsToCreate.length} batches failed.`);
65
+ console.log(`✅ Successfully created ${count} new records in ${moment().unix() - start} sec`);
66
+ if (failedBatches.length !== 0) {
67
+ console.log(`${failedBatches.length} batches failed.`);
68
+ process.exit(1);
69
+ }
71
70
  if (failedBatches.length === 0) {
72
- await BucketService.deleteFile(`rewards/${process.env.FILENAME}.gz`, `merkl-rewards-lake-${process.env.ENV}`, `merkl-data-${process.env.ENV}`);
71
+ await file.delete();
72
+ console.log("Object deleted");
73
73
  }
74
74
  };
75
75
  main();
@@ -56,8 +56,6 @@ const transform = (rewardBreakdowns) => {
56
56
  amount: rewardBreakdown.amount,
57
57
  claimed: rewardBreakdown.claimed,
58
58
  pending: rewardBreakdown.pending,
59
- auxiliaryData1: rewardBreakdown.auxiliaryData1 ?? "",
60
- auxiliaryData2: rewardBreakdown.auxiliaryData2 ?? "",
61
59
  });
62
60
  }
63
61
  return transformedRewardBreakdowns;
@@ -232,8 +232,6 @@ export declare const RewardController: Elysia<"/rewards", {
232
232
  rewardToken: string;
233
233
  breakdowns: {
234
234
  protocolId?: string | undefined;
235
- auxiliaryData1?: string | undefined;
236
- auxiliaryData2?: string | undefined;
237
235
  reason: string;
238
236
  pending: string;
239
237
  recipient: string;
@@ -299,8 +297,6 @@ export declare const RewardController: Elysia<"/rewards", {
299
297
  post: {
300
298
  body: {
301
299
  data: {
302
- auxiliaryData1?: string | undefined;
303
- auxiliaryData2?: string | undefined;
304
300
  reason: string;
305
301
  pending: string;
306
302
  recipient: string;
@@ -90,8 +90,6 @@ export declare const CreateManyBreakdownDto: import("@sinclair/typebox").TArray<
90
90
  amount: import("@sinclair/typebox").TString;
91
91
  claimed: import("@sinclair/typebox").TString;
92
92
  pending: import("@sinclair/typebox").TString;
93
- auxiliaryData1: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
94
- auxiliaryData2: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
95
93
  }>>;
96
94
  }>>;
97
95
  declare const RewardDto: import("@sinclair/typebox").TObject<{
@@ -124,8 +122,6 @@ declare const PendingDto: import("@sinclair/typebox").TObject<{
124
122
  recipient: import("@sinclair/typebox").TString;
125
123
  reason: import("@sinclair/typebox").TString;
126
124
  pending: import("@sinclair/typebox").TString;
127
- auxiliaryData1: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
128
- auxiliaryData2: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
129
125
  }>;
130
126
  export declare const UpdatePendingDto: import("@sinclair/typebox").TObject<{
131
127
  distributionChainId: import("@sinclair/typebox").TNumber;
@@ -136,8 +132,6 @@ export declare const UpdatePendingDto: import("@sinclair/typebox").TObject<{
136
132
  recipient: import("@sinclair/typebox").TString;
137
133
  reason: import("@sinclair/typebox").TString;
138
134
  pending: import("@sinclair/typebox").TString;
139
- auxiliaryData1: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
140
- auxiliaryData2: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
141
135
  }>>;
142
136
  }>;
143
137
  export declare const RewardsByUser: import("@sinclair/typebox").TObject<{
@@ -197,8 +191,6 @@ export declare const RewardV3Dto: import("@sinclair/typebox").TRecord<import("@s
197
191
  accumulated: import("@sinclair/typebox").TString;
198
192
  unclaimed: import("@sinclair/typebox").TString;
199
193
  pending: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
200
- auxiliaryData1: import("@sinclair/typebox").TString;
201
- auxiliaryData2: import("@sinclair/typebox").TString;
202
194
  decimals: import("@sinclair/typebox").TNumber;
203
195
  mainParameter: import("@sinclair/typebox").TString;
204
196
  symbol: import("@sinclair/typebox").TString;
@@ -22,8 +22,6 @@ const BreakdownDto = t.Object({
22
22
  amount: t.String(),
23
23
  claimed: t.String(),
24
24
  pending: t.String(),
25
- auxiliaryData1: t.Optional(t.String()),
26
- auxiliaryData2: t.Optional(t.String()),
27
25
  });
28
26
  export const CreateManyBreakdownDto = t.Array(t.Object({
29
27
  distributionChainId: t.Numeric(),
@@ -53,8 +51,6 @@ const PendingDto = t.Object({
53
51
  recipient: t.String(),
54
52
  reason: t.String(),
55
53
  pending: t.String(),
56
- auxiliaryData1: t.Optional(t.String()),
57
- auxiliaryData2: t.Optional(t.String()),
58
54
  });
59
55
  export const UpdatePendingDto = t.Object({
60
56
  distributionChainId: t.Numeric(),
@@ -139,8 +135,6 @@ export const RewardV3Dto = t.Record(t.String({ title: "Chain" }), t.Object({
139
135
  accumulated: t.String(),
140
136
  unclaimed: t.String(),
141
137
  pending: t.Optional(t.String()),
142
- auxiliaryData1: t.String(),
143
- auxiliaryData2: t.String(),
144
138
  decimals: t.Numeric(),
145
139
  mainParameter: t.String(),
146
140
  symbol: t.String(),
@@ -80,8 +80,6 @@ export declare abstract class RewardRepository {
80
80
  amount: string;
81
81
  claimed: string;
82
82
  protocolId: string | null;
83
- auxiliaryData1: string | null;
84
- auxiliaryData2: string | null;
85
83
  rewardId: string;
86
84
  })[];
87
85
  } & {
@@ -107,8 +105,6 @@ export declare abstract class RewardRepository {
107
105
  amount: string;
108
106
  claimed: string;
109
107
  protocolId: string | null;
110
- auxiliaryData1: string | null;
111
- auxiliaryData2: string | null;
112
108
  rewardId: string;
113
109
  })[];
114
110
  } & {
@@ -158,8 +154,6 @@ export declare abstract class RewardRepository {
158
154
  amount: string;
159
155
  claimed: string;
160
156
  protocolId: string | null;
161
- auxiliaryData1: string | null;
162
- auxiliaryData2: string | null;
163
157
  rewardId: string;
164
158
  }[]>;
165
159
  static createRewardPendings(rewardTokenId: string, root: string, toCreate: {
@@ -183,8 +177,6 @@ export declare abstract class RewardRepository {
183
177
  amount: string;
184
178
  claimed: string;
185
179
  protocolId: string | null;
186
- auxiliaryData1: string | null;
187
- auxiliaryData2: string | null;
188
180
  rewardId: string;
189
181
  }[]>;
190
182
  static findManyRootsWithRewardOnChain(chainId: number): Promise<string[]>;
@@ -46,8 +46,6 @@ export class RewardRepository {
46
46
  amount: breakdown.amount,
47
47
  claimed: breakdown.claimed,
48
48
  pending: breakdown.pending,
49
- auxiliaryData1: breakdown.auxiliaryData1 ?? "",
50
- auxiliaryData2: breakdown.auxiliaryData2 ?? "",
51
49
  });
52
50
  });
53
51
  }
@@ -211,8 +209,6 @@ export class RewardRepository {
211
209
  },
212
210
  data: {
213
211
  pending: x.pending,
214
- auxiliaryData1: x.auxiliaryData1,
215
- auxiliaryData2: x.auxiliaryData2,
216
212
  },
217
213
  });
218
214
  }));
@@ -69,8 +69,6 @@ export declare abstract class RewardService {
69
69
  pending: string;
70
70
  amount: string;
71
71
  claimed: string;
72
- auxiliaryData1: string | null;
73
- auxiliaryData2: string | null;
74
72
  };
75
73
  /**
76
74
  * Format the reward to conform to its resource model declaration
@@ -147,8 +145,6 @@ export declare abstract class RewardService {
147
145
  pending: string;
148
146
  amount: string;
149
147
  claimed: string;
150
- auxiliaryData1: string | null;
151
- auxiliaryData2: string | null;
152
148
  }[];
153
149
  claimed: bigint;
154
150
  amount: bigint;
@@ -234,8 +230,6 @@ export declare abstract class RewardService {
234
230
  amount: string;
235
231
  claimed: string;
236
232
  protocolId: string | null;
237
- auxiliaryData1: string | null;
238
- auxiliaryData2: string | null;
239
233
  rewardId: string;
240
234
  })[];
241
235
  } & {
@@ -260,8 +254,6 @@ export declare abstract class RewardService {
260
254
  claimed: bigint;
261
255
  amount: bigint;
262
256
  pending: bigint;
263
- auxiliaryData1: string | null;
264
- auxiliaryData2: string | null;
265
257
  }[];
266
258
  /**
267
259
  * Applies the splitBreakdownByOpportunity function to each rewards in the array
@@ -342,8 +334,6 @@ export declare abstract class RewardService {
342
334
  pending: string;
343
335
  amount: string;
344
336
  claimed: string;
345
- auxiliaryData1: string | null;
346
- auxiliaryData2: string | null;
347
337
  }[];
348
338
  claimed: bigint;
349
339
  amount: bigint;
@@ -357,8 +347,6 @@ export declare abstract class RewardService {
357
347
  claimed: bigint;
358
348
  amount: bigint;
359
349
  pending: bigint;
360
- auxiliaryData1: string | null;
361
- auxiliaryData2: string | null;
362
350
  }[];
363
351
  })[];
364
352
  distributor: string;
@@ -437,8 +425,6 @@ export declare abstract class RewardService {
437
425
  pending: string;
438
426
  amount: string;
439
427
  claimed: string;
440
- auxiliaryData1: string | null;
441
- auxiliaryData2: string | null;
442
428
  }[];
443
429
  claimed: bigint;
444
430
  amount: bigint;
@@ -453,8 +439,6 @@ export declare abstract class RewardService {
453
439
  pending: string;
454
440
  amount: string;
455
441
  claimed: string;
456
- auxiliaryData1: string | null;
457
- auxiliaryData2: string | null;
458
442
  }[];
459
443
  })[];
460
444
  })[];
@@ -535,8 +519,6 @@ export declare abstract class RewardService {
535
519
  amount: string;
536
520
  claimed: string;
537
521
  protocolId: string | null;
538
- auxiliaryData1: string | null;
539
- auxiliaryData2: string | null;
540
522
  rewardId: string;
541
523
  })[];
542
524
  } & {
@@ -106,8 +106,6 @@ export class RewardService {
106
106
  claimed: relatedBreakdowns.reduce((total, { claimed }) => total + BigInt(claimed), 0n),
107
107
  amount: relatedBreakdowns.reduce((total, { amount }) => total + BigInt(amount), 0n),
108
108
  pending: relatedBreakdowns.reduce((total, { pending }) => total + BigInt(pending), 0n),
109
- auxiliaryData1: relatedBreakdowns[0]?.auxiliaryData1,
110
- auxiliaryData2: relatedBreakdowns[0]?.auxiliaryData2,
111
109
  };
112
110
  });
113
111
  }
@@ -77,8 +77,6 @@ export class RewardConvertorService {
77
77
  accumulated: "0",
78
78
  unclaimed: "0",
79
79
  pending: "0",
80
- auxiliaryData1: breakdown.auxiliaryData1 === "" ? "0" : (breakdown.auxiliaryData1 ?? "0"),
81
- auxiliaryData2: breakdown.auxiliaryData2 === "" ? "0" : (breakdown.auxiliaryData2 ?? "0"),
82
80
  decimals: token.decimals,
83
81
  mainParameter: breakdown.opportunity.identifier,
84
82
  symbol: token.symbol,
@@ -2009,8 +2009,6 @@ export declare const v4: Elysia<"/v4", {
2009
2009
  rewardToken: string;
2010
2010
  breakdowns: {
2011
2011
  protocolId?: string | undefined;
2012
- auxiliaryData1?: string | undefined;
2013
- auxiliaryData2?: string | undefined;
2014
2012
  reason: string;
2015
2013
  pending: string;
2016
2014
  recipient: string;
@@ -2076,8 +2074,6 @@ export declare const v4: Elysia<"/v4", {
2076
2074
  post: {
2077
2075
  body: {
2078
2076
  data: {
2079
- auxiliaryData1?: string | undefined;
2080
- auxiliaryData2?: string | undefined;
2081
2077
  reason: string;
2082
2078
  pending: string;
2083
2079
  recipient: string;
@@ -2856,8 +2852,6 @@ export declare const v4: Elysia<"/v4", {
2856
2852
  pending: string;
2857
2853
  amount: string;
2858
2854
  claimed: string;
2859
- auxiliaryData1: string | null;
2860
- auxiliaryData2: string | null;
2861
2855
  }[];
2862
2856
  claimed: bigint;
2863
2857
  amount: bigint;
@@ -2871,8 +2865,6 @@ export declare const v4: Elysia<"/v4", {
2871
2865
  claimed: bigint;
2872
2866
  amount: bigint;
2873
2867
  pending: bigint;
2874
- auxiliaryData1: string | null;
2875
- auxiliaryData2: string | null;
2876
2868
  }[];
2877
2869
  })[];
2878
2870
  distributor: string;
@@ -2982,8 +2974,6 @@ export declare const v4: Elysia<"/v4", {
2982
2974
  pending: string;
2983
2975
  amount: string;
2984
2976
  claimed: string;
2985
- auxiliaryData1: string | null;
2986
- auxiliaryData2: string | null;
2987
2977
  }[];
2988
2978
  claimed: bigint;
2989
2979
  amount: bigint;
@@ -2998,8 +2988,6 @@ export declare const v4: Elysia<"/v4", {
2998
2988
  pending: string;
2999
2989
  amount: string;
3000
2990
  claimed: string;
3001
- auxiliaryData1: string | null;
3002
- auxiliaryData2: string | null;
3003
2991
  }[];
3004
2992
  })[];
3005
2993
  })[];
@@ -226,8 +226,6 @@ export declare const UserController: Elysia<"/users", {
226
226
  pending: string;
227
227
  amount: string;
228
228
  claimed: string;
229
- auxiliaryData1: string | null;
230
- auxiliaryData2: string | null;
231
229
  }[];
232
230
  claimed: bigint;
233
231
  amount: bigint;
@@ -241,8 +239,6 @@ export declare const UserController: Elysia<"/users", {
241
239
  claimed: bigint;
242
240
  amount: bigint;
243
241
  pending: bigint;
244
- auxiliaryData1: string | null;
245
- auxiliaryData2: string | null;
246
242
  }[];
247
243
  })[];
248
244
  distributor: string;
@@ -352,8 +348,6 @@ export declare const UserController: Elysia<"/users", {
352
348
  pending: string;
353
349
  amount: string;
354
350
  claimed: string;
355
- auxiliaryData1: string | null;
356
- auxiliaryData2: string | null;
357
351
  }[];
358
352
  claimed: bigint;
359
353
  amount: bigint;
@@ -368,8 +362,6 @@ export declare const UserController: Elysia<"/users", {
368
362
  pending: string;
369
363
  amount: string;
370
364
  claimed: string;
371
- auxiliaryData1: string | null;
372
- auxiliaryData2: string | null;
373
365
  }[];
374
366
  })[];
375
367
  })[];
@@ -31,8 +31,6 @@ export declare const UserRewardsResourceDto: import("@sinclair/typebox").TObject
31
31
  amount: import("@sinclair/typebox").TString;
32
32
  claimed: import("@sinclair/typebox").TString;
33
33
  pending: import("@sinclair/typebox").TString;
34
- auxiliaryData1: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
35
- auxiliaryData2: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
36
34
  campaignId: import("@sinclair/typebox").TString;
37
35
  }>>;
38
36
  claimed: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TBigInt, import("@sinclair/typebox").TString]>;
@@ -30,8 +30,6 @@ export const UserRewardsResourceDto = t.Object({
30
30
  amount: t.String(),
31
31
  claimed: t.String(),
32
32
  pending: t.String(),
33
- auxiliaryData1: t.Union([t.String(), t.Null()]),
34
- auxiliaryData2: t.Union([t.String(), t.Null()]),
35
33
  campaignId: t.String(),
36
34
  })),
37
35
  claimed: t.Union([t.BigInt(), t.String()]),
@@ -39,8 +39,6 @@ declare const _default: (app: Elysia) => Elysia<"", {
39
39
  token: string;
40
40
  mainParameter: string;
41
41
  decimals: number;
42
- auxiliaryData1: string;
43
- auxiliaryData2: string;
44
42
  unclaimed: string;
45
43
  accumulated: string;
46
44
  };
@@ -851,8 +851,6 @@ export declare const v3: Elysia<"/v3", {
851
851
  token: string;
852
852
  mainParameter: string;
853
853
  decimals: number;
854
- auxiliaryData1: string;
855
- auxiliaryData2: string;
856
854
  unclaimed: string;
857
855
  accumulated: string;
858
856
  };