@getpara/react-native-wallet 1.7.1 → 2.0.0-dev.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.
@@ -1,7 +1,10 @@
1
1
  import { StorageUtils } from '@getpara/web-sdk';
2
+ /**
3
+ * Implements `StorageUtils` using React Native Async Storage.
4
+ */
2
5
  export declare class AsyncStorage implements StorageUtils {
6
+ clear(prefix: string): Promise<void>;
3
7
  get(key: string): Promise<string | null>;
4
- set(key: string, value: string): Promise<void>;
5
8
  removeItem(key: string): Promise<void>;
6
- clear(prefix: string): Promise<void>;
9
+ set(key: string, value: string): Promise<void>;
7
10
  }
@@ -8,56 +8,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import RNAsyncStorage from '@react-native-async-storage/async-storage';
11
+ /**
12
+ * Implements `StorageUtils` using React Native Async Storage.
13
+ */
11
14
  export class AsyncStorage {
12
- get(key) {
15
+ clear(prefix) {
13
16
  return __awaiter(this, void 0, void 0, function* () {
14
- try {
15
- return yield RNAsyncStorage.getItem(key);
16
- }
17
- catch (error) {
18
- console.warn('Error retrieving stored item:', error);
19
- return null;
17
+ const keys = yield RNAsyncStorage.getAllKeys();
18
+ for (const key of keys) {
19
+ if (key.startsWith(prefix)) {
20
+ yield RNAsyncStorage.removeItem(key);
21
+ }
20
22
  }
21
23
  });
22
24
  }
23
- set(key, value) {
25
+ get(key) {
24
26
  return __awaiter(this, void 0, void 0, function* () {
25
- try {
26
- yield RNAsyncStorage.setItem(key, value);
27
- }
28
- catch (error) {
29
- console.warn(`Error storing key ${key}:`, error);
30
- }
27
+ return RNAsyncStorage.getItem(key);
31
28
  });
32
29
  }
33
30
  removeItem(key) {
34
31
  return __awaiter(this, void 0, void 0, function* () {
35
- try {
36
- yield RNAsyncStorage.removeItem(key);
37
- }
38
- catch (error) {
39
- console.warn(`Error removing key ${key}:`, error);
40
- }
32
+ yield RNAsyncStorage.removeItem(key);
41
33
  });
42
34
  }
43
- clear(prefix) {
35
+ set(key, value) {
44
36
  return __awaiter(this, void 0, void 0, function* () {
45
- try {
46
- const keys = yield RNAsyncStorage.getAllKeys();
47
- for (const key of keys) {
48
- if (key.startsWith(prefix)) {
49
- try {
50
- yield RNAsyncStorage.removeItem(key);
51
- }
52
- catch (error) {
53
- console.warn(`Error clearing key ${key}:`, error);
54
- }
55
- }
56
- }
57
- }
58
- catch (error) {
59
- console.warn(`Error getting keys for prefix ${prefix}:`, error);
60
- }
37
+ yield RNAsyncStorage.setItem(key, value);
61
38
  });
62
39
  }
63
40
  }
@@ -1,4 +1,7 @@
1
1
  import { StorageUtils } from '@getpara/web-sdk';
2
+ /**
3
+ * Implements `StorageUtils` using React Native `Keychain`.
4
+ */
2
5
  export declare class KeychainStorage implements StorageUtils {
3
6
  get(key: string): Promise<string | null>;
4
7
  set(key: string, value: string): Promise<void>;
@@ -9,6 +9,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import Keychain from 'react-native-keychain';
11
11
  const USERNAME = '@CAPSULE';
12
+ const KEYCHAIN_USER_CANCELLED_ERRORS = [
13
+ 'user canceled the operation',
14
+ 'error: code: 13, msg: cancel',
15
+ 'error: code: 10, msg: fingerprint operation canceled by the user',
16
+ ];
17
+ function isUserCancelledError(error) {
18
+ return KEYCHAIN_USER_CANCELLED_ERRORS.some(userCancelledError => error.toString().toLowerCase().includes(userCancelledError));
19
+ }
20
+ /**
21
+ * Implements `StorageUtils` using React Native `Keychain`.
22
+ */
12
23
  export class KeychainStorage {
13
24
  get(key) {
14
25
  return __awaiter(this, void 0, void 0, function* () {
@@ -22,57 +33,39 @@ export class KeychainStorage {
22
33
  return item.password;
23
34
  }
24
35
  catch (error) {
25
- console.warn('Error retrieving stored item:', error);
26
- return null;
36
+ if (error instanceof Error && !isUserCancelledError(error)) {
37
+ // triggered when biometry verification fails and user cancels the action
38
+ throw new Error('Error retrieving stored item ' + error.message);
39
+ }
40
+ throw error;
27
41
  }
28
42
  });
29
43
  }
30
44
  set(key, value) {
31
45
  return __awaiter(this, void 0, void 0, function* () {
32
- try {
33
- const result = yield Keychain.setGenericPassword(USERNAME, value, {
34
- service: key,
35
- accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED,
36
- securityLevel: Keychain.SECURITY_LEVEL.ANY,
37
- storage: Keychain.STORAGE_TYPE.AES_GCM_NO_AUTH,
38
- });
39
- if (!result) {
40
- console.warn(`Failed to store key ${key}`);
41
- }
42
- }
43
- catch (error) {
44
- console.warn(`Error storing key ${key}:`, error);
46
+ const result = yield Keychain.setGenericPassword(USERNAME, value, {
47
+ service: key,
48
+ accessible: Keychain.ACCESSIBLE.AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY,
49
+ securityLevel: Keychain.SECURITY_LEVEL.ANY,
50
+ });
51
+ if (!result) {
52
+ throw new Error('Failed to store key ' + key);
45
53
  }
46
54
  });
47
55
  }
48
56
  removeItem(key) {
49
57
  return __awaiter(this, void 0, void 0, function* () {
50
- try {
51
- yield Keychain.resetGenericPassword({ service: key });
52
- }
53
- catch (error) {
54
- console.warn(`Error removing key ${key}:`, error);
55
- }
58
+ yield Keychain.resetGenericPassword({ service: key });
56
59
  });
57
60
  }
58
61
  clear(prefix) {
59
62
  return __awaiter(this, void 0, void 0, function* () {
60
- try {
61
- const services = yield Keychain.getAllGenericPasswordServices();
62
- for (const key of services) {
63
- if (key && key.startsWith(prefix)) {
64
- try {
65
- yield Keychain.resetGenericPassword({ service: key });
66
- }
67
- catch (error) {
68
- console.warn(`Error clearing key ${key}:`, error);
69
- }
70
- }
63
+ const services = yield Keychain.getAllGenericPasswordServices();
64
+ for (const key of services) {
65
+ if (key && key.startsWith(prefix)) {
66
+ yield Keychain.resetGenericPassword({ service: key });
71
67
  }
72
68
  }
73
- catch (error) {
74
- console.warn(`Error getting services for prefix ${prefix}:`, error);
75
- }
76
69
  });
77
70
  }
78
71
  }
@@ -16,7 +16,7 @@ export declare class ParaMobile extends ParaCore {
16
16
  * @param {string} [relyingPartyId] - The relying party ID for WebAuthn.
17
17
  * @param {ConstructorOpts} [opts] - Additional constructor options.
18
18
  */
19
- constructor(env: Environment, apiKey?: string, relyingPartyId?: string, opts?: ConstructorOpts);
19
+ constructor(env: Environment, apiKey: string, relyingPartyId?: string, opts?: ConstructorOpts);
20
20
  protected getPlatformUtils(): PlatformUtils;
21
21
  /**
22
22
  * Verifies an email and returns the biometrics ID.
@@ -169,8 +169,8 @@ export class ParaMobile extends ParaCore {
169
169
  const publicKeyHex = getPublicKeyHex(keyPair);
170
170
  const encryptionKeyHash = getSHA256HashHex(userHandleEncoded);
171
171
  const encryptedPrivateKeyHex = yield encryptPrivateKey(keyPair, userHandleEncoded);
172
- const session = yield this.ctx.client.touchSession();
173
- yield this.ctx.client.patchSessionPublicKey(session.data.partnerId, this.getUserId(), biometricsId, {
172
+ const { partnerId } = yield this.ctx.client.touchSession();
173
+ yield this.ctx.client.patchSessionPublicKey(partnerId, this.getUserId(), biometricsId, {
174
174
  publicKey: resultJson.id,
175
175
  sigDerivedPublicKey: publicKeyHex,
176
176
  cosePublicKey,
@@ -205,9 +205,9 @@ export class ParaMobile extends ParaCore {
205
205
  else {
206
206
  resultJson = result;
207
207
  }
208
- const session = yield this.ctx.client.touchSession();
208
+ const { partnerId } = yield this.ctx.client.touchSession();
209
209
  const publicKey = resultJson.id;
210
- const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(session.data.partnerId, {
210
+ const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(partnerId, {
211
211
  publicKey,
212
212
  signature: {
213
213
  clientDataJSON: resultJson.response.clientDataJSON,
@@ -254,16 +254,7 @@ export class ParaMobile extends ParaCore {
254
254
  type: desiredWallet.type || undefined,
255
255
  };
256
256
  }
257
- const currentWalletIds = {};
258
- for (const wallet of Object.values(walletsToInsert)) {
259
- const { id, type } = wallet;
260
- const currentIdsForType = currentWalletIds[type || 'EVM'] || [];
261
- currentWalletIds[type || 'EVM'] = [...currentIdsForType, id];
262
- }
263
257
  yield this.setWallets(walletsToInsert);
264
- yield this.setCurrentWalletIds(currentWalletIds, {
265
- sessionLookupId: session.data.sessionLookupId,
266
- });
267
258
  });
268
259
  }
269
260
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getpara/react-native-wallet",
3
- "version": "1.7.1",
3
+ "version": "2.0.0-dev.0",
4
4
  "description": "Para Wallet for React Native",
5
5
  "homepage": "https://getpara.com",
6
6
  "author": "Para Team <hello@getpara.com> (https://getpara.com)",
@@ -22,9 +22,9 @@
22
22
  "compile-signer": "bash ./scripts/compileSigner.sh"
23
23
  },
24
24
  "dependencies": {
25
- "@getpara/core-sdk": "1.7.1",
26
- "@getpara/user-management-client": "1.7.1",
27
- "@getpara/web-sdk": "1.7.1",
25
+ "@getpara/core-sdk": "2.0.0-dev.0",
26
+ "@getpara/user-management-client": "2.0.0-dev.0",
27
+ "@getpara/web-sdk": "2.0.0-dev.0",
28
28
  "@peculiar/webcrypto": "^1.5.0",
29
29
  "@sentry/react-native": "^6.7.0",
30
30
  "node-forge": "1.3.1",
@@ -33,16 +33,16 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@craftzdog/react-native-buffer": "6.0.5",
36
- "@react-native-async-storage/async-storage": "2.1.2",
36
+ "@react-native-async-storage/async-storage": "2.1.0",
37
37
  "@types/node-forge": "1.3.1",
38
38
  "@types/react": "^18.0.31",
39
39
  "@types/react-native": "0.70.0",
40
40
  "@types/text-encoding": "0.0.39",
41
- "react-native-keychain": "10.0.0",
41
+ "react-native-keychain": "9.2.2",
42
42
  "react-native-modpow": "1.1.0",
43
- "react-native-passkey": "3.1.0",
43
+ "react-native-passkey": "3.0.0",
44
44
  "react-native-quick-base64": "2.1.2",
45
- "react-native-quick-crypto": "0.7.12",
45
+ "react-native-quick-crypto": "0.7.11",
46
46
  "typescript": "^5.4.3"
47
47
  },
48
48
  "peerDependencies": {
@@ -60,5 +60,5 @@
60
60
  "publishConfig": {
61
61
  "access": "public"
62
62
  },
63
- "gitHead": "767395af96d4a724946a092de760e9137a73369a"
63
+ "gitHead": "f94ef031ef0e1894f5f0800e55f6ca2904641780"
64
64
  }
@@ -1,46 +1,28 @@
1
1
  import { StorageUtils } from '@getpara/web-sdk';
2
2
  import RNAsyncStorage from '@react-native-async-storage/async-storage';
3
3
 
4
+ /**
5
+ * Implements `StorageUtils` using React Native Async Storage.
6
+ */
4
7
  export class AsyncStorage implements StorageUtils {
5
- async get(key: string): Promise<string | null> {
6
- try {
7
- return await RNAsyncStorage.getItem(key);
8
- } catch (error) {
9
- console.warn('Error retrieving stored item:', error);
10
- return null;
8
+ async clear(prefix: string): Promise<void> {
9
+ const keys = await RNAsyncStorage.getAllKeys();
10
+ for (const key of keys) {
11
+ if (key.startsWith(prefix)) {
12
+ await RNAsyncStorage.removeItem(key);
13
+ }
11
14
  }
12
15
  }
13
16
 
14
- async set(key: string, value: string): Promise<void> {
15
- try {
16
- await RNAsyncStorage.setItem(key, value);
17
- } catch (error) {
18
- console.warn(`Error storing key ${key}:`, error);
19
- }
17
+ async get(key: string): Promise<string | null> {
18
+ return RNAsyncStorage.getItem(key);
20
19
  }
21
20
 
22
21
  async removeItem(key: string): Promise<void> {
23
- try {
24
- await RNAsyncStorage.removeItem(key);
25
- } catch (error) {
26
- console.warn(`Error removing key ${key}:`, error);
27
- }
22
+ await RNAsyncStorage.removeItem(key);
28
23
  }
29
24
 
30
- async clear(prefix: string): Promise<void> {
31
- try {
32
- const keys = await RNAsyncStorage.getAllKeys();
33
- for (const key of keys) {
34
- if (key.startsWith(prefix)) {
35
- try {
36
- await RNAsyncStorage.removeItem(key);
37
- } catch (error) {
38
- console.warn(`Error clearing key ${key}:`, error);
39
- }
40
- }
41
- }
42
- } catch (error) {
43
- console.warn(`Error getting keys for prefix ${prefix}:`, error);
44
- }
25
+ async set(key: string, value: string): Promise<void> {
26
+ await RNAsyncStorage.setItem(key, value);
45
27
  }
46
28
  }
@@ -2,7 +2,21 @@ import { StorageUtils } from '@getpara/web-sdk';
2
2
  import Keychain from 'react-native-keychain';
3
3
 
4
4
  const USERNAME = '@CAPSULE';
5
+ const KEYCHAIN_USER_CANCELLED_ERRORS = [
6
+ 'user canceled the operation',
7
+ 'error: code: 13, msg: cancel',
8
+ 'error: code: 10, msg: fingerprint operation canceled by the user',
9
+ ];
5
10
 
11
+ function isUserCancelledError(error: Error) {
12
+ return KEYCHAIN_USER_CANCELLED_ERRORS.some(userCancelledError =>
13
+ error.toString().toLowerCase().includes(userCancelledError),
14
+ );
15
+ }
16
+
17
+ /**
18
+ * Implements `StorageUtils` using React Native `Keychain`.
19
+ */
6
20
  export class KeychainStorage implements StorageUtils {
7
21
  async get(key: string): Promise<string | null> {
8
22
  try {
@@ -14,49 +28,32 @@ export class KeychainStorage implements StorageUtils {
14
28
  }
15
29
  return item.password;
16
30
  } catch (error) {
17
- console.warn('Error retrieving stored item:', error);
18
- return null;
31
+ if (error instanceof Error && !isUserCancelledError(error)) {
32
+ // triggered when biometry verification fails and user cancels the action
33
+ throw new Error('Error retrieving stored item ' + error.message);
34
+ }
35
+ throw error;
19
36
  }
20
37
  }
21
-
22
38
  async set(key: string, value: string): Promise<void> {
23
- try {
24
- const result = await Keychain.setGenericPassword(USERNAME, value, {
25
- service: key,
26
- accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED,
27
- securityLevel: Keychain.SECURITY_LEVEL.ANY,
28
- storage: Keychain.STORAGE_TYPE.AES_GCM_NO_AUTH,
29
- });
30
- if (!result) {
31
- console.warn(`Failed to store key ${key}`);
32
- }
33
- } catch (error) {
34
- console.warn(`Error storing key ${key}:`, error);
39
+ const result = await Keychain.setGenericPassword(USERNAME, value, {
40
+ service: key,
41
+ accessible: Keychain.ACCESSIBLE.AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY,
42
+ securityLevel: Keychain.SECURITY_LEVEL.ANY,
43
+ });
44
+ if (!result) {
45
+ throw new Error('Failed to store key ' + key);
35
46
  }
36
47
  }
37
-
38
48
  async removeItem(key: string): Promise<void> {
39
- try {
40
- await Keychain.resetGenericPassword({ service: key });
41
- } catch (error) {
42
- console.warn(`Error removing key ${key}:`, error);
43
- }
49
+ await Keychain.resetGenericPassword({ service: key });
44
50
  }
45
-
46
51
  async clear(prefix: string): Promise<void> {
47
- try {
48
- const services = await Keychain.getAllGenericPasswordServices();
49
- for (const key of services) {
50
- if (key && key.startsWith(prefix)) {
51
- try {
52
- await Keychain.resetGenericPassword({ service: key });
53
- } catch (error) {
54
- console.warn(`Error clearing key ${key}:`, error);
55
- }
56
- }
52
+ const services = await Keychain.getAllGenericPasswordServices();
53
+ for (const key of services) {
54
+ if (key && key.startsWith(prefix)) {
55
+ await Keychain.resetGenericPassword({ service: key });
57
56
  }
58
- } catch (error) {
59
- console.warn(`Error getting services for prefix ${prefix}:`, error);
60
57
  }
61
58
  }
62
59
  }
@@ -22,7 +22,7 @@ import {
22
22
  PasskeyGetRequest,
23
23
  PasskeyGetResult,
24
24
  } from 'react-native-passkey';
25
- import { Auth, CurrentWalletIds, extractAuthInfo, PublicKeyStatus, WalletScheme } from '@getpara/user-management-client';
25
+ import { Auth, extractAuthInfo, PublicKeyStatus, WalletScheme } from '@getpara/user-management-client';
26
26
  import { setEnv } from '../config.js';
27
27
  import base64url from 'base64url';
28
28
  import { webcrypto } from 'crypto';
@@ -46,7 +46,7 @@ export class ParaMobile extends ParaCore {
46
46
  * @param {string} [relyingPartyId] - The relying party ID for WebAuthn.
47
47
  * @param {ConstructorOpts} [opts] - Additional constructor options.
48
48
  */
49
- constructor(env: Environment, apiKey?: string, relyingPartyId?: string, opts?: ConstructorOpts) {
49
+ constructor(env: Environment, apiKey: string, relyingPartyId?: string, opts?: ConstructorOpts) {
50
50
  super(env, apiKey, opts);
51
51
 
52
52
  // starting with non-prod to see what kind of errors we get and if sensitive data is tracked
@@ -174,8 +174,8 @@ export class ParaMobile extends ParaCore {
174
174
  const encryptionKeyHash = getSHA256HashHex(userHandleEncoded);
175
175
  const encryptedPrivateKeyHex = await encryptPrivateKey(keyPair, userHandleEncoded);
176
176
 
177
- const session = await this.ctx.client.touchSession();
178
- await this.ctx.client.patchSessionPublicKey(session.data.partnerId, this.getUserId()!, biometricsId, {
177
+ const { partnerId } = await this.ctx.client.touchSession();
178
+ await this.ctx.client.patchSessionPublicKey(partnerId, this.getUserId()!, biometricsId, {
179
179
  publicKey: resultJson.id,
180
180
  sigDerivedPublicKey: publicKeyHex,
181
181
  cosePublicKey,
@@ -220,9 +220,9 @@ export class ParaMobile extends ParaCore {
220
220
  resultJson = result;
221
221
  }
222
222
 
223
- const session = await this.ctx.client.touchSession();
223
+ const { partnerId } = await this.ctx.client.touchSession();
224
224
  const publicKey = resultJson.id;
225
- const verifyWebChallengeResult = await this.ctx.client.verifyWebChallenge(session.data.partnerId, {
225
+ const verifyWebChallengeResult = await this.ctx.client.verifyWebChallenge(partnerId, {
226
226
  publicKey,
227
227
  signature: {
228
228
  clientDataJSON: resultJson.response.clientDataJSON,
@@ -293,16 +293,6 @@ export class ParaMobile extends ParaCore {
293
293
  };
294
294
  }
295
295
 
296
- const currentWalletIds: CurrentWalletIds = {};
297
- for (const wallet of Object.values(walletsToInsert)) {
298
- const { id, type } = wallet;
299
- const currentIdsForType = currentWalletIds[type || 'EVM'] || [];
300
- currentWalletIds[type || 'EVM'] = [...currentIdsForType, id];
301
- }
302
-
303
296
  await this.setWallets(walletsToInsert);
304
- await this.setCurrentWalletIds(currentWalletIds, {
305
- sessionLookupId: session.data.sessionLookupId,
306
- });
307
297
  }
308
298
  }