@tomo-inc/wallet-adaptor-base 0.0.19 → 0.0.21
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.
- package/dist/index.cjs +18 -22
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +18 -22
- package/package.json +7 -2
- package/project.json +1 -1
- package/src/__tests__/WalletConnectProvider.test.ts +535 -0
- package/src/__tests__/WalletConnectSolanaProvider.test.ts +537 -0
- package/src/__tests__/browsers.test.ts +263 -0
- package/src/__tests__/chainId.test.ts +66 -0
- package/src/__tests__/chains-utils.test.ts +49 -0
- package/src/__tests__/defaultConnectors.test.ts +8 -5
- package/src/__tests__/detector.test.ts +402 -0
- package/src/__tests__/index.test.ts +275 -0
- package/src/__tests__/isMobile.test.ts +187 -0
- package/src/__tests__/log.test.ts +40 -0
- package/src/__tests__/utils.test.ts +66 -0
- package/src/__tests__/wallet-api.test.ts +1755 -0
- package/src/__tests__/wallet-config.test.ts +75 -0
- package/src/__tests__/wallet-eip6963.test.ts +377 -0
- package/src/__tests__/wallet-standard.test.ts +41 -3
- package/src/__tests__/wallet-walletconnect.test.ts +370 -0
- package/src/__tests__/wallets/index.test.ts +42 -0
- package/src/type.ts +4 -0
- package/src/utils/chainId.ts +6 -5
- package/src/utils/wallet-config.ts +2 -9
- package/src/wallet-api/connect.ts +4 -2
- package/src/wallets/detector.ts +3 -4
- package/src/wallets/providers/WalletConnectProvider.ts +5 -4
- package/src/wallets/providers/WalletConnectSolanaProvider.ts +1 -1
- package/src/wallets/wallet-eip6963.ts +1 -1
- package/vitest.config.ts +20 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { WalletConnectProvider } from "../wallets/providers/WalletConnectProvider";
|
|
3
|
+
import { WalletConnectClient } from "@tomo-inc/wallet-connect-protocol";
|
|
4
|
+
|
|
5
|
+
// Mock WalletConnectClient - use vi.hoisted to create mock instance and constructor
|
|
6
|
+
const { mockClient, MockWalletConnectClient } = vi.hoisted(() => {
|
|
7
|
+
const createMockClient = () => ({
|
|
8
|
+
initialize: vi.fn().mockResolvedValue(undefined),
|
|
9
|
+
connect: vi.fn().mockResolvedValue("wc:test-uri"),
|
|
10
|
+
disconnectSession: vi.fn().mockResolvedValue(undefined),
|
|
11
|
+
getActiveSessions: vi.fn().mockReturnValue([]),
|
|
12
|
+
sendRequest: vi.fn().mockResolvedValue("result"),
|
|
13
|
+
on: vi.fn(),
|
|
14
|
+
off: vi.fn(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const mockClientInstance = createMockClient();
|
|
18
|
+
|
|
19
|
+
// Create a proper constructor function
|
|
20
|
+
function MockWalletConnectClientConstructor() {
|
|
21
|
+
return mockClientInstance;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Wrap with vi.fn() to make it spyable
|
|
25
|
+
const MockClient = vi.fn(MockWalletConnectClientConstructor);
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
mockClient: mockClientInstance,
|
|
29
|
+
MockWalletConnectClient: MockClient,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
vi.mock("@tomo-inc/wallet-connect-protocol", () => ({
|
|
34
|
+
WalletConnectClient: MockWalletConnectClient,
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
describe("WalletConnectProvider", () => {
|
|
38
|
+
let provider: WalletConnectProvider;
|
|
39
|
+
const config = {
|
|
40
|
+
projectId: "test-project-id",
|
|
41
|
+
metadata: {
|
|
42
|
+
name: "Test App",
|
|
43
|
+
description: "Test Description",
|
|
44
|
+
url: "https://test.com",
|
|
45
|
+
icons: ["https://test.com/icon.png"],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
vi.clearAllMocks();
|
|
51
|
+
provider = new WalletConnectProvider(config);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
vi.restoreAllMocks();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("constructor and client listeners", () => {
|
|
59
|
+
it("should create provider with default namespaces", () => {
|
|
60
|
+
expect(WalletConnectClient).toHaveBeenCalledWith({
|
|
61
|
+
projectId: config.projectId,
|
|
62
|
+
metadata: config.metadata,
|
|
63
|
+
});
|
|
64
|
+
expect(mockClient.on).toHaveBeenCalledWith("session_proposal", expect.any(Function));
|
|
65
|
+
expect(mockClient.on).toHaveBeenCalledWith("session_delete", expect.any(Function));
|
|
66
|
+
expect(mockClient.on).toHaveBeenCalledWith("session_update", expect.any(Function));
|
|
67
|
+
expect(mockClient.on).toHaveBeenCalledWith("display_uri", expect.any(Function));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should handle session_proposal and update session when getActiveSessions returns sessions", () => {
|
|
71
|
+
const mockSession = {
|
|
72
|
+
topic: "proposal-topic",
|
|
73
|
+
namespaces: {
|
|
74
|
+
eip155: { accounts: ["eip155:1:0xabc"] },
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
mockClient.getActiveSessions.mockReturnValue([mockSession]);
|
|
78
|
+
const sessionProposalHandler = (mockClient.on as any).mock.calls.find((c: any[]) => c[0] === "session_proposal")?.[1];
|
|
79
|
+
expect(sessionProposalHandler).toBeDefined();
|
|
80
|
+
const emitSpy = vi.spyOn(provider as any, "emit");
|
|
81
|
+
sessionProposalHandler();
|
|
82
|
+
expect(provider["session"]).toEqual(mockSession);
|
|
83
|
+
expect(provider["accounts"]).toEqual(["0xabc"]);
|
|
84
|
+
expect(provider["chainId"]).toBe("0x1");
|
|
85
|
+
expect(emitSpy).toHaveBeenCalledWith("connect", expect.any(Object));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should handle session_delete and clear session", () => {
|
|
89
|
+
provider["session"] = { topic: "t", namespaces: {} } as any;
|
|
90
|
+
provider["accounts"] = ["0x123"];
|
|
91
|
+
const sessionDeleteHandler = (mockClient.on as any).mock.calls.find((c: any[]) => c[0] === "session_delete")?.[1];
|
|
92
|
+
sessionDeleteHandler();
|
|
93
|
+
expect(provider["session"]).toBeNull();
|
|
94
|
+
expect(provider["accounts"]).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should handle session_update and emit accountsChanged", () => {
|
|
98
|
+
provider["session"] = {
|
|
99
|
+
topic: "t",
|
|
100
|
+
namespaces: { eip155: { accounts: ["eip155:1:0xdef"] } },
|
|
101
|
+
} as any;
|
|
102
|
+
const sessionUpdateHandler = (mockClient.on as any).mock.calls.find((c: any[]) => c[0] === "session_update")?.[1];
|
|
103
|
+
provider["updateAccountsFromSession"] = vi.fn();
|
|
104
|
+
const emitSpy = vi.spyOn(provider as any, "emit");
|
|
105
|
+
sessionUpdateHandler();
|
|
106
|
+
expect(provider["updateAccountsFromSession"]).toHaveBeenCalled();
|
|
107
|
+
expect(emitSpy).toHaveBeenCalledWith("accountsChanged", expect.any(Array));
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("should handle display_uri and set uri", () => {
|
|
111
|
+
const displayUriHandler = (mockClient.on as any).mock.calls.find((c: any[]) => c[0] === "display_uri")?.[1];
|
|
112
|
+
displayUriHandler({ uri: "wc://new-uri" });
|
|
113
|
+
expect(provider.uri).toBe("wc://new-uri");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("should use custom namespaces when provided", () => {
|
|
117
|
+
const customNamespaces = {
|
|
118
|
+
eip155: {
|
|
119
|
+
chains: ["eip155:5"],
|
|
120
|
+
methods: ["eth_chainId"],
|
|
121
|
+
events: [],
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const customProvider = new WalletConnectProvider({
|
|
126
|
+
...config,
|
|
127
|
+
namespaces: customNamespaces,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(customProvider).toBeDefined();
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe("initialize", () => {
|
|
135
|
+
it("should initialize client and get URI when no active sessions", async () => {
|
|
136
|
+
mockClient.getActiveSessions.mockReturnValue([]);
|
|
137
|
+
mockClient.connect.mockResolvedValue("wc:new-uri");
|
|
138
|
+
|
|
139
|
+
await provider.initialize();
|
|
140
|
+
|
|
141
|
+
expect(mockClient.initialize).toHaveBeenCalled();
|
|
142
|
+
expect(mockClient.connect).toHaveBeenCalledWith({
|
|
143
|
+
requiredNamespaces: expect.any(Object),
|
|
144
|
+
});
|
|
145
|
+
expect(provider.uri).toBe("wc:new-uri");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should not create new URI when active sessions exist", async () => {
|
|
149
|
+
const mockSession = {
|
|
150
|
+
topic: "test-topic",
|
|
151
|
+
namespaces: {},
|
|
152
|
+
};
|
|
153
|
+
mockClient.getActiveSessions.mockReturnValue([mockSession]);
|
|
154
|
+
|
|
155
|
+
await provider.initialize();
|
|
156
|
+
|
|
157
|
+
expect(mockClient.initialize).toHaveBeenCalled();
|
|
158
|
+
expect(mockClient.connect).not.toHaveBeenCalled();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe("getUri", () => {
|
|
163
|
+
it("should return existing URI if available", async () => {
|
|
164
|
+
provider.uri = "wc:existing-uri";
|
|
165
|
+
const uri = await provider.getUri();
|
|
166
|
+
|
|
167
|
+
expect(uri).toBe("wc:existing-uri");
|
|
168
|
+
expect(mockClient.connect).not.toHaveBeenCalled();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("should create new URI if not available", async () => {
|
|
172
|
+
mockClient.connect.mockResolvedValue("wc:new-uri");
|
|
173
|
+
const uri = await provider.getUri();
|
|
174
|
+
|
|
175
|
+
expect(uri).toBe("wc:new-uri");
|
|
176
|
+
expect(mockClient.connect).toHaveBeenCalled();
|
|
177
|
+
expect(provider.uri).toBe("wc:new-uri");
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe("connect", () => {
|
|
182
|
+
it("should connect and wait for session", async () => {
|
|
183
|
+
vi.useFakeTimers();
|
|
184
|
+
mockClient.connect.mockResolvedValue("wc:test-uri");
|
|
185
|
+
mockClient.getActiveSessions.mockReturnValueOnce([]).mockReturnValueOnce([
|
|
186
|
+
{
|
|
187
|
+
topic: "test-topic",
|
|
188
|
+
namespaces: {
|
|
189
|
+
eip155: {
|
|
190
|
+
accounts: ["eip155:1:0x123"],
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
]);
|
|
195
|
+
|
|
196
|
+
const connectPromise = provider.connect();
|
|
197
|
+
// Simulate session establishment
|
|
198
|
+
setTimeout(() => {
|
|
199
|
+
const sessions = mockClient.getActiveSessions();
|
|
200
|
+
if (sessions.length > 0) {
|
|
201
|
+
// Trigger session_proposal handler
|
|
202
|
+
const handlers = (mockClient.on as any).mock.calls.filter((call: any[]) => call[0] === "session_proposal");
|
|
203
|
+
if (handlers.length > 0) {
|
|
204
|
+
handlers[0][1]();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}, 100);
|
|
208
|
+
|
|
209
|
+
vi.advanceTimersByTime(200);
|
|
210
|
+
const result = await connectPromise;
|
|
211
|
+
|
|
212
|
+
expect(result).toBeDefined();
|
|
213
|
+
vi.useRealTimers();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should emit error and return undefined when waitForConnection fails", async () => {
|
|
217
|
+
vi.useFakeTimers();
|
|
218
|
+
mockClient.getActiveSessions.mockReturnValue([]);
|
|
219
|
+
mockClient.connect.mockResolvedValue("wc:uri");
|
|
220
|
+
const connectPromise = provider.connect();
|
|
221
|
+
// Timeout is 300000ms; advance to trigger rejection
|
|
222
|
+
await vi.advanceTimersByTimeAsync(300001);
|
|
223
|
+
const result = await connectPromise;
|
|
224
|
+
expect(result).toBeUndefined();
|
|
225
|
+
vi.useRealTimers();
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe("disconnect", () => {
|
|
230
|
+
it("should disconnect session", async () => {
|
|
231
|
+
provider["session"] = {
|
|
232
|
+
topic: "test-topic",
|
|
233
|
+
namespaces: {},
|
|
234
|
+
} as any;
|
|
235
|
+
|
|
236
|
+
await provider.disconnect();
|
|
237
|
+
|
|
238
|
+
expect(mockClient.disconnectSession).toHaveBeenCalledWith("test-topic");
|
|
239
|
+
expect(provider["session"]).toBeNull();
|
|
240
|
+
expect(provider["accounts"]).toEqual([]);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("should handle disconnect when not connected", async () => {
|
|
244
|
+
provider["session"] = null;
|
|
245
|
+
|
|
246
|
+
await provider.disconnect();
|
|
247
|
+
|
|
248
|
+
expect(mockClient.disconnectSession).not.toHaveBeenCalled();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe("request", () => {
|
|
253
|
+
it("should handle eth_requestAccounts when connected", async () => {
|
|
254
|
+
provider["session"] = {
|
|
255
|
+
topic: "test-topic",
|
|
256
|
+
namespaces: {},
|
|
257
|
+
} as any;
|
|
258
|
+
provider["accounts"] = ["0x123"];
|
|
259
|
+
|
|
260
|
+
const result = await provider.request({ method: "eth_requestAccounts" });
|
|
261
|
+
|
|
262
|
+
expect(result).toEqual(["0x123"]);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it("should handle eth_requestAccounts when not connected", async () => {
|
|
266
|
+
provider["session"] = null;
|
|
267
|
+
mockClient.connect.mockResolvedValue("wc:test-uri");
|
|
268
|
+
mockClient.getActiveSessions.mockReturnValue([]);
|
|
269
|
+
|
|
270
|
+
const resultPromise = provider.request({ method: "eth_requestAccounts" });
|
|
271
|
+
|
|
272
|
+
// Should trigger connect
|
|
273
|
+
expect(mockClient.connect).toHaveBeenCalled();
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it("should handle eth_chainId", async () => {
|
|
277
|
+
provider["chainId"] = "0x5";
|
|
278
|
+
const result = await provider.request({ method: "eth_chainId" });
|
|
279
|
+
|
|
280
|
+
expect(result).toBe("0x5");
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("should send request to client", async () => {
|
|
284
|
+
provider["session"] = {
|
|
285
|
+
topic: "test-topic",
|
|
286
|
+
namespaces: {},
|
|
287
|
+
} as any;
|
|
288
|
+
provider["chainId"] = "0x1";
|
|
289
|
+
|
|
290
|
+
await provider.request({
|
|
291
|
+
method: "eth_getBalance",
|
|
292
|
+
params: ["0x123", "latest"],
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
expect(mockClient.sendRequest).toHaveBeenCalledWith({
|
|
296
|
+
topic: "test-topic",
|
|
297
|
+
chainId: "eip155:1",
|
|
298
|
+
request: {
|
|
299
|
+
method: "eth_getBalance",
|
|
300
|
+
params: ["0x123", "latest"],
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("should throw error when not connected", async () => {
|
|
306
|
+
provider["session"] = null;
|
|
307
|
+
|
|
308
|
+
await expect(
|
|
309
|
+
provider.request({
|
|
310
|
+
method: "eth_getBalance",
|
|
311
|
+
params: [],
|
|
312
|
+
}),
|
|
313
|
+
).rejects.toThrow("Not connected");
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it("should handle request errors", async () => {
|
|
317
|
+
provider["session"] = {
|
|
318
|
+
topic: "test-topic",
|
|
319
|
+
namespaces: {},
|
|
320
|
+
} as any;
|
|
321
|
+
mockClient.sendRequest.mockRejectedValue(new Error("Request failed"));
|
|
322
|
+
|
|
323
|
+
await expect(
|
|
324
|
+
provider.request({
|
|
325
|
+
method: "eth_getBalance",
|
|
326
|
+
params: [],
|
|
327
|
+
}),
|
|
328
|
+
).rejects.toThrow("Request failed");
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
describe("getAccounts", () => {
|
|
333
|
+
it("should return accounts when connected", async () => {
|
|
334
|
+
provider["session"] = {
|
|
335
|
+
topic: "test-topic",
|
|
336
|
+
namespaces: {},
|
|
337
|
+
} as any;
|
|
338
|
+
provider["accounts"] = ["0x123", "0x456"];
|
|
339
|
+
|
|
340
|
+
const accounts = await provider.getAccounts();
|
|
341
|
+
|
|
342
|
+
expect(accounts).toEqual(["0x123", "0x456"]);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("should return empty array when not connected", async () => {
|
|
346
|
+
provider["session"] = null;
|
|
347
|
+
|
|
348
|
+
const accounts = await provider.getAccounts();
|
|
349
|
+
|
|
350
|
+
expect(accounts).toEqual([]);
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe("getChainId", () => {
|
|
355
|
+
it("should return current chain ID", async () => {
|
|
356
|
+
provider["chainId"] = "0x5";
|
|
357
|
+
const chainId = await provider.getChainId();
|
|
358
|
+
|
|
359
|
+
expect(chainId).toBe("0x5");
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe("isConnected", () => {
|
|
364
|
+
it("should return true when connected", () => {
|
|
365
|
+
provider["session"] = {
|
|
366
|
+
topic: "test-topic",
|
|
367
|
+
namespaces: {},
|
|
368
|
+
} as any;
|
|
369
|
+
provider["accounts"] = ["0x123"];
|
|
370
|
+
|
|
371
|
+
expect(provider.isConnected()).toBe(true);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it("should return false when not connected", () => {
|
|
375
|
+
provider["session"] = null;
|
|
376
|
+
expect(provider.isConnected()).toBe(false);
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
it("should return false when no accounts", () => {
|
|
380
|
+
provider["session"] = {
|
|
381
|
+
topic: "test-topic",
|
|
382
|
+
namespaces: {},
|
|
383
|
+
} as any;
|
|
384
|
+
provider["accounts"] = [];
|
|
385
|
+
|
|
386
|
+
expect(provider.isConnected()).toBe(false);
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
describe("getSession", () => {
|
|
391
|
+
it("should return current session", () => {
|
|
392
|
+
const mockSession = {
|
|
393
|
+
topic: "test-topic",
|
|
394
|
+
namespaces: {},
|
|
395
|
+
} as any;
|
|
396
|
+
provider["session"] = mockSession;
|
|
397
|
+
|
|
398
|
+
expect(provider.getSession()).toBe(mockSession);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("should return null when not connected", () => {
|
|
402
|
+
provider["session"] = null;
|
|
403
|
+
|
|
404
|
+
expect(provider.getSession()).toBeNull();
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
describe("event listeners", () => {
|
|
409
|
+
it("should add event listener", () => {
|
|
410
|
+
const listener = vi.fn();
|
|
411
|
+
provider.on("test-event", listener);
|
|
412
|
+
|
|
413
|
+
expect(provider["eventListeners"].has("test-event")).toBe(true);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it("should remove event listener", () => {
|
|
417
|
+
const listener = vi.fn();
|
|
418
|
+
provider.on("test-event", listener);
|
|
419
|
+
provider.off("test-event", listener);
|
|
420
|
+
|
|
421
|
+
expect(provider["eventListeners"].get("test-event")?.has(listener)).toBe(false);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it("should emit events to listeners", () => {
|
|
425
|
+
const listener = vi.fn();
|
|
426
|
+
provider.on("test-event", listener);
|
|
427
|
+
|
|
428
|
+
provider["emit"]("test-event", { data: "test" });
|
|
429
|
+
|
|
430
|
+
expect(listener).toHaveBeenCalledWith({ data: "test" });
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it("should handle listener errors gracefully", () => {
|
|
434
|
+
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
435
|
+
const listener = vi.fn(() => {
|
|
436
|
+
throw new Error("Listener error");
|
|
437
|
+
});
|
|
438
|
+
provider.on("test-event", listener);
|
|
439
|
+
|
|
440
|
+
provider["emit"]("test-event", { data: "test" });
|
|
441
|
+
|
|
442
|
+
expect(consoleErrorSpy).toHaveBeenCalled();
|
|
443
|
+
consoleErrorSpy.mockRestore();
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
describe("helper methods", () => {
|
|
448
|
+
beforeEach(() => {
|
|
449
|
+
provider["session"] = {
|
|
450
|
+
topic: "test-topic",
|
|
451
|
+
namespaces: {},
|
|
452
|
+
} as any;
|
|
453
|
+
provider["accounts"] = ["0x123"];
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it("should sign message", async () => {
|
|
457
|
+
mockClient.sendRequest.mockResolvedValue("0xsignature");
|
|
458
|
+
|
|
459
|
+
const signature = await provider.signMessage("test message");
|
|
460
|
+
|
|
461
|
+
expect(signature).toBe("0xsignature");
|
|
462
|
+
expect(mockClient.sendRequest).toHaveBeenCalledWith({
|
|
463
|
+
topic: "test-topic",
|
|
464
|
+
chainId: "eip155:1",
|
|
465
|
+
request: {
|
|
466
|
+
method: "personal_sign",
|
|
467
|
+
params: ["test message", "0x123"],
|
|
468
|
+
},
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it("should throw when signing message with no account", async () => {
|
|
473
|
+
provider["accounts"] = [];
|
|
474
|
+
|
|
475
|
+
await expect(provider.signMessage("test")).rejects.toThrow("No account connected");
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it("should sign typed data", async () => {
|
|
479
|
+
mockClient.sendRequest.mockResolvedValue("0xsignature");
|
|
480
|
+
const typedData = { types: {}, domain: {}, message: {} };
|
|
481
|
+
|
|
482
|
+
const signature = await provider.signTypedData(typedData);
|
|
483
|
+
|
|
484
|
+
expect(signature).toBe("0xsignature");
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it("should send transaction", async () => {
|
|
488
|
+
mockClient.sendRequest.mockResolvedValue("0xtxhash");
|
|
489
|
+
const transaction = { to: "0x456", value: "0x0" };
|
|
490
|
+
|
|
491
|
+
const txHash = await provider.sendTransaction(transaction);
|
|
492
|
+
|
|
493
|
+
expect(txHash).toBe("0xtxhash");
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
it("should throw error when switching chain", async () => {
|
|
497
|
+
await expect(provider.switchChain("0x5")).rejects.toThrow("Please reconnect to switch chains");
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
describe("updateAccountsFromSession", () => {
|
|
502
|
+
it("should update accounts from session", () => {
|
|
503
|
+
const mockSession = {
|
|
504
|
+
topic: "test-topic",
|
|
505
|
+
namespaces: {
|
|
506
|
+
eip155: {
|
|
507
|
+
accounts: ["eip155:1:0x123", "eip155:1:0x456"],
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
} as any;
|
|
511
|
+
|
|
512
|
+
provider["session"] = mockSession;
|
|
513
|
+
provider["updateAccountsFromSession"]();
|
|
514
|
+
|
|
515
|
+
expect(provider["accounts"]).toEqual(["0x123", "0x456"]);
|
|
516
|
+
expect(provider["chainId"]).toBe("0x1");
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it("should handle empty accounts", () => {
|
|
520
|
+
const mockSession = {
|
|
521
|
+
topic: "test-topic",
|
|
522
|
+
namespaces: {
|
|
523
|
+
eip155: {
|
|
524
|
+
accounts: [],
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
} as any;
|
|
528
|
+
|
|
529
|
+
provider["session"] = mockSession;
|
|
530
|
+
provider["updateAccountsFromSession"]();
|
|
531
|
+
|
|
532
|
+
expect(provider["accounts"]).toEqual([]);
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
});
|