@ledgerhq/coin-sui 0.16.0-nightly.7 → 0.16.0-nightly.9

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 (277) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +20 -0
  3. package/lib/logic/estimateFees.d.ts +4 -1
  4. package/lib/logic/estimateFees.d.ts.map +1 -1
  5. package/lib/logic/estimateFees.js +2 -1
  6. package/lib/logic/estimateFees.js.map +1 -1
  7. package/lib-es/logic/estimateFees.d.ts +4 -1
  8. package/lib-es/logic/estimateFees.d.ts.map +1 -1
  9. package/lib-es/logic/estimateFees.js +2 -1
  10. package/lib-es/logic/estimateFees.js.map +1 -1
  11. package/package.json +6 -6
  12. package/src/logic/estimateFees.test.ts +22 -16
  13. package/src/logic/estimateFees.ts +6 -1
  14. package/lib/api/index.integration.test.d.ts +0 -2
  15. package/lib/api/index.integration.test.d.ts.map +0 -1
  16. package/lib/api/index.integration.test.js +0 -185
  17. package/lib/api/index.integration.test.js.map +0 -1
  18. package/lib/api/index.test.d.ts +0 -2
  19. package/lib/api/index.test.d.ts.map +0 -1
  20. package/lib/api/index.test.js +0 -173
  21. package/lib/api/index.test.js.map +0 -1
  22. package/lib/bridge/bridge.integration.test.d.ts +0 -4
  23. package/lib/bridge/bridge.integration.test.d.ts.map +0 -1
  24. package/lib/bridge/bridge.integration.test.js +0 -145
  25. package/lib/bridge/bridge.integration.test.js.map +0 -1
  26. package/lib/bridge/broadcast.test.d.ts +0 -2
  27. package/lib/bridge/broadcast.test.d.ts.map +0 -1
  28. package/lib/bridge/broadcast.test.js +0 -48
  29. package/lib/bridge/broadcast.test.js.map +0 -1
  30. package/lib/bridge/buildOptimisticOperation.test.d.ts +0 -2
  31. package/lib/bridge/buildOptimisticOperation.test.d.ts.map +0 -1
  32. package/lib/bridge/buildOptimisticOperation.test.js +0 -52
  33. package/lib/bridge/buildOptimisticOperation.test.js.map +0 -1
  34. package/lib/bridge/buildTransaction.integration.test.d.ts +0 -2
  35. package/lib/bridge/buildTransaction.integration.test.d.ts.map +0 -1
  36. package/lib/bridge/buildTransaction.integration.test.js +0 -72
  37. package/lib/bridge/buildTransaction.integration.test.js.map +0 -1
  38. package/lib/bridge/buildTransaction.test.d.ts +0 -2
  39. package/lib/bridge/buildTransaction.test.d.ts.map +0 -1
  40. package/lib/bridge/buildTransaction.test.js +0 -231
  41. package/lib/bridge/buildTransaction.test.js.map +0 -1
  42. package/lib/bridge/estimateMaxSpendable.test.d.ts +0 -2
  43. package/lib/bridge/estimateMaxSpendable.test.d.ts.map +0 -1
  44. package/lib/bridge/estimateMaxSpendable.test.js +0 -52
  45. package/lib/bridge/estimateMaxSpendable.test.js.map +0 -1
  46. package/lib/bridge/formatters.test.d.ts +0 -2
  47. package/lib/bridge/formatters.test.d.ts.map +0 -1
  48. package/lib/bridge/formatters.test.js +0 -18
  49. package/lib/bridge/formatters.test.js.map +0 -1
  50. package/lib/bridge/getFeesForTransaction.test.d.ts +0 -2
  51. package/lib/bridge/getFeesForTransaction.test.d.ts.map +0 -1
  52. package/lib/bridge/getFeesForTransaction.test.js +0 -35
  53. package/lib/bridge/getFeesForTransaction.test.js.map +0 -1
  54. package/lib/bridge/getTransactionStatus.test.d.ts +0 -2
  55. package/lib/bridge/getTransactionStatus.test.d.ts.map +0 -1
  56. package/lib/bridge/getTransactionStatus.test.js +0 -69
  57. package/lib/bridge/getTransactionStatus.test.js.map +0 -1
  58. package/lib/bridge/index.test.d.ts +0 -2
  59. package/lib/bridge/index.test.d.ts.map +0 -1
  60. package/lib/bridge/index.test.js +0 -265
  61. package/lib/bridge/index.test.js.map +0 -1
  62. package/lib/bridge/preload.test.d.ts +0 -2
  63. package/lib/bridge/preload.test.d.ts.map +0 -1
  64. package/lib/bridge/preload.test.js +0 -52
  65. package/lib/bridge/preload.test.js.map +0 -1
  66. package/lib/bridge/prepareTransaction.test.d.ts +0 -2
  67. package/lib/bridge/prepareTransaction.test.d.ts.map +0 -1
  68. package/lib/bridge/prepareTransaction.test.js +0 -97
  69. package/lib/bridge/prepareTransaction.test.js.map +0 -1
  70. package/lib/bridge/serialization.test.d.ts +0 -2
  71. package/lib/bridge/serialization.test.d.ts.map +0 -1
  72. package/lib/bridge/serialization.test.js +0 -131
  73. package/lib/bridge/serialization.test.js.map +0 -1
  74. package/lib/bridge/signOperation.integration.test.d.ts +0 -2
  75. package/lib/bridge/signOperation.integration.test.d.ts.map +0 -1
  76. package/lib/bridge/signOperation.integration.test.js +0 -80
  77. package/lib/bridge/signOperation.integration.test.js.map +0 -1
  78. package/lib/bridge/signOperation.test.d.ts +0 -2
  79. package/lib/bridge/signOperation.test.d.ts.map +0 -1
  80. package/lib/bridge/signOperation.test.js +0 -445
  81. package/lib/bridge/signOperation.test.js.map +0 -1
  82. package/lib/bridge/synchronisation.test.d.ts +0 -2
  83. package/lib/bridge/synchronisation.test.d.ts.map +0 -1
  84. package/lib/bridge/synchronisation.test.js +0 -505
  85. package/lib/bridge/synchronisation.test.js.map +0 -1
  86. package/lib/bridge/transaction.test.d.ts +0 -2
  87. package/lib/bridge/transaction.test.d.ts.map +0 -1
  88. package/lib/bridge/transaction.test.js +0 -68
  89. package/lib/bridge/transaction.test.js.map +0 -1
  90. package/lib/logic/broadcast.test.d.ts +0 -2
  91. package/lib/logic/broadcast.test.d.ts.map +0 -1
  92. package/lib/logic/broadcast.test.js +0 -62
  93. package/lib/logic/broadcast.test.js.map +0 -1
  94. package/lib/logic/combine.test.d.ts +0 -2
  95. package/lib/logic/combine.test.d.ts.map +0 -1
  96. package/lib/logic/combine.test.js +0 -37
  97. package/lib/logic/combine.test.js.map +0 -1
  98. package/lib/logic/craftTransaction.integration.test.d.ts +0 -2
  99. package/lib/logic/craftTransaction.integration.test.d.ts.map +0 -1
  100. package/lib/logic/craftTransaction.integration.test.js +0 -98
  101. package/lib/logic/craftTransaction.integration.test.js.map +0 -1
  102. package/lib/logic/craftTransaction.test.d.ts +0 -2
  103. package/lib/logic/craftTransaction.test.d.ts.map +0 -1
  104. package/lib/logic/craftTransaction.test.js +0 -127
  105. package/lib/logic/craftTransaction.test.js.map +0 -1
  106. package/lib/logic/estimateFees.integration.test.d.ts +0 -2
  107. package/lib/logic/estimateFees.integration.test.d.ts.map +0 -1
  108. package/lib/logic/estimateFees.integration.test.js +0 -82
  109. package/lib/logic/estimateFees.integration.test.js.map +0 -1
  110. package/lib/logic/estimateFees.test.d.ts +0 -2
  111. package/lib/logic/estimateFees.test.d.ts.map +0 -1
  112. package/lib/logic/estimateFees.test.js +0 -70
  113. package/lib/logic/estimateFees.test.js.map +0 -1
  114. package/lib/logic/getBalance.integration.test.d.ts +0 -2
  115. package/lib/logic/getBalance.integration.test.d.ts.map +0 -1
  116. package/lib/logic/getBalance.integration.test.js +0 -56
  117. package/lib/logic/getBalance.integration.test.js.map +0 -1
  118. package/lib/logic/getBalance.test.d.ts +0 -2
  119. package/lib/logic/getBalance.test.d.ts.map +0 -1
  120. package/lib/logic/getBalance.test.js +0 -64
  121. package/lib/logic/getBalance.test.js.map +0 -1
  122. package/lib/logic/lastBlock.test.d.ts +0 -2
  123. package/lib/logic/lastBlock.test.d.ts.map +0 -1
  124. package/lib/logic/lastBlock.test.js +0 -27
  125. package/lib/logic/lastBlock.test.js.map +0 -1
  126. package/lib/logic/listOperations.test.d.ts +0 -2
  127. package/lib/logic/listOperations.test.d.ts.map +0 -1
  128. package/lib/logic/listOperations.test.js +0 -79
  129. package/lib/logic/listOperations.test.js.map +0 -1
  130. package/lib/network/sdk.integration.test.d.ts +0 -2
  131. package/lib/network/sdk.integration.test.d.ts.map +0 -1
  132. package/lib/network/sdk.integration.test.js +0 -215
  133. package/lib/network/sdk.integration.test.js.map +0 -1
  134. package/lib/network/sdk.test.d.ts +0 -2
  135. package/lib/network/sdk.test.d.ts.map +0 -1
  136. package/lib/network/sdk.test.js +0 -1814
  137. package/lib/network/sdk.test.js.map +0 -1
  138. package/lib/signer/getAddress.test.d.ts +0 -2
  139. package/lib/signer/getAddress.test.d.ts.map +0 -1
  140. package/lib/signer/getAddress.test.js +0 -106
  141. package/lib/signer/getAddress.test.js.map +0 -1
  142. package/lib/test/config.test.d.ts +0 -2
  143. package/lib/test/config.test.d.ts.map +0 -1
  144. package/lib/test/config.test.js +0 -44
  145. package/lib/test/config.test.js.map +0 -1
  146. package/lib-es/api/index.integration.test.d.ts +0 -2
  147. package/lib-es/api/index.integration.test.d.ts.map +0 -1
  148. package/lib-es/api/index.integration.test.js +0 -183
  149. package/lib-es/api/index.integration.test.js.map +0 -1
  150. package/lib-es/api/index.test.d.ts +0 -2
  151. package/lib-es/api/index.test.d.ts.map +0 -1
  152. package/lib-es/api/index.test.js +0 -148
  153. package/lib-es/api/index.test.js.map +0 -1
  154. package/lib-es/bridge/bridge.integration.test.d.ts +0 -4
  155. package/lib-es/bridge/bridge.integration.test.d.ts.map +0 -1
  156. package/lib-es/bridge/bridge.integration.test.js +0 -139
  157. package/lib-es/bridge/bridge.integration.test.js.map +0 -1
  158. package/lib-es/bridge/broadcast.test.d.ts +0 -2
  159. package/lib-es/bridge/broadcast.test.d.ts.map +0 -1
  160. package/lib-es/bridge/broadcast.test.js +0 -46
  161. package/lib-es/bridge/broadcast.test.js.map +0 -1
  162. package/lib-es/bridge/buildOptimisticOperation.test.d.ts +0 -2
  163. package/lib-es/bridge/buildOptimisticOperation.test.d.ts.map +0 -1
  164. package/lib-es/bridge/buildOptimisticOperation.test.js +0 -47
  165. package/lib-es/bridge/buildOptimisticOperation.test.js.map +0 -1
  166. package/lib-es/bridge/buildTransaction.integration.test.d.ts +0 -2
  167. package/lib-es/bridge/buildTransaction.integration.test.d.ts.map +0 -1
  168. package/lib-es/bridge/buildTransaction.integration.test.js +0 -67
  169. package/lib-es/bridge/buildTransaction.integration.test.js.map +0 -1
  170. package/lib-es/bridge/buildTransaction.test.d.ts +0 -2
  171. package/lib-es/bridge/buildTransaction.test.d.ts.map +0 -1
  172. package/lib-es/bridge/buildTransaction.test.js +0 -229
  173. package/lib-es/bridge/buildTransaction.test.js.map +0 -1
  174. package/lib-es/bridge/estimateMaxSpendable.test.d.ts +0 -2
  175. package/lib-es/bridge/estimateMaxSpendable.test.d.ts.map +0 -1
  176. package/lib-es/bridge/estimateMaxSpendable.test.js +0 -50
  177. package/lib-es/bridge/estimateMaxSpendable.test.js.map +0 -1
  178. package/lib-es/bridge/formatters.test.d.ts +0 -2
  179. package/lib-es/bridge/formatters.test.d.ts.map +0 -1
  180. package/lib-es/bridge/formatters.test.js +0 -16
  181. package/lib-es/bridge/formatters.test.js.map +0 -1
  182. package/lib-es/bridge/getFeesForTransaction.test.d.ts +0 -2
  183. package/lib-es/bridge/getFeesForTransaction.test.d.ts.map +0 -1
  184. package/lib-es/bridge/getFeesForTransaction.test.js +0 -30
  185. package/lib-es/bridge/getFeesForTransaction.test.js.map +0 -1
  186. package/lib-es/bridge/getTransactionStatus.test.d.ts +0 -2
  187. package/lib-es/bridge/getTransactionStatus.test.d.ts.map +0 -1
  188. package/lib-es/bridge/getTransactionStatus.test.js +0 -64
  189. package/lib-es/bridge/getTransactionStatus.test.js.map +0 -1
  190. package/lib-es/bridge/index.test.d.ts +0 -2
  191. package/lib-es/bridge/index.test.d.ts.map +0 -1
  192. package/lib-es/bridge/index.test.js +0 -260
  193. package/lib-es/bridge/index.test.js.map +0 -1
  194. package/lib-es/bridge/preload.test.d.ts +0 -2
  195. package/lib-es/bridge/preload.test.d.ts.map +0 -1
  196. package/lib-es/bridge/preload.test.js +0 -50
  197. package/lib-es/bridge/preload.test.js.map +0 -1
  198. package/lib-es/bridge/prepareTransaction.test.d.ts +0 -2
  199. package/lib-es/bridge/prepareTransaction.test.d.ts.map +0 -1
  200. package/lib-es/bridge/prepareTransaction.test.js +0 -92
  201. package/lib-es/bridge/prepareTransaction.test.js.map +0 -1
  202. package/lib-es/bridge/serialization.test.d.ts +0 -2
  203. package/lib-es/bridge/serialization.test.d.ts.map +0 -1
  204. package/lib-es/bridge/serialization.test.js +0 -126
  205. package/lib-es/bridge/serialization.test.js.map +0 -1
  206. package/lib-es/bridge/signOperation.integration.test.d.ts +0 -2
  207. package/lib-es/bridge/signOperation.integration.test.d.ts.map +0 -1
  208. package/lib-es/bridge/signOperation.integration.test.js +0 -75
  209. package/lib-es/bridge/signOperation.integration.test.js.map +0 -1
  210. package/lib-es/bridge/signOperation.test.d.ts +0 -2
  211. package/lib-es/bridge/signOperation.test.d.ts.map +0 -1
  212. package/lib-es/bridge/signOperation.test.js +0 -440
  213. package/lib-es/bridge/signOperation.test.js.map +0 -1
  214. package/lib-es/bridge/synchronisation.test.d.ts +0 -2
  215. package/lib-es/bridge/synchronisation.test.d.ts.map +0 -1
  216. package/lib-es/bridge/synchronisation.test.js +0 -477
  217. package/lib-es/bridge/synchronisation.test.js.map +0 -1
  218. package/lib-es/bridge/transaction.test.d.ts +0 -2
  219. package/lib-es/bridge/transaction.test.d.ts.map +0 -1
  220. package/lib-es/bridge/transaction.test.js +0 -66
  221. package/lib-es/bridge/transaction.test.js.map +0 -1
  222. package/lib-es/logic/broadcast.test.d.ts +0 -2
  223. package/lib-es/logic/broadcast.test.d.ts.map +0 -1
  224. package/lib-es/logic/broadcast.test.js +0 -57
  225. package/lib-es/logic/broadcast.test.js.map +0 -1
  226. package/lib-es/logic/combine.test.d.ts +0 -2
  227. package/lib-es/logic/combine.test.d.ts.map +0 -1
  228. package/lib-es/logic/combine.test.js +0 -35
  229. package/lib-es/logic/combine.test.js.map +0 -1
  230. package/lib-es/logic/craftTransaction.integration.test.d.ts +0 -2
  231. package/lib-es/logic/craftTransaction.integration.test.d.ts.map +0 -1
  232. package/lib-es/logic/craftTransaction.integration.test.js +0 -93
  233. package/lib-es/logic/craftTransaction.integration.test.js.map +0 -1
  234. package/lib-es/logic/craftTransaction.test.d.ts +0 -2
  235. package/lib-es/logic/craftTransaction.test.d.ts.map +0 -1
  236. package/lib-es/logic/craftTransaction.test.js +0 -122
  237. package/lib-es/logic/craftTransaction.test.js.map +0 -1
  238. package/lib-es/logic/estimateFees.integration.test.d.ts +0 -2
  239. package/lib-es/logic/estimateFees.integration.test.d.ts.map +0 -1
  240. package/lib-es/logic/estimateFees.integration.test.js +0 -77
  241. package/lib-es/logic/estimateFees.integration.test.js.map +0 -1
  242. package/lib-es/logic/estimateFees.test.d.ts +0 -2
  243. package/lib-es/logic/estimateFees.test.d.ts.map +0 -1
  244. package/lib-es/logic/estimateFees.test.js +0 -65
  245. package/lib-es/logic/estimateFees.test.js.map +0 -1
  246. package/lib-es/logic/getBalance.integration.test.d.ts +0 -2
  247. package/lib-es/logic/getBalance.integration.test.d.ts.map +0 -1
  248. package/lib-es/logic/getBalance.integration.test.js +0 -51
  249. package/lib-es/logic/getBalance.integration.test.js.map +0 -1
  250. package/lib-es/logic/getBalance.test.d.ts +0 -2
  251. package/lib-es/logic/getBalance.test.d.ts.map +0 -1
  252. package/lib-es/logic/getBalance.test.js +0 -62
  253. package/lib-es/logic/getBalance.test.js.map +0 -1
  254. package/lib-es/logic/lastBlock.test.d.ts +0 -2
  255. package/lib-es/logic/lastBlock.test.d.ts.map +0 -1
  256. package/lib-es/logic/lastBlock.test.js +0 -25
  257. package/lib-es/logic/lastBlock.test.js.map +0 -1
  258. package/lib-es/logic/listOperations.test.d.ts +0 -2
  259. package/lib-es/logic/listOperations.test.d.ts.map +0 -1
  260. package/lib-es/logic/listOperations.test.js +0 -77
  261. package/lib-es/logic/listOperations.test.js.map +0 -1
  262. package/lib-es/network/sdk.integration.test.d.ts +0 -2
  263. package/lib-es/network/sdk.integration.test.d.ts.map +0 -1
  264. package/lib-es/network/sdk.integration.test.js +0 -210
  265. package/lib-es/network/sdk.integration.test.js.map +0 -1
  266. package/lib-es/network/sdk.test.d.ts +0 -2
  267. package/lib-es/network/sdk.test.d.ts.map +0 -1
  268. package/lib-es/network/sdk.test.js +0 -1786
  269. package/lib-es/network/sdk.test.js.map +0 -1
  270. package/lib-es/signer/getAddress.test.d.ts +0 -2
  271. package/lib-es/signer/getAddress.test.d.ts.map +0 -1
  272. package/lib-es/signer/getAddress.test.js +0 -101
  273. package/lib-es/signer/getAddress.test.js.map +0 -1
  274. package/lib-es/test/config.test.d.ts +0 -2
  275. package/lib-es/test/config.test.d.ts.map +0 -1
  276. package/lib-es/test/config.test.js +0 -39
  277. package/lib-es/test/config.test.js.map +0 -1
