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