@getpara/react-native-wallet 2.0.0-alpha.3 → 2.0.0-alpha.5
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/AsyncStorage.d.ts +2 -5
- package/dist/AsyncStorage.js +37 -14
- package/dist/KeychainStorage.d.ts +0 -3
- package/dist/KeychainStorage.js +35 -28
- package/dist/react-native/ParaMobile.d.ts +1 -1
- package/dist/react-native/ParaMobile.js +12 -3
- package/dist/react-native/ReactNativeUtils.d.ts +3 -2
- package/dist/react-native/ReactNativeUtils.js +8 -7
- package/dist/shim.js +7 -0
- package/package.json +10 -10
- package/src/AsyncStorage.ts +32 -14
- package/src/KeychainStorage.ts +34 -31
- package/src/react-native/ParaMobile.ts +15 -5
- package/src/react-native/ReactNativeUtils.ts +9 -8
- package/src/shim.js +8 -0
package/dist/AsyncStorage.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { StorageUtils } from '@getpara/web-sdk';
|
|
2
|
-
/**
|
|
3
|
-
* Implements `StorageUtils` using React Native Async Storage.
|
|
4
|
-
*/
|
|
5
2
|
export declare class AsyncStorage implements StorageUtils {
|
|
6
|
-
clear(prefix: string): Promise<void>;
|
|
7
3
|
get(key: string): Promise<string | null>;
|
|
8
|
-
removeItem(key: string): Promise<void>;
|
|
9
4
|
set(key: string, value: string): Promise<void>;
|
|
5
|
+
removeItem(key: string): Promise<void>;
|
|
6
|
+
clear(prefix: string): Promise<void>;
|
|
10
7
|
}
|
package/dist/AsyncStorage.js
CHANGED
|
@@ -8,33 +8,56 @@ 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
|
-
*/
|
|
14
11
|
export class AsyncStorage {
|
|
15
|
-
|
|
12
|
+
get(key) {
|
|
16
13
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
try {
|
|
15
|
+
return yield RNAsyncStorage.getItem(key);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
console.warn('Error retrieving stored item:', error);
|
|
19
|
+
return null;
|
|
22
20
|
}
|
|
23
21
|
});
|
|
24
22
|
}
|
|
25
|
-
|
|
23
|
+
set(key, value) {
|
|
26
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
-
|
|
25
|
+
try {
|
|
26
|
+
yield RNAsyncStorage.setItem(key, value);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.warn(`Error storing key ${key}:`, error);
|
|
30
|
+
}
|
|
28
31
|
});
|
|
29
32
|
}
|
|
30
33
|
removeItem(key) {
|
|
31
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
-
|
|
35
|
+
try {
|
|
36
|
+
yield RNAsyncStorage.removeItem(key);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.warn(`Error removing key ${key}:`, error);
|
|
40
|
+
}
|
|
33
41
|
});
|
|
34
42
|
}
|
|
35
|
-
|
|
43
|
+
clear(prefix) {
|
|
36
44
|
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
|
|
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
|
+
}
|
|
38
61
|
});
|
|
39
62
|
}
|
|
40
63
|
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { StorageUtils } from '@getpara/web-sdk';
|
|
2
|
-
/**
|
|
3
|
-
* Implements `StorageUtils` using React Native `Keychain`.
|
|
4
|
-
*/
|
|
5
2
|
export declare class KeychainStorage implements StorageUtils {
|
|
6
3
|
get(key: string): Promise<string | null>;
|
|
7
4
|
set(key: string, value: string): Promise<void>;
|
package/dist/KeychainStorage.js
CHANGED
|
@@ -9,17 +9,6 @@ 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
|
-
*/
|
|
23
12
|
export class KeychainStorage {
|
|
24
13
|
get(key) {
|
|
25
14
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -33,39 +22,57 @@ export class KeychainStorage {
|
|
|
33
22
|
return item.password;
|
|
34
23
|
}
|
|
35
24
|
catch (error) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
throw new Error('Error retrieving stored item ' + error.message);
|
|
39
|
-
}
|
|
40
|
-
throw error;
|
|
25
|
+
console.warn('Error retrieving stored item:', error);
|
|
26
|
+
return null;
|
|
41
27
|
}
|
|
42
28
|
});
|
|
43
29
|
}
|
|
44
30
|
set(key, value) {
|
|
45
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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);
|
|
53
45
|
}
|
|
54
46
|
});
|
|
55
47
|
}
|
|
56
48
|
removeItem(key) {
|
|
57
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
-
|
|
50
|
+
try {
|
|
51
|
+
yield Keychain.resetGenericPassword({ service: key });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.warn(`Error removing key ${key}:`, error);
|
|
55
|
+
}
|
|
59
56
|
});
|
|
60
57
|
}
|
|
61
58
|
clear(prefix) {
|
|
62
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
+
}
|
|
67
71
|
}
|
|
68
72
|
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.warn(`Error getting services for prefix ${prefix}:`, error);
|
|
75
|
+
}
|
|
69
76
|
});
|
|
70
77
|
}
|
|
71
78
|
}
|
|
@@ -144,7 +144,7 @@ export class ParaMobile extends ParaCore {
|
|
|
144
144
|
* @param {AuthParams} params - The authentication parameters.
|
|
145
145
|
* @returns {Promise<void>}
|
|
146
146
|
*/
|
|
147
|
-
|
|
147
|
+
loginWithPasskey() {
|
|
148
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
149
149
|
this.assertIsAuthSet();
|
|
150
150
|
const userId = this.assertUserId();
|
|
@@ -163,7 +163,7 @@ export class ParaMobile extends ParaCore {
|
|
|
163
163
|
else {
|
|
164
164
|
resultJson = result;
|
|
165
165
|
}
|
|
166
|
-
const { partnerId } = yield this.ctx.client.touchSession();
|
|
166
|
+
const { partnerId, sessionLookupId } = yield this.ctx.client.touchSession();
|
|
167
167
|
const publicKey = resultJson.id;
|
|
168
168
|
const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(partnerId, {
|
|
169
169
|
publicKey,
|
|
@@ -173,7 +173,7 @@ export class ParaMobile extends ParaCore {
|
|
|
173
173
|
signature: resultJson.response.signature,
|
|
174
174
|
},
|
|
175
175
|
});
|
|
176
|
-
if (userId !== verifyWebChallengeResult.userId) {
|
|
176
|
+
if (userId !== verifyWebChallengeResult.data.userId) {
|
|
177
177
|
throw new Error('User ID mismatch');
|
|
178
178
|
}
|
|
179
179
|
const encryptedSharesResult = yield this.ctx.client.getBiometricKeyshares(userId, resultJson.id);
|
|
@@ -203,7 +203,16 @@ export class ParaMobile extends ParaCore {
|
|
|
203
203
|
type: desiredWallet.type || undefined,
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
|
+
const currentWalletIds = {};
|
|
207
|
+
for (const wallet of Object.values(walletsToInsert)) {
|
|
208
|
+
const { id, type } = wallet;
|
|
209
|
+
const currentIdsForType = currentWalletIds[type || 'EVM'] || [];
|
|
210
|
+
currentWalletIds[type || 'EVM'] = [...currentIdsForType, id];
|
|
211
|
+
}
|
|
206
212
|
yield this.setWallets(walletsToInsert);
|
|
213
|
+
yield this.setCurrentWalletIds(currentWalletIds, {
|
|
214
|
+
sessionLookupId,
|
|
215
|
+
});
|
|
207
216
|
});
|
|
208
217
|
}
|
|
209
218
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { PlatformUtils, TPregenIdentifierType } from '@getpara/web-sdk';
|
|
2
2
|
import { Ctx } from '@getpara/web-sdk';
|
|
3
3
|
import { SignatureRes } from '@getpara/web-sdk';
|
|
4
|
-
import { BackupKitEmailProps,
|
|
4
|
+
import { BackupKitEmailProps, TWalletType, SDKType } from '@getpara/user-management-client';
|
|
5
5
|
import { AsyncStorage } from '../AsyncStorage.js';
|
|
6
6
|
import { KeychainStorage } from '../KeychainStorage.js';
|
|
7
7
|
export declare class ReactNativeUtils implements PlatformUtils {
|
|
8
|
+
sdkType: SDKType;
|
|
8
9
|
disableProviderModal?: boolean | undefined;
|
|
9
10
|
localStorage: AsyncStorage;
|
|
10
11
|
sessionStorage: AsyncStorage;
|
|
@@ -14,7 +15,7 @@ export declare class ReactNativeUtils implements PlatformUtils {
|
|
|
14
15
|
p: string;
|
|
15
16
|
q: string;
|
|
16
17
|
}>;
|
|
17
|
-
keygen(ctx: Ctx, userId: string, type: Exclude<
|
|
18
|
+
keygen(ctx: Ctx, userId: string, type: Exclude<TWalletType, 'SOLANA'>, _secretKey: string | null, _sessionCookie: string, _emailProps?: BackupKitEmailProps | undefined): Promise<{
|
|
18
19
|
signer: string;
|
|
19
20
|
walletId: string;
|
|
20
21
|
}>;
|
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { KeyShareType
|
|
10
|
+
import { KeyShareType } from '@getpara/user-management-client';
|
|
11
11
|
import { NativeModules } from 'react-native';
|
|
12
12
|
import { AsyncStorage } from '../AsyncStorage.js';
|
|
13
13
|
import { KeychainStorage } from '../KeychainStorage.js';
|
|
@@ -47,6 +47,7 @@ function sendTransactionRequest(ctx, userId, walletId, protocolId, transaction,
|
|
|
47
47
|
}
|
|
48
48
|
export class ReactNativeUtils {
|
|
49
49
|
constructor() {
|
|
50
|
+
this.sdkType = 'REACT_NATIVE';
|
|
50
51
|
this.localStorage = new AsyncStorage();
|
|
51
52
|
this.sessionStorage = new AsyncStorage();
|
|
52
53
|
this.secureStorage = new KeychainStorage();
|
|
@@ -63,7 +64,7 @@ export class ReactNativeUtils {
|
|
|
63
64
|
const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
|
|
64
65
|
type,
|
|
65
66
|
useTwoSigners: true,
|
|
66
|
-
scheme: ctx.useDKLS ?
|
|
67
|
+
scheme: ctx.useDKLS ? 'DKLS' : 'CGGMP',
|
|
67
68
|
});
|
|
68
69
|
if (ctx.mpcComputationClient && !ctx.useDKLS) {
|
|
69
70
|
const { signer } = yield keygenRequest(ctx, userId, walletId, protocolId);
|
|
@@ -141,8 +142,8 @@ export class ReactNativeUtils {
|
|
|
141
142
|
ed25519Keygen(ctx, userId, _sessionCookie, _emailProps) {
|
|
142
143
|
return __awaiter(this, void 0, void 0, function* () {
|
|
143
144
|
const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
|
|
144
|
-
scheme:
|
|
145
|
-
type:
|
|
145
|
+
scheme: 'ED25519',
|
|
146
|
+
type: 'SOLANA',
|
|
146
147
|
});
|
|
147
148
|
const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
148
149
|
return { signer, walletId };
|
|
@@ -153,8 +154,8 @@ export class ReactNativeUtils {
|
|
|
153
154
|
const { walletId, protocolId } = yield ctx.client.createPregenWallet({
|
|
154
155
|
pregenIdentifier,
|
|
155
156
|
pregenIdentifierType,
|
|
156
|
-
scheme:
|
|
157
|
-
type:
|
|
157
|
+
scheme: 'ED25519',
|
|
158
|
+
type: 'SOLANA',
|
|
158
159
|
});
|
|
159
160
|
const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
160
161
|
return { signer, walletId };
|
|
@@ -162,7 +163,7 @@ export class ReactNativeUtils {
|
|
|
162
163
|
}
|
|
163
164
|
ed25519Sign(ctx, userId, walletId, share, base64Bytes, _sessionCookie) {
|
|
164
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
-
const { protocolId } = yield ctx.client.preSignMessage(userId, walletId, base64Bytes,
|
|
166
|
+
const { protocolId } = yield ctx.client.preSignMessage(userId, walletId, base64Bytes, 'ED25519');
|
|
166
167
|
const base64Sig = yield ParaSignerModule.ed25519Sign(protocolId, share, base64Bytes);
|
|
167
168
|
return { signature: base64Sig };
|
|
168
169
|
});
|
package/dist/shim.js
CHANGED
|
@@ -8,6 +8,7 @@ import { Buffer } from '@craftzdog/react-native-buffer';
|
|
|
8
8
|
import process from 'process';
|
|
9
9
|
import 'react-native-url-polyfill/auto';
|
|
10
10
|
import { TextEncoder, TextDecoder } from 'text-encoding';
|
|
11
|
+
import structuredClone from '@ungap/structured-clone';
|
|
11
12
|
const setupProcessPolyfill = () => {
|
|
12
13
|
if (typeof globalThis.process === 'undefined') {
|
|
13
14
|
globalThis.process = process;
|
|
@@ -61,8 +62,14 @@ const setupTextEncodingPolyfills = () => {
|
|
|
61
62
|
globalThis.TextEncoder = TextEncoder;
|
|
62
63
|
globalThis.TextDecoder = TextDecoder;
|
|
63
64
|
};
|
|
65
|
+
const setupStructuredClonePolyfill = () => {
|
|
66
|
+
if (typeof globalThis.structuredClone === 'undefined') {
|
|
67
|
+
globalThis.structuredClone = structuredClone;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
64
70
|
setupProcessPolyfill();
|
|
65
71
|
setupBufferPolyfill();
|
|
66
72
|
setupBase64Polyfills();
|
|
67
73
|
setupCryptoPolyfills();
|
|
68
74
|
setupTextEncodingPolyfills();
|
|
75
|
+
setupStructuredClonePolyfill();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpara/react-native-wallet",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.5",
|
|
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,27 +22,27 @@
|
|
|
22
22
|
"compile-signer": "bash ./scripts/compileSigner.sh"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@getpara/core-sdk": "2.0.0-alpha.
|
|
26
|
-
"@getpara/user-management-client": "2.0.0-alpha.
|
|
27
|
-
"@getpara/web-sdk": "2.0.0-alpha.
|
|
25
|
+
"@getpara/core-sdk": "2.0.0-alpha.5",
|
|
26
|
+
"@getpara/user-management-client": "2.0.0-alpha.5",
|
|
27
|
+
"@getpara/web-sdk": "2.0.0-alpha.5",
|
|
28
28
|
"@peculiar/webcrypto": "^1.5.0",
|
|
29
|
-
"@sentry/react-native": "^6.
|
|
29
|
+
"@sentry/react-native": "^6.10.0",
|
|
30
30
|
"node-forge": "1.3.1",
|
|
31
31
|
"react-native-url-polyfill": "2.0.0",
|
|
32
32
|
"text-encoding": "0.7.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@craftzdog/react-native-buffer": "6.0.5",
|
|
36
|
-
"@react-native-async-storage/async-storage": "2.1.
|
|
36
|
+
"@react-native-async-storage/async-storage": "2.1.2",
|
|
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": "
|
|
41
|
+
"react-native-keychain": "10.0.0",
|
|
42
42
|
"react-native-modpow": "1.1.0",
|
|
43
|
-
"react-native-passkey": "3.
|
|
43
|
+
"react-native-passkey": "3.1.0",
|
|
44
44
|
"react-native-quick-base64": "2.1.2",
|
|
45
|
-
"react-native-quick-crypto": "0.7.
|
|
45
|
+
"react-native-quick-crypto": "0.7.12",
|
|
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": "
|
|
63
|
+
"gitHead": "3ecfca088f24489f2e8fa5493d0f4459b08880e1"
|
|
64
64
|
}
|
package/src/AsyncStorage.ts
CHANGED
|
@@ -1,28 +1,46 @@
|
|
|
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
|
-
*/
|
|
7
4
|
export class AsyncStorage implements StorageUtils {
|
|
8
|
-
async
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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;
|
|
14
11
|
}
|
|
15
12
|
}
|
|
16
13
|
|
|
17
|
-
async
|
|
18
|
-
|
|
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
|
+
}
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
async removeItem(key: string): Promise<void> {
|
|
22
|
-
|
|
23
|
+
try {
|
|
24
|
+
await RNAsyncStorage.removeItem(key);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.warn(`Error removing key ${key}:`, error);
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
|
|
25
|
-
async
|
|
26
|
-
|
|
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
|
+
}
|
|
27
45
|
}
|
|
28
46
|
}
|
package/src/KeychainStorage.ts
CHANGED
|
@@ -2,21 +2,7 @@ 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
|
-
];
|
|
10
5
|
|
|
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
|
-
*/
|
|
20
6
|
export class KeychainStorage implements StorageUtils {
|
|
21
7
|
async get(key: string): Promise<string | null> {
|
|
22
8
|
try {
|
|
@@ -28,32 +14,49 @@ export class KeychainStorage implements StorageUtils {
|
|
|
28
14
|
}
|
|
29
15
|
return item.password;
|
|
30
16
|
} catch (error) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
throw new Error('Error retrieving stored item ' + error.message);
|
|
34
|
-
}
|
|
35
|
-
throw error;
|
|
17
|
+
console.warn('Error retrieving stored item:', error);
|
|
18
|
+
return null;
|
|
36
19
|
}
|
|
37
20
|
}
|
|
21
|
+
|
|
38
22
|
async set(key: string, value: string): Promise<void> {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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);
|
|
46
35
|
}
|
|
47
36
|
}
|
|
37
|
+
|
|
48
38
|
async removeItem(key: string): Promise<void> {
|
|
49
|
-
|
|
39
|
+
try {
|
|
40
|
+
await Keychain.resetGenericPassword({ service: key });
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.warn(`Error removing key ${key}:`, error);
|
|
43
|
+
}
|
|
50
44
|
}
|
|
45
|
+
|
|
51
46
|
async clear(prefix: string): Promise<void> {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
+
}
|
|
56
57
|
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.warn(`Error getting services for prefix ${prefix}:`, error);
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
}
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
PasskeyGetRequest,
|
|
24
24
|
PasskeyGetResult,
|
|
25
25
|
} from 'react-native-passkey';
|
|
26
|
-
import { PublicKeyStatus,
|
|
26
|
+
import { CurrentWalletIds, PublicKeyStatus, TWalletScheme } from '@getpara/user-management-client';
|
|
27
27
|
import { setEnv } from '../config.js';
|
|
28
28
|
import base64url from 'base64url';
|
|
29
29
|
import { webcrypto } from 'crypto';
|
|
@@ -172,7 +172,7 @@ export class ParaMobile extends ParaCore {
|
|
|
172
172
|
* @param {AuthParams} params - The authentication parameters.
|
|
173
173
|
* @returns {Promise<void>}
|
|
174
174
|
*/
|
|
175
|
-
async
|
|
175
|
+
async loginWithPasskey(): Promise<void> {
|
|
176
176
|
this.assertIsAuthSet();
|
|
177
177
|
const userId = this.assertUserId();
|
|
178
178
|
|
|
@@ -195,7 +195,7 @@ export class ParaMobile extends ParaCore {
|
|
|
195
195
|
resultJson = result;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
const { partnerId } = await this.ctx.client.touchSession();
|
|
198
|
+
const { partnerId, sessionLookupId } = await this.ctx.client.touchSession();
|
|
199
199
|
const publicKey = resultJson.id;
|
|
200
200
|
const verifyWebChallengeResult = await this.ctx.client.verifyWebChallenge(partnerId, {
|
|
201
201
|
publicKey,
|
|
@@ -206,7 +206,7 @@ export class ParaMobile extends ParaCore {
|
|
|
206
206
|
},
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
-
if (userId !== verifyWebChallengeResult.userId) {
|
|
209
|
+
if (userId !== verifyWebChallengeResult.data.userId) {
|
|
210
210
|
throw new Error('User ID mismatch');
|
|
211
211
|
}
|
|
212
212
|
|
|
@@ -249,11 +249,21 @@ export class ParaMobile extends ParaCore {
|
|
|
249
249
|
signer: decryptedShare.signer,
|
|
250
250
|
address: desiredWallet.address || undefined,
|
|
251
251
|
publicKey: desiredWallet.publicKey || undefined,
|
|
252
|
-
scheme: desiredWallet.scheme as
|
|
252
|
+
scheme: desiredWallet.scheme as TWalletScheme,
|
|
253
253
|
type: desiredWallet.type || undefined,
|
|
254
254
|
};
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
const currentWalletIds: 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
264
|
await this.setWallets(walletsToInsert);
|
|
265
|
+
await this.setCurrentWalletIds(currentWalletIds, {
|
|
266
|
+
sessionLookupId,
|
|
267
|
+
});
|
|
258
268
|
}
|
|
259
269
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PlatformUtils, TPregenIdentifierType } from '@getpara/web-sdk';
|
|
2
2
|
import { Ctx } from '@getpara/web-sdk';
|
|
3
3
|
import { SignatureRes } from '@getpara/web-sdk';
|
|
4
|
-
import { BackupKitEmailProps, KeyShareType,
|
|
4
|
+
import { BackupKitEmailProps, KeyShareType, TWalletType, SDKType } from '@getpara/user-management-client';
|
|
5
5
|
import { NativeModules } from 'react-native';
|
|
6
6
|
|
|
7
7
|
import { AsyncStorage } from '../AsyncStorage.js';
|
|
@@ -55,6 +55,7 @@ async function sendTransactionRequest(
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export class ReactNativeUtils implements PlatformUtils {
|
|
58
|
+
sdkType: SDKType = 'REACT_NATIVE';
|
|
58
59
|
disableProviderModal?: boolean | undefined;
|
|
59
60
|
localStorage = new AsyncStorage();
|
|
60
61
|
sessionStorage = new AsyncStorage();
|
|
@@ -69,7 +70,7 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
69
70
|
async keygen(
|
|
70
71
|
ctx: Ctx,
|
|
71
72
|
userId: string,
|
|
72
|
-
type: Exclude<
|
|
73
|
+
type: Exclude<TWalletType, 'SOLANA'>,
|
|
73
74
|
_secretKey: string | null,
|
|
74
75
|
_sessionCookie: string,
|
|
75
76
|
_emailProps?: BackupKitEmailProps | undefined,
|
|
@@ -77,7 +78,7 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
77
78
|
const { walletId, protocolId } = await ctx.client.createWallet(userId, {
|
|
78
79
|
type,
|
|
79
80
|
useTwoSigners: true,
|
|
80
|
-
scheme: ctx.useDKLS ?
|
|
81
|
+
scheme: ctx.useDKLS ? 'DKLS' : 'CGGMP',
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
if (ctx.mpcComputationClient && !ctx.useDKLS) {
|
|
@@ -220,8 +221,8 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
220
221
|
walletId: string;
|
|
221
222
|
}> {
|
|
222
223
|
const { walletId, protocolId } = await ctx.client.createWallet(userId, {
|
|
223
|
-
scheme:
|
|
224
|
-
type:
|
|
224
|
+
scheme: 'ED25519',
|
|
225
|
+
type: 'SOLANA',
|
|
225
226
|
});
|
|
226
227
|
|
|
227
228
|
const signer = await ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
@@ -240,8 +241,8 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
240
241
|
const { walletId, protocolId } = await ctx.client.createPregenWallet({
|
|
241
242
|
pregenIdentifier,
|
|
242
243
|
pregenIdentifierType,
|
|
243
|
-
scheme:
|
|
244
|
-
type:
|
|
244
|
+
scheme: 'ED25519',
|
|
245
|
+
type: 'SOLANA',
|
|
245
246
|
});
|
|
246
247
|
|
|
247
248
|
const signer = await ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
@@ -256,7 +257,7 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
256
257
|
base64Bytes: string,
|
|
257
258
|
_sessionCookie: string,
|
|
258
259
|
): Promise<SignatureRes> {
|
|
259
|
-
const { protocolId } = await ctx.client.preSignMessage(userId, walletId, base64Bytes,
|
|
260
|
+
const { protocolId } = await ctx.client.preSignMessage(userId, walletId, base64Bytes, 'ED25519');
|
|
260
261
|
|
|
261
262
|
const base64Sig = await ParaSignerModule.ed25519Sign(protocolId, share, base64Bytes);
|
|
262
263
|
return { signature: base64Sig };
|
package/src/shim.js
CHANGED
|
@@ -8,6 +8,7 @@ import { Buffer } from '@craftzdog/react-native-buffer';
|
|
|
8
8
|
import process from 'process';
|
|
9
9
|
import 'react-native-url-polyfill/auto';
|
|
10
10
|
import { TextEncoder, TextDecoder } from 'text-encoding';
|
|
11
|
+
import structuredClone from '@ungap/structured-clone';
|
|
11
12
|
|
|
12
13
|
const setupProcessPolyfill = () => {
|
|
13
14
|
if (typeof globalThis.process === 'undefined') {
|
|
@@ -67,8 +68,15 @@ const setupTextEncodingPolyfills = () => {
|
|
|
67
68
|
globalThis.TextDecoder = TextDecoder;
|
|
68
69
|
};
|
|
69
70
|
|
|
71
|
+
const setupStructuredClonePolyfill = () => {
|
|
72
|
+
if (typeof globalThis.structuredClone === 'undefined') {
|
|
73
|
+
globalThis.structuredClone = structuredClone;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
70
77
|
setupProcessPolyfill();
|
|
71
78
|
setupBufferPolyfill();
|
|
72
79
|
setupBase64Polyfills();
|
|
73
80
|
setupCryptoPolyfills();
|
|
74
81
|
setupTextEncodingPolyfills();
|
|
82
|
+
setupStructuredClonePolyfill();
|