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