@glowlabs-org/utils 0.2.109 → 0.2.110

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.
@@ -22,7 +22,6 @@ export interface FractionData {
22
22
  minSharesToRaise: bigint;
23
23
  useCounterfactualAddress: boolean;
24
24
  claimedFromMinSharesToRaise: boolean;
25
- owner: string;
26
25
  step: bigint;
27
26
  to: string;
28
27
  soldSteps: bigint;
@@ -49,6 +48,15 @@ export interface BuyFractionsParams {
49
48
  id: string; // bytes32 as hex string
50
49
  stepsToBuy: bigint;
51
50
  minStepsToBuy: bigint;
51
+ refundTo: string; // Address to receive refunds if needed
52
+ creditTo: string; // Address to credit the purchase to
53
+ useCounterfactualAddressForRefund: boolean; // Whether to use counterfactual address for refunds
54
+ }
55
+
56
+ // Refund details structure matching the contract
57
+ export interface RefundDetails {
58
+ refundTo: string;
59
+ useCounterfactualAddress: boolean;
52
60
  }
53
61
 
54
62
  // Utility to extract the most useful revert reason from an ethers error object
@@ -292,10 +300,18 @@ export function useOffchainFractions(
292
300
 
293
301
  setIsProcessing(true);
294
302
 
295
- const { creator, id, stepsToBuy, minStepsToBuy } = params;
303
+ const {
304
+ creator,
305
+ id,
306
+ stepsToBuy,
307
+ minStepsToBuy,
308
+ refundTo,
309
+ creditTo,
310
+ useCounterfactualAddressForRefund,
311
+ } = params;
296
312
 
297
313
  // Validate parameters
298
- if (!creator || !id) {
314
+ if (!creator || !id || !refundTo || !creditTo) {
299
315
  throw new Error(OffchainFractionsError.INVALID_PARAMETERS);
300
316
  }
301
317
 
@@ -303,6 +319,10 @@ export function useOffchainFractions(
303
319
  throw new Error("stepsToBuy must be greater than zero");
304
320
  }
305
321
 
322
+ if (minStepsToBuy === 0n) {
323
+ throw new Error("minStepsToBuy must be greater than zero");
324
+ }
325
+
306
326
  // Get fraction data to calculate required amount
307
327
  const fractionData = await getFraction(creator, id);
308
328
  const requiredAmount = stepsToBuy * fractionData.step;
@@ -330,9 +350,18 @@ export function useOffchainFractions(
330
350
  try {
331
351
  await contract
332
352
  .getFunction("buyFractions")
333
- .staticCall(creator, id, stepsToBuy, minStepsToBuy, {
334
- from: owner,
335
- });
353
+ .staticCall(
354
+ creator,
355
+ id,
356
+ stepsToBuy,
357
+ minStepsToBuy,
358
+ refundTo,
359
+ creditTo,
360
+ useCounterfactualAddressForRefund,
361
+ {
362
+ from: owner,
363
+ }
364
+ );
336
365
  } catch (staticError) {
337
366
  throw new Error(parseEthersError(staticError));
338
367
  }
@@ -342,7 +371,10 @@ export function useOffchainFractions(
342
371
  creator,
343
372
  id,
344
373
  stepsToBuy,
345
- minStepsToBuy
374
+ minStepsToBuy,
375
+ refundTo,
376
+ creditTo,
377
+ useCounterfactualAddressForRefund
346
378
  );
347
379
  await tx.wait();
348
380
 
@@ -356,10 +388,15 @@ export function useOffchainFractions(
356
388
 
357
389
  /**
358
390
  * Claim refund from an unfilled sale
391
+ * @param user The user address claiming the refund
359
392
  * @param creator The address that created the fraction sale
360
393
  * @param id The unique identifier of the fraction sale
361
394
  */
362
- async function claimRefund(creator: string, id: string): Promise<string> {
395
+ async function claimRefund(
396
+ user: string,
397
+ creator: string,
398
+ id: string
399
+ ): Promise<string> {
363
400
  assertSigner(signer);
364
401
 
365
402
  try {
@@ -370,29 +407,31 @@ export function useOffchainFractions(
370
407
  setIsProcessing(true);
371
408
 
372
409
  // Validate parameters
373
- if (!creator || !id) {
410
+ if (!user || !creator || !id) {
374
411
  throw new Error(OffchainFractionsError.INVALID_PARAMETERS);
375
412
  }
376
413
 
377
414
  const owner = await signer.getAddress();
378
415
 
379
416
  // Check if user has steps purchased
380
- const userSteps = await getStepsPurchased(owner, creator, id);
417
+ const userSteps = await getStepsPurchased(user, creator, id);
381
418
  if (userSteps === 0n) {
382
419
  throw new Error("No steps purchased for this fraction");
383
420
  }
384
421
 
385
422
  // Run a static call first to surface any revert reason
386
423
  try {
387
- await contract.getFunction("claimRefund").staticCall(creator, id, {
388
- from: owner,
389
- });
424
+ await contract
425
+ .getFunction("claimRefund")
426
+ .staticCall(user, creator, id, {
427
+ from: owner,
428
+ });
390
429
  } catch (staticError) {
391
430
  throw new Error(parseEthersError(staticError));
392
431
  }
393
432
 
394
433
  // Execute the transaction
395
- const tx = await contract.getFunction("claimRefund")(creator, id);
434
+ const tx = await contract.getFunction("claimRefund")(user, creator, id);
396
435
  await tx.wait();
397
436
 
398
437
  return tx.hash;
@@ -471,7 +510,6 @@ export function useOffchainFractions(
471
510
  minSharesToRaise: result.minSharesToRaise,
472
511
  useCounterfactualAddress: result.useCounterfactualAddress,
473
512
  claimedFromMinSharesToRaise: result.claimedFromMinSharesToRaise,
474
- owner: result.owner,
475
513
  step: result.step,
476
514
  to: result.to,
477
515
  soldSteps: result.soldSteps,
@@ -512,6 +550,217 @@ export function useOffchainFractions(
512
550
  }
513
551
  }
514
552
 
553
+ /**
554
+ * Get the refund wildcard operator address
555
+ * @returns The wildcard operator address that can perform refunds for any user
556
+ */
557
+ async function getRefundWildcardOperator(): Promise<string> {
558
+ assertSigner(signer);
559
+
560
+ try {
561
+ const contract = getOffchainFractionsContract();
562
+ if (!contract)
563
+ throw new Error(OffchainFractionsError.CONTRACT_NOT_AVAILABLE);
564
+
565
+ const result = await contract.getFunction("REFUND_WILDCARD_OPERATOR")();
566
+ return result;
567
+ } catch (error) {
568
+ throw new Error(parseEthersError(error));
569
+ }
570
+ }
571
+
572
+ /**
573
+ * Get refund details for a user's purchase
574
+ * @param user The user address
575
+ * @param creator The address that created the fraction sale
576
+ * @param id The unique identifier of the fraction sale
577
+ */
578
+ async function getRefundDetails(
579
+ user: string,
580
+ creator: string,
581
+ id: string
582
+ ): Promise<RefundDetails> {
583
+ assertSigner(signer);
584
+
585
+ try {
586
+ const contract = getOffchainFractionsContract();
587
+ if (!contract)
588
+ throw new Error(OffchainFractionsError.CONTRACT_NOT_AVAILABLE);
589
+
590
+ const result = await contract.getFunction("getRefundDetails")(
591
+ user,
592
+ creator,
593
+ id
594
+ );
595
+ return {
596
+ refundTo: result.refundTo,
597
+ useCounterfactualAddress: result.useCounterfactualAddress,
598
+ };
599
+ } catch (error) {
600
+ throw new Error(parseEthersError(error));
601
+ }
602
+ }
603
+
604
+ /**
605
+ * Set refund details for a user's purchase
606
+ * @param creator The address that created the fraction sale
607
+ * @param id The unique identifier of the fraction sale
608
+ * @param refundTo The address to receive refunds
609
+ * @param useCounterfactualAddress Whether to use counterfactual address for refunds
610
+ */
611
+ async function setRefundDetails(
612
+ creator: string,
613
+ id: string,
614
+ refundTo: string,
615
+ useCounterfactualAddress: boolean
616
+ ): Promise<string> {
617
+ assertSigner(signer);
618
+
619
+ try {
620
+ const contract = getOffchainFractionsContract();
621
+ if (!contract)
622
+ throw new Error(OffchainFractionsError.CONTRACT_NOT_AVAILABLE);
623
+
624
+ setIsProcessing(true);
625
+
626
+ // Validate parameters
627
+ if (!creator || !id || !refundTo) {
628
+ throw new Error(OffchainFractionsError.INVALID_PARAMETERS);
629
+ }
630
+
631
+ const owner = await signer.getAddress();
632
+
633
+ // Run a static call first to surface any revert reason
634
+ try {
635
+ await contract
636
+ .getFunction("setRefundDetails")
637
+ .staticCall(creator, id, refundTo, useCounterfactualAddress, {
638
+ from: owner,
639
+ });
640
+ } catch (staticError) {
641
+ throw new Error(parseEthersError(staticError));
642
+ }
643
+
644
+ // Execute the transaction
645
+ const tx = await contract.getFunction("setRefundDetails")(
646
+ creator,
647
+ id,
648
+ refundTo,
649
+ useCounterfactualAddress
650
+ );
651
+ await tx.wait();
652
+
653
+ return tx.hash;
654
+ } catch (error) {
655
+ throw new Error(parseEthersError(error));
656
+ } finally {
657
+ setIsProcessing(false);
658
+ }
659
+ }
660
+
661
+ /**
662
+ * Set refund operator approval status
663
+ * @param refundOperator The address of the refund operator
664
+ * @param isApproved Whether to approve or revoke the operator
665
+ */
666
+ async function setRefundOperatorStatus(
667
+ refundOperator: string,
668
+ isApproved: boolean
669
+ ): Promise<string> {
670
+ assertSigner(signer);
671
+
672
+ try {
673
+ const contract = getOffchainFractionsContract();
674
+ if (!contract)
675
+ throw new Error(OffchainFractionsError.CONTRACT_NOT_AVAILABLE);
676
+
677
+ setIsProcessing(true);
678
+
679
+ // Validate parameters
680
+ if (!refundOperator) {
681
+ throw new Error(OffchainFractionsError.INVALID_PARAMETERS);
682
+ }
683
+
684
+ const owner = await signer.getAddress();
685
+
686
+ // Run a static call first to surface any revert reason
687
+ try {
688
+ await contract
689
+ .getFunction("setRefundOperatorStatus")
690
+ .staticCall(refundOperator, isApproved, {
691
+ from: owner,
692
+ });
693
+ } catch (staticError) {
694
+ throw new Error(parseEthersError(staticError));
695
+ }
696
+
697
+ // Execute the transaction
698
+ const tx = await contract.getFunction("setRefundOperatorStatus")(
699
+ refundOperator,
700
+ isApproved
701
+ );
702
+ await tx.wait();
703
+
704
+ return tx.hash;
705
+ } catch (error) {
706
+ throw new Error(parseEthersError(error));
707
+ } finally {
708
+ setIsProcessing(false);
709
+ }
710
+ }
711
+
712
+ /**
713
+ * Check if a refund operator is approved for a user
714
+ * @param user The user address
715
+ * @param refundOperator The refund operator address
716
+ */
717
+ async function isRefundOperatorApproved(
718
+ user: string,
719
+ refundOperator: string
720
+ ): Promise<boolean> {
721
+ assertSigner(signer);
722
+
723
+ try {
724
+ const contract = getOffchainFractionsContract();
725
+ if (!contract)
726
+ throw new Error(OffchainFractionsError.CONTRACT_NOT_AVAILABLE);
727
+
728
+ const result = await contract.getFunction("isRefundOperatorApproved")(
729
+ user,
730
+ refundOperator
731
+ );
732
+ return result;
733
+ } catch (error) {
734
+ throw new Error(parseEthersError(error));
735
+ }
736
+ }
737
+
738
+ /**
739
+ * Get refund approval status for a user and operator
740
+ * @param user The user address
741
+ * @param refundOperator The refund operator address
742
+ */
743
+ async function getRefundApprovalStatus(
744
+ user: string,
745
+ refundOperator: string
746
+ ): Promise<boolean> {
747
+ assertSigner(signer);
748
+
749
+ try {
750
+ const contract = getOffchainFractionsContract();
751
+ if (!contract)
752
+ throw new Error(OffchainFractionsError.CONTRACT_NOT_AVAILABLE);
753
+
754
+ const result = await contract.getFunction("refundApprovals")(
755
+ user,
756
+ refundOperator
757
+ );
758
+ return result.isApproved;
759
+ } catch (error) {
760
+ throw new Error(parseEthersError(error));
761
+ }
762
+ }
763
+
515
764
  /**
516
765
  * Check if a fraction sale is expired
517
766
  * @param creator The address that created the fraction sale
@@ -680,7 +929,15 @@ export function useOffchainFractions(
680
929
  if (!contract)
681
930
  throw new Error(OffchainFractionsError.CONTRACT_NOT_AVAILABLE);
682
931
 
683
- const { creator, id, stepsToBuy, minStepsToBuy } = params;
932
+ const {
933
+ creator,
934
+ id,
935
+ stepsToBuy,
936
+ minStepsToBuy,
937
+ refundTo,
938
+ creditTo,
939
+ useCounterfactualAddressForRefund,
940
+ } = params;
684
941
 
685
942
  const feeData = await signer.provider?.getFeeData();
686
943
  const gasPrice =
@@ -691,7 +948,15 @@ export function useOffchainFractions(
691
948
 
692
949
  const estimatedGas: bigint = await contract
693
950
  .getFunction("buyFractions")
694
- .estimateGas(creator, id, stepsToBuy, minStepsToBuy);
951
+ .estimateGas(
952
+ creator,
953
+ id,
954
+ stepsToBuy,
955
+ minStepsToBuy,
956
+ refundTo,
957
+ creditTo,
958
+ useCounterfactualAddressForRefund
959
+ );
695
960
 
696
961
  const estimatedCost: bigint = estimatedGas * gasPrice;
697
962
 
@@ -722,6 +987,14 @@ export function useOffchainFractions(
722
987
  getFraction,
723
988
  getStepsPurchased,
724
989
 
990
+ // Refund management functions
991
+ getRefundWildcardOperator,
992
+ getRefundDetails,
993
+ setRefundDetails,
994
+ setRefundOperatorStatus,
995
+ isRefundOperatorApproved,
996
+ getRefundApprovalStatus,
997
+
725
998
  // Token operations
726
999
  approveToken,
727
1000
  checkTokenAllowance,