@glowlabs-org/utils 0.2.154 → 0.2.156

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 (39) hide show
  1. package/README.md +175 -17
  2. package/dist/cjs/browser.d.ts +2 -0
  3. package/dist/cjs/browser.js +7 -1
  4. package/dist/cjs/browser.js.map +1 -1
  5. package/dist/cjs/{farms-router-DwbBMkUd.js → farms-router-DekpTBQj.js} +750 -11
  6. package/dist/cjs/farms-router-DekpTBQj.js.map +1 -0
  7. package/dist/cjs/index.d.ts +1 -0
  8. package/dist/cjs/index.js +2 -1
  9. package/dist/cjs/index.js.map +1 -1
  10. package/dist/cjs/lib/abis/rewardKernelABI.d.ts +418 -0
  11. package/dist/cjs/lib/control-api/farms-router.d.ts +2 -1
  12. package/dist/cjs/lib/control-api/region-router.d.ts +2 -1
  13. package/dist/cjs/lib/control-api/wallets-router.d.ts +2 -2
  14. package/dist/cjs/lib/hooks/use-rewards-kernel.d.ts +45 -0
  15. package/dist/cjs/lib/types/index.d.ts +77 -1
  16. package/dist/esm/browser.d.ts +2 -0
  17. package/dist/esm/browser.js +2 -2
  18. package/dist/esm/{farms-router-C0g4hf2Z.js → farms-router-L56VPDNz.js} +749 -12
  19. package/dist/esm/farms-router-L56VPDNz.js.map +1 -0
  20. package/dist/esm/index.d.ts +1 -0
  21. package/dist/esm/index.js +2 -2
  22. package/dist/esm/lib/abis/rewardKernelABI.d.ts +418 -0
  23. package/dist/esm/lib/control-api/farms-router.d.ts +2 -1
  24. package/dist/esm/lib/control-api/region-router.d.ts +2 -1
  25. package/dist/esm/lib/control-api/wallets-router.d.ts +2 -2
  26. package/dist/esm/lib/hooks/use-rewards-kernel.d.ts +45 -0
  27. package/dist/esm/lib/types/index.d.ts +77 -1
  28. package/package.json +1 -1
  29. package/src/browser.ts +2 -0
  30. package/src/index.ts +1 -0
  31. package/src/lib/abis/rewardKernelABI.ts +264 -0
  32. package/src/lib/control-api/farms-router.ts +33 -0
  33. package/src/lib/control-api/region-router.ts +29 -0
  34. package/src/lib/control-api/wallets-router.ts +36 -2
  35. package/src/lib/hooks/README.md +295 -0
  36. package/src/lib/hooks/use-rewards-kernel.ts +547 -0
  37. package/src/lib/types/index.ts +91 -1
  38. package/dist/cjs/farms-router-DwbBMkUd.js.map +0 -1
  39. package/dist/esm/farms-router-C0g4hf2Z.js.map +0 -1
