@getpara/react-native-wallet 1.11.0 → 2.0.0-alpha.10
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 +22 -73
- package/dist/react-native/ReactNativeUtils.d.ts +3 -2
- package/dist/react-native/ReactNativeUtils.js +8 -7
- package/package.json +6 -6
- package/src/react-native/ParaMobile.ts +28 -67
- package/src/react-native/ReactNativeUtils.ts +9 -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,22 +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';
|
|
22
11
|
import * as Sentry from '@sentry/react-native';
|
|
23
12
|
import { ReactNativeUtils } from './ReactNativeUtils.js';
|
|
24
13
|
import { Passkey, } from 'react-native-passkey';
|
|
25
|
-
import {
|
|
14
|
+
import { PublicKeyStatus } from '@getpara/user-management-client';
|
|
26
15
|
import { setEnv } from '../config.js';
|
|
27
16
|
import base64url from 'base64url';
|
|
28
17
|
import { webcrypto } from 'crypto';
|
|
@@ -45,6 +34,7 @@ export class ParaMobile extends ParaCore {
|
|
|
45
34
|
*/
|
|
46
35
|
constructor(env, apiKey, relyingPartyId, opts) {
|
|
47
36
|
super(env, apiKey, opts);
|
|
37
|
+
this.isNativePasskey = true;
|
|
48
38
|
// starting with non-prod to see what kind of errors we get and if sensitive data is tracked
|
|
49
39
|
// will turn on in prod after monitoring
|
|
50
40
|
if (env !== Environment.PROD && env !== Environment.DEV) {
|
|
@@ -76,56 +66,25 @@ export class ParaMobile extends ParaCore {
|
|
|
76
66
|
getPlatformUtils() {
|
|
77
67
|
return new ReactNativeUtils();
|
|
78
68
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Verifies an email and returns the biometrics ID.
|
|
81
|
-
* @param {string} verificationCode - The verification code sent to the email.
|
|
82
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
83
|
-
*/
|
|
84
|
-
verifyEmailBiometricsId(_a) {
|
|
85
|
-
const _super = Object.create(null, {
|
|
86
|
-
verifyEmail: { get: () => super.verifyEmail }
|
|
87
|
-
});
|
|
88
|
-
return __awaiter(this, arguments, void 0, function* ({ verificationCode }) {
|
|
89
|
-
const webAuthCreateUrl = yield _super.verifyEmail.call(this, { verificationCode });
|
|
90
|
-
const segments = webAuthCreateUrl.split('/');
|
|
91
|
-
const segments2 = segments[segments.length - 1].split('?');
|
|
92
|
-
const biometricsId = segments2[0];
|
|
93
|
-
return biometricsId;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Verifies a phone number and returns the biometrics ID.
|
|
98
|
-
* @param {string} verificationCode - The verification code sent to the phone.
|
|
99
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
100
|
-
*/
|
|
101
|
-
verifyPhoneBiometricsId(_a) {
|
|
102
|
-
const _super = Object.create(null, {
|
|
103
|
-
verifyPhone: { get: () => super.verifyPhone }
|
|
104
|
-
});
|
|
105
|
-
return __awaiter(this, arguments, void 0, function* ({ verificationCode }) {
|
|
106
|
-
const webAuthCreateUrl = yield _super.verifyPhone.call(this, { verificationCode });
|
|
107
|
-
const segments = webAuthCreateUrl.split('/');
|
|
108
|
-
const segments2 = segments[segments.length - 1].split('?');
|
|
109
|
-
const biometricsId = segments2[0];
|
|
110
|
-
return biometricsId;
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
69
|
/**
|
|
114
70
|
* Registers a passkey for the user.
|
|
115
71
|
* @param {Auth<'email'> | Auth<'phone'>} auth - The user's authentication details
|
|
116
72
|
* @param {string} biometricsId - The biometrics ID obtained from verification.
|
|
117
73
|
* @returns {Promise<void>}
|
|
118
74
|
*/
|
|
119
|
-
registerPasskey(
|
|
75
|
+
registerPasskey(authState) {
|
|
120
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
-
|
|
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();
|
|
122
82
|
if (!webcrypto || !webcrypto.getRandomValues) {
|
|
123
83
|
throw new Error('Web crypto is not available. Ensure you have imported the shim from @getpara/react-native-wallet.');
|
|
124
84
|
}
|
|
125
85
|
const userHandle = new Uint8Array(32);
|
|
126
86
|
webcrypto.getRandomValues(userHandle);
|
|
127
87
|
const userHandleEncoded = base64url.encode(userHandle);
|
|
128
|
-
const { identifier: displayIdentifier } = extractAuthInfo(auth, { isRequired: true });
|
|
129
88
|
const requestJson = {
|
|
130
89
|
authenticatorSelection: {
|
|
131
90
|
authenticatorAttachment: 'platform',
|
|
@@ -139,8 +98,8 @@ export class ParaMobile extends ParaCore {
|
|
|
139
98
|
},
|
|
140
99
|
user: {
|
|
141
100
|
id: userHandleEncoded,
|
|
142
|
-
name:
|
|
143
|
-
displayName:
|
|
101
|
+
name: authInfo.identifier,
|
|
102
|
+
displayName: authInfo.identifier,
|
|
144
103
|
},
|
|
145
104
|
pubKeyCredParams: [
|
|
146
105
|
{
|
|
@@ -169,15 +128,15 @@ export class ParaMobile extends ParaCore {
|
|
|
169
128
|
const publicKeyHex = getPublicKeyHex(keyPair);
|
|
170
129
|
const encryptionKeyHash = getSHA256HashHex(userHandleEncoded);
|
|
171
130
|
const encryptedPrivateKeyHex = yield encryptPrivateKey(keyPair, userHandleEncoded);
|
|
172
|
-
const
|
|
173
|
-
yield this.ctx.client.patchSessionPublicKey(
|
|
131
|
+
const { partnerId } = yield this.ctx.client.touchSession();
|
|
132
|
+
yield this.ctx.client.patchSessionPublicKey(partnerId, userId, authState.passkeyId, {
|
|
174
133
|
publicKey: resultJson.id,
|
|
175
134
|
sigDerivedPublicKey: publicKeyHex,
|
|
176
135
|
cosePublicKey,
|
|
177
136
|
clientDataJSON,
|
|
178
137
|
status: PublicKeyStatus.COMPLETE,
|
|
179
138
|
});
|
|
180
|
-
yield this.ctx.client.uploadEncryptedWalletPrivateKey(
|
|
139
|
+
yield this.ctx.client.uploadEncryptedWalletPrivateKey(userId, encryptedPrivateKeyHex, encryptionKeyHash, resultJson.id);
|
|
181
140
|
});
|
|
182
141
|
}
|
|
183
142
|
/**
|
|
@@ -185,12 +144,11 @@ export class ParaMobile extends ParaCore {
|
|
|
185
144
|
* @param {AuthParams} params - The authentication parameters.
|
|
186
145
|
* @returns {Promise<void>}
|
|
187
146
|
*/
|
|
188
|
-
|
|
147
|
+
loginWithPasskey() {
|
|
189
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
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 });
|
|
194
152
|
const requestJson = {
|
|
195
153
|
challenge,
|
|
196
154
|
timeout: 60000,
|
|
@@ -205,9 +163,9 @@ export class ParaMobile extends ParaCore {
|
|
|
205
163
|
else {
|
|
206
164
|
resultJson = result;
|
|
207
165
|
}
|
|
208
|
-
const
|
|
166
|
+
const { partnerId, sessionLookupId } = yield this.ctx.client.touchSession();
|
|
209
167
|
const publicKey = resultJson.id;
|
|
210
|
-
const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(
|
|
168
|
+
const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(partnerId, {
|
|
211
169
|
publicKey,
|
|
212
170
|
signature: {
|
|
213
171
|
clientDataJSON: resultJson.response.clientDataJSON,
|
|
@@ -215,17 +173,8 @@ export class ParaMobile extends ParaCore {
|
|
|
215
173
|
signature: resultJson.response.signature,
|
|
216
174
|
},
|
|
217
175
|
});
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const { user } = yield this.ctx.client.getUser(userId);
|
|
221
|
-
if (user.phone) {
|
|
222
|
-
yield this.setPhoneNumber(user.phone.number, user.phone.countryCode);
|
|
223
|
-
}
|
|
224
|
-
if (user.email) {
|
|
225
|
-
yield this.setEmail(user.email);
|
|
226
|
-
}
|
|
227
|
-
if (user.farcasterUsername) {
|
|
228
|
-
yield this.setFarcasterUsername(user.farcasterUsername);
|
|
176
|
+
if (userId !== verifyWebChallengeResult.data.userId) {
|
|
177
|
+
throw new Error('User ID mismatch');
|
|
229
178
|
}
|
|
230
179
|
const encryptedSharesResult = yield this.ctx.client.getBiometricKeyshares(userId, resultJson.id);
|
|
231
180
|
const encryptionKeyHash = getSHA256HashHex(resultJson.response.userHandle);
|
|
@@ -262,7 +211,7 @@ export class ParaMobile extends ParaCore {
|
|
|
262
211
|
}
|
|
263
212
|
yield this.setWallets(walletsToInsert);
|
|
264
213
|
yield this.setCurrentWalletIds(currentWalletIds, {
|
|
265
|
-
sessionLookupId
|
|
214
|
+
sessionLookupId,
|
|
266
215
|
});
|
|
267
216
|
});
|
|
268
217
|
}
|
|
@@ -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpara/react-native-wallet",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-alpha.10",
|
|
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,11 +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.10",
|
|
26
|
+
"@getpara/user-management-client": "2.0.0-alpha.10",
|
|
27
|
+
"@getpara/web-sdk": "2.0.0-alpha.10",
|
|
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"
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "92904c321f1dd8101046d8d2d70aa341bac99842"
|
|
64
64
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AuthStateSignup,
|
|
2
3
|
ConstructorOpts,
|
|
3
4
|
ParaCore,
|
|
4
5
|
Environment,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
PasskeyGetRequest,
|
|
23
24
|
PasskeyGetResult,
|
|
24
25
|
} from 'react-native-passkey';
|
|
25
|
-
import {
|
|
26
|
+
import { CurrentWalletIds, PublicKeyStatus, TWalletScheme } from '@getpara/user-management-client';
|
|
26
27
|
import { setEnv } from '../config.js';
|
|
27
28
|
import base64url from 'base64url';
|
|
28
29
|
import { webcrypto } from 'crypto';
|
|
@@ -38,6 +39,8 @@ const RS256_ALGORITHM = -257;
|
|
|
38
39
|
* const para = new ParaMobile(Environment.BETA, "api_key");
|
|
39
40
|
*/
|
|
40
41
|
export class ParaMobile extends ParaCore {
|
|
42
|
+
isNativePasskey = true;
|
|
43
|
+
|
|
41
44
|
private relyingPartyId: string;
|
|
42
45
|
/**
|
|
43
46
|
* Creates an instance of ParaMobile.
|
|
@@ -46,7 +49,7 @@ export class ParaMobile extends ParaCore {
|
|
|
46
49
|
* @param {string} [relyingPartyId] - The relying party ID for WebAuthn.
|
|
47
50
|
* @param {ConstructorOpts} [opts] - Additional constructor options.
|
|
48
51
|
*/
|
|
49
|
-
constructor(env: Environment, apiKey
|
|
52
|
+
constructor(env: Environment, apiKey: string, relyingPartyId?: string, opts?: ConstructorOpts) {
|
|
50
53
|
super(env, apiKey, opts);
|
|
51
54
|
|
|
52
55
|
// starting with non-prod to see what kind of errors we get and if sensitive data is tracked
|
|
@@ -83,40 +86,20 @@ export class ParaMobile extends ParaCore {
|
|
|
83
86
|
return new ReactNativeUtils();
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
/**
|
|
87
|
-
* Verifies an email and returns the biometrics ID.
|
|
88
|
-
* @param {string} verificationCode - The verification code sent to the email.
|
|
89
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
90
|
-
*/
|
|
91
|
-
async verifyEmailBiometricsId({ verificationCode }: { verificationCode: string }): Promise<string> {
|
|
92
|
-
const webAuthCreateUrl = await super.verifyEmail({ verificationCode });
|
|
93
|
-
const segments = webAuthCreateUrl.split('/');
|
|
94
|
-
const segments2 = segments[segments.length - 1]!.split('?');
|
|
95
|
-
const biometricsId = segments2[0]!;
|
|
96
|
-
|
|
97
|
-
return biometricsId;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Verifies a phone number and returns the biometrics ID.
|
|
102
|
-
* @param {string} verificationCode - The verification code sent to the phone.
|
|
103
|
-
* @returns {Promise<string>} The biometrics ID.
|
|
104
|
-
*/
|
|
105
|
-
async verifyPhoneBiometricsId({ verificationCode }: { verificationCode: string }): Promise<string> {
|
|
106
|
-
const webAuthCreateUrl = await super.verifyPhone({ verificationCode });
|
|
107
|
-
const segments = webAuthCreateUrl.split('/');
|
|
108
|
-
const segments2 = segments[segments.length - 1]!.split('?');
|
|
109
|
-
const biometricsId = segments2[0]!;
|
|
110
|
-
|
|
111
|
-
return biometricsId;
|
|
112
|
-
}
|
|
113
89
|
/**
|
|
114
90
|
* Registers a passkey for the user.
|
|
115
91
|
* @param {Auth<'email'> | Auth<'phone'>} auth - The user's authentication details
|
|
116
92
|
* @param {string} biometricsId - The biometrics ID obtained from verification.
|
|
117
93
|
* @returns {Promise<void>}
|
|
118
94
|
*/
|
|
119
|
-
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
|
+
|
|
120
103
|
if (!webcrypto || !webcrypto.getRandomValues) {
|
|
121
104
|
throw new Error('Web crypto is not available. Ensure you have imported the shim from @getpara/react-native-wallet.');
|
|
122
105
|
}
|
|
@@ -124,8 +107,6 @@ export class ParaMobile extends ParaCore {
|
|
|
124
107
|
webcrypto.getRandomValues(userHandle);
|
|
125
108
|
const userHandleEncoded = base64url.encode(userHandle as any);
|
|
126
109
|
|
|
127
|
-
const { identifier: displayIdentifier } = extractAuthInfo(auth, { isRequired: true });
|
|
128
|
-
|
|
129
110
|
const requestJson: PasskeyCreateRequest = {
|
|
130
111
|
authenticatorSelection: {
|
|
131
112
|
authenticatorAttachment: 'platform' as any,
|
|
@@ -139,8 +120,8 @@ export class ParaMobile extends ParaCore {
|
|
|
139
120
|
},
|
|
140
121
|
user: {
|
|
141
122
|
id: userHandleEncoded,
|
|
142
|
-
name:
|
|
143
|
-
displayName:
|
|
123
|
+
name: authInfo.identifier,
|
|
124
|
+
displayName: authInfo.identifier,
|
|
144
125
|
},
|
|
145
126
|
pubKeyCredParams: [
|
|
146
127
|
{
|
|
@@ -174,8 +155,8 @@ export class ParaMobile extends ParaCore {
|
|
|
174
155
|
const encryptionKeyHash = getSHA256HashHex(userHandleEncoded);
|
|
175
156
|
const encryptedPrivateKeyHex = await encryptPrivateKey(keyPair, userHandleEncoded);
|
|
176
157
|
|
|
177
|
-
const
|
|
178
|
-
await this.ctx.client.patchSessionPublicKey(
|
|
158
|
+
const { partnerId } = await this.ctx.client.touchSession();
|
|
159
|
+
await this.ctx.client.patchSessionPublicKey(partnerId, userId, authState.passkeyId, {
|
|
179
160
|
publicKey: resultJson.id,
|
|
180
161
|
sigDerivedPublicKey: publicKeyHex,
|
|
181
162
|
cosePublicKey,
|
|
@@ -183,12 +164,7 @@ export class ParaMobile extends ParaCore {
|
|
|
183
164
|
status: PublicKeyStatus.COMPLETE,
|
|
184
165
|
});
|
|
185
166
|
|
|
186
|
-
await this.ctx.client.uploadEncryptedWalletPrivateKey(
|
|
187
|
-
this.getUserId()!,
|
|
188
|
-
encryptedPrivateKeyHex,
|
|
189
|
-
encryptionKeyHash,
|
|
190
|
-
resultJson.id,
|
|
191
|
-
);
|
|
167
|
+
await this.ctx.client.uploadEncryptedWalletPrivateKey(userId, encryptedPrivateKeyHex, encryptionKeyHash, resultJson.id);
|
|
192
168
|
}
|
|
193
169
|
|
|
194
170
|
/**
|
|
@@ -196,12 +172,11 @@ export class ParaMobile extends ParaCore {
|
|
|
196
172
|
* @param {AuthParams} params - The authentication parameters.
|
|
197
173
|
* @returns {Promise<void>}
|
|
198
174
|
*/
|
|
199
|
-
async
|
|
200
|
-
|
|
175
|
+
async loginWithPasskey(): Promise<void> {
|
|
176
|
+
this.assertIsAuthSet();
|
|
177
|
+
const userId = this.assertUserId();
|
|
201
178
|
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
const { challenge, allowedPublicKeys } = await this.ctx.client.getWebChallenge(authInfo.auth);
|
|
179
|
+
const { challenge, allowedPublicKeys } = await this.ctx.client.getWebChallenge({ userId });
|
|
205
180
|
|
|
206
181
|
const requestJson: PasskeyGetRequest = {
|
|
207
182
|
challenge,
|
|
@@ -220,9 +195,9 @@ export class ParaMobile extends ParaCore {
|
|
|
220
195
|
resultJson = result;
|
|
221
196
|
}
|
|
222
197
|
|
|
223
|
-
const
|
|
198
|
+
const { partnerId, sessionLookupId } = await this.ctx.client.touchSession();
|
|
224
199
|
const publicKey = resultJson.id;
|
|
225
|
-
const verifyWebChallengeResult = await this.ctx.client.verifyWebChallenge(
|
|
200
|
+
const verifyWebChallengeResult = await this.ctx.client.verifyWebChallenge(partnerId, {
|
|
226
201
|
publicKey,
|
|
227
202
|
signature: {
|
|
228
203
|
clientDataJSON: resultJson.response.clientDataJSON,
|
|
@@ -231,22 +206,8 @@ export class ParaMobile extends ParaCore {
|
|
|
231
206
|
},
|
|
232
207
|
});
|
|
233
208
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
await this.setUserId(userId);
|
|
237
|
-
|
|
238
|
-
const { user } = await this.ctx.client.getUser(userId);
|
|
239
|
-
|
|
240
|
-
if (user.phone) {
|
|
241
|
-
await this.setPhoneNumber(user.phone.number, user.phone.countryCode);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (user.email) {
|
|
245
|
-
await this.setEmail(user.email);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (user.farcasterUsername) {
|
|
249
|
-
await this.setFarcasterUsername(user.farcasterUsername);
|
|
209
|
+
if (userId !== verifyWebChallengeResult.data.userId) {
|
|
210
|
+
throw new Error('User ID mismatch');
|
|
250
211
|
}
|
|
251
212
|
|
|
252
213
|
const encryptedSharesResult = await this.ctx.client.getBiometricKeyshares(userId, resultJson.id);
|
|
@@ -288,7 +249,7 @@ export class ParaMobile extends ParaCore {
|
|
|
288
249
|
signer: decryptedShare.signer,
|
|
289
250
|
address: desiredWallet.address || undefined,
|
|
290
251
|
publicKey: desiredWallet.publicKey || undefined,
|
|
291
|
-
scheme: desiredWallet.scheme as
|
|
252
|
+
scheme: desiredWallet.scheme as TWalletScheme,
|
|
292
253
|
type: desiredWallet.type || undefined,
|
|
293
254
|
};
|
|
294
255
|
}
|
|
@@ -302,7 +263,7 @@ export class ParaMobile extends ParaCore {
|
|
|
302
263
|
|
|
303
264
|
await this.setWallets(walletsToInsert);
|
|
304
265
|
await this.setCurrentWalletIds(currentWalletIds, {
|
|
305
|
-
sessionLookupId
|
|
266
|
+
sessionLookupId,
|
|
306
267
|
});
|
|
307
268
|
}
|
|
308
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 };
|