1
1
import { beforeEach , describe , expect , it , vi } from "vitest" ;
2
+ import { TEST_CLIENT } from "../../../../../test/src/test-clients.js" ;
3
+ import { TEST_ACCOUNT_A } from "../../../../../test/src/test-wallets.js" ;
2
4
import { baseSepolia } from "../../../../chains/chain-definitions/base-sepolia.js" ;
3
- import { createThirdwebClient } from "../../../../client/client.js" ;
4
5
import { getEcosystemInfo } from "../../../ecosystem/get-ecosystem-wallet-auth-options.js" ;
5
- import type { Account } from "../../../interfaces/wallet.js" ;
6
+ import { predictSmartAccountAddress } from "../../../smart/lib/calls.js" ;
7
+ import { DEFAULT_ACCOUNT_FACTORY_V0_6 } from "../../../smart/lib/constants.js" ;
8
+ import type { AuthLoginReturnType } from "../authentication/types.js" ;
6
9
import type { InAppConnector } from "../interfaces/connector.js" ;
7
10
import { createInAppWallet } from "./in-app-core.js" ;
8
- import { autoConnectInAppWallet , connectInAppWallet } from "./index.js" ;
11
+ import * as InAppWallet from "./index.js" ;
9
12
10
13
vi . mock ( "../../../../analytics/track/connect.js" , ( ) => ( {
11
14
trackConnect : vi . fn ( ) ,
12
15
} ) ) ;
13
16
14
- vi . mock ( "./index.js" , ( ) => ( {
15
- autoConnectInAppWallet : vi . fn ( ) ,
16
- connectInAppWallet : vi . fn ( ) ,
17
- } ) ) ;
18
-
17
+ vi . spyOn ( InAppWallet , "connectInAppWallet" ) ;
18
+ vi . spyOn ( InAppWallet , "autoConnectInAppWallet" ) ;
19
19
vi . mock ( "../../../ecosystem/get-ecosystem-wallet-auth-options.js" , ( ) => ( {
20
20
getEcosystemInfo : vi . fn ( ) ,
21
21
} ) ) ;
22
22
23
- describe ( "createInAppWallet" , ( ) => {
24
- const mockClient = createThirdwebClient ( {
25
- clientId : "test-client" ,
26
- } ) ;
23
+ describe . runIf ( process . env . TW_SECRET_KEY ) ( "createInAppWallet" , ( ) => {
24
+ const mockClient = TEST_CLIENT ;
27
25
const mockChain = baseSepolia ;
28
- const mockAccount = { address : "0x123" } as Account ;
26
+ const mockAccount = TEST_ACCOUNT_A ;
27
+ const mockUser = {
28
+ status : "Logged In, Wallet Initialized" ,
29
+ walletAddress : TEST_ACCOUNT_A . address ,
30
+ authDetails : {
31
+ userWalletId : TEST_ACCOUNT_A . address ,
32
+ recoveryShareManagement : "ENCLAVE" ,
33
+ email : "test@test.com" ,
34
+ } ,
35
+ account : mockAccount ,
36
+ } as const ;
37
+ const mockAuthResult : AuthLoginReturnType = {
38
+ user : mockUser ,
39
+ } ;
29
40
30
41
const mockConnectorFactory = vi . fn ( ( ) =>
31
42
Promise . resolve ( {
32
- connect : vi . fn ( ) ,
43
+ connect : vi . fn ( ) . mockResolvedValue ( mockAuthResult ) ,
33
44
logout : vi . fn ( ( ) => Promise . resolve ( { success : true } ) ) ,
34
45
authenticate : vi . fn ( ) ,
35
46
getAccounts : vi . fn ( ) ,
36
47
getAccount : vi . fn ( ) ,
37
48
getProfiles : vi . fn ( ) ,
38
- getUser : vi . fn ( ) ,
49
+ getUser : vi . fn ( ) . mockResolvedValue ( mockUser ) ,
39
50
linkProfile : vi . fn ( ) ,
51
+ unlinkProfile : vi . fn ( ) ,
40
52
preAuthenticate : vi . fn ( ) ,
41
53
} as InAppConnector ) ,
42
54
) ;
@@ -46,8 +58,6 @@ describe("createInAppWallet", () => {
46
58
} ) ;
47
59
48
60
it ( "should connect successfully" , async ( ) => {
49
- vi . mocked ( connectInAppWallet ) . mockResolvedValue ( [ mockAccount , mockChain ] ) ;
50
-
51
61
const wallet = createInAppWallet ( {
52
62
connectorFactory : mockConnectorFactory ,
53
63
} ) ;
@@ -61,7 +71,7 @@ describe("createInAppWallet", () => {
61
71
} ) ;
62
72
63
73
expect ( result ) . toBe ( mockAccount ) ;
64
- expect ( connectInAppWallet ) . toHaveBeenCalledWith (
74
+ expect ( InAppWallet . connectInAppWallet ) . toHaveBeenCalledWith (
65
75
expect . objectContaining ( {
66
76
client : mockClient ,
67
77
chain : mockChain ,
@@ -72,11 +82,6 @@ describe("createInAppWallet", () => {
72
82
} ) ;
73
83
74
84
it ( "should auto connect successfully" , async ( ) => {
75
- vi . mocked ( autoConnectInAppWallet ) . mockResolvedValue ( [
76
- mockAccount ,
77
- mockChain ,
78
- ] ) ;
79
-
80
85
const wallet = createInAppWallet ( {
81
86
connectorFactory : mockConnectorFactory ,
82
87
} ) ;
@@ -87,7 +92,7 @@ describe("createInAppWallet", () => {
87
92
} ) ;
88
93
89
94
expect ( result ) . toBe ( mockAccount ) ;
90
- expect ( autoConnectInAppWallet ) . toHaveBeenCalledWith (
95
+ expect ( InAppWallet . autoConnectInAppWallet ) . toHaveBeenCalledWith (
91
96
expect . objectContaining ( {
92
97
client : mockClient ,
93
98
chain : mockChain ,
@@ -102,15 +107,13 @@ describe("createInAppWallet", () => {
102
107
smartAccountOptions : {
103
108
defaultChainId : mockChain . id ,
104
109
sponsorGas : true ,
105
- accountFactoryAddress : "0x456" ,
110
+ accountFactoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
106
111
} ,
107
112
authOptions : [ ] ,
108
113
name : "hello world" ,
109
114
slug : "test-ecosystem" ,
110
115
} ) ;
111
116
112
- vi . mocked ( connectInAppWallet ) . mockResolvedValue ( [ mockAccount , mockChain ] ) ;
113
-
114
117
const wallet = createInAppWallet ( {
115
118
connectorFactory : mockConnectorFactory ,
116
119
ecosystem : { id : "ecosystem.test-ecosystem" } ,
@@ -124,8 +127,14 @@ describe("createInAppWallet", () => {
124
127
verificationCode : "" ,
125
128
} ) ;
126
129
127
- expect ( result ) . toBe ( mockAccount ) ;
128
- expect ( connectInAppWallet ) . toHaveBeenCalledWith (
130
+ const expectedSmartAccountAddress = await predictSmartAccountAddress ( {
131
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
132
+ chain : mockChain ,
133
+ adminAddress : TEST_ACCOUNT_A . address ,
134
+ client : mockClient ,
135
+ } ) ;
136
+ expect ( result . address ) . toBe ( expectedSmartAccountAddress ) ;
137
+ expect ( InAppWallet . connectInAppWallet ) . toHaveBeenCalledWith (
129
138
expect . objectContaining ( {
130
139
client : mockClient ,
131
140
chain : mockChain ,
@@ -134,7 +143,7 @@ describe("createInAppWallet", () => {
134
143
smartAccount : expect . objectContaining ( {
135
144
chain : mockChain ,
136
145
sponsorGas : true ,
137
- factoryAddress : "0x456" ,
146
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
138
147
} ) ,
139
148
} ) ,
140
149
expect . any ( Object ) ,
@@ -145,15 +154,13 @@ describe("createInAppWallet", () => {
145
154
smartAccountOptions : {
146
155
defaultChainId : mockChain . id ,
147
156
sponsorGas : true ,
148
- accountFactoryAddress : "0x456" ,
157
+ accountFactoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
149
158
} ,
150
159
authOptions : [ ] ,
151
160
name : "hello world" ,
152
161
slug : "test-ecosystem" ,
153
162
} ) ;
154
163
155
- vi . mocked ( connectInAppWallet ) . mockResolvedValue ( [ mockAccount , mockChain ] ) ;
156
-
157
164
const wallet = createInAppWallet ( {
158
165
connectorFactory : mockConnectorFactory ,
159
166
ecosystem : { id : "ecosystem.test-ecosystem" } ,
@@ -166,16 +173,22 @@ describe("createInAppWallet", () => {
166
173
verificationCode : "" ,
167
174
} ) ;
168
175
169
- expect ( result ) . toBe ( mockAccount ) ;
170
- expect ( connectInAppWallet ) . toHaveBeenCalledWith (
176
+ const expectedSmartAccountAddress = await predictSmartAccountAddress ( {
177
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
178
+ chain : mockChain ,
179
+ adminAddress : TEST_ACCOUNT_A . address ,
180
+ client : mockClient ,
181
+ } ) ;
182
+ expect ( result . address ) . toBe ( expectedSmartAccountAddress ) ;
183
+ expect ( InAppWallet . connectInAppWallet ) . toHaveBeenCalledWith (
171
184
expect . objectContaining ( {
172
185
client : mockClient ,
173
186
} ) ,
174
187
expect . objectContaining ( {
175
188
smartAccount : expect . objectContaining ( {
176
189
chain : mockChain ,
177
190
sponsorGas : true ,
178
- factoryAddress : "0x456" ,
191
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
179
192
} ) ,
180
193
} ) ,
181
194
expect . any ( Object ) ,
@@ -187,18 +200,13 @@ describe("createInAppWallet", () => {
187
200
smartAccountOptions : {
188
201
defaultChainId : mockChain . id ,
189
202
sponsorGas : true ,
190
- accountFactoryAddress : "0x456" ,
203
+ accountFactoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
191
204
} ,
192
205
authOptions : [ ] ,
193
206
name : "hello world" ,
194
207
slug : "test-ecosystem" ,
195
208
} ) ;
196
209
197
- vi . mocked ( autoConnectInAppWallet ) . mockResolvedValue ( [
198
- mockAccount ,
199
- mockChain ,
200
- ] ) ;
201
-
202
210
const wallet = createInAppWallet ( {
203
211
connectorFactory : mockConnectorFactory ,
204
212
ecosystem : { id : "ecosystem.test-ecosystem" } ,
@@ -209,8 +217,14 @@ describe("createInAppWallet", () => {
209
217
chain : mockChain ,
210
218
} ) ;
211
219
212
- expect ( result ) . toBe ( mockAccount ) ;
213
- expect ( autoConnectInAppWallet ) . toHaveBeenCalledWith (
220
+ const expectedSmartAccountAddress = await predictSmartAccountAddress ( {
221
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
222
+ chain : mockChain ,
223
+ adminAddress : TEST_ACCOUNT_A . address ,
224
+ client : mockClient ,
225
+ } ) ;
226
+ expect ( result . address ) . toBe ( expectedSmartAccountAddress ) ;
227
+ expect ( InAppWallet . autoConnectInAppWallet ) . toHaveBeenCalledWith (
214
228
expect . objectContaining ( {
215
229
client : mockClient ,
216
230
chain : mockChain ,
@@ -219,7 +233,7 @@ describe("createInAppWallet", () => {
219
233
smartAccount : expect . objectContaining ( {
220
234
chain : mockChain ,
221
235
sponsorGas : true ,
222
- factoryAddress : "0x456" ,
236
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
223
237
} ) ,
224
238
} ) ,
225
239
expect . any ( Object ) ,
@@ -231,18 +245,13 @@ describe("createInAppWallet", () => {
231
245
smartAccountOptions : {
232
246
defaultChainId : mockChain . id ,
233
247
sponsorGas : true ,
234
- accountFactoryAddress : "0x456" ,
248
+ accountFactoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
235
249
} ,
236
250
authOptions : [ ] ,
237
251
name : "hello world" ,
238
252
slug : "test-ecosystem" ,
239
253
} ) ;
240
254
241
- vi . mocked ( autoConnectInAppWallet ) . mockResolvedValue ( [
242
- mockAccount ,
243
- mockChain ,
244
- ] ) ;
245
-
246
255
const wallet = createInAppWallet ( {
247
256
connectorFactory : mockConnectorFactory ,
248
257
ecosystem : { id : "ecosystem.test-ecosystem" } ,
@@ -252,19 +261,71 @@ describe("createInAppWallet", () => {
252
261
client : mockClient ,
253
262
} ) ;
254
263
255
- expect ( result ) . toBe ( mockAccount ) ;
256
- expect ( autoConnectInAppWallet ) . toHaveBeenCalledWith (
264
+ const expectedSmartAccountAddress = await predictSmartAccountAddress ( {
265
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
266
+ chain : mockChain ,
267
+ adminAddress : TEST_ACCOUNT_A . address ,
268
+ client : mockClient ,
269
+ } ) ;
270
+ expect ( result . address ) . toBe ( expectedSmartAccountAddress ) ;
271
+ expect ( InAppWallet . autoConnectInAppWallet ) . toHaveBeenCalledWith (
257
272
expect . objectContaining ( {
258
273
client : mockClient ,
259
274
} ) ,
260
275
expect . objectContaining ( {
261
276
smartAccount : expect . objectContaining ( {
262
277
chain : mockChain ,
263
278
sponsorGas : true ,
264
- factoryAddress : "0x456" ,
279
+ factoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
265
280
} ) ,
266
281
} ) ,
267
282
expect . any ( Object ) ,
268
283
) ;
269
284
} ) ;
285
+
286
+ it ( "should return undefined for getAdminAccount if the account is not a smart account" , ( ) => {
287
+ const wallet = createInAppWallet ( {
288
+ connectorFactory : mockConnectorFactory ,
289
+ } ) ;
290
+
291
+ expect ( wallet . getAdminAccount ?.( ) ) . toBeUndefined ( ) ;
292
+ } ) ;
293
+
294
+ it ( "should return undefined if no account is connected" , ( ) => {
295
+ const wallet = createInAppWallet ( {
296
+ connectorFactory : mockConnectorFactory ,
297
+ } ) ;
298
+
299
+ expect ( wallet . getAdminAccount ?.( ) ) . toBeUndefined ( ) ;
300
+ } ) ;
301
+
302
+ it ( "should return the admin account for a smart account" , async ( ) => {
303
+ vi . unmock ( "./index.js" ) ;
304
+ vi . mocked ( getEcosystemInfo ) . mockResolvedValue ( {
305
+ smartAccountOptions : {
306
+ defaultChainId : mockChain . id ,
307
+ sponsorGas : true ,
308
+ accountFactoryAddress : DEFAULT_ACCOUNT_FACTORY_V0_6 ,
309
+ } ,
310
+ authOptions : [ ] ,
311
+ name : "hello world" ,
312
+ slug : "test-ecosystem" ,
313
+ } ) ;
314
+
315
+ const wallet = createInAppWallet ( {
316
+ connectorFactory : mockConnectorFactory ,
317
+ ecosystem : { id : "ecosystem.test-ecosystem" } ,
318
+ } ) ;
319
+
320
+ const smartAccount = await wallet . connect ( {
321
+ client : mockClient ,
322
+ strategy : "email" ,
323
+ email : "" ,
324
+ verificationCode : "" ,
325
+ } ) ;
326
+
327
+ const adminAccount = wallet . getAdminAccount ?.( ) ;
328
+ expect ( adminAccount ) . toBeDefined ( ) ;
329
+ expect ( adminAccount ?. address ) . not . toBe ( smartAccount . address ) ;
330
+ } ) ;
270
331
} ) ;
0 commit comments