@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.
@@ -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
- // STAGING_PERS_API_URL: 'https://dev.api.pers.ninja/v2',
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
- this.triggerStatusUpdate(SigningStatus.COMPLETED, 'Transaction signed successfully', {
1969
- transactionId: payload.transactionId,
1970
- signature: result.signature
1971
- }, statusCallback);
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
@@ -2175,9 +2212,8 @@ class BrowserWebAuthnProvider {
2175
2212
  // 1. Prepare options for navigator.credentials.create
2176
2213
  // We construct authenticatorSelection manually to ensure no conflicting legacy properties are present
2177
2214
  const authenticatorSelection = {
2178
- residentKey: 'required', // Force Passkey (discoverable credential)
2179
- // requireResidentKey: true, // REMOVED: Legacy property that can cause conflicts with 1Password
2180
- userVerification: challenge.authenticatorSelection?.userVerification || 'preferred',
2215
+ residentKey: WEBAUTHN_CONFIG.RESIDENT_KEY, // Force Passkey (discoverable credential)
2216
+ userVerification: challenge.authenticatorSelection?.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
2181
2217
  };
2182
2218
  const publicKey = {
2183
2219
  challenge: base64UrlToBuffer(challenge.challenge),
@@ -2193,16 +2229,13 @@ class BrowserWebAuthnProvider {
2193
2229
  pubKeyCredParams: challenge.pubKeyCredParams,
2194
2230
  authenticatorSelection,
2195
2231
  attestation: 'none',
2196
- timeout: challenge.timeout || 60000,
2232
+ timeout: challenge.timeout || WEBAUTHN_CONFIG.TIMEOUT,
2197
2233
  excludeCredentials: challenge.excludeCredentials?.map((cred) => ({
2198
2234
  id: base64UrlToBuffer(cred.id),
2199
2235
  type: 'public-key',
2200
2236
  transports: cred.transports,
2201
2237
  })),
2202
2238
  };
2203
- // console.log('WebAuthn create options:', publicKey);
2204
- // console.log('WebAuthn create challenge:', challenge);
2205
- // console.log('this.config', this.config)
2206
2239
  // 2. Call the browser's native WebAuthn API
2207
2240
  const credential = await navigator.credentials.create({ publicKey });
2208
2241
  if (!credential)
@@ -2226,8 +2259,8 @@ class BrowserWebAuthnProvider {
2226
2259
  const publicKey = {
2227
2260
  challenge: base64UrlToBuffer(challenge.challenge),
2228
2261
  rpId: challenge.rpId || this.config.relyingParty.id,
2229
- userVerification: challenge.userVerification || 'preferred',
2230
- timeout: 60000,
2262
+ userVerification: challenge.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
2263
+ timeout: WEBAUTHN_CONFIG.TIMEOUT,
2231
2264
  allowCredentials: challenge.allowCredentials?.webauthn?.map((cred) => ({
2232
2265
  id: base64UrlToBuffer(cred.id),
2233
2266
  type: 'public-key',
@@ -2266,13 +2299,7 @@ class BrowserWebAuthnProvider {
2266
2299
  * Get WebAuthn provider for browser environments
2267
2300
  */
2268
2301
  async function getBrowserWebAuthnProvider() {
2269
- const config = {
2270
- relyingParty: {
2271
- id: typeof window !== 'undefined' ? window.location.hostname : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
2272
- name: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_NAME,
2273
- origin: typeof window !== 'undefined' ? window.location.origin : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
2274
- }
2275
- };
2302
+ const config = getWebAuthnConfig();
2276
2303
  return new BrowserWebAuthnProvider(config);
2277
2304
  }
2278
2305