@@ -1,1814 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- const sdk = __importStar(require("./sdk"));
30
- const config_1 = __importDefault(require("../config"));
31
- const bignumber_js_1 = require("bignumber.js");
32
- const client_1 = require("@mysten/sui/client");
33
- const assert_1 = __importStar(require("assert"));
34
- // Mock SUI client for tests
35
- jest.mock("@mysten/sui/client", () => {
36
- return {
37
- ...jest.requireActual("@mysten/sui/client"),
38
- SuiClient: jest.fn().mockImplementation(() => ({
39
- getAllBalances: jest.fn().mockResolvedValue([
40
- { coinType: "0x2::sui::SUI", totalBalance: "1000000000" },
41
- { coinType: "0x123::test::TOKEN", totalBalance: "500000" },
42
- ]),
43
- queryTransactionBlocks: jest.fn().mockResolvedValue({
44
- data: [],
45
- hasNextPage: false,
46
- }),
47
- dryRunTransactionBlock: jest.fn().mockResolvedValue({
48
- effects: {
49
- gasUsed: {
50
- computationCost: "1000000",
51
- storageCost: "500000",
52
- storageRebate: "450000",
53
- },
54
- },
55
- input: {
56
- gasData: {
57
- budget: "4000000",
58
- },
59
- },
60
- }),
61
- getCoins: jest.fn().mockResolvedValue({
62
- data: [{ coinObjectId: "0xtest_coin_object_id" }],
63
- }),
64
- executeTransactionBlock: jest.fn().mockResolvedValue({
65
- digest: "transaction_digest_123",
66
- effects: {
67
- status: { status: "success" },
68
- },
69
- }),
70
- getReferenceGasPrice: jest.fn().mockResolvedValue("1000"),
71
- getTransactionBlock: jest.fn().mockResolvedValue({
72
- transaction: {
73
- data: {
74
- transaction: {
75
- kind: "ProgrammableTransaction",
76
- inputs: [],
77
- transactions: [],
78
- },
79
- },
80
- },
81
- effects: {
82
- status: { status: "success" },
83
- },
84
- }),
85
- })),
86
- getFullnodeUrl: jest.fn().mockReturnValue("https://mockapi.sui.io"),
87
- };
88
- });
89
- // Mock the Transaction class
90
- jest.mock("@mysten/sui/transactions", () => {
91
- const mockTxb = {
92
- // This will be the built transaction block
93
- transactionBlock: new Uint8Array(),
94
- };
95
- return {
96
- ...jest.requireActual("@mysten/sui/transactions"),
97
- Transaction: jest.fn().mockImplementation(() => {
98
- return {
99
- gas: "0xmock_gas_object_id",
100
- setSender: jest.fn(),
101
- splitCoins: jest.fn().mockReturnValue(["0xmock_coin"]),
102
- transferObjects: jest.fn(),
103
- moveCall: jest.fn(),
104
- object: jest.fn(),
105
- pure: {
106
- address: jest.fn(),
107
- u64: jest.fn(),
108
- },
109
- build: jest.fn().mockResolvedValue(mockTxb),
110
- setGasBudgetIfNotSet: jest.fn(),
111
- };
112
- }),
113
- };
114
- });
115
- const mockTransaction = {
116
- digest: "DhKLpX5kwuKuyRa71RGqpX5EY2M8Efw535ZVXYXsRiDt",
117
- transaction: {
118
- data: {
119
- messageVersion: "v1",
120
- transaction: {
121
- kind: "ProgrammableTransaction",
122
- inputs: [
123
- {
124
- type: "pure",
125
- valueType: "address",
126
- value: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
127
- },
128
- ],
129
- transactions: [
130
- {
131
- TransferObjects: [["GasCoin"], { Input: 0 }],
132
- },
133
- ],
134
- },
135
- sender: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
136
- gasData: {
137
- payment: [
138
- {
139
- objectId: "0x9d49c70b621b618c7918468a7ac286e71cffe6e30c4e4175a4385516b121cb0e",
140
- version: "57",
141
- digest: "2rPEonJQQUXmAmAegn3fVqBjpKrC5NadAZBetb5wJQm6",
142
- },
143
- ],
144
- owner: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
145
- price: "1000",
146
- budget: "2988000",
147
- },
148
- },
149
- txSignatures: [
150
- "AJKFd5y+1y/ggTAKTZlrrQlvSWXoYCSU7ksxyBG6BI9FDjN/R8db5PNbw19Bs+Lp4VE0cu9BBzAc/gYDFwgYrQVgR+QnZSFg3qWm+IjLX2dEep/wlLje2lziXO+HmZApcQ==",
151
- ],
152
- },
153
- effects: {
154
- messageVersion: "v1",
155
- status: { status: "success" },
156
- executedEpoch: "18",
157
- gasUsed: {
158
- computationCost: "1000000",
159
- storageCost: "988000",
160
- storageRebate: "978120",
161
- nonRefundableStorageFee: "9880",
162
- },
163
- modifiedAtVersions: [
164
- {
165
- objectId: "0x9d49c70b621b618c7918468a7ac286e71cffe6e30c4e4175a4385516b121cb0e",
166
- sequenceNumber: "57",
167
- },
168
- ],
169
- transactionDigest: "DhKLpX5kwuKuyRa71RGqpX5EY2M8Efw535ZVXYXsRiDt",
170
- mutated: [
171
- {
172
- owner: {
173
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
174
- },
175
- reference: {
176
- objectId: "0x9d49c70b621b618c7918468a7ac286e71cffe6e30c4e4175a4385516b121cb0e",
177
- version: "58",
178
- digest: "82pvkMbymnBFQjhuDDaaW88BeATbNgWWcWH67DcLaPBi",
179
- },
180
- },
181
- ],
182
- gasObject: {
183
- owner: { AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0" },
184
- reference: {
185
- objectId: "0x9d49c70b621b618c7918468a7ac286e71cffe6e30c4e4175a4385516b121cb0e",
186
- version: "58",
187
- digest: "82pvkMbymnBFQjhuDDaaW88BeATbNgWWcWH67DcLaPBi",
188
- },
189
- },
190
- dependencies: ["D8tHbu9JwGuoaH67PFXCoswqDUy2M4S6KVLWhCodt1a7"],
191
- },
192
- balanceChanges: [
193
- {
194
- owner: { AddressOwner: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24" },
195
- coinType: "0x2::sui::SUI",
196
- amount: "-10000000000",
197
- },
198
- {
199
- owner: { AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0" },
200
- coinType: "0x2::sui::SUI",
201
- amount: "9998990120",
202
- },
203
- {
204
- owner: { AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0" },
205
- coinType: "0x123::test::TOKEN",
206
- amount: "500000",
207
- },
208
- ],
209
- timestampMs: "1742294454878",
210
- checkpoint: "313024",
211
- };
212
- // Create a mock staking transaction
213
- // amount must be a negative number
214
- function mockStakingTx(address, amount) {
215
- (0, assert_1.default)(new bignumber_js_1.BigNumber(amount).lte(0), "amount must be a negative number");
216
- return {
217
- digest: "delegate_tx_digest_123",
218
- transaction: {
219
- data: {
220
- sender: address,
221
- transaction: {
222
- kind: "ProgrammableTransaction",
223
- inputs: [],
224
- transactions: [
225
- {
226
- MoveCall: {
227
- function: "request_add_stake",
228
- },
229
- },
230
- ],
231
- },
232
- },
233
- },
234
- effects: {
235
- status: { status: "success" },
236
- gasUsed: {
237
- computationCost: "1000000",
238
- storageCost: "500000",
239
- storageRebate: "450000",
240
- },
241
- },
242
- balanceChanges: [
243
- {
244
- owner: { AddressOwner: address },
245
- coinType: "0x2::sui::SUI",
246
- amount: amount.startsWith("-") ? amount : `-${amount}`,
247
- },
248
- ],
249
- timestampMs: "1742294454878",
250
- checkpoint: "313024",
251
- };
252
- }
253
- // amount must be a positive number
254
- function mockUnstakingTx(address, amount) {
255
- (0, assert_1.default)(new bignumber_js_1.BigNumber(amount).gte(0), "amount must be a positive number");
256
- return {
257
- digest: "undelegate_tx_digest_456",
258
- transaction: {
259
- data: {
260
- sender: address,
261
- transaction: {
262
- kind: "ProgrammableTransaction",
263
- inputs: [],
264
- transactions: [
265
- {
266
- MoveCall: {
267
- function: "request_withdraw_stake",
268
- },
269
- },
270
- ],
271
- },
272
- },
273
- },
274
- effects: {
275
- status: { status: "success" },
276
- gasUsed: {
277
- computationCost: "1000000",
278
- storageCost: "500000",
279
- storageRebate: "450000",
280
- },
281
- },
282
- balanceChanges: [
283
- {
284
- owner: { AddressOwner: address },
285
- coinType: "0x2::sui::SUI",
286
- amount: amount,
287
- },
288
- ],
289
- timestampMs: "1742294454878",
290
- checkpoint: "313024",
291
- };
292
- }
293
- const mockApi = new client_1.SuiClient({ url: "mock" });
294
- // Add getTransactionBlock method to mockApi
295
- mockApi.getTransactionBlock = jest.fn();
296
- // Helper function to generate mock coins from an array of balances
297
- const createMockCoins = (balances) => {
298
- return balances.map((balance, index) => ({
299
- coinObjectId: `0xcoin${index + 1}`,
300
- balance,
301
- digest: `0xdigest${index + 1}`,
302
- version: "1",
303
- }));
304
- };
305
- beforeAll(() => {
306
- config_1.default.setCoinConfig(() => ({
307
- status: {
308
- type: "active",
309
- },
310
- node: {
311
- url: "https://mockapi.sui.io",
312
- },
313
- }));
314
- });
315
- beforeEach(() => {
316
- mockApi.queryTransactionBlocks.mockReset();
317
- });
318
- describe("SDK Functions", () => {
319
- test("getAccountBalances should return array of account balances", async () => {
320
- // Patch getAllBalancesCached to return a valid array for this test
321
- jest.spyOn(sdk, "getAllBalancesCached").mockResolvedValue([
322
- {
323
- coinType: "0x2::sui::SUI",
324
- totalBalance: "1000000000",
325
- coinObjectCount: 1,
326
- lockedBalance: {},
327
- },
328
- {
329
- coinType: "0x123::test::TOKEN",
330
- totalBalance: "500000",
331
- coinObjectCount: 1,
332
- lockedBalance: {},
333
- },
334
- ]);
335
- const address = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
336
- const balances = await sdk.getAccountBalances(address);
337
- expect(Array.isArray(balances)).toBe(true);
338
- expect(balances.length).toBeGreaterThan(0);
339
- // Check structure of the first balance
340
- const firstBalance = balances[0];
341
- expect(firstBalance).toHaveProperty("coinType");
342
- expect(firstBalance).toHaveProperty("blockHeight");
343
- expect(firstBalance).toHaveProperty("balance");
344
- expect(firstBalance.balance).toBeInstanceOf(bignumber_js_1.BigNumber);
345
- // Should include SUI and token balances
346
- const coinTypes = balances.map(b => b.coinType);
347
- expect(coinTypes).toContain(sdk.DEFAULT_COIN_TYPE);
348
- });
349
- test("getOperationType should return IN for incoming tx", () => {
350
- const address = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
351
- expect(sdk.getOperationType(address, mockTransaction)).toBe("IN");
352
- });
353
- test("getOperationType should return OUT for outgoing tx", () => {
354
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
355
- expect(sdk.getOperationType(address, mockTransaction)).toBe("OUT");
356
- });
357
- test("getOperationSenders should return sender address", () => {
358
- expect(sdk.getOperationSenders(mockTransaction.transaction?.data)).toEqual(["0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24"]);
359
- });
360
- test("getOperationRecipients should return recipient addresses", () => {
361
- expect(sdk.getOperationRecipients(mockTransaction.transaction?.data)).toEqual(["0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0"]);
362
- });
363
- test("getOperationFee should calculate fee correctly", () => {
364
- expect(sdk.getOperationFee(mockTransaction)).toEqual(new bignumber_js_1.BigNumber(1009880));
365
- });
366
- test("getOperationDate should return correct date", () => {
367
- const date = sdk.getOperationDate(mockTransaction);
368
- expect(date).toBeDefined();
369
- expect(date).toBeInstanceOf(Date);
370
- });
371
- test("getOperationCoinType should extract token coin type", () => {
372
- // For a token transaction
373
- const tokenTx = {
374
- ...mockTransaction,
375
- balanceChanges: [
376
- {
377
- owner: {
378
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
379
- },
380
- coinType: "0x123::test::TOKEN",
381
- amount: "500000",
382
- },
383
- {
384
- owner: {
385
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
386
- },
387
- coinType: sdk.DEFAULT_COIN_TYPE,
388
- amount: "-1009880",
389
- },
390
- ],
391
- };
392
- expect(sdk.getOperationCoinType(tokenTx)).toBe("0x123::test::TOKEN");
393
- // For a SUI-only transaction
394
- const suiTx = {
395
- ...mockTransaction,
396
- balanceChanges: [
397
- {
398
- owner: {
399
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
400
- },
401
- coinType: sdk.DEFAULT_COIN_TYPE,
402
- amount: "9998990120",
403
- },
404
- ],
405
- };
406
- expect(sdk.getOperationCoinType(suiTx)).toBe(sdk.DEFAULT_COIN_TYPE);
407
- });
408
- test("transactionToOperation should map transaction to operation", () => {
409
- const accountId = "mockAccountId";
410
- const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
411
- // Create a SUI-only transaction for this test to avoid token detection
412
- const suiTx = {
413
- ...mockTransaction,
414
- balanceChanges: [
415
- {
416
- owner: {
417
- AddressOwner: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
418
- },
419
- coinType: sdk.DEFAULT_COIN_TYPE,
420
- amount: "-10000000000",
421
- },
422
- {
423
- owner: {
424
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
425
- },
426
- coinType: sdk.DEFAULT_COIN_TYPE,
427
- amount: "9998990120",
428
- },
429
- ],
430
- };
431
- // Instead of mocking, just directly verify the amount
432
- const operation = sdk.transactionToOperation(accountId, address, suiTx);
433
- expect(operation).toHaveProperty("id");
434
- expect(operation).toHaveProperty("accountId", accountId);
435
- expect(operation).toHaveProperty("extra");
436
- expect(operation.extra.coinType).toBe(sdk.DEFAULT_COIN_TYPE);
437
- // Directly calculate expected amount for SUI coin type
438
- const expectedAmount = sdk.getOperationAmount(address, suiTx, sdk.DEFAULT_COIN_TYPE);
439
- expect(expectedAmount.toString()).toBe("9998990120");
440
- });
441
- test("transactionToOperation should map token transaction to operation", () => {
442
- const accountId = "mockAccountId";
443
- const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
444
- // Create a token transaction
445
- const tokenTx = {
446
- ...mockTransaction,
447
- balanceChanges: [
448
- {
449
- owner: {
450
- AddressOwner: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
451
- },
452
- coinType: "0x123::test::TOKEN",
453
- amount: "-500000",
454
- },
455
- {
456
- owner: {
457
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
458
- },
459
- coinType: "0x123::test::TOKEN",
460
- amount: "500000",
461
- },
462
- {
463
- owner: {
464
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
465
- },
466
- coinType: sdk.DEFAULT_COIN_TYPE,
467
- amount: "-1000000",
468
- },
469
- ],
470
- };
471
- const operation = sdk.transactionToOperation(accountId, address, tokenTx);
472
- expect(operation).toHaveProperty("id");
473
- expect(operation).toHaveProperty("accountId", accountId);
474
- expect(operation).toHaveProperty("extra");
475
- expect(operation.extra.coinType).toBe("0x123::test::TOKEN");
476
- expect(operation.value).toEqual(new bignumber_js_1.BigNumber("500000"));
477
- });
478
- test("transactionToOp should map token transaction to operation", () => {
479
- const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
480
- // Create a token transaction
481
- const tokenTx = {
482
- ...mockTransaction,
483
- balanceChanges: [
484
- {
485
- owner: {
486
- AddressOwner: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
487
- },
488
- coinType: "0x123::test::TOKEN",
489
- amount: "-500000",
490
- },
491
- {
492
- owner: {
493
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
494
- },
495
- coinType: "0x123::test::TOKEN",
496
- amount: "500000",
497
- },
498
- {
499
- owner: {
500
- AddressOwner: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
501
- },
502
- coinType: sdk.DEFAULT_COIN_TYPE,
503
- amount: "-1000000",
504
- },
505
- ],
506
- };
507
- const operation = sdk.alpacaTransactionToOp(address, tokenTx);
508
- expect(operation.id).toEqual("DhKLpX5kwuKuyRa71RGqpX5EY2M8Efw535ZVXYXsRiDt");
509
- expect(operation.type).toEqual("IN");
510
- expect(operation.senders).toEqual([
511
- "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
512
- ]);
513
- expect(operation.recipients).toEqual([
514
- "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
515
- ]);
516
- expect(operation.value).toEqual(500000n);
517
- expect(operation.asset).toEqual({ type: "token", assetReference: "0x123::test::TOKEN" });
518
- expect(operation.memo).toBeUndefined();
519
- expect(operation.details).toBeUndefined();
520
- expect(operation.tx.block.hash).toBeUndefined();
521
- expect(operation.tx).toMatchObject({
522
- hash: "DhKLpX5kwuKuyRa71RGqpX5EY2M8Efw535ZVXYXsRiDt",
523
- block: {},
524
- fees: 1009880n,
525
- date: new Date("2025-03-18T10:40:54.878Z"),
526
- });
527
- });
528
- test("getOperations should fetch operations", async () => {
529
- const accountId = "mockAccountId";
530
- const addr = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
531
- const operations = await sdk.getOperations(accountId, addr);
532
- expect(Array.isArray(operations)).toBe(true);
533
- });
534
- test("paymentInfo should return gas budget and fees", async () => {
535
- const sender = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
536
- const fakeTransaction = {
537
- mode: "send",
538
- coinType: sdk.DEFAULT_COIN_TYPE,
539
- family: "sui",
540
- amount: new bignumber_js_1.BigNumber(100),
541
- recipient: "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164",
542
- errors: {},
543
- };
544
- const info = await sdk.paymentInfo(sender, fakeTransaction);
545
- expect(info).toHaveProperty("gasBudget");
546
- expect(info).toHaveProperty("totalGasUsed");
547
- expect(info).toHaveProperty("fees");
548
- });
549
- test("createTransaction should build a transaction", async () => {
550
- const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
551
- const transaction = {
552
- mode: "send",
553
- coinType: sdk.DEFAULT_COIN_TYPE,
554
- amount: new bignumber_js_1.BigNumber(100),
555
- recipient: "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164",
556
- };
557
- const tx = await sdk.createTransaction(address, transaction);
558
- expect(tx).toBeDefined();
559
- });
560
- test("executeTransactionBlock should execute a transaction", async () => {
561
- const result = await sdk.executeTransactionBlock({
562
- transactionBlock: new Uint8Array(),
563
- signature: "mockSignature",
564
- options: { showEffects: true },
565
- });
566
- expect(result).toHaveProperty("digest", "transaction_digest_123");
567
- expect(result?.effects).toBeDefined();
568
- if (result?.effects) {
569
- expect(result.effects).toHaveProperty("status");
570
- expect(result.effects.status).toHaveProperty("status", "success");
571
- }
572
- });
573
- });
574
- describe("Staking Operations", () => {
575
- describe("Operation Type Detection", () => {
576
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
577
- test("getOperationType should return DELEGATE for staking transaction", () => {
578
- expect(sdk.getOperationType(address, mockStakingTx(address, "-1000000000"))).toBe("DELEGATE");
579
- });
580
- test("getOperationType should return UNDELEGATE for unstaking transaction", () => {
581
- expect(sdk.getOperationType(address, mockUnstakingTx(address, "1000000000"))).toBe("UNDELEGATE");
582
- });
583
- function prependOtherMoveCall(block) {
584
- if (block?.kind === "ProgrammableTransaction") {
585
- block.transactions.unshift({
586
- MoveCall: {
587
- function: "other_function",
588
- module: "module",
589
- package: "package",
590
- },
591
- });
592
- }
593
- }
594
- test("getOperationType should return UNDELEGATE when it's not the first MoveCall ", () => {
595
- const tx = mockUnstakingTx(address, "1000");
596
- if (tx.transaction) {
597
- prependOtherMoveCall(tx.transaction.data.transaction);
598
- expect(sdk.getOperationType(address, tx)).toBe("UNDELEGATE");
599
- }
600
- else {
601
- (0, assert_1.fail)("can't prepare fixture");
602
- }
603
- });
604
- test("getOperationType should return DELEGATE when it's not the first MoveCall ", () => {
605
- const tx = mockStakingTx(address, "-1000");
606
- if (tx.transaction) {
607
- prependOtherMoveCall(tx.transaction.data.transaction);
608
- expect(sdk.getOperationType(address, tx)).toBe("DELEGATE");
609
- }
610
- else {
611
- (0, assert_1.fail)("can't prepare fixture");
612
- }
613
- });
614
- });
615
- describe("Operation Amount Calculation", () => {
616
- const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
617
- function bridgeOperationAmount(mock, coinType = sdk.DEFAULT_COIN_TYPE) {
618
- return sdk.getOperationAmount(address, mock, coinType);
619
- }
620
- test("getOperationAmount should calculate staking amount", () => expect(bridgeOperationAmount(mockStakingTx(address, "-1000000000"))).toEqual(new bignumber_js_1.BigNumber("1000000000")));
621
- test("getOperationAmount should calculate unstaking amount of 1000", () => expect(bridgeOperationAmount(mockUnstakingTx(address, "1000"))).toEqual(new bignumber_js_1.BigNumber("-1000")));
622
- test("getOperationAmount should calculate unstaking amount of 0", () => expect(bridgeOperationAmount(mockUnstakingTx(address, "0"))).toEqual(new bignumber_js_1.BigNumber("0")));
623
- test("getOperationAmount should calculate amount correctly for SUI", () => expect(bridgeOperationAmount(mockTransaction)).toEqual(new bignumber_js_1.BigNumber("9998990120")));
624
- test("getOperationAmount should calculate amount correctly for tokens", () => expect(bridgeOperationAmount(mockTransaction, "0x123::test::TOKEN")).toEqual(new bignumber_js_1.BigNumber("500000")));
625
- function alpacaOperationAmount(mock, coinType = sdk.DEFAULT_COIN_TYPE) {
626
- return sdk.alpacaGetOperationAmount(address, mock, coinType);
627
- }
628
- test("alpaca getOperationAmount should calculate staking amount", () => expect(alpacaOperationAmount(mockStakingTx(address, "-1000000000"))).toEqual(new bignumber_js_1.BigNumber("1000000000")));
629
- test("alpaca getOperationAmount should calculate unstaking amount of 1000", () => expect(alpacaOperationAmount(mockUnstakingTx(address, "1000"))).toEqual(new bignumber_js_1.BigNumber("1000")));
630
- test("alpaca getOperationAmount should calculate unstaking amount of 0", () => expect(alpacaOperationAmount(mockUnstakingTx(address, "0"))).toEqual(new bignumber_js_1.BigNumber("0")));
631
- test("alpaca getOperationAmount should calculate amount correctly for SUI", () => expect(alpacaOperationAmount(mockTransaction)).toEqual(new bignumber_js_1.BigNumber("9998990120")));
632
- test("alpaca getOperationAmount should calculate amount correctly for tokens", () => expect(alpacaOperationAmount(mockTransaction, "0x123::test::TOKEN")).toEqual(new bignumber_js_1.BigNumber("500000")));
633
- });
634
- describe("Operation Recipients", () => {
635
- test("getOperationRecipients should return empty array for staking transaction", () => {
636
- const recipients = sdk.getOperationRecipients(mockStakingTx("0xdeadbeef", "-1000000000").transaction?.data);
637
- expect(recipients).toEqual([]);
638
- });
639
- test("getOperationRecipients should return empty array for unstaking transaction", () => {
640
- const recipients = sdk.getOperationRecipients(mockUnstakingTx("0xdeadbeef", "1000000000").transaction?.data);
641
- expect(recipients).toEqual([]);
642
- });
643
- });
644
- describe("Transaction Creation", () => {
645
- test("createTransaction should build delegate transaction", async () => {
646
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
647
- const transaction = {
648
- mode: "delegate",
649
- coinType: sdk.DEFAULT_COIN_TYPE,
650
- amount: new bignumber_js_1.BigNumber(1000000000), // 1 SUI
651
- recipient: "0xvalidator_address_123",
652
- };
653
- const tx = await sdk.createTransaction(address, transaction);
654
- expect(tx).toBeDefined();
655
- });
656
- test("createTransaction should build undelegate transaction with specific amount", async () => {
657
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
658
- const transaction = {
659
- mode: "undelegate",
660
- coinType: sdk.DEFAULT_COIN_TYPE,
661
- amount: new bignumber_js_1.BigNumber(500000000), // 0.5 SUI
662
- stakedSuiId: "0xstaked_sui_object_123",
663
- useAllAmount: false,
664
- recipient: "0xvalidator_address_123", // Required by type but not used for undelegate
665
- };
666
- const tx = await sdk.createTransaction(address, transaction);
667
- expect(tx).toBeDefined();
668
- });
669
- test("createTransaction should build undelegate transaction with all amount", async () => {
670
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
671
- const transaction = {
672
- mode: "undelegate",
673
- coinType: sdk.DEFAULT_COIN_TYPE,
674
- amount: new bignumber_js_1.BigNumber(0),
675
- stakedSuiId: "0xstaked_sui_object_123",
676
- useAllAmount: true,
677
- recipient: "0xvalidator_address_123", // Required by type but not used for undelegate
678
- };
679
- const tx = await sdk.createTransaction(address, transaction);
680
- expect(tx).toBeDefined();
681
- });
682
- });
683
- describe("Payment Info for Staking", () => {
684
- test("paymentInfo should return gas budget and fees for delegate transaction", async () => {
685
- const sender = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
686
- const fakeTransaction = {
687
- mode: "delegate",
688
- coinType: sdk.DEFAULT_COIN_TYPE,
689
- family: "sui",
690
- amount: new bignumber_js_1.BigNumber(1000000000), // 1 SUI
691
- recipient: "0xvalidator_address_123",
692
- errors: {},
693
- };
694
- const info = await sdk.paymentInfo(sender, fakeTransaction);
695
- expect(info).toHaveProperty("gasBudget");
696
- expect(info).toHaveProperty("totalGasUsed");
697
- expect(info).toHaveProperty("fees");
698
- });
699
- test("paymentInfo should return gas budget and fees for undelegate transaction", async () => {
700
- const sender = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
701
- const fakeTransaction = {
702
- mode: "undelegate",
703
- coinType: sdk.DEFAULT_COIN_TYPE,
704
- family: "sui",
705
- amount: new bignumber_js_1.BigNumber(500000000), // 0.5 SUI
706
- stakedSuiId: "0xstaked_sui_object_123",
707
- useAllAmount: false,
708
- recipient: "0xvalidator_address_123", // Required by type but not used for undelegate
709
- errors: {},
710
- };
711
- const info = await sdk.paymentInfo(sender, fakeTransaction);
712
- expect(info).toHaveProperty("gasBudget");
713
- expect(info).toHaveProperty("totalGasUsed");
714
- expect(info).toHaveProperty("fees");
715
- });
716
- });
717
- describe("Transaction to Operation Mapping", () => {
718
- test("transactionToOperation should map staking transaction correctly", () => {
719
- const accountId = "mockAccountId";
720
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
721
- const operation = sdk.transactionToOperation(accountId, address, mockStakingTx(address, "-1000000000"));
722
- expect(operation).toHaveProperty("id");
723
- expect(operation).toHaveProperty("accountId", accountId);
724
- expect(operation).toHaveProperty("type", "DELEGATE");
725
- expect(operation).toHaveProperty("hash", "delegate_tx_digest_123");
726
- expect(operation).toHaveProperty("extra");
727
- expect(operation.extra.coinType).toBe(sdk.DEFAULT_COIN_TYPE);
728
- expect(operation.value).toEqual(new bignumber_js_1.BigNumber("1000000000")); // The function returns minus of the balance change
729
- expect(operation.recipients).toEqual([]);
730
- expect(operation.senders).toEqual([address]);
731
- });
732
- test("transactionToOperation should map unstaking transaction correctly", () => {
733
- const accountId = "mockAccountId";
734
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
735
- const operation = sdk.transactionToOperation(accountId, address, mockUnstakingTx(address, "1000000000"));
736
- expect(operation).toHaveProperty("id");
737
- expect(operation).toHaveProperty("accountId", accountId);
738
- expect(operation).toHaveProperty("type", "UNDELEGATE");
739
- expect(operation).toHaveProperty("hash", "undelegate_tx_digest_456");
740
- expect(operation).toHaveProperty("extra");
741
- expect(operation.extra.coinType).toBe(sdk.DEFAULT_COIN_TYPE);
742
- expect(operation.value).toEqual(new bignumber_js_1.BigNumber("-1000000000"));
743
- expect(operation.recipients).toEqual([]);
744
- expect(operation.senders).toEqual([address]);
745
- });
746
- test("transactionToOp should map staking transaction correctly", () => {
747
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
748
- const operation = sdk.alpacaTransactionToOp(address, mockStakingTx(address, "-1000000000"));
749
- expect(operation.id).toEqual("delegate_tx_digest_123");
750
- expect(operation.type).toEqual("DELEGATE");
751
- expect(operation.senders).toEqual([address]);
752
- expect(operation.recipients).toEqual([]);
753
- expect(operation.value).toEqual(1000000000n); // The function returns minus of the balance change
754
- expect(operation.asset).toEqual({ type: "native" });
755
- expect(operation.tx.block.hash).toBeUndefined();
756
- });
757
- test("transactionToOp should map unstaking transaction correctly", () => {
758
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
759
- const operation = sdk.alpacaTransactionToOp(address, mockUnstakingTx(address, "1000000000"));
760
- expect(operation.id).toEqual("undelegate_tx_digest_456");
761
- expect(operation.type).toEqual("UNDELEGATE");
762
- expect(operation.senders).toEqual([address]);
763
- expect(operation.recipients).toEqual([]);
764
- expect(operation.value).toEqual(1000000000n);
765
- expect(operation.asset).toEqual({ type: "native" });
766
- expect(operation.tx.block.hash).toBeUndefined();
767
- });
768
- });
769
- describe("Operation Extra Information", () => {
770
- test("getOperationExtra should be a function", () => {
771
- expect(typeof sdk.getOperationExtra).toBe("function");
772
- });
773
- test("getOperationExtra should return a Promise", () => {
774
- const result = sdk.getOperationExtra("test_digest");
775
- expect(result).toBeInstanceOf(Promise);
776
- });
777
- });
778
- });
779
- describe("queryTransactions", () => {
780
- it("should call api.queryTransactionBlocks with correct params for IN", async () => {
781
- mockApi.queryTransactionBlocks.mockResolvedValueOnce({
782
- data: [{ digest: "tx1" }],
783
- hasNextPage: false,
784
- });
785
- const result = await sdk.queryTransactions({
786
- api: mockApi,
787
- addr: "0xabc",
788
- type: "IN",
789
- order: "ascending",
790
- });
791
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledWith(expect.objectContaining({
792
- filter: { ToAddress: "0xabc" },
793
- }));
794
- expect(result.data).toHaveLength(1);
795
- });
796
- it("should call api.queryTransactionBlocks with correct params for OUT", async () => {
797
- mockApi.queryTransactionBlocks.mockResolvedValueOnce({
798
- data: [{ digest: "tx2" }],
799
- hasNextPage: false,
800
- });
801
- const result = await sdk.queryTransactions({
802
- api: mockApi,
803
- addr: "0xdef",
804
- type: "OUT",
805
- order: "ascending",
806
- });
807
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledWith(expect.objectContaining({
808
- filter: { FromAddress: "0xdef" },
809
- }));
810
- expect(result.data).toHaveLength(1);
811
- });
812
- });
813
- describe("loadOperations", () => {
814
- it("should paginate and accumulate results", async () => {
815
- const pageSize = sdk.TRANSACTIONS_LIMIT_PER_QUERY;
816
- const firstPage = Array.from({ length: pageSize }, (_, i) => ({ digest: `tx${i + 1}` }));
817
- mockApi.queryTransactionBlocks
818
- .mockResolvedValueOnce({
819
- data: firstPage,
820
- hasNextPage: true,
821
- nextCursor: "cursor1",
822
- })
823
- .mockResolvedValueOnce({
824
- data: [{ digest: `tx${pageSize + 1}` }],
825
- hasNextPage: false,
826
- });
827
- const result = await sdk.loadOperations({
828
- api: mockApi,
829
- addr: "0xabc",
830
- type: "IN",
831
- order: "ascending",
832
- operations: [],
833
- });
834
- expect(result.operations).toHaveLength(pageSize + 1);
835
- expect(result.operations.map(tx => tx.digest)).toEqual([
836
- ...firstPage.map(tx => tx.digest),
837
- `tx${pageSize + 1}`,
838
- ]);
839
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledTimes(2);
840
- });
841
- it("should stop if less than TRANSACTIONS_LIMIT_PER_QUERY returned", async () => {
842
- // Create an array with length less than TRANSACTIONS_LIMIT_PER_QUERY
843
- const txs = Array.from({ length: sdk.TRANSACTIONS_LIMIT_PER_QUERY - 1 }, (_, i) => ({
844
- digest: `tx${i + 1}`,
845
- }));
846
- mockApi.queryTransactionBlocks.mockResolvedValueOnce({
847
- data: txs,
848
- hasNextPage: false, // Only one call should be made
849
- });
850
- const result = await sdk.loadOperations({
851
- api: mockApi,
852
- addr: "0xabc",
853
- type: "OUT",
854
- order: "ascending",
855
- operations: [],
856
- });
857
- expect(result.operations).toHaveLength(sdk.TRANSACTIONS_LIMIT_PER_QUERY - 1);
858
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledTimes(1);
859
- });
860
- it("should not exceed TRANSACTIONS_LIMIT", async () => {
861
- const page = Array.from({ length: sdk.TRANSACTIONS_LIMIT_PER_QUERY }, (_, i) => ({
862
- digest: `tx${i + 1}`,
863
- }));
864
- const expectedCalls = Math.ceil(sdk.TRANSACTIONS_LIMIT / sdk.TRANSACTIONS_LIMIT_PER_QUERY);
865
- let callCount = 0;
866
- mockApi.queryTransactionBlocks.mockImplementation(() => {
867
- callCount++;
868
- return Promise.resolve({
869
- data: page,
870
- hasNextPage: callCount < expectedCalls,
871
- nextCursor: callCount < expectedCalls ? "cursor" : null,
872
- });
873
- });
874
- const result = await sdk.loadOperations({
875
- api: mockApi,
876
- addr: "0xabc",
877
- type: "IN",
878
- order: "ascending",
879
- operations: [],
880
- });
881
- expect(result.operations).toHaveLength(sdk.TRANSACTIONS_LIMIT);
882
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledTimes(expectedCalls);
883
- });
884
- it("should retry without cursor when InvalidParams error occurs", async () => {
885
- // Reset the mock for this test
886
- mockApi.queryTransactionBlocks.mockReset();
887
- // Call fails with InvalidParams
888
- mockApi.queryTransactionBlocks.mockRejectedValueOnce({ type: "InvalidParams" });
889
- const result = await sdk.loadOperations({
890
- api: mockApi,
891
- addr: "0xabc",
892
- type: "IN",
893
- cursor: "some-cursor",
894
- order: "ascending",
895
- operations: [],
896
- });
897
- // Should have been called once (no retry in actual implementation)
898
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledTimes(1);
899
- // Should have been called with the cursor
900
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledWith(expect.objectContaining({
901
- filter: { ToAddress: "0xabc" },
902
- cursor: "some-cursor",
903
- }));
904
- // Result should be empty array (no retry, just return operations)
905
- expect(result.operations).toHaveLength(0);
906
- });
907
- it("should should not retry after unexpected errors and return empty data", async () => {
908
- mockApi.queryTransactionBlocks.mockRejectedValueOnce(new Error("unexpected"));
909
- const result = await sdk.loadOperations({
910
- api: mockApi,
911
- addr: "0xerr",
912
- type: "IN",
913
- order: "ascending",
914
- operations: [],
915
- });
916
- expect(result.operations).toEqual([]);
917
- expect(mockApi.queryTransactionBlocks).toHaveBeenCalledTimes(1);
918
- });
919
- });
920
- describe("getOperations filtering logic", () => {
921
- const mockAccountId = "mockAccountId";
922
- const mockAddr = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
923
- // Mock loadOperations to return controlled test data
924
- const mockLoadOperations = jest.spyOn(sdk, "loadOperations");
925
- // Helper function to create mock transaction data
926
- const createMockTransaction = (digest, timestampMs, sender = mockAddr, recipients = [], balanceChangeAmount) => {
927
- // If sender is mockAddr (OUT), amount is negative; if sender is otherAddr (IN), amount is positive
928
- const isOut = sender === mockAddr;
929
- const amount = balanceChangeAmount ?? (isOut ? "-1000000" : "1000000");
930
- return {
931
- digest,
932
- timestampMs,
933
- effects: {
934
- status: { status: "success" },
935
- gasUsed: {
936
- computationCost: "1000000",
937
- storageCost: "500000",
938
- storageRebate: "450000",
939
- nonRefundableStorageFee: "0",
940
- },
941
- executedEpoch: "1",
942
- gasObject: {
943
- owner: { AddressOwner: sender },
944
- reference: {
945
- objectId: "0xgas",
946
- version: "1",
947
- digest: "gas-digest",
948
- },
949
- },
950
- messageVersion: "v1",
951
- transactionDigest: digest,
952
- },
953
- balanceChanges: [
954
- {
955
- owner: { AddressOwner: mockAddr },
956
- coinType: sdk.DEFAULT_COIN_TYPE,
957
- amount,
958
- },
959
- ],
960
- transaction: {
961
- data: {
962
- sender,
963
- transaction: {
964
- kind: "ProgrammableTransaction",
965
- inputs: recipients.map(r => ({ type: "pure", valueType: "address", value: r })),
966
- transactions: [],
967
- },
968
- gasData: {
969
- budget: "1000",
970
- owner: sender,
971
- payment: [],
972
- price: "1",
973
- },
974
- messageVersion: "v1",
975
- },
976
- txSignatures: [],
977
- },
978
- };
979
- };
980
- const otherAddr = "0xotheraddress";
981
- // OUT = sender is mockAddr, IN = sender is otherAddr
982
- beforeEach(() => {
983
- mockLoadOperations.mockReset();
984
- // Mock loadOperations to return different data based on operation type
985
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
986
- if (type === "OUT") {
987
- return {
988
- operations: [
989
- createMockTransaction("sent1", "1000", mockAddr, []),
990
- createMockTransaction("sent2", "2000", mockAddr, []),
991
- ],
992
- cursor: null,
993
- };
994
- }
995
- else if (type === "IN") {
996
- return {
997
- operations: [
998
- createMockTransaction("received1", "1500", otherAddr, [mockAddr]),
999
- createMockTransaction("received2", "2500", otherAddr, [mockAddr]),
1000
- ],
1001
- cursor: null,
1002
- };
1003
- }
1004
- return { operations: [], cursor: null };
1005
- });
1006
- });
1007
- afterEach(() => {
1008
- // Remove mockRestore as it might interfere with the mock setup
1009
- });
1010
- test("should not apply timestamp filter when cursor is provided", async () => {
1011
- const cursor = "test-cursor";
1012
- const operations = await sdk.getOperations(mockAccountId, mockAddr, cursor);
1013
- // Should not filter by timestamp when cursor is provided
1014
- expect(operations).toHaveLength(4);
1015
- expect(operations.map(op => op.hash)).toEqual(["received2", "sent2", "received1", "sent1"]);
1016
- });
1017
- test("should not apply timestamp filter when operations don't reach limits", async () => {
1018
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1019
- // Should not filter by timestamp when limits aren't reached
1020
- expect(operations).toHaveLength(4);
1021
- expect(operations.map(op => op.hash)).toEqual(["received2", "sent2", "received1", "sent1"]);
1022
- });
1023
- test("should apply timestamp filter when sent operations reach limit", async () => {
1024
- // Mock to return enough sent operations to reach limit
1025
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1026
- if (type === "OUT") {
1027
- return {
1028
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`sent${i + 1}`, String(1000 + i * 100), mockAddr, [])),
1029
- cursor: null,
1030
- };
1031
- }
1032
- else if (type === "IN") {
1033
- return {
1034
- operations: [
1035
- createMockTransaction("received1", "500", otherAddr, [mockAddr]),
1036
- createMockTransaction("received2", "1500", otherAddr, [mockAddr]),
1037
- ],
1038
- cursor: null,
1039
- };
1040
- }
1041
- return { operations: [], cursor: null };
1042
- });
1043
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1044
- // Filter timestamp should be the maximum of the last timestamps from both arrays
1045
- // sent: last timestamp = 1000 + 299*100 = 30900
1046
- // received: last timestamp = 1500
1047
- // filter = max(30900, 1500) = 30900
1048
- // Only operations with timestamp >= 30900 should remain
1049
- expect(operations).toHaveLength(1); // Only sent300 (30900)
1050
- expect(operations.map(op => op.hash)).toEqual(["sent300"]);
1051
- });
1052
- test("should apply timestamp filter when received operations reach limit", async () => {
1053
- // Mock to return enough received operations to reach limit
1054
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1055
- if (type === "OUT") {
1056
- return {
1057
- operations: [
1058
- createMockTransaction("sent1", "500", mockAddr, []),
1059
- createMockTransaction("sent2", "1500", mockAddr, []),
1060
- ],
1061
- cursor: null,
1062
- };
1063
- }
1064
- else if (type === "IN") {
1065
- return {
1066
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`received${i + 1}`, String(1000 + i * 100), otherAddr, [
1067
- mockAddr,
1068
- ])),
1069
- cursor: null,
1070
- };
1071
- }
1072
- return { operations: [], cursor: null };
1073
- });
1074
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1075
- // Filter timestamp should be the maximum of the last timestamps from both arrays
1076
- // sent: last timestamp = 1500
1077
- // received: last timestamp = 1000 + 299*100 = 30900
1078
- // filter = max(1500, 30900) = 30900
1079
- // Only operations with timestamp >= 30900 should remain
1080
- expect(operations).toHaveLength(1); // Only received300 (30900)
1081
- expect(operations.map(op => op.hash)).toEqual(["received300"]);
1082
- });
1083
- test("should apply timestamp filter when both operations reach limit", async () => {
1084
- // Mock to return enough operations to reach limit for both types
1085
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1086
- if (type === "OUT") {
1087
- return {
1088
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`sent${i + 1}`, String(1000 + i * 100), mockAddr, [])),
1089
- cursor: null,
1090
- };
1091
- }
1092
- else if (type === "IN") {
1093
- return {
1094
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`received${i + 1}`, String(2000 + i * 100), otherAddr, [
1095
- mockAddr,
1096
- ])),
1097
- cursor: null,
1098
- };
1099
- }
1100
- return { operations: [], cursor: null };
1101
- });
1102
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1103
- // Filter timestamp should be the maximum of the last timestamps from both arrays
1104
- // sent: last timestamp = 1000 + 299*100 = 30900
1105
- // received: last timestamp = 2000 + 299*100 = 31900
1106
- // filter = max(30900, 31900) = 31900
1107
- // Only operations with timestamp >= 31900 should remain
1108
- expect(operations).toHaveLength(1); // Only received300 (31900)
1109
- expect(operations.map(op => op.hash)).toEqual(["received300"]);
1110
- });
1111
- test("should handle null/undefined timestampMs values", async () => {
1112
- // Mock to return operations with null timestamps and reach limit
1113
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1114
- if (type === "OUT") {
1115
- return {
1116
- operations: [
1117
- createMockTransaction("sent1", "1000", mockAddr, []),
1118
- createMockTransaction("sent2", null, mockAddr, []),
1119
- createMockTransaction("sent3", "3000", mockAddr, []),
1120
- ...Array.from({ length: sdk.TRANSACTIONS_LIMIT - 3 }, (_, i) => createMockTransaction(`sent${i + 4}`, String(4000 + i * 100), mockAddr, [])),
1121
- ],
1122
- cursor: null,
1123
- };
1124
- }
1125
- else if (type === "IN") {
1126
- return {
1127
- operations: [
1128
- createMockTransaction("received1", null, otherAddr, [mockAddr]),
1129
- createMockTransaction("received2", "2000", otherAddr, [mockAddr]),
1130
- createMockTransaction("received3", "4000", otherAddr, [mockAddr]),
1131
- ],
1132
- cursor: null,
1133
- };
1134
- }
1135
- return { operations: [], cursor: null };
1136
- });
1137
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1138
- // Filter timestamp should be the timestamp of the last sent operation (4000 + 296*100 = 33600)
1139
- // Only operations with timestamp >= 33600 should remain
1140
- expect(operations).toHaveLength(1); // Only sent300 (33600)
1141
- expect(operations.map(op => op.hash)).toEqual(["sent300"]);
1142
- });
1143
- test("should maintain chronological order after filtering", async () => {
1144
- // Mock to return operations that reach limit
1145
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1146
- if (type === "OUT") {
1147
- return {
1148
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`sent${i + 1}`, String(1000 + i * 10), mockAddr, [])),
1149
- cursor: null,
1150
- };
1151
- }
1152
- else if (type === "IN") {
1153
- return {
1154
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`received${i + 1}`, String(500 + i * 10), otherAddr, [mockAddr])),
1155
- cursor: null,
1156
- };
1157
- }
1158
- return { operations: [], cursor: null };
1159
- });
1160
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1161
- // Should be sorted by timestamp in descending order
1162
- const timestamps = operations.map(op => Number(op.date.getTime()));
1163
- expect(timestamps).toEqual(timestamps.slice().sort((a, b) => b - a));
1164
- });
1165
- test("should handle empty operations arrays", async () => {
1166
- // Mock to return empty arrays
1167
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1168
- return { operations: [], cursor: null };
1169
- });
1170
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1171
- expect(operations).toHaveLength(0);
1172
- });
1173
- test("should handle mixed empty and non-empty operations", async () => {
1174
- // Mock to return only OUT operations
1175
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1176
- if (type === "OUT") {
1177
- return {
1178
- operations: [
1179
- createMockTransaction("sent1", "1000", mockAddr, []),
1180
- createMockTransaction("sent2", "2000", mockAddr, []),
1181
- ],
1182
- cursor: null,
1183
- };
1184
- }
1185
- else if (type === "IN") {
1186
- return { operations: [], cursor: null };
1187
- }
1188
- return { operations: [], cursor: null };
1189
- });
1190
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1191
- expect(operations).toHaveLength(2);
1192
- expect(operations.map(op => op.hash)).toEqual(["sent2", "sent1"]);
1193
- });
1194
- test("should handle operations with same timestamps", async () => {
1195
- // Mock to return operations with same timestamps and reach limit
1196
- mockLoadOperations.mockImplementation(async ({ type, ..._params }) => {
1197
- if (type === "OUT") {
1198
- return {
1199
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`sent${i + 1}`, "1000", mockAddr, [])),
1200
- cursor: null,
1201
- };
1202
- }
1203
- else if (type === "IN") {
1204
- return {
1205
- operations: [
1206
- createMockTransaction("received1", "1000", otherAddr, [mockAddr]),
1207
- createMockTransaction("received2", "1000", otherAddr, [mockAddr]),
1208
- ],
1209
- cursor: null,
1210
- };
1211
- }
1212
- return { operations: [], cursor: null };
1213
- });
1214
- const operations = await sdk.getOperations(mockAccountId, mockAddr);
1215
- // Filter timestamp should be 1000 (the common timestamp)
1216
- // All operations have timestamp 1000, so all should pass the filter
1217
- expect(operations).toHaveLength(sdk.TRANSACTIONS_LIMIT + 2); // All 300 sent + 2 received
1218
- expect(operations[0].hash).toBe("sent1"); // First one should be the first sent
1219
- expect(operations[operations.length - 1].hash).toBe("received2"); // Last one should be the last received
1220
- });
1221
- });
1222
- describe("filterOperations", () => {
1223
- const createMockTransaction = (digest, timestampMs) => ({
1224
- digest,
1225
- timestampMs,
1226
- effects: {
1227
- status: { status: "success" },
1228
- gasUsed: {
1229
- computationCost: "1000000",
1230
- storageCost: "500000",
1231
- storageRebate: "450000",
1232
- nonRefundableStorageFee: "0",
1233
- },
1234
- executedEpoch: "1",
1235
- gasObject: {
1236
- owner: { AddressOwner: "0x123" },
1237
- reference: {
1238
- objectId: "0xgas",
1239
- version: "1",
1240
- digest: "gas-digest",
1241
- },
1242
- },
1243
- messageVersion: "v1",
1244
- transactionDigest: digest,
1245
- },
1246
- transaction: {
1247
- data: {
1248
- sender: "0x123",
1249
- transaction: {
1250
- kind: "ProgrammableTransaction",
1251
- inputs: [],
1252
- transactions: [],
1253
- },
1254
- gasData: {
1255
- budget: "1000",
1256
- owner: "0x123",
1257
- payment: [],
1258
- price: "1",
1259
- },
1260
- messageVersion: "v1",
1261
- },
1262
- txSignatures: [],
1263
- },
1264
- balanceChanges: [],
1265
- });
1266
- describe("when cursor is provided", () => {
1267
- test("should not apply timestamp filtering", () => {
1268
- const operationList1 = {
1269
- operations: [createMockTransaction("tx1", "1000"), createMockTransaction("tx2", "2000")],
1270
- cursor: null,
1271
- };
1272
- const operationList2 = {
1273
- operations: [createMockTransaction("tx3", "1500"), createMockTransaction("tx4", "2500")],
1274
- cursor: null,
1275
- };
1276
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1277
- // Should return all operations sorted by timestamp in descending order
1278
- expect(result.operations).toHaveLength(4);
1279
- expect(result.operations.map(tx => tx.digest)).toEqual(["tx4", "tx2", "tx3", "tx1"]);
1280
- });
1281
- test("should handle null cursor", () => {
1282
- const operationList1 = {
1283
- operations: [createMockTransaction("tx1", "1000"), createMockTransaction("tx2", "2000")],
1284
- cursor: null,
1285
- };
1286
- const operationList2 = {
1287
- operations: [createMockTransaction("tx3", "1500"), createMockTransaction("tx4", "2500")],
1288
- cursor: null,
1289
- };
1290
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1291
- // Should return all operations sorted by timestamp in descending order
1292
- expect(result.operations).toHaveLength(4);
1293
- expect(result.operations.map(tx => tx.digest)).toEqual(["tx4", "tx2", "tx3", "tx1"]);
1294
- });
1295
- test("should handle undefined cursor", () => {
1296
- const operationList1 = {
1297
- operations: [createMockTransaction("tx1", "1000"), createMockTransaction("tx2", "2000")],
1298
- cursor: null,
1299
- };
1300
- const operationList2 = {
1301
- operations: [createMockTransaction("tx3", "1500"), createMockTransaction("tx4", "2500")],
1302
- cursor: null,
1303
- };
1304
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1305
- // Should return all operations sorted by timestamp in descending order
1306
- expect(result.operations).toHaveLength(4);
1307
- expect(result.operations.map(tx => tx.digest)).toEqual(["tx4", "tx2", "tx3", "tx1"]);
1308
- });
1309
- });
1310
- describe("when cursor is not provided and operations reach limits", () => {
1311
- test("should apply timestamp filtering when both lists reach limit", () => {
1312
- const operationList1 = {
1313
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx1_${i + 1}`, String(1000 + i * 100))),
1314
- cursor: null,
1315
- };
1316
- const operationList2 = {
1317
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx2_${i + 1}`, String(2000 + i * 100))),
1318
- cursor: null,
1319
- };
1320
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1321
- // Filter timestamp should be max of last timestamps:
1322
- // operationList1: 1000 + 299*100 = 30900
1323
- // operationList2: 2000 + 299*100 = 31900
1324
- // filter = max(30900, 31900) = 31900
1325
- // Only operations with timestamp >= 31900 should remain
1326
- const filteredOperations = result.operations.filter(tx => Number(tx.timestampMs) >= 31900);
1327
- expect(filteredOperations).toHaveLength(1);
1328
- expect(filteredOperations[0].digest).toBe("tx2_300");
1329
- });
1330
- test("should apply timestamp filtering when only first list reaches limit", () => {
1331
- const operationList1 = {
1332
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx1_${i + 1}`, String(1000 + i * 100))),
1333
- cursor: null,
1334
- };
1335
- const operationList2 = {
1336
- operations: [createMockTransaction("tx2_1", "500"), createMockTransaction("tx2_2", "1500")],
1337
- cursor: null,
1338
- };
1339
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1340
- // Filter timestamp should be max of last timestamps:
1341
- // operationList1: 1000 + 299*100 = 30900
1342
- // operationList2: 1500
1343
- // filter = max(30900, 1500) = 30900
1344
- // Only operations with timestamp >= 30900 should remain
1345
- const filteredOperations = result.operations.filter(tx => Number(tx.timestampMs) >= 30900);
1346
- expect(filteredOperations).toHaveLength(1);
1347
- expect(filteredOperations[0].digest).toBe("tx1_300");
1348
- });
1349
- test("should apply timestamp filtering when only second list reaches limit", () => {
1350
- const operationList1 = {
1351
- operations: [createMockTransaction("tx1_1", "500"), createMockTransaction("tx1_2", "1500")],
1352
- cursor: null,
1353
- };
1354
- const operationList2 = {
1355
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx2_${i + 1}`, String(2000 + i * 100))),
1356
- cursor: null,
1357
- };
1358
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1359
- // Filter timestamp should be max of last timestamps:
1360
- // operationList1: 1500
1361
- // operationList2: 2000 + 299*100 = 31900
1362
- // filter = max(1500, 31900) = 31900
1363
- // Only operations with timestamp >= 31900 should remain
1364
- const filteredOperations = result.operations.filter(tx => Number(tx.timestampMs) >= 31900);
1365
- expect(filteredOperations).toHaveLength(1);
1366
- expect(filteredOperations[0].digest).toBe("tx2_300");
1367
- });
1368
- });
1369
- describe("when cursor is not provided and operations don't reach limits", () => {
1370
- test("should not apply timestamp filtering when neither list reaches limit", () => {
1371
- const operationList1 = {
1372
- operations: [
1373
- createMockTransaction("tx1_1", "1000"),
1374
- createMockTransaction("tx1_2", "2000"),
1375
- ],
1376
- cursor: null,
1377
- };
1378
- const operationList2 = {
1379
- operations: [
1380
- createMockTransaction("tx2_1", "1500"),
1381
- createMockTransaction("tx2_2", "2500"),
1382
- ],
1383
- cursor: null,
1384
- };
1385
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1386
- // Should return all operations sorted by timestamp in descending order
1387
- expect(result.operations).toHaveLength(4);
1388
- expect(result.operations.map(tx => tx.digest)).toEqual(["tx2_2", "tx1_2", "tx2_1", "tx1_1"]);
1389
- });
1390
- test("should apply timestamp filtering when only one list reaches limit", () => {
1391
- const operationList1 = {
1392
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx1_${i + 1}`, String(1000 + i * 100))),
1393
- cursor: null,
1394
- };
1395
- const operationList2 = {
1396
- operations: [createMockTransaction("tx2_1", "1500")],
1397
- cursor: null,
1398
- };
1399
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1400
- // Should apply timestamp filtering since one list reaches limit
1401
- // Filter timestamp should be the timestamp of the last operation in list1 (1000 + 299*100 = 30900)
1402
- // Only operations with timestamp >= 30900 should remain
1403
- const filteredOperations = result.operations.filter(tx => Number(tx.timestampMs) >= 30900);
1404
- expect(filteredOperations).toHaveLength(1);
1405
- expect(filteredOperations[0].digest).toBe("tx1_300");
1406
- });
1407
- });
1408
- describe("edge cases", () => {
1409
- test("should handle null/undefined timestampMs values", () => {
1410
- const operationList1 = {
1411
- operations: [
1412
- createMockTransaction("tx1_1", "1000"),
1413
- createMockTransaction("tx1_2", null),
1414
- createMockTransaction("tx1_3", "3000"),
1415
- ...Array.from({ length: sdk.TRANSACTIONS_LIMIT - 3 }, (_, i) => createMockTransaction(`tx1_${i + 4}`, String(4000 + i * 100))),
1416
- ],
1417
- cursor: null,
1418
- };
1419
- const operationList2 = {
1420
- operations: [
1421
- createMockTransaction("tx2_1", null),
1422
- createMockTransaction("tx2_2", "2000"),
1423
- createMockTransaction("tx2_3", "4000"),
1424
- ],
1425
- cursor: null,
1426
- };
1427
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1428
- // Filter timestamp should be the timestamp of the last operation in list1 (4000 + 296*100 = 33600)
1429
- // Only operations with timestamp >= 33600 should remain
1430
- const filteredOperations = result.operations.filter(tx => Number(tx.timestampMs) >= 33600);
1431
- expect(filteredOperations).toHaveLength(1);
1432
- expect(filteredOperations[0].digest).toBe("tx1_300");
1433
- });
1434
- test("should handle empty arrays", () => {
1435
- const result = sdk.filterOperations({ operations: [], cursor: null }, { operations: [], cursor: null }, "ascending");
1436
- expect(result.operations).toHaveLength(0);
1437
- });
1438
- test("should handle one empty array", () => {
1439
- const operationList1 = {
1440
- operations: [
1441
- createMockTransaction("tx1_1", "1000"),
1442
- createMockTransaction("tx1_2", "2000"),
1443
- ],
1444
- cursor: null,
1445
- };
1446
- const operationList2 = {
1447
- operations: [],
1448
- cursor: null,
1449
- };
1450
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1451
- expect(result.operations).toHaveLength(2);
1452
- expect(result.operations.map(tx => tx.digest)).toEqual(["tx1_2", "tx1_1"]);
1453
- });
1454
- test("should remove duplicate transactions by digest", () => {
1455
- const operationList1 = {
1456
- operations: [createMockTransaction("tx1", "1000"), createMockTransaction("tx2", "2000")],
1457
- cursor: null,
1458
- };
1459
- const operationList2 = {
1460
- operations: [
1461
- createMockTransaction("tx2", "2000"), // Duplicate digest
1462
- createMockTransaction("tx3", "3000"),
1463
- ],
1464
- cursor: null,
1465
- };
1466
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1467
- // Should remove duplicate tx2
1468
- expect(result.operations).toHaveLength(3);
1469
- expect(result.operations.map(tx => tx.digest)).toEqual(["tx3", "tx2", "tx1"]);
1470
- });
1471
- test("should maintain chronological order after filtering", () => {
1472
- const operationList1 = {
1473
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx1_${i + 1}`, String(1000 + i * 10))),
1474
- cursor: null,
1475
- };
1476
- const operationList2 = {
1477
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx2_${i + 1}`, String(500 + i * 10))),
1478
- cursor: null,
1479
- };
1480
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1481
- // Should be sorted by timestamp in descending order
1482
- const timestamps = result.operations.map(tx => Number(tx.timestampMs));
1483
- expect(timestamps).toEqual(timestamps.slice().sort((a, b) => b - a));
1484
- });
1485
- test("should handle operations with same timestamps", () => {
1486
- const operationList1 = {
1487
- operations: Array.from({ length: sdk.TRANSACTIONS_LIMIT }, (_, i) => createMockTransaction(`tx1_${i + 1}`, "1000")),
1488
- cursor: null,
1489
- };
1490
- const operationList2 = {
1491
- operations: [
1492
- createMockTransaction("tx2_1", "1000"),
1493
- createMockTransaction("tx2_2", "1000"),
1494
- ],
1495
- cursor: null,
1496
- };
1497
- const result = sdk.filterOperations(operationList1, operationList2, "ascending");
1498
- // Filter timestamp should be 1000 (the common timestamp)
1499
- // All operations have timestamp 1000, so all should pass the filter
1500
- expect(result.operations).toHaveLength(sdk.TRANSACTIONS_LIMIT + 2);
1501
- });
1502
- });
1503
- describe("conversion methods", () => {
1504
- test("toBlockOperation should map native transfers correctly", () => {
1505
- expect(sdk.toBlockOperation(mockTransaction, {
1506
- owner: {
1507
- AddressOwner: "0x65449f57946938c84c5127",
1508
- },
1509
- coinType: sdk.DEFAULT_COIN_TYPE,
1510
- amount: "-10000000000",
1511
- })).toEqual([
1512
- {
1513
- type: "transfer",
1514
- address: "0x65449f57946938c84c5127",
1515
- amount: -10000000000n,
1516
- asset: { type: "native" },
1517
- },
1518
- ]);
1519
- });
1520
- test("toBlockOperation should ignore transfers from shared owner", () => {
1521
- expect(sdk.toBlockOperation(mockTransaction, {
1522
- owner: {
1523
- Shared: {
1524
- initial_shared_version: "0",
1525
- },
1526
- },
1527
- coinType: sdk.DEFAULT_COIN_TYPE,
1528
- amount: "-10000000000",
1529
- })).toEqual([]);
1530
- });
1531
- test("toBlockOperation should ignore transfers from object owner", () => {
1532
- expect(sdk.toBlockOperation(mockTransaction, {
1533
- owner: {
1534
- ObjectOwner: "test",
1535
- },
1536
- coinType: sdk.DEFAULT_COIN_TYPE,
1537
- amount: "-10000000000",
1538
- })).toEqual([]);
1539
- });
1540
- test("toBlockOperation should ignore transfers from immutable owner", () => {
1541
- expect(sdk.toBlockOperation(mockTransaction, {
1542
- owner: "Immutable",
1543
- coinType: sdk.DEFAULT_COIN_TYPE,
1544
- amount: "-10000000000",
1545
- })).toEqual([]);
1546
- });
1547
- test("toBlockOperation should ignore transfers from consensus owner", () => {
1548
- expect(sdk.toBlockOperation(mockTransaction, {
1549
- owner: {
1550
- ConsensusAddressOwner: {
1551
- owner: "test",
1552
- start_version: "1",
1553
- },
1554
- },
1555
- coinType: sdk.DEFAULT_COIN_TYPE,
1556
- amount: "-10000000000",
1557
- })).toEqual([]);
1558
- });
1559
- test("toBlockOperation should map token transfers correctly", () => {
1560
- expect(sdk.toBlockOperation(mockTransaction, {
1561
- owner: {
1562
- AddressOwner: "0x65449f57946938c84c5127",
1563
- },
1564
- coinType: "0x168da5bf1f48dafc111b0a488fa454aca95e0b5e::usdc::USDC",
1565
- amount: "8824",
1566
- })).toEqual([
1567
- {
1568
- type: "transfer",
1569
- address: "0x65449f57946938c84c5127",
1570
- amount: 8824n,
1571
- asset: {
1572
- type: "token",
1573
- assetReference: "0x168da5bf1f48dafc111b0a488fa454aca95e0b5e::usdc::USDC",
1574
- },
1575
- },
1576
- ]);
1577
- });
1578
- test("toBlockOperation should map staking operations correctly", () => {
1579
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
1580
- expect(sdk.toBlockOperation(mockStakingTx(address, "-1000000000"), {
1581
- owner: { AddressOwner: address },
1582
- coinType: sdk.DEFAULT_COIN_TYPE,
1583
- amount: "-10000000000",
1584
- })).toEqual([
1585
- {
1586
- type: "other",
1587
- operationType: "DELEGATE",
1588
- address: address,
1589
- asset: { type: "native" },
1590
- amount: 10000000000n,
1591
- },
1592
- ]);
1593
- });
1594
- test("toBlockOperation should map unstaking operations correctly", () => {
1595
- const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
1596
- expect(sdk.toBlockOperation(mockUnstakingTx(address, "1000000000"), {
1597
- owner: { AddressOwner: address },
1598
- coinType: sdk.DEFAULT_COIN_TYPE,
1599
- amount: "10000000000",
1600
- })).toEqual([
1601
- {
1602
- type: "other",
1603
- operationType: "UNDELEGATE",
1604
- address: address,
1605
- asset: { type: "native" },
1606
- amount: 10000000000n,
1607
- },
1608
- ]);
1609
- });
1610
- test("toBlockInfo should map checkpoints correctly", () => {
1611
- expect(sdk.toBlockInfo({
1612
- checkpointCommitments: [],
1613
- digest: "0xaaaaaaaaa",
1614
- previousDigest: "0xbbbbbbbbbb",
1615
- epoch: "",
1616
- epochRollingGasCostSummary: {
1617
- computationCost: "",
1618
- nonRefundableStorageFee: "",
1619
- storageCost: "",
1620
- storageRebate: "",
1621
- },
1622
- networkTotalTransactions: "",
1623
- sequenceNumber: "42",
1624
- timestampMs: "1751696298663",
1625
- transactions: [],
1626
- validatorSignature: "",
1627
- })).toEqual({
1628
- height: 42,
1629
- hash: "0xaaaaaaaaa",
1630
- time: new Date(1751696298663),
1631
- parent: {
1632
- height: 41,
1633
- hash: "0xbbbbbbbbbb",
1634
- },
1635
- });
1636
- });
1637
- test("toBlockTransaction should map transactions correctly", () => {
1638
- expect(sdk.toBlockTransaction(
1639
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1640
- mockTransaction)).toEqual({
1641
- hash: "DhKLpX5kwuKuyRa71RGqpX5EY2M8Efw535ZVXYXsRiDt",
1642
- failed: false,
1643
- fees: 1009880n,
1644
- feesPayer: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
1645
- operations: [
1646
- {
1647
- address: "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24",
1648
- amount: -10000000000n,
1649
- asset: { type: "native" },
1650
- type: "transfer",
1651
- },
1652
- {
1653
- address: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
1654
- amount: 9998990120n,
1655
- asset: { type: "native" },
1656
- type: "transfer",
1657
- },
1658
- {
1659
- address: "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0",
1660
- amount: 500000n,
1661
- asset: { type: "token", assetReference: "0x123::test::TOKEN" },
1662
- type: "transfer",
1663
- },
1664
- ],
1665
- });
1666
- });
1667
- test("toSuiAsset should map native coin correctly", () => {
1668
- expect(sdk.toSuiAsset(sdk.DEFAULT_COIN_TYPE)).toEqual({ type: "native" });
1669
- });
1670
- test("suiCoinTypeToAsset should map tokens correctly", () => {
1671
- expect(sdk.toSuiAsset("0x123::test::TOKEN")).toEqual({
1672
- type: "token",
1673
- assetReference: "0x123::test::TOKEN",
1674
- });
1675
- });
1676
- });
1677
- });
1678
- describe("getCoinsForAmount", () => {
1679
- const mockAddress = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
1680
- const mockCoinType = "0x2::sui::SUI";
1681
- beforeEach(() => {
1682
- mockApi.getCoins.mockReset();
1683
- });
1684
- describe("basic functionality", () => {
1685
- test("handles single coin scenarios", async () => {
1686
- const sufficientCoins = createMockCoins(["1000"]);
1687
- mockApi.getCoins.mockResolvedValueOnce({ data: sufficientCoins, hasNextPage: false });
1688
- let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1689
- expect(result).toHaveLength(1);
1690
- expect(result[0].balance).toBe("1000");
1691
- const insufficientCoins = createMockCoins(["500"]);
1692
- mockApi.getCoins.mockResolvedValueOnce({ data: insufficientCoins, hasNextPage: false });
1693
- result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1694
- expect(result).toHaveLength(1);
1695
- expect(result[0].balance).toBe("500");
1696
- });
1697
- test("selects minimum coins needed", async () => {
1698
- const exactMatchCoins = createMockCoins(["600", "400", "300"]);
1699
- mockApi.getCoins.mockResolvedValueOnce({ data: exactMatchCoins, hasNextPage: false });
1700
- let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1701
- expect(result).toHaveLength(2);
1702
- expect(result[0].balance).toBe("600");
1703
- expect(result[1].balance).toBe("400");
1704
- const exceedCoins = createMockCoins(["800", "400", "200"]);
1705
- mockApi.getCoins.mockResolvedValueOnce({ data: exceedCoins, hasNextPage: false });
1706
- result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1707
- expect(result).toHaveLength(2);
1708
- expect(result[0].balance).toBe("800");
1709
- expect(result[1].balance).toBe("400");
1710
- });
1711
- test("handles edge cases", async () => {
1712
- mockApi.getCoins.mockResolvedValueOnce({ data: [], hasNextPage: false });
1713
- let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1714
- expect(result).toHaveLength(0);
1715
- const coins = createMockCoins(["1000"]);
1716
- mockApi.getCoins.mockResolvedValueOnce({ data: coins, hasNextPage: false });
1717
- result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 0);
1718
- expect(result).toHaveLength(0);
1719
- });
1720
- });
1721
- describe("sorting and filtering", () => {
1722
- test("filters zero balance coins", async () => {
1723
- const mockCoins = createMockCoins(["1000", "500"]);
1724
- mockCoins.splice(1, 0, createMockCoins(["0"])[0]);
1725
- mockCoins.push({ coinObjectId: "0xcoin4", balance: "0", digest: "0xdigest4", version: "1" });
1726
- mockApi.getCoins.mockResolvedValueOnce({ data: mockCoins, hasNextPage: false });
1727
- const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1728
- expect(result).toHaveLength(1);
1729
- expect(result[0].balance).toBe("1000");
1730
- expect(result.every(coin => parseInt(coin.balance) > 0)).toBe(true);
1731
- });
1732
- test("sorts and optimizes coin selection", async () => {
1733
- const unsortedCoins = createMockCoins(["100", "800", "300", "500"]);
1734
- mockApi.getCoins.mockResolvedValueOnce({ data: unsortedCoins, hasNextPage: false });
1735
- let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1736
- expect(result).toHaveLength(2);
1737
- expect(result[0].balance).toBe("800");
1738
- expect(result[1].balance).toBe("500");
1739
- const mixedCoins = createMockCoins(["200", "800", "400"]);
1740
- mixedCoins.unshift(createMockCoins(["0"])[0]);
1741
- mixedCoins.splice(2, 0, createMockCoins(["0"])[0]);
1742
- mockApi.getCoins.mockResolvedValueOnce({ data: mixedCoins, hasNextPage: false });
1743
- result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1744
- expect(result).toHaveLength(2);
1745
- expect(result[0].balance).toBe("800");
1746
- expect(result[1].balance).toBe("400");
1747
- expect(result.every(coin => parseInt(coin.balance) > 0)).toBe(true);
1748
- });
1749
- test("handles all zero balance coins", async () => {
1750
- const mockCoins = createMockCoins(["0", "0", "0"]);
1751
- mockApi.getCoins.mockResolvedValueOnce({ data: mockCoins, hasNextPage: false });
1752
- const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1753
- expect(result).toHaveLength(0);
1754
- expect(result).toEqual([]);
1755
- });
1756
- });
1757
- describe("pagination", () => {
1758
- test("handles single page scenarios", async () => {
1759
- const mockCoins = createMockCoins(["800", "400", "300"]);
1760
- mockApi.getCoins.mockResolvedValueOnce({
1761
- data: mockCoins,
1762
- hasNextPage: true,
1763
- nextCursor: "cursor1",
1764
- });
1765
- const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1766
- expect(result).toHaveLength(2);
1767
- expect(result[0].balance).toBe("800");
1768
- expect(result[1].balance).toBe("400");
1769
- expect(mockApi.getCoins).toHaveBeenCalledTimes(1);
1770
- });
1771
- test("handles multi-page scenarios", async () => {
1772
- const firstPageCoins = createMockCoins(["300", "200"]);
1773
- const secondPageCoins = createMockCoins(["600", "400", "100"]);
1774
- mockApi.getCoins
1775
- .mockResolvedValueOnce({
1776
- data: firstPageCoins,
1777
- hasNextPage: true,
1778
- nextCursor: "cursor1",
1779
- })
1780
- .mockResolvedValueOnce({
1781
- data: secondPageCoins,
1782
- hasNextPage: false,
1783
- });
1784
- const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1785
- expect(result).toHaveLength(3);
1786
- expect(result[0].balance).toBe("300");
1787
- expect(result[1].balance).toBe("200");
1788
- expect(result[2].balance).toBe("600");
1789
- expect(mockApi.getCoins).toHaveBeenCalledTimes(2);
1790
- });
1791
- test("handles insufficient funds across pages", async () => {
1792
- const firstPageCoins = createMockCoins(["300", "200"]);
1793
- const secondPageCoins = createMockCoins(["200", "100"]);
1794
- mockApi.getCoins
1795
- .mockResolvedValueOnce({
1796
- data: firstPageCoins,
1797
- hasNextPage: true,
1798
- nextCursor: "cursor1",
1799
- })
1800
- .mockResolvedValueOnce({
1801
- data: secondPageCoins,
1802
- hasNextPage: false,
1803
- });
1804
- const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
1805
- expect(result).toHaveLength(4);
1806
- expect(result[0].balance).toBe("300");
1807
- expect(result[1].balance).toBe("200");
1808
- expect(result[2].balance).toBe("200");
1809
- expect(result[3].balance).toBe("100");
1810
- expect(mockApi.getCoins).toHaveBeenCalledTimes(2);
1811
- });
1812
- });
1813
- });
1814
- //# sourceMappingURL=sdk.test.js.map