@@ -3,6 +3,8 @@ import {mockUser} from "../__mocks__/fcl"
3
3
import * as fcl from "@onflow/fcl"
4
4
import * as rlp from "@onflow/rlp"
5
5
import { CurrentUser } from "@onflow/typedefs"
6
+ import { ChainIdStore , NetworkManager } from "../network/network-manager"
7
+ import { BehaviorSubject , Subject } from "../util/observable"
6
8
7
9
jest . mock ( "@onflow/fcl" , ( ) => {
8
10
const fcl = jest . requireActual ( "@onflow/fcl" )
@@ -24,35 +26,41 @@ const mockFcl = jest.mocked(fcl)
24
26
const mockQuery = jest . mocked ( fcl . query )
25
27
26
28
describe ( "AccountManager" , ( ) => {
29
+ let networkManager : jest . Mocked < NetworkManager >
30
+ let userMock : ReturnType < typeof mockUser >
31
+
27
32
beforeEach ( ( ) => {
28
33
jest . clearAllMocks ( )
34
+
35
+ const chainId$ = new BehaviorSubject < number | null > ( 747 )
36
+ networkManager = {
37
+ $chainId : chainId$ ,
38
+ getChainId : ( ) => chainId$ . getValue ( ) ,
39
+ } as any as jest . Mocked < NetworkManager >
40
+ userMock = mockUser ( )
29
41
} )
30
42
31
43
it ( "should initialize with null COA address" , async ( ) => {
32
- const user = mockUser ( )
33
- const accountManager = new AccountManager ( user . mock )
44
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
34
45
expect ( await accountManager . getCOAAddress ( ) ) . toBeNull ( )
35
46
expect ( await accountManager . getAccounts ( ) ) . toEqual ( [ ] )
36
47
} )
37
48
38
49
it ( "should reset state when the user is not logged in" , async ( ) => {
39
- const user = mockUser ( )
40
-
41
- const accountManager = new AccountManager ( user . mock )
50
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
42
51
43
52
expect ( await accountManager . getCOAAddress ( ) ) . toBeNull ( )
44
53
expect ( await accountManager . getAccounts ( ) ) . toEqual ( [ ] )
45
54
} )
46
55
47
56
it ( "should fetch and update COA address when user logs in" , async ( ) => {
48
- const user = mockUser ( )
49
57
mockQuery . mockResolvedValue ( "0x123" )
50
58
51
- const accountManager = new AccountManager ( user . mock )
59
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
52
60
53
61
expect ( await accountManager . getCOAAddress ( ) ) . toBe ( null )
54
62
55
- user . set ! ( { addr : "0x1" } as CurrentUser )
63
+ userMock . set ! ( { addr : "0x1" } as CurrentUser )
56
64
57
65
expect ( await accountManager . getCOAAddress ( ) ) . toBe ( "0x123" )
58
66
expect ( await accountManager . getAccounts ( ) ) . toEqual ( [ "0x123" ] )
@@ -63,26 +71,24 @@ describe("AccountManager", () => {
63
71
} )
64
72
65
73
it ( "should not update COA address if user has not changed" , async ( ) => {
66
- const user = mockUser ( )
67
74
mockQuery . mockResolvedValue ( "0x123" )
68
75
69
- const accountManager = new AccountManager ( user . mock )
76
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
70
77
71
- user . set ! ( { addr : "0x1" } as CurrentUser )
78
+ userMock . set ! ( { addr : "0x1" } as CurrentUser )
72
79
73
80
await new Promise ( setImmediate )
74
81
75
82
expect ( await accountManager . getCOAAddress ( ) ) . toBe ( "0x123" )
76
83
expect ( fcl . query ) . toHaveBeenCalledTimes ( 1 )
77
84
78
- user . set ! ( { addr : "0x1" } as CurrentUser )
85
+ userMock . set ! ( { addr : "0x1" } as CurrentUser )
79
86
80
87
expect ( await accountManager . getCOAAddress ( ) ) . toBe ( "0x123" )
81
88
expect ( fcl . query ) . toHaveBeenCalledTimes ( 1 ) // Should not have fetched again
82
89
} )
83
90
84
91
it ( "should not update COA address if fetch is outdated when user changes" , async ( ) => {
85
- const user = mockUser ( )
86
92
mockQuery . mockResolvedValue ( "0x123" )
87
93
88
94
mockQuery
@@ -93,39 +99,36 @@ describe("AccountManager", () => {
93
99
// 2nd fetch: immediate
94
100
. mockResolvedValueOnce ( "0x456" )
95
101
96
- const accountManager = new AccountManager ( user . mock )
102
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
97
103
98
- await user . set ! ( { addr : "0x1" } as CurrentUser )
99
- await user . set ! ( { addr : "0x2" } as CurrentUser )
104
+ await userMock . set ! ( { addr : "0x1" } as CurrentUser )
105
+ await userMock . set ! ( { addr : "0x2" } as CurrentUser )
100
106
101
107
// The second fetch (for address 0x2) is the latest, so "0x456"
102
108
expect ( await accountManager . getCOAAddress ( ) ) . toBe ( "0x456" )
103
109
} )
104
110
105
111
it ( "should throw if COA address fetch fails" , async ( ) => {
106
- const user = mockUser ( )
107
112
mockQuery . mockRejectedValueOnce ( new Error ( "Fetch failed" ) )
108
113
109
- const accountManager = new AccountManager ( user . mock )
114
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
110
115
111
- await user . set ! ( { addr : "0x1" } as CurrentUser )
116
+ await userMock . set ! ( { addr : "0x1" } as CurrentUser )
112
117
113
118
await expect ( accountManager . getCOAAddress ( ) ) . rejects . toThrow ( "Fetch failed" )
114
119
} )
115
120
116
121
it ( "should handle user changes correctly" , async ( ) => {
117
- const user = mockUser ( )
118
-
119
122
mockQuery
120
123
. mockResolvedValueOnce ( "0x123" ) // for user 0x1
121
124
. mockResolvedValueOnce ( "0x456" ) // for user 0x2
122
125
123
- const accountManager = new AccountManager ( user . mock )
126
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
124
127
125
- await user . set ( { addr : "0x1" } as CurrentUser )
128
+ await userMock . set ( { addr : "0x1" } as CurrentUser )
126
129
expect ( await accountManager . getCOAAddress ( ) ) . toBe ( "0x123" )
127
130
128
- await user . set ( { addr : "0x2" } as CurrentUser )
131
+ await userMock . set ( { addr : "0x2" } as CurrentUser )
129
132
130
133
await new Promise ( setImmediate )
131
134
expect ( await accountManager . getCOAAddress ( ) ) . toBe ( "0x456" )
@@ -134,14 +137,12 @@ describe("AccountManager", () => {
134
137
it ( "should call the callback with updated accounts in subscribe" , async ( ) => {
135
138
mockQuery . mockResolvedValue ( "0x123" )
136
139
137
- const user = mockUser ( )
138
-
139
- const accountManager = new AccountManager ( user . mock )
140
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
140
141
141
142
const callback = jest . fn ( )
142
143
accountManager . subscribe ( callback )
143
144
144
- user . set ( { addr : "0x1" } as CurrentUser )
145
+ userMock . set ( { addr : "0x1" } as CurrentUser )
145
146
146
147
await new Promise ( setImmediate )
147
148
@@ -150,11 +151,10 @@ describe("AccountManager", () => {
150
151
151
152
it ( "should reset accounts in subscribe if user is not authenticated" , async ( ) => {
152
153
mockQuery . mockResolvedValue ( "0x123" )
153
- const user = mockUser ( )
154
154
155
155
const callback = jest . fn ( )
156
156
157
- const accountManager = new AccountManager ( user . mock )
157
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
158
158
159
159
accountManager . subscribe ( callback )
160
160
@@ -166,11 +166,11 @@ describe("AccountManager", () => {
166
166
it ( "should call the callback when COA address is updated" , async ( ) => {
167
167
const callback = jest . fn ( )
168
168
169
- const user = mockUser ( { addr : "0x1" } as CurrentUser )
170
-
171
169
mockQuery . mockResolvedValueOnce ( "0x123" )
172
170
173
- const accountManager = new AccountManager ( user . mock )
171
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
172
+
173
+ userMock . set ( { addr : "0x1" } as CurrentUser )
174
174
175
175
accountManager . subscribe ( callback )
176
176
@@ -180,23 +180,31 @@ describe("AccountManager", () => {
180
180
} )
181
181
182
182
it ( "should return an empty array when COA address is null" , async ( ) => {
183
- const { mock : user } = mockUser ( )
184
- const accountManager = new AccountManager ( user )
183
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
185
184
expect ( await accountManager . getAccounts ( ) ) . toEqual ( [ ] )
186
185
} )
187
186
188
187
it ( "should return COA address array when available" , async ( ) => {
189
188
mockQuery . mockResolvedValueOnce ( "0x123" )
190
- const { mock : user } = mockUser ( { addr : "0x1" } as CurrentUser )
189
+ userMock . set ( { addr : "0x1" } as CurrentUser )
191
190
192
- const accountManager = new AccountManager ( user )
191
+ const accountManager = new AccountManager ( userMock . mock , networkManager )
193
192
194
193
expect ( await accountManager . getAccounts ( ) ) . toEqual ( [ "0x123" ] )
195
194
} )
196
195
} )
197
196
198
197
describe ( "send transaction" , ( ) => {
198
+ let networkManager : jest . Mocked < NetworkManager >
199
+ let $mockChainId : BehaviorSubject < number | null >
200
+
199
201
beforeEach ( ( ) => {
202
+ $mockChainId = new BehaviorSubject < number | null > ( 747 )
203
+ networkManager = {
204
+ $chainId : $mockChainId ,
205
+ getChainId : ( ) => $mockChainId . getValue ( ) ,
206
+ } as any as jest . Mocked < NetworkManager >
207
+
200
208
jest . clearAllMocks ( )
201
209
} )
202
210
@@ -219,7 +227,7 @@ describe("send transaction", () => {
219
227
jest . mocked ( fcl . query ) . mockResolvedValue ( "0x1234" )
220
228
221
229
const user = mockUser ( { addr : "0x4444" } as CurrentUser ) . mock
222
- const accountManager = new AccountManager ( user )
230
+ const accountManager = new AccountManager ( user , networkManager )
223
231
224
232
const tx = {
225
233
to : "0x1234" ,
@@ -248,6 +256,9 @@ describe("send transaction", () => {
248
256
} )
249
257
250
258
test ( "send transaction testnet" , async ( ) => {
259
+ // Set chainId to testnet
260
+ $mockChainId . next ( 646 )
261
+
251
262
const mockTxResult = {
252
263
onceExecuted : jest . fn ( ) . mockResolvedValue ( {
253
264
events : [
@@ -266,7 +277,7 @@ describe("send transaction", () => {
266
277
jest . mocked ( fcl . query ) . mockResolvedValue ( "0x1234" )
267
278
268
279
const user = mockUser ( { addr : "0x4444" } as CurrentUser )
269
- const accountManager = new AccountManager ( user . mock )
280
+ const accountManager = new AccountManager ( user . mock , networkManager )
270
281
271
282
const tx = {
272
283
to : "0x1234" ,
@@ -306,7 +317,7 @@ describe("send transaction", () => {
306
317
jest . mocked ( fcl . query ) . mockResolvedValue ( "0x1234" )
307
318
308
319
const user = mockUser ( { addr : "0x4444" } as CurrentUser )
309
- const accountManager = new AccountManager ( user . mock )
320
+ const accountManager = new AccountManager ( user . mock , networkManager )
310
321
311
322
const tx = {
312
323
to : "0x1234" ,
@@ -315,7 +326,7 @@ describe("send transaction", () => {
315
326
data : "0x1234" ,
316
327
nonce : "0" ,
317
328
gas : "0" ,
318
- chainId : "646 " ,
329
+ chainId : "747 " ,
319
330
}
320
331
321
332
await expect ( accountManager . sendTransaction ( tx ) ) . rejects . toThrow (
@@ -326,7 +337,7 @@ describe("send transaction", () => {
326
337
test ( "throws error if from address does not match user address" , async ( ) => {
327
338
jest . mocked ( fcl . query ) . mockResolvedValue ( "0x1234" )
328
339
const user = mockUser ( { addr : "0x4444" } as CurrentUser )
329
- const accountManager = new AccountManager ( user . mock )
340
+ const accountManager = new AccountManager ( user . mock , networkManager )
330
341
331
342
const tx = {
332
343
to : "0x1234" ,
@@ -339,14 +350,15 @@ describe("send transaction", () => {
339
350
}
340
351
341
352
await expect ( accountManager . sendTransaction ( tx ) ) . rejects . toThrow (
342
- `From address does not match authenticated user address.\nUser: 0x1234\nFrom: 0x4567 `
353
+ `Chain ID does not match the current network. Expected: 747, Received: 646 `
343
354
)
344
355
345
356
expect ( fcl . mutate ) . not . toHaveBeenCalled ( )
346
357
} )
347
358
} )
348
359
349
360
describe ( "signMessage" , ( ) => {
361
+ let networkManager : jest . Mocked < NetworkManager >
350
362
let accountManager : AccountManager
351
363
let user : ReturnType < typeof mockUser > [ "mock" ]
352
364
let updateUser : ReturnType < typeof mockUser > [ "set" ]
@@ -355,7 +367,12 @@ describe("signMessage", () => {
355
367
jest . clearAllMocks ( )
356
368
; ( { mock : user , set : updateUser } = mockUser ( { addr : "0x123" } as CurrentUser ) )
357
369
jest . mocked ( fcl . query ) . mockResolvedValue ( "0xCOA1" )
358
- accountManager = new AccountManager ( user )
370
+ const $mockChainId = new BehaviorSubject < number | null > ( 747 )
371
+ networkManager = {
372
+ $chainId : $mockChainId ,
373
+ getChainId : ( ) => $mockChainId . getValue ( ) ,
374
+ } as any as jest . Mocked < NetworkManager >
375
+ accountManager = new AccountManager ( user , networkManager )
359
376
} )
360
377
361
378
it ( "should throw an error if the COA address is not available" , async ( ) => {
@@ -400,10 +417,7 @@ describe("signMessage", () => {
400
417
} )
401
418
402
419
it ( "should throw an error if signUserMessage returns an empty array" , async ( ) => {
403
- accountManager [ "coaAddress" ] = "0xCOA1"
404
-
405
- user . signUserMessage = jest . fn ( ) . mockResolvedValue ( [ ] )
406
-
420
+ user . signUserMessage . mockResolvedValue ( [ ] )
407
421
await expect (
408
422
accountManager . signMessage ( "Test message" , "0xCOA1" )
409
423
) . rejects . toThrow ( "Failed to sign message" )
0 commit comments