@glowlabs-org/utils 0.2.150 → 0.2.151

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.
package/dist/esm/index.js CHANGED
@@ -13,8 +13,8 @@ import { parseUnits, formatUnits } from 'viem';
13
13
  import { MerkleTree } from 'merkletreejs';
14
14
  import { solidityPackedKeccak256, keccak256 } from 'ethers';
15
15
  import Decimal from 'decimal.js';
16
- import { H as HUB_URL, U as USDG_WEIGHT_DECIMAL_PRECISION, G as GLOW_WEIGHT_DECIMAL_PRECISION, M as MAX_WEIGHT } from './farms-router-wk3VSuCV.js';
17
- export { C as ControlRouter, F as FarmsRouter, d as KICKSTARTER_STATUS, K as KickstarterRouter, O as OFF_CHAIN_PAYMENT_CURRENCIES, P as PAYMENT_CURRENCIES, b as REGIONS, R as RegionRouter, S as STAKING_DIRECTIONS, T as TRANSFER_TYPES, W as WalletsRouter, c as configureSentry, u as useForwarder, a as useOffchainFractions } from './farms-router-wk3VSuCV.js';
16
+ import { H as HUB_URL, U as USDG_WEIGHT_DECIMAL_PRECISION, G as GLOW_WEIGHT_DECIMAL_PRECISION, M as MAX_WEIGHT } from './farms-router-Cpy_o4_u.js';
17
+ export { C as ControlRouter, F as FarmsRouter, d as KICKSTARTER_STATUS, K as KickstarterRouter, O as OFF_CHAIN_PAYMENT_CURRENCIES, P as PAYMENT_CURRENCIES, b as REGIONS, R as RegionRouter, S as STAKING_DIRECTIONS, T as TRANSFER_TYPES, W as WalletsRouter, c as configureSentry, u as useForwarder, a as useOffchainFractions } from './farms-router-Cpy_o4_u.js';
18
18
 
19
19
  const GENESIS_TIMESTAMP = 1700352000;
20
20
 
