@getpara/react-native-wallet 0.1.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.
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build.gradle +76 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/para/reactnativewallet/ParaSignerModule.java +294 -0
- package/android/src/main/java/com/para/reactnativewallet/ParaSignerPackage.java +30 -0
- package/capsule-react-native-wallet.podspec +36 -0
- package/dist/AsyncStorage.d.ts +10 -0
- package/dist/AsyncStorage.js +41 -0
- package/dist/KeychainStorage.d.ts +10 -0
- package/dist/KeychainStorage.js +72 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +61 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/react-native/ParaMobile.d.ts +49 -0
- package/dist/react-native/ParaMobile.js +237 -0
- package/dist/react-native/ReactNativeUtils.d.ts +50 -0
- package/dist/react-native/ReactNativeUtils.js +171 -0
- package/dist/shim.d.ts +1 -0
- package/dist/shim.js +49 -0
- package/ios/ParaSignerModule.h +12 -0
- package/ios/ParaSignerModule.m +411 -0
- package/ios/ReactNativeWallet.xcodeproj/project.pbxproj +269 -0
- package/package.json +63 -0
- package/signer.xcframework/Info.plist +44 -0
- package/signer.xcframework/ios-arm64/Signer.framework/Headers/Signer.h +13 -0
- package/signer.xcframework/ios-arm64/Signer.framework/Headers/Signer.objc.h +300 -0
- package/signer.xcframework/ios-arm64/Signer.framework/Headers/Universe.objc.h +29 -0
- package/signer.xcframework/ios-arm64/Signer.framework/Headers/ref.h +35 -0
- package/signer.xcframework/ios-arm64/Signer.framework/Info.plist +18 -0
- package/signer.xcframework/ios-arm64/Signer.framework/Modules/module.modulemap +8 -0
- package/signer.xcframework/ios-arm64/Signer.framework/Signer +0 -0
- package/signer.xcframework/ios-arm64_x86_64-simulator/Signer.framework/Headers/Signer.h +13 -0
- package/signer.xcframework/ios-arm64_x86_64-simulator/Signer.framework/Headers/Signer.objc.h +300 -0
- package/signer.xcframework/ios-arm64_x86_64-simulator/Signer.framework/Headers/Universe.objc.h +29 -0
- package/signer.xcframework/ios-arm64_x86_64-simulator/Signer.framework/Headers/ref.h +35 -0
- package/signer.xcframework/ios-arm64_x86_64-simulator/Signer.framework/Info.plist +18 -0
- package/signer.xcframework/ios-arm64_x86_64-simulator/Signer.framework/Modules/module.modulemap +8 -0
- package/signer.xcframework/ios-arm64_x86_64-simulator/Signer.framework/Signer +0 -0
- package/src/AsyncStorage.ts +30 -0
- package/src/KeychainStorage.ts +61 -0
- package/src/config.ts +70 -0
- package/src/index.tsx +2 -0
- package/src/react-native/ParaMobile.ts +294 -0
- package/src/react-native/ReactNativeUtils.ts +266 -0
- package/src/shim.js +59 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ConstructorOpts, ParaCore, Environment, PlatformUtils } from '@getpara/web-sdk';
|
|
2
|
+
import { webcrypto } from 'crypto';
|
|
3
|
+
import { CountryCallingCode } from 'libphonenumber-js';
|
|
4
|
+
/**
|
|
5
|
+
* Represents a mobile implementation of the Para SDK.
|
|
6
|
+
* @extends ParaCore
|
|
7
|
+
*/
|
|
8
|
+
export declare class ParaMobile extends ParaCore {
|
|
9
|
+
private relyingPartyId;
|
|
10
|
+
/**
|
|
11
|
+
* Creates an instance of ParaMobile.
|
|
12
|
+
* @param {Environment} env - The environment to use (DEV, SANDBOX, BETA, or PROD).
|
|
13
|
+
* @param {string} [apiKey] - The API key for authentication.
|
|
14
|
+
* @param {string} [relyingPartyId] - The relying party ID for WebAuthn.
|
|
15
|
+
* @param {ConstructorOpts} [opts] - Additional constructor options.
|
|
16
|
+
*/
|
|
17
|
+
constructor(env: Environment, apiKey?: string, relyingPartyId?: string, opts?: ConstructorOpts);
|
|
18
|
+
protected getPlatformUtils(): PlatformUtils;
|
|
19
|
+
/**
|
|
20
|
+
* Verifies an email and returns the biometrics ID.
|
|
21
|
+
* @param {string} verificationCode - The verification code sent to the email.
|
|
22
|
+
* @returns {Promise<string>} The biometrics ID.
|
|
23
|
+
*/
|
|
24
|
+
verifyEmailBiometricsId(verificationCode: string): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Verifies a phone number and returns the biometrics ID.
|
|
27
|
+
* @param {string} verificationCode - The verification code sent to the phone.
|
|
28
|
+
* @returns {Promise<string>} The biometrics ID.
|
|
29
|
+
*/
|
|
30
|
+
verifyPhoneBiometricsId(verificationCode: string): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Registers a passkey for the user.
|
|
33
|
+
* @param {string} identifier - The user's email or phone number.
|
|
34
|
+
* @param {string} biometricsId - The biometrics ID obtained from verification.
|
|
35
|
+
* @param {webcrypto.Crypto} crypto - The Web Crypto API instance.
|
|
36
|
+
* @param {'email' | 'phone'} [identifierType='email'] - The type of identifier used.
|
|
37
|
+
* @param {CountryCallingCode} [countryCode] - The country calling code for phone numbers.
|
|
38
|
+
* @returns {Promise<void>}
|
|
39
|
+
*/
|
|
40
|
+
registerPasskey(identifier: string, biometricsId: string, crypto: webcrypto.Crypto, identifierType?: 'email' | 'phone', countryCode?: CountryCallingCode): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Logs in the user using either email or phone number.
|
|
43
|
+
* @param {string} [email] - The user's email address.
|
|
44
|
+
* @param {string} [phone] - The user's phone number.
|
|
45
|
+
* @param {CountryCallingCode} [countryCode] - The country calling code for phone numbers.
|
|
46
|
+
* @returns {Promise<Wallet[]>} An array of user wallets.
|
|
47
|
+
*/
|
|
48
|
+
login(email?: string, phone?: string, countryCode?: CountryCallingCode): Promise<void>;
|
|
49
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// Copyright (c) Para Labs Inc. All rights reserved.
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
import { ParaCore, Environment, decryptPrivateKeyAndDecryptShare, encryptPrivateKey, getAsymmetricKeyPair, getDerivedPrivateKeyAndDecrypt, getPublicKeyHex, getSHA256HashHex, parseCredentialCreationRes, } from '@getpara/web-sdk';
|
|
12
|
+
import { ReactNativeUtils } from './ReactNativeUtils.js';
|
|
13
|
+
import { Passkey, } from 'react-native-passkey';
|
|
14
|
+
import { extractAuth, PublicKeyStatus } from '@getpara/user-management-client';
|
|
15
|
+
import { setEnv } from '../config.js';
|
|
16
|
+
import base64url from 'base64url';
|
|
17
|
+
const ES256_ALGORITHM = -7;
|
|
18
|
+
const RS256_ALGORITHM = -257;
|
|
19
|
+
/**
|
|
20
|
+
* Represents a mobile implementation of the Para SDK.
|
|
21
|
+
* @extends ParaCore
|
|
22
|
+
*/
|
|
23
|
+
export class ParaMobile extends ParaCore {
|
|
24
|
+
/**
|
|
25
|
+
* Creates an instance of ParaMobile.
|
|
26
|
+
* @param {Environment} env - The environment to use (DEV, SANDBOX, BETA, or PROD).
|
|
27
|
+
* @param {string} [apiKey] - The API key for authentication.
|
|
28
|
+
* @param {string} [relyingPartyId] - The relying party ID for WebAuthn.
|
|
29
|
+
* @param {ConstructorOpts} [opts] - Additional constructor options.
|
|
30
|
+
*/
|
|
31
|
+
constructor(env, apiKey, relyingPartyId, opts) {
|
|
32
|
+
super(env, apiKey, opts);
|
|
33
|
+
setEnv(env);
|
|
34
|
+
if (relyingPartyId) {
|
|
35
|
+
this.relyingPartyId = relyingPartyId;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
switch (env) {
|
|
39
|
+
case Environment.DEV:
|
|
40
|
+
throw new Error('relyingPartyId is required');
|
|
41
|
+
case Environment.SANDBOX:
|
|
42
|
+
this.relyingPartyId = 'app.sandbox.usecapsule.com';
|
|
43
|
+
break;
|
|
44
|
+
case Environment.BETA:
|
|
45
|
+
this.relyingPartyId = 'app.beta.usecapsule.com';
|
|
46
|
+
break;
|
|
47
|
+
case Environment.PROD:
|
|
48
|
+
this.relyingPartyId = 'app.usecapsule.com';
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
getPlatformUtils() {
|
|
54
|
+
return new ReactNativeUtils();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Verifies an email and returns the biometrics ID.
|
|
58
|
+
* @param {string} verificationCode - The verification code sent to the email.
|
|
59
|
+
* @returns {Promise<string>} The biometrics ID.
|
|
60
|
+
*/
|
|
61
|
+
verifyEmailBiometricsId(verificationCode) {
|
|
62
|
+
const _super = Object.create(null, {
|
|
63
|
+
verifyEmail: { get: () => super.verifyEmail }
|
|
64
|
+
});
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
const webAuthCreateUrl = yield _super.verifyEmail.call(this, verificationCode);
|
|
67
|
+
const segments = webAuthCreateUrl.split('/');
|
|
68
|
+
const segments2 = segments[segments.length - 1].split('?');
|
|
69
|
+
const biometricsId = segments2[0];
|
|
70
|
+
return biometricsId;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Verifies a phone number and returns the biometrics ID.
|
|
75
|
+
* @param {string} verificationCode - The verification code sent to the phone.
|
|
76
|
+
* @returns {Promise<string>} The biometrics ID.
|
|
77
|
+
*/
|
|
78
|
+
verifyPhoneBiometricsId(verificationCode) {
|
|
79
|
+
const _super = Object.create(null, {
|
|
80
|
+
verifyPhone: { get: () => super.verifyPhone }
|
|
81
|
+
});
|
|
82
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
const webAuthCreateUrl = yield _super.verifyPhone.call(this, verificationCode);
|
|
84
|
+
const segments = webAuthCreateUrl.split('/');
|
|
85
|
+
const segments2 = segments[segments.length - 1].split('?');
|
|
86
|
+
const biometricsId = segments2[0];
|
|
87
|
+
return biometricsId;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Registers a passkey for the user.
|
|
92
|
+
* @param {string} identifier - The user's email or phone number.
|
|
93
|
+
* @param {string} biometricsId - The biometrics ID obtained from verification.
|
|
94
|
+
* @param {webcrypto.Crypto} crypto - The Web Crypto API instance.
|
|
95
|
+
* @param {'email' | 'phone'} [identifierType='email'] - The type of identifier used.
|
|
96
|
+
* @param {CountryCallingCode} [countryCode] - The country calling code for phone numbers.
|
|
97
|
+
* @returns {Promise<void>}
|
|
98
|
+
*/
|
|
99
|
+
registerPasskey(identifier_1, biometricsId_1, crypto_1) {
|
|
100
|
+
return __awaiter(this, arguments, void 0, function* (identifier, biometricsId, crypto, identifierType = 'email', countryCode) {
|
|
101
|
+
const userHandle = new Uint8Array(32);
|
|
102
|
+
crypto.getRandomValues(userHandle);
|
|
103
|
+
const userHandleEncoded = base64url.encode(userHandle);
|
|
104
|
+
const displayIdentifier = identifierType === 'email' ? identifier : `${countryCode}${identifier}`;
|
|
105
|
+
const requestJson = {
|
|
106
|
+
authenticatorSelection: {
|
|
107
|
+
authenticatorAttachment: 'platform',
|
|
108
|
+
requireResidentKey: true,
|
|
109
|
+
residentKey: 'required',
|
|
110
|
+
userVerification: 'required',
|
|
111
|
+
},
|
|
112
|
+
rp: {
|
|
113
|
+
id: this.relyingPartyId,
|
|
114
|
+
name: 'Para',
|
|
115
|
+
},
|
|
116
|
+
user: {
|
|
117
|
+
id: userHandleEncoded,
|
|
118
|
+
name: displayIdentifier,
|
|
119
|
+
displayName: displayIdentifier,
|
|
120
|
+
},
|
|
121
|
+
pubKeyCredParams: [
|
|
122
|
+
{
|
|
123
|
+
type: 'public-key',
|
|
124
|
+
alg: ES256_ALGORITHM,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'public-key',
|
|
128
|
+
alg: RS256_ALGORITHM,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
attestation: 'direct',
|
|
132
|
+
timeout: 60000,
|
|
133
|
+
challenge: base64url.encode('somechallenge'),
|
|
134
|
+
};
|
|
135
|
+
const result = yield Passkey.create(requestJson);
|
|
136
|
+
let resultJson;
|
|
137
|
+
if (typeof result === 'string') {
|
|
138
|
+
resultJson = JSON.parse(result);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
resultJson = result;
|
|
142
|
+
}
|
|
143
|
+
const { cosePublicKey, clientDataJSON } = parseCredentialCreationRes(resultJson, ES256_ALGORITHM);
|
|
144
|
+
const keyPair = yield getAsymmetricKeyPair(this.ctx);
|
|
145
|
+
const publicKeyHex = getPublicKeyHex(keyPair);
|
|
146
|
+
const encryptionKeyHash = getSHA256HashHex(userHandleEncoded);
|
|
147
|
+
const encryptedPrivateKeyHex = yield encryptPrivateKey(keyPair, userHandleEncoded);
|
|
148
|
+
const session = yield this.ctx.client.touchSession();
|
|
149
|
+
yield this.ctx.client.patchSessionPublicKey(session.data.partnerId, this.getUserId(), biometricsId, {
|
|
150
|
+
publicKey: resultJson.id,
|
|
151
|
+
sigDerivedPublicKey: publicKeyHex,
|
|
152
|
+
cosePublicKey,
|
|
153
|
+
clientDataJSON,
|
|
154
|
+
status: PublicKeyStatus.COMPLETE,
|
|
155
|
+
});
|
|
156
|
+
yield this.ctx.client.uploadEncryptedWalletPrivateKey(this.getUserId(), encryptedPrivateKeyHex, encryptionKeyHash, resultJson.id);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Logs in the user using either email or phone number.
|
|
161
|
+
* @param {string} [email] - The user's email address.
|
|
162
|
+
* @param {string} [phone] - The user's phone number.
|
|
163
|
+
* @param {CountryCallingCode} [countryCode] - The country calling code for phone numbers.
|
|
164
|
+
* @returns {Promise<Wallet[]>} An array of user wallets.
|
|
165
|
+
*/
|
|
166
|
+
login(email, phone, countryCode) {
|
|
167
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
168
|
+
yield this.logout();
|
|
169
|
+
const auth = extractAuth({ email, phone, countryCode }, { optional: true });
|
|
170
|
+
const { challenge, allowedPublicKeys } = yield this.ctx.client.getWebChallenge(auth);
|
|
171
|
+
const requestJson = {
|
|
172
|
+
challenge,
|
|
173
|
+
timeout: 60000,
|
|
174
|
+
rpId: this.relyingPartyId,
|
|
175
|
+
allowCredentials: (allowedPublicKeys === null || allowedPublicKeys === void 0 ? void 0 : allowedPublicKeys[0]) ? [{ type: 'public-key', id: allowedPublicKeys[0] }] : [],
|
|
176
|
+
};
|
|
177
|
+
const result = yield Passkey.get(requestJson);
|
|
178
|
+
let resultJson;
|
|
179
|
+
if (typeof result === 'string') {
|
|
180
|
+
resultJson = JSON.parse(result);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
resultJson = result;
|
|
184
|
+
}
|
|
185
|
+
const session = yield this.ctx.client.touchSession();
|
|
186
|
+
const publicKey = resultJson.id;
|
|
187
|
+
const verifyWebChallengeResult = yield this.ctx.client.verifyWebChallenge(session.data.partnerId, {
|
|
188
|
+
publicKey,
|
|
189
|
+
signature: {
|
|
190
|
+
clientDataJSON: resultJson.response.clientDataJSON,
|
|
191
|
+
authenticatorData: resultJson.response.authenticatorData,
|
|
192
|
+
signature: resultJson.response.signature,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
const userId = verifyWebChallengeResult.data.userId;
|
|
196
|
+
yield this.setUserId(userId);
|
|
197
|
+
const { user } = yield this.ctx.client.getUser(userId);
|
|
198
|
+
if (user.phone) {
|
|
199
|
+
yield this.setPhoneNumber(user.phone.number, user.phone.countryCode);
|
|
200
|
+
}
|
|
201
|
+
if (user.email) {
|
|
202
|
+
yield this.setEmail(user.email);
|
|
203
|
+
}
|
|
204
|
+
if (user.farcasterUsername) {
|
|
205
|
+
yield this.setFarcasterUsername(user.farcasterUsername);
|
|
206
|
+
}
|
|
207
|
+
const encryptedSharesResult = yield this.ctx.client.getBiometricKeyshares(userId, resultJson.id);
|
|
208
|
+
const encryptionKeyHash = getSHA256HashHex(resultJson.response.userHandle);
|
|
209
|
+
const { encryptedPrivateKeys } = yield this.ctx.client.getEncryptedWalletPrivateKeys(userId, encryptionKeyHash);
|
|
210
|
+
let decryptedShares;
|
|
211
|
+
if (encryptedPrivateKeys.length === 0) {
|
|
212
|
+
decryptedShares = yield getDerivedPrivateKeyAndDecrypt(this.ctx, resultJson.response.userHandle, encryptedSharesResult.data.keyShares);
|
|
213
|
+
const keyPair = yield getAsymmetricKeyPair(this.ctx, resultJson.response.userHandle);
|
|
214
|
+
const encryptedPrivateKeyHex = yield encryptPrivateKey(keyPair, resultJson.response.userHandle);
|
|
215
|
+
yield this.ctx.client.uploadEncryptedWalletPrivateKey(userId, encryptedPrivateKeyHex, encryptionKeyHash, resultJson.id);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
decryptedShares = yield decryptPrivateKeyAndDecryptShare(resultJson.response.userHandle, encryptedSharesResult.data.keyShares, encryptedPrivateKeys[0].encryptedPrivateKey);
|
|
219
|
+
}
|
|
220
|
+
const walletsRes = yield this.ctx.client.getWallets(userId);
|
|
221
|
+
const desiredWallets = walletsRes.data.wallets;
|
|
222
|
+
const walletsToInsert = {};
|
|
223
|
+
for (let desiredWallet of desiredWallets) {
|
|
224
|
+
const decryptedShare = decryptedShares.find(share => share.walletId === desiredWallet.id);
|
|
225
|
+
walletsToInsert[decryptedShare.walletId] = {
|
|
226
|
+
id: decryptedShare.walletId,
|
|
227
|
+
signer: decryptedShare.signer,
|
|
228
|
+
address: desiredWallet.address || undefined,
|
|
229
|
+
publicKey: desiredWallet.publicKey || undefined,
|
|
230
|
+
scheme: desiredWallet.scheme,
|
|
231
|
+
type: desiredWallet.type || undefined,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
yield this.setWallets(walletsToInsert);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { PlatformUtils, TPregenIdentifierType } from '@getpara/web-sdk';
|
|
2
|
+
import { Ctx } from '@getpara/web-sdk';
|
|
3
|
+
import { SignatureRes } from '@getpara/web-sdk';
|
|
4
|
+
import { BackupKitEmailProps, WalletType } from '@getpara/user-management-client';
|
|
5
|
+
import { AsyncStorage } from '../AsyncStorage.js';
|
|
6
|
+
import { KeychainStorage } from '../KeychainStorage.js';
|
|
7
|
+
export declare class ReactNativeUtils implements PlatformUtils {
|
|
8
|
+
disableProviderModal?: boolean | undefined;
|
|
9
|
+
localStorage: AsyncStorage;
|
|
10
|
+
sessionStorage: AsyncStorage;
|
|
11
|
+
secureStorage: KeychainStorage;
|
|
12
|
+
isSyncStorage: boolean;
|
|
13
|
+
generateBlumPrimes(_ctx: Ctx): Promise<{
|
|
14
|
+
p: string;
|
|
15
|
+
q: string;
|
|
16
|
+
}>;
|
|
17
|
+
keygen(ctx: Ctx, userId: string, type: Exclude<WalletType, WalletType.SOLANA>, _secretKey: string | null, _sessionCookie: string, _emailProps?: BackupKitEmailProps | undefined): Promise<{
|
|
18
|
+
signer: string;
|
|
19
|
+
walletId: string;
|
|
20
|
+
}>;
|
|
21
|
+
refresh(_ctx: Ctx, _sessionCookie: string, _userId: string, _walletId: string, _share: string, _oldPartnerId?: string, _newPartnerId?: string): Promise<{
|
|
22
|
+
signer: string;
|
|
23
|
+
}>;
|
|
24
|
+
preKeygen(_ctx: Ctx, _partnerId: string, _email: string, _secretKey: string | null, _sessionCookie: string): Promise<{
|
|
25
|
+
signer: string;
|
|
26
|
+
walletId: string;
|
|
27
|
+
}>;
|
|
28
|
+
getPrivateKey(_ctx: Ctx, _userId: string, _walletId: string, _share: string, _sessionCookie: string): Promise<string>;
|
|
29
|
+
openPopup(_popupUrl: string): any;
|
|
30
|
+
private baseSignTransaction;
|
|
31
|
+
sendTransaction(ctx: Ctx, userId: string, walletId: string, share: string, rlpEncodedTxBase64: string, chainId: string, _sessionCookie: string, isDKLS?: boolean): Promise<SignatureRes>;
|
|
32
|
+
signHash(_address: string, _hash: string): Promise<{
|
|
33
|
+
v: number;
|
|
34
|
+
r: Buffer;
|
|
35
|
+
s: Buffer;
|
|
36
|
+
}>;
|
|
37
|
+
signMessage(ctx: Ctx, userId: string, walletId: string, share: string, messageBase64: string, // base64 message
|
|
38
|
+
_sessionCookie: string, isDKLS?: boolean): Promise<SignatureRes>;
|
|
39
|
+
signTransaction(ctx: Ctx, userId: string, walletId: string, share: string, rlpEncodedTxBase64: string, // base64 encoding of rlp encoded tx
|
|
40
|
+
chainId: string, _sessionCookie: string, isDKLS?: boolean): Promise<SignatureRes>;
|
|
41
|
+
ed25519Keygen(ctx: Ctx, userId: string, _sessionCookie: string, _emailProps?: BackupKitEmailProps): Promise<{
|
|
42
|
+
signer: string;
|
|
43
|
+
walletId: string;
|
|
44
|
+
}>;
|
|
45
|
+
ed25519PreKeygen(ctx: Ctx, pregenIdentifier: string, pregenIdentifierType: TPregenIdentifierType, _sessionCookie: string): Promise<{
|
|
46
|
+
signer: string;
|
|
47
|
+
walletId: string;
|
|
48
|
+
}>;
|
|
49
|
+
ed25519Sign(ctx: Ctx, userId: string, walletId: string, share: string, base64Bytes: string, _sessionCookie: string): Promise<SignatureRes>;
|
|
50
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// Copyright (c) Capsule Labs Inc. All rights reserved.
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
import { KeyShareType, WalletScheme, WalletType } from '@getpara/user-management-client';
|
|
12
|
+
import { NativeModules } from 'react-native';
|
|
13
|
+
import { AsyncStorage } from '../AsyncStorage.js';
|
|
14
|
+
import { KeychainStorage } from '../KeychainStorage.js';
|
|
15
|
+
const { ParaSignerModule } = NativeModules;
|
|
16
|
+
function keygenRequest(ctx, userId, walletId, protocolId) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const { data } = yield ctx.mpcComputationClient.post('/wallets', {
|
|
19
|
+
userId,
|
|
20
|
+
walletId,
|
|
21
|
+
protocolId,
|
|
22
|
+
});
|
|
23
|
+
return data;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function signMessageRequest(ctx, userId, walletId, protocolId, message, signer) {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
const { data } = yield ctx.mpcComputationClient.post(`/wallets/${walletId}/messages/sign`, {
|
|
29
|
+
userId,
|
|
30
|
+
protocolId,
|
|
31
|
+
message,
|
|
32
|
+
signer,
|
|
33
|
+
});
|
|
34
|
+
return data;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function sendTransactionRequest(ctx, userId, walletId, protocolId, transaction, signer, chainId) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
const { data } = yield ctx.mpcComputationClient.post(`/wallets/${walletId}/transactions/send`, {
|
|
40
|
+
userId,
|
|
41
|
+
protocolId,
|
|
42
|
+
transaction,
|
|
43
|
+
signer,
|
|
44
|
+
chainId,
|
|
45
|
+
});
|
|
46
|
+
return data;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export class ReactNativeUtils {
|
|
50
|
+
constructor() {
|
|
51
|
+
this.localStorage = new AsyncStorage();
|
|
52
|
+
this.sessionStorage = new AsyncStorage();
|
|
53
|
+
this.secureStorage = new KeychainStorage();
|
|
54
|
+
this.isSyncStorage = false;
|
|
55
|
+
}
|
|
56
|
+
// only used in web for now, can implement functionality if ever needed for mobile
|
|
57
|
+
generateBlumPrimes(_ctx) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
throw new Error('method not implemented');
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
keygen(ctx, userId, type, _secretKey, _sessionCookie, _emailProps) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
|
|
65
|
+
type,
|
|
66
|
+
useTwoSigners: true,
|
|
67
|
+
scheme: ctx.useDKLS ? WalletScheme.DKLS : WalletScheme.CGGMP,
|
|
68
|
+
});
|
|
69
|
+
if (ctx.mpcComputationClient && !ctx.useDKLS) {
|
|
70
|
+
const { signer } = yield keygenRequest(ctx, userId, walletId, protocolId);
|
|
71
|
+
return { signer, walletId };
|
|
72
|
+
}
|
|
73
|
+
const createAccountFn = !ctx.useDKLS ? ParaSignerModule.createAccount : ParaSignerModule.dklsCreateAccount;
|
|
74
|
+
const signer = yield createAccountFn(walletId, protocolId, KeyShareType.USER, userId);
|
|
75
|
+
return { signer, walletId };
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
refresh(_ctx, _sessionCookie, _userId, _walletId, _share, _oldPartnerId, _newPartnerId) {
|
|
79
|
+
throw new Error('Method not implemented.');
|
|
80
|
+
}
|
|
81
|
+
preKeygen(_ctx, _partnerId, _email, _secretKey, _sessionCookie) {
|
|
82
|
+
throw new Error('Method not implemented.');
|
|
83
|
+
}
|
|
84
|
+
getPrivateKey(_ctx, _userId, _walletId, _share, _sessionCookie) {
|
|
85
|
+
throw new Error('Method not implemented.');
|
|
86
|
+
}
|
|
87
|
+
openPopup(_popupUrl) {
|
|
88
|
+
throw new Error('Method not implemented.');
|
|
89
|
+
}
|
|
90
|
+
baseSignTransaction(ctx, userId, walletId, protocolId, share, rlpEncodedTxBase64, chainId, isDKLS) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
if (ctx.mpcComputationClient && !isDKLS) {
|
|
93
|
+
const signature = (yield sendTransactionRequest(ctx, userId, walletId, protocolId, rlpEncodedTxBase64, share, chainId))
|
|
94
|
+
.signature;
|
|
95
|
+
return { signature };
|
|
96
|
+
}
|
|
97
|
+
const sendTransactionFn = isDKLS ? ParaSignerModule.dklsSendTransaction : ParaSignerModule.sendTransaction;
|
|
98
|
+
const signature = yield sendTransactionFn(protocolId, share, rlpEncodedTxBase64, userId);
|
|
99
|
+
return { signature: signature.slice(2) };
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
sendTransaction(ctx, userId, walletId, share, rlpEncodedTxBase64, chainId, _sessionCookie, isDKLS) {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
const { protocolId } = (yield ctx.client.sendTransaction(userId, walletId, {
|
|
105
|
+
transaction: rlpEncodedTxBase64,
|
|
106
|
+
chainId,
|
|
107
|
+
})).data;
|
|
108
|
+
return this.baseSignTransaction(ctx, userId, walletId, protocolId, share, rlpEncodedTxBase64, chainId, isDKLS);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
signHash(_address, _hash) {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
throw new Error('not implemented');
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
signMessage(ctx, userId, walletId, share, messageBase64, // base64 message
|
|
117
|
+
_sessionCookie, isDKLS) {
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
const res = yield ctx.client.preSignMessage(userId, walletId, messageBase64);
|
|
120
|
+
if (ctx.mpcComputationClient && !isDKLS) {
|
|
121
|
+
const signature = (yield signMessageRequest(ctx, userId, walletId, res.protocolId, messageBase64, share)).signature;
|
|
122
|
+
return { signature };
|
|
123
|
+
}
|
|
124
|
+
const signMessageFn = isDKLS ? ParaSignerModule.dklsSignMessage : ParaSignerModule.signMessage;
|
|
125
|
+
const signature = yield signMessageFn(res.protocolId, share, messageBase64, userId);
|
|
126
|
+
if (signature.startsWith('0x')) {
|
|
127
|
+
return { signature: signature.slice(2) };
|
|
128
|
+
}
|
|
129
|
+
return { signature };
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
signTransaction(ctx, userId, walletId, share, rlpEncodedTxBase64, // base64 encoding of rlp encoded tx
|
|
133
|
+
chainId, _sessionCookie, isDKLS) {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
const { protocolId } = (yield ctx.client.signTransaction(userId, walletId, {
|
|
136
|
+
transaction: rlpEncodedTxBase64,
|
|
137
|
+
chainId,
|
|
138
|
+
})).data;
|
|
139
|
+
return this.baseSignTransaction(ctx, userId, walletId, protocolId, share, rlpEncodedTxBase64, chainId, isDKLS);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
ed25519Keygen(ctx, userId, _sessionCookie, _emailProps) {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
|
|
145
|
+
scheme: WalletScheme.ED25519,
|
|
146
|
+
type: WalletType.SOLANA,
|
|
147
|
+
});
|
|
148
|
+
const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
149
|
+
return { signer, walletId };
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
ed25519PreKeygen(ctx, pregenIdentifier, pregenIdentifierType, _sessionCookie) {
|
|
153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
const { walletId, protocolId } = yield ctx.client.createWalletPreGen({
|
|
155
|
+
pregenIdentifier,
|
|
156
|
+
pregenIdentifierType,
|
|
157
|
+
scheme: WalletScheme.ED25519,
|
|
158
|
+
type: WalletType.SOLANA,
|
|
159
|
+
});
|
|
160
|
+
const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
|
|
161
|
+
return { signer, walletId };
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
ed25519Sign(ctx, userId, walletId, share, base64Bytes, _sessionCookie) {
|
|
165
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
+
const { protocolId } = yield ctx.client.preSignMessage(userId, walletId, base64Bytes, WalletScheme.ED25519);
|
|
167
|
+
const base64Sig = yield ParaSignerModule.ed25519Sign(protocolId, share, base64Bytes);
|
|
168
|
+
return { signature: base64Sig };
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
package/dist/shim.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/shim.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// 1) Node-like crypto + Web Crypto API (subtle + getRandomValues)
|
|
2
|
+
import crypto from 'react-native-quick-crypto';
|
|
3
|
+
import { webcrypto } from 'crypto';
|
|
4
|
+
import { Crypto } from '@peculiar/webcrypto';
|
|
5
|
+
if (typeof global.crypto === 'undefined') {
|
|
6
|
+
// Attach Node-style crypto for randomFillSync, createHash, etc.
|
|
7
|
+
global.crypto = crypto;
|
|
8
|
+
}
|
|
9
|
+
// If `crypto.subtle` is missing, patch it with `@peculiar/webcrypto`
|
|
10
|
+
if (!global.crypto.subtle) {
|
|
11
|
+
const peculiarCrypto = new Crypto();
|
|
12
|
+
global.crypto.subtle = peculiarCrypto.subtle;
|
|
13
|
+
global.crypto.getRandomValues = peculiarCrypto.getRandomValues.bind(peculiarCrypto);
|
|
14
|
+
}
|
|
15
|
+
// Add getRandomValues to webcrypto from peculiar
|
|
16
|
+
const peculiarCrypto = new Crypto();
|
|
17
|
+
webcrypto.getRandomValues = peculiarCrypto.getRandomValues.bind(peculiarCrypto);
|
|
18
|
+
// 2) Provide TextEncoder / TextDecoder
|
|
19
|
+
import * as FSTED from 'fastestsmallesttextencoderdecoder';
|
|
20
|
+
if (typeof global.TextEncoder === 'undefined') {
|
|
21
|
+
global.TextEncoder = FSTED.TextEncoder;
|
|
22
|
+
}
|
|
23
|
+
if (typeof global.TextDecoder === 'undefined') {
|
|
24
|
+
global.TextDecoder = FSTED.TextDecoder;
|
|
25
|
+
}
|
|
26
|
+
// 3) Provide atob / btoa via react-native-quick-base64
|
|
27
|
+
import { atob, btoa } from 'react-native-quick-base64';
|
|
28
|
+
if (typeof global.atob === 'undefined') {
|
|
29
|
+
global.atob = atob;
|
|
30
|
+
}
|
|
31
|
+
if (typeof global.btoa === 'undefined') {
|
|
32
|
+
global.btoa = btoa;
|
|
33
|
+
}
|
|
34
|
+
// 4) Patch node-forge with react-native-modpow for faster RSA ops
|
|
35
|
+
import Forge from 'node-forge';
|
|
36
|
+
import modPow from 'react-native-modpow';
|
|
37
|
+
Forge.jsbn.BigInteger.prototype.modPow = function nativeModPow(e, m) {
|
|
38
|
+
const result = modPow({
|
|
39
|
+
target: this.toString(16),
|
|
40
|
+
value: e.toString(16),
|
|
41
|
+
modifier: m.toString(16),
|
|
42
|
+
});
|
|
43
|
+
return new Forge.jsbn.BigInteger(result, 16);
|
|
44
|
+
};
|
|
45
|
+
// 5) Provide global Buffer
|
|
46
|
+
import { Buffer } from '@craftzdog/react-native-buffer';
|
|
47
|
+
if (typeof global.Buffer === 'undefined') {
|
|
48
|
+
global.Buffer = Buffer;
|
|
49
|
+
}
|