@ledgerhq/coin-sui 0.11.0 → 0.12.0-nightly.1

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 (188) hide show
  1. package/.eslintrc.js +1 -0
  2. package/.turbo/turbo-build.log +1 -1
  3. package/.unimportedrc.json +1 -0
  4. package/CHANGELOG.md +21 -0
  5. package/index.d.ts +0 -1
  6. package/jest.config.js +1 -1
  7. package/lib/bridge/broadcast.d.ts.map +1 -1
  8. package/lib/bridge/broadcast.js +3 -0
  9. package/lib/bridge/broadcast.js.map +1 -1
  10. package/lib/bridge/buildOptimisticOperation.js +31 -0
  11. package/lib/bridge/buildOptimisticOperation.js.map +1 -1
  12. package/lib/bridge/buildTransaction.d.ts +1 -1
  13. package/lib/bridge/buildTransaction.d.ts.map +1 -1
  14. package/lib/bridge/buildTransaction.js +3 -1
  15. package/lib/bridge/buildTransaction.js.map +1 -1
  16. package/lib/bridge/buildTransaction.test.js +4 -0
  17. package/lib/bridge/buildTransaction.test.js.map +1 -1
  18. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
  19. package/lib/bridge/estimateMaxSpendable.js +15 -3
  20. package/lib/bridge/estimateMaxSpendable.js.map +1 -1
  21. package/lib/bridge/estimateMaxSpendable.test.js +27 -0
  22. package/lib/bridge/estimateMaxSpendable.test.js.map +1 -1
  23. package/lib/bridge/getFeesForTransaction.d.ts.map +1 -1
  24. package/lib/bridge/getFeesForTransaction.js +13 -1
  25. package/lib/bridge/getFeesForTransaction.js.map +1 -1
  26. package/lib/bridge/getOperationExtra.d.ts +2 -0
  27. package/lib/bridge/getOperationExtra.d.ts.map +1 -0
  28. package/lib/bridge/getOperationExtra.js +6 -0
  29. package/lib/bridge/getOperationExtra.js.map +1 -0
  30. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  31. package/lib/bridge/getTransactionStatus.js +45 -20
  32. package/lib/bridge/getTransactionStatus.js.map +1 -1
  33. package/lib/bridge/preload.d.ts.map +1 -1
  34. package/lib/bridge/preload.js +5 -3
  35. package/lib/bridge/preload.js.map +1 -1
  36. package/lib/bridge/preload.test.js +13 -217
  37. package/lib/bridge/preload.test.js.map +1 -1
  38. package/lib/bridge/prepareTransaction.js +1 -1
  39. package/lib/bridge/prepareTransaction.js.map +1 -1
  40. package/lib/bridge/synchronisation.d.ts.map +1 -1
  41. package/lib/bridge/synchronisation.js +5 -2
  42. package/lib/bridge/synchronisation.js.map +1 -1
  43. package/lib/bridge/synchronisation.test.js +355 -7
  44. package/lib/bridge/synchronisation.test.js.map +1 -1
  45. package/lib/bridge/utils.d.ts +1 -1
  46. package/lib/bridge/utils.d.ts.map +1 -1
  47. package/lib/bridge/utils.js +22 -0
  48. package/lib/bridge/utils.js.map +1 -1
  49. package/lib/constants.d.ts +4 -0
  50. package/lib/constants.d.ts.map +1 -0
  51. package/lib/constants.js +7 -0
  52. package/lib/constants.js.map +1 -0
  53. package/lib/errors.d.ts +13 -0
  54. package/lib/errors.d.ts.map +1 -0
  55. package/lib/errors.js +21 -0
  56. package/lib/errors.js.map +1 -0
  57. package/lib/logic/craftTransaction.d.ts +5 -10
  58. package/lib/logic/craftTransaction.d.ts.map +1 -1
  59. package/lib/logic/craftTransaction.js +2 -1
  60. package/lib/logic/craftTransaction.js.map +1 -1
  61. package/lib/logic/estimateFees.d.ts +1 -1
  62. package/lib/logic/estimateFees.d.ts.map +1 -1
  63. package/lib/logic/estimateFees.js +14 -2
  64. package/lib/logic/estimateFees.js.map +1 -1
  65. package/lib/logic/index.d.ts +2 -1
  66. package/lib/logic/index.d.ts.map +1 -1
  67. package/lib/logic/index.js +3 -1
  68. package/lib/logic/index.js.map +1 -1
  69. package/lib/logic/stake.d.ts +3 -0
  70. package/lib/logic/stake.d.ts.map +1 -0
  71. package/lib/logic/stake.js +12 -0
  72. package/lib/logic/stake.js.map +1 -0
  73. package/lib/network/index.d.ts +5 -4
  74. package/lib/network/index.d.ts.map +1 -1
  75. package/lib/network/index.js +5 -3
  76. package/lib/network/index.js.map +1 -1
  77. package/lib/network/sdk.d.ts +5 -3
  78. package/lib/network/sdk.d.ts.map +1 -1
  79. package/lib/network/sdk.js +148 -26
  80. package/lib/network/sdk.js.map +1 -1
  81. package/lib/network/sdk.test.js +491 -6
  82. package/lib/network/sdk.test.js.map +1 -1
  83. package/lib/types/bridge.d.ts +33 -6
  84. package/lib/types/bridge.d.ts.map +1 -1
  85. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  86. package/lib-es/bridge/broadcast.js +3 -0
  87. package/lib-es/bridge/broadcast.js.map +1 -1
  88. package/lib-es/bridge/buildOptimisticOperation.js +31 -0
  89. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
  90. package/lib-es/bridge/buildTransaction.d.ts +1 -1
  91. package/lib-es/bridge/buildTransaction.d.ts.map +1 -1
  92. package/lib-es/bridge/buildTransaction.js +3 -1
  93. package/lib-es/bridge/buildTransaction.js.map +1 -1
  94. package/lib-es/bridge/buildTransaction.test.js +4 -0
  95. package/lib-es/bridge/buildTransaction.test.js.map +1 -1
  96. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
  97. package/lib-es/bridge/estimateMaxSpendable.js +15 -3
  98. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
  99. package/lib-es/bridge/estimateMaxSpendable.test.js +27 -0
  100. package/lib-es/bridge/estimateMaxSpendable.test.js.map +1 -1
  101. package/lib-es/bridge/getFeesForTransaction.d.ts.map +1 -1
  102. package/lib-es/bridge/getFeesForTransaction.js +13 -1
  103. package/lib-es/bridge/getFeesForTransaction.js.map +1 -1
  104. package/lib-es/bridge/getOperationExtra.d.ts +2 -0
  105. package/lib-es/bridge/getOperationExtra.d.ts.map +1 -0
  106. package/lib-es/bridge/getOperationExtra.js +2 -0
  107. package/lib-es/bridge/getOperationExtra.js.map +1 -0
  108. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  109. package/lib-es/bridge/getTransactionStatus.js +46 -21
  110. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  111. package/lib-es/bridge/preload.d.ts.map +1 -1
  112. package/lib-es/bridge/preload.js +5 -3
  113. package/lib-es/bridge/preload.js.map +1 -1
  114. package/lib-es/bridge/preload.test.js +14 -218
  115. package/lib-es/bridge/preload.test.js.map +1 -1
  116. package/lib-es/bridge/prepareTransaction.js +1 -1
  117. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  118. package/lib-es/bridge/synchronisation.d.ts.map +1 -1
  119. package/lib-es/bridge/synchronisation.js +6 -3
  120. package/lib-es/bridge/synchronisation.js.map +1 -1
  121. package/lib-es/bridge/synchronisation.test.js +332 -7
  122. package/lib-es/bridge/synchronisation.test.js.map +1 -1
  123. package/lib-es/bridge/utils.d.ts +1 -1
  124. package/lib-es/bridge/utils.d.ts.map +1 -1
  125. package/lib-es/bridge/utils.js +22 -0
  126. package/lib-es/bridge/utils.js.map +1 -1
  127. package/lib-es/constants.d.ts +4 -0
  128. package/lib-es/constants.d.ts.map +1 -0
  129. package/lib-es/constants.js +4 -0
  130. package/lib-es/constants.js.map +1 -0
  131. package/lib-es/errors.d.ts +13 -0
  132. package/lib-es/errors.d.ts.map +1 -0
  133. package/lib-es/errors.js +18 -0
  134. package/lib-es/errors.js.map +1 -0
  135. package/lib-es/logic/craftTransaction.d.ts +5 -10
  136. package/lib-es/logic/craftTransaction.d.ts.map +1 -1
  137. package/lib-es/logic/craftTransaction.js +2 -1
  138. package/lib-es/logic/craftTransaction.js.map +1 -1
  139. package/lib-es/logic/estimateFees.d.ts +1 -1
  140. package/lib-es/logic/estimateFees.d.ts.map +1 -1
  141. package/lib-es/logic/estimateFees.js +14 -2
  142. package/lib-es/logic/estimateFees.js.map +1 -1
  143. package/lib-es/logic/index.d.ts +2 -1
  144. package/lib-es/logic/index.d.ts.map +1 -1
  145. package/lib-es/logic/index.js +1 -0
  146. package/lib-es/logic/index.js.map +1 -1
  147. package/lib-es/logic/stake.d.ts +3 -0
  148. package/lib-es/logic/stake.d.ts.map +1 -0
  149. package/lib-es/logic/stake.js +8 -0
  150. package/lib-es/logic/stake.js.map +1 -0
  151. package/lib-es/network/index.d.ts +5 -4
  152. package/lib-es/network/index.d.ts.map +1 -1
  153. package/lib-es/network/index.js +4 -3
  154. package/lib-es/network/index.js.map +1 -1
  155. package/lib-es/network/sdk.d.ts +5 -3
  156. package/lib-es/network/sdk.d.ts.map +1 -1
  157. package/lib-es/network/sdk.js +144 -25
  158. package/lib-es/network/sdk.js.map +1 -1
  159. package/lib-es/network/sdk.test.js +491 -6
  160. package/lib-es/network/sdk.test.js.map +1 -1
  161. package/lib-es/types/bridge.d.ts +33 -6
  162. package/lib-es/types/bridge.d.ts.map +1 -1
  163. package/package.json +20 -12
  164. package/src/bridge/broadcast.ts +3 -0
  165. package/src/bridge/buildOptimisticOperation.ts +47 -4
  166. package/src/bridge/buildTransaction.test.ts +4 -0
  167. package/src/bridge/buildTransaction.ts +3 -1
  168. package/src/bridge/estimateMaxSpendable.test.ts +33 -0
  169. package/src/bridge/estimateMaxSpendable.ts +17 -3
  170. package/src/bridge/getFeesForTransaction.ts +14 -1
  171. package/src/bridge/getOperationExtra.ts +1 -0
  172. package/src/bridge/getTransactionStatus.ts +53 -21
  173. package/src/bridge/preload.test.ts +13 -279
  174. package/src/bridge/preload.ts +5 -3
  175. package/src/bridge/prepareTransaction.ts +1 -1
  176. package/src/bridge/synchronisation.test.ts +389 -7
  177. package/src/bridge/synchronisation.ts +6 -3
  178. package/src/bridge/utils.ts +25 -1
  179. package/src/constants.ts +4 -0
  180. package/src/errors.ts +21 -0
  181. package/src/logic/craftTransaction.ts +6 -9
  182. package/src/logic/estimateFees.ts +16 -1
  183. package/src/logic/index.ts +2 -1
  184. package/src/logic/stake.ts +9 -0
  185. package/src/network/index.ts +6 -3
  186. package/src/network/sdk.test.ts +538 -10
  187. package/src/network/sdk.ts +179 -31
  188. package/src/types/bridge.ts +32 -6
