@explorins/pers-signer 1.0.26 → 1.0.31
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/browser.cjs.js +65 -38
- package/dist/browser.cjs.js.map +1 -1
- package/dist/browser.esm.js +65 -38
- package/dist/browser.esm.js.map +1 -1
- package/dist/index.cjs.js +76 -54
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +76 -54
- package/dist/index.esm.js.map +1 -1
- package/dist/react-native.cjs.js +76 -54
- package/dist/react-native.cjs.js.map +1 -1
- package/dist/react-native.esm.js +76 -54
- package/dist/react-native.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/react-native.cjs.js
CHANGED
|
@@ -137,13 +137,11 @@ const SIGNER_CONFIG = {
|
|
|
137
137
|
* Used as fallback when production signer API is unavailable
|
|
138
138
|
*/
|
|
139
139
|
STAGING_SIGNER_API_URL: 'https://signer-api-staging.pers.ninja/v1',
|
|
140
|
-
// STAGING_SIGNER_API_URL: 'http://localhost:8080/v1',
|
|
141
140
|
/**
|
|
142
141
|
* PERS Platform API URLs
|
|
143
142
|
*/
|
|
144
143
|
DEFAULT_PERS_API_URL: 'https://api.pers.ninja/v2',
|
|
145
|
-
|
|
146
|
-
STAGING_PERS_API_URL: 'https://explorins-loyalty.ngrok.io',
|
|
144
|
+
STAGING_PERS_API_URL: 'https://dev.api.pers.ninja/v2',
|
|
147
145
|
/**
|
|
148
146
|
* Default relying party name for WebAuthn operations
|
|
149
147
|
* This appears in the browser's authentication prompts
|
|
@@ -155,8 +153,31 @@ const SIGNER_CONFIG = {
|
|
|
155
153
|
*/
|
|
156
154
|
// Default fallback provider for Sepolia testnet (no API key required)
|
|
157
155
|
const DEFAULT_FALLBACK_PROVIDER = 'https://ethereum-sepolia.publicnode.com';
|
|
156
|
+
/**
|
|
157
|
+
* WebAuthn configuration constants
|
|
158
|
+
*/
|
|
159
|
+
const WEBAUTHN_CONFIG = {
|
|
160
|
+
/**
|
|
161
|
+
* Timeout for WebAuthn operations (in milliseconds)
|
|
162
|
+
*/
|
|
163
|
+
TIMEOUT: 60000,
|
|
164
|
+
/**
|
|
165
|
+
* User verification requirement
|
|
166
|
+
* 'preferred' - ask for verification if available
|
|
167
|
+
* 'required' - require verification
|
|
168
|
+
* 'discouraged' - don't ask for verification
|
|
169
|
+
*/
|
|
170
|
+
USER_VERIFICATION: 'preferred',
|
|
171
|
+
/**
|
|
172
|
+
* Resident key requirement (Passkeys)
|
|
173
|
+
*/
|
|
174
|
+
RESIDENT_KEY: 'required',
|
|
175
|
+
/**
|
|
176
|
+
* Authenticator attachment preference
|
|
177
|
+
*/
|
|
178
|
+
AUTHENTICATOR_ATTACHMENT: 'platform',
|
|
179
|
+
};
|
|
158
180
|
|
|
159
|
-
// import serviceState from '../core/ServiceState';
|
|
160
181
|
/**
|
|
161
182
|
* Detects the environment (Staging vs Production) based on the JWT token issuer.
|
|
162
183
|
* Updates the global service state accordingly.
|
|
@@ -170,15 +191,8 @@ function detectStagingEnvironmentFromToken(token) {
|
|
|
170
191
|
// Check if issuer matches staging URL
|
|
171
192
|
if (payload.iss === SIGNER_CONFIG.STAGING_PERS_API_URL
|
|
172
193
|
|| SIGNER_CONFIG.STAGING_PERS_API_URL.includes(payload.iss)
|
|
173
|
-
|| SIGNER_CONFIG.STAGING_SIGNER_API_URL.includes(payload.iss)
|
|
174
|
-
// Temporary additional checks for known staging issuers
|
|
175
|
-
// || 'https://signer-api-staging.pers.ninja'.includes(payload.iss)
|
|
176
|
-
|| 'https://dev.api.pers.ninja/v2'.includes(payload.iss)) {
|
|
194
|
+
|| SIGNER_CONFIG.STAGING_SIGNER_API_URL.includes(payload.iss)) {
|
|
177
195
|
return true;
|
|
178
|
-
/* } else if (payload.iss === SIGNER_CONFIG.DEFAULT_PERS_API_URL ||
|
|
179
|
-
SIGNER_CONFIG.DEFAULT_PERS_API_URL.includes(payload.iss)) {
|
|
180
|
-
// Explicitly production
|
|
181
|
-
return false; */
|
|
182
196
|
}
|
|
183
197
|
}
|
|
184
198
|
return false;
|
|
@@ -1205,11 +1219,11 @@ class TransactionSigningService {
|
|
|
1205
1219
|
let provider;
|
|
1206
1220
|
try {
|
|
1207
1221
|
// Try primary provider first
|
|
1208
|
-
console.info(`[TransactionSigningService] Attempting to connect to primary provider: ${ethersProviderUrl}`);
|
|
1222
|
+
//console.info(`[TransactionSigningService] Attempting to connect to primary provider: ${ethersProviderUrl}`);
|
|
1209
1223
|
provider = new ethers.JsonRpcProvider(ethersProviderUrl);
|
|
1210
1224
|
// Test the connection with a simple call
|
|
1211
1225
|
await provider.getNetwork();
|
|
1212
|
-
console.info(`[TransactionSigningService] Successfully connected to primary provider`);
|
|
1226
|
+
//console.info(`[TransactionSigningService] Successfully connected to primary provider`);
|
|
1213
1227
|
}
|
|
1214
1228
|
catch (primaryError) {
|
|
1215
1229
|
console.warn(`[TransactionSigningService] Primary provider failed, falling back to: ${DEFAULT_FALLBACK_PROVIDER}`, primaryError);
|
|
@@ -1217,7 +1231,7 @@ class TransactionSigningService {
|
|
|
1217
1231
|
provider = new ethers.JsonRpcProvider(DEFAULT_FALLBACK_PROVIDER);
|
|
1218
1232
|
// Test the fallback connection
|
|
1219
1233
|
await provider.getNetwork();
|
|
1220
|
-
console.info(`[TransactionSigningService] Successfully connected to fallback provider`);
|
|
1234
|
+
//console.info(`[TransactionSigningService] Successfully connected to fallback provider`);
|
|
1221
1235
|
}
|
|
1222
1236
|
catch (fallbackError) {
|
|
1223
1237
|
console.error(`[TransactionSigningService] Both primary and fallback providers failed`, { primaryError, fallbackError });
|
|
@@ -1281,13 +1295,13 @@ class TransactionSigningService {
|
|
|
1281
1295
|
// Validate input parameters first using TransactionValidator
|
|
1282
1296
|
TransactionValidator.validateSigningParams(params);
|
|
1283
1297
|
const { transactionId, authTokens, ethersProviderUrl } = params;
|
|
1284
|
-
console.info(`[TransactionSigningService] Starting signature process for ${transactionId}`);
|
|
1298
|
+
// console.info(`[TransactionSigningService] Starting signature process for ${transactionId}`);
|
|
1285
1299
|
try {
|
|
1286
1300
|
// Step 2: Prepare wallet for signing
|
|
1287
1301
|
const wallet = await this.prepareWallet(authTokens, ethersProviderUrl);
|
|
1288
1302
|
// Step 3: Execute transaction signing
|
|
1289
1303
|
const signature = await this.executeTransactionSigning(wallet, signingData);
|
|
1290
|
-
console.info(`[TransactionSigningService] Completed signing successfully: ${transactionId}`);
|
|
1304
|
+
// console.info(`[TransactionSigningService] Completed signing successfully: ${transactionId}`);
|
|
1291
1305
|
return {
|
|
1292
1306
|
success: true,
|
|
1293
1307
|
transactionId,
|
|
@@ -1756,7 +1770,6 @@ class PersSignerSDK {
|
|
|
1756
1770
|
* @throws {Error} If required configuration is missing
|
|
1757
1771
|
*/
|
|
1758
1772
|
constructor(config) {
|
|
1759
|
-
console.log('DEBUG: v1.2.0');
|
|
1760
1773
|
this.config = config;
|
|
1761
1774
|
setConfigProvider(new WebConfigProvider({
|
|
1762
1775
|
apiUrl: config.apiUrl || SIGNER_CONFIG.DEFAULT_SIGNER_API_URL,
|
|
@@ -1965,10 +1978,12 @@ class PersSignerSDK {
|
|
|
1965
1978
|
authTokens,
|
|
1966
1979
|
ethersProviderUrl: this.config.ethersProviderUrl ?? DEFAULT_FALLBACK_PROVIDER
|
|
1967
1980
|
}, signingData);
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1981
|
+
if (result.success) {
|
|
1982
|
+
this.triggerStatusUpdate(SigningStatus.COMPLETED, 'Transaction signed successfully', {
|
|
1983
|
+
transactionId: payload.transactionId,
|
|
1984
|
+
signature: result.signature
|
|
1985
|
+
}, statusCallback);
|
|
1986
|
+
}
|
|
1972
1987
|
return result;
|
|
1973
1988
|
}
|
|
1974
1989
|
catch (error) {
|
|
@@ -2112,6 +2127,28 @@ class PersSignerSDK {
|
|
|
2112
2127
|
}
|
|
2113
2128
|
}
|
|
2114
2129
|
|
|
2130
|
+
/**
|
|
2131
|
+
* Get the WebAuthn configuration based on the current environment.
|
|
2132
|
+
* This logic is shared between browser and React Native implementations
|
|
2133
|
+
* to ensure consistent behavior while respecting platform differences.
|
|
2134
|
+
*/
|
|
2135
|
+
function getWebAuthnConfig() {
|
|
2136
|
+
// Check if running in a browser environment with window.location available
|
|
2137
|
+
// We use a safe check that won't crash in React Native
|
|
2138
|
+
const isBrowser = typeof window !== 'undefined' && !!window.location && !!window.location.hostname;
|
|
2139
|
+
return {
|
|
2140
|
+
relyingParty: {
|
|
2141
|
+
// In browser, prefer the actual hostname to avoid RP ID mismatch errors
|
|
2142
|
+
// In React Native, use the configured default RP ID
|
|
2143
|
+
id: isBrowser ? window.location.hostname : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
2144
|
+
name: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_NAME,
|
|
2145
|
+
// In browser, use the actual origin
|
|
2146
|
+
// In React Native, fallback to the default RP ID (or a configured origin if added later)
|
|
2147
|
+
origin: isBrowser ? window.location.origin : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
2148
|
+
}
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2115
2152
|
/**
|
|
2116
2153
|
* Base64URL encoding/decoding utilities
|
|
2117
2154
|
* Used for WebAuthn credential ID and challenge handling
|
|
@@ -2169,13 +2206,18 @@ function toBase64Url(str) {
|
|
|
2169
2206
|
*/
|
|
2170
2207
|
class ReactNativeWebAuthnProvider {
|
|
2171
2208
|
constructor(config) {
|
|
2209
|
+
this.passkeyLibrary = null;
|
|
2172
2210
|
this.config = config;
|
|
2173
2211
|
}
|
|
2174
2212
|
async getPasskeyLibrary() {
|
|
2213
|
+
if (this.passkeyLibrary) {
|
|
2214
|
+
return this.passkeyLibrary;
|
|
2215
|
+
}
|
|
2175
2216
|
try {
|
|
2176
2217
|
// Dynamic import to avoid hard dependency
|
|
2177
2218
|
// @ts-ignore - Optional dependency
|
|
2178
2219
|
const { Passkey } = await import('react-native-passkey');
|
|
2220
|
+
this.passkeyLibrary = Passkey;
|
|
2179
2221
|
return Passkey;
|
|
2180
2222
|
}
|
|
2181
2223
|
catch (error) {
|
|
@@ -2191,7 +2233,6 @@ class ReactNativeWebAuthnProvider {
|
|
|
2191
2233
|
}
|
|
2192
2234
|
}
|
|
2193
2235
|
async handleWebFallback(operation, challenge) {
|
|
2194
|
-
console.log(`Falling back to browser WebAuthn for React Native Web (${operation})...`);
|
|
2195
2236
|
try {
|
|
2196
2237
|
// Import and use browser WebAuthn provider
|
|
2197
2238
|
const { getBrowserWebAuthnProvider } = await Promise.resolve().then(function () { return WebAuthnProvider_browser; });
|
|
@@ -2214,8 +2255,8 @@ class ReactNativeWebAuthnProvider {
|
|
|
2214
2255
|
// If it's a very long string, it might be an issue.
|
|
2215
2256
|
// But let's focus on aligning the authenticatorSelection first.
|
|
2216
2257
|
const authenticatorSelection = {
|
|
2217
|
-
residentKey:
|
|
2218
|
-
userVerification: challenge.authenticatorSelection?.userVerification ||
|
|
2258
|
+
residentKey: WEBAUTHN_CONFIG.RESIDENT_KEY, // Force Passkey (discoverable credential)
|
|
2259
|
+
userVerification: challenge.authenticatorSelection?.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
2219
2260
|
// Explicitly undefined to avoid issues, though JS objects don't usually include undefined keys in JSON
|
|
2220
2261
|
// But react-native-passkey might handle it differently.
|
|
2221
2262
|
};
|
|
@@ -2244,11 +2285,9 @@ class ReactNativeWebAuthnProvider {
|
|
|
2244
2285
|
transports: v.transports
|
|
2245
2286
|
})), // Cast to any to avoid strict type mismatch with react-native-passkey types
|
|
2246
2287
|
authenticatorSelection,
|
|
2247
|
-
timeout: challenge.timeout ||
|
|
2288
|
+
timeout: challenge.timeout || WEBAUTHN_CONFIG.TIMEOUT,
|
|
2248
2289
|
};
|
|
2249
|
-
console.log('[RNWebAuthn] Calling Passkey.create with:', JSON.stringify(request, null, 2));
|
|
2250
2290
|
const result = await Passkey.create(request);
|
|
2251
|
-
console.log('[RNWebAuthn] Passkey.create success:', JSON.stringify(result, null, 2));
|
|
2252
2291
|
return {
|
|
2253
2292
|
id: result.id,
|
|
2254
2293
|
clientDataJSON: result.response.clientDataJSON,
|
|
@@ -2276,12 +2315,10 @@ class ReactNativeWebAuthnProvider {
|
|
|
2276
2315
|
// transports: cred.transports,
|
|
2277
2316
|
})),
|
|
2278
2317
|
rpId: challenge.rpId || this.config.relyingParty.id,
|
|
2279
|
-
userVerification: challenge.userVerification ||
|
|
2280
|
-
timeout: challenge.timeout ||
|
|
2318
|
+
userVerification: challenge.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
2319
|
+
timeout: challenge.timeout || WEBAUTHN_CONFIG.TIMEOUT,
|
|
2281
2320
|
};
|
|
2282
|
-
console.log('[RNWebAuthn] Calling Passkey.get (sign) with:', JSON.stringify(request, null, 2));
|
|
2283
2321
|
const credential = await Passkey.get(request);
|
|
2284
|
-
console.log('[RNWebAuthn] Passkey.get success:', JSON.stringify(credential, null, 2));
|
|
2285
2322
|
return {
|
|
2286
2323
|
kind: 'Fido2',
|
|
2287
2324
|
credentialAssertion: {
|
|
@@ -2306,12 +2343,7 @@ class ReactNativeWebAuthnProvider {
|
|
|
2306
2343
|
* Get WebAuthn provider for React Native environments
|
|
2307
2344
|
*/
|
|
2308
2345
|
async function getReactNativeWebAuthnProvider() {
|
|
2309
|
-
const config =
|
|
2310
|
-
relyingParty: {
|
|
2311
|
-
id: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
2312
|
-
name: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_NAME,
|
|
2313
|
-
}
|
|
2314
|
-
};
|
|
2346
|
+
const config = getWebAuthnConfig();
|
|
2315
2347
|
return new ReactNativeWebAuthnProvider(config);
|
|
2316
2348
|
}
|
|
2317
2349
|
|
|
@@ -2392,9 +2424,8 @@ class BrowserWebAuthnProvider {
|
|
|
2392
2424
|
// 1. Prepare options for navigator.credentials.create
|
|
2393
2425
|
// We construct authenticatorSelection manually to ensure no conflicting legacy properties are present
|
|
2394
2426
|
const authenticatorSelection = {
|
|
2395
|
-
residentKey:
|
|
2396
|
-
|
|
2397
|
-
userVerification: challenge.authenticatorSelection?.userVerification || 'preferred',
|
|
2427
|
+
residentKey: WEBAUTHN_CONFIG.RESIDENT_KEY, // Force Passkey (discoverable credential)
|
|
2428
|
+
userVerification: challenge.authenticatorSelection?.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
2398
2429
|
};
|
|
2399
2430
|
const publicKey = {
|
|
2400
2431
|
challenge: base64UrlToBuffer(challenge.challenge),
|
|
@@ -2410,16 +2441,13 @@ class BrowserWebAuthnProvider {
|
|
|
2410
2441
|
pubKeyCredParams: challenge.pubKeyCredParams,
|
|
2411
2442
|
authenticatorSelection,
|
|
2412
2443
|
attestation: 'none',
|
|
2413
|
-
timeout: challenge.timeout ||
|
|
2444
|
+
timeout: challenge.timeout || WEBAUTHN_CONFIG.TIMEOUT,
|
|
2414
2445
|
excludeCredentials: challenge.excludeCredentials?.map((cred) => ({
|
|
2415
2446
|
id: base64UrlToBuffer(cred.id),
|
|
2416
2447
|
type: 'public-key',
|
|
2417
2448
|
transports: cred.transports,
|
|
2418
2449
|
})),
|
|
2419
2450
|
};
|
|
2420
|
-
// console.log('WebAuthn create options:', publicKey);
|
|
2421
|
-
// console.log('WebAuthn create challenge:', challenge);
|
|
2422
|
-
// console.log('this.config', this.config)
|
|
2423
2451
|
// 2. Call the browser's native WebAuthn API
|
|
2424
2452
|
const credential = await navigator.credentials.create({ publicKey });
|
|
2425
2453
|
if (!credential)
|
|
@@ -2443,8 +2471,8 @@ class BrowserWebAuthnProvider {
|
|
|
2443
2471
|
const publicKey = {
|
|
2444
2472
|
challenge: base64UrlToBuffer(challenge.challenge),
|
|
2445
2473
|
rpId: challenge.rpId || this.config.relyingParty.id,
|
|
2446
|
-
userVerification: challenge.userVerification ||
|
|
2447
|
-
timeout:
|
|
2474
|
+
userVerification: challenge.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
2475
|
+
timeout: WEBAUTHN_CONFIG.TIMEOUT,
|
|
2448
2476
|
allowCredentials: challenge.allowCredentials?.webauthn?.map((cred) => ({
|
|
2449
2477
|
id: base64UrlToBuffer(cred.id),
|
|
2450
2478
|
type: 'public-key',
|
|
@@ -2483,13 +2511,7 @@ class BrowserWebAuthnProvider {
|
|
|
2483
2511
|
* Get WebAuthn provider for browser environments
|
|
2484
2512
|
*/
|
|
2485
2513
|
async function getBrowserWebAuthnProvider() {
|
|
2486
|
-
const config =
|
|
2487
|
-
relyingParty: {
|
|
2488
|
-
id: typeof window !== 'undefined' ? window.location.hostname : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
2489
|
-
name: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_NAME,
|
|
2490
|
-
origin: typeof window !== 'undefined' ? window.location.origin : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
2491
|
-
}
|
|
2492
|
-
};
|
|
2514
|
+
const config = getWebAuthnConfig();
|
|
2493
2515
|
return new BrowserWebAuthnProvider(config);
|
|
2494
2516
|
}
|
|
2495
2517
|
|