@getpara/react-native-wallet 1.12.0 → 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/react-native/ParaMobile.d.ts +5 -23
- package/dist/react-native/ParaMobile.js +31 -73
- package/dist/react-native/ReactNativeUtils.d.ts +2 -2
- package/dist/react-native/ReactNativeUtils.js +7 -7
- package/package.json +6 -5
- package/src/react-native/ParaMobile.ts +38 -67
- package/src/react-native/ReactNativeUtils.ts +8 -8
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ConstructorOpts, ParaCore, Environment, PlatformUtils } from '@getpara/web-sdk';
|
|
2
|
-
import { Auth } from '@getpara/user-management-client';
|
|
1
|
+
import { AuthStateSignup, ConstructorOpts, ParaCore, Environment, PlatformUtils } from '@getpara/web-sdk';
|
|
3
2
|
/**
|
|
4
3
|
* Represents a mobile implementation of the Para SDK.
|
|
5
4
|
* @extends ParaCore
|
|
@@ -8,6 +7,7 @@ import { Auth } from '@getpara/user-management-client';
|
|
|
8
7
|
* const para = new ParaMobile(Environment.BETA, "api_key");
|
|
9
8
|
*/
|
|
10
9
|
export declare class ParaMobile extends ParaCore {
|
|
10
|
+
isNativePasskey: boolean;
|
|
11
11
|
private relyingPartyId;
|
|
12
12
|
/**
|
|
13
13
|
* Creates an instance of ParaMobile.
|
|
@@ -16,37 +16,19 @@ 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
|
|
19
|
+
constructor(env: Environment, apiKey: string, relyingPartyId?: string, opts?: ConstructorOpts);
|
|
20
20
|
protected getPlatformUtils(): PlatformUtils;
|
|
21
|
-
/**
|
|
22
|
-
* Verifies an email and returns the biometrics ID.
|
|
23
|
-
* @param {string} verificationCode - The verification code sent to the email.
|
|
24
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
25
|
-
*/
|
|
26
|
-
verifyEmailBiometricsId({ verificationCode }: {
|
|
27
|
-
verificationCode: string;
|
|
28
|
-
}): Promise<string>;
|
|
29
|
-
/**
|
|
30
|
-
* Verifies a phone number and returns the biometrics ID.
|
|
31
|
-
* @param {string} verificationCode - The verification code sent to the phone.
|
|
32
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
33
|
-
*/
|
|
34
|
-
verifyPhoneBiometricsId({ verificationCode }: {
|
|
35
|
-
verificationCode: string;
|
|
36
|
-
}): Promise<string>;
|
|
37
21
|
/**
|
|
38
22
|
* Registers a passkey for the user.
|
|
39
23
|
* @param {Auth<'email'> | Auth<'phone'>} auth - The user's authentication details
|
|
40
24
|
* @param {string} biometricsId - The biometrics ID obtained from verification.
|
|
41
25
|
* @returns {Promise<void>}
|
|
42
26
|
*/
|
|
43
|
-
registerPasskey(
|
|
44
|
-
biometricsId: string;
|
|
45
|
-
} & (Auth<'email'> | Auth<'phone'>)): Promise<void>;
|
|
27
|
+
registerPasskey(authState: AuthStateSignup): Promise<void>;
|
|
46
28
|
/**
|
|
47
29
|
* Logs in the user using their authentication credentials.
|
|
48
30
|
* @param {AuthParams} params - The authentication parameters.
|
|
49
31
|
* @returns {Promise<void>}
|
|
50
32
|
*/
|
|
51
|
-
|
|
33
|
+
loginWithPasskey(): Promise<void>;
|
|
52
34
|
}
|
|
@@ -7,21 +7,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
-
var t = {};
|
|
12
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
-
t[p[i]] = s[p[i]];
|
|
18
|
-
}
|
|
19
|
-
return t;
|
|
20
|
-
};
|
|
21
10
|
import { ParaCore, Environment, decryptPrivateKeyAndDecryptShare, encryptPrivateKey, getAsymmetricKeyPair, getDerivedPrivateKeyAndDecrypt, getPublicKeyHex, getSHA256HashHex, parseCredentialCreationRes, } from '@getpara/web-sdk';
|
|
11
|
+
import * as Sentry from '@sentry/react-native';
|
|
22
12
|
import { ReactNativeUtils } from './ReactNativeUtils.js';
|
|
23
13
|
import { Passkey, } from 'react-native-passkey';
|
|
24
|
-
import {
|
|
14
|
+
import { PublicKeyStatus } from '@getpara/user-management-client';
|
|
25
15
|
import { setEnv } from '../config.js';
|
|
26
16
|
import base64url from 'base64url';
|
|
27
17
|
import { webcrypto } from 'crypto';
|
|
@@ -44,6 +34,15 @@ export class ParaMobile extends ParaCore {
|
|
|
44
34
|
*/
|
|
45
35
|
constructor(env, apiKey, relyingPartyId, opts) {
|
|
46
36
|
super(env, apiKey, opts);
|
|
37
|
+
this.isNativePasskey = true;
|
|
38
|
+
// starting with non-prod to see what kind of errors we get and if sensitive data is tracked
|
|
39
|
+
// will turn on in prod after monitoring
|
|
40
|
+
if (env !== Environment.PROD && env !== Environment.DEV) {
|
|
41
|
+
Sentry.init({
|
|
42
|
+
environment: env.toLowerCase(),
|
|
43
|
+
dsn: 'https://59cea0cfbbb30a646c4e9f2feea06da4@o4504568036720640.ingest.us.sentry.io/4508850922323968',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
47
46
|
setEnv(env);
|
|
48
47
|
if (relyingPartyId) {
|
|
49
48
|
this.relyingPartyId = relyingPartyId;
|
|
@@ -67,56 +66,25 @@ export class ParaMobile extends ParaCore {
|
|
|
67
66
|
getPlatformUtils() {
|
|
68
67
|
return new ReactNativeUtils();
|
|
69
68
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Verifies an email and returns the biometrics ID.
|
|
72
|
-
* @param {string} verificationCode - The verification code sent to the email.
|
|
73
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
74
|
-
*/
|
|
75
|
-
verifyEmailBiometricsId(_a) {
|
|
76
|
-
const _super = Object.create(null, {
|
|
77
|
-
verifyEmail: { get: () => super.verifyEmail }
|
|
78
|
-
});
|
|
79
|
-
return __awaiter(this, arguments, void 0, function* ({ verificationCode }) {
|
|
80
|
-
const webAuthCreateUrl = yield _super.verifyEmail.call(this, { verificationCode });
|
|
81
|
-
const segments = webAuthCreateUrl.split('/');
|
|
82
|
-
const segments2 = segments[segments.length - 1].split('?');
|
|
83
|
-
const biometricsId = segments2[0];
|
|
84
|
-
return biometricsId;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Verifies a phone number and returns the biometrics ID.
|
|
89
|
-
* @param {string} verificationCode - The verification code sent to the phone.
|
|
90
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
91
|
-
*/
|
|
92
|
-
verifyPhoneBiometricsId(_a) {
|
|
93
|
-
const _super = Object.create(null, {
|
|
94
|
-
verifyPhone: { get: () => super.verifyPhone }
|
|
95
|
-
});
|
|
96
|
-
return __awaiter(this, arguments, void 0, function* ({ verificationCode }) {
|
|
97
|
-
const webAuthCreateUrl = yield _super.verifyPhone.call(this, { verificationCode });
|
|
98
|
-
const segments = webAuthCreateUrl.split('/');
|
|
99
|
-
const segments2 = segments[segments.length - 1].split('?');
|
|
100
|
-
const biometricsId = segments2[0];
|
|
101
|
-
return biometricsId;
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
69
|
/**
|
|
105
70
|
* Registers a passkey for the user.
|
|
106
71
|
* @param {Auth<'email'> | Auth<'phone'>} auth - The user's authentication details
|
|
107
72
|
* @param {string} biometricsId - The biometrics ID obtained from verification.
|
|
108
73
|
* @returns {Promise<void>}
|
|
109
74
|
*/
|
|
110
|
-
registerPasskey(
|
|
75
|
+
registerPasskey(authState) {
|
|
111
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
-
|
|
77
|
+
if (!authState.passkeyId) {
|
|
78
|
+
throw new Error('Passkey ID not found. Make sure you have enabled passkey logins in the Para Developer Portal.');
|
|
79
|
+
}
|
|
80
|
+
const userId = this.assertUserId();
|
|
81
|
+
const authInfo = this.assertIsAuthSet();
|
|
113
82
|
if (!webcrypto || !webcrypto.getRandomValues) {
|
|
114
83
|
throw new Error('Web crypto is not available. Ensure you have imported the shim from @getpara/react-native-wallet.');
|
|
115
84
|
}
|
|
116
85
|
const userHandle = new Uint8Array(32);
|
|
117
86
|
webcrypto.getRandomValues(userHandle);
|
|
118
87
|
const userHandleEncoded = base64url.encode(userHandle);
|
|
119
|
-
const { identifier: displayIdentifier } = extractAuthInfo(auth, { isRequired: true });
|
|
120
88
|
const requestJson = {
|
|
121
89
|
authenticatorSelection: {
|
|
122
90
|
authenticatorAttachment: 'platform',
|
|
@@ -130,8 +98,8 @@ export class ParaMobile extends ParaCore {
|
|
|
130
98
|
},
|
|
131
99
|
user: {
|
|
132
100
|
id: userHandleEncoded,
|
|
133
|
-
name:
|
|
134
|
-
displayName:
|
|
101
|
+
name: authInfo.identifier,
|
|
102
|
+
displayName: authInfo.identifier,
|
|
135
103
|
},
|
|
136
104
|
pubKeyCredParams: [
|
|
137
105
|
{
|
|
@@ -160,15 +128,15 @@ export class ParaMobile extends ParaCore {
|
|
|
160
128
|
const publicKeyHex = getPublicKeyHex(keyPair);
|
|
161
129
|
const encryptionKeyHash = getSHA256HashHex(userHandleEncoded);
|
|
162
130
|
const encryptedPrivateKeyHex = yield encryptPrivateKey(keyPair, userHandleEncoded);
|
|
163
|
-
const
|
|
164
|
-
yield this.ctx.client.patchSessionPublicKey(
|
|
131
|
+
const { partnerId } = yield this.ctx.client.touchSession();
|
|
132
|
+
yield this.ctx.client.patchSessionPublicKey(partnerId, userId, authState.passkeyId, {
|
|
165
133
|
publicKey: resultJson.id,
|
|
166
134
|
sigDerivedPublicKey: publicKeyHex,
|
|
167
135
|
cosePublicKey,
|
|
168
136
|
clientDataJSON,
|
|
169
137
|
status: PublicKeyStatus.COMPLETE,
|
|
170
138
|
});
|
|
171
|
-
yield this.ctx.client.uploadEncryptedWalletPrivateKey(
|
|
139
|
+
yield this.ctx.client.uploadEncryptedWalletPrivateKey(userId, encryptedPrivateKeyHex, encryptionKeyHash, resultJson.id);
|
|
172
140
|
});
|
|
173
141
|
}
|
|
174
142
|
/**
|
|
@@ -176,12 +144,11 @@ export class ParaMobile extends ParaCore {
|
|
|
176
144
|
* @param {AuthParams} params - The authentication parameters.
|
|
177
145
|
* @returns {Promise<void>}
|
|
178
146
|
*/
|
|
179
|
-
|
|
147
|
+
loginWithPasskey() {
|
|
180
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
const { challenge, allowedPublicKeys } = yield this.ctx.client.getWebChallenge(authInfo.auth);
|
|
149
|
+
this.assertIsAuthSet();
|
|
150
|
+
const userId = this.assertUserId();
|
|
151
|
+
const { challenge, allowedPublicKeys } = yield this.ctx.client.getWebChallenge({ userId });
|
|
185
152
|
const requestJson = {
|
|
186
153
|
challenge,
|
|
187
154
|
timeout: 60000,
|
|
@@ -196,9 +163,9 @@ export class ParaMobile extends ParaCore {
|
|
|
196
163
|
else {
|
|
197
164
|
resultJson = result;
|
|
198
165
|
}
|
|
199
|
-
const
|
|
166
|
+
const { partnerId, sessionLookupId } = yield this.ctx.client.touchSession();
|
|
200
167
|
const publicKey = resultJson.id;
|
|
201
|
-
const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(
|
|
168
|
+
const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(partnerId, {
|
|
202
169
|
publicKey,
|
|
203
170
|
signature: {
|
|
204
171
|
clientDataJSON: resultJson.response.clientDataJSON,
|
|
@@ -206,17 +173,8 @@ export class ParaMobile extends ParaCore {
|
|
|
206
173
|
signature: resultJson.response.signature,
|
|
207
174
|
},
|
|
208
175
|
});
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const { user } = yield this.ctx.client.getUser(userId);
|
|
212
|
-
if (user.phone) {
|
|
213
|
-
yield this.setPhoneNumber(user.phone.number, user.phone.countryCode);
|
|
214
|
-
}
|
|
215
|
-
if (user.email) {
|
|
216
|
-
yield this.setEmail(user.email);
|
|
217
|
-
}
|
|
218
|
-
if (user.farcasterUsername) {
|
|
219
|
-
yield this.setFarcasterUsername(user.farcasterUsername);
|
|
176
|
+
if (userId !== verifyWebChallengeResult.data.userId) {
|
|
177
|
+
throw new Error('User ID mismatch');
|
|
220
178
|
}
|
|
221
179
|
const encryptedSharesResult = yield this.ctx.client.getBiometricKeyshares(userId, resultJson.id);
|
|
222
180
|
const encryptionKeyHash = getSHA256HashHex(resultJson.response.userHandle);
|
|
@@ -253,7 +211,7 @@ export class ParaMobile extends ParaCore {
|
|
|
253
211
|
}
|
|
254
212
|
yield this.setWallets(walletsToInsert);
|
|
255
213
|
yield this.setCurrentWalletIds(currentWalletIds, {
|
|
256
|
-
sessionLookupId
|
|
214
|
+
sessionLookupId,
|
|
257
215
|
});
|
|
258
216
|
});
|
|
259
217
|
}
|
|
@@ -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,
|
|
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 {
|
|
@@ -15,7 +15,7 @@ export declare class ReactNativeUtils implements PlatformUtils {
|
|
|
15
15
|
p: string;
|
|
16
16
|
q: string;
|
|
17
17
|
}>;
|
|
18
|
-
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<{
|
|
19
19
|
signer: string;
|
|
20
20
|
walletId: string;
|
|
21
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';
|
|
@@ -64,7 +64,7 @@ export class ReactNativeUtils {
|
|
|
64
64
|
const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
|
|
65
65
|
type,
|
|
66
66
|
useTwoSigners: true,
|
|
67
|
-
scheme: ctx.useDKLS ?
|
|
67
|
+
scheme: ctx.useDKLS ? 'DKLS' : 'CGGMP',
|
|
68
68
|
});
|
|
69
69
|
if (ctx.mpcComputationClient && !ctx.useDKLS) {
|
|
70
70
|
const { signer } = yield keygenRequest(ctx, userId, walletId, protocolId);
|
|
@@ -142,8 +142,8 @@ export class ReactNativeUtils {
|
|
|
142
142
|
ed25519Keygen(ctx, userId, _sessionCookie, _emailProps) {
|
|
143
143
|
return __awaiter(this, void 0, void 0, function* () {
|
|
144
144
|
const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
|
|
145
|
-
scheme:
|
|
146
|
-
type:
|
|
145
|
+
scheme: 'ED25519',
|
|
146
|
+
type: 'SOLANA',
|
|
147
147
|
});
|
|
148
148
|
const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
149
149
|
return { signer, walletId };
|
|
@@ -154,8 +154,8 @@ export class ReactNativeUtils {
|
|
|
154
154
|
const { walletId, protocolId } = yield ctx.client.createPregenWallet({
|
|
155
155
|
pregenIdentifier,
|
|
156
156
|
pregenIdentifierType,
|
|
157
|
-
scheme:
|
|
158
|
-
type:
|
|
157
|
+
scheme: 'ED25519',
|
|
158
|
+
type: 'SOLANA',
|
|
159
159
|
});
|
|
160
160
|
const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
161
161
|
return { signer, walletId };
|
|
@@ -163,7 +163,7 @@ export class ReactNativeUtils {
|
|
|
163
163
|
}
|
|
164
164
|
ed25519Sign(ctx, userId, walletId, share, base64Bytes, _sessionCookie) {
|
|
165
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
-
const { protocolId } = yield ctx.client.preSignMessage(userId, walletId, base64Bytes,
|
|
166
|
+
const { protocolId } = yield ctx.client.preSignMessage(userId, walletId, base64Bytes, 'ED25519');
|
|
167
167
|
const base64Sig = yield ParaSignerModule.ed25519Sign(protocolId, share, base64Bytes);
|
|
168
168
|
return { signature: base64Sig };
|
|
169
169
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpara/react-native-wallet",
|
|
3
|
-
"version": "
|
|
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,10 +22,11 @@
|
|
|
22
22
|
"compile-signer": "bash ./scripts/compileSigner.sh"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@getpara/core-sdk": "
|
|
26
|
-
"@getpara/user-management-client": "
|
|
27
|
-
"@getpara/web-sdk": "
|
|
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.10.0",
|
|
29
30
|
"node-forge": "1.3.1",
|
|
30
31
|
"react-native-url-polyfill": "2.0.0",
|
|
31
32
|
"text-encoding": "0.7.0"
|
|
@@ -59,5 +60,5 @@
|
|
|
59
60
|
"publishConfig": {
|
|
60
61
|
"access": "public"
|
|
61
62
|
},
|
|
62
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "3ecfca088f24489f2e8fa5493d0f4459b08880e1"
|
|
63
64
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AuthStateSignup,
|
|
2
3
|
ConstructorOpts,
|
|
3
4
|
ParaCore,
|
|
4
5
|
Environment,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
getSHA256HashHex,
|
|
13
14
|
parseCredentialCreationRes,
|
|
14
15
|
} from '@getpara/web-sdk';
|
|
16
|
+
import * as Sentry from '@sentry/react-native';
|
|
15
17
|
|
|
16
18
|
import { ReactNativeUtils } from './ReactNativeUtils.js';
|
|
17
19
|
import {
|
|
@@ -21,7 +23,7 @@ import {
|
|
|
21
23
|
PasskeyGetRequest,
|
|
22
24
|
PasskeyGetResult,
|
|
23
25
|
} from 'react-native-passkey';
|
|
24
|
-
import {
|
|
26
|
+
import { CurrentWalletIds, PublicKeyStatus, TWalletScheme } from '@getpara/user-management-client';
|
|
25
27
|
import { setEnv } from '../config.js';
|
|
26
28
|
import base64url from 'base64url';
|
|
27
29
|
import { webcrypto } from 'crypto';
|
|
@@ -37,6 +39,8 @@ const RS256_ALGORITHM = -257;
|
|
|
37
39
|
* const para = new ParaMobile(Environment.BETA, "api_key");
|
|
38
40
|
*/
|
|
39
41
|
export class ParaMobile extends ParaCore {
|
|
42
|
+
isNativePasskey = true;
|
|
43
|
+
|
|
40
44
|
private relyingPartyId: string;
|
|
41
45
|
/**
|
|
42
46
|
* Creates an instance of ParaMobile.
|
|
@@ -45,9 +49,18 @@ export class ParaMobile extends ParaCore {
|
|
|
45
49
|
* @param {string} [relyingPartyId] - The relying party ID for WebAuthn.
|
|
46
50
|
* @param {ConstructorOpts} [opts] - Additional constructor options.
|
|
47
51
|
*/
|
|
48
|
-
constructor(env: Environment, apiKey
|
|
52
|
+
constructor(env: Environment, apiKey: string, relyingPartyId?: string, opts?: ConstructorOpts) {
|
|
49
53
|
super(env, apiKey, opts);
|
|
50
54
|
|
|
55
|
+
// starting with non-prod to see what kind of errors we get and if sensitive data is tracked
|
|
56
|
+
// will turn on in prod after monitoring
|
|
57
|
+
if (env !== Environment.PROD && env !== Environment.DEV) {
|
|
58
|
+
Sentry.init({
|
|
59
|
+
environment: env.toLowerCase(),
|
|
60
|
+
dsn: 'https://59cea0cfbbb30a646c4e9f2feea06da4@o4504568036720640.ingest.us.sentry.io/4508850922323968',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
51
64
|
setEnv(env);
|
|
52
65
|
|
|
53
66
|
if (relyingPartyId) {
|
|
@@ -73,40 +86,20 @@ export class ParaMobile extends ParaCore {
|
|
|
73
86
|
return new ReactNativeUtils();
|
|
74
87
|
}
|
|
75
88
|
|
|
76
|
-
/**
|
|
77
|
-
* Verifies an email and returns the biometrics ID.
|
|
78
|
-
* @param {string} verificationCode - The verification code sent to the email.
|
|
79
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
80
|
-
*/
|
|
81
|
-
async verifyEmailBiometricsId({ verificationCode }: { verificationCode: string }): Promise<string> {
|
|
82
|
-
const webAuthCreateUrl = await super.verifyEmail({ verificationCode });
|
|
83
|
-
const segments = webAuthCreateUrl.split('/');
|
|
84
|
-
const segments2 = segments[segments.length - 1]!.split('?');
|
|
85
|
-
const biometricsId = segments2[0]!;
|
|
86
|
-
|
|
87
|
-
return biometricsId;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Verifies a phone number and returns the biometrics ID.
|
|
92
|
-
* @param {string} verificationCode - The verification code sent to the phone.
|
|
93
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
94
|
-
*/
|
|
95
|
-
async verifyPhoneBiometricsId({ verificationCode }: { verificationCode: string }): Promise<string> {
|
|
96
|
-
const webAuthCreateUrl = await super.verifyPhone({ verificationCode });
|
|
97
|
-
const segments = webAuthCreateUrl.split('/');
|
|
98
|
-
const segments2 = segments[segments.length - 1]!.split('?');
|
|
99
|
-
const biometricsId = segments2[0]!;
|
|
100
|
-
|
|
101
|
-
return biometricsId;
|
|
102
|
-
}
|
|
103
89
|
/**
|
|
104
90
|
* Registers a passkey for the user.
|
|
105
91
|
* @param {Auth<'email'> | Auth<'phone'>} auth - The user's authentication details
|
|
106
92
|
* @param {string} biometricsId - The biometrics ID obtained from verification.
|
|
107
93
|
* @returns {Promise<void>}
|
|
108
94
|
*/
|
|
109
|
-
async registerPasskey(
|
|
95
|
+
async registerPasskey(authState: AuthStateSignup) {
|
|
96
|
+
if (!authState.passkeyId) {
|
|
97
|
+
throw new Error('Passkey ID not found. Make sure you have enabled passkey logins in the Para Developer Portal.');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const userId = this.assertUserId();
|
|
101
|
+
const authInfo = this.assertIsAuthSet();
|
|
102
|
+
|
|
110
103
|
if (!webcrypto || !webcrypto.getRandomValues) {
|
|
111
104
|
throw new Error('Web crypto is not available. Ensure you have imported the shim from @getpara/react-native-wallet.');
|
|
112
105
|
}
|
|
@@ -114,8 +107,6 @@ export class ParaMobile extends ParaCore {
|
|
|
114
107
|
webcrypto.getRandomValues(userHandle);
|
|
115
108
|
const userHandleEncoded = base64url.encode(userHandle as any);
|
|
116
109
|
|
|
117
|
-
const { identifier: displayIdentifier } = extractAuthInfo(auth, { isRequired: true });
|
|
118
|
-
|
|
119
110
|
const requestJson: PasskeyCreateRequest = {
|
|
120
111
|
authenticatorSelection: {
|
|
121
112
|
authenticatorAttachment: 'platform' as any,
|
|
@@ -129,8 +120,8 @@ export class ParaMobile extends ParaCore {
|
|
|
129
120
|
},
|
|
130
121
|
user: {
|
|
131
122
|
id: userHandleEncoded,
|
|
132
|
-
name:
|
|
133
|
-
displayName:
|
|
123
|
+
name: authInfo.identifier,
|
|
124
|
+
displayName: authInfo.identifier,
|
|
134
125
|
},
|
|
135
126
|
pubKeyCredParams: [
|
|
136
127
|
{
|
|
@@ -164,8 +155,8 @@ export class ParaMobile extends ParaCore {
|
|
|
164
155
|
const encryptionKeyHash = getSHA256HashHex(userHandleEncoded);
|
|
165
156
|
const encryptedPrivateKeyHex = await encryptPrivateKey(keyPair, userHandleEncoded);
|
|
166
157
|
|
|
167
|
-
const
|
|
168
|
-
await this.ctx.client.patchSessionPublicKey(
|
|
158
|
+
const { partnerId } = await this.ctx.client.touchSession();
|
|
159
|
+
await this.ctx.client.patchSessionPublicKey(partnerId, userId, authState.passkeyId, {
|
|
169
160
|
publicKey: resultJson.id,
|
|
170
161
|
sigDerivedPublicKey: publicKeyHex,
|
|
171
162
|
cosePublicKey,
|
|
@@ -173,12 +164,7 @@ export class ParaMobile extends ParaCore {
|
|
|
173
164
|
status: PublicKeyStatus.COMPLETE,
|
|
174
165
|
});
|
|
175
166
|
|
|
176
|
-
await this.ctx.client.uploadEncryptedWalletPrivateKey(
|
|
177
|
-
this.getUserId()!,
|
|
178
|
-
encryptedPrivateKeyHex,
|
|
179
|
-
encryptionKeyHash,
|
|
180
|
-
resultJson.id,
|
|
181
|
-
);
|
|
167
|
+
await this.ctx.client.uploadEncryptedWalletPrivateKey(userId, encryptedPrivateKeyHex, encryptionKeyHash, resultJson.id);
|
|
182
168
|
}
|
|
183
169
|
|
|
184
170
|
/**
|
|
@@ -186,12 +172,11 @@ export class ParaMobile extends ParaCore {
|
|
|
186
172
|
* @param {AuthParams} params - The authentication parameters.
|
|
187
173
|
* @returns {Promise<void>}
|
|
188
174
|
*/
|
|
189
|
-
async
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const authInfo = extractAuthInfo(auth, { isRequired: true });
|
|
175
|
+
async loginWithPasskey(): Promise<void> {
|
|
176
|
+
this.assertIsAuthSet();
|
|
177
|
+
const userId = this.assertUserId();
|
|
193
178
|
|
|
194
|
-
const { challenge, allowedPublicKeys } = await this.ctx.client.getWebChallenge(
|
|
179
|
+
const { challenge, allowedPublicKeys } = await this.ctx.client.getWebChallenge({ userId });
|
|
195
180
|
|
|
196
181
|
const requestJson: PasskeyGetRequest = {
|
|
197
182
|
challenge,
|
|
@@ -210,9 +195,9 @@ export class ParaMobile extends ParaCore {
|
|
|
210
195
|
resultJson = result;
|
|
211
196
|
}
|
|
212
197
|
|
|
213
|
-
const
|
|
198
|
+
const { partnerId, sessionLookupId } = await this.ctx.client.touchSession();
|
|
214
199
|
const publicKey = resultJson.id;
|
|
215
|
-
const verifyWebChallengeResult = await this.ctx.client.verifyWebChallenge(
|
|
200
|
+
const verifyWebChallengeResult = await this.ctx.client.verifyWebChallenge(partnerId, {
|
|
216
201
|
publicKey,
|
|
217
202
|
signature: {
|
|
218
203
|
clientDataJSON: resultJson.response.clientDataJSON,
|
|
@@ -221,22 +206,8 @@ export class ParaMobile extends ParaCore {
|
|
|
221
206
|
},
|
|
222
207
|
});
|
|
223
208
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
await this.setUserId(userId);
|
|
227
|
-
|
|
228
|
-
const { user } = await this.ctx.client.getUser(userId);
|
|
229
|
-
|
|
230
|
-
if (user.phone) {
|
|
231
|
-
await this.setPhoneNumber(user.phone.number, user.phone.countryCode);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (user.email) {
|
|
235
|
-
await this.setEmail(user.email);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (user.farcasterUsername) {
|
|
239
|
-
await this.setFarcasterUsername(user.farcasterUsername);
|
|
209
|
+
if (userId !== verifyWebChallengeResult.data.userId) {
|
|
210
|
+
throw new Error('User ID mismatch');
|
|
240
211
|
}
|
|
241
212
|
|
|
242
213
|
const encryptedSharesResult = await this.ctx.client.getBiometricKeyshares(userId, resultJson.id);
|
|
@@ -278,7 +249,7 @@ export class ParaMobile extends ParaCore {
|
|
|
278
249
|
signer: decryptedShare.signer,
|
|
279
250
|
address: desiredWallet.address || undefined,
|
|
280
251
|
publicKey: desiredWallet.publicKey || undefined,
|
|
281
|
-
scheme: desiredWallet.scheme as
|
|
252
|
+
scheme: desiredWallet.scheme as TWalletScheme,
|
|
282
253
|
type: desiredWallet.type || undefined,
|
|
283
254
|
};
|
|
284
255
|
}
|
|
@@ -292,7 +263,7 @@ export class ParaMobile extends ParaCore {
|
|
|
292
263
|
|
|
293
264
|
await this.setWallets(walletsToInsert);
|
|
294
265
|
await this.setCurrentWalletIds(currentWalletIds, {
|
|
295
|
-
sessionLookupId
|
|
266
|
+
sessionLookupId,
|
|
296
267
|
});
|
|
297
268
|
}
|
|
298
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';
|
|
@@ -70,7 +70,7 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
70
70
|
async keygen(
|
|
71
71
|
ctx: Ctx,
|
|
72
72
|
userId: string,
|
|
73
|
-
type: Exclude<
|
|
73
|
+
type: Exclude<TWalletType, 'SOLANA'>,
|
|
74
74
|
_secretKey: string | null,
|
|
75
75
|
_sessionCookie: string,
|
|
76
76
|
_emailProps?: BackupKitEmailProps | undefined,
|
|
@@ -78,7 +78,7 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
78
78
|
const { walletId, protocolId } = await ctx.client.createWallet(userId, {
|
|
79
79
|
type,
|
|
80
80
|
useTwoSigners: true,
|
|
81
|
-
scheme: ctx.useDKLS ?
|
|
81
|
+
scheme: ctx.useDKLS ? 'DKLS' : 'CGGMP',
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
if (ctx.mpcComputationClient && !ctx.useDKLS) {
|
|
@@ -221,8 +221,8 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
221
221
|
walletId: string;
|
|
222
222
|
}> {
|
|
223
223
|
const { walletId, protocolId } = await ctx.client.createWallet(userId, {
|
|
224
|
-
scheme:
|
|
225
|
-
type:
|
|
224
|
+
scheme: 'ED25519',
|
|
225
|
+
type: 'SOLANA',
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
const signer = await ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
@@ -241,8 +241,8 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
241
241
|
const { walletId, protocolId } = await ctx.client.createPregenWallet({
|
|
242
242
|
pregenIdentifier,
|
|
243
243
|
pregenIdentifierType,
|
|
244
|
-
scheme:
|
|
245
|
-
type:
|
|
244
|
+
scheme: 'ED25519',
|
|
245
|
+
type: 'SOLANA',
|
|
246
246
|
});
|
|
247
247
|
|
|
248
248
|
const signer = await ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
@@ -257,7 +257,7 @@ export class ReactNativeUtils implements PlatformUtils {
|
|
|
257
257
|
base64Bytes: string,
|
|
258
258
|
_sessionCookie: string,
|
|
259
259
|
): Promise<SignatureRes> {
|
|
260
|
-
const { protocolId } = await ctx.client.preSignMessage(userId, walletId, base64Bytes,
|
|
260
|
+
const { protocolId } = await ctx.client.preSignMessage(userId, walletId, base64Bytes, 'ED25519');
|
|
261
261
|
|
|
262
262
|
const base64Sig = await ParaSignerModule.ed25519Sign(protocolId, share, base64Bytes);
|
|
263
263
|
return { signature: base64Sig };
|