@@ -42,6 +42,20 @@ jest.mock("@mysten/sui/client", () => {
42
42
  },
43
43
  }),
44
44
  getReferenceGasPrice: jest.fn().mockResolvedValue("1000"),
45
+ getTransactionBlock: jest.fn().mockResolvedValue({
46
+ transaction: {
47
+ data: {
48
+ transaction: {
49
+ kind: "ProgrammableTransaction",
50
+ inputs: [],
51
+ transactions: [],
52
+ },
53
+ },
54
+ },
55
+ effects: {
56
+ status: { status: "success" },
57
+ },
58
+ }),
45
59
  })),
46
60
  getFullnodeUrl: jest.fn().mockReturnValue("https://mockapi.sui.io"),
47
61
  };
@@ -62,7 +76,14 @@ jest.mock("@mysten/sui/transactions", () => {
62
76
  setSender: jest.fn(),
63
77
  splitCoins: jest.fn().mockReturnValue(["0xmock_coin"]),
64
78
  transferObjects: jest.fn(),
79
+ moveCall: jest.fn(),
80
+ object: jest.fn(),
81
+ pure: {
82
+ address: jest.fn(),
83
+ u64: jest.fn(),
84
+ },
65
85
  build: jest.fn().mockResolvedValue(mockTxb),
86
+ setGasBudgetIfNotSet: jest.fn(),
66
87
  };
67
88
  }),
