@glowlabs-org/utils 0.2.161 → 0.2.163

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.
@@ -1,549 +1,5 @@
1
1
  "use strict";
2
2
 
3
- /**
4
- * # Farms Router
5
- *
6
- * This router handles operations related to solar farms.
7
- *
8
- * ## Endpoints
9
- *
10
- * ### GET `/farms/:farmId/reward-splits`
11
- *
12
- * Returns the current reward splits for a specific farm based on its farmId. The splits show how GLW and deposit rewards are distributed among wallet addresses.
13
- *
14
- * **Parameters:**
15
- * - `farmId` (string): Farm ID (UUID format)
16
- *
17
- * **Response:**
18
- *
19
- * Success response:
20
- * ```json
21
- * {
22
- * "farmId": "string",
23
- * "rewardSplits": [
24
- * {
25
- * "walletAddress": "string", // Wallet address in 0x format
26
- * "glowSplitPercent6Decimals": "string", // GLW reward split percentage (6 decimals)
27
- * "depositSplitPercent6Decimals": "string" // Deposit reward split percentage (6 decimals)
28
- * }
29
- * ],
30
- * "totalSplits": "number" // Total number of reward splits
31
- * }
32
- * ```
33
- *
34
- * Error response:
35
- * ```json
36
- * {
37
- * "error": "string"
38
- * }
39
- * ```
40
- *
41
- * **Error Codes:**
42
- * - `400`: Invalid or missing farm ID
43
- * - `404`: Farm not found
44
- * - `500`: Server error
45
- *
46
- * **Notes:**
47
- * - Returns the current state of reward splits based on the complete transfer history
48
- * - Splits are calculated by starting with initial allocations and applying all transfers
49
- * - Only returns wallets with non-zero splits (either GLW or deposit rewards)
50
- * - GLW and deposit split percentages are in 6 decimal format (e.g., 750000 = 75%)
51
- *
52
- * **Example:**
53
- *
54
- * ```bash
55
- * GET /farms/550e8400-e29b-41d4-a716-446655440000/reward-splits
56
- * ```
57
- *
58
- * ### GET `/farms/:farmId/weekly-rewards`
59
- *
60
- * Returns aggregated weekly totals for a farm grouped by payment currency. Each row is sourced from the `weekly_farm_rewards` table created during the weekly-report generation process.
61
- *
62
- * **Parameters:**
63
- * - `farmId` (string): Farm ID (UUID format)
64
- *
65
- * **Query Parameters (optional):**
66
- * - `startWeek` (number): Inclusive lower bound week/epoch.
67
- * - `endWeek` (number): Inclusive upper bound week/epoch.
68
- * - `paymentCurrency` (enum): Filter by a single payment currency (`PAYMENT_CURRENCIES` from `@glowlabs-org/utils/browser`).
69
- * - `limit` (number): Maximum rows to return (default 52, capped at 520).
70
- *
71
- * **Response:**
72
- *
73
- * Success response:
74
- * ```json
75
- * {
76
- * "farmId": "aa2b2449-85e9-45fe-91f1-ed21c9aed72d",
77
- * "summary": {
78
- * "totalProtocolDepositPaid": "22110600000",
79
- * "totalGlowInflation": "6827965927008037794707",
80
- * "totalExpectedProduction": "96500000000000000",
81
- * "weeksActive": 1
82
- * },
83
- * "rewards": [
84
- * {
85
- * "weekNumber": 98,
86
- * "paymentCurrency": "GLW",
87
- * "protocolDepositPaidTotal": "22110600000",
88
- * "glowInflationTotal": "6827965927008037794707",
89
- * "expectedProductionTotal": "96500000000000000",
90
- * "protocolDepositRewardsDistributed": "221106000"
91
- * }
92
- * ]
93
- * }
94
- * ```
95
- *
96
- * Error response:
97
- * ```json
98
- * {
99
- * "error": "string"
100
- * }
101
- * ```
102
- *
103
- * **Notes:**
104
- * - The query helper automatically swaps `startWeek`/`endWeek` if they are supplied in reverse order.
105
- * - `protocolDepositPaidTotal` is the **total amount the farm paid** as protocol deposit in the native decimals of `paymentCurrency` (6 decimals for USDG/USDC/SGCTL, 18 decimals for GLW/GCTL). This represents the total paid by the farm, not the amount distributed to individual wallets.
106
- * - `glowInflationTotal` is the **total GLW inflation rewards allocated to this farm** (18 decimals). This is distributed to farm owners based on their `glowSplitPercent6Decimals`.
107
- * - `expectedProductionTotal` is the farm's weekly carbon credit production in WAD (18 decimals).
108
- * - `protocolDepositRewardsDistributed` represents the portion of protocol deposits distributed out to wallet recipients (same native decimals as `paymentCurrency`).
109
- * - `weeksActive` counts distinct epochs present in the response, independent of the payment currency filters.
110
- * - Data is sourced from the dedicated `weekly_farm_rewards` table for optimized farm-specific queries.
111
- *
112
- * **Example:**
113
- *
114
- * ```bash
115
- * GET /farms/aa2b2449-85e9-45fe-91f1-ed21c9aed72d/weekly-rewards?startWeek=97&endWeek=98
116
- * ```
117
- *
118
- * ### GET `/farms/wallet/:walletAddress/farms-with-rewards`
119
- *
120
- * Returns all farms where the specified wallet address has reward splits, along with their calculated weekly rewards for that wallet.
121
- *
122
- * **Parameters:**
123
- * - `walletAddress` (string): Wallet address in 0x format
124
- *
125
- * **Response:**
126
- *
127
- * Success response:
128
- * ```json
129
- * {
130
- * "farms": [
131
- * {
132
- * "farmId": "string",
133
- * "certifiedInstallerId": "string" | null,
134
- * "name": "string",
135
- * "location": "string",
136
- * "kwhCapacity": "string",
137
- * "solarPanelsQuantity": number,
138
- * "expectedWeeklyCarbonCredits": "string",
139
- * "protocolDepositPaidAmount": "string",
140
- * "protocolDepositPaidCurrency": "string",
141
- *
142
- * "builtEpoch": number,
143
- * "builtAt": "string",
144
- * "afterInstallPictures": [
145
- * {
146
- * "id": "string",
147
- * "name": "string",
148
- * "url": "string",
149
- * "isShowingSolarPanels": boolean
150
- * }
151
- * ],
152
- * "protocolDepositUSDC6Decimals": "string",
153
- * "regionId": number,
154
- * "rewardSplits": [
155
- * {
156
- * "walletAddress": "string",
157
- * "glowSplitPercent6Decimals": "string",
158
- * "depositSplitPercent6Decimals": "string"
159
- * }
160
- * ],
161
- * "userWeeklyRewards": {
162
- * "protocolDepositAsset": "string", // Farm payment currency (enum)
163
- * "protocolDepositRewards": "string", // User's weekly protocol deposit rewards in the farm's payment currency
164
- * "glwInflationRewards": "string", // User's weekly GLW inflation rewards (18 decimals)
165
- * "userGlowSplitPercent": "string", // User's GLW split percentage (6 decimals)
166
- * "userDepositSplitPercent": "string" // User's deposit split percentage (6 decimals)
167
- * }
168
- * }
169
- * ],
170
- * "totalFarms": number // Total number of farms returned
171
- * }
172
- * ```
173
- *
174
- * Error response:
175
- * ```json
176
- * {
177
- * "error": "string"
178
- * }
179
- * ```
180
- *
181
- * **Notes:**
182
- * - Only returns farms in active regions (where `isActivated = true`)
183
- * - Weekly rewards are computed via the rewards simulator API using `getFarmRewardsForWeek`
184
- * - Farms built before epoch 97 are excluded from the payload (preloaded via `preloadGlowV1`)
185
- * - Simulator inputs use `weeksAlive = 100`
186
- * - Protocol deposit rewards are returned in the farm's payment currency; GLW rewards use 18 decimals
187
- *
188
- * **Example:**
189
- *
190
- * ```bash
191
- * GET /farms/wallet/0x1234567890abcdef1234567890abcdef12345678/farms-with-rewards
192
- * ```
193
- *
194
- * ### POST `/farms/estimate-reward-score`
195
- *
196
- * Calculates the reward score for a potential marketplace farm based on its parameters and current region data. This endpoint uses the same reward calculation logic as the actual weekly reward distribution to ensure consistency.
197
- *
198
- * **Request Body:**
199
- *
200
- * ```json
201
- * {
202
- * "userId": "string", // User's wallet address (sponsor)
203
- * "sponsorSplitPercent": "number", // Sponsor's split percentage (0-100)
204
- * "protocolDepositAmount": "string", // Protocol deposit amount in the payment currency
205
- * "paymentCurrency": "USDC" | "USDG" | "GLW" | "GCTL" | "SGCTL", // Payment currency
206
- * "expectedWeeklyCarbonCredits": "number", // Weekly carbon credits production (minimum 0)
207
- * "regionId": "number" // Region ID
208
- * }
209
- * ```
210
- *
211
- * **Response:**
212
- *
213
- * Success response:
214
- *
215
- * ```json
216
- * {
217
- * "rewardScore": "number", // Reward score (integer, rounded up)
218
- * "userWeeklyPdRewards": "string", // User's weekly PD rewards in the payment currency
219
- * "userWeeklyPdRewardsUsd": "string", // User's weekly PD rewards value in USD (6 decimals)
220
- * "userWeeklyGlwRewards": "string", // User's weekly GLW rewards (18 decimals)
221
- * "userWeeklyGlwValueUsd": "string", // User's weekly GLW rewards value in USD (6 decimals)
222
- * "userEstimatedWeeklyCash": "string", // User's total estimated weekly cash in USD (6 decimals)
223
- * "userProtocolDeposit": "string", // User's portion of protocol deposit in USD (6 decimals)
224
- * "userGlowSplitPercent": "string", // User's GLW split percentage (6 decimals)
225
- * "userDepositSplitPercent": "string", // User's deposit split percentage (6 decimals)
226
- * "glwPriceUsd6": "string", // GLW price used in calculation (6 decimals)
227
- * "regionInfo": {
228
- * "regionId": "number",
229
- * "regionGctlStaked": "string",
230
- * "totalGctlStakedAllRegions": "string"
231
- * }
232
- * }
233
- * ```
234
- *
235
- * Error response:
236
- *
237
- * ```json
238
- * {
239
- * "error": "string"
240
- * }
241
- * ```
242
- *
243
- * **Example:**
244
- *
245
- * ```bash
246
- * POST /farms/estimate-reward-score
247
- * Content-Type: application/json
248
- *
249
- * {
250
- * "userId": "0x1234567890abcdef1234567890abcdef12345678",
251
- * "sponsorSplitPercent": 75,
252
- * "protocolDepositAmount": "10000000000",
253
- * "paymentCurrency": "USDC",
254
- * "expectedWeeklyCarbonCredits": 100,
255
- * "regionId": 1
256
- * }
257
- * ```
258
- *
259
- * **Notes:**
260
- *
261
- * - Only considers active regions (where `isActivated = true`)
262
- * - Rewards are computed via the rewards simulator API using `getFarmRewardsForWeek` with `preloadGlowV1` and GCTL distribution
263
- * - Simulator inputs use `weeksAlive = 100` and exclude pre-epoch-97 farms (preloaded via `preloadGlowV1`)
264
- *
265
- * ### POST `/farms/estimate-reward-scores-batch`
266
- *
267
- * Calculates reward scores for multiple potential marketplace farms. Each farm is calculated independently as if joining the protocol by itself.
268
- *
269
- * **Request Body:**
270
- *
271
- * ```json
272
- * {
273
- * "farms": [
274
- * {
275
- * "userId": "string", // User's wallet address (sponsor)
276
- * "sponsorSplitPercent": "number", // Sponsor's split percentage (0-100)
277
- * "protocolDepositAmount": "string", // Protocol deposit amount in the payment currency
278
- * "paymentCurrency": "USDC" | "USDG" | "GLW" | "GCTL" | "SGCTL", // Payment currency
279
- * "expectedWeeklyCarbonCredits": "number", // Weekly carbon credits production (minimum 0)
280
- * "regionId": "number" // Region ID
281
- * }
282
- * ]
283
- * }
284
- * ```
285
- *
286
- * **Response:**
287
- *
288
- * ```json
289
- * {
290
- * "results": [
291
- * // For successful calculations:
292
- * {
293
- * "success": true,
294
- * "data": {
295
- * "rewardScore": "number", // Reward score (integer, rounded up)
296
- * "userWeeklyPdRewards": "string", // User's weekly PD rewards in the payment currency
297
- * "userWeeklyPdRewardsUsd": "string", // User's weekly PD rewards value in USD (6 decimals)
298
- * "userWeeklyGlwRewards": "string", // User's weekly GLW rewards (18 decimals)
299
- * "userWeeklyGlwValueUsd": "string", // User's weekly GLW rewards value in USD (6 decimals)
300
- * "userEstimatedWeeklyCash": "string", // User's total estimated weekly cash in USD (6 decimals)
301
- * "userProtocolDeposit": "string", // User's portion of protocol deposit in USD (6 decimals)
302
- * "userGlowSplitPercent": "string", // User's GLW split percentage (6 decimals)
303
- * "userDepositSplitPercent": "string", // User's deposit split percentage (6 decimals)
304
- * "glwPriceUsd6": "string", // GLW price used in calculation (6 decimals)
305
- * "regionInfo": {
306
- * "regionId": "number",
307
- * "regionGctlStaked": "string",
308
- * "totalGctlStakedAllRegions": "string"
309
- * }
310
- * }
311
- * },
312
- * // For failed calculations:
313
- * {
314
- * "success": false,
315
- * "error": "string", // Error message
316
- * "farmData": {
317
- * "userId": "string",
318
- * "regionId": "number",
319
- * "paymentCurrency": "string"
320
- * }
321
- * }
322
- * ]
323
- * }
324
- * ```
325
- *
326
- * **Example:**
327
- *
328
- * ```bash
329
- * POST /farms/estimate-reward-scores-batch
330
- * Content-Type: application/json
331
- *
332
- * {
333
- * "farms": [
334
- * {
335
- * "userId": "0x1234567890abcdef1234567890abcdef12345678",
336
- * "sponsorSplitPercent": 75,
337
- * "protocolDepositAmount": "10000000000",
338
- * "paymentCurrency": "USDC",
339
- * "expectedWeeklyCarbonCredits": 100,
340
- * "regionId": 1
341
- * },
342
- * {
343
- * "userId": "0xabcdef1234567890abcdef1234567890abcdef12",
344
- * "sponsorSplitPercent": 50,
345
- * "protocolDepositAmount": "5000000000",
346
- * "paymentCurrency": "USDG",
347
- * "expectedWeeklyCarbonCredits": 50,
348
- * "regionId": 2
349
- * }
350
- * ]
351
- * }
352
- * ```
353
- *
354
- * **Notes:**
355
- *
356
- * - Each farm in the batch is calculated independently, as if it's the only new farm joining the protocol
357
- * - The calculation does not accumulate region data between farms in the batch
358
- * - If one farm calculation fails, it won't affect the other farms in the batch
359
- * - Failed calculations include basic identifying information to help with debugging
360
- * - Only considers active regions (where `isActivated = true`)
361
- * - Rewards are computed via the rewards simulator API using `getFarmRewardsForWeek` with `preloadGlowV1` and GCTL distribution; simulator inputs use `weeksAlive = 100` and exclude pre-epoch-97 farms
362
- *
363
- * ### POST `/farms/mining-scores-batch`
364
- *
365
- * Calculates mining scores for existing farms that are already live on the protocol. The mining score represents the return on investment for a miner based on the farm's total GLW rewards.
366
- *
367
- * **Mining Score Formula:**
368
- * ```
369
- * mining_score = 100 * ((glw_per_miner_after_split * weeks_of_miner_life_remaining * glw_price) / dollar_cost_of_miner)
370
- * ```
371
- *
372
- * Where:
373
- * - `glw_per_miner_after_split` = (farm's total GLW rewards / number of miners) × miner_reward_split
374
- * - `miner_reward_split` = percentage of GLW rewards the miner receives (6 decimals, where 1000000 = 100%)
375
- * - `weeks_of_miner_life_remaining` = farm's end reward period - current epoch
376
- * - `glw_price` = current GLW price in USD (6 decimals)
377
- * - `dollar_cost_of_miner` = cost of the miner in USD (6 decimals)
378
- *
379
- * **Mathematically equivalent to:**
380
- * ```
381
- * mining_score = 100 * ((farm_total_glw / number_of_miners) * miner_reward_split * weeks * glw_price) / dollar_cost
382
- * ```
383
- *
384
- * **Request Body:**
385
- *
386
- * ```json
387
- * {
388
- * "farms": [
389
- * {
390
- * "farmId": "string", // The farm ID of the existing farm
391
- * "userId": "string", // User's wallet address to calculate mining score for
392
- * "dollarCostOfMiner": "string", // Dollar cost of the miner (USD with 6 decimals)
393
- * "numberOfMiners": "number", // Number of miners in the farm
394
- * "minerRewardSplit": "string" // Miner's reward split percentage (6 decimals, e.g., 100000 = 10%)
395
- * }
396
- * ]
397
- * }
398
- * ```
399
- *
400
- * **Response:**
401
- *
402
- * ```json
403
- * {
404
- * "results": [
405
- * // For successful calculations:
406
- * {
407
- * "success": true,
408
- * "data": {
409
- * "miningScore": "number", // Mining score (calculated using farm's total GLW rewards)
410
- * "userWeeklyGlwRewards": "string", // User's portion of weekly GLW rewards after split (18 decimals)
411
- * "glwPriceUsd6": "string", // GLW price used in calculation (6 decimals)
412
- * "dollarCostOfMiner": "string", // Dollar cost of miner (6 decimals)
413
- * "weeksOfMinerLifeRemaining": "number", // Weeks of miner life remaining (calculated from farm's end reward period)
414
- * "regionInfo": {
415
- * "regionId": "number",
416
- * "regionGctlStaked": "string",
417
- * "totalGctlStakedAllRegions": "string"
418
- * }
419
- * }
420
- * },
421
- * // For failed calculations:
422
- * {
423
- * "success": false,
424
- * "error": "string", // Error message
425
- * "farmData": {
426
- * "farmId": "string",
427
- * "userId": "string"
428
- * }
429
- * }
430
- * ]
431
- * }
432
- * ```
433
- *
434
- * **Example:**
435
- *
436
- * ```bash
437
- * POST /farms/mining-scores-batch
438
- * Content-Type: application/json
439
- *
440
- * {
441
- * "farms": [
442
- * {
443
- * "farmId": "550e8400-e29b-41d4-a716-446655440000",
444
- * "userId": "0x1234567890abcdef1234567890abcdef12345678",
445
- * "dollarCostOfMiner": "5000000000",
446
- * "numberOfMiners": 10,
447
- * "minerRewardSplit": "100000"
448
- * },
449
- * {
450
- * "farmId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
451
- * "userId": "0xabcdef1234567890abcdef1234567890abcdef12",
452
- * "dollarCostOfMiner": "3000000000",
453
- * "numberOfMiners": 5,
454
- * "minerRewardSplit": "150000"
455
- * }
456
- * ]
457
- * }
458
- * ```
459
- *
460
- * **Notes:**
461
- *
462
- * - The mining score represents the ROI for a single miner, calculated as: (GLW value earned over lifetime) / (miner cost) × 100
463
- * - Weekly GLW rewards are obtained via the rewards simulator API using `getFarmRewardsForWeek`
464
- * - Farms built before epoch 97 are excluded from the simulator payload (preloaded via `preloadGlowV1`); simulator inputs use `weeksAlive = 100`
465
- * - `dollarCostOfMiner` should be provided in USD with 6 decimals (e.g., 5000000000 = $5,000.00)
466
- * - `numberOfMiners` indicates how many miners are in the farm (the total GLW rewards are divided by this number)
467
- * - `minerRewardSplit` is the percentage of GLW rewards the miner receives in 6 decimals (e.g., 100000 = 10%, 1000000 = 100%)
468
- * - Higher mining scores indicate better return on investment
469
- * - The calculation uses the current GLW price from the `getGlwPrice()` function
470
- * - Only works with existing farms that are found in the database
471
- * - Only considers farms in active regions (where `isActivated = true`)
472
- *
473
- * ### GET `/farms/efficiency-scores`
474
- *
475
- * Returns efficiency scores for farms, indicating the carbon credits produced per $100,000 of protocol deposit per week.
476
- *
477
- * **Efficiency Score Formula:**
478
- * ```
479
- * efficiencyScore = (CC / PD) / 100,000
480
- * ```
481
- *
482
- * Where:
483
- * - `CC` = weekly carbon credits in WAD format (18 decimals)
484
- * - `PD` = protocol deposit in USD (6 decimals)
485
- *
486
- * Due to the decimal difference (CC has 18 decimals, PD has 6 decimals), the actual calculation maintains a 10^12 factor, resulting in:
487
- * ```
488
- * efficiencyScore = (CC_actual / PD_actual) × 10^8
489
- * ```
490
- *
491
- * **Query Parameters (optional):**
492
- * - `farmId` (string): Optional farm ID. If provided, returns efficiency score for that specific farm only.
493
- *
494
- * **Response:**
495
- *
496
- * Single farm response (when farmId is provided):
497
- * ```json
498
- * {
499
- * "farmId": "string",
500
- * "efficiencyScore": "number", // Carbon credits per $100,000 deposit per week
501
- * "protocolDepositUsd6": "string", // Protocol deposit in USD (6 decimals)
502
- * "weeklyImpactAssetsWad": "string" // Weekly carbon credits in WAD format (18 decimals)
503
- * }
504
- * ```
505
- *
506
- * All farms response (when farmId is not provided):
507
- * ```json
508
- * [
509
- * {
510
- * "farmId": "string",
511
- * "efficiencyScore": "number", // Carbon credits per $100,000 deposit per week
512
- * "protocolDepositUsd6": "string", // Protocol deposit in USD (6 decimals)
513
- * "weeklyImpactAssetsWad": "string" // Weekly carbon credits in WAD format (18 decimals)
514
- * }
515
- * ]
516
- * ```
517
- *
518
- * Error response:
519
- * ```json
520
- * {
521
- * "error": "string"
522
- * }
523
- * ```
524
- *
525
- * **Example:**
526
- *
527
- * Get efficiency score for a specific farm:
528
- * ```bash
529
- * GET /farms/efficiency-scores?farmId=550e8400-e29b-41d4-a716-446655440000
530
- * ```
531
- *
532
- * Get efficiency scores for all farms (sorted by efficiency descending):
533
- * ```bash
534
- * GET /farms/efficiency-scores
535
- * ```
536
- *
537
- * **Notes:**
538
- *
539
- * - The efficiency score represents carbon credits produced per $100,000 of protocol deposit per week
540
- * - Higher scores indicate more efficient farms (more carbon credits per dollar invested)
541
- * - Scores are sorted in descending order when fetching all farms
542
- * - Includes both legacy V1 farms (from `legacyFarms.json`) and V2+ farms from the database
543
- * - Legacy farms are processed first to avoid duplicates in the results
544
- * - Farms with zero carbon credits will have an efficiency score of 0
545
- */
546
-
547
3
  import type {
548
4
  SponsoredFarm,
549
5
  SponsoredFarmsResponse,
@@ -564,6 +20,12 @@ import type {
564
20
  FarmEfficiencyScore,
565
21
  SingleEfficiencyScoreResponse,
566
22
  EfficiencyScoresErrorResponse,
23
+ FarmWeeklyRewardsBatchQuery,
24
+ FarmWeeklyRewardsBatchResponse,
25
+ WalletFarmRewardsHistoryQuery,
26
+ WalletFarmRewardsHistoryResponse,
27
+ WalletFarmRewardsHistoryBatchQuery,
28
+ WalletFarmRewardsHistoryBatchResponse,
567
29
  } from "../types";
568
30
  import {
569
31
  sentryAddBreadcrumb,
@@ -801,6 +263,98 @@ export function FarmsRouter(baseUrl: string) {
801
263
  }
802
264
  };
803
265
 
266
+ const fetchFarmWeeklyRewardsBatch = async (
267
+ params: FarmWeeklyRewardsBatchQuery
268
+ ): Promise<FarmWeeklyRewardsBatchResponse> => {
269
+ try {
270
+ sentryAddBreadcrumb({
271
+ category: "control-api",
272
+ message: "POST /farms/rewards-history/batch",
273
+ level: "info",
274
+ data: { baseUrl, farmsCount: params.farmIds?.length },
275
+ });
276
+
277
+ const data = await request<FarmWeeklyRewardsBatchResponse>(
278
+ "/farms/rewards-history/batch",
279
+ {
280
+ method: "POST",
281
+ headers: {
282
+ "Content-Type": "application/json",
283
+ },
284
+ body: JSON.stringify(params),
285
+ }
286
+ );
287
+
288
+ return data;
289
+ } catch (error) {
290
+ sentryCaptureException(error, {
291
+ action: "fetchFarmWeeklyRewardsBatch",
292
+ baseUrl,
293
+ farmsCount: params.farmIds?.length,
294
+ });
295
+ throw new Error(parseApiError(error));
296
+ }
297
+ };
298
+
299
+ const fetchWalletFarmRewardsHistory = async (
300
+ walletAddress: string,
301
+ query?: WalletFarmRewardsHistoryQuery
302
+ ): Promise<WalletFarmRewardsHistoryResponse> => {
303
+ try {
304
+ if (!walletAddress) {
305
+ throw new Error("Wallet address is required");
306
+ }
307
+
308
+ const params = new URLSearchParams();
309
+ if (query?.startWeek !== undefined)
310
+ params.set("startWeek", query.startWeek.toString());
311
+ if (query?.endWeek !== undefined)
312
+ params.set("endWeek", query.endWeek.toString());
313
+
314
+ const queryString = params.toString();
315
+ const path = `/farms/by-wallet/${encodeURIComponent(
316
+ walletAddress
317
+ )}/farm-rewards-history${queryString ? `?${queryString}` : ""}`;
318
+
319
+ return await request<WalletFarmRewardsHistoryResponse>(path);
320
+ } catch (error) {
321
+ throw new Error(parseApiError(error));
322
+ }
323
+ };
324
+
325
+ const fetchWalletFarmRewardsHistoryBatch = async (
326
+ params: WalletFarmRewardsHistoryBatchQuery
327
+ ): Promise<WalletFarmRewardsHistoryBatchResponse> => {
328
+ try {
329
+ sentryAddBreadcrumb({
330
+ category: "control-api",
331
+ message: "POST /farms/by-wallet/farm-rewards-history/batch",
332
+ level: "info",
333
+ data: { baseUrl, walletsCount: params.wallets?.length },
334
+ });
335
+
336
+ const data = await request<WalletFarmRewardsHistoryBatchResponse>(
337
+ "/farms/by-wallet/farm-rewards-history/batch",
338
+ {
339
+ method: "POST",
340
+ headers: {
341
+ "Content-Type": "application/json",
342
+ },
343
+ body: JSON.stringify(params),
344
+ }
345
+ );
346
+
347
+ return data;
348
+ } catch (error) {
349
+ sentryCaptureException(error, {
350
+ action: "fetchWalletFarmRewardsHistoryBatch",
351
+ baseUrl,
352
+ walletsCount: params.wallets?.length,
353
+ });
354
+ throw new Error(parseApiError(error));
355
+ }
356
+ };
357
+
804
358
  return {
805
359
  fetchFarmRewardSplits,
806
360
  fetchSponsoredFarms,
@@ -810,5 +364,8 @@ export function FarmsRouter(baseUrl: string) {
810
364
  estimateRewardScoresBatch,
811
365
  calculateMiningScoresBatch,
812
366
  fetchEfficiencyScores,
367
+ fetchFarmWeeklyRewardsBatch,
368
+ fetchWalletFarmRewardsHistory,
369
+ fetchWalletFarmRewardsHistoryBatch,
813
370
  } as const;
814
371
  }