@portal-hq/web 3.3.4-beta.1 → 3.3.5-alpha

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Portal MPC Support for Web",
4
4
  "author": "Portal Labs, Inc.",
5
5
  "homepage": "https://portalhq.io/",
6
- "version": "3.3.4-beta.1",
6
+ "version": "3.3.5-alpha",
7
7
  "license": "MIT",
8
8
  "main": "lib/commonjs/index",
9
9
  "module": "lib/esm/index",
@@ -84,10 +84,18 @@ export const mockClientResponse = {
84
84
 
85
85
  export const mockEjectResult = {
86
86
  SECP256K1: 'test',
87
- ED25519: 'test',
87
+ }
88
+ export const mockEjectPrivateKeysResult = {
89
+ SECP256K1: 'test-SECP256K1',
90
+ ED25519: 'test-ED25519',
88
91
  }
89
92
 
90
93
  export const mockOrgBackupShare = 'test-org-share'
94
+ export const mockOrgBackupShares = {
95
+ SECP256K1: 'test-SECP256K1-org-share',
96
+ ED25519: 'test-ED25519-org-share',
97
+ }
98
+
91
99
  export const mockSharesOnDevice = {
92
100
  SECP256K1: true,
93
101
  ED25519: false,
@@ -133,7 +141,7 @@ export const mockGenerateResponse = {
133
141
  },
134
142
  }
135
143
  export const mockBackupResponse = {
136
- cipherText: mockCipherText
144
+ cipherText: mockCipherText,
137
145
  }
138
146
 
139
147
  export const mockContent = 'test-content'
@@ -2,6 +2,7 @@ import {
2
2
  mockAddress,
3
3
  mockClientResponse,
4
4
  mockEjectResult,
5
+ mockEjectPrivateKeysResult,
5
6
  mockMpcBackupResponse,
6
7
  mockSharesOnDevice,
7
8
  mockSignedHash,
@@ -22,6 +23,9 @@ mpcMock.backup = jest.fn().mockResolvedValue(mockMpcBackupResponse)
22
23
  mpcMock.recover = jest.fn().mockResolvedValue(mockAddress)
23
24
  mpcMock.getClient = jest.fn().mockResolvedValue(mockClientResponse)
24
25
  mpcMock.eject = jest.fn().mockResolvedValue(mockEjectResult)
26
+ mpcMock.ejectPrivateKeys = jest
27
+ .fn()
28
+ .mockResolvedValue(mockEjectPrivateKeysResult)
25
29
  mpcMock.checkSharesOnDevice = jest.fn().mockResolvedValue(mockSharesOnDevice)
26
30
 
27
31
  export default mpcMock as jest.Mocked<Mpc>
package/src/index.test.ts CHANGED
@@ -11,10 +11,12 @@ import {
11
11
  mockClientResponse,
12
12
  mockEip155Address,
13
13
  mockEjectResult,
14
+ mockEjectPrivateKeysResult,
14
15
  mockEthRpcUrl,
15
16
  mockEthTransaction,
16
17
  mockMpcBackupResponse,
17
18
  mockOrgBackupShare,
19
+ mockOrgBackupShares,
18
20
  mockQuoteArgs,
19
21
  mockRpcConfig,
20
22
  mockSharesOnDevice,
@@ -392,6 +394,128 @@ describe('Portal', () => {
392
394
  })
393
395
  })
394
396
 
397
+ describe('ejectPrivateKeys', () => {
398
+ it('should successfully eject a wallet when backup with portal is enabled', async () => {
399
+ const res = await portal.ejectPrivateKeys(
400
+ BackupMethods.password,
401
+ mockBackupConfig,
402
+ {
403
+ SECP256K1: '',
404
+ ED25519: '',
405
+ },
406
+ )
407
+
408
+ expect(res).toEqual(mockEjectPrivateKeysResult)
409
+ expect(portal.mpc.ejectPrivateKeys).toHaveBeenCalledTimes(1)
410
+ expect(portal.mpc.ejectPrivateKeys).toHaveBeenCalledWith({
411
+ cipherText: '',
412
+ backupMethod: BackupMethods.password,
413
+ backupConfigs: mockBackupConfig,
414
+ organizationBackupShares: {
415
+ SECP256K1: '',
416
+ ED25519: '',
417
+ },
418
+ host: 'web.portalhq.io',
419
+ mpcVersion: 'v6',
420
+ featureFlags: {},
421
+ })
422
+ })
423
+
424
+ it('should successfully eject a wallet when backup with portal is not enabled', async () => {
425
+ portal.mpc.getClient = (
426
+ portal.mpc.getClient as jest.Mock
427
+ ).mockResolvedValueOnce({
428
+ ...mockClientResponse,
429
+ environment: {
430
+ ...mockClientResponse.environment,
431
+ backupWithPortalEnabled: false,
432
+ },
433
+ })
434
+
435
+ const res = await portal.ejectPrivateKeys(
436
+ BackupMethods.password,
437
+ mockBackupConfig,
438
+ mockOrgBackupShares,
439
+ mockCipherText,
440
+ )
441
+
442
+ expect(res).toEqual(mockEjectPrivateKeysResult)
443
+ expect(portal.mpc.ejectPrivateKeys).toHaveBeenCalledTimes(1)
444
+ expect(portal.mpc.ejectPrivateKeys).toHaveBeenCalledWith({
445
+ cipherText: mockCipherText,
446
+ organizationBackupShares: mockOrgBackupShares,
447
+ backupMethod: BackupMethods.password,
448
+ backupConfigs: mockBackupConfig,
449
+ host: 'web.portalhq.io',
450
+ mpcVersion: 'v6',
451
+ featureFlags: {},
452
+ })
453
+ })
454
+
455
+ it('should error out if client could not be found', async () => {
456
+ portal.mpc.getClient = (
457
+ portal.mpc.getClient as jest.Mock
458
+ ).mockResolvedValueOnce(null)
459
+
460
+ await expect(
461
+ portal.ejectPrivateKeys(
462
+ BackupMethods.password,
463
+ mockBackupConfig,
464
+ mockOrgBackupShares,
465
+ mockCipherText,
466
+ ),
467
+ ).rejects.toThrowError(new Error('Client not found.'))
468
+ })
469
+
470
+ it('should error if clientBackupCipherText was not supplied when backup with portal is not enabled', async () => {
471
+ portal.mpc.getClient = (
472
+ portal.mpc.getClient as jest.Mock
473
+ ).mockResolvedValueOnce({
474
+ ...mockClientResponse,
475
+ environment: {
476
+ ...mockClientResponse.environment,
477
+ backupWithPortalEnabled: false,
478
+ },
479
+ })
480
+
481
+ await expect(
482
+ portal.ejectPrivateKeys(
483
+ BackupMethods.password,
484
+ mockBackupConfig,
485
+ mockOrgBackupShares,
486
+ ),
487
+ ).rejects.toThrowError(
488
+ new Error('clientBackupCipherText cannot be empty string.'),
489
+ )
490
+ })
491
+
492
+ it('should error if orgBackupShare was empty when backup with portal is not enabled', async () => {
493
+ portal.mpc.getClient = (
494
+ portal.mpc.getClient as jest.Mock
495
+ ).mockResolvedValueOnce({
496
+ ...mockClientResponse,
497
+ environment: {
498
+ ...mockClientResponse.environment,
499
+ backupWithPortalEnabled: false,
500
+ },
501
+ })
502
+
503
+ await expect(
504
+ portal.ejectPrivateKeys(
505
+ BackupMethods.password,
506
+ mockBackupConfig,
507
+ {
508
+ SECP256K1: '',
509
+ ED25519: '',
510
+ },
511
+ mockCipherText,
512
+ ),
513
+ ).rejects.toThrowError(
514
+ new Error('SECP256K1 orgBackupShare cannot be empty string.'),
515
+ )
516
+ })
517
+ })
518
+
395
519
  describe('getEip155Address', () => {
396
520
  it("should return the wallet's eip155 address correctly", async () => {
397
521
  const res = await portal.getEip155Address()
package/src/index.ts CHANGED
@@ -8,10 +8,12 @@ import {
8
8
  import {
9
9
  Asset,
10
10
  BuiltTransaction,
11
+ EjectPrivateKeysResult,
11
12
  EvaluateTransactionOperationType,
12
13
  EvaluateTransactionParam,
13
14
  EvaluatedTransaction,
14
15
  NFTAsset,
16
+ OrgBackupShares,
15
17
  type BackupConfigs,
16
18
  type BackupResponse,
17
19
  type Balance,
@@ -101,7 +103,7 @@ class Portal {
101
103
 
102
104
  this.provider = new Provider({
103
105
  portal: this,
104
- chainId: chainId ? Number(chainId): undefined,
106
+ chainId: chainId ? Number(chainId) : undefined,
105
107
  })
106
108
  }
107
109
 
@@ -255,7 +257,7 @@ class Portal {
255
257
  }
256
258
  }
257
259
 
258
- const { SECP256K1, ED25519 } = await this.mpc.eject({
260
+ const { SECP256K1 } = await this.mpc.eject({
259
261
  cipherText: clientBackupCipherText,
260
262
  backupMethod,
261
263
  backupConfigs,
@@ -265,6 +267,41 @@ class Portal {
265
267
  featureFlags: this.featureFlags,
266
268
  })
267
269
 
270
+ return {
271
+ SECP256K1,
272
+ }
273
+ }
274
+
275
+ public async ejectPrivateKeys(
276
+ backupMethod: BackupMethods,
277
+ backupConfigs: BackupConfigs = {},
278
+ orgBackupShares: OrgBackupShares,
279
+ clientBackupCipherText = '',
280
+ ): Promise<EjectPrivateKeysResult> {
281
+ const client = await this.mpc.getClient()
282
+ if (!client) {
283
+ throw new Error('Client not found.')
284
+ }
285
+
286
+ if (!client.environment.backupWithPortalEnabled) {
287
+ if (clientBackupCipherText === '') {
288
+ throw new Error('clientBackupCipherText cannot be empty string.')
289
+ }
290
+ if (orgBackupShares.SECP256K1 === '') {
291
+ throw new Error('SECP256K1 orgBackupShare cannot be empty string.')
292
+ }
293
+ }
294
+
295
+ const { SECP256K1, ED25519 } = await this.mpc.ejectPrivateKeys({
296
+ cipherText: clientBackupCipherText,
297
+ backupMethod,
298
+ backupConfigs,
299
+ organizationBackupShares: orgBackupShares,
300
+ host: this.host,
301
+ mpcVersion: this.mpcVersion,
302
+ featureFlags: this.featureFlags,
303
+ })
304
+
268
305
  return {
269
306
  SECP256K1,
270
307
  ED25519,