@@ -0,0 +1,547 @@
1
+ import {
2
+ type WalletClient,
3
+ type PublicClient,
4
+ type Address,
5
+ formatEther,
6
+ } from "viem";
7
+ import { REWARDS_KERNEL_ABI } from "../abis/rewardKernelABI";
8
+ import { getAddresses } from "../../constants/addresses";
9
+ import {
10
+ parseViemError,
11
+ waitForViemTransactionWithRetry,
12
+ } from "../../utils/transaction-utils";
13
+ import {
14
+ sentryAddBreadcrumb,
15
+ sentryCaptureException,
16
+ } from "../../utils/sentry";
17
+
18
+ export enum RewardsKernelError {
19
+ CONTRACT_NOT_AVAILABLE = "Contract not available",
20
+ SIGNER_NOT_AVAILABLE = "Signer not available",
21
+ UNKNOWN_ERROR = "Unknown error",
22
+ INVALID_PARAMETERS = "Invalid parameters",
23
+ ALREADY_CLAIMED = "Already claimed from this nonce",
24
+ NOT_FINALIZED = "Nonce not yet finalized",
25
+ NONCE_REJECTED = "Cannot claim from rejected nonce",
26
+ }
27
+
28
+ // Token and amount structure matching the contract
29
+ export interface TokenAndAmount {
30
+ token: `0x${string}`;
31
+ amount: bigint;
32
+ }
33
+
34
+ // Reward metadata structure
35
+ export interface RewardMeta {
36
+ merkleRoot: string;
37
+ pushTimestamp: number;
38
+ rejected: boolean;
39
+ }
40
+
41
+ // Parameters for claiming a payout
42
+ export interface ClaimPayoutParams {
43
+ nonce: bigint;
44
+ proof: `0x${string}`[]; // bytes32[] as hex strings
45
+ tokensAndAmounts: TokenAndAmount[];
46
+ from: `0x${string}`; // Address providing the tokens
47
+ to: `0x${string}`; // Address receiving the tokens
48
+ isGuardedToken: boolean[]; // Which tokens are guarded
49
+ toCounterfactual: boolean[]; // Whether to send to counterfactual wallet
50
+ }
51
+
52
+ // Type-guard style helper to ensure a wallet client exists
53
+ function assertWalletClient(
54
+ maybeWalletClient: WalletClient | undefined
55
+ ): asserts maybeWalletClient is WalletClient {
56
+ if (!maybeWalletClient) {
57
+ throw new Error(RewardsKernelError.SIGNER_NOT_AVAILABLE);
58
+ }
59
+ if (!maybeWalletClient.account) {
60
+ throw new Error("Wallet client must have an account");
61
+ }
62
+ }
63
+
64
+ export function useRewardsKernel(
65
+ walletClient: WalletClient | undefined,
66
+ publicClient: PublicClient | undefined,
67
+ CHAIN_ID: number
68
+ ) {
69
+ // Use dynamic addresses based on chain configuration
70
+ const ADDRESSES = getAddresses(CHAIN_ID);
71
+
72
+ // Framework-agnostic processing flag
73
+ let isProcessing = false;
74
+ const setIsProcessing = (value: boolean) => {
75
+ isProcessing = value;
76
+ };
77
+
78
+ // Helper to assert public client is available
79
+ function assertPublicClient(
80
+ maybePublicClient: PublicClient | undefined
81
+ ): asserts maybePublicClient is PublicClient {
82
+ if (!maybePublicClient) {
83
+ throw new Error("Public client not available");
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Claim payout from a finalized nonce
89
+ * @param params Parameters for claiming the payout
90
+ */
91
+ async function claimPayout(params: ClaimPayoutParams): Promise<string> {
92
+ assertWalletClient(walletClient);
93
+ assertPublicClient(publicClient);
94
+
95
+ try {
96
+ setIsProcessing(true);
97
+
98
+ sentryAddBreadcrumb({
99
+ category: "rewards-kernel",
100
+ message: "claimPayout.start",
101
+ level: "info",
102
+ data: {
103
+ chainId: walletClient?.chain?.id,
104
+ contract: ADDRESSES.REWARDS_KERNEL,
105
+ nonce: params.nonce.toString(),
106
+ to: params.to,
107
+ from: params.from,
108
+ tokensCount: params.tokensAndAmounts.length,
109
+ },
110
+ });
111
+
112
+ const {
113
+ nonce,
114
+ proof,
115
+ tokensAndAmounts,
116
+ from,
117
+ to,
118
+ isGuardedToken,
119
+ toCounterfactual,
120
+ } = params;
121
+
122
+ // Validate parameters
123
+ if (!proof || proof.length === 0) {
124
+ throw new Error("Merkle proof is required");
125
+ }
126
+
127
+ if (!tokensAndAmounts || tokensAndAmounts.length === 0) {
128
+ throw new Error("Tokens and amounts are required");
129
+ }
130
+
131
+ if (isGuardedToken.length !== tokensAndAmounts.length) {
132
+ throw new Error(
133
+ "isGuardedToken array length must match tokensAndAmounts"
134
+ );
135
+ }
136
+
137
+ if (toCounterfactual.length !== tokensAndAmounts.length) {
138
+ throw new Error(
139
+ "toCounterfactual array length must match tokensAndAmounts"
140
+ );
141
+ }
142
+
143
+ if (!from || !to) {
144
+ throw new Error(RewardsKernelError.INVALID_PARAMETERS);
145
+ }
146
+
147
+ // Check if already claimed
148
+ const owner = walletClient.account?.address;
149
+ if (!owner) {
150
+ throw new Error("No account found in wallet client");
151
+ }
152
+
153
+ const alreadyClaimed = await isClaimed(owner, nonce);
154
+ if (alreadyClaimed) {
155
+ throw new Error(RewardsKernelError.ALREADY_CLAIMED);
156
+ }
157
+
158
+ // Check if finalized
159
+ const finalized = await isFinalized(nonce);
160
+ if (!finalized) {
161
+ throw new Error(RewardsKernelError.NOT_FINALIZED);
162
+ }
163
+
164
+ // Run a simulation first to surface any revert reason
165
+ try {
166
+ await publicClient.simulateContract({
167
+ address: ADDRESSES.REWARDS_KERNEL as Address,
168
+ abi: REWARDS_KERNEL_ABI,
169
+ functionName: "claimPayout",
170
+ args: [
171
+ nonce,
172
+ proof as `0x${string}`[],
173
+ tokensAndAmounts as readonly {
174
+ token: `0x${string}`;
175
+ amount: bigint;
176
+ }[],
177
+ from as Address,
178
+ to as Address,
179
+ isGuardedToken,
180
+ toCounterfactual,
181
+ ],
182
+ account: walletClient.account!,
183
+ });
184
+ } catch (simulationError) {
185
+ sentryCaptureException(simulationError, {
186
+ action: "claimPayout.simulate",
187
+ chainId: walletClient?.chain?.id,
188
+ contract: ADDRESSES.REWARDS_KERNEL,
189
+ nonce: nonce.toString(),
190
+ });
191
+ throw new Error(parseViemError(simulationError));
192
+ }
193
+
194
+ // Execute the transaction
195
+ const hash = await walletClient.writeContract({
196
+ address: ADDRESSES.REWARDS_KERNEL as Address,
197
+ abi: REWARDS_KERNEL_ABI,
198
+ functionName: "claimPayout",
199
+ args: [
200
+ nonce,
201
+ proof as `0x${string}`[],
202
+ tokensAndAmounts as readonly {
203
+ token: `0x${string}`;
204
+ amount: bigint;
205
+ }[],
206
+ from as Address,
207
+ to as Address,
208
+ isGuardedToken,
209
+ toCounterfactual,
210
+ ],
211
+ chain: walletClient.chain,
212
+ account: walletClient.account!,
213
+ });
214
+
215
+ await waitForViemTransactionWithRetry(publicClient, hash);
216
+
217
+ return hash;
218
+ } catch (error) {
219
+ sentryCaptureException(error, {
220
+ action: "claimPayout",
221
+ chainId: walletClient?.chain?.id,
222
+ contract: ADDRESSES.REWARDS_KERNEL,
223
+ nonce: params.nonce.toString(),
224
+ from: params.from,
225
+ to: params.to,
226
+ });
227
+ throw new Error(parseViemError(error));
228
+ } finally {
229
+ setIsProcessing(false);
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Get reward metadata for a specific nonce
235
+ * @param nonce The nonce to query
236
+ */
237
+ async function getRewardMeta(nonce: bigint): Promise<RewardMeta> {
238
+ assertPublicClient(publicClient);
239
+
240
+ try {
241
+ const result = (await publicClient.readContract({
242
+ address: ADDRESSES.REWARDS_KERNEL as Address,
243
+ abi: REWARDS_KERNEL_ABI,
244
+ functionName: "getRewardMeta",
245
+ args: [nonce],
246
+ })) as any;
247
+
248
+ return {
249
+ merkleRoot: result[0],
250
+ pushTimestamp: Number(result[1]),
251
+ rejected: result[2],
252
+ };
253
+ } catch (error) {
254
+ throw new Error(parseViemError(error));
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Get the maximum claimable amount for a token at a specific nonce
260
+ * @param nonce The nonce to query
261
+ * @param token The token address
262
+ */
263
+ async function getMaxReward(
264
+ nonce: bigint,
265
+ token: `0x${string}`
266
+ ): Promise<bigint> {
267
+ assertPublicClient(publicClient);
268
+
269
+ try {
270
+ const result = (await publicClient.readContract({
271
+ address: ADDRESSES.REWARDS_KERNEL as Address,
272
+ abi: REWARDS_KERNEL_ABI,
273
+ functionName: "getMaxReward",
274
+ args: [nonce, token as Address],
275
+ })) as bigint;
276
+
277
+ return result;
278
+ } catch (error) {
279
+ throw new Error(parseViemError(error));
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Get the amount already claimed for a token at a specific nonce
285
+ * @param nonce The nonce to query
286
+ * @param token The token address
287
+ */
288
+ async function getAmountClaimed(
289
+ nonce: bigint,
290
+ token: `0x${string}`
291
+ ): Promise<bigint> {
292
+ assertPublicClient(publicClient);
293
+
294
+ try {
295
+ const result = (await publicClient.readContract({
296
+ address: ADDRESSES.REWARDS_KERNEL as Address,
297
+ abi: REWARDS_KERNEL_ABI,
298
+ functionName: "getAmountClaimed",
299
+ args: [nonce, token as Address],
300
+ })) as bigint;
301
+
302
+ return result;
303
+ } catch (error) {
304
+ throw new Error(parseViemError(error));
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Check if a nonce is finalized and claimable
310
+ * @param nonce The nonce to check
311
+ */
312
+ async function isFinalized(nonce: bigint): Promise<boolean> {
313
+ assertPublicClient(publicClient);
314
+
315
+ try {
316
+ const result = (await publicClient.readContract({
317
+ address: ADDRESSES.REWARDS_KERNEL as Address,
318
+ abi: REWARDS_KERNEL_ABI,
319
+ functionName: "isFinalized",
320
+ args: [nonce],
321
+ })) as boolean;
322
+
323
+ return result;
324
+ } catch (error) {
325
+ throw new Error(parseViemError(error));
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Check if a user has already claimed from a specific nonce
331
+ * @param user The user address
332
+ * @param nonce The nonce to check
333
+ */
334
+ async function isClaimed(
335
+ user: `0x${string}`,
336
+ nonce: bigint
337
+ ): Promise<boolean> {
338
+ assertPublicClient(publicClient);
339
+
340
+ try {
341
+ const result = (await publicClient.readContract({
342
+ address: ADDRESSES.REWARDS_KERNEL as Address,
343
+ abi: REWARDS_KERNEL_ABI,
344
+ functionName: "isClaimed",
345
+ args: [user as Address, nonce],
346
+ })) as boolean;
347
+
348
+ return result;
349
+ } catch (error) {
350
+ throw new Error(parseViemError(error));
351
+ }
352
+ }
353
+
354
+ /**
355
+ * Get the next nonce that will be used for posting
356
+ */
357
+ async function getNextPostNonce(): Promise<bigint> {
358
+ assertPublicClient(publicClient);
359
+
360
+ try {
361
+ const result = (await publicClient.readContract({
362
+ address: ADDRESSES.REWARDS_KERNEL as Address,
363
+ abi: REWARDS_KERNEL_ABI,
364
+ functionName: "$nextPostNonce",
365
+ args: [],
366
+ })) as bigint;
367
+
368
+ return result;
369
+ } catch (error) {
370
+ throw new Error(parseViemError(error));
371
+ }
372
+ }
373
+
374
+ /**
375
+ * Get the finality period in seconds
376
+ */
377
+ async function getFinality(): Promise<bigint> {
378
+ assertPublicClient(publicClient);
379
+
380
+ try {
381
+ const result = (await publicClient.readContract({
382
+ address: ADDRESSES.REWARDS_KERNEL as Address,
383
+ abi: REWARDS_KERNEL_ABI,
384
+ functionName: "FINALITY",
385
+ args: [],
386
+ })) as bigint;
387
+
388
+ return result;
389
+ } catch (error) {
390
+ throw new Error(parseViemError(error));
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Get the foundation multisig address
396
+ */
397
+ async function getFoundationMultisig(): Promise<string> {
398
+ assertPublicClient(publicClient);
399
+
400
+ try {
401
+ const result = (await publicClient.readContract({
402
+ address: ADDRESSES.REWARDS_KERNEL as Address,
403
+ abi: REWARDS_KERNEL_ABI,
404
+ functionName: "FOUNDATION_MULTISIG",
405
+ args: [],
406
+ })) as string;
407
+
408
+ return result;
409
+ } catch (error) {
410
+ throw new Error(parseViemError(error));
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Get the rejection multisig address
416
+ */
417
+ async function getRejectionMultisig(): Promise<string> {
418
+ assertPublicClient(publicClient);
419
+
420
+ try {
421
+ const result = (await publicClient.readContract({
422
+ address: ADDRESSES.REWARDS_KERNEL as Address,
423
+ abi: REWARDS_KERNEL_ABI,
424
+ functionName: "REJECTION_MULTISIG",
425
+ args: [],
426
+ })) as string;
427
+
428
+ return result;
429
+ } catch (error) {
430
+ throw new Error(parseViemError(error));
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Get the counterfactual holder factory address
436
+ */
437
+ async function getCFHFactory(): Promise<string> {
438
+ assertPublicClient(publicClient);
439
+
440
+ try {
441
+ const result = (await publicClient.readContract({
442
+ address: ADDRESSES.REWARDS_KERNEL as Address,
443
+ abi: REWARDS_KERNEL_ABI,
444
+ functionName: "CFH_FACTORY",
445
+ args: [],
446
+ })) as string;
447
+
448
+ return result;
449
+ } catch (error) {
450
+ throw new Error(parseViemError(error));
451
+ }
452
+ }
453
+
454
+ /**
455
+ * Estimate gas for claiming a payout
456
+ * @param params Parameters for claiming the payout
457
+ * @param ethPriceInUSD Current ETH price in USD (for cost estimation)
458
+ */
459
+ async function estimateGasForClaimPayout(
460
+ params: ClaimPayoutParams,
461
+ ethPriceInUSD: number | null
462
+ ): Promise<string> {
463
+ assertWalletClient(walletClient);
464
+ assertPublicClient(publicClient);
465
+
466
+ try {
467
+ const {
468
+ nonce,
469
+ proof,
470
+ tokensAndAmounts,
471
+ from,
472
+ to,
473
+ isGuardedToken,
474
+ toCounterfactual,
475
+ } = params;
476
+
477
+ const gasPrice = await publicClient.getGasPrice();
478
+ if (!gasPrice) {
479
+ throw new Error("Could not fetch gas price to estimate cost.");
480
+ }
481
+
482
+ const estimatedGas = await publicClient.estimateContractGas({
483
+ address: ADDRESSES.REWARDS_KERNEL as Address,
484
+ abi: REWARDS_KERNEL_ABI,
485
+ functionName: "claimPayout",
486
+ args: [
487
+ nonce,
488
+ proof as `0x${string}`[],
489
+ tokensAndAmounts as readonly {
490
+ token: `0x${string}`;
491
+ amount: bigint;
492
+ }[],
493
+ from as Address,
494
+ to as Address,
495
+ isGuardedToken,
496
+ toCounterfactual,
497
+ ],
498
+ account: walletClient.account!,
499
+ });
500
+
501
+ const estimatedCost: bigint = estimatedGas * gasPrice;
502
+
503
+ if (ethPriceInUSD) {
504
+ const estimatedCostInEth = formatEther(estimatedCost);
505
+ const estimatedCostInUSD = (
506
+ parseFloat(estimatedCostInEth) * ethPriceInUSD
507
+ ).toFixed(2);
508
+ return estimatedCostInUSD;
509
+ } else {
510
+ throw new Error(
511
+ "Could not fetch the ETH price to calculate cost in USD."
512
+ );
513
+ }
514
+ } catch (error: any) {
515
+ throw new Error(parseViemError(error));
516
+ }
517
+ }
518
+
519
+ return {
520
+ // Core contract functions
521
+ claimPayout,
522
+
523
+ // View functions
524
+ getRewardMeta,
525
+ getMaxReward,
526
+ getAmountClaimed,
527
+ isFinalized,
528
+ isClaimed,
529
+ getNextPostNonce,
530
+ getFinality,
531
+ getFoundationMultisig,
532
+ getRejectionMultisig,
533
+ getCFHFactory,
534
+
535
+ // Gas estimation
536
+ estimateGasForClaimPayout,
537
+
538
+ // State
539
+ get isProcessing() {
540
+ return isProcessing;
541
+ },
542
+ addresses: ADDRESSES,
543
+
544
+ // Wallet client availability
545
+ isSignerAvailable: !!walletClient,
546
+ };
547
+ }
@@ -573,7 +573,9 @@ export interface WalletFarmInfo {
573
573
  protocolDepositPaidCurrency: string;
574
574
 
575
575
  builtEpoch: number;
576
- builtAt: string; // ISO 8601
576
+ builtAt?: string; // ISO 8601
577
+ glowSplitPercent6Decimals: string; // Wallet's GLW reward split (6 decimals)
578
+ depositSplitPercent6Decimals: string; // Wallet's deposit reward split (6 decimals)
577
579
  }
578
580
 
579
581
  export interface WalletDetails {
@@ -586,6 +588,94 @@ export interface WalletDetails {
586
588
  ownedFarms: WalletFarmInfo[];
587
589
  }
588
590
 
591
+ export interface WeeklyReward {
592
+ weekNumber: number;
593
+ paymentCurrency: PaymentCurrency;
594
+ protocolDepositRewardsReceived: string; // Protocol deposit rewards received by wallet
595
+ glowInflationTotal: string; // GLW inflation rewards (18 decimals)
596
+ }
597
+
598
+ export interface WeeklyRewardsSummary {
599
+ totalProtocolDepositRewardsReceived: string;
600
+ totalGlowInflation: string;
601
+ weeksActive: number;
602
+ }
603
+
604
+ export interface WalletWeeklyRewardsResponse {
605
+ wallet: string;
606
+ summary: WeeklyRewardsSummary;
607
+ rewards: WeeklyReward[];
608
+ }
609
+
610
+ export interface WeeklyRewardsQuery {
611
+ startWeek?: number; // Inclusive lower bound epoch/week
612
+ endWeek?: number; // Inclusive upper bound epoch/week
613
+ paymentCurrency?: PaymentCurrency; // Filter by payment currency
614
+ limit?: number; // Max rows to return (default 52, capped at 520)
615
+ }
616
+
617
+ // ----------------------------- Farm Weekly Rewards ---------------------------
618
+ export interface FarmWeeklyReward {
619
+ weekNumber: number;
620
+ paymentCurrency: PaymentCurrency;
621
+ protocolDepositPaidTotal: string; // Total amount farm paid as protocol deposit
622
+ glowInflationTotal: string; // Total GLW inflation rewards allocated to farm (18 decimals)
623
+ expectedProductionTotal: string; // Farm's weekly carbon credit production in WAD (18 decimals)
624
+ protocolDepositRewardsDistributed: string; // Portion of protocol deposits distributed to wallets
625
+ }
626
+
627
+ export interface FarmWeeklyRewardsSummary {
628
+ totalProtocolDepositPaid: string;
629
+ totalGlowInflation: string;
630
+ totalExpectedProduction: string;
631
+ weeksActive: number;
632
+ }
633
+
634
+ export interface FarmWeeklyRewardsResponse {
635
+ farmId: string;
636
+ summary: FarmWeeklyRewardsSummary;
637
+ rewards: FarmWeeklyReward[];
638
+ }
639
+
640
+ export interface FarmWeeklyRewardsQuery {
641
+ startWeek?: number; // Inclusive lower bound epoch/week
642
+ endWeek?: number; // Inclusive upper bound epoch/week
643
+ paymentCurrency?: PaymentCurrency; // Filter by payment currency
644
+ limit?: number; // Max rows to return (default 52, capped at 520)
645
+ }
646
+
647
+ // ----------------------------- Region Weekly Rewards -------------------------
648
+ export interface RegionWeeklyReward {
649
+ weekNumber: number;
650
+ paymentCurrency: PaymentCurrency;
651
+ protocolDepositPaidTotal: string; // Total amount paid by all farms in region as protocol deposit
652
+ glowInflationTotal: string; // Total GLW inflation rewards allocated to region (18 decimals)
653
+ expectedProductionTotal: string; // Region's total weekly carbon credit production in WAD (18 decimals)
654
+ protocolDepositRewardsDistributed: string; // Always "0" for regions (tracked at farm level)
655
+ createdAt?: string; // ISO 8601
656
+ updatedAt?: string; // ISO 8601
657
+ }
658
+
659
+ export interface RegionWeeklyRewardsSummary {
660
+ totalProtocolDepositPaid: string;
661
+ totalGlowInflation: string;
662
+ totalExpectedProduction: string;
663
+ weeksActive: number;
664
+ }
665
+
666
+ export interface RegionWeeklyRewardsResponse {
667
+ regionId: number;
668
+ summary: RegionWeeklyRewardsSummary;
669
+ rewards: RegionWeeklyReward[];
670
+ }
671
+
672
+ export interface RegionWeeklyRewardsQuery {
673
+ startWeek?: number; // Inclusive lower bound epoch/week
674
+ endWeek?: number; // Inclusive upper bound epoch/week
675
+ paymentCurrency?: PaymentCurrency; // Filter by payment currency
676
+ limit?: number; // Max rows to return (default 52, capped at 520)
677
+ }
678
+
589
679
  // ----------------------------- Farms Reward Score ---------------------------
590
680
  export interface EstimateRewardScoreParams {
591
681
  userId: string;