68
89
  };
@@ -168,6 +189,9 @@ const mockTransaction = {
168
189
 
169
190
  const mockApi = new SuiClient({ url: "mock" }) as jest.Mocked<SuiClient>;
170
191
 
192
+ // Add getTransactionBlock method to mockApi
193
+ mockApi.getTransactionBlock = jest.fn();
194
+
171
195
  // Helper function to generate mock coins from an array of balances
172
196
  const createMockCoins = (balances: string[]): any[] => {
173
197
  return balances.map((balance, index) => ({
@@ -230,16 +254,16 @@ describe("SDK Functions", () => {
230
254
 
231
255
  test("getOperationType should return IN for incoming tx", () => {
232
256
  const address = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
233
- expect(
234
- sdk.getOperationType(address, mockTransaction.transaction?.data as TransactionBlockData),
235
- ).toBe("IN");
257
+ expect(sdk.getOperationType(address, mockTransaction as SuiTransactionBlockResponse)).toBe(
258
+ "IN",
259
+ );
236
260
  });
237
261
 
238
262
  test("getOperationType should return OUT for outgoing tx", () => {
239
263
  const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
240
- expect(
241
- sdk.getOperationType(address, mockTransaction.transaction?.data as TransactionBlockData),
242
- ).toBe("OUT");
264
+ expect(sdk.getOperationType(address, mockTransaction as SuiTransactionBlockResponse)).toBe(
265
+ "OUT",
266
+ );
243
267
  });
244
268
 
245
269
  test("getOperationSenders should return sender address", () => {
@@ -526,6 +550,512 @@ describe("SDK Functions", () => {
526
550
  });
527
551
  });
528
552
 
553
+ describe("Staking Operations", () => {
554
+ describe("Operation Type Detection", () => {
555
+ test("getOperationType should return DELEGATE for staking transaction", () => {
556
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
557
+
558
+ // Create a mock staking transaction
559
+ const mockStakingTx = {
560
+ digest: "delegate_tx_digest_123",
561
+ transaction: {
562
+ data: {
563
+ sender: address,
564
+ transaction: {
565
+ kind: "ProgrammableTransaction",
566
+ inputs: [],
567
+ transactions: [
568
+ {
569
+ MoveCall: {
570
+ function: "request_add_stake",
571
+ },
572
+ },
573
+ ],
574
+ },
575
+ },
576
+ },
577
+ effects: {
578
+ status: { status: "success" },
579
+ gasUsed: {
580
+ computationCost: "1000000",
581
+ storageCost: "500000",
582
+ storageRebate: "450000",
583
+ },
584
+ },
585
+ balanceChanges: [
586
+ {
587
+ owner: { AddressOwner: address },
588
+ coinType: "0x2::sui::SUI",
589
+ amount: "-1000000000",
590
+ },
591
+ ],
592
+ timestampMs: "1742294454878",
593
+ checkpoint: "313024",
594
+ } as unknown as SuiTransactionBlockResponse;
595
+
596
+ expect(sdk.getOperationType(address, mockStakingTx)).toBe("DELEGATE");
597
+ });
598
+
599
+ test("getOperationType should return UNDELEGATE for unstaking transaction", () => {
600
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
601
+
602
+ // Create a mock unstaking transaction
603
+ const mockUnstakingTx = {
604
+ digest: "undelegate_tx_digest_456",
605
+ transaction: {
606
+ data: {
607
+ sender: address,
608
+ transaction: {
609
+ kind: "ProgrammableTransaction",
610
+ inputs: [],
611
+ transactions: [
612
+ {
613
+ MoveCall: {
614
+ function: "request_withdraw_stake",
615
+ },
616
+ },
617
+ ],
618
+ },
619
+ },
620
+ },
621
+ effects: {
622
+ status: { status: "success" },
623
+ gasUsed: {
624
+ computationCost: "1000000",
625
+ storageCost: "500000",
626
+ storageRebate: "450000",
627
+ },
628
+ },
629
+ balanceChanges: [
630
+ {
631
+ owner: { AddressOwner: address },
632
+ coinType: "0x2::sui::SUI",
633
+ amount: "0",
634
+ },
635
+ ],
636
+ timestampMs: "1742294454878",
637
+ checkpoint: "313024",
638
+ } as unknown as SuiTransactionBlockResponse;
639
+
640
+ expect(sdk.getOperationType(address, mockUnstakingTx)).toBe("UNDELEGATE");
641
+ });
642
+ });
643
+
644
+ describe("Operation Amount Calculation", () => {
645
+ test("getOperationAmount should calculate staking amount correctly", () => {
646
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
647
+
648
+ const mockStakingTx = {
649
+ transaction: {
650
+ data: {
651
+ transaction: {
652
+ kind: "ProgrammableTransaction",
653
+ transactions: [
654
+ {
655
+ MoveCall: {
656
+ function: "request_add_stake",
657
+ },
658
+ },
659
+ ],
660
+ },
661
+ },
662
+ },
663
+ balanceChanges: [
664
+ {
665
+ owner: { AddressOwner: address },
666
+ coinType: "0x2::sui::SUI",
667
+ amount: "-1000000000",
668
+ },
669
+ ],
670
+ } as unknown as SuiTransactionBlockResponse;
671
+
672
+ const amount = sdk.getOperationAmount(address, mockStakingTx, sdk.DEFAULT_COIN_TYPE);
673
+ expect(amount).toEqual(new BigNumber("1000000000")); // The function returns minus of the balance change
674
+ });
675
+
676
+ test("getOperationAmount should calculate unstaking amount correctly", () => {
677
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
678
+
679
+ const mockUnstakingTx = {
680
+ transaction: {
681
+ data: {
682
+ transaction: {
683
+ kind: "ProgrammableTransaction",
684
+ transactions: [
685
+ {
686
+ MoveCall: {
687
+ function: "request_withdraw_stake",
688
+ },
689
+ },
690
+ ],
691
+ },
692
+ },
693
+ },
694
+ balanceChanges: [
695
+ {
696
+ owner: { AddressOwner: address },
697
+ coinType: "0x2::sui::SUI",
698
+ amount: "0",
699
+ },
700
+ ],
701
+ } as unknown as SuiTransactionBlockResponse;
702
+
703
+ const amount = sdk.getOperationAmount(address, mockUnstakingTx, sdk.DEFAULT_COIN_TYPE);
704
+ expect(amount).toEqual(new BigNumber("0"));
705
+ });
706
+ });
707
+
708
+ describe("Operation Recipients", () => {
709
+ test("getOperationRecipients should return empty array for staking transaction", () => {
710
+ const mockStakingTx = {
711
+ transaction: {
712
+ data: {
713
+ transaction: {
714
+ kind: "ProgrammableTransaction",
715
+ inputs: [],
716
+ transactions: [
717
+ {
718
+ MoveCall: {
719
+ function: "request_add_stake",
720
+ },
721
+ },
722
+ ],
723
+ },
724
+ },
725
+ },
726
+ } as unknown as SuiTransactionBlockResponse;
727
+
728
+ const recipients = sdk.getOperationRecipients(mockStakingTx.transaction?.data);
729
+ expect(recipients).toEqual([]);
730
+ });
731
+
732
+ test("getOperationRecipients should return empty array for unstaking transaction", () => {
733
+ const mockUnstakingTx = {
734
+ transaction: {
735
+ data: {
736
+ transaction: {
737
+ kind: "ProgrammableTransaction",
738
+ inputs: [],
739
+ transactions: [
740
+ {
741
+ MoveCall: {
742
+ function: "request_withdraw_stake",
743
+ },
744
+ },
745
+ ],
746
+ },
747
+ },
748
+ },
749
+ } as unknown as SuiTransactionBlockResponse;
750
+
751
+ const recipients = sdk.getOperationRecipients(mockUnstakingTx.transaction?.data);
752
+ expect(recipients).toEqual([]);
753
+ });
754
+ });
755
+
756
+ describe("Transaction Creation", () => {
757
+ test("createTransaction should build delegate transaction", async () => {
758
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
759
+ const transaction = {
760
+ mode: "delegate" as const,
761
+ coinType: sdk.DEFAULT_COIN_TYPE,
762
+ amount: new BigNumber(1000000000), // 1 SUI
763
+ recipient: "0xvalidator_address_123",
764
+ };
765
+
766
+ const tx = await sdk.createTransaction(address, transaction);
767
+ expect(tx).toBeDefined();
768
+ });
769
+
770
+ test("createTransaction should build undelegate transaction with specific amount", async () => {
771
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
772
+ const transaction = {
773
+ mode: "undelegate" as const,
774
+ coinType: sdk.DEFAULT_COIN_TYPE,
775
+ amount: new BigNumber(500000000), // 0.5 SUI
776
+ stakedSuiId: "0xstaked_sui_object_123",
777
+ useAllAmount: false,
778
+ recipient: "0xvalidator_address_123", // Required by type but not used for undelegate
779
+ };
780
+
781
+ const tx = await sdk.createTransaction(address, transaction);
782
+ expect(tx).toBeDefined();
783
+ });
784
+
785
+ test("createTransaction should build undelegate transaction with all amount", async () => {
786
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
787
+ const transaction = {
788
+ mode: "undelegate" as const,
789
+ coinType: sdk.DEFAULT_COIN_TYPE,
790
+ amount: new BigNumber(0),
791
+ stakedSuiId: "0xstaked_sui_object_123",
792
+ useAllAmount: true,
793
+ recipient: "0xvalidator_address_123", // Required by type but not used for undelegate
794
+ };
795
+
796
+ const tx = await sdk.createTransaction(address, transaction);
797
+ expect(tx).toBeDefined();
798
+ });
799
+ });
800
+
801
+ describe("Payment Info for Staking", () => {
802
+ test("paymentInfo should return gas budget and fees for delegate transaction", async () => {
803
+ const sender = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
804
+ const fakeTransaction = {
805
+ mode: "delegate" as const,
806
+ coinType: sdk.DEFAULT_COIN_TYPE,
807
+ family: "sui" as const,
808
+ amount: new BigNumber(1000000000), // 1 SUI
809
+ recipient: "0xvalidator_address_123",
810
+ errors: {},
811
+ };
812
+ const info = await sdk.paymentInfo(sender, fakeTransaction);
813
+ expect(info).toHaveProperty("gasBudget");
814
+ expect(info).toHaveProperty("totalGasUsed");
815
+ expect(info).toHaveProperty("fees");
816
+ });
817
+
818
+ test("paymentInfo should return gas budget and fees for undelegate transaction", async () => {
819
+ const sender = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
820
+ const fakeTransaction = {
821
+ mode: "undelegate" as const,
822
+ coinType: sdk.DEFAULT_COIN_TYPE,
823
+ family: "sui" as const,
824
+ amount: new BigNumber(500000000), // 0.5 SUI
825
+ stakedSuiId: "0xstaked_sui_object_123",
826
+ useAllAmount: false,
827
+ recipient: "0xvalidator_address_123", // Required by type but not used for undelegate
828
+ errors: {},
829
+ };
830
+ const info = await sdk.paymentInfo(sender, fakeTransaction);
831
+ expect(info).toHaveProperty("gasBudget");
832
+ expect(info).toHaveProperty("totalGasUsed");
833
+ expect(info).toHaveProperty("fees");
834
+ });
835
+ });
836
+
837
+ describe("Transaction to Operation Mapping", () => {
838
+ test("transactionToOperation should map staking transaction correctly", () => {
839
+ const accountId = "mockAccountId";
840
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
841
+
842
+ const mockStakingTx = {
843
+ digest: "delegate_tx_digest_123",
844
+ transaction: {
845
+ data: {
846
+ sender: address,
847
+ transaction: {
848
+ kind: "ProgrammableTransaction",
849
+ inputs: [],
850
+ transactions: [
851
+ {
852
+ MoveCall: {
853
+ function: "request_add_stake",
854
+ },
855
+ },
856
+ ],
857
+ },
858
+ },
859
+ },
860
+ effects: {
861
+ status: { status: "success" },
862
+ gasUsed: {
863
+ computationCost: "1000000",
864
+ storageCost: "500000",
865
+ storageRebate: "450000",
866
+ },
867
+ },
868
+ balanceChanges: [
869
+ {
870
+ owner: { AddressOwner: address },
871
+ coinType: "0x2::sui::SUI",
872
+ amount: "-1000000000",
873
+ },
874
+ ],
875
+ timestampMs: "1742294454878",
876
+ checkpoint: "313024",
877
+ } as unknown as SuiTransactionBlockResponse;
878
+
879
+ const operation = sdk.transactionToOperation(accountId, address, mockStakingTx);
880
+
881
+ expect(operation).toHaveProperty("id");
882
+ expect(operation).toHaveProperty("accountId", accountId);
883
+ expect(operation).toHaveProperty("type", "DELEGATE");
884
+ expect(operation).toHaveProperty("hash", "delegate_tx_digest_123");
885
+ expect(operation).toHaveProperty("extra");
886
+ expect((operation.extra as { coinType: string }).coinType).toBe(sdk.DEFAULT_COIN_TYPE);
887
+ expect(operation.value).toEqual(new BigNumber("1000000000")); // The function returns minus of the balance change
888
+ expect(operation.recipients).toEqual([]);
889
+ expect(operation.senders).toEqual([address]);
890
+ });
891
+
892
+ test("transactionToOperation should map unstaking transaction correctly", () => {
893
+ const accountId = "mockAccountId";
894
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
895
+
896
+ const mockUnstakingTx = {
897
+ digest: "undelegate_tx_digest_456",
898
+ transaction: {
899
+ data: {
900
+ sender: address,
901
+ transaction: {
902
+ kind: "ProgrammableTransaction",
903
+ inputs: [],
904
+ transactions: [
905
+ {
906
+ MoveCall: {
907
+ function: "request_withdraw_stake",
908
+ },
909
+ },
910
+ ],
911
+ },
912
+ },
913
+ },
914
+ effects: {
915
+ status: { status: "success" },
916
+ gasUsed: {
917
+ computationCost: "1000000",
918
+ storageCost: "500000",
919
+ storageRebate: "450000",
920
+ },
921
+ },
922
+ balanceChanges: [
923
+ {
924
+ owner: { AddressOwner: address },
925
+ coinType: "0x2::sui::SUI",
926
+ amount: "0",
927
+ },
928
+ ],
929
+ timestampMs: "1742294454878",
930
+ checkpoint: "313024",
931
+ } as unknown as SuiTransactionBlockResponse;
932
+
933
+ const operation = sdk.transactionToOperation(accountId, address, mockUnstakingTx);
934
+
935
+ expect(operation).toHaveProperty("id");
936
+ expect(operation).toHaveProperty("accountId", accountId);
937
+ expect(operation).toHaveProperty("type", "UNDELEGATE");
938
+ expect(operation).toHaveProperty("hash", "undelegate_tx_digest_456");
939
+ expect(operation).toHaveProperty("extra");
940
+ expect((operation.extra as { coinType: string }).coinType).toBe(sdk.DEFAULT_COIN_TYPE);
941
+ expect(operation.value).toEqual(new BigNumber("0"));
942
+ expect(operation.recipients).toEqual([]);
943
+ expect(operation.senders).toEqual([address]);
944
+ });
945
+
946
+ test("transactionToOp should map staking transaction correctly", () => {
947
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
948
+
949
+ const mockStakingTx = {
950
+ digest: "delegate_tx_digest_123",
951
+ transaction: {
952
+ data: {
953
+ sender: address,
954
+ transaction: {
955
+ kind: "ProgrammableTransaction",
956
+ inputs: [],
957
+ transactions: [
958
+ {
959
+ MoveCall: {
960
+ function: "request_add_stake",
961
+ },
962
+ },
963
+ ],
964
+ },
965
+ },
966
+ },
967
+ effects: {
968
+ status: { status: "success" },
969
+ gasUsed: {
970
+ computationCost: "1000000",
971
+ storageCost: "500000",
972
+ storageRebate: "450000",
973
+ },
974
+ },
975
+ balanceChanges: [
976
+ {
977
+ owner: { AddressOwner: address },
978
+ coinType: "0x2::sui::SUI",
979
+ amount: "-1000000000",
980
+ },
981
+ ],
982
+ timestampMs: "1742294454878",
983
+ checkpoint: "313024",
984
+ } as unknown as SuiTransactionBlockResponse;
985
+
986
+ const operation = sdk.transactionToOp(address, mockStakingTx);
987
+
988
+ expect(operation.id).toEqual("delegate_tx_digest_123");
989
+ expect(operation.type).toEqual("DELEGATE");
990
+ expect(operation.senders).toEqual([address]);
991
+ expect(operation.recipients).toEqual([]);
992
+ expect(operation.value).toEqual(1000000000n); // The function returns minus of the balance change
993
+ expect(operation.asset).toEqual({ type: "native" });
994
+ });
995
+
996
+ test("transactionToOp should map unstaking transaction correctly", () => {
997
+ const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
998
+
999
+ const mockUnstakingTx = {
1000
+ digest: "undelegate_tx_digest_456",
1001
+ transaction: {
1002
+ data: {
1003
+ sender: address,
1004
+ transaction: {
1005
+ kind: "ProgrammableTransaction",
1006
+ inputs: [],
1007
+ transactions: [
1008
+ {
1009
+ MoveCall: {
1010
+ function: "request_withdraw_stake",
1011
+ },
1012
+ },
1013
+ ],
1014
+ },
1015
+ },
1016
+ },
1017
+ effects: {
1018
+ status: { status: "success" },
1019
+ gasUsed: {
1020
+ computationCost: "1000000",
1021
+ storageCost: "500000",
1022
+ storageRebate: "450000",
1023
+ },
1024
+ },
1025
+ balanceChanges: [
1026
+ {
1027
+ owner: { AddressOwner: address },
1028
+ coinType: "0x2::sui::SUI",
1029
+ amount: "0",
1030
+ },
1031
+ ],
1032
+ timestampMs: "1742294454878",
1033
+ checkpoint: "313024",
1034
+ } as unknown as SuiTransactionBlockResponse;
1035
+
1036
+ const operation = sdk.transactionToOp(address, mockUnstakingTx);
1037
+
1038
+ expect(operation.id).toEqual("undelegate_tx_digest_456");
1039
+ expect(operation.type).toEqual("UNDELEGATE");
1040
+ expect(operation.senders).toEqual([address]);
1041
+ expect(operation.recipients).toEqual([]);
1042
+ expect(operation.value).toEqual(0n);
1043
+ expect(operation.asset).toEqual({ type: "native" });
1044
+ });
1045
+ });
1046
+
1047
+ describe("Operation Extra Information", () => {
1048
+ test("getOperationExtra should be a function", () => {
1049
+ expect(typeof sdk.getOperationExtra).toBe("function");
1050
+ });
1051
+
1052
+ test("getOperationExtra should return a Promise", () => {
1053
+ const result = sdk.getOperationExtra("test_digest");
1054
+ expect(result).toBeInstanceOf(Promise);
1055
+ });
1056
+ });
1057
+ });
1058
+
529
1059
  describe("queryTransactions", () => {
530
1060
  it("should call api.queryTransactionBlocks with correct params for IN", async () => {
531
1061
  mockApi.queryTransactionBlocks.mockResolvedValueOnce({
@@ -1356,10 +1886,8 @@ describe("filterOperations", () => {
1356
1886
  expect(
1357
1887
  sdk.toBlockOperation({
1358
1888
  owner: {
1359
- ConsensusV2: {
1360
- authenticator: {
1361
- SingleOwner: "test",
1362
- },
1889
+ ConsensusAddressOwner: {
1890
+ owner: "test",
1363
1891
  start_version: "1",
1364
1892
  },
1365
1893
  },