@spacesops/wdk-react-native-core 1.0.0-beta.40

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 (275) hide show
  1. package/README.md +551 -0
  2. package/dist/__mocks__/react.d.ts +40 -0
  3. package/dist/__mocks__/react.js +33 -0
  4. package/dist/__mocks__/react.js.map +1 -0
  5. package/dist/__mocks__/secureStorage.d.ts +26 -0
  6. package/dist/__mocks__/secureStorage.js +80 -0
  7. package/dist/__mocks__/secureStorage.js.map +1 -0
  8. package/dist/__tests__/hooks/useBalance.test.d.ts +6 -0
  9. package/dist/__tests__/hooks/useBalance.test.js +217 -0
  10. package/dist/__tests__/hooks/useBalance.test.js.map +1 -0
  11. package/dist/__tests__/hooks/useWallet.test.d.ts +6 -0
  12. package/dist/__tests__/hooks/useWallet.test.js +105 -0
  13. package/dist/__tests__/hooks/useWallet.test.js.map +1 -0
  14. package/dist/__tests__/hooks/useWalletManager.test.d.ts +6 -0
  15. package/dist/__tests__/hooks/useWalletManager.test.js +193 -0
  16. package/dist/__tests__/hooks/useWalletManager.test.js.map +1 -0
  17. package/dist/__tests__/hooks/useWdkApp.test.d.ts +6 -0
  18. package/dist/__tests__/hooks/useWdkApp.test.js +55 -0
  19. package/dist/__tests__/hooks/useWdkApp.test.js.map +1 -0
  20. package/dist/__tests__/hooks/useWorklet.test.d.ts +6 -0
  21. package/dist/__tests__/hooks/useWorklet.test.js +168 -0
  22. package/dist/__tests__/hooks/useWorklet.test.js.map +1 -0
  23. package/dist/__tests__/provider/WdkAppProvider.test.d.ts +6 -0
  24. package/dist/__tests__/provider/WdkAppProvider.test.js +57 -0
  25. package/dist/__tests__/provider/WdkAppProvider.test.js.map +1 -0
  26. package/dist/__tests__/services/accountService.test.d.ts +6 -0
  27. package/dist/__tests__/services/accountService.test.js +216 -0
  28. package/dist/__tests__/services/accountService.test.js.map +1 -0
  29. package/dist/__tests__/services/addressService.test.d.ts +6 -0
  30. package/dist/__tests__/services/addressService.test.js +246 -0
  31. package/dist/__tests__/services/addressService.test.js.map +1 -0
  32. package/dist/__tests__/services/balanceService.test.d.ts +6 -0
  33. package/dist/__tests__/services/balanceService.test.js +333 -0
  34. package/dist/__tests__/services/balanceService.test.js.map +1 -0
  35. package/dist/__tests__/services/walletSetupService.test.d.ts +6 -0
  36. package/dist/__tests__/services/walletSetupService.test.js +304 -0
  37. package/dist/__tests__/services/walletSetupService.test.js.map +1 -0
  38. package/dist/__tests__/services/walletSwitchingService.test.d.ts +6 -0
  39. package/dist/__tests__/services/walletSwitchingService.test.js +209 -0
  40. package/dist/__tests__/services/walletSwitchingService.test.js.map +1 -0
  41. package/dist/__tests__/services/workletLifecycleService.test.d.ts +6 -0
  42. package/dist/__tests__/services/workletLifecycleService.test.js +451 -0
  43. package/dist/__tests__/services/workletLifecycleService.test.js.map +1 -0
  44. package/dist/__tests__/setup.d.ts +7 -0
  45. package/dist/__tests__/setup.js +49 -0
  46. package/dist/__tests__/setup.js.map +1 -0
  47. package/dist/__tests__/storage/mmkvStorage.test.d.ts +6 -0
  48. package/dist/__tests__/storage/mmkvStorage.test.js +213 -0
  49. package/dist/__tests__/storage/mmkvStorage.test.js.map +1 -0
  50. package/dist/__tests__/store/walletStore.test.d.ts +4 -0
  51. package/dist/__tests__/store/walletStore.test.js +86 -0
  52. package/dist/__tests__/store/walletStore.test.js.map +1 -0
  53. package/dist/__tests__/store/workletStore.test.d.ts +4 -0
  54. package/dist/__tests__/store/workletStore.test.js +255 -0
  55. package/dist/__tests__/store/workletStore.test.js.map +1 -0
  56. package/dist/__tests__/types/hrpc.test.d.ts +4 -0
  57. package/dist/__tests__/types/hrpc.test.js +99 -0
  58. package/dist/__tests__/types/hrpc.test.js.map +1 -0
  59. package/dist/__tests__/utils/balanceUtils.test.d.ts +4 -0
  60. package/dist/__tests__/utils/balanceUtils.test.js +133 -0
  61. package/dist/__tests__/utils/balanceUtils.test.js.map +1 -0
  62. package/dist/__tests__/utils/errorHandling.test.d.ts +6 -0
  63. package/dist/__tests__/utils/errorHandling.test.js +119 -0
  64. package/dist/__tests__/utils/errorHandling.test.js.map +1 -0
  65. package/dist/__tests__/utils/errorUtils.test.d.ts +4 -0
  66. package/dist/__tests__/utils/errorUtils.test.js +133 -0
  67. package/dist/__tests__/utils/errorUtils.test.js.map +1 -0
  68. package/dist/__tests__/utils/initializationState.test.d.ts +6 -0
  69. package/dist/__tests__/utils/initializationState.test.js +243 -0
  70. package/dist/__tests__/utils/initializationState.test.js.map +1 -0
  71. package/dist/__tests__/utils/jsonUtils.test.d.ts +4 -0
  72. package/dist/__tests__/utils/jsonUtils.test.js +118 -0
  73. package/dist/__tests__/utils/jsonUtils.test.js.map +1 -0
  74. package/dist/__tests__/utils/mmkvKeyManager.test.d.ts +6 -0
  75. package/dist/__tests__/utils/mmkvKeyManager.test.js +158 -0
  76. package/dist/__tests__/utils/mmkvKeyManager.test.js.map +1 -0
  77. package/dist/__tests__/utils/mnemonicUtils.test.d.ts +4 -0
  78. package/dist/__tests__/utils/mnemonicUtils.test.js +40 -0
  79. package/dist/__tests__/utils/mnemonicUtils.test.js.map +1 -0
  80. package/dist/__tests__/utils/raceConditions.test.d.ts +6 -0
  81. package/dist/__tests__/utils/raceConditions.test.js +239 -0
  82. package/dist/__tests__/utils/raceConditions.test.js.map +1 -0
  83. package/dist/__tests__/utils/result.test.d.ts +4 -0
  84. package/dist/__tests__/utils/result.test.js +66 -0
  85. package/dist/__tests__/utils/result.test.js.map +1 -0
  86. package/dist/__tests__/utils/schemas.test.d.ts +4 -0
  87. package/dist/__tests__/utils/schemas.test.js +66 -0
  88. package/dist/__tests__/utils/schemas.test.js.map +1 -0
  89. package/dist/__tests__/utils/storeHelpers.test.d.ts +4 -0
  90. package/dist/__tests__/utils/storeHelpers.test.js +227 -0
  91. package/dist/__tests__/utils/storeHelpers.test.js.map +1 -0
  92. package/dist/__tests__/utils/typeGuards.test.d.ts +4 -0
  93. package/dist/__tests__/utils/typeGuards.test.js +175 -0
  94. package/dist/__tests__/utils/typeGuards.test.js.map +1 -0
  95. package/dist/__tests__/utils/validation.test.d.ts +4 -0
  96. package/dist/__tests__/utils/validation.test.js +126 -0
  97. package/dist/__tests__/utils/validation.test.js.map +1 -0
  98. package/dist/__tests__/utils/walletUtils.test.d.ts +4 -0
  99. package/dist/__tests__/utils/walletUtils.test.js +156 -0
  100. package/dist/__tests__/utils/walletUtils.test.js.map +1 -0
  101. package/dist/hooks/useBalance.d.ts +170 -0
  102. package/dist/hooks/useBalance.js +442 -0
  103. package/dist/hooks/useBalance.js.map +1 -0
  104. package/dist/hooks/useWallet.d.ts +43 -0
  105. package/dist/hooks/useWallet.js +193 -0
  106. package/dist/hooks/useWallet.js.map +1 -0
  107. package/dist/hooks/useWalletManager.d.ts +100 -0
  108. package/dist/hooks/useWalletManager.js +526 -0
  109. package/dist/hooks/useWalletManager.js.map +1 -0
  110. package/dist/hooks/useWdkApp.d.ts +66 -0
  111. package/dist/hooks/useWdkApp.js +74 -0
  112. package/dist/hooks/useWdkApp.js.map +1 -0
  113. package/dist/hooks/useWorklet.d.ts +66 -0
  114. package/dist/hooks/useWorklet.js +42 -0
  115. package/dist/hooks/useWorklet.js.map +1 -0
  116. package/dist/index.d.ts +33 -0
  117. package/dist/index.js +36 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/provider/WdkAppProvider.d.ts +112 -0
  120. package/dist/provider/WdkAppProvider.js +558 -0
  121. package/dist/provider/WdkAppProvider.js.map +1 -0
  122. package/dist/services/accountService.d.ts +52 -0
  123. package/dist/services/accountService.js +119 -0
  124. package/dist/services/accountService.js.map +1 -0
  125. package/dist/services/addressService.d.ts +22 -0
  126. package/dist/services/addressService.js +110 -0
  127. package/dist/services/addressService.js.map +1 -0
  128. package/dist/services/balanceService.d.ts +114 -0
  129. package/dist/services/balanceService.js +208 -0
  130. package/dist/services/balanceService.js.map +1 -0
  131. package/dist/services/walletSetupService.d.ts +217 -0
  132. package/dist/services/walletSetupService.js +535 -0
  133. package/dist/services/walletSetupService.js.map +1 -0
  134. package/dist/services/walletSwitchingService.d.ts +48 -0
  135. package/dist/services/walletSwitchingService.js +143 -0
  136. package/dist/services/walletSwitchingService.js.map +1 -0
  137. package/dist/services/workletLifecycleService.d.ts +117 -0
  138. package/dist/services/workletLifecycleService.js +433 -0
  139. package/dist/services/workletLifecycleService.js.map +1 -0
  140. package/dist/storage/mmkvStorage.d.ts +44 -0
  141. package/dist/storage/mmkvStorage.js +348 -0
  142. package/dist/storage/mmkvStorage.js.map +1 -0
  143. package/dist/store/walletStore.d.ts +130 -0
  144. package/dist/store/walletStore.js +204 -0
  145. package/dist/store/walletStore.js.map +1 -0
  146. package/dist/store/workletStore.d.ts +121 -0
  147. package/dist/store/workletStore.js +256 -0
  148. package/dist/store/workletStore.js.map +1 -0
  149. package/dist/types/hrpc.d.ts +60 -0
  150. package/dist/types/hrpc.js +26 -0
  151. package/dist/types/hrpc.js.map +1 -0
  152. package/dist/types.d.ts +168 -0
  153. package/dist/types.js +7 -0
  154. package/dist/types.js.map +1 -0
  155. package/dist/utils/balanceUtils.d.ts +30 -0
  156. package/dist/utils/balanceUtils.js +86 -0
  157. package/dist/utils/balanceUtils.js.map +1 -0
  158. package/dist/utils/constants.d.ts +66 -0
  159. package/dist/utils/constants.js +73 -0
  160. package/dist/utils/constants.js.map +1 -0
  161. package/dist/utils/errorHandling.d.ts +47 -0
  162. package/dist/utils/errorHandling.js +54 -0
  163. package/dist/utils/errorHandling.js.map +1 -0
  164. package/dist/utils/errorUtils.d.ts +89 -0
  165. package/dist/utils/errorUtils.js +264 -0
  166. package/dist/utils/errorUtils.js.map +1 -0
  167. package/dist/utils/initializationState.d.ts +129 -0
  168. package/dist/utils/initializationState.js +220 -0
  169. package/dist/utils/initializationState.js.map +1 -0
  170. package/dist/utils/jsonUtils.d.ts +21 -0
  171. package/dist/utils/jsonUtils.js +67 -0
  172. package/dist/utils/jsonUtils.js.map +1 -0
  173. package/dist/utils/logger.d.ts +27 -0
  174. package/dist/utils/logger.js +50 -0
  175. package/dist/utils/logger.js.map +1 -0
  176. package/dist/utils/mmkvKeyManager.d.ts +57 -0
  177. package/dist/utils/mmkvKeyManager.js +214 -0
  178. package/dist/utils/mmkvKeyManager.js.map +1 -0
  179. package/dist/utils/mnemonicUtils.d.ts +17 -0
  180. package/dist/utils/mnemonicUtils.js +28 -0
  181. package/dist/utils/mnemonicUtils.js.map +1 -0
  182. package/dist/utils/operationMutex.d.ts +69 -0
  183. package/dist/utils/operationMutex.js +150 -0
  184. package/dist/utils/operationMutex.js.map +1 -0
  185. package/dist/utils/result.d.ts +34 -0
  186. package/dist/utils/result.js +43 -0
  187. package/dist/utils/result.js.map +1 -0
  188. package/dist/utils/schemas.d.ts +365 -0
  189. package/dist/utils/schemas.js +152 -0
  190. package/dist/utils/schemas.js.map +1 -0
  191. package/dist/utils/storeHelpers.d.ts +112 -0
  192. package/dist/utils/storeHelpers.js +198 -0
  193. package/dist/utils/storeHelpers.js.map +1 -0
  194. package/dist/utils/typeGuards.d.ts +70 -0
  195. package/dist/utils/typeGuards.js +95 -0
  196. package/dist/utils/typeGuards.js.map +1 -0
  197. package/dist/utils/validation.d.ts +53 -0
  198. package/dist/utils/validation.js +152 -0
  199. package/dist/utils/validation.js.map +1 -0
  200. package/dist/utils/walletStateHelpers.d.ts +62 -0
  201. package/dist/utils/walletStateHelpers.js +81 -0
  202. package/dist/utils/walletStateHelpers.js.map +1 -0
  203. package/dist/utils/walletUtils.d.ts +38 -0
  204. package/dist/utils/walletUtils.js +87 -0
  205. package/dist/utils/walletUtils.js.map +1 -0
  206. package/package.json +79 -0
  207. package/src/__mocks__/react.ts +34 -0
  208. package/src/__mocks__/secureStorage.ts +87 -0
  209. package/src/__tests__/hooks/useBalance.test.ts +286 -0
  210. package/src/__tests__/hooks/useWallet.test.ts +122 -0
  211. package/src/__tests__/hooks/useWalletManager.test.ts +271 -0
  212. package/src/__tests__/hooks/useWdkApp.test.tsx +59 -0
  213. package/src/__tests__/hooks/useWorklet.test.ts +195 -0
  214. package/src/__tests__/provider/WdkAppProvider.test.tsx +67 -0
  215. package/src/__tests__/services/accountService.test.ts +337 -0
  216. package/src/__tests__/services/addressService.test.ts +312 -0
  217. package/src/__tests__/services/balanceService.test.ts +411 -0
  218. package/src/__tests__/services/walletSetupService.test.ts +463 -0
  219. package/src/__tests__/services/walletSwitchingService.test.ts +258 -0
  220. package/src/__tests__/services/workletLifecycleService.test.ts +514 -0
  221. package/src/__tests__/setup.ts +54 -0
  222. package/src/__tests__/storage/mmkvStorage.test.ts +325 -0
  223. package/src/__tests__/store/walletStore.test.ts +101 -0
  224. package/src/__tests__/store/workletStore.test.ts +329 -0
  225. package/src/__tests__/types/hrpc.test.ts +125 -0
  226. package/src/__tests__/utils/balanceUtils.test.ts +151 -0
  227. package/src/__tests__/utils/errorHandling.test.ts +147 -0
  228. package/src/__tests__/utils/errorUtils.test.ts +170 -0
  229. package/src/__tests__/utils/initializationState.test.ts +337 -0
  230. package/src/__tests__/utils/jsonUtils.test.ts +131 -0
  231. package/src/__tests__/utils/mmkvKeyManager.test.ts +205 -0
  232. package/src/__tests__/utils/mnemonicUtils.test.ts +48 -0
  233. package/src/__tests__/utils/raceConditions.test.ts +292 -0
  234. package/src/__tests__/utils/result.test.ts +73 -0
  235. package/src/__tests__/utils/schemas.test.ts +82 -0
  236. package/src/__tests__/utils/storeHelpers.test.ts +323 -0
  237. package/src/__tests__/utils/typeGuards.test.ts +209 -0
  238. package/src/__tests__/utils/validation.test.ts +152 -0
  239. package/src/__tests__/utils/walletUtils.test.ts +195 -0
  240. package/src/hooks/useBalance.ts +597 -0
  241. package/src/hooks/useWallet.ts +288 -0
  242. package/src/hooks/useWalletManager.ts +654 -0
  243. package/src/hooks/useWdkApp.ts +78 -0
  244. package/src/hooks/useWorklet.ts +109 -0
  245. package/src/index.ts +112 -0
  246. package/src/provider/WdkAppProvider.tsx +764 -0
  247. package/src/services/accountService.ts +134 -0
  248. package/src/services/addressService.ts +125 -0
  249. package/src/services/balanceService.ts +291 -0
  250. package/src/services/walletSetupService.ts +695 -0
  251. package/src/services/walletSwitchingService.ts +157 -0
  252. package/src/services/workletLifecycleService.ts +561 -0
  253. package/src/storage/mmkvStorage.ts +417 -0
  254. package/src/store/walletStore.ts +301 -0
  255. package/src/store/workletStore.ts +340 -0
  256. package/src/types/hrpc.ts +78 -0
  257. package/src/types.ts +188 -0
  258. package/src/utils/balanceUtils.ts +96 -0
  259. package/src/utils/constants.ts +84 -0
  260. package/src/utils/errorHandling.md +163 -0
  261. package/src/utils/errorHandling.ts +61 -0
  262. package/src/utils/errorUtils.ts +300 -0
  263. package/src/utils/initializationState.ts +242 -0
  264. package/src/utils/jsonUtils.ts +75 -0
  265. package/src/utils/logger.ts +54 -0
  266. package/src/utils/mmkvKeyManager.ts +256 -0
  267. package/src/utils/mnemonicUtils.ts +35 -0
  268. package/src/utils/operationMutex.ts +181 -0
  269. package/src/utils/result.ts +57 -0
  270. package/src/utils/schemas.ts +190 -0
  271. package/src/utils/storeHelpers.ts +236 -0
  272. package/src/utils/typeGuards.ts +129 -0
  273. package/src/utils/validation.ts +174 -0
  274. package/src/utils/walletStateHelpers.ts +104 -0
  275. package/src/utils/walletUtils.ts +107 -0
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Tests for AccountService
3
+ *
4
+ * Tests account method calls through the worklet
5
+ */
6
+
7
+ import { AccountService } from '../../services/accountService'
8
+ import { getWorkletStore } from '../../store/workletStore'
9
+
10
+ // Mock stores
11
+ jest.mock('../../store/workletStore', () => ({
12
+ getWorkletStore: jest.fn(),
13
+ }))
14
+
15
+ describe('AccountService', () => {
16
+ let mockWorkletStore: any
17
+ let mockHRPC: any
18
+
19
+ beforeEach(() => {
20
+ jest.clearAllMocks()
21
+
22
+ // Setup mock HRPC
23
+ mockHRPC = {
24
+ callMethod: jest.fn(),
25
+ }
26
+
27
+ // Setup mock worklet store
28
+ mockWorkletStore = {
29
+ getState: jest.fn(() => ({
30
+ isInitialized: true,
31
+ hrpc: mockHRPC,
32
+ })),
33
+ }
34
+
35
+ // Setup store mocks
36
+ ;(getWorkletStore as jest.Mock).mockReturnValue(mockWorkletStore)
37
+ })
38
+
39
+ describe('callAccountMethod', () => {
40
+ it('should call method and return result', async () => {
41
+ const mockResult = '1000000000000000000'
42
+ mockHRPC.callMethod.mockResolvedValue({
43
+ result: JSON.stringify(mockResult),
44
+ })
45
+
46
+ const result = await AccountService.callAccountMethod(
47
+ 'ethereum',
48
+ 0,
49
+ 'getBalance'
50
+ )
51
+
52
+ expect(result).toBe(mockResult)
53
+ expect(mockHRPC.callMethod).toHaveBeenCalledWith({
54
+ methodName: 'getBalance',
55
+ network: 'ethereum',
56
+ accountIndex: 0,
57
+ args: null,
58
+ })
59
+ })
60
+
61
+ it('should handle method with arguments', async () => {
62
+ const mockArgs = { message: 'Hello World' }
63
+ const mockResult = { signature: '0x123' }
64
+ mockHRPC.callMethod.mockResolvedValue({
65
+ result: JSON.stringify(mockResult),
66
+ })
67
+
68
+ const result = await AccountService.callAccountMethod(
69
+ 'ethereum',
70
+ 0,
71
+ 'signMessage',
72
+ mockArgs
73
+ )
74
+
75
+ expect(result).toEqual(mockResult)
76
+ expect(mockHRPC.callMethod).toHaveBeenCalledWith({
77
+ methodName: 'signMessage',
78
+ network: 'ethereum',
79
+ accountIndex: 0,
80
+ args: JSON.stringify(mockArgs),
81
+ })
82
+ })
83
+
84
+ it('should convert BigInt values to strings', async () => {
85
+ // getBalance returns a string, not an object
86
+ const mockResult = '1000000000000000000'
87
+ mockHRPC.callMethod.mockResolvedValue({
88
+ result: JSON.stringify(mockResult),
89
+ })
90
+
91
+ const result = await AccountService.callAccountMethod(
92
+ 'ethereum',
93
+ 0,
94
+ 'getBalance'
95
+ )
96
+
97
+ expect(result).toBe('1000000000000000000')
98
+ })
99
+
100
+ it('should convert BigInt in nested objects', async () => {
101
+ // Test with signMessage which can return an object
102
+ const mockResult = {
103
+ data: {
104
+ balance: BigInt('1000000000000000000'),
105
+ nested: {
106
+ amount: BigInt('2000000000000000000'),
107
+ },
108
+ },
109
+ }
110
+ const jsonString = JSON.stringify(
111
+ mockResult,
112
+ (_, value) => (typeof value === 'bigint' ? value.toString() : value)
113
+ )
114
+ mockHRPC.callMethod.mockResolvedValue({
115
+ result: jsonString,
116
+ })
117
+
118
+ const result = await AccountService.callAccountMethod(
119
+ 'ethereum',
120
+ 0,
121
+ 'signMessage',
122
+ { message: 'test' }
123
+ )
124
+
125
+ expect(result).toEqual({
126
+ data: {
127
+ balance: '1000000000000000000',
128
+ nested: {
129
+ amount: '2000000000000000000',
130
+ },
131
+ },
132
+ })
133
+ })
134
+
135
+ it('should convert BigInt in arrays', async () => {
136
+ // Test with signTransaction which can return an object with arrays
137
+ const mockResult = {
138
+ balances: ['1000000000000000000', '2000000000000000000'],
139
+ }
140
+ // Simulate BigInt in response by using a custom replacer
141
+ const jsonString = JSON.stringify(
142
+ {
143
+ balances: [BigInt('1000000000000000000'), BigInt('2000000000000000000')],
144
+ },
145
+ (_, value) => (typeof value === 'bigint' ? value.toString() : value)
146
+ )
147
+ mockHRPC.callMethod.mockResolvedValue({
148
+ result: jsonString,
149
+ })
150
+
151
+ const result = await AccountService.callAccountMethod(
152
+ 'ethereum',
153
+ 0,
154
+ 'signTransaction',
155
+ { transaction: {} }
156
+ )
157
+
158
+ expect(result).toEqual({
159
+ balances: ['1000000000000000000', '2000000000000000000'],
160
+ })
161
+ })
162
+
163
+ it('should validate methodName', async () => {
164
+ await expect(
165
+ AccountService.callAccountMethod('ethereum', 0, '', null)
166
+ ).rejects.toThrow('methodName must be a non-empty string')
167
+
168
+ await expect(
169
+ AccountService.callAccountMethod('ethereum', 0, ' ', null)
170
+ ).rejects.toThrow('methodName must be a non-empty string')
171
+ })
172
+
173
+ it('should accept various method names', async () => {
174
+ const methods = [
175
+ 'getAddress',
176
+ 'getBalance',
177
+ 'getTokenBalance',
178
+ 'signMessage',
179
+ 'signTransaction',
180
+ 'sendTransaction',
181
+ ]
182
+
183
+ for (const method of methods) {
184
+ // getBalance and getTokenBalance return strings, others can return objects
185
+ const mockResult = (method === 'getBalance' || method === 'getTokenBalance')
186
+ ? '1000000000000000000'
187
+ : { success: true }
188
+ mockHRPC.callMethod.mockResolvedValue({
189
+ result: JSON.stringify(mockResult),
190
+ })
191
+
192
+ await expect(
193
+ AccountService.callAccountMethod('ethereum', 0, method, null)
194
+ ).resolves.toBeDefined()
195
+ }
196
+ })
197
+
198
+ it('should use safeStringify for args', async () => {
199
+ const mockArgs = { test: 'value' }
200
+ mockHRPC.callMethod.mockResolvedValue({
201
+ result: JSON.stringify({ success: true }),
202
+ })
203
+
204
+ await AccountService.callAccountMethod(
205
+ 'ethereum',
206
+ 0,
207
+ 'signMessage',
208
+ mockArgs
209
+ )
210
+
211
+ expect(mockHRPC.callMethod).toHaveBeenCalledWith({
212
+ methodName: 'signMessage',
213
+ network: 'ethereum',
214
+ accountIndex: 0,
215
+ args: JSON.stringify(mockArgs),
216
+ })
217
+ })
218
+
219
+ it('should reject circular references in args', async () => {
220
+ const circular: any = { a: 1 }
221
+ circular.self = circular
222
+
223
+ await expect(
224
+ AccountService.callAccountMethod('ethereum', 0, 'signMessage', circular)
225
+ ).rejects.toThrow('circular references')
226
+ })
227
+
228
+ it('should validate balance response format', async () => {
229
+ mockHRPC.callMethod.mockResolvedValue({
230
+ result: JSON.stringify('invalid-balance-format'),
231
+ })
232
+
233
+ await expect(
234
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
235
+ ).rejects.toThrow('Invalid balance format')
236
+ })
237
+
238
+ it('should accept valid balance response format', async () => {
239
+ mockHRPC.callMethod.mockResolvedValue({
240
+ result: JSON.stringify('1000000000000000000'),
241
+ })
242
+
243
+ const result = await AccountService.callAccountMethod(
244
+ 'ethereum',
245
+ 0,
246
+ 'getBalance',
247
+ null
248
+ )
249
+
250
+ expect(result).toBe('1000000000000000000')
251
+ })
252
+
253
+ it('should validate network name', async () => {
254
+ await expect(
255
+ AccountService.callAccountMethod('', 0, 'getBalance', null)
256
+ ).rejects.toThrow(/network.*non-empty|Network name must contain only|String must contain at least 1 character/)
257
+ })
258
+
259
+ it('should validate account index', async () => {
260
+ await expect(
261
+ AccountService.callAccountMethod('ethereum', -1, 'getBalance', null)
262
+ ).rejects.toThrow(/accountIndex.*non-negative|Number must be greater than or equal to 0/)
263
+ })
264
+
265
+ it('should throw error if WDK not initialized', async () => {
266
+ mockWorkletStore.getState = jest.fn(() => ({
267
+ isInitialized: false,
268
+ hrpc: null,
269
+ }))
270
+
271
+ await expect(
272
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
273
+ ).rejects.toThrow('WDK not initialized')
274
+ })
275
+
276
+ it('should throw error if HRPC not available', async () => {
277
+ mockWorkletStore.getState = jest.fn(() => ({
278
+ isInitialized: true,
279
+ hrpc: null,
280
+ }))
281
+
282
+ await expect(
283
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
284
+ ).rejects.toThrow('WDK not initialized')
285
+ })
286
+
287
+ it('should throw error if method returns no result', async () => {
288
+ // workletResponseSchema requires result to be a string, so we need to mock a response that fails schema validation
289
+ mockHRPC.callMethod.mockResolvedValue({
290
+ result: null,
291
+ })
292
+
293
+ await expect(
294
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
295
+ ).rejects.toThrow(/Method getBalance returned no result|Expected string/)
296
+ })
297
+
298
+ it('should throw error if result is null', async () => {
299
+ mockHRPC.callMethod.mockResolvedValue({
300
+ result: JSON.stringify(null),
301
+ })
302
+
303
+ await expect(
304
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
305
+ ).rejects.toThrow('Parsed result is null or undefined')
306
+ })
307
+
308
+ it('should throw error if result is null', async () => {
309
+ mockHRPC.callMethod.mockResolvedValue({
310
+ result: JSON.stringify(null),
311
+ })
312
+
313
+ await expect(
314
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
315
+ ).rejects.toThrow('Parsed result is null or undefined')
316
+ })
317
+
318
+ it('should throw error if JSON parsing fails', async () => {
319
+ mockHRPC.callMethod.mockResolvedValue({
320
+ result: 'invalid json',
321
+ })
322
+
323
+ await expect(
324
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
325
+ ).rejects.toThrow('Failed to parse result from getBalance')
326
+ })
327
+
328
+ it('should handle worklet call errors', async () => {
329
+ mockHRPC.callMethod.mockRejectedValue(new Error('Worklet error'))
330
+
331
+ await expect(
332
+ AccountService.callAccountMethod('ethereum', 0, 'getBalance', null)
333
+ ).rejects.toThrow()
334
+ })
335
+ })
336
+ })
337
+
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Tests for AddressService
3
+ *
4
+ * Tests address retrieval functionality
5
+ */
6
+
7
+ import { AddressService } from '../../services/addressService'
8
+ import { getWorkletStore } from '../../store/workletStore'
9
+ import { getWalletStore } from '../../store/walletStore'
10
+
11
+ // Mock stores
12
+ jest.mock('../../store/workletStore', () => ({
13
+ getWorkletStore: jest.fn(),
14
+ }))
15
+
16
+ jest.mock('../../store/walletStore', () => ({
17
+ getWalletStore: jest.fn(),
18
+ }))
19
+
20
+ describe('AddressService', () => {
21
+ let mockWorkletStore: any
22
+ let mockWalletStore: any
23
+ let mockHRPC: any
24
+
25
+ beforeEach(() => {
26
+ jest.clearAllMocks()
27
+
28
+ // Setup mock HRPC
29
+ mockHRPC = {
30
+ callMethod: jest.fn(),
31
+ }
32
+
33
+ // Setup mock worklet store
34
+ mockWorkletStore = {
35
+ getState: jest.fn(() => ({
36
+ isInitialized: true,
37
+ hrpc: mockHRPC,
38
+ isWorkletStarted: true,
39
+ })),
40
+ }
41
+
42
+ // Setup mock wallet store
43
+ mockWalletStore = {
44
+ getState: jest.fn(() => ({
45
+ addresses: {},
46
+ walletLoading: {},
47
+ activeWalletId: 'test-wallet-1',
48
+ })),
49
+ setState: jest.fn(),
50
+ }
51
+
52
+ // Setup store mocks
53
+ ;(getWorkletStore as jest.Mock).mockReturnValue(mockWorkletStore)
54
+ ;(getWalletStore as jest.Mock).mockReturnValue(mockWalletStore)
55
+ })
56
+
57
+ describe('getAddress', () => {
58
+ it('should get address from worklet and cache it', async () => {
59
+ const mockAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
60
+ mockHRPC.callMethod.mockResolvedValue({
61
+ result: JSON.stringify(mockAddress),
62
+ })
63
+
64
+ const address = await AddressService.getAddress('ethereum', 0)
65
+
66
+ expect(address).toBe(mockAddress)
67
+ expect(mockHRPC.callMethod).toHaveBeenCalledWith({
68
+ methodName: 'getAddress',
69
+ network: 'ethereum',
70
+ accountIndex: 0,
71
+ args: null,
72
+ })
73
+
74
+ // Verify address was cached
75
+ expect(mockWalletStore.setState).toHaveBeenCalledWith(
76
+ expect.any(Function)
77
+ )
78
+
79
+ // Verify the state update function
80
+ const setStateCall = mockWalletStore.setState.mock.calls.find(
81
+ (call: any[]) => {
82
+ const stateUpdater = call[0]
83
+ if (typeof stateUpdater === 'function') {
84
+ const prevState = {
85
+ addresses: {},
86
+ walletLoading: {},
87
+ activeWalletId: 'test-wallet-1',
88
+ }
89
+ const newState = stateUpdater(prevState)
90
+ return newState.addresses?.['test-wallet-1']?.ethereum?.[0] === mockAddress
91
+ }
92
+ return false
93
+ }
94
+ )
95
+ expect(setStateCall).toBeDefined()
96
+ })
97
+
98
+ it('should return cached address if available', async () => {
99
+ const cachedAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
100
+ mockWalletStore.getState = jest.fn(() => ({
101
+ addresses: {
102
+ 'test-wallet-1': {
103
+ ethereum: {
104
+ 0: cachedAddress,
105
+ },
106
+ },
107
+ },
108
+ walletLoading: {},
109
+ activeWalletId: 'test-wallet-1',
110
+ }))
111
+
112
+ const address = await AddressService.getAddress('ethereum', 0)
113
+
114
+ expect(address).toBe(cachedAddress)
115
+ // Should not call HRPC if cached
116
+ expect(mockHRPC.callMethod).not.toHaveBeenCalled()
117
+ })
118
+
119
+ it('should handle different networks', async () => {
120
+ const ethereumAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
121
+ const polygonAddress = '0x842d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
122
+
123
+ mockHRPC.callMethod
124
+ .mockResolvedValueOnce({
125
+ result: JSON.stringify(ethereumAddress),
126
+ })
127
+ .mockResolvedValueOnce({
128
+ result: JSON.stringify(polygonAddress),
129
+ })
130
+
131
+ const ethAddr = await AddressService.getAddress('ethereum', 0)
132
+ const polyAddr = await AddressService.getAddress('polygon', 0)
133
+
134
+ expect(ethAddr).toBe(ethereumAddress)
135
+ expect(polyAddr).toBe(polygonAddress)
136
+ expect(mockHRPC.callMethod).toHaveBeenCalledTimes(2)
137
+ })
138
+
139
+ it('should handle different account indices', async () => {
140
+ const address0 = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
141
+ const address1 = '0x842d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
142
+
143
+ mockHRPC.callMethod
144
+ .mockResolvedValueOnce({
145
+ result: JSON.stringify(address0),
146
+ })
147
+ .mockResolvedValueOnce({
148
+ result: JSON.stringify(address1),
149
+ })
150
+
151
+ const addr0 = await AddressService.getAddress('ethereum', 0)
152
+ const addr1 = await AddressService.getAddress('ethereum', 1)
153
+
154
+ expect(addr0).toBe(address0)
155
+ expect(addr1).toBe(address1)
156
+ expect(mockHRPC.callMethod).toHaveBeenCalledWith(
157
+ expect.objectContaining({
158
+ network: 'ethereum',
159
+ accountIndex: 0,
160
+ })
161
+ )
162
+ expect(mockHRPC.callMethod).toHaveBeenCalledWith(
163
+ expect.objectContaining({
164
+ network: 'ethereum',
165
+ accountIndex: 1,
166
+ })
167
+ )
168
+ })
169
+
170
+ it('should throw error if WDK not initialized', async () => {
171
+ mockWorkletStore.getState = jest.fn(() => ({
172
+ isInitialized: false,
173
+ hrpc: null,
174
+ }))
175
+ mockWalletStore.getState = jest.fn(() => ({
176
+ addresses: {},
177
+ walletLoading: {},
178
+ activeWalletId: 'test-wallet-1',
179
+ }))
180
+
181
+ await expect(AddressService.getAddress('ethereum', 0)).rejects.toThrow(
182
+ 'WDK not initialized'
183
+ )
184
+ })
185
+
186
+ it('should throw error if HRPC not available', async () => {
187
+ mockWorkletStore.getState = jest.fn(() => ({
188
+ isInitialized: true,
189
+ hrpc: null,
190
+ }))
191
+ mockWalletStore.getState = jest.fn(() => ({
192
+ addresses: {},
193
+ walletLoading: {},
194
+ activeWalletId: 'test-wallet-1',
195
+ }))
196
+
197
+ await expect(AddressService.getAddress('ethereum', 0)).rejects.toThrow(
198
+ 'WDK not initialized'
199
+ )
200
+ })
201
+
202
+ it('should throw error if worklet call fails', async () => {
203
+ mockHRPC.callMethod.mockRejectedValue(new Error('Worklet error'))
204
+
205
+ await expect(AddressService.getAddress('ethereum', 0)).rejects.toThrow()
206
+ })
207
+
208
+ it('should throw error if worklet returns no result', async () => {
209
+ mockHRPC.callMethod.mockResolvedValue({
210
+ result: null,
211
+ })
212
+ mockWalletStore.getState = jest.fn(() => ({
213
+ addresses: {},
214
+ walletLoading: {},
215
+ activeWalletId: 'test-wallet-1',
216
+ }))
217
+
218
+ await expect(AddressService.getAddress('ethereum', 0)).rejects.toThrow(
219
+ /Failed to get address|Expected string/
220
+ )
221
+ })
222
+
223
+ it('should validate network name', async () => {
224
+ await expect(AddressService.getAddress('', 0)).rejects.toThrow(
225
+ /network.*non-empty|Network name must contain only|String must contain at least 1 character/
226
+ )
227
+ })
228
+
229
+ it('should validate account index', async () => {
230
+ await expect(AddressService.getAddress('ethereum', -1)).rejects.toThrow(
231
+ /accountIndex.*non-negative|Number must be greater than or equal to 0/
232
+ )
233
+ })
234
+
235
+ it('should handle all networks from the configuration', async () => {
236
+ const networks = ['ethereum', 'polygon', 'arbitrum', 'sepolia', 'plasma', 'spark']
237
+ // Use valid Ethereum address for most networks, Spark address for spark
238
+ const mockEthereumAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
239
+ const mockSparkAddress = 'spark1abcdefghijklmnopqrstuvwxyz123456'
240
+
241
+ for (const network of networks) {
242
+ const mockAddress = network === 'spark' ? mockSparkAddress : mockEthereumAddress
243
+ mockHRPC.callMethod.mockResolvedValueOnce({
244
+ result: JSON.stringify(mockAddress),
245
+ })
246
+
247
+ const address = await AddressService.getAddress(network, 0)
248
+ expect(address).toBe(mockAddress)
249
+ expect(mockHRPC.callMethod).toHaveBeenCalledWith(
250
+ expect.objectContaining({
251
+ network,
252
+ accountIndex: 0,
253
+ })
254
+ )
255
+ }
256
+
257
+ expect(mockHRPC.callMethod).toHaveBeenCalledTimes(networks.length)
258
+ })
259
+
260
+ it('should set loading state during address fetch', async () => {
261
+ const mockAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
262
+ mockHRPC.callMethod.mockResolvedValue({
263
+ result: JSON.stringify(mockAddress),
264
+ })
265
+
266
+ await AddressService.getAddress('ethereum', 0)
267
+
268
+ // Verify loading state was set to true, then false
269
+ const setStateCalls = mockWalletStore.setState.mock.calls
270
+ expect(setStateCalls.length).toBeGreaterThan(0)
271
+
272
+ // Track state changes - start with initial state
273
+ let currentState: any = {
274
+ walletLoading: {},
275
+ addresses: {},
276
+ balanceLoading: {},
277
+ lastBalanceUpdate: {},
278
+ balances: {},
279
+ activeWalletId: 'test-wallet-1',
280
+ }
281
+ let loadingWasSetToTrue = false
282
+ let loadingWasSetToFalse = false
283
+
284
+ for (const call of setStateCalls) {
285
+ const stateUpdater = call[0]
286
+ if (typeof stateUpdater === 'function') {
287
+ // Ensure all required state properties exist
288
+ const prevState = {
289
+ walletLoading: currentState.walletLoading || {},
290
+ addresses: currentState.addresses || {},
291
+ balanceLoading: currentState.balanceLoading || {},
292
+ lastBalanceUpdate: currentState.lastBalanceUpdate || {},
293
+ balances: currentState.balances || {},
294
+ activeWalletId: currentState.activeWalletId || 'test-wallet-1',
295
+ }
296
+ currentState = { ...prevState, ...stateUpdater(prevState) }
297
+ // Loading state is now per-wallet: walletLoading[walletId][loadingKey]
298
+ if (currentState.walletLoading?.['test-wallet-1']?.['ethereum-0'] === true) {
299
+ loadingWasSetToTrue = true
300
+ }
301
+ if (currentState.walletLoading?.['test-wallet-1']?.['ethereum-0'] === false) {
302
+ loadingWasSetToFalse = true
303
+ }
304
+ }
305
+ }
306
+
307
+ expect(loadingWasSetToTrue).toBe(true)
308
+ expect(loadingWasSetToFalse).toBe(true)
309
+ })
310
+ })
311
+ })
312
+