@portal-hq/web 3.2.2 → 3.3.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.
@@ -0,0 +1,520 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
+ return new (P || (P = Promise))(function (resolve, reject) {
7
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
11
+ });
12
+ };
13
+ import Portal, { BackupMethods, GetTransactionsOrder } from '.';
14
+ import { mockAddress, mockBackupConfig, mockBlockHashResponse, mockCipherText, mockClientResponse, mockEip155Address, mockEjectResult, mockEthRpcUrl, mockEthTransaction, mockMpcBackupResponse, mockOrgBackupShare, mockQuoteArgs, mockRpcConfig, mockSharesOnDevice, mockSignedHash, mockSolanaAddress, mockSolRpcUrl, } from './__mocks/constants';
15
+ import mpcMock from './__mocks/portal/mpc';
16
+ import providerMock from './__mocks/portal/provider';
17
+ /**
18
+ * context -
19
+ * https://github.com/jestjs/jest/issues/4422
20
+ * https://github.com/anza-xyz/solana-pay/issues/106
21
+ * */
22
+ const originalUint8ArrayHasInstance = Uint8Array[Symbol.hasInstance];
23
+ beforeAll(() => {
24
+ Object.defineProperty(Uint8Array, Symbol.hasInstance, {
25
+ value(potentialInstance) {
26
+ return (originalUint8ArrayHasInstance.call(this, potentialInstance) ||
27
+ Buffer.isBuffer(potentialInstance));
28
+ },
29
+ });
30
+ });
31
+ afterAll(() => {
32
+ Object.defineProperty(Uint8Array, Symbol.hasInstance, originalUint8ArrayHasInstance);
33
+ });
34
+ describe('Portal', () => {
35
+ let portal;
36
+ beforeEach(() => {
37
+ jest.clearAllMocks();
38
+ portal = new Portal({
39
+ rpcConfig: Object.assign(Object.assign({}, mockRpcConfig), {
40
+ // for testing -
41
+ // @ts-ignore-next-line
42
+ 'incorrect-config': { test: 'test' } }),
43
+ });
44
+ portal.mpc = mpcMock;
45
+ portal.provider = providerMock;
46
+ });
47
+ describe('clearLocalWallet', () => {
48
+ it('should call mpc.clearLocalWallet', () => __awaiter(void 0, void 0, void 0, function* () {
49
+ yield portal.clearLocalWallet();
50
+ expect(portal.mpc.clearLocalWallet).toHaveBeenCalledTimes(1);
51
+ }));
52
+ });
53
+ describe('createWallet', () => {
54
+ it('should successfully generate a wallet and call mpc.generate correctly', () => __awaiter(void 0, void 0, void 0, function* () {
55
+ const mockProgressFn = jest.fn();
56
+ const res = yield portal.createWallet(mockProgressFn);
57
+ expect(res).toBe(mockAddress);
58
+ expect(portal.mpc.generate).toHaveBeenCalledTimes(1);
59
+ expect(portal.mpc.generate).toHaveBeenCalledWith({
60
+ host: 'web.portalhq.io',
61
+ mpcVersion: 'v6',
62
+ featureFlags: {},
63
+ }, mockProgressFn);
64
+ }));
65
+ it('should successfully generate a wallet and call mpc.generate correctly with custom constructor args', () => __awaiter(void 0, void 0, void 0, function* () {
66
+ portal = new Portal({
67
+ rpcConfig: mockRpcConfig,
68
+ featureFlags: { isMultiBackupEnabled: true },
69
+ host: 'test-host',
70
+ });
71
+ portal.mpc = mpcMock;
72
+ portal.provider = providerMock;
73
+ const mockProgressFn = jest.fn();
74
+ const res = yield portal.createWallet(mockProgressFn);
75
+ expect(res).toBe(mockAddress);
76
+ expect(portal.mpc.generate).toHaveBeenCalledTimes(1);
77
+ expect(portal.mpc.generate).toHaveBeenCalledWith({
78
+ host: 'test-host',
79
+ mpcVersion: 'v6',
80
+ featureFlags: { isMultiBackupEnabled: true },
81
+ }, mockProgressFn);
82
+ }));
83
+ });
84
+ describe('backupWallet', () => {
85
+ it('should successfully backup a wallet and call mpc.backup correctly', () => __awaiter(void 0, void 0, void 0, function* () {
86
+ const mockProgressFn = jest.fn();
87
+ const res = yield portal.backupWallet(BackupMethods.gdrive, mockProgressFn, mockBackupConfig);
88
+ expect(res).toBe(mockMpcBackupResponse);
89
+ expect(portal.mpc.backup).toHaveBeenCalledTimes(1);
90
+ expect(portal.mpc.backup).toHaveBeenCalledWith({
91
+ backupMethod: BackupMethods.gdrive,
92
+ backupConfigs: mockBackupConfig,
93
+ host: 'web.portalhq.io',
94
+ mpcVersion: 'v6',
95
+ featureFlags: {},
96
+ }, mockProgressFn);
97
+ }));
98
+ it('should successfully backup a wallet and call mpc.backup correctly with custom constructor args', () => __awaiter(void 0, void 0, void 0, function* () {
99
+ portal = new Portal({
100
+ rpcConfig: mockRpcConfig,
101
+ featureFlags: { isMultiBackupEnabled: true },
102
+ host: 'test-host',
103
+ });
104
+ portal.mpc = mpcMock;
105
+ portal.provider = providerMock;
106
+ const mockProgressFn = jest.fn();
107
+ const res = yield portal.backupWallet(BackupMethods.passkey, mockProgressFn, mockBackupConfig);
108
+ expect(res).toBe(mockMpcBackupResponse);
109
+ expect(portal.mpc.backup).toHaveBeenCalledTimes(1);
110
+ expect(portal.mpc.backup).toHaveBeenCalledWith({
111
+ backupMethod: BackupMethods.passkey,
112
+ backupConfigs: mockBackupConfig,
113
+ host: 'test-host',
114
+ mpcVersion: 'v6',
115
+ featureFlags: { isMultiBackupEnabled: true },
116
+ }, mockProgressFn);
117
+ }));
118
+ });
119
+ describe('recoverWallet', () => {
120
+ it('should successfully recover a wallet and call mpc.recover correctly', () => __awaiter(void 0, void 0, void 0, function* () {
121
+ const mockProgressFn = jest.fn();
122
+ const res = yield portal.recoverWallet(mockCipherText, BackupMethods.password, mockBackupConfig, mockProgressFn);
123
+ expect(res).toBe(mockAddress);
124
+ expect(portal.mpc.recover).toHaveBeenCalledTimes(1);
125
+ expect(portal.mpc.recover).toHaveBeenCalledWith({
126
+ cipherText: mockCipherText,
127
+ backupMethod: BackupMethods.password,
128
+ backupConfigs: mockBackupConfig,
129
+ host: 'web.portalhq.io',
130
+ mpcVersion: 'v6',
131
+ featureFlags: {},
132
+ }, mockProgressFn);
133
+ }));
134
+ it('should successfully recover a wallet and call mpc.recover correctly with custom constructor args', () => __awaiter(void 0, void 0, void 0, function* () {
135
+ portal = new Portal({
136
+ rpcConfig: mockRpcConfig,
137
+ featureFlags: { isMultiBackupEnabled: true },
138
+ host: 'test-host',
139
+ });
140
+ portal.mpc = mpcMock;
141
+ portal.provider = providerMock;
142
+ const mockProgressFn = jest.fn();
143
+ const res = yield portal.recoverWallet(mockCipherText, BackupMethods.password, mockBackupConfig, mockProgressFn);
144
+ expect(res).toBe(mockAddress);
145
+ expect(portal.mpc.recover).toHaveBeenCalledTimes(1);
146
+ expect(portal.mpc.recover).toHaveBeenCalledWith({
147
+ cipherText: mockCipherText,
148
+ backupMethod: BackupMethods.password,
149
+ backupConfigs: mockBackupConfig,
150
+ host: 'test-host',
151
+ mpcVersion: 'v6',
152
+ featureFlags: { isMultiBackupEnabled: true },
153
+ }, mockProgressFn);
154
+ }));
155
+ });
156
+ describe('provisionWallet', () => {
157
+ it('should successfully generate a wallet and call mpc.recover correctly', () => __awaiter(void 0, void 0, void 0, function* () {
158
+ const mockProgressFn = jest.fn();
159
+ const res = yield portal.provisionWallet(mockCipherText, BackupMethods.password, mockBackupConfig, mockProgressFn);
160
+ expect(res).toBe(mockAddress);
161
+ expect(portal.mpc.recover).toHaveBeenCalledTimes(1);
162
+ expect(portal.mpc.recover).toHaveBeenCalledWith({
163
+ cipherText: mockCipherText,
164
+ backupMethod: BackupMethods.password,
165
+ backupConfigs: mockBackupConfig,
166
+ host: 'web.portalhq.io',
167
+ mpcVersion: 'v6',
168
+ featureFlags: {},
169
+ }, mockProgressFn);
170
+ }));
171
+ it('should successfully generate a wallet and call mpc.recover correctly with custom constructor args', () => __awaiter(void 0, void 0, void 0, function* () {
172
+ portal = new Portal({
173
+ rpcConfig: mockRpcConfig,
174
+ featureFlags: { isMultiBackupEnabled: true },
175
+ host: 'test-host',
176
+ });
177
+ portal.mpc = mpcMock;
178
+ portal.provider = providerMock;
179
+ const mockProgressFn = jest.fn();
180
+ const res = yield portal.provisionWallet(mockCipherText, BackupMethods.password, mockBackupConfig, mockProgressFn);
181
+ expect(res).toBe(mockAddress);
182
+ expect(portal.mpc.recover).toHaveBeenCalledTimes(1);
183
+ expect(portal.mpc.recover).toHaveBeenCalledWith({
184
+ cipherText: mockCipherText,
185
+ backupMethod: BackupMethods.password,
186
+ backupConfigs: mockBackupConfig,
187
+ host: 'test-host',
188
+ mpcVersion: 'v6',
189
+ featureFlags: { isMultiBackupEnabled: true },
190
+ }, mockProgressFn);
191
+ }));
192
+ });
193
+ describe('eject', () => {
194
+ it('should successfully eject a wallet when backup with portal is enabled', () => __awaiter(void 0, void 0, void 0, function* () {
195
+ const res = yield portal.eject(BackupMethods.password, mockBackupConfig);
196
+ expect(res).toEqual(mockEjectResult);
197
+ expect(portal.mpc.eject).toHaveBeenCalledTimes(1);
198
+ expect(portal.mpc.eject).toHaveBeenCalledWith({
199
+ cipherText: '',
200
+ backupMethod: BackupMethods.password,
201
+ backupConfigs: mockBackupConfig,
202
+ organizationBackupShare: '',
203
+ host: 'web.portalhq.io',
204
+ mpcVersion: 'v6',
205
+ featureFlags: {},
206
+ });
207
+ }));
208
+ it('should successfully eject a wallet when backup with portal is not enabled', () => __awaiter(void 0, void 0, void 0, function* () {
209
+ portal.mpc.getClient = portal.mpc.getClient.mockResolvedValueOnce(Object.assign(Object.assign({}, mockClientResponse), { environment: Object.assign(Object.assign({}, mockClientResponse.environment), { backupWithPortalEnabled: false }) }));
210
+ const res = yield portal.eject(BackupMethods.password, mockBackupConfig, mockOrgBackupShare, mockCipherText);
211
+ expect(res).toEqual(mockEjectResult);
212
+ expect(portal.mpc.eject).toHaveBeenCalledTimes(1);
213
+ expect(portal.mpc.eject).toHaveBeenCalledWith({
214
+ cipherText: mockCipherText,
215
+ organizationBackupShare: mockOrgBackupShare,
216
+ backupMethod: BackupMethods.password,
217
+ backupConfigs: mockBackupConfig,
218
+ host: 'web.portalhq.io',
219
+ mpcVersion: 'v6',
220
+ featureFlags: {},
221
+ });
222
+ }));
223
+ it('should error out if client could not be found', () => __awaiter(void 0, void 0, void 0, function* () {
224
+ portal.mpc.getClient = portal.mpc.getClient.mockResolvedValueOnce(null);
225
+ yield expect(portal.eject(BackupMethods.password, mockBackupConfig, mockOrgBackupShare, mockCipherText)).rejects.toThrowError(new Error('Client not found.'));
226
+ }));
227
+ it('should error if clientBackupCipherText was not supplied when backup with portal is not enabled', () => __awaiter(void 0, void 0, void 0, function* () {
228
+ portal.mpc.getClient = portal.mpc.getClient.mockResolvedValueOnce(Object.assign(Object.assign({}, mockClientResponse), { environment: Object.assign(Object.assign({}, mockClientResponse.environment), { backupWithPortalEnabled: false }) }));
229
+ yield expect(portal.eject(BackupMethods.password, mockBackupConfig)).rejects.toThrowError(new Error('clientBackupCipherText cannot be empty string.'));
230
+ }));
231
+ it('should error if orgBackupShare was empty when backup with portal is not enabled', () => __awaiter(void 0, void 0, void 0, function* () {
232
+ portal.mpc.getClient = portal.mpc.getClient.mockResolvedValueOnce(Object.assign(Object.assign({}, mockClientResponse), { environment: Object.assign(Object.assign({}, mockClientResponse.environment), { backupWithPortalEnabled: false }) }));
233
+ yield expect(portal.eject(BackupMethods.password, mockBackupConfig, '', mockCipherText)).rejects.toThrowError(new Error('orgBackupShare cannot be empty string.'));
234
+ }));
235
+ });
236
+ describe('getEip155Address', () => {
237
+ it("should return the wallet's eip155 address correctly", () => __awaiter(void 0, void 0, void 0, function* () {
238
+ const res = yield portal.getEip155Address();
239
+ expect(res).toBe(mockEip155Address);
240
+ }));
241
+ });
242
+ describe('getSolanaAddress', () => {
243
+ it("should return the wallet's solana address correctly", () => __awaiter(void 0, void 0, void 0, function* () {
244
+ const res = yield portal.getSolanaAddress();
245
+ expect(res).toBe(mockSolanaAddress);
246
+ }));
247
+ });
248
+ describe('doesWalletExist', () => {
249
+ it('should successfully return if wallets exist', () => __awaiter(void 0, void 0, void 0, function* () {
250
+ const res = yield portal.doesWalletExist();
251
+ expect(res).toBe(mockClientResponse.wallets.length > 0);
252
+ }));
253
+ it('should successfully return if wallets exist for a specific chain', () => __awaiter(void 0, void 0, void 0, function* () {
254
+ expect(yield portal.doesWalletExist('eip155:1')).toBe(!!mockClientResponse.metadata.namespaces['eip155']);
255
+ expect(yield portal.doesWalletExist('unsupported:chain')).toBe(false);
256
+ }));
257
+ });
258
+ describe('isWalletOnDevice', () => {
259
+ it('should successfully check if wallet is on device', () => __awaiter(void 0, void 0, void 0, function* () {
260
+ const res = yield portal.isWalletOnDevice();
261
+ expect(res).toBe(mockSharesOnDevice.ED25519 && mockSharesOnDevice.SECP256K1);
262
+ }));
263
+ it('should successfully check if wallet is on device for a specific chain', () => __awaiter(void 0, void 0, void 0, function* () {
264
+ expect(yield portal.isWalletOnDevice('eip155:1')).toBe(mockSharesOnDevice.SECP256K1);
265
+ expect(yield portal.isWalletOnDevice('unsupported:chain')).toBe(false);
266
+ }));
267
+ });
268
+ describe('isWalletBackedUp', () => {
269
+ it('should successfully check if wallet is backed up', () => __awaiter(void 0, void 0, void 0, function* () {
270
+ const res = yield portal.isWalletBackedUp();
271
+ expect(res).toBe(true);
272
+ }));
273
+ it('should successfully check if wallet is backed up for a specific chain', () => __awaiter(void 0, void 0, void 0, function* () {
274
+ expect(yield portal.isWalletBackedUp('eip155:1')).toBe(true);
275
+ expect(yield portal.isWalletBackedUp('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')).toBe(false);
276
+ expect(yield portal.isWalletBackedUp('unsupported:chain')).toBe(false);
277
+ }));
278
+ });
279
+ describe('sendSol', () => {
280
+ beforeEach(() => {
281
+ portal.address = mockSolanaAddress;
282
+ });
283
+ it('should successfully send sol', () => __awaiter(void 0, void 0, void 0, function* () {
284
+ portal.provider.request = portal.provider.request
285
+ .mockResolvedValueOnce(mockBlockHashResponse)
286
+ .mockResolvedValueOnce(mockSignedHash);
287
+ const result = yield portal.sendSol({
288
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
289
+ to: '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
290
+ lamports: 10000,
291
+ });
292
+ expect(result).toBe(mockSignedHash);
293
+ expect(portal.provider.request).toHaveBeenCalledTimes(2);
294
+ expect(portal.provider.request.mock.calls[0]).toEqual([
295
+ {
296
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
297
+ method: 'getLatestBlockhash',
298
+ params: [],
299
+ },
300
+ ]);
301
+ expect(portal.provider.request.mock.calls[1]).toEqual([
302
+ {
303
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
304
+ method: 'sol_signAndSendTransaction',
305
+ params: [
306
+ {
307
+ message: {
308
+ accountKeys: [
309
+ mockSolanaAddress,
310
+ '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
311
+ '11111111111111111111111111111111',
312
+ ],
313
+ header: {
314
+ numReadonlySignedAccounts: 0,
315
+ numReadonlyUnsignedAccounts: 1,
316
+ numRequiredSignatures: 1,
317
+ },
318
+ instructions: [
319
+ {
320
+ accounts: [0, 1],
321
+ // @solana/web3.js/src/programs/system.ts > .transfer > encodeData
322
+ data: '3Bxs43ZMjSRQLs6o',
323
+ programIdIndex: 2,
324
+ },
325
+ ],
326
+ recentBlockhash: mockBlockHashResponse.value.blockhash,
327
+ },
328
+ signatures: null,
329
+ },
330
+ ],
331
+ },
332
+ ]);
333
+ }));
334
+ it('should throw an error if the chainId is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
335
+ yield expect(portal.sendSol({
336
+ chainId: 'eip155:1',
337
+ to: '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
338
+ lamports: 10000,
339
+ })).rejects.toThrow(new Error('[Portal] Invalid chainId. Please provide a chainId that starts with "solana:"'));
340
+ }));
341
+ it('should throw an error if the to address is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
342
+ yield expect(portal.sendSol({
343
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
344
+ to: 'test',
345
+ lamports: 10000,
346
+ })).rejects.toThrow(new Error('[Portal] Invalid "to" Solana address provided, must be 44 characters'));
347
+ }));
348
+ it('should throw an error if the lamports arg is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
349
+ yield expect(portal.sendSol({
350
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
351
+ to: '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
352
+ lamports: -32,
353
+ })).rejects.toThrow(new Error('[Portal] Invalid lamports amount, must be a positive number greater than 0'));
354
+ }));
355
+ it('should throw an error if the latest blockhash could not be fetched', () => __awaiter(void 0, void 0, void 0, function* () {
356
+ portal.provider.request = portal.provider.request.mockResolvedValueOnce({ error: 'test' });
357
+ yield expect(portal.sendSol({
358
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
359
+ to: '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
360
+ lamports: 10000,
361
+ })).rejects.toThrow(new Error('[Portal] Failed to get most recent blockhash'));
362
+ }));
363
+ it('should throw an error if rpc url was empty for the chain', () => __awaiter(void 0, void 0, void 0, function* () {
364
+ portal = new Portal({
365
+ rpcConfig: {
366
+ 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1': '',
367
+ },
368
+ });
369
+ portal.address = mockSolanaAddress;
370
+ portal.mpc = mpcMock;
371
+ portal.provider = providerMock;
372
+ portal.provider.request = portal.provider.request.mockResolvedValueOnce(mockBlockHashResponse);
373
+ yield expect(portal.sendSol({
374
+ chainId: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
375
+ to: '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
376
+ lamports: 10000,
377
+ })).rejects.toThrow(new Error('[Portal] No RPC endpoint configured for chainId'));
378
+ }));
379
+ it("should throw an error if client's solana address could not be fetched", () => __awaiter(void 0, void 0, void 0, function* () {
380
+ portal.provider.request = portal.provider.request.mockResolvedValueOnce(mockBlockHashResponse);
381
+ portal.mpc.getClient = portal.mpc.getClient.mockResolvedValueOnce(null);
382
+ yield expect(portal.sendSol({
383
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
384
+ to: '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
385
+ lamports: 10000,
386
+ })).rejects.toThrow(new Error('[Portal] Failed to get Solana address'));
387
+ }));
388
+ it("should throw an error if txn hash wasn't returned from the provider", () => __awaiter(void 0, void 0, void 0, function* () {
389
+ portal.provider.request = portal.provider.request
390
+ .mockResolvedValueOnce(mockBlockHashResponse)
391
+ .mockResolvedValueOnce(null);
392
+ yield expect(portal.sendSol({
393
+ chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
394
+ to: '9G2CRh8pzicbRkiNLh8Xsp2DEP28UhwtHSyqetGYTCWD',
395
+ lamports: 10000,
396
+ })).rejects.toThrow(new Error('[Portal] Failed to send Solana transaction'));
397
+ }));
398
+ });
399
+ describe('sendEth', () => {
400
+ it('should correctly call provider.request', () => __awaiter(void 0, void 0, void 0, function* () {
401
+ portal.address = mockAddress;
402
+ yield portal.sendEth({
403
+ chainId: 'eip155:1',
404
+ to: 'test',
405
+ value: '42',
406
+ });
407
+ expect(portal.provider.request).toHaveBeenCalledTimes(1);
408
+ expect(portal.provider.request).toHaveBeenCalledWith({
409
+ chainId: 'eip155:1',
410
+ method: 'eth_sendTransaction',
411
+ params: [
412
+ {
413
+ from: mockAddress,
414
+ to: 'test',
415
+ value: '42',
416
+ },
417
+ ],
418
+ });
419
+ }));
420
+ });
421
+ describe('getBalances', () => {
422
+ it('should correctly call mpc.getBalances', () => __awaiter(void 0, void 0, void 0, function* () {
423
+ yield portal.getBalances('eip155:1');
424
+ expect(portal.mpc.getBalances).toHaveBeenCalledTimes(1);
425
+ expect(portal.mpc.getBalances).toHaveBeenCalledWith('eip155:1');
426
+ }));
427
+ });
428
+ describe('getClient', () => {
429
+ it('should correctly call mpc.getClient', () => __awaiter(void 0, void 0, void 0, function* () {
430
+ yield portal.getClient();
431
+ expect(portal.mpc.getClient).toHaveBeenCalledTimes(1);
432
+ expect(portal.mpc.getClient).toHaveBeenCalledWith();
433
+ }));
434
+ });
435
+ describe('getNFTs', () => {
436
+ it('should correctly call mpc.getNFTs', () => __awaiter(void 0, void 0, void 0, function* () {
437
+ yield portal.getNFTs('eip155:1');
438
+ expect(portal.mpc.getNFTs).toHaveBeenCalledTimes(1);
439
+ expect(portal.mpc.getNFTs).toHaveBeenCalledWith('eip155:1');
440
+ }));
441
+ });
442
+ describe('getTransactions', () => {
443
+ it('should correctly call mpc.getTransactions', () => __awaiter(void 0, void 0, void 0, function* () {
444
+ yield portal.getTransactions('eip155:1', 1, 10, GetTransactionsOrder.DESC);
445
+ expect(portal.mpc.getTransactions).toHaveBeenCalledTimes(1);
446
+ expect(portal.mpc.getTransactions).toHaveBeenCalledWith('eip155:1', 1, 10, GetTransactionsOrder.DESC);
447
+ }));
448
+ });
449
+ describe('simulateTransaction', () => {
450
+ it('should correctly call mpc.simulateTransaction', () => __awaiter(void 0, void 0, void 0, function* () {
451
+ yield portal.simulateTransaction('eip155:1', mockEthTransaction);
452
+ expect(portal.mpc.simulateTransaction).toHaveBeenCalledTimes(1);
453
+ expect(portal.mpc.simulateTransaction).toHaveBeenCalledWith(mockEthTransaction, 'eip155:1');
454
+ }));
455
+ });
456
+ describe('evaluateTransaction', () => {
457
+ it('should correctly call mpc.evaluateTransaction', () => __awaiter(void 0, void 0, void 0, function* () {
458
+ yield portal.evaluateTransaction('eip155:1', mockEthTransaction, 'validation');
459
+ expect(portal.mpc.evaluateTransaction).toHaveBeenCalledTimes(1);
460
+ expect(portal.mpc.evaluateTransaction).toHaveBeenCalledWith('eip155:1', mockEthTransaction, 'validation');
461
+ }));
462
+ });
463
+ describe('buildTransaction', () => {
464
+ it('should correctly call mpc.buildTransaction', () => __awaiter(void 0, void 0, void 0, function* () {
465
+ yield portal.buildTransaction('eip155:1', mockAddress, 'USDC', '1');
466
+ expect(portal.mpc.buildTransaction).toHaveBeenCalledTimes(1);
467
+ expect(portal.mpc.buildTransaction).toHaveBeenCalledWith('eip155:1', mockAddress, 'USDC', '1');
468
+ }));
469
+ });
470
+ describe('getNFTAssets', () => {
471
+ it('should correctly call mpc.getNFTAssets', () => __awaiter(void 0, void 0, void 0, function* () {
472
+ yield portal.getNFTAssets('eip155:1');
473
+ expect(portal.mpc.getNFTAssets).toHaveBeenCalledTimes(1);
474
+ expect(portal.mpc.getNFTAssets).toHaveBeenCalledWith('eip155:1');
475
+ }));
476
+ });
477
+ describe('getAssets', () => {
478
+ it('should correctly call mpc.getAssets', () => __awaiter(void 0, void 0, void 0, function* () {
479
+ yield portal.getAssets('eip155:1');
480
+ expect(portal.mpc.getAssets).toHaveBeenCalledTimes(1);
481
+ expect(portal.mpc.getAssets).toHaveBeenCalledWith('eip155:1', false);
482
+ }));
483
+ });
484
+ describe('getQuote', () => {
485
+ it('should correctly call mpc.getQuote', () => __awaiter(void 0, void 0, void 0, function* () {
486
+ yield portal.getQuote('test', mockQuoteArgs, 'eip155:1');
487
+ expect(portal.mpc.getQuote).toHaveBeenCalledTimes(1);
488
+ expect(portal.mpc.getQuote).toHaveBeenCalledWith('test', mockQuoteArgs, 'eip155:1');
489
+ }));
490
+ });
491
+ describe('getSources', () => {
492
+ it('should correctly call mpc.getSources', () => __awaiter(void 0, void 0, void 0, function* () {
493
+ yield portal.getSources('test', 'eip155:1');
494
+ expect(portal.mpc.getSources).toHaveBeenCalledTimes(1);
495
+ expect(portal.mpc.getSources).toHaveBeenCalledWith('test', 'eip155:1');
496
+ }));
497
+ });
498
+ describe('storedClientBackupShare', () => {
499
+ it('should correctly call mpc.storedClientBackupShare', () => __awaiter(void 0, void 0, void 0, function* () {
500
+ yield portal.storedClientBackupShare(true, BackupMethods.password);
501
+ expect(portal.mpc.storedClientBackupShare).toHaveBeenCalledTimes(1);
502
+ expect(portal.mpc.storedClientBackupShare).toHaveBeenCalledWith(true, BackupMethods.password);
503
+ }));
504
+ });
505
+ describe('getRpcUrl', () => {
506
+ it('should return the correct rpc url for the given chainId', () => {
507
+ expect(portal.getRpcUrl('eip155:1')).toEqual(mockEthRpcUrl);
508
+ expect(portal.getRpcUrl('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')).toEqual(mockSolRpcUrl);
509
+ });
510
+ it('should throw an error if the chainId is not provided', () => {
511
+ expect(() => portal.getRpcUrl()).toThrow(new Error('[Portal] No chainId provided. Please provide a chainId to get the RPC endpoint'));
512
+ });
513
+ it('should throw an error if the chainId is not present in the rpc config', () => {
514
+ expect(() => portal.getRpcUrl('test')).toThrow(new Error('[Portal] No RPC endpoint configured for chainId: test'));
515
+ });
516
+ it('should throw an error if the chainId is not present in the rpc config', () => {
517
+ expect(() => portal.getRpcUrl('incorrect-config')).toThrow(new Error('[Portal] Could not find a valid rpcConfig entry for chainId: incorrect-config'));
518
+ });
519
+ });
520
+ });
@@ -59,7 +59,7 @@ export class MpcError extends Error {
59
59
  // Init the actual error
60
60
  super(error.message(context));
61
61
  // Custom error context
62
- this.code = (error === null || error === void 0 ? void 0 : error.code) || 999;
62
+ this.code = (error === null || error === void 0 ? void 0 : error.code) || '999';
63
63
  if (context) {
64
64
  this.context = context;
65
65
  }