@reown/appkit 1.6.6 → 1.6.7-basic-test.7.0
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/esm/exports/basic.js +12 -0
- package/dist/esm/exports/basic.js.map +1 -0
- package/dist/esm/exports/constants.js +1 -1
- package/dist/esm/exports/constants.js.map +1 -1
- package/dist/esm/exports/index.js +1 -3
- package/dist/esm/exports/index.js.map +1 -1
- package/dist/esm/exports/react.js +1 -3
- package/dist/esm/exports/react.js.map +1 -1
- package/dist/esm/exports/vue.js +1 -3
- package/dist/esm/exports/vue.js.map +1 -1
- package/dist/esm/package.json +7 -2
- package/dist/esm/src/adapters/ChainAdapterBlueprint.js +0 -1
- package/dist/esm/src/adapters/ChainAdapterBlueprint.js.map +1 -1
- package/dist/esm/src/client/appkit-basic.js +29 -0
- package/dist/esm/src/client/appkit-basic.js.map +1 -0
- package/dist/esm/src/client/appkit.js +320 -0
- package/dist/esm/src/client/appkit.js.map +1 -0
- package/dist/esm/src/client/core.js +1334 -0
- package/dist/esm/src/client/core.js.map +1 -0
- package/dist/esm/src/client.js +3 -0
- package/dist/esm/src/client.js.map +1 -1
- package/dist/esm/tests/appkit.test.js +1482 -0
- package/dist/esm/tests/appkit.test.js.map +1 -0
- package/dist/esm/tests/client/adapter-management.test.js +83 -0
- package/dist/esm/tests/client/adapter-management.test.js.map +1 -0
- package/dist/esm/tests/client/appkit-basic.test.js +44 -0
- package/dist/esm/tests/client/appkit-basic.test.js.map +1 -0
- package/dist/esm/tests/client/balance.test.js +67 -0
- package/dist/esm/tests/client/balance.test.js.map +1 -0
- package/dist/esm/tests/client/connection.test.js +52 -0
- package/dist/esm/tests/client/connection.test.js.map +1 -0
- package/dist/esm/tests/client/initialization.test.js +114 -0
- package/dist/esm/tests/client/initialization.test.js.map +1 -0
- package/dist/esm/tests/client/listeners.test.js +35 -0
- package/dist/esm/tests/client/listeners.test.js.map +1 -0
- package/dist/esm/tests/client/public-methods.test.js +700 -0
- package/dist/esm/tests/client/public-methods.test.js.map +1 -0
- package/dist/esm/tests/client/universal-adapter.test.js +44 -0
- package/dist/esm/tests/client/universal-adapter.test.js.map +1 -0
- package/dist/esm/tests/client/walletconnect-events.test.js +80 -0
- package/dist/esm/tests/client/walletconnect-events.test.js.map +1 -0
- package/dist/esm/tests/connectors/WalletConnectConnector.test.js +63 -0
- package/dist/esm/tests/connectors/WalletConnectConnector.test.js.map +1 -0
- package/dist/esm/tests/mocks/Account.js +13 -0
- package/dist/esm/tests/mocks/Account.js.map +1 -0
- package/dist/esm/tests/mocks/Adapter.js +95 -0
- package/dist/esm/tests/mocks/Adapter.js.map +1 -0
- package/dist/esm/tests/mocks/AppKit.js +24 -0
- package/dist/esm/tests/mocks/AppKit.js.map +1 -0
- package/dist/esm/tests/mocks/Networks.js +5 -0
- package/dist/esm/tests/mocks/Networks.js.map +1 -0
- package/dist/esm/tests/mocks/Options.js +17 -0
- package/dist/esm/tests/mocks/Options.js.map +1 -0
- package/dist/esm/tests/mocks/Providers.js +46 -0
- package/dist/esm/tests/mocks/Providers.js.map +1 -0
- package/dist/esm/tests/mocks/UniversalProvider.js +139 -0
- package/dist/esm/tests/mocks/UniversalProvider.js.map +1 -0
- package/dist/esm/tests/siwe.test.js +270 -0
- package/dist/esm/tests/siwe.test.js.map +1 -0
- package/dist/esm/tests/test-utils.js +32 -0
- package/dist/esm/tests/test-utils.js.map +1 -0
- package/dist/esm/tests/universal-adapter.test.js +246 -0
- package/dist/esm/tests/universal-adapter.test.js.map +1 -0
- package/dist/esm/tests/utils/HelpersUtil.test.js +218 -0
- package/dist/esm/tests/utils/HelpersUtil.test.js.map +1 -0
- package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -0
- package/dist/types/exports/basic.d.ts +8 -0
- package/dist/types/exports/constants.d.ts +1 -1
- package/dist/types/exports/index.d.ts +2 -3
- package/dist/types/exports/react.d.ts +2 -3
- package/dist/types/exports/vue.d.ts +2 -3
- package/dist/types/src/adapters/ChainAdapterBlueprint.d.ts +3 -3
- package/dist/types/src/client/appkit-basic.d.ts +23 -0
- package/dist/types/src/client/appkit.d.ts +22 -0
- package/dist/types/src/client/core.d.ts +208 -0
- package/dist/types/src/library/react/index.d.ts +1 -1
- package/dist/types/src/library/vue/index.d.ts +1 -1
- package/dist/types/src/utils/TypesUtil.d.ts +5 -0
- package/dist/types/tests/appkit.test.d.ts +1 -0
- package/dist/types/tests/client/adapter-management.test.d.ts +1 -0
- package/dist/types/tests/client/appkit-basic.test.d.ts +1 -0
- package/dist/types/tests/client/balance.test.d.ts +1 -0
- package/dist/types/tests/client/connection.test.d.ts +1 -0
- package/dist/types/tests/client/initialization.test.d.ts +1 -0
- package/dist/types/tests/client/listeners.test.d.ts +1 -0
- package/dist/types/tests/client/public-methods.test.d.ts +1 -0
- package/dist/types/tests/client/universal-adapter.test.d.ts +1 -0
- package/dist/types/tests/client/walletconnect-events.test.d.ts +1 -0
- package/dist/types/tests/connectors/WalletConnectConnector.test.d.ts +1 -0
- package/dist/types/tests/mocks/Account.d.ts +12 -0
- package/dist/types/tests/mocks/Adapter.d.ts +5 -0
- package/dist/types/tests/mocks/AppKit.d.ts +3 -0
- package/dist/types/tests/mocks/Networks.d.ts +3 -0
- package/dist/types/tests/mocks/Options.d.ts +6 -0
- package/dist/types/tests/mocks/UniversalProvider.d.ts +3 -0
- package/dist/types/tests/siwe.test.d.ts +1 -0
- package/dist/types/tests/test-utils.d.ts +5 -0
- package/dist/types/tests/universal-adapter.test.d.ts +1 -0
- package/dist/types/tests/utils/HelpersUtil.test.d.ts +1 -0
- package/package.json +15 -10
|
@@ -0,0 +1,1482 @@
|
|
|
1
|
+
import UniversalProvider from '@walletconnect/universal-provider';
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { Emitter, NetworkUtil, SafeLocalStorage, SafeLocalStorageKeys, getSafeConnectorIdKey } from '@reown/appkit-common';
|
|
4
|
+
import { AccountController, AlertController, AssetUtil, BlockchainApiController, ChainController, ConnectionController, ConnectorController, ConstantsUtil, CoreHelperUtil, EnsController, EventsController, ModalController, OptionsController, PublicStateController, RouterController, SnackController, StorageUtil, ThemeController } from '@reown/appkit-core';
|
|
5
|
+
import { CaipNetworksUtil, ErrorUtil } from '@reown/appkit-utils';
|
|
6
|
+
import { AppKit } from '../src/client/appkit';
|
|
7
|
+
import { base as baseNetwork, mainnet as mainnetNetwork, polygon as polygonNetwork, sepolia as sepoliaNetwork, solana as solanaNetwork } from '../src/networks/index.js';
|
|
8
|
+
import { ProviderUtil } from '../src/store';
|
|
9
|
+
import { UniversalAdapter } from '../src/universal-adapter/client';
|
|
10
|
+
import mockUniversalAdapter from './mocks/Adapter';
|
|
11
|
+
import { mockOptions } from './mocks/Options';
|
|
12
|
+
import mockProvider from './mocks/UniversalProvider';
|
|
13
|
+
// Extend networks as CAIP networks
|
|
14
|
+
const [base, mainnet, polygon, sepolia, solana] = CaipNetworksUtil.extendCaipNetworks([baseNetwork, mainnetNetwork, polygonNetwork, sepoliaNetwork, solanaNetwork], { customNetworkImageUrls: {}, projectId: 'test-project-id' });
|
|
15
|
+
// Mock all controllers and UniversalAdapterClient
|
|
16
|
+
vi.mock('@reown/appkit-core');
|
|
17
|
+
vi.mock('../src/universal-adapter/client');
|
|
18
|
+
vi.mock('../src/client.ts', async () => {
|
|
19
|
+
const actual = await vi.importActual('../src/client.ts');
|
|
20
|
+
return {
|
|
21
|
+
...actual,
|
|
22
|
+
injectModalUi: vi.fn(),
|
|
23
|
+
syncExistingConnection: vi.fn()
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
vi.mocked(global).window = { location: { origin: '' } };
|
|
27
|
+
vi.mocked(global).document = {
|
|
28
|
+
body: {
|
|
29
|
+
insertAdjacentElement: vi.fn()
|
|
30
|
+
},
|
|
31
|
+
createElement: vi.fn().mockReturnValue({ appendChild: vi.fn() }),
|
|
32
|
+
getElementsByTagName: vi.fn().mockReturnValue([{ textContent: '' }]),
|
|
33
|
+
querySelector: vi.fn()
|
|
34
|
+
};
|
|
35
|
+
describe('Base', () => {
|
|
36
|
+
let appKit;
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
vi.mocked(ConnectorController).getConnectors = vi.fn().mockReturnValue([]);
|
|
39
|
+
vi.spyOn(ConstantsUtil, 'BALANCE_SUPPORTED_CHAINS', 'get').mockReturnValue(['eip155', 'solana']);
|
|
40
|
+
appKit = new AppKit(mockOptions);
|
|
41
|
+
vi.spyOn(OptionsController, 'getSnapshot').mockReturnValue({ ...OptionsController.state });
|
|
42
|
+
vi.spyOn(ThemeController, 'getSnapshot').mockReturnValue({ ...ThemeController.state });
|
|
43
|
+
});
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
vi.restoreAllMocks();
|
|
46
|
+
});
|
|
47
|
+
describe('Base Initialization', () => {
|
|
48
|
+
it('should initialize controllers', async () => {
|
|
49
|
+
const sendEvent = vi.spyOn(EventsController, 'sendEvent');
|
|
50
|
+
// Mock the abstract method injectModalUi to bypass it
|
|
51
|
+
vi.spyOn(AppKit.prototype, 'injectModalUi').mockImplementation(async () => { });
|
|
52
|
+
const copyMockOptions = { ...mockOptions };
|
|
53
|
+
delete copyMockOptions.adapters;
|
|
54
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
55
|
+
expect(sendEvent).toHaveBeenCalledOnce();
|
|
56
|
+
expect(sendEvent).toHaveBeenCalledWith({
|
|
57
|
+
type: 'track',
|
|
58
|
+
event: 'INITIALIZE',
|
|
59
|
+
properties: {
|
|
60
|
+
...copyMockOptions,
|
|
61
|
+
networks: copyMockOptions.networks.map((n) => n.id),
|
|
62
|
+
siweConfig: {
|
|
63
|
+
options: copyMockOptions.siweConfig?.options || {}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
expect(ChainController.initialize).toHaveBeenCalledOnce();
|
|
68
|
+
expect(ChainController.initialize).toHaveBeenCalledWith(mockOptions.adapters, [mainnet, sepolia, solana], {
|
|
69
|
+
connectionControllerClient: expect.any(Object),
|
|
70
|
+
networkControllerClient: expect.any(Object)
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
it('should set EIP6963 enabled by default', () => {
|
|
74
|
+
new AppKit({
|
|
75
|
+
...mockOptions
|
|
76
|
+
});
|
|
77
|
+
expect(OptionsController.setEIP6963Enabled).toHaveBeenCalledWith(true);
|
|
78
|
+
});
|
|
79
|
+
it('should set EIP6963 disabled when option is disabled in config', () => {
|
|
80
|
+
new AppKit({
|
|
81
|
+
...mockOptions,
|
|
82
|
+
enableEIP6963: false
|
|
83
|
+
});
|
|
84
|
+
expect(OptionsController.setEIP6963Enabled).toHaveBeenCalledWith(false);
|
|
85
|
+
});
|
|
86
|
+
it('should set partially defaultAccountType', () => {
|
|
87
|
+
new AppKit({
|
|
88
|
+
...mockOptions,
|
|
89
|
+
defaultAccountTypes: {
|
|
90
|
+
eip155: 'eoa',
|
|
91
|
+
bip122: 'ordinal'
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
expect(OptionsController.setDefaultAccountTypes).toHaveBeenCalledWith({
|
|
95
|
+
eip155: 'eoa',
|
|
96
|
+
bip122: 'ordinal'
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('Base Public methods', () => {
|
|
101
|
+
it('should open modal', async () => {
|
|
102
|
+
await appKit.open();
|
|
103
|
+
expect(ModalController.open).toHaveBeenCalled();
|
|
104
|
+
});
|
|
105
|
+
it('should close modal', async () => {
|
|
106
|
+
await appKit.close();
|
|
107
|
+
expect(ModalController.close).toHaveBeenCalled();
|
|
108
|
+
});
|
|
109
|
+
it('should set loading state', () => {
|
|
110
|
+
appKit.setLoading(true);
|
|
111
|
+
expect(ModalController.setLoading).toHaveBeenCalledWith(true);
|
|
112
|
+
});
|
|
113
|
+
it('should get theme mode', () => {
|
|
114
|
+
vi.spyOn(ThemeController.state, 'themeMode', 'get').mockReturnValueOnce('dark');
|
|
115
|
+
expect(appKit.getThemeMode()).toBe('dark');
|
|
116
|
+
});
|
|
117
|
+
it('should set theme mode', () => {
|
|
118
|
+
appKit.setThemeMode('light');
|
|
119
|
+
expect(ThemeController.setThemeMode).toHaveBeenCalledWith('light');
|
|
120
|
+
});
|
|
121
|
+
it('should get theme variables', () => {
|
|
122
|
+
vi.spyOn(ThemeController.state, 'themeVariables', 'get').mockReturnValueOnce({
|
|
123
|
+
'--w3m-accent': '#000'
|
|
124
|
+
});
|
|
125
|
+
expect(appKit.getThemeVariables()).toEqual({ '--w3m-accent': '#000' });
|
|
126
|
+
});
|
|
127
|
+
it('should set theme variables', () => {
|
|
128
|
+
const themeVariables = { '--w3m-accent': '#fff' };
|
|
129
|
+
appKit.setThemeVariables(themeVariables);
|
|
130
|
+
expect(ThemeController.setThemeVariables).toHaveBeenCalledWith(themeVariables);
|
|
131
|
+
});
|
|
132
|
+
it('should subscribe to theme changes', () => {
|
|
133
|
+
const callback = vi.fn();
|
|
134
|
+
appKit.subscribeTheme(callback);
|
|
135
|
+
expect(ThemeController.subscribe).toHaveBeenCalledWith(callback);
|
|
136
|
+
});
|
|
137
|
+
it('should get wallet info', () => {
|
|
138
|
+
vi.mocked(AccountController).state = { connectedWalletInfo: { name: 'Test Wallet' } };
|
|
139
|
+
expect(appKit.getWalletInfo()).toEqual({ name: 'Test Wallet' });
|
|
140
|
+
});
|
|
141
|
+
it('should subscribe to wallet info changes', () => {
|
|
142
|
+
const callback = vi.fn();
|
|
143
|
+
appKit.subscribeWalletInfo(callback);
|
|
144
|
+
expect(AccountController.subscribeKey).toHaveBeenCalledWith('connectedWalletInfo', callback);
|
|
145
|
+
});
|
|
146
|
+
it('should subscribe to address updates', () => {
|
|
147
|
+
const callback = vi.fn();
|
|
148
|
+
appKit.subscribeShouldUpdateToAddress(callback);
|
|
149
|
+
expect(AccountController.subscribeKey).toHaveBeenCalledWith('shouldUpdateToAddress', callback);
|
|
150
|
+
});
|
|
151
|
+
it('should subscribe to CAIP network changes', () => {
|
|
152
|
+
const callback = vi.fn();
|
|
153
|
+
appKit.subscribeCaipNetworkChange(callback);
|
|
154
|
+
expect(ChainController.subscribeKey).toHaveBeenCalledWith('activeCaipNetwork', callback);
|
|
155
|
+
});
|
|
156
|
+
it('should get state', () => {
|
|
157
|
+
vi.mocked(PublicStateController).state = { isConnected: true };
|
|
158
|
+
expect(appKit.getState()).toEqual({ isConnected: true });
|
|
159
|
+
});
|
|
160
|
+
it('should subscribe to state changes', () => {
|
|
161
|
+
const callback = vi.fn();
|
|
162
|
+
appKit.subscribeState(callback);
|
|
163
|
+
expect(PublicStateController.subscribe).toHaveBeenCalledWith(callback);
|
|
164
|
+
});
|
|
165
|
+
it('should show error message', () => {
|
|
166
|
+
appKit.showErrorMessage('Test error');
|
|
167
|
+
expect(SnackController.showError).toHaveBeenCalledWith('Test error');
|
|
168
|
+
});
|
|
169
|
+
it('should show success message', () => {
|
|
170
|
+
appKit.showSuccessMessage('Test success');
|
|
171
|
+
expect(SnackController.showSuccess).toHaveBeenCalledWith('Test success');
|
|
172
|
+
});
|
|
173
|
+
it('should get event', () => {
|
|
174
|
+
vi.mocked(EventsController).state = { name: 'test_event' };
|
|
175
|
+
expect(appKit.getEvent()).toEqual({ name: 'test_event' });
|
|
176
|
+
});
|
|
177
|
+
it('should subscribe to events', () => {
|
|
178
|
+
const callback = vi.fn();
|
|
179
|
+
appKit.subscribeEvents(callback);
|
|
180
|
+
expect(EventsController.subscribe).toHaveBeenCalledWith(callback);
|
|
181
|
+
});
|
|
182
|
+
it('should replace route', () => {
|
|
183
|
+
appKit.replace('Connect');
|
|
184
|
+
expect(RouterController.replace).toHaveBeenCalledWith('Connect');
|
|
185
|
+
});
|
|
186
|
+
it('should redirect to route', () => {
|
|
187
|
+
appKit.redirect('Networks');
|
|
188
|
+
expect(RouterController.push).toHaveBeenCalledWith('Networks');
|
|
189
|
+
});
|
|
190
|
+
it('should pop transaction stack', () => {
|
|
191
|
+
appKit.popTransactionStack(true);
|
|
192
|
+
expect(RouterController.popTransactionStack).toHaveBeenCalledWith(true);
|
|
193
|
+
});
|
|
194
|
+
it('should check if modal is open', () => {
|
|
195
|
+
vi.mocked(ModalController).state = { open: true };
|
|
196
|
+
expect(appKit.isOpen()).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
it('should check if transaction stack is empty', () => {
|
|
199
|
+
vi.mocked(RouterController).state = { transactionStack: [] };
|
|
200
|
+
expect(appKit.isTransactionStackEmpty()).toBe(true);
|
|
201
|
+
});
|
|
202
|
+
it('should check if transaction should replace view', () => {
|
|
203
|
+
vi.mocked(RouterController).state = { transactionStack: [{ replace: true }] };
|
|
204
|
+
expect(appKit.isTransactionShouldReplaceView()).toBe(true);
|
|
205
|
+
});
|
|
206
|
+
it('should set status', () => {
|
|
207
|
+
appKit.setStatus('connected', 'eip155');
|
|
208
|
+
expect(AccountController.setStatus).toHaveBeenCalledWith('connected', 'eip155');
|
|
209
|
+
});
|
|
210
|
+
it('should set all accounts', () => {
|
|
211
|
+
const evmAddresses = [
|
|
212
|
+
{ address: '0x1', namespace: 'eip155', type: 'eoa' },
|
|
213
|
+
{ address: '0x2', namespace: 'eip155', type: 'smartAccount' }
|
|
214
|
+
];
|
|
215
|
+
const solanaAddresses = [{ address: 'asdbjk', namespace: 'solana', type: 'eoa' }];
|
|
216
|
+
const bip122Addresses = [
|
|
217
|
+
{ address: 'asdasd1', namespace: 'bip122', type: 'payment' },
|
|
218
|
+
{ address: 'asdasd2', namespace: 'bip122', type: 'ordinal' },
|
|
219
|
+
{ address: 'ASDASD3', namespace: 'bip122', type: 'stx' }
|
|
220
|
+
];
|
|
221
|
+
appKit.setAllAccounts(evmAddresses, 'eip155');
|
|
222
|
+
appKit.setAllAccounts(solanaAddresses, 'solana');
|
|
223
|
+
appKit.setAllAccounts(bip122Addresses, 'bip122');
|
|
224
|
+
expect(AccountController.setAllAccounts).toHaveBeenCalledWith(evmAddresses, 'eip155');
|
|
225
|
+
expect(AccountController.setAllAccounts).toHaveBeenCalledWith(solanaAddresses, 'solana');
|
|
226
|
+
expect(AccountController.setAllAccounts).toHaveBeenCalledWith(bip122Addresses, 'bip122');
|
|
227
|
+
expect(OptionsController.setHasMultipleAddresses).toHaveBeenCalledWith(true);
|
|
228
|
+
});
|
|
229
|
+
it('should add address label', () => {
|
|
230
|
+
appKit.addAddressLabel('0x123', 'eip155 Address', 'eip155');
|
|
231
|
+
expect(AccountController.addAddressLabel).toHaveBeenCalledWith('0x123', 'eip155 Address', 'eip155');
|
|
232
|
+
});
|
|
233
|
+
it('should remove address label', () => {
|
|
234
|
+
appKit.removeAddressLabel('0x123', 'eip155');
|
|
235
|
+
expect(AccountController.removeAddressLabel).toHaveBeenCalledWith('0x123', 'eip155');
|
|
236
|
+
});
|
|
237
|
+
it('should get CAIP address', () => {
|
|
238
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
239
|
+
activeChain: 'eip155',
|
|
240
|
+
activeCaipAddress: 'eip155:1:0x123',
|
|
241
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]])
|
|
242
|
+
});
|
|
243
|
+
expect(appKit.getCaipAddress()).toBe('eip155:1:0x123');
|
|
244
|
+
});
|
|
245
|
+
it('should get address', () => {
|
|
246
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
247
|
+
chains: new Map(),
|
|
248
|
+
activeChain: 'eip155'
|
|
249
|
+
});
|
|
250
|
+
vi.mocked(AccountController).state = { address: '0x123' };
|
|
251
|
+
expect(appKit.getAddress()).toBe('0x123');
|
|
252
|
+
});
|
|
253
|
+
it('should get provider', () => {
|
|
254
|
+
const mockProvider = vi.fn();
|
|
255
|
+
vi.mocked(ProviderUtil.state).providers = { eip155: mockProvider };
|
|
256
|
+
vi.mocked(ProviderUtil.state).providerIds = { eip155: 'INJECTED' };
|
|
257
|
+
expect(appKit.getProvider('eip155')).toBe(mockProvider);
|
|
258
|
+
});
|
|
259
|
+
it('should get preferred account type', () => {
|
|
260
|
+
vi.mocked(AccountController).state = { preferredAccountType: 'eoa' };
|
|
261
|
+
expect(appKit.getPreferredAccountType()).toBe('eoa');
|
|
262
|
+
});
|
|
263
|
+
it('should set CAIP address', () => {
|
|
264
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
265
|
+
...ChainController.state,
|
|
266
|
+
activeChain: 'eip155',
|
|
267
|
+
activeCaipAddress: 'eip155:1:0x123',
|
|
268
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]])
|
|
269
|
+
});
|
|
270
|
+
appKit.setCaipAddress('eip155:1:0x123', 'eip155');
|
|
271
|
+
expect(AccountController.setCaipAddress).toHaveBeenCalledWith('eip155:1:0x123', 'eip155');
|
|
272
|
+
expect(appKit.getIsConnectedState()).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
it('should set balance', () => {
|
|
275
|
+
appKit.setBalance('1.5', 'ETH', 'eip155');
|
|
276
|
+
expect(AccountController.setBalance).toHaveBeenCalledWith('1.5', 'ETH', 'eip155');
|
|
277
|
+
});
|
|
278
|
+
it('should set profile name', () => {
|
|
279
|
+
appKit.setProfileName('John Doe', 'eip155');
|
|
280
|
+
expect(AccountController.setProfileName).toHaveBeenCalledWith('John Doe', 'eip155');
|
|
281
|
+
});
|
|
282
|
+
it('should set profile image', () => {
|
|
283
|
+
appKit.setProfileImage('https://example.com/image.png', 'eip155');
|
|
284
|
+
expect(AccountController.setProfileImage).toHaveBeenCalledWith('https://example.com/image.png', 'eip155');
|
|
285
|
+
});
|
|
286
|
+
it('should reset account', () => {
|
|
287
|
+
appKit.resetAccount('eip155');
|
|
288
|
+
expect(AccountController.resetAccount).toHaveBeenCalledWith('eip155');
|
|
289
|
+
});
|
|
290
|
+
it('should set CAIP network', () => {
|
|
291
|
+
const caipNetwork = mainnet;
|
|
292
|
+
appKit.setCaipNetwork(caipNetwork);
|
|
293
|
+
expect(ChainController.setActiveCaipNetwork).toHaveBeenCalledWith(caipNetwork);
|
|
294
|
+
});
|
|
295
|
+
it('should get CAIP network', () => {
|
|
296
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
297
|
+
activeCaipNetwork: mainnet,
|
|
298
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]])
|
|
299
|
+
});
|
|
300
|
+
expect(appKit.getCaipNetwork()).toEqual(mainnet);
|
|
301
|
+
});
|
|
302
|
+
it('should set requested CAIP networks', () => {
|
|
303
|
+
const requestedNetworks = [mainnet];
|
|
304
|
+
appKit.setRequestedCaipNetworks(requestedNetworks, 'eip155');
|
|
305
|
+
expect(ChainController.setRequestedCaipNetworks).toHaveBeenCalledWith(requestedNetworks, 'eip155');
|
|
306
|
+
});
|
|
307
|
+
it('should set connectors', () => {
|
|
308
|
+
const existingConnectors = [
|
|
309
|
+
{ id: 'phantom', name: 'Phantom', chain: 'eip155', type: 'INJECTED' }
|
|
310
|
+
];
|
|
311
|
+
// Mock getConnectors to return existing connectors
|
|
312
|
+
vi.mocked(ConnectorController.getConnectors).mockReturnValue(existingConnectors);
|
|
313
|
+
const newConnectors = [
|
|
314
|
+
{ id: 'metamask', name: 'MetaMask', chain: 'eip155', type: 'INJECTED' }
|
|
315
|
+
];
|
|
316
|
+
appKit.setConnectors(newConnectors);
|
|
317
|
+
// Verify that setConnectors was called with combined array
|
|
318
|
+
expect(ConnectorController.setConnectors).toHaveBeenCalledWith([
|
|
319
|
+
...existingConnectors,
|
|
320
|
+
...newConnectors
|
|
321
|
+
]);
|
|
322
|
+
});
|
|
323
|
+
it('should add connector', () => {
|
|
324
|
+
const connector = {
|
|
325
|
+
id: 'metamask',
|
|
326
|
+
name: 'MetaMask',
|
|
327
|
+
chain: 'eip155',
|
|
328
|
+
type: 'INJECTED'
|
|
329
|
+
};
|
|
330
|
+
appKit.addConnector(connector);
|
|
331
|
+
expect(ConnectorController.addConnector).toHaveBeenCalledWith(connector);
|
|
332
|
+
});
|
|
333
|
+
it('should get connectors', () => {
|
|
334
|
+
const mockConnectors = [
|
|
335
|
+
{ id: 'metamask', name: 'MetaMask', chain: 'eip155:1', type: 'INJECTED' }
|
|
336
|
+
];
|
|
337
|
+
vi.mocked(ConnectorController.getConnectors).mockReturnValue(mockConnectors);
|
|
338
|
+
expect(appKit.getConnectors()).toEqual(mockConnectors);
|
|
339
|
+
});
|
|
340
|
+
it('should get approved CAIP network IDs', () => {
|
|
341
|
+
vi.mocked(ChainController.getAllApprovedCaipNetworkIds).mockReturnValue(['eip155:1']);
|
|
342
|
+
expect(appKit.getApprovedCaipNetworkIds()).toEqual(['eip155:1']);
|
|
343
|
+
});
|
|
344
|
+
it('should set approved CAIP networks data', () => {
|
|
345
|
+
appKit.setApprovedCaipNetworksData('eip155');
|
|
346
|
+
expect(ChainController.setApprovedCaipNetworksData).toHaveBeenCalledWith('eip155');
|
|
347
|
+
});
|
|
348
|
+
it('should reset network', () => {
|
|
349
|
+
appKit.resetNetwork('eip155');
|
|
350
|
+
expect(ChainController.resetNetwork).toHaveBeenCalled();
|
|
351
|
+
});
|
|
352
|
+
it('should reset WC connection', () => {
|
|
353
|
+
appKit.resetWcConnection();
|
|
354
|
+
expect(ConnectionController.resetWcConnection).toHaveBeenCalled();
|
|
355
|
+
});
|
|
356
|
+
it('should fetch identity', async () => {
|
|
357
|
+
const mockRequest = { caipChainId: 'eip155:1', address: '0x123' };
|
|
358
|
+
vi.mocked(BlockchainApiController.fetchIdentity).mockResolvedValue({
|
|
359
|
+
name: 'John Doe',
|
|
360
|
+
avatar: null
|
|
361
|
+
});
|
|
362
|
+
const result = await appKit.fetchIdentity(mockRequest);
|
|
363
|
+
expect(BlockchainApiController.fetchIdentity).toHaveBeenCalledWith(mockRequest);
|
|
364
|
+
expect(result).toEqual({ name: 'John Doe', avatar: null });
|
|
365
|
+
});
|
|
366
|
+
it('should set address explorer URL', () => {
|
|
367
|
+
appKit.setAddressExplorerUrl('https://etherscan.io/address/0x123', 'eip155');
|
|
368
|
+
expect(AccountController.setAddressExplorerUrl).toHaveBeenCalledWith('https://etherscan.io/address/0x123', 'eip155');
|
|
369
|
+
});
|
|
370
|
+
it('should set smart account deployed', () => {
|
|
371
|
+
appKit.setSmartAccountDeployed(true, 'eip155');
|
|
372
|
+
expect(AccountController.setSmartAccountDeployed).toHaveBeenCalledWith(true, 'eip155');
|
|
373
|
+
});
|
|
374
|
+
it('should set connected wallet info', () => {
|
|
375
|
+
const walletInfo = { name: 'MetaMask', icon: 'icon-url' };
|
|
376
|
+
appKit.setConnectedWalletInfo(walletInfo, 'eip155');
|
|
377
|
+
expect(AccountController.setConnectedWalletInfo).toHaveBeenCalledWith(walletInfo, 'eip155');
|
|
378
|
+
});
|
|
379
|
+
it('should set smart account enabled networks', () => {
|
|
380
|
+
const networks = [1, 137];
|
|
381
|
+
appKit.setSmartAccountEnabledNetworks(networks, 'eip155');
|
|
382
|
+
expect(ChainController.setSmartAccountEnabledNetworks).toHaveBeenCalledWith(networks, 'eip155');
|
|
383
|
+
});
|
|
384
|
+
it('should set preferred account type', () => {
|
|
385
|
+
appKit.setPreferredAccountType('eoa', 'eip155');
|
|
386
|
+
expect(AccountController.setPreferredAccountType).toHaveBeenCalledWith('eoa', 'eip155');
|
|
387
|
+
});
|
|
388
|
+
it('should create accounts with correct account types from user accounts', async () => {
|
|
389
|
+
const mockUser = {
|
|
390
|
+
address: '0x123',
|
|
391
|
+
accounts: [
|
|
392
|
+
{ address: '0x1', type: 'eoa' },
|
|
393
|
+
{ address: '0x2', type: 'smartAccount' }
|
|
394
|
+
],
|
|
395
|
+
preferredAccountType: 'eoa',
|
|
396
|
+
user: {
|
|
397
|
+
email: 'email@test.com',
|
|
398
|
+
username: 'test'
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
402
|
+
activeChain: 'eip155',
|
|
403
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]])
|
|
404
|
+
});
|
|
405
|
+
vi.spyOn(CoreHelperUtil, 'createAccount').mockImplementation((namespace, address, type) => {
|
|
406
|
+
if (namespace === 'eip155') {
|
|
407
|
+
return {
|
|
408
|
+
address,
|
|
409
|
+
type: type,
|
|
410
|
+
namespace: 'eip155'
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
throw new Error('Unexpected namespace');
|
|
414
|
+
});
|
|
415
|
+
const mockAuthProvider = {
|
|
416
|
+
onConnect: vi.fn(callback => callback(mockUser)),
|
|
417
|
+
connect: vi.fn(),
|
|
418
|
+
getSmartAccountEnabledNetworks: vi.fn(),
|
|
419
|
+
onGetSmartAccountEnabledNetworks: vi.fn(),
|
|
420
|
+
onSetPreferredAccount: vi.fn(),
|
|
421
|
+
onRpcRequest: vi.fn(),
|
|
422
|
+
onRpcError: vi.fn(),
|
|
423
|
+
onRpcSuccess: vi.fn(),
|
|
424
|
+
onNotConnected: vi.fn(),
|
|
425
|
+
onIsConnected: vi.fn(),
|
|
426
|
+
getLoginEmailUsed: vi.fn().mockReturnValue(false),
|
|
427
|
+
isConnected: vi.fn().mockResolvedValue({ isConnected: false }),
|
|
428
|
+
getEmail: vi.fn().mockReturnValue('email@email.com'),
|
|
429
|
+
getUsername: vi.fn().mockReturnValue('test'),
|
|
430
|
+
onSocialConnected: vi.fn(),
|
|
431
|
+
syncDappData: vi.fn(),
|
|
432
|
+
syncTheme: vi.fn()
|
|
433
|
+
};
|
|
434
|
+
const appKitWithAuth = new AppKit({
|
|
435
|
+
...mockOptions,
|
|
436
|
+
features: {
|
|
437
|
+
email: true
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
appKitWithAuth.authProvider = mockAuthProvider;
|
|
441
|
+
await appKitWithAuth.syncAuthConnector(mockAuthProvider);
|
|
442
|
+
expect(CoreHelperUtil.createAccount).toHaveBeenCalledWith('eip155', '0x1', 'eoa');
|
|
443
|
+
expect(CoreHelperUtil.createAccount).toHaveBeenCalledWith('eip155', '0x2', 'smartAccount');
|
|
444
|
+
expect(AccountController.setAllAccounts).toHaveBeenCalledWith([
|
|
445
|
+
{ address: '0x1', type: 'eoa', namespace: 'eip155' },
|
|
446
|
+
{ address: '0x2', type: 'smartAccount', namespace: 'eip155' }
|
|
447
|
+
], 'eip155');
|
|
448
|
+
expect(AccountController.setPreferredAccountType).toHaveBeenCalledWith('eoa', 'eip155');
|
|
449
|
+
});
|
|
450
|
+
it('should get Reown name', async () => {
|
|
451
|
+
vi.mocked(EnsController.getNamesForAddress).mockResolvedValue([
|
|
452
|
+
{
|
|
453
|
+
name: 'john.reown.id',
|
|
454
|
+
addresses: { eip155: { address: '0x123', created: '0' } },
|
|
455
|
+
attributes: [],
|
|
456
|
+
registered: 0,
|
|
457
|
+
updated: 0
|
|
458
|
+
}
|
|
459
|
+
]);
|
|
460
|
+
const result = await appKit.getReownName('john.reown.id');
|
|
461
|
+
expect(EnsController.getNamesForAddress).toHaveBeenCalledWith('john.reown.id');
|
|
462
|
+
expect(result).toEqual([
|
|
463
|
+
{
|
|
464
|
+
name: 'john.reown.id',
|
|
465
|
+
addresses: { eip155: { address: '0x123', created: '0' } },
|
|
466
|
+
attributes: [],
|
|
467
|
+
registered: 0,
|
|
468
|
+
updated: 0
|
|
469
|
+
}
|
|
470
|
+
]);
|
|
471
|
+
});
|
|
472
|
+
it('should set EIP6963 enabled', () => {
|
|
473
|
+
appKit.setEIP6963Enabled(true);
|
|
474
|
+
expect(OptionsController.setEIP6963Enabled).toHaveBeenCalledWith(true);
|
|
475
|
+
});
|
|
476
|
+
it('should set client ID', () => {
|
|
477
|
+
appKit.setClientId('client-123');
|
|
478
|
+
expect(BlockchainApiController.setClientId).toHaveBeenCalledWith('client-123');
|
|
479
|
+
});
|
|
480
|
+
it('should get connector image', () => {
|
|
481
|
+
vi.mocked(AssetUtil.getConnectorImage).mockReturnValue('connector-image-url');
|
|
482
|
+
const result = appKit.getConnectorImage({
|
|
483
|
+
id: 'metamask',
|
|
484
|
+
type: 'INJECTED',
|
|
485
|
+
chain: 'eip155',
|
|
486
|
+
name: 'Metamask'
|
|
487
|
+
});
|
|
488
|
+
expect(AssetUtil.getConnectorImage).toHaveBeenCalledWith({
|
|
489
|
+
id: 'metamask',
|
|
490
|
+
type: 'INJECTED',
|
|
491
|
+
chain: 'eip155',
|
|
492
|
+
name: 'Metamask'
|
|
493
|
+
});
|
|
494
|
+
expect(result).toBe('connector-image-url');
|
|
495
|
+
});
|
|
496
|
+
it('should switch network when requested', async () => {
|
|
497
|
+
const mockAppKit = new AppKit(mockOptions);
|
|
498
|
+
vi.mocked(ChainController.switchActiveNetwork).mockResolvedValue(undefined);
|
|
499
|
+
mockAppKit.switchNetwork(mainnet);
|
|
500
|
+
expect(ChainController.switchActiveNetwork).toHaveBeenCalledWith(expect.objectContaining({
|
|
501
|
+
id: mainnet.id,
|
|
502
|
+
name: mainnet.name
|
|
503
|
+
}));
|
|
504
|
+
mockAppKit.switchNetwork(polygon);
|
|
505
|
+
expect(ChainController.switchActiveNetwork).toHaveBeenCalledTimes(1);
|
|
506
|
+
});
|
|
507
|
+
it('should use the correct network when syncing account if is does not allow all networks and network is not allowed', async () => {
|
|
508
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
509
|
+
{
|
|
510
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
511
|
+
chainId: 'eip155:1',
|
|
512
|
+
symbol: 'ETH'
|
|
513
|
+
}
|
|
514
|
+
]);
|
|
515
|
+
vi.mocked(ChainController.getAllApprovedCaipNetworkIds).mockReturnValue([
|
|
516
|
+
'eip155:1',
|
|
517
|
+
'eip155:11155111'
|
|
518
|
+
]);
|
|
519
|
+
vi.spyOn(ChainController, 'getNetworkProp').mockReturnValue(false);
|
|
520
|
+
vi.spyOn(ChainController.state, 'activeChain', 'get').mockReturnValueOnce('eip155');
|
|
521
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValueOnce({
|
|
522
|
+
namespace: mainnet.chainNamespace,
|
|
523
|
+
chainId: mainnet.id,
|
|
524
|
+
caipNetworkId: mainnet.caipNetworkId
|
|
525
|
+
});
|
|
526
|
+
vi.spyOn(OptionsController, 'state', 'get').mockReturnValueOnce({
|
|
527
|
+
allowUnsupportedChain: false
|
|
528
|
+
});
|
|
529
|
+
const mockAccountData = {
|
|
530
|
+
address: '0x123',
|
|
531
|
+
chainId: '2',
|
|
532
|
+
chainNamespace: 'eip155'
|
|
533
|
+
};
|
|
534
|
+
await appKit['syncAccount'](mockAccountData);
|
|
535
|
+
expect(ChainController.getNetworkProp).toHaveBeenCalledWith('supportsAllNetworks', 'eip155');
|
|
536
|
+
expect(ChainController.setActiveCaipNetwork).toHaveBeenCalledWith(mainnet);
|
|
537
|
+
});
|
|
538
|
+
it('should set connected wallet info when syncing account', async () => {
|
|
539
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
540
|
+
{
|
|
541
|
+
...sepolia,
|
|
542
|
+
nativeCurrency: { symbol: 'ETH' },
|
|
543
|
+
chainNamespace: 'eip155'
|
|
544
|
+
}
|
|
545
|
+
]);
|
|
546
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
547
|
+
{
|
|
548
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
549
|
+
chainId: 'eip155:1',
|
|
550
|
+
symbol: 'ETH'
|
|
551
|
+
}
|
|
552
|
+
]);
|
|
553
|
+
vi.spyOn(ChainController, 'getAllApprovedCaipNetworkIds').mockReturnValue(['eip155:1']);
|
|
554
|
+
vi.mocked(appKit).caipNetworks = [mainnet];
|
|
555
|
+
// Mock the connector data
|
|
556
|
+
const mockConnector = {
|
|
557
|
+
id: 'test-wallet',
|
|
558
|
+
name: 'Test Wallet',
|
|
559
|
+
imageUrl: 'test-wallet-icon'
|
|
560
|
+
};
|
|
561
|
+
vi.mocked(ConnectorController.getConnectors).mockReturnValue([mockConnector]);
|
|
562
|
+
vi.mocked(StorageUtil.getActiveNetworkProps).mockReturnValue({
|
|
563
|
+
namespace: mainnet.chainNamespace,
|
|
564
|
+
chainId: mainnet.id,
|
|
565
|
+
caipNetworkId: mainnet.caipNetworkId
|
|
566
|
+
});
|
|
567
|
+
const mockAccountData = {
|
|
568
|
+
address: '0x123',
|
|
569
|
+
chainId: mainnet.id,
|
|
570
|
+
chainNamespace: mainnet.chainNamespace
|
|
571
|
+
};
|
|
572
|
+
vi.spyOn(StorageUtil, 'getConnectedConnectorId').mockReturnValue(mockConnector.id);
|
|
573
|
+
await appKit['syncAccount'](mockAccountData);
|
|
574
|
+
expect(AccountController.setConnectedWalletInfo).toHaveBeenCalledWith(expect.objectContaining({
|
|
575
|
+
name: mockConnector.name,
|
|
576
|
+
icon: mockConnector.imageUrl
|
|
577
|
+
}), 'eip155');
|
|
578
|
+
});
|
|
579
|
+
it('should sync identity only if address changed', async () => {
|
|
580
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
581
|
+
{
|
|
582
|
+
...mainnet,
|
|
583
|
+
nativeCurrency: { symbol: 'ETH' },
|
|
584
|
+
chainNamespace: 'eip155'
|
|
585
|
+
}
|
|
586
|
+
]);
|
|
587
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
588
|
+
{
|
|
589
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
590
|
+
chainId: 'eip155:1',
|
|
591
|
+
symbol: 'ETH'
|
|
592
|
+
}
|
|
593
|
+
]);
|
|
594
|
+
vi.spyOn(ChainController, 'getAllApprovedCaipNetworkIds').mockReturnValue(['eip155:1']);
|
|
595
|
+
vi.mocked(appKit).caipNetworks = [mainnet];
|
|
596
|
+
const mockAccountData = {
|
|
597
|
+
address: '0x123',
|
|
598
|
+
chainId: mainnet.id,
|
|
599
|
+
chainNamespace: mainnet.chainNamespace
|
|
600
|
+
};
|
|
601
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValue({
|
|
602
|
+
namespace: mainnet.chainNamespace,
|
|
603
|
+
chainId: mainnet.id,
|
|
604
|
+
caipNetworkId: mainnet.caipNetworkId
|
|
605
|
+
});
|
|
606
|
+
vi.mocked(BlockchainApiController.fetchIdentity).mockResolvedValue({
|
|
607
|
+
name: 'John Doe',
|
|
608
|
+
avatar: null
|
|
609
|
+
});
|
|
610
|
+
vi.mocked(AccountController).state = { address: '0x123' };
|
|
611
|
+
await appKit['syncAccount'](mockAccountData);
|
|
612
|
+
expect(BlockchainApiController.fetchIdentity).not.toHaveBeenCalled();
|
|
613
|
+
await appKit['syncAccount']({ ...mockAccountData, address: '0x456' });
|
|
614
|
+
expect(BlockchainApiController.fetchIdentity).toHaveBeenCalledOnce();
|
|
615
|
+
});
|
|
616
|
+
it('should not sync identity on non-evm network', async () => {
|
|
617
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
618
|
+
{
|
|
619
|
+
...solana,
|
|
620
|
+
nativeCurrency: { symbol: 'SOL' },
|
|
621
|
+
chainNamespace: 'solana'
|
|
622
|
+
}
|
|
623
|
+
]);
|
|
624
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
625
|
+
{
|
|
626
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
627
|
+
chainId: 'solana:1',
|
|
628
|
+
symbol: 'SOL'
|
|
629
|
+
}
|
|
630
|
+
]);
|
|
631
|
+
vi.spyOn(ChainController, 'getAllApprovedCaipNetworkIds').mockReturnValue(['solana:1']);
|
|
632
|
+
vi.mocked(appKit).caipNetworks = [solana];
|
|
633
|
+
const mockAccountData = {
|
|
634
|
+
address: '0x123',
|
|
635
|
+
chainId: solana.id,
|
|
636
|
+
chainNamespace: solana.chainNamespace
|
|
637
|
+
};
|
|
638
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValueOnce({
|
|
639
|
+
namespace: solana.chainNamespace,
|
|
640
|
+
chainId: solana.id,
|
|
641
|
+
caipNetworkId: solana.caipNetworkId
|
|
642
|
+
});
|
|
643
|
+
await appKit['syncAccount'](mockAccountData);
|
|
644
|
+
expect(BlockchainApiController.fetchIdentity).not.toHaveBeenCalled();
|
|
645
|
+
});
|
|
646
|
+
it('should not sync identity on a test network', async () => {
|
|
647
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
648
|
+
{
|
|
649
|
+
...sepolia,
|
|
650
|
+
nativeCurrency: { symbol: 'sETH' },
|
|
651
|
+
chainNamespace: 'eip155'
|
|
652
|
+
}
|
|
653
|
+
]);
|
|
654
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
655
|
+
{
|
|
656
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
657
|
+
chainId: 'eip155:11155111',
|
|
658
|
+
symbol: 'sETH'
|
|
659
|
+
}
|
|
660
|
+
]);
|
|
661
|
+
vi.spyOn(ChainController, 'getAllApprovedCaipNetworkIds').mockReturnValue(['eip155:11155111']);
|
|
662
|
+
vi.mocked(appKit).caipNetworks = [sepolia];
|
|
663
|
+
const mockAccountData = {
|
|
664
|
+
address: '0x123',
|
|
665
|
+
chainId: '11155111',
|
|
666
|
+
chainNamespace: 'eip155'
|
|
667
|
+
};
|
|
668
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValueOnce({
|
|
669
|
+
namespace: 'eip155',
|
|
670
|
+
chainId: '11155111',
|
|
671
|
+
caipNetworkId: 'eip155:11155111'
|
|
672
|
+
});
|
|
673
|
+
await appKit['syncAccount'](mockAccountData);
|
|
674
|
+
expect(BlockchainApiController.fetchIdentity).not.toHaveBeenCalled();
|
|
675
|
+
});
|
|
676
|
+
it('should sync balance correctly', async () => {
|
|
677
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
678
|
+
mainnet
|
|
679
|
+
]);
|
|
680
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
681
|
+
{
|
|
682
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
683
|
+
chainId: 'eip155:1',
|
|
684
|
+
symbol: 'ETH'
|
|
685
|
+
}
|
|
686
|
+
]);
|
|
687
|
+
vi.spyOn(ChainController, 'getAllApprovedCaipNetworkIds').mockReturnValue(['eip155:1']);
|
|
688
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValueOnce({
|
|
689
|
+
namespace: mainnet.chainNamespace,
|
|
690
|
+
chainId: mainnet.id,
|
|
691
|
+
caipNetworkId: mainnet.caipNetworkId
|
|
692
|
+
});
|
|
693
|
+
const mockAccountData = {
|
|
694
|
+
address: '0x123',
|
|
695
|
+
chainId: mainnet.id,
|
|
696
|
+
chainNamespace: mainnet.chainNamespace
|
|
697
|
+
};
|
|
698
|
+
vi.spyOn(AccountController, 'state', 'get').mockReturnValue(mockAccountData);
|
|
699
|
+
appKit = new AppKit({ ...mockOptions });
|
|
700
|
+
await appKit['syncAccount']({ ...mockAccountData, address: '0x1234' });
|
|
701
|
+
expect(AccountController.fetchTokenBalance).toHaveBeenCalled();
|
|
702
|
+
});
|
|
703
|
+
it('should not sync balance on testnets', async () => {
|
|
704
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
705
|
+
{
|
|
706
|
+
...sepolia,
|
|
707
|
+
nativeCurrency: { symbol: 'sETH' },
|
|
708
|
+
chainNamespace: 'eip155'
|
|
709
|
+
}
|
|
710
|
+
]);
|
|
711
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
712
|
+
{
|
|
713
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
714
|
+
chainId: 'eip155:11155111',
|
|
715
|
+
symbol: 'sETH'
|
|
716
|
+
}
|
|
717
|
+
]);
|
|
718
|
+
vi.spyOn(ChainController, 'getAllApprovedCaipNetworkIds').mockReturnValue(['eip155:11155111']);
|
|
719
|
+
const mockAccountData = {
|
|
720
|
+
address: '0x123',
|
|
721
|
+
chainId: '11155111',
|
|
722
|
+
chainNamespace: 'eip155'
|
|
723
|
+
};
|
|
724
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValueOnce({
|
|
725
|
+
namespace: 'eip155',
|
|
726
|
+
chainId: '11155111',
|
|
727
|
+
caipNetworkId: 'eip155:11155111'
|
|
728
|
+
});
|
|
729
|
+
vi.spyOn(CaipNetworksUtil, 'extendCaipNetworks').mockReturnValueOnce([
|
|
730
|
+
{
|
|
731
|
+
id: '11155111',
|
|
732
|
+
chainNamespace: 'eip155',
|
|
733
|
+
caipNetworkId: 'eip155:11155111',
|
|
734
|
+
testnet: true,
|
|
735
|
+
nativeCurrency: { symbol: 'ETH' }
|
|
736
|
+
}
|
|
737
|
+
]);
|
|
738
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
739
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]]),
|
|
740
|
+
activeChain: 'eip155'
|
|
741
|
+
});
|
|
742
|
+
vi.spyOn(AccountController, 'state', 'get').mockReturnValue(mockAccountData);
|
|
743
|
+
appKit = new AppKit({ ...mockOptions });
|
|
744
|
+
const mockAdapter = {
|
|
745
|
+
getBalance: vi.fn().mockResolvedValue({ balance: '0.00', symbol: 'sETH' })
|
|
746
|
+
};
|
|
747
|
+
vi.mocked(appKit).getAdapter = vi.fn().mockReturnValue(mockAdapter);
|
|
748
|
+
await appKit['syncAccount'](mockAccountData);
|
|
749
|
+
expect(AccountController.fetchTokenBalance).not.toHaveBeenCalled();
|
|
750
|
+
expect(AccountController.setBalance).toHaveBeenCalledWith('0.00', 'sETH', 'eip155');
|
|
751
|
+
});
|
|
752
|
+
it('should disconnect correctly', async () => {
|
|
753
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
754
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]]),
|
|
755
|
+
activeChain: 'eip155'
|
|
756
|
+
});
|
|
757
|
+
const mockRemoveItem = vi.fn();
|
|
758
|
+
vi.spyOn(SafeLocalStorage, 'removeItem').mockImplementation(mockRemoveItem);
|
|
759
|
+
const appKit = new AppKit({
|
|
760
|
+
...mockOptions,
|
|
761
|
+
networks: [base],
|
|
762
|
+
adapters: [mockUniversalAdapter]
|
|
763
|
+
});
|
|
764
|
+
await appKit.disconnect();
|
|
765
|
+
expect(ConnectionController.disconnect).toHaveBeenCalled();
|
|
766
|
+
// TODO: Unmock all of this file and check for AccountController hooks called from ChainController
|
|
767
|
+
});
|
|
768
|
+
it('should not show unsupported chain UI when allowUnsupportedChain is true', async () => {
|
|
769
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
770
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]]),
|
|
771
|
+
activeChain: 'eip155'
|
|
772
|
+
});
|
|
773
|
+
appKit.caipNetworks = [mainnet];
|
|
774
|
+
OptionsController.state.allowUnsupportedChain = undefined;
|
|
775
|
+
vi.spyOn(OptionsController.state, 'allowUnsupportedChain', 'get').mockResolvedValueOnce(true);
|
|
776
|
+
const overrideAdapter = {
|
|
777
|
+
getAccounts: vi.fn().mockResolvedValue({ accounts: [] }),
|
|
778
|
+
syncConnection: vi.fn().mockResolvedValue({
|
|
779
|
+
chainId: 'eip155:999', // Unsupported chain
|
|
780
|
+
address: '0x123',
|
|
781
|
+
accounts: [{ address: '0x123', type: 'eoa' }]
|
|
782
|
+
}),
|
|
783
|
+
getBalance: vi.fn().mockResolvedValue({ balance: '0', symbol: 'ETH' }),
|
|
784
|
+
getProfile: vi.fn().mockResolvedValue({}),
|
|
785
|
+
on: vi.fn(),
|
|
786
|
+
off: vi.fn(),
|
|
787
|
+
emit: vi.fn()
|
|
788
|
+
};
|
|
789
|
+
vi.spyOn(appKit, 'getAdapter').mockReturnValueOnce(overrideAdapter);
|
|
790
|
+
vi.spyOn(appKit, 'setUnsupportedNetwork').mockImplementation(vi.fn());
|
|
791
|
+
vi.spyOn(SafeLocalStorage, 'getItem').mockImplementation((key) => {
|
|
792
|
+
const connectorKey = getSafeConnectorIdKey('eip155');
|
|
793
|
+
if (key === connectorKey) {
|
|
794
|
+
return 'test-wallet';
|
|
795
|
+
}
|
|
796
|
+
if (key === SafeLocalStorageKeys.ACTIVE_CAIP_NETWORK_ID) {
|
|
797
|
+
return 'eip155:1';
|
|
798
|
+
}
|
|
799
|
+
return undefined;
|
|
800
|
+
});
|
|
801
|
+
vi.mocked(ChainController.showUnsupportedChainUI).mockImplementation(vi.fn());
|
|
802
|
+
await appKit.syncExistingConnection();
|
|
803
|
+
expect(ChainController.showUnsupportedChainUI).not.toHaveBeenCalled();
|
|
804
|
+
});
|
|
805
|
+
it('should subscribe to providers', () => {
|
|
806
|
+
const callback = vi.fn();
|
|
807
|
+
const providers = {
|
|
808
|
+
eip155: { provider: {} },
|
|
809
|
+
solana: {},
|
|
810
|
+
polkadot: {},
|
|
811
|
+
bip122: {}
|
|
812
|
+
};
|
|
813
|
+
const mockSubscribeProviders = vi.fn().mockImplementation(cb => {
|
|
814
|
+
cb(providers);
|
|
815
|
+
return () => { };
|
|
816
|
+
});
|
|
817
|
+
// Mock the entire ProviderUtil
|
|
818
|
+
vi.mocked(ProviderUtil).subscribeProviders = mockSubscribeProviders;
|
|
819
|
+
appKit.subscribeProviders(callback);
|
|
820
|
+
expect(mockSubscribeProviders).toHaveBeenCalled();
|
|
821
|
+
expect(callback).toHaveBeenCalledWith(providers);
|
|
822
|
+
});
|
|
823
|
+
});
|
|
824
|
+
describe('syncExistingConnection', () => {
|
|
825
|
+
it('should set status to "connecting" and sync the connection when a connector and namespace are present', async () => {
|
|
826
|
+
vi.spyOn(AccountController, 'state', 'get').mockReturnValueOnce({
|
|
827
|
+
currentTab: 0,
|
|
828
|
+
addressLabels: new Map(),
|
|
829
|
+
allAccounts: []
|
|
830
|
+
});
|
|
831
|
+
vi.mocked(CoreHelperUtil.isClient).mockReturnValueOnce(true);
|
|
832
|
+
vi.spyOn(StorageUtil, 'getActiveNamespace').mockReturnValue('eip155');
|
|
833
|
+
vi.spyOn(StorageUtil, 'getConnectedConnectorId').mockReturnValue('test-connector');
|
|
834
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
835
|
+
activeCaipNetwork: { id: 'eip155:1', chainNamespace: 'eip155' }
|
|
836
|
+
});
|
|
837
|
+
vi.mocked(StorageUtil.getActiveNetworkProps).mockReturnValue({
|
|
838
|
+
namespace: mainnet.chainNamespace,
|
|
839
|
+
chainId: mainnet.id,
|
|
840
|
+
caipNetworkId: mainnet.caipNetworkId
|
|
841
|
+
});
|
|
842
|
+
const mockAdapter = {
|
|
843
|
+
getAccounts: vi.fn().mockResolvedValue({ accounts: [{ address: '0x123', type: 'eoa' }] }),
|
|
844
|
+
syncConnection: vi.fn().mockResolvedValue({
|
|
845
|
+
address: '0x123',
|
|
846
|
+
chainId: mainnet.id,
|
|
847
|
+
chainNamespace: mainnet.chainNamespace,
|
|
848
|
+
accounts: [{ address: '0x123', type: 'eoa' }]
|
|
849
|
+
}),
|
|
850
|
+
on: vi.fn(),
|
|
851
|
+
getBalance: vi.fn().mockResolvedValue({ balance: '0', symbol: 'ETH' })
|
|
852
|
+
};
|
|
853
|
+
vi.spyOn(appKit, 'getAdapter').mockReturnValueOnce(mockAdapter);
|
|
854
|
+
vi.mocked(appKit).chainNamespaces = ['eip155'];
|
|
855
|
+
await appKit['syncExistingConnection']();
|
|
856
|
+
expect(mockAdapter.syncConnection).toHaveBeenCalled();
|
|
857
|
+
expect(AccountController.setStatus).toHaveBeenCalledWith('connecting', 'eip155');
|
|
858
|
+
expect(AccountController.setStatus).toHaveBeenCalledWith('connected', 'eip155');
|
|
859
|
+
});
|
|
860
|
+
it('should set status to "disconnected" when no connector is present', async () => {
|
|
861
|
+
vi.mocked(CoreHelperUtil.isClient).mockReturnValueOnce(true);
|
|
862
|
+
vi.spyOn(StorageUtil, 'getConnectedConnectorId').mockReturnValueOnce(undefined);
|
|
863
|
+
vi.mocked(appKit).chainNamespaces = ['eip155'];
|
|
864
|
+
await appKit['syncExistingConnection']();
|
|
865
|
+
expect(AccountController.setStatus).toHaveBeenCalledWith('disconnected', 'eip155');
|
|
866
|
+
});
|
|
867
|
+
it('should set status to "disconnected" if the connector is set to "AUTH" and the adapter fails to sync', async () => {
|
|
868
|
+
vi.mocked(CoreHelperUtil.isClient).mockReturnValueOnce(true);
|
|
869
|
+
vi.spyOn(SafeLocalStorage, 'getItem').mockImplementation(key => {
|
|
870
|
+
const connectorKey = getSafeConnectorIdKey('eip155');
|
|
871
|
+
if (key === connectorKey) {
|
|
872
|
+
return 'AUTH';
|
|
873
|
+
}
|
|
874
|
+
if (key === SafeLocalStorageKeys.ACTIVE_CAIP_NETWORK_ID) {
|
|
875
|
+
return 'eip155:1';
|
|
876
|
+
}
|
|
877
|
+
return undefined;
|
|
878
|
+
});
|
|
879
|
+
vi.mocked(appKit).chainNamespaces = ['eip155'];
|
|
880
|
+
const mockAdapter = {
|
|
881
|
+
getAccounts: vi.fn().mockResolvedValue({ accounts: [] }),
|
|
882
|
+
syncConnection: vi.fn().mockResolvedValue(null),
|
|
883
|
+
on: vi.fn()
|
|
884
|
+
};
|
|
885
|
+
vi.spyOn(appKit, 'getAdapter').mockReturnValueOnce(mockAdapter);
|
|
886
|
+
await appKit['syncExistingConnection']();
|
|
887
|
+
expect(AccountController.setStatus).toHaveBeenCalledWith('disconnected', 'eip155');
|
|
888
|
+
});
|
|
889
|
+
it('should reconnect to multiple namespaces if previously connected', async () => {
|
|
890
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
891
|
+
chains: new Map(),
|
|
892
|
+
activeChain: 'eip155'
|
|
893
|
+
});
|
|
894
|
+
vi.spyOn(ProviderUtil, 'setProviderId').mockImplementation(vi.fn());
|
|
895
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValue({
|
|
896
|
+
namespace: 'eip155',
|
|
897
|
+
chainId: mainnet.id,
|
|
898
|
+
caipNetworkId: mainnet.caipNetworkId
|
|
899
|
+
});
|
|
900
|
+
vi.spyOn(StorageUtil, 'getConnectedNamespaces').mockReturnValueOnce(['eip155', 'solana']);
|
|
901
|
+
vi.spyOn(StorageUtil, 'getConnectedConnectorId').mockImplementation(namespace => {
|
|
902
|
+
if (namespace === 'eip155') {
|
|
903
|
+
return 'evm-connector';
|
|
904
|
+
}
|
|
905
|
+
return 'solana-connector';
|
|
906
|
+
});
|
|
907
|
+
const mockEvmAdapter = {
|
|
908
|
+
getAccounts: vi.fn().mockResolvedValue({ accounts: [{ address: '0x123', type: 'eoa' }] }),
|
|
909
|
+
syncConnection: vi.fn().mockResolvedValue({
|
|
910
|
+
address: '0x123',
|
|
911
|
+
chainId: mainnet.id,
|
|
912
|
+
chainNamespace: mainnet.chainNamespace,
|
|
913
|
+
accounts: [{ address: '0x123', type: 'eoa' }],
|
|
914
|
+
type: 'EXTERNAL',
|
|
915
|
+
id: 'evm-connector'
|
|
916
|
+
}),
|
|
917
|
+
on: vi.fn()
|
|
918
|
+
};
|
|
919
|
+
const mockSolanaAdapter = {
|
|
920
|
+
getAccounts: vi.fn().mockResolvedValue({ accounts: [{ address: 'Hgbsh1', type: 'eoa' }] }),
|
|
921
|
+
syncConnection: vi.fn().mockResolvedValue({
|
|
922
|
+
address: 'Hgbsh1',
|
|
923
|
+
chainId: solana.id,
|
|
924
|
+
chainNamespace: solana.chainNamespace,
|
|
925
|
+
accounts: [{ address: 'Hgbsh1', type: 'eoa' }],
|
|
926
|
+
type: 'EXTERNAL',
|
|
927
|
+
id: 'solana-connector'
|
|
928
|
+
}),
|
|
929
|
+
on: vi.fn()
|
|
930
|
+
};
|
|
931
|
+
vi.spyOn(appKit, 'getAdapter').mockImplementation(namespace => {
|
|
932
|
+
if (namespace === 'eip155') {
|
|
933
|
+
return mockEvmAdapter;
|
|
934
|
+
}
|
|
935
|
+
return mockSolanaAdapter;
|
|
936
|
+
});
|
|
937
|
+
vi.mocked(appKit).chainNamespaces = ['eip155', 'solana'];
|
|
938
|
+
await appKit['syncExistingConnection']();
|
|
939
|
+
expect(mockEvmAdapter.syncConnection).toHaveBeenCalled();
|
|
940
|
+
expect(mockSolanaAdapter.syncConnection).toHaveBeenCalled();
|
|
941
|
+
expect(mockEvmAdapter.getAccounts).toHaveBeenCalled();
|
|
942
|
+
expect(mockSolanaAdapter.getAccounts).toHaveBeenCalled();
|
|
943
|
+
expect(ProviderUtil.setProviderId).toHaveBeenCalledWith('eip155', 'EXTERNAL');
|
|
944
|
+
expect(ProviderUtil.setProviderId).toHaveBeenCalledWith('solana', 'EXTERNAL');
|
|
945
|
+
expect(StorageUtil.setConnectedConnectorId).toHaveBeenCalledWith('eip155', 'evm-connector');
|
|
946
|
+
expect(StorageUtil.setConnectedConnectorId).toHaveBeenCalledWith('solana', 'solana-connector');
|
|
947
|
+
});
|
|
948
|
+
});
|
|
949
|
+
describe('Base Initialization', () => {
|
|
950
|
+
let appKit;
|
|
951
|
+
let mockAdapter;
|
|
952
|
+
let mockUniversalAdapter;
|
|
953
|
+
beforeEach(() => {
|
|
954
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
955
|
+
chains: new Map(),
|
|
956
|
+
activeChain: 'eip155'
|
|
957
|
+
});
|
|
958
|
+
vi.mocked(ConnectorController).getConnectors = vi.fn().mockReturnValue([]);
|
|
959
|
+
mockAdapter = {
|
|
960
|
+
getAccounts: vi.fn().mockResolvedValue({ accounts: [] }),
|
|
961
|
+
namespace: 'eip155',
|
|
962
|
+
construct: vi.fn(),
|
|
963
|
+
setUniversalProvider: vi.fn(),
|
|
964
|
+
setAuthProvider: vi.fn(),
|
|
965
|
+
syncConnectors: vi.fn(),
|
|
966
|
+
connectors: [],
|
|
967
|
+
on: vi.fn(),
|
|
968
|
+
off: vi.fn(),
|
|
969
|
+
emit: vi.fn(),
|
|
970
|
+
removeAllEventListeners: vi.fn()
|
|
971
|
+
};
|
|
972
|
+
vi.mocked(UniversalAdapter).mockImplementation(() => mockUniversalAdapter);
|
|
973
|
+
appKit = new AppKit({
|
|
974
|
+
...mockOptions,
|
|
975
|
+
adapters: [mockAdapter]
|
|
976
|
+
});
|
|
977
|
+
vi.spyOn(appKit, 'getUniversalProvider').mockResolvedValue({
|
|
978
|
+
on: vi.fn(),
|
|
979
|
+
off: vi.fn(),
|
|
980
|
+
emit: vi.fn()
|
|
981
|
+
});
|
|
982
|
+
});
|
|
983
|
+
it('should call syncConnectors when initializing adapters', async () => {
|
|
984
|
+
const appKit = new AppKit({
|
|
985
|
+
...mockOptions,
|
|
986
|
+
networks: [base],
|
|
987
|
+
adapters: [mockAdapter]
|
|
988
|
+
});
|
|
989
|
+
const initChainAdapters = appKit.initChainAdapters.bind(appKit);
|
|
990
|
+
vi.spyOn(appKit, 'createUniversalProviderForAdapter').mockResolvedValueOnce(undefined);
|
|
991
|
+
vi.spyOn(appKit, 'createAuthProviderForAdapter').mockReturnValueOnce(undefined);
|
|
992
|
+
await initChainAdapters([mockAdapter]);
|
|
993
|
+
expect(mockAdapter.syncConnectors).toHaveBeenCalled();
|
|
994
|
+
});
|
|
995
|
+
it('should create UniversalAdapter when no blueprint is provided for namespace', async () => {
|
|
996
|
+
const appKit = new AppKit({
|
|
997
|
+
...mockOptions,
|
|
998
|
+
networks: [mainnetNetwork],
|
|
999
|
+
adapters: [mockAdapter]
|
|
1000
|
+
});
|
|
1001
|
+
const createAdapters = appKit.createAdapters.bind(appKit);
|
|
1002
|
+
vi.spyOn(appKit, 'createUniversalProvider').mockResolvedValue(undefined);
|
|
1003
|
+
const mockUniversalAdapter = {
|
|
1004
|
+
setUniversalProvider: vi.fn(),
|
|
1005
|
+
setAuthProvider: vi.fn()
|
|
1006
|
+
};
|
|
1007
|
+
vi.mocked(UniversalAdapter).mockImplementation(() => mockUniversalAdapter);
|
|
1008
|
+
const adapters = await createAdapters([]);
|
|
1009
|
+
expect(adapters.eip155).toBeDefined();
|
|
1010
|
+
expect(UniversalAdapter).toHaveBeenCalledWith({
|
|
1011
|
+
namespace: 'eip155',
|
|
1012
|
+
networks: [mainnet]
|
|
1013
|
+
});
|
|
1014
|
+
});
|
|
1015
|
+
it('should initialize UniversalProvider when not provided in options', async () => {
|
|
1016
|
+
vi.spyOn(CoreHelperUtil, 'isClient').mockReturnValue(true);
|
|
1017
|
+
const upSpy = vi.spyOn(UniversalProvider, 'init');
|
|
1018
|
+
new AppKit({
|
|
1019
|
+
...mockOptions,
|
|
1020
|
+
projectId: '123',
|
|
1021
|
+
networks: [mainnet],
|
|
1022
|
+
adapters: [mockAdapter]
|
|
1023
|
+
});
|
|
1024
|
+
// Wait for the promise to fetchIdentity to resolve
|
|
1025
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
1026
|
+
expect(OptionsController.setUsingInjectedUniversalProvider).toHaveBeenCalled();
|
|
1027
|
+
expect(upSpy).toHaveBeenCalled();
|
|
1028
|
+
});
|
|
1029
|
+
it('should not initialize UniversalProvider when provided in options', async () => {
|
|
1030
|
+
vi.spyOn(CoreHelperUtil, 'isClient').mockReturnValue(true);
|
|
1031
|
+
const upSpy = vi.spyOn(UniversalProvider, 'init');
|
|
1032
|
+
new AppKit({
|
|
1033
|
+
...mockOptions,
|
|
1034
|
+
projectId: 'test',
|
|
1035
|
+
networks: [mainnet],
|
|
1036
|
+
universalProvider: mockProvider,
|
|
1037
|
+
adapters: [mockAdapter]
|
|
1038
|
+
});
|
|
1039
|
+
// Wait for the promise to fetchIdentity to resolve
|
|
1040
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
1041
|
+
expect(upSpy).not.toHaveBeenCalled();
|
|
1042
|
+
expect(OptionsController.setUsingInjectedUniversalProvider).toHaveBeenCalled();
|
|
1043
|
+
});
|
|
1044
|
+
it('should initialize multiple adapters for different namespaces', async () => {
|
|
1045
|
+
const mockSolanaAdapter = {
|
|
1046
|
+
namespace: 'solana',
|
|
1047
|
+
construct: vi.fn(),
|
|
1048
|
+
setUniversalProvider: vi.fn(),
|
|
1049
|
+
setAuthProvider: vi.fn(),
|
|
1050
|
+
syncConnectors: vi.fn(),
|
|
1051
|
+
connectors: [],
|
|
1052
|
+
on: vi.fn(),
|
|
1053
|
+
off: vi.fn(),
|
|
1054
|
+
emit: vi.fn()
|
|
1055
|
+
};
|
|
1056
|
+
const appKit = new AppKit({
|
|
1057
|
+
...mockOptions,
|
|
1058
|
+
networks: [mainnet, solana],
|
|
1059
|
+
adapters: [mockSolanaAdapter, mockAdapter]
|
|
1060
|
+
});
|
|
1061
|
+
const createAdapters = appKit.createAdapters.bind(appKit);
|
|
1062
|
+
vi.spyOn(appKit, 'createUniversalProvider').mockResolvedValue(undefined);
|
|
1063
|
+
const adapters = await createAdapters([mockAdapter, mockSolanaAdapter]);
|
|
1064
|
+
expect(mockAdapter.syncConnectors).toHaveBeenCalled();
|
|
1065
|
+
expect(mockSolanaAdapter.syncConnectors).toHaveBeenCalled();
|
|
1066
|
+
expect(adapters.eip155).toBeDefined();
|
|
1067
|
+
expect(adapters.solana).toBeDefined();
|
|
1068
|
+
});
|
|
1069
|
+
it('should set universal provider and auth provider for each adapter', async () => {
|
|
1070
|
+
const appKit = new AppKit({
|
|
1071
|
+
...mockOptions,
|
|
1072
|
+
networks: [mainnet],
|
|
1073
|
+
adapters: [mockAdapter]
|
|
1074
|
+
});
|
|
1075
|
+
const mockUniversalProvider = {
|
|
1076
|
+
on: vi.fn(),
|
|
1077
|
+
off: vi.fn(),
|
|
1078
|
+
emit: vi.fn()
|
|
1079
|
+
};
|
|
1080
|
+
vi.spyOn(appKit, 'initialize').mockResolvedValue(undefined);
|
|
1081
|
+
vi.spyOn(CoreHelperUtil, 'isClient').mockReturnValue(true);
|
|
1082
|
+
vi.spyOn(UniversalProvider, 'init').mockResolvedValue(mockUniversalProvider);
|
|
1083
|
+
const initChainAdapters = appKit.initChainAdapters.bind(appKit);
|
|
1084
|
+
await initChainAdapters([mockAdapter]);
|
|
1085
|
+
expect(mockAdapter.setUniversalProvider).toHaveBeenCalled();
|
|
1086
|
+
expect(mockAdapter.setAuthProvider).toHaveBeenCalled();
|
|
1087
|
+
});
|
|
1088
|
+
});
|
|
1089
|
+
describe('Alert Errors', () => {
|
|
1090
|
+
it('should handle alert errors based on error messages', () => {
|
|
1091
|
+
const errors = [
|
|
1092
|
+
{
|
|
1093
|
+
alert: ErrorUtil.ALERT_ERRORS.INVALID_APP_CONFIGURATION,
|
|
1094
|
+
message: 'Error: WebSocket connection closed abnormally with code: 3000 (Unauthorized: origin not allowed)'
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
alert: ErrorUtil.ALERT_ERRORS.JWT_TOKEN_NOT_VALID,
|
|
1098
|
+
message: 'WebSocket connection closed abnormally with code: 3000 (JWT validation error: JWT Token is not yet valid:)'
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
alert: ErrorUtil.ALERT_ERRORS.INVALID_PROJECT_ID,
|
|
1102
|
+
message: 'Uncaught Error: WebSocket connection closed abnormally with code: 3000 (Unauthorized: invalid key)'
|
|
1103
|
+
}
|
|
1104
|
+
];
|
|
1105
|
+
for (const { alert, message } of errors) {
|
|
1106
|
+
// @ts-expect-error
|
|
1107
|
+
appKit.handleAlertError(new Error(message));
|
|
1108
|
+
expect(AlertController.open).toHaveBeenCalledWith(alert, 'error');
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
});
|
|
1112
|
+
});
|
|
1113
|
+
describe('Listeners', () => {
|
|
1114
|
+
it('should set caip address, profile name and profile image on accountChanged event', async () => {
|
|
1115
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
1116
|
+
{
|
|
1117
|
+
...sepolia,
|
|
1118
|
+
nativeCurrency: { symbol: 'sETH' },
|
|
1119
|
+
chainNamespace: 'eip155'
|
|
1120
|
+
}
|
|
1121
|
+
]);
|
|
1122
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
1123
|
+
{
|
|
1124
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
1125
|
+
chainId: 'eip155:11155111',
|
|
1126
|
+
symbol: 'sETH'
|
|
1127
|
+
}
|
|
1128
|
+
]);
|
|
1129
|
+
vi.spyOn(AccountController, 'state', 'get').mockReturnValue({
|
|
1130
|
+
address: '0x'
|
|
1131
|
+
});
|
|
1132
|
+
vi.spyOn(StorageUtil, 'getActiveNetworkProps').mockReturnValueOnce({
|
|
1133
|
+
namespace: mainnet.chainNamespace,
|
|
1134
|
+
chainId: mainnet.id,
|
|
1135
|
+
caipNetworkId: mainnet.caipNetworkId
|
|
1136
|
+
});
|
|
1137
|
+
const mockAccount = {
|
|
1138
|
+
address: '0x123',
|
|
1139
|
+
chainId: mainnet.id,
|
|
1140
|
+
chainNamespace: mainnet.chainNamespace
|
|
1141
|
+
};
|
|
1142
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1143
|
+
activeChain: mockAccount.chainNamespace,
|
|
1144
|
+
activeCaipAddress: `${mockAccount.chainNamespace}:${mockAccount.chainId}:${mockAccount.address}`,
|
|
1145
|
+
chains: new Map([])
|
|
1146
|
+
});
|
|
1147
|
+
const emitter = new Emitter();
|
|
1148
|
+
const mockAdapter = {
|
|
1149
|
+
namespace: 'eip155',
|
|
1150
|
+
construct: vi.fn(),
|
|
1151
|
+
syncConnectors: vi.fn(),
|
|
1152
|
+
getAccounts: vi.fn().mockResolvedValue({ accounts: [] }),
|
|
1153
|
+
syncConnection: vi.fn(),
|
|
1154
|
+
getBalance: vi.fn().mockResolvedValue({ balance: '0', symbol: 'ETH' }),
|
|
1155
|
+
getProfile: vi.fn(),
|
|
1156
|
+
on: emitter.on,
|
|
1157
|
+
emit: emitter.emit
|
|
1158
|
+
};
|
|
1159
|
+
// Initialize AppKit
|
|
1160
|
+
const appKit = new AppKit({
|
|
1161
|
+
...mockOptions,
|
|
1162
|
+
networks: [mainnet],
|
|
1163
|
+
features: {
|
|
1164
|
+
email: false,
|
|
1165
|
+
socials: []
|
|
1166
|
+
},
|
|
1167
|
+
adapters: [mockAdapter]
|
|
1168
|
+
});
|
|
1169
|
+
const identity = { name: 'vitalik.eth', avatar: null };
|
|
1170
|
+
const setCaipAddressSpy = vi.spyOn(AccountController, 'setCaipAddress');
|
|
1171
|
+
const fetchIdentitySpy = vi
|
|
1172
|
+
.spyOn(BlockchainApiController, 'fetchIdentity')
|
|
1173
|
+
.mockResolvedValueOnce(identity);
|
|
1174
|
+
const setProfileNameSpy = vi.spyOn(appKit, 'setProfileName');
|
|
1175
|
+
const setProfileImageSpy = vi.spyOn(appKit, 'setProfileImage');
|
|
1176
|
+
emitter.emit('accountChanged', mockAccount);
|
|
1177
|
+
expect(setCaipAddressSpy).toHaveBeenCalledWith(`${mockAccount.chainNamespace}:${mockAccount.chainId}:${mockAccount.address}`, 'eip155');
|
|
1178
|
+
// Wait for the promise to fetchIdentity to resolve
|
|
1179
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
1180
|
+
expect(fetchIdentitySpy).toHaveBeenCalledWith({ address: mockAccount.address });
|
|
1181
|
+
expect(setProfileNameSpy).toHaveBeenCalledWith(identity.name, 'eip155');
|
|
1182
|
+
expect(setProfileImageSpy).toHaveBeenCalledWith(identity.avatar, 'eip155');
|
|
1183
|
+
});
|
|
1184
|
+
});
|
|
1185
|
+
describe('Adapter Management', () => {
|
|
1186
|
+
let appKit;
|
|
1187
|
+
let mockAdapter;
|
|
1188
|
+
beforeEach(() => {
|
|
1189
|
+
vi.spyOn(OptionsController, 'getSnapshot').mockReturnValue({ ...OptionsController.state });
|
|
1190
|
+
vi.spyOn(ThemeController, 'getSnapshot').mockReturnValue({ ...ThemeController.state });
|
|
1191
|
+
mockAdapter = {
|
|
1192
|
+
namespace: 'eip155',
|
|
1193
|
+
construct: vi.fn(),
|
|
1194
|
+
setUniversalProvider: vi.fn(),
|
|
1195
|
+
setAuthProvider: vi.fn(),
|
|
1196
|
+
syncConnectors: vi.fn(),
|
|
1197
|
+
connectors: [],
|
|
1198
|
+
on: vi.fn(),
|
|
1199
|
+
off: vi.fn(),
|
|
1200
|
+
emit: vi.fn(),
|
|
1201
|
+
removeAllEventListeners: vi.fn()
|
|
1202
|
+
};
|
|
1203
|
+
appKit = new AppKit({
|
|
1204
|
+
...mockOptions,
|
|
1205
|
+
networks: [mainnet],
|
|
1206
|
+
adapters: [mockAdapter]
|
|
1207
|
+
});
|
|
1208
|
+
appKit.connectionControllerClient = {};
|
|
1209
|
+
appKit.networkControllerClient = {};
|
|
1210
|
+
});
|
|
1211
|
+
describe('addAdapter', () => {
|
|
1212
|
+
it('should add a new adapter successfully', () => {
|
|
1213
|
+
const newAdapter = {
|
|
1214
|
+
namespace: 'solana',
|
|
1215
|
+
construct: vi.fn(),
|
|
1216
|
+
setUniversalProvider: vi.fn(),
|
|
1217
|
+
setAuthProvider: vi.fn(),
|
|
1218
|
+
syncConnectors: vi.fn(),
|
|
1219
|
+
connectors: [],
|
|
1220
|
+
on: vi.fn(),
|
|
1221
|
+
off: vi.fn(),
|
|
1222
|
+
emit: vi.fn()
|
|
1223
|
+
};
|
|
1224
|
+
appKit.addAdapter(newAdapter, [solana]);
|
|
1225
|
+
expect(appKit.chainAdapters?.solana).toBeDefined();
|
|
1226
|
+
expect(appKit.chainNamespaces).toContain('solana');
|
|
1227
|
+
expect(ChainController.addAdapter).toHaveBeenCalledWith(newAdapter, {
|
|
1228
|
+
connectionControllerClient: expect.any(Object),
|
|
1229
|
+
networkControllerClient: expect.any(Object)
|
|
1230
|
+
}, expect.any(Array));
|
|
1231
|
+
});
|
|
1232
|
+
it('should not add adapter if clients are not initialized', () => {
|
|
1233
|
+
const newAdapter = {
|
|
1234
|
+
namespace: 'solana'
|
|
1235
|
+
};
|
|
1236
|
+
appKit.connectionControllerClient = undefined;
|
|
1237
|
+
appKit.networkControllerClient = undefined;
|
|
1238
|
+
appKit.addAdapter(newAdapter, [solana]);
|
|
1239
|
+
expect(appKit.chainAdapters?.solana).toBeUndefined();
|
|
1240
|
+
});
|
|
1241
|
+
it('should not add adapter if chainAdapters is not initialized', () => {
|
|
1242
|
+
vi.spyOn(appKit, 'createAdapter').mockImplementation(() => { });
|
|
1243
|
+
vi.spyOn(appKit, 'initChainAdapter').mockImplementation(() => { });
|
|
1244
|
+
vi.spyOn(ChainController, 'addAdapter').mockImplementation(() => { });
|
|
1245
|
+
const newAdapter = {
|
|
1246
|
+
namespace: 'solana'
|
|
1247
|
+
};
|
|
1248
|
+
appKit.chainAdapters = undefined;
|
|
1249
|
+
appKit.addAdapter(newAdapter, [solana]);
|
|
1250
|
+
expect(appKit.createAdapter).not.toHaveBeenCalled();
|
|
1251
|
+
expect(appKit.initChainAdapter).not.toHaveBeenCalled();
|
|
1252
|
+
expect(ChainController.addAdapter).not.toHaveBeenCalled();
|
|
1253
|
+
});
|
|
1254
|
+
});
|
|
1255
|
+
describe('removeAdapter', () => {
|
|
1256
|
+
it('should remove an existing adapter successfully', () => {
|
|
1257
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1258
|
+
activeCaipAddress: undefined
|
|
1259
|
+
});
|
|
1260
|
+
appKit.removeAdapter('eip155');
|
|
1261
|
+
expect(appKit.chainAdapters?.eip155).toBeUndefined();
|
|
1262
|
+
expect(appKit.chainNamespaces).not.toContain('eip155');
|
|
1263
|
+
expect(mockAdapter.removeAllEventListeners).toHaveBeenCalled();
|
|
1264
|
+
expect(ChainController.removeAdapter).toHaveBeenCalledWith('eip155');
|
|
1265
|
+
expect(ConnectorController.removeAdapter).toHaveBeenCalledWith('eip155');
|
|
1266
|
+
});
|
|
1267
|
+
it('should not remove adapter if user is connected', () => {
|
|
1268
|
+
vi.spyOn(ChainController, 'removeAdapter').mockImplementation(() => { });
|
|
1269
|
+
vi.spyOn(ConnectorController, 'removeAdapter').mockImplementation(() => { });
|
|
1270
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1271
|
+
activeCaipAddress: 'eip155:1:0x123'
|
|
1272
|
+
});
|
|
1273
|
+
appKit.removeAdapter('eip155');
|
|
1274
|
+
expect(appKit.chainAdapters?.eip155).toBeDefined();
|
|
1275
|
+
expect(appKit.chainNamespaces).toContain('eip155');
|
|
1276
|
+
expect(mockAdapter.removeAllEventListeners).not.toHaveBeenCalled();
|
|
1277
|
+
expect(ChainController.removeAdapter).not.toHaveBeenCalled();
|
|
1278
|
+
expect(ConnectorController.removeAdapter).not.toHaveBeenCalled();
|
|
1279
|
+
});
|
|
1280
|
+
it('should not remove adapter if adapter does not exist', () => {
|
|
1281
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1282
|
+
activeCaipAddress: undefined
|
|
1283
|
+
});
|
|
1284
|
+
appKit.removeAdapter('polkadot');
|
|
1285
|
+
expect(ChainController.removeAdapter).not.toHaveBeenCalled();
|
|
1286
|
+
expect(ConnectorController.removeAdapter).not.toHaveBeenCalled();
|
|
1287
|
+
});
|
|
1288
|
+
it('should not remove adapter if chainAdapters is not initialized', () => {
|
|
1289
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1290
|
+
activeCaipAddress: undefined
|
|
1291
|
+
});
|
|
1292
|
+
appKit.chainAdapters = undefined;
|
|
1293
|
+
appKit.removeAdapter('eip155');
|
|
1294
|
+
expect(ChainController.removeAdapter).not.toHaveBeenCalled();
|
|
1295
|
+
expect(ConnectorController.removeAdapter).not.toHaveBeenCalled();
|
|
1296
|
+
});
|
|
1297
|
+
});
|
|
1298
|
+
});
|
|
1299
|
+
describe('Balance sync', () => {
|
|
1300
|
+
beforeEach(() => {
|
|
1301
|
+
vi.resetAllMocks();
|
|
1302
|
+
vi.spyOn(ConstantsUtil, 'BALANCE_SUPPORTED_CHAINS', 'get').mockReturnValue(['eip155', 'solana']);
|
|
1303
|
+
vi.spyOn(OptionsController, 'getSnapshot').mockReturnValue({ ...OptionsController.state });
|
|
1304
|
+
vi.spyOn(ThemeController, 'getSnapshot').mockReturnValue({ ...ThemeController.state });
|
|
1305
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({ ...ChainController.state });
|
|
1306
|
+
});
|
|
1307
|
+
it('should not sync balance if theres no matching caipNetwork', async () => {
|
|
1308
|
+
const appKit = new AppKit({
|
|
1309
|
+
...mockOptions,
|
|
1310
|
+
networks: [mainnet]
|
|
1311
|
+
});
|
|
1312
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([]);
|
|
1313
|
+
await appKit['syncBalance']({
|
|
1314
|
+
address: '0x123',
|
|
1315
|
+
chainId: sepolia.id,
|
|
1316
|
+
chainNamespace: sepolia.chainNamespace
|
|
1317
|
+
});
|
|
1318
|
+
expect(NetworkUtil.getNetworksByNamespace).toHaveBeenCalled();
|
|
1319
|
+
expect(AccountController.fetchTokenBalance).not.toHaveBeenCalled();
|
|
1320
|
+
expect(AccountController.setBalance).not.toHaveBeenCalled();
|
|
1321
|
+
});
|
|
1322
|
+
it('should fetch native balance on testnet', async () => {
|
|
1323
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
1324
|
+
{ ...sepolia, caipNetworkId: 'eip155:11155111', chainNamespace: 'eip155' }
|
|
1325
|
+
]);
|
|
1326
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1327
|
+
chains: new Map([['eip155', { namespace: 'eip155' }]]),
|
|
1328
|
+
activeChain: 'eip155'
|
|
1329
|
+
});
|
|
1330
|
+
vi.spyOn(AccountController, 'state', 'get').mockReturnValue({
|
|
1331
|
+
address: '0x123'
|
|
1332
|
+
});
|
|
1333
|
+
const mockAdapter = {
|
|
1334
|
+
...mockUniversalAdapter,
|
|
1335
|
+
getBalance: vi.fn().mockResolvedValue({ balance: '1.00', symbol: 'sETH' })
|
|
1336
|
+
};
|
|
1337
|
+
const appKit = new AppKit({
|
|
1338
|
+
...mockOptions,
|
|
1339
|
+
adapters: [mockAdapter],
|
|
1340
|
+
networks: [sepolia]
|
|
1341
|
+
});
|
|
1342
|
+
await appKit['syncBalance']({
|
|
1343
|
+
address: '0x123',
|
|
1344
|
+
chainId: sepolia.id,
|
|
1345
|
+
chainNamespace: 'eip155'
|
|
1346
|
+
});
|
|
1347
|
+
expect(NetworkUtil.getNetworksByNamespace).toHaveBeenCalled();
|
|
1348
|
+
expect(AccountController.fetchTokenBalance).not.toHaveBeenCalled();
|
|
1349
|
+
expect(AccountController.setBalance).toHaveBeenCalledWith('1.00', 'sETH', 'eip155');
|
|
1350
|
+
});
|
|
1351
|
+
it('should set the correct native token balance', async () => {
|
|
1352
|
+
vi.spyOn(NetworkUtil, 'getNetworksByNamespace').mockReturnValue([
|
|
1353
|
+
{ ...mainnet, caipNetworkId: 'eip155:1', chainNamespace: 'eip155' }
|
|
1354
|
+
]);
|
|
1355
|
+
vi.spyOn(AccountController, 'fetchTokenBalance').mockResolvedValue([
|
|
1356
|
+
{
|
|
1357
|
+
quantity: { numeric: '1.00', decimals: '18' },
|
|
1358
|
+
chainId: 'eip155:1',
|
|
1359
|
+
symbol: 'ETH'
|
|
1360
|
+
},
|
|
1361
|
+
{
|
|
1362
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
1363
|
+
chainId: 'eip155:137',
|
|
1364
|
+
symbol: 'POL'
|
|
1365
|
+
},
|
|
1366
|
+
{
|
|
1367
|
+
quantity: { numeric: '0.00', decimals: '18' },
|
|
1368
|
+
chainId: 'eip155:1',
|
|
1369
|
+
symbol: 'USDC'
|
|
1370
|
+
}
|
|
1371
|
+
]);
|
|
1372
|
+
const appKit = new AppKit({
|
|
1373
|
+
...mockOptions,
|
|
1374
|
+
networks: [mainnet]
|
|
1375
|
+
});
|
|
1376
|
+
await appKit['syncBalance']({
|
|
1377
|
+
address: '0x123',
|
|
1378
|
+
chainId: mainnet.id,
|
|
1379
|
+
chainNamespace: 'eip155'
|
|
1380
|
+
});
|
|
1381
|
+
expect(NetworkUtil.getNetworksByNamespace).toHaveBeenCalled();
|
|
1382
|
+
expect(AccountController.fetchTokenBalance).toHaveBeenCalled();
|
|
1383
|
+
expect(AccountController.setBalance).toHaveBeenCalledWith('1.00', mainnet.nativeCurrency.symbol, 'eip155');
|
|
1384
|
+
});
|
|
1385
|
+
});
|
|
1386
|
+
describe('WalletConnect Events', () => {
|
|
1387
|
+
let appkit;
|
|
1388
|
+
let universalProvider;
|
|
1389
|
+
let chainChangedCallback;
|
|
1390
|
+
let displayUriCallback;
|
|
1391
|
+
beforeEach(async () => {
|
|
1392
|
+
appkit = new AppKit({
|
|
1393
|
+
...mockOptions,
|
|
1394
|
+
adapters: [],
|
|
1395
|
+
networks: [mainnet]
|
|
1396
|
+
});
|
|
1397
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({});
|
|
1398
|
+
universalProvider = { on: vi.fn() };
|
|
1399
|
+
appkit['universalProvider'] = universalProvider;
|
|
1400
|
+
appkit['caipNetworks'] = mockOptions.networks;
|
|
1401
|
+
appkit['listenWalletConnect']();
|
|
1402
|
+
chainChangedCallback = universalProvider.on.mock.calls.find(([event]) => event === 'chainChanged')?.[1];
|
|
1403
|
+
displayUriCallback = universalProvider.on.mock.calls.find(([event]) => event === 'display_uri')?.[1];
|
|
1404
|
+
});
|
|
1405
|
+
describe('chainChanged', () => {
|
|
1406
|
+
it('should call setUnsupportedNetwork', () => {
|
|
1407
|
+
const setUnsupportedNetworkSpy = vi.spyOn(appkit, 'setUnsupportedNetwork');
|
|
1408
|
+
chainChangedCallback('unknown_chain_id');
|
|
1409
|
+
expect(setUnsupportedNetworkSpy).toHaveBeenCalledWith('unknown_chain_id');
|
|
1410
|
+
});
|
|
1411
|
+
it('should call setCaipNetwork', () => {
|
|
1412
|
+
const setCaipNetworkSpy = vi.spyOn(appkit, 'setCaipNetwork');
|
|
1413
|
+
const newChain = mockOptions.networks[0];
|
|
1414
|
+
// should accept as number
|
|
1415
|
+
chainChangedCallback(newChain.id);
|
|
1416
|
+
expect(setCaipNetworkSpy).toHaveBeenNthCalledWith(1, newChain);
|
|
1417
|
+
// should accept as string
|
|
1418
|
+
ChainController.state.activeCaipNetwork = undefined;
|
|
1419
|
+
chainChangedCallback(newChain.id.toString());
|
|
1420
|
+
expect(setCaipNetworkSpy).toHaveBeenNthCalledWith(2, newChain);
|
|
1421
|
+
});
|
|
1422
|
+
});
|
|
1423
|
+
describe('open', () => {
|
|
1424
|
+
beforeEach(() => {
|
|
1425
|
+
vi.clearAllMocks();
|
|
1426
|
+
vi.spyOn(OptionsController, 'getSnapshot').mockReturnValue({ ...OptionsController.state });
|
|
1427
|
+
vi.spyOn(ThemeController, 'getSnapshot').mockReturnValue({ ...ThemeController.state });
|
|
1428
|
+
});
|
|
1429
|
+
it('should open different views', async () => {
|
|
1430
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1431
|
+
...ChainController.state,
|
|
1432
|
+
activeCaipNetwork: mainnet
|
|
1433
|
+
});
|
|
1434
|
+
const openSpy = vi.spyOn(ModalController, 'open');
|
|
1435
|
+
const views = [
|
|
1436
|
+
'Account',
|
|
1437
|
+
'Connect',
|
|
1438
|
+
'Networks',
|
|
1439
|
+
'ApproveTransaction',
|
|
1440
|
+
'OnRampProviders',
|
|
1441
|
+
'ConnectingWalletConnectBasic',
|
|
1442
|
+
'Swap',
|
|
1443
|
+
'WhatIsAWallet',
|
|
1444
|
+
'WhatIsANetwork',
|
|
1445
|
+
'AllWallets',
|
|
1446
|
+
'WalletSend'
|
|
1447
|
+
];
|
|
1448
|
+
const appkit = new AppKit({
|
|
1449
|
+
...mockOptions,
|
|
1450
|
+
adapters: [],
|
|
1451
|
+
networks: [mainnet]
|
|
1452
|
+
});
|
|
1453
|
+
for (const view of views) {
|
|
1454
|
+
await appkit.open({ view });
|
|
1455
|
+
expect(openSpy).toHaveBeenCalledWith({ view });
|
|
1456
|
+
}
|
|
1457
|
+
});
|
|
1458
|
+
it('should filter connectors by namespace when opening modal', async () => {
|
|
1459
|
+
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
|
|
1460
|
+
...ChainController.state,
|
|
1461
|
+
activeCaipNetwork: mainnet
|
|
1462
|
+
});
|
|
1463
|
+
const openSpy = vi.spyOn(ModalController, 'open');
|
|
1464
|
+
const setFilterByNamespaceSpy = vi.spyOn(ConnectorController, 'setFilterByNamespace');
|
|
1465
|
+
const appkit = new AppKit({
|
|
1466
|
+
...mockOptions,
|
|
1467
|
+
adapters: [],
|
|
1468
|
+
networks: [mainnet]
|
|
1469
|
+
});
|
|
1470
|
+
await appkit.open({ view: 'Connect', namespace: 'eip155' });
|
|
1471
|
+
expect(openSpy).toHaveBeenCalled();
|
|
1472
|
+
expect(setFilterByNamespaceSpy).toHaveBeenCalledWith('eip155');
|
|
1473
|
+
});
|
|
1474
|
+
});
|
|
1475
|
+
describe('display_uri', () => {
|
|
1476
|
+
it('should call openUri', () => {
|
|
1477
|
+
displayUriCallback('mock_uri');
|
|
1478
|
+
expect(ConnectionController.setUri).toHaveBeenCalledWith('mock_uri');
|
|
1479
|
+
});
|
|
1480
|
+
});
|
|
1481
|
+
});
|
|
1482
|
+
//# sourceMappingURL=appkit.test.js.map
|