@@ -1,4 +1,4 @@
1
- import type { StakeRequest, RegionStake, WalletRegionStake, WalletRegionUnlocked, WalletRegionCommittedBalance, TransferDetails, GlwRegionRewardsResponse, MintedEventsResponse, StakeEventsResponse, FailedOperationsResponse, PendingTransfersResponse, PendingTransferType, RestakeRequest, MigrationAmountResponse } from "../types";
1
+ import type { StakeRequest, RegionStake, WalletRegionStake, WalletRegionUnlocked, WalletRegionCommittedBalance, TransferDetails, GlwRegionRewardsResponse, MintedEventsResponse, StakeEventsResponse, FailedOperationsResponse, PendingTransfersResponse, PendingTransferType, RestakeRequest, MigrationAmountResponse, RetryFailedOperationResponse, FarmRewardSplit } from "../types";
2
2
  export interface PayProtocolDepositUsingStakedControlRequest {
3
3
  wallet: string;
4
4
  regionId: number;
@@ -28,6 +28,7 @@ export declare function ControlRouter(baseUrl: string): {
28
28
  readonly fetchGctlPrice: () => Promise<string>;
29
29
  readonly fetchGlwPrice: () => Promise<string>;
30
30
  readonly fetchCirculatingSupply: () => Promise<string>;
31
+ readonly fetchHoldersCount: () => Promise<number>;
31
32
  readonly fetchLastNonce: (wallet: string) => Promise<string>;
32
33
  readonly fetchMintedEvents: (page?: number, limit?: number) => Promise<MintedEventsResponse>;
33
34
  readonly fetchStakeEvents: (page?: number, limit?: number, regionId?: number) => Promise<StakeEventsResponse>;
@@ -39,11 +40,12 @@ export declare function ControlRouter(baseUrl: string): {
39
40
  readonly fetchWalletRegionCommittedBalance: (wallet: string, regionId: number) => Promise<WalletRegionCommittedBalance>;
40
41
  readonly fetchTransferDetails: (txId: string) => Promise<TransferDetails>;
41
42
  readonly fetchGlwRegionRewards: () => Promise<GlwRegionRewardsResponse>;
43
+ readonly fetchFarmRewardSplits: (farmId: string) => Promise<FarmRewardSplit[]>;
42
44
  readonly fetchMigrationAmount: (wallet: string) => Promise<MigrationAmountResponse>;
43
45
  readonly stakeGctl: (stakeRequest: StakeRequest) => Promise<boolean>;
44
46
  readonly unstakeGctl: (unstakeRequest: StakeRequest) => Promise<boolean>;
45
47
  readonly restakeGctl: (restakeRequest: RestakeRequest) => Promise<boolean>;
46
- readonly retryFailedOperation: (operationId: string) => Promise<boolean>;
48
+ readonly retryFailedOperation: (operationId: string) => Promise<RetryFailedOperationResponse>;
47
49
  readonly payProtocolDepositUsingStakedControl: (paymentRequest: PayProtocolDepositUsingStakedControlRequest) => Promise<PayProtocolDepositUsingStakedControlResponse>;
48
50
  readonly migrateUser: (migrateRequest: MigrateUserRequest) => Promise<MigrateUserResponse>;
49
51
  readonly isStaking: boolean;
@@ -311,18 +311,14 @@ export interface RegionDetails extends RegionWithMetadata {
311
311
  carbonCreditsIssued: number;
312
312
  carbonCreditsPerWeek: number;
313
313
  }
314
- export interface ActiveRegionStakeEvent {
315
- id: string;
316
- regionId: number;
317
- wallet: string;
314
+ export interface ActiveRegionSnapshot {
318
315
  epoch: number;
319
- amount: string;
320
- direction: string;
321
- ts: string;
322
- processed: boolean;
323
- progressClaimed: string;
324
- progressMoved: string;
325
- actionSignatureData: unknown | null;
316
+ totals: {
317
+ gctlStaked: string;
318
+ pendingUnstake: string;
319
+ pendingRestakeOut: string;
320
+ pendingRestakeIn: string;
321
+ };
326
322
  }
327
323
  export interface ActiveRegionSummary {
328
324
  id: number;
@@ -336,7 +332,7 @@ export interface ActiveRegionSummary {
336
332
  pendingUnstake: string;
337
333
  pendingRestakeOut: string;
338
334
  pendingRestakeIn: string;
339
- events: ActiveRegionStakeEvent[];
335
+ snapshots: ActiveRegionSnapshot[];
340
336
  }
341
337
  export interface ActiveRegionsSummaryResponse {
342
338
  total: {
@@ -577,4 +573,11 @@ export interface FarmRewardSplitsResponse {
577
573
  export interface FarmRewardSplitsErrorResponse {
578
574
  error: string;
579
575
  }
576
+ export interface HoldersCountResponse {
577
+ holders: number;
578
+ }
579
+ export interface RetryFailedOperationResponse {
580
+ success?: boolean;
581
+ queued?: boolean;
582
+ }
580
583
  export type { MintedEvent as ControlMintedEvent };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glowlabs-org/utils",
3
- "version": "0.2.150",
3
+ "version": "0.2.151",
4
4
  "description": "A library containing all typechain types and addresses relating to the glow guarded launch",
5
5
  "keywords": [],
6
6
  "author": "",
@@ -19,7 +19,20 @@ import type {
19
19
  PendingTransferType,
20
20
  RestakeRequest,
21
21
  MigrationAmountResponse,
22
+ HoldersCountResponse,
23
+ RetryFailedOperationResponse,
24
+ FarmRewardSplitsResponse,
25
+ FarmRewardSplitsErrorResponse,
26
+ FarmRewardSplit,
22
27
  } from "../types";
28
+
29
+ interface FetchGctlBalanceResponse {
30
+ gctl_balance: string;
31
+ }
32
+
33
+ interface FetchCommittedBalanceResponse {
34
+ gctl_committed_balance: string;
35
+ }
23
36
  import {
24
37
  sentryAddBreadcrumb,
25
38
  sentryCaptureException,
@@ -69,6 +82,9 @@ function parseApiError(error: unknown): string {
69
82
  // --------------------------------------------------------------------------
70
83
 
71
84
  export function ControlRouter(baseUrl: string) {
85
+ if (!baseUrl) {
86
+ throw new Error("CONTROL API base URL is not set");
87
+ }
72
88
  // ----------------------- Internal helpers --------------------------------
73
89
  const request = async <T>(path: string, init?: RequestInit): Promise<T> => {
74
90
  const res = await fetch(`${baseUrl}${path}`, init);
@@ -82,7 +98,7 @@ export function ControlRouter(baseUrl: string) {
82
98
  // ----------------------- GETters -----------------------------------------
83
99
  const fetchGctlBalance = async (wallet: string): Promise<string> => {
84
100
  try {
85
- const data = await request<{ gctl_balance: string }>(
101
+ const data = await request<FetchGctlBalanceResponse>(
86
102
  `/balance/${wallet}`
87
103
  );
88
104
  return (data?.gctl_balance ?? "0").toString();
@@ -93,7 +109,7 @@ export function ControlRouter(baseUrl: string) {
93
109
 
94
110
  const fetchCommittedBalance = async (wallet: string): Promise<string> => {
95
111
  try {
96
- const data = await request<{ gctl_committed_balance: string }>(
112
+ const data = await request<FetchCommittedBalanceResponse>(
97
113
  `/committed-balance/${wallet}`
98
114
  );
99
115
  return (data?.gctl_committed_balance ?? "0").toString();
@@ -138,6 +154,15 @@ export function ControlRouter(baseUrl: string) {
138
154
  }
139
155
  };
140
156
 
157
+ const fetchHoldersCount = async (): Promise<number> => {
158
+ try {
159
+ const data = await request<HoldersCountResponse>(`/holders/count`);
160
+ return data.holders;
161
+ } catch (error) {
162
+ throw new Error(parseApiError(error));
163
+ }
164
+ };
165
+
141
166
  // Build pagination query helper
142
167
  const buildPaginationQuery = (page?: number, limit?: number) => {
143
168
  const p = page ?? 1;
@@ -225,6 +250,21 @@ export function ControlRouter(baseUrl: string) {
225
250
  }
226
251
  };
227
252
 
253
+ const fetchFarmRewardSplits = async (
254
+ farmId: string
255
+ ): Promise<FarmRewardSplit[]> => {
256
+ try {
257
+ if (!farmId) throw new Error("Farm ID is required");
258
+ const data = await request<
259
+ FarmRewardSplitsResponse | FarmRewardSplitsErrorResponse
260
+ >(`/farms/${encodeURIComponent(farmId)}/reward-splits`);
261
+ if ("error" in data) throw new Error(data.error);
262
+ return data.rewardSplits ?? [];
263
+ } catch (error) {
264
+ throw new Error(parseApiError(error));
265
+ }
266
+ };
267
+
228
268
  // Exposed query with error parsing
229
269
  const getTransferDetails = async (txId: string): Promise<TransferDetails> => {
230
270
  try {
@@ -399,7 +439,7 @@ export function ControlRouter(baseUrl: string) {
399
439
 
400
440
  const retryFailedOperation = async (
401
441
  operationId: string
402
- ): Promise<boolean> => {
442
+ ): Promise<RetryFailedOperationResponse> => {
403
443
  isRetryingFailedOperation = true;
404
444
  try {
405
445
  sentryAddBreadcrumb({
@@ -408,11 +448,14 @@ export function ControlRouter(baseUrl: string) {
408
448
  level: "info",
409
449
  data: { baseUrl, operationId },
410
450
  });
411
- await request(`/operations/failed/${operationId}/retry`, {
412
- method: "POST",
413
- headers: { "Content-Type": "application/json" },
414
- });
415
- return true;
451
+ const response = await request<RetryFailedOperationResponse>(
452
+ `/operations/failed/${operationId}/retry`,
453
+ {
454
+ method: "POST",
455
+ headers: { "Content-Type": "application/json" },
456
+ }
457
+ );
458
+ return response;
416
459
  } catch (error) {
417
460
  sentryCaptureException(error, {
418
461
  action: "retryFailedOperation",
@@ -520,6 +563,7 @@ export function ControlRouter(baseUrl: string) {
520
563
  fetchGctlPrice,
521
564
  fetchGlwPrice,
522
565
  fetchCirculatingSupply,
566
+ fetchHoldersCount,
523
567
  fetchLastNonce,
524
568
  fetchMintedEvents,
525
569
  fetchStakeEvents,
@@ -531,6 +575,7 @@ export function ControlRouter(baseUrl: string) {
531
575
  fetchWalletRegionCommittedBalance,
532
576
  fetchTransferDetails: getTransferDetails,
533
577
  fetchGlwRegionRewards,
578
+ fetchFarmRewardSplits,
534
579
  fetchMigrationAmount,
535
580
 
536
581
  // Mutations
@@ -1,5 +1,58 @@
1
1
  "use strict";
2
2
 
3
+ /**
4
+ * # Regions Router
5
+ *
6
+ * This router wraps the Control API endpoints that power Kickstarter-style
7
+ * activation across geographic regions. It surfaces read APIs for activation
8
+ * progress plus the installer certification mutation.
9
+ *
10
+ * ## Components
11
+ * - **router.ts**: exports the `RegionRouter` factory with helpers for each
12
+ * endpoint:
13
+ * - `GET /regions/all` – list regions with activation progress (stake, farms,
14
+ * installers). Accepts optional `?isActive=true|false` filter.
15
+ * - `GET /regions/:idOrSlug` – return region VCR view.
16
+ * - `GET /regions/active/summary` – aggregate GLW/week distribution, pending
17
+ * restakes, and recent epoch snapshots for active regions.
18
+ * - `GET /regions/solar-farms/:regionId` – list sponsored farms for a region.
19
+ * - `POST /regions/installers/apply` – certify an installer via signature.
20
+ * - `GET /regions/activation-events` – activation-event timeline, optional
21
+ * `regionId` filter.
22
+ * - `GET /regions/activation-config` – static activation thresholds and
23
+ * campaign duration for a region code.
24
+ * - **getters.ts**: shared data aggregation utilities used by the router
25
+ * implementation.
26
+ * - **db/schema.ts**: Drizzle schema for `regions`, `region_kickstarters`,
27
+ * `solar_farms`, `certified_installers`, and `region_activation_events`.
28
+ * - **constants**: activation thresholds imported from `@src/constants`:
29
+ * ```ts
30
+ * import {
31
+ * MIN_FARMS,
32
+ * US_STAKE_THRESHOLD,
33
+ * NON_US_STAKE_THRESHOLD,
34
+ * CAMPAIGN_DURATION_DAYS,
35
+ * MIN_INSTALLERS,
36
+ * US_STAKED_TRESHOLD_BIGINT,
37
+ * NON_US_STAKED_TRESHOLD_BIGINT,
38
+ * } from "@src/constants";
39
+ * ```
40
+ * - Region metadata: `regionMetadata` from `@glowlabs-org/utils/browser` feeds
41
+ * `/activation-config` responses.
42
+ * - Kickstarter endpoints live in `KickstarterRouter`.
43
+ *
44
+ * ## Activation Criteria
45
+ * A region activates when it satisfies all of:
46
+ * 1. Stake threshold met (≥ 20 000 GCTL for US, ≥ 200 000 GCTL otherwise).
47
+ * 2. At least 10 solar farms registered.
48
+ * 3. At least 1 certified installer.
49
+ *
50
+ * ## API Responses
51
+ * All numeric stake values are returned as strings (atomic units) to avoid
52
+ * precision loss. Dates are ISO 8601 strings. The router exposes typed helpers
53
+ * for the full dataset described above.
54
+ */
55
+
3
56
  import { generateSlug } from "src/utils/generate-slug";
4
57
  import { regionMetadata } from "../region-metadata";
5
58
  import type {
@@ -377,18 +377,14 @@ export interface RegionDetails extends RegionWithMetadata {
377
377
  carbonCreditsPerWeek: number;
378
378
  }
379
379
 
380
- export interface ActiveRegionStakeEvent {
381
- id: string;
382
- regionId: number;
383
- wallet: string;
380
+ export interface ActiveRegionSnapshot {
384
381
  epoch: number;
385
- amount: string;
386
- direction: string;
387
- ts: string; // ISO 8601 timestamp
388
- processed: boolean;
389
- progressClaimed: string;
390
- progressMoved: string;
391
- actionSignatureData: unknown | null;
382
+ totals: {
383
+ gctlStaked: string;
384
+ pendingUnstake: string;
385
+ pendingRestakeOut: string;
386
+ pendingRestakeIn: string;
387
+ };
392
388
  }
393
389
 
394
390
  export interface ActiveRegionSummary {
@@ -403,7 +399,7 @@ export interface ActiveRegionSummary {
403
399
  pendingUnstake: string;
404
400
  pendingRestakeOut: string;
405
401
  pendingRestakeIn: string;
406
- events: ActiveRegionStakeEvent[];
402
+ snapshots: ActiveRegionSnapshot[];
407
403
  }
408
404
 
409
405
  export interface ActiveRegionsSummaryResponse {
@@ -703,6 +699,15 @@ export interface FarmRewardSplitsErrorResponse {
703
699
  error: string;
704
700
  }
705
701
 
702
+ export interface HoldersCountResponse {
703
+ holders: number;
704
+ }
705
+
706
+ export interface RetryFailedOperationResponse {
707
+ success?: boolean;
708
+ queued?: boolean;
709
+ }
710
+
706
711
  // ---------------------------------------------------------------------------
707
712
  // Barrel exports (convenience)
708
713
  // ---------------------------------------------------------------------------