@glowlabs-org/utils 0.2.142 → 0.2.145

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.
@@ -11,6 +11,10 @@ import {
11
11
  parseViemError,
12
12
  waitForViemTransactionWithRetry,
13
13
  } from "../../utils/transaction-utils";
14
+ import {
15
+ sentryAddBreadcrumb,
16
+ sentryCaptureException,
17
+ } from "../../utils/sentry";
14
18
 
15
19
  export enum OffchainFractionsError {
16
20
  CONTRACT_NOT_AVAILABLE = "Contract not available",
@@ -195,6 +199,24 @@ export function useOffchainFractions(
195
199
  try {
196
200
  setIsProcessing(true);
197
201
 
202
+ sentryAddBreadcrumb({
203
+ category: "offchain-fractions",
204
+ message: "createFraction.start",
205
+ level: "info",
206
+ data: {
207
+ chainId: walletClient?.chain?.id,
208
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
209
+ id: params.id,
210
+ token: params.token,
211
+ step: params.step.toString(),
212
+ totalSteps: params.totalSteps.toString(),
213
+ to: params.to,
214
+ expiration: params.expiration,
215
+ minSharesToRaise: params.minSharesToRaise.toString(),
216
+ closer: params.closer,
217
+ },
218
+ });
219
+
198
220
  const {
199
221
  id,
200
222
  token,
@@ -240,6 +262,12 @@ export function useOffchainFractions(
240
262
  account: walletClient.account!,
241
263
  });
242
264
  } catch (simulationError) {
265
+ sentryCaptureException(simulationError, {
266
+ action: "createFraction.simulate",
267
+ chainId: walletClient?.chain?.id,
268
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
269
+ id: params.id,
270
+ });
243
271
  throw new Error(parseViemError(simulationError));
244
272
  }
245
273
 
@@ -267,6 +295,13 @@ export function useOffchainFractions(
267
295
 
268
296
  return hash;
269
297
  } catch (error) {
298
+ sentryCaptureException(error, {
299
+ action: "createFraction",
300
+ chainId: walletClient?.chain?.id,
301
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
302
+ id: params.id,
303
+ token: params.token,
304
+ });
270
305
  throw new Error(parseViemError(error));
271
306
  } finally {
272
307
  setIsProcessing(false);
@@ -284,6 +319,24 @@ export function useOffchainFractions(
284
319
  try {
285
320
  setIsProcessing(true);
286
321
 
322
+ sentryAddBreadcrumb({
323
+ category: "offchain-fractions",
324
+ message: "buyFractions.start",
325
+ level: "info",
326
+ data: {
327
+ chainId: walletClient?.chain?.id,
328
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
329
+ creator: params.creator,
330
+ id: params.id,
331
+ stepsToBuy: params.stepsToBuy.toString(),
332
+ minStepsToBuy: params.minStepsToBuy.toString(),
333
+ refundTo: params.refundTo,
334
+ creditTo: params.creditTo,
335
+ useCounterfactualAddressForRefund:
336
+ params.useCounterfactualAddressForRefund,
337
+ },
338
+ });
339
+
287
340
  const {
288
341
  creator,
289
342
  id,
@@ -354,6 +407,13 @@ export function useOffchainFractions(
354
407
  account: walletClient.account!,
355
408
  });
356
409
  } catch (simulationError) {
410
+ sentryCaptureException(simulationError, {
411
+ action: "buyFractions.simulate",
412
+ chainId: walletClient?.chain?.id,
413
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
414
+ creator: params.creator,
415
+ id: params.id,
416
+ });
357
417
  throw new Error(parseViemError(simulationError));
358
418
  }
359
419
 
@@ -379,6 +439,14 @@ export function useOffchainFractions(
379
439
 
380
440
  return hash;
381
441
  } catch (error) {
442
+ sentryCaptureException(error, {
443
+ action: "buyFractions",
444
+ chainId: walletClient?.chain?.id,
445
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
446
+ creator: params.creator,
447
+ id: params.id,
448
+ stepsToBuy: params.stepsToBuy.toString(),
449
+ });
382
450
  throw new Error(parseViemError(error));
383
451
  } finally {
384
452
  setIsProcessing(false);
@@ -402,6 +470,19 @@ export function useOffchainFractions(
402
470
  try {
403
471
  setIsProcessing(true);
404
472
 
473
+ sentryAddBreadcrumb({
474
+ category: "offchain-fractions",
475
+ message: "claimRefund.start",
476
+ level: "info",
477
+ data: {
478
+ chainId: walletClient?.chain?.id,
479
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
480
+ user,
481
+ creator,
482
+ id,
483
+ },
484
+ });
485
+
405
486
  // Normalize addresses to lowercase for consistency
406
487
  const normalizedUser = user?.toLowerCase();
407
488
  const normalizedCreator = creator?.toLowerCase();
@@ -452,7 +533,14 @@ export function useOffchainFractions(
452
533
  account: walletClient.account!,
453
534
  });
454
535
  } catch (simulationError) {
455
- console.error("Simulation failed:", simulationError);
536
+ sentryCaptureException(simulationError, {
537
+ action: "claimRefund.simulate",
538
+ chainId: walletClient?.chain?.id,
539
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
540
+ user,
541
+ creator,
542
+ id,
543
+ });
456
544
  throw new Error(parseViemError(simulationError));
457
545
  }
458
546
 
@@ -470,6 +558,14 @@ export function useOffchainFractions(
470
558
 
471
559
  return hash;
472
560
  } catch (error) {
561
+ sentryCaptureException(error, {
562
+ action: "claimRefund",
563
+ chainId: walletClient?.chain?.id,
564
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
565
+ user,
566
+ creator,
567
+ id,
568
+ });
473
569
  throw new Error(parseViemError(error));
474
570
  } finally {
475
571
  setIsProcessing(false);
@@ -488,6 +584,18 @@ export function useOffchainFractions(
488
584
  try {
489
585
  setIsProcessing(true);
490
586
 
587
+ sentryAddBreadcrumb({
588
+ category: "offchain-fractions",
589
+ message: "closeFraction.start",
590
+ level: "info",
591
+ data: {
592
+ chainId: walletClient?.chain?.id,
593
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
594
+ creator,
595
+ id,
596
+ },
597
+ });
598
+
491
599
  // Validate parameters
492
600
  if (!creator || !id) {
493
601
  throw new Error(OffchainFractionsError.INVALID_PARAMETERS);
@@ -508,6 +616,13 @@ export function useOffchainFractions(
508
616
  account: walletClient.account!,
509
617
  });
510
618
  } catch (simulationError) {
619
+ sentryCaptureException(simulationError, {
620
+ action: "closeFraction.simulate",
621
+ chainId: walletClient?.chain?.id,
622
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
623
+ creator,
624
+ id,
625
+ });
511
626
  throw new Error(parseViemError(simulationError));
512
627
  }
513
628
 
@@ -525,6 +640,13 @@ export function useOffchainFractions(
525
640
 
526
641
  return hash;
527
642
  } catch (error) {
643
+ sentryCaptureException(error, {
644
+ action: "closeFraction",
645
+ chainId: walletClient?.chain?.id,
646
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
647
+ creator,
648
+ id,
649
+ });
528
650
  throw new Error(parseViemError(error));
529
651
  } finally {
530
652
  setIsProcessing(false);
@@ -672,6 +794,20 @@ export function useOffchainFractions(
672
794
  try {
673
795
  setIsProcessing(true);
674
796
 
797
+ sentryAddBreadcrumb({
798
+ category: "offchain-fractions",
799
+ message: "setRefundDetails.start",
800
+ level: "info",
801
+ data: {
802
+ chainId: walletClient?.chain?.id,
803
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
804
+ creator,
805
+ id,
806
+ refundTo,
807
+ useCounterfactualAddress,
808
+ },
809
+ });
810
+
675
811
  // Validate parameters
676
812
  if (!creator || !id || !refundTo) {
677
813
  throw new Error(OffchainFractionsError.INVALID_PARAMETERS);
@@ -697,6 +833,13 @@ export function useOffchainFractions(
697
833
  account: walletClient.account!,
698
834
  });
699
835
  } catch (simulationError) {
836
+ sentryCaptureException(simulationError, {
837
+ action: "setRefundDetails.simulate",
838
+ chainId: walletClient?.chain?.id,
839
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
840
+ creator,
841
+ id,
842
+ });
700
843
  throw new Error(parseViemError(simulationError));
701
844
  }
702
845
 
@@ -719,6 +862,14 @@ export function useOffchainFractions(
719
862
 
720
863
  return hash;
721
864
  } catch (error) {
865
+ sentryCaptureException(error, {
866
+ action: "setRefundDetails",
867
+ chainId: walletClient?.chain?.id,
868
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
869
+ creator,
870
+ id,
871
+ refundTo,
872
+ });
722
873
  throw new Error(parseViemError(error));
723
874
  } finally {
724
875
  setIsProcessing(false);
@@ -740,6 +891,18 @@ export function useOffchainFractions(
740
891
  try {
741
892
  setIsProcessing(true);
742
893
 
894
+ sentryAddBreadcrumb({
895
+ category: "offchain-fractions",
896
+ message: "setRefundOperatorStatus.start",
897
+ level: "info",
898
+ data: {
899
+ chainId: walletClient?.chain?.id,
900
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
901
+ refundOperator,
902
+ isApproved,
903
+ },
904
+ });
905
+
743
906
  // Validate parameters
744
907
  if (!refundOperator) {
745
908
  throw new Error(OffchainFractionsError.INVALID_PARAMETERS);
@@ -760,6 +923,13 @@ export function useOffchainFractions(
760
923
  account: walletClient.account!,
761
924
  });
762
925
  } catch (simulationError) {
926
+ sentryCaptureException(simulationError, {
927
+ action: "setRefundOperatorStatus.simulate",
928
+ chainId: walletClient?.chain?.id,
929
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
930
+ refundOperator,
931
+ isApproved,
932
+ });
763
933
  throw new Error(parseViemError(simulationError));
764
934
  }
765
935
 
@@ -777,6 +947,13 @@ export function useOffchainFractions(
777
947
 
778
948
  return hash;
779
949
  } catch (error) {
950
+ sentryCaptureException(error, {
951
+ action: "setRefundOperatorStatus",
952
+ chainId: walletClient?.chain?.id,
953
+ contract: ADDRESSES.OFFCHAIN_FRACTIONS,
954
+ refundOperator,
955
+ isApproved,
956
+ });
780
957
  throw new Error(parseViemError(error));
781
958
  } finally {
782
959
  setIsProcessing(false);
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+
3
+ export interface SentryBreadcrumb {
4
+ category: string;
5
+ message?: string;
6
+ level?: "error" | "warning" | "info" | "debug";
7
+ data?: Record<string, unknown>;
8
+ }
9
+
10
+ export interface SentryClientLike {
11
+ captureException: (
12
+ error: unknown,
13
+ context?: { extra?: Record<string, unknown> }
14
+ ) => void;
15
+ addBreadcrumb?: (breadcrumb: SentryBreadcrumb) => void;
16
+ }
17
+
18
+ type SentryConfig = {
19
+ enabled?: boolean;
20
+ client?: SentryClientLike | null;
21
+ defaultContext?: Record<string, unknown>;
22
+ };
23
+
24
+ let configuredClient: SentryClientLike | null = null;
25
+ let isEnabled = true;
26
+ let defaultExtra: Record<string, unknown> = {};
27
+
28
+ function getSentry(): SentryClientLike | null {
29
+ const client =
30
+ configuredClient ??
31
+ ((globalThis as any)?.Sentry as SentryClientLike | undefined);
32
+ if (!client || typeof client.captureException !== "function") return null;
33
+ return client;
34
+ }
35
+
36
+ export function configureSentry(config: SentryConfig): void {
37
+ if (config.enabled !== undefined) isEnabled = !!config.enabled;
38
+ if (config.client !== undefined) configuredClient = config.client;
39
+ if (config.defaultContext) defaultExtra = { ...config.defaultContext };
40
+ }
41
+
42
+ function shouldSkipSentry(error: unknown): boolean {
43
+ try {
44
+ const possible: any = error;
45
+ const code: string | undefined = possible?.code || possible?.cause?.code;
46
+ const name: string | undefined = possible?.name || possible?.cause?.name;
47
+ const message: string = String(
48
+ possible?.message || possible?.cause?.message || ""
49
+ );
50
+
51
+ // User rejected wallet request (ethers/viem/common providers)
52
+ if (code === "ACTION_REJECTED") return true;
53
+ if (name === "UserRejectedRequestError") return true;
54
+ if (/user rejected/i.test(message)) return true;
55
+
56
+ // Terminal waitForViemTransactionWithRetry error (retries exhausted)
57
+ if (/Transaction failed after\s+\d+\s+attempts:/i.test(message)) {
58
+ return true;
59
+ }
60
+
61
+ return false;
62
+ } catch {
63
+ return false;
64
+ }
65
+ }
66
+
67
+ export function sentryAddBreadcrumb(breadcrumb: SentryBreadcrumb): void {
68
+ try {
69
+ if (!isEnabled) return;
70
+ getSentry()?.addBreadcrumb?.(breadcrumb);
71
+ } catch {}
72
+ }
73
+
74
+ export function sentryCaptureException(
75
+ error: unknown,
76
+ extra?: Record<string, unknown>
77
+ ): void {
78
+ try {
79
+ if (!isEnabled) return;
80
+ if (shouldSkipSentry(error)) return;
81
+ const client = getSentry();
82
+ if (!client) return;
83
+ const merged = extra ? { ...defaultExtra, ...extra } : defaultExtra;
84
+ client.captureException(
85
+ error,
86
+ Object.keys(merged).length ? { extra: merged } : undefined
87
+ );
88
+ } catch {}
89
+ }