@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/index.esm.js
CHANGED
|
@@ -67,13 +67,11 @@ const SIGNER_CONFIG = {
|
|
|
67
67
|
* Used as fallback when production signer API is unavailable
|
|
68
68
|
*/
|
|
69
69
|
STAGING_SIGNER_API_URL: 'https://signer-api-staging.pers.ninja/v1',
|
|
70
|
-
// STAGING_SIGNER_API_URL: 'http://localhost:8080/v1',
|
|
71
70
|
/**
|
|
72
71
|
* PERS Platform API URLs
|
|
73
72
|
*/
|
|
74
73
|
DEFAULT_PERS_API_URL: 'https://api.pers.ninja/v2',
|
|
75
|
-
|
|
76
|
-
STAGING_PERS_API_URL: 'https://explorins-loyalty.ngrok.io',
|
|
74
|
+
STAGING_PERS_API_URL: 'https://dev.api.pers.ninja/v2',
|
|
77
75
|
/**
|
|
78
76
|
* Default relying party name for WebAuthn operations
|
|
79
77
|
* This appears in the browser's authentication prompts
|
|
@@ -85,8 +83,31 @@ const SIGNER_CONFIG = {
|
|
|
85
83
|
*/
|
|
86
84
|
// Default fallback provider for Sepolia testnet (no API key required)
|
|
87
85
|
const DEFAULT_FALLBACK_PROVIDER = 'https://ethereum-sepolia.publicnode.com';
|
|
86
|
+
/**
|
|
87
|
+
* WebAuthn configuration constants
|
|
88
|
+
*/
|
|
89
|
+
const WEBAUTHN_CONFIG = {
|
|
90
|
+
/**
|
|
91
|
+
* Timeout for WebAuthn operations (in milliseconds)
|
|
92
|
+
*/
|
|
93
|
+
TIMEOUT: 60000,
|
|
94
|
+
/**
|
|
95
|
+
* User verification requirement
|
|
96
|
+
* 'preferred' - ask for verification if available
|
|
97
|
+
* 'required' - require verification
|
|
98
|
+
* 'discouraged' - don't ask for verification
|
|
99
|
+
*/
|
|
100
|
+
USER_VERIFICATION: 'preferred',
|
|
101
|
+
/**
|
|
102
|
+
* Resident key requirement (Passkeys)
|
|
103
|
+
*/
|
|
104
|
+
RESIDENT_KEY: 'required',
|
|
105
|
+
/**
|
|
106
|
+
* Authenticator attachment preference
|
|
107
|
+
*/
|
|
108
|
+
AUTHENTICATOR_ATTACHMENT: 'platform',
|
|
109
|
+
};
|
|
88
110
|
|
|
89
|
-
// import serviceState from '../core/ServiceState';
|
|
90
111
|
/**
|
|
91
112
|
* Detects the environment (Staging vs Production) based on the JWT token issuer.
|
|
92
113
|
* Updates the global service state accordingly.
|
|
@@ -100,15 +121,8 @@ function detectStagingEnvironmentFromToken(token) {
|
|
|
100
121
|
// Check if issuer matches staging URL
|
|
101
122
|
if (payload.iss === SIGNER_CONFIG.STAGING_PERS_API_URL
|
|
102
123
|
|| SIGNER_CONFIG.STAGING_PERS_API_URL.includes(payload.iss)
|
|
103
|
-
|| SIGNER_CONFIG.STAGING_SIGNER_API_URL.includes(payload.iss)
|
|
104
|
-
// Temporary additional checks for known staging issuers
|
|
105
|
-
// || 'https://signer-api-staging.pers.ninja'.includes(payload.iss)
|
|
106
|
-
|| 'https://dev.api.pers.ninja/v2'.includes(payload.iss)) {
|
|
124
|
+
|| SIGNER_CONFIG.STAGING_SIGNER_API_URL.includes(payload.iss)) {
|
|
107
125
|
return true;
|
|
108
|
-
/* } else if (payload.iss === SIGNER_CONFIG.DEFAULT_PERS_API_URL ||
|
|
109
|
-
SIGNER_CONFIG.DEFAULT_PERS_API_URL.includes(payload.iss)) {
|
|
110
|
-
// Explicitly production
|
|
111
|
-
return false; */
|
|
112
126
|
}
|
|
113
127
|
}
|
|
114
128
|
return false;
|
|
@@ -1451,11 +1465,11 @@ class TransactionSigningService {
|
|
|
1451
1465
|
let provider;
|
|
1452
1466
|
try {
|
|
1453
1467
|
// Try primary provider first
|
|
1454
|
-
console.info(`[TransactionSigningService] Attempting to connect to primary provider: ${ethersProviderUrl}`);
|
|
1468
|
+
//console.info(`[TransactionSigningService] Attempting to connect to primary provider: ${ethersProviderUrl}`);
|
|
1455
1469
|
provider = new JsonRpcProvider(ethersProviderUrl);
|
|
1456
1470
|
// Test the connection with a simple call
|
|
1457
1471
|
await provider.getNetwork();
|
|
1458
|
-
console.info(`[TransactionSigningService] Successfully connected to primary provider`);
|
|
1472
|
+
//console.info(`[TransactionSigningService] Successfully connected to primary provider`);
|
|
1459
1473
|
}
|
|
1460
1474
|
catch (primaryError) {
|
|
1461
1475
|
console.warn(`[TransactionSigningService] Primary provider failed, falling back to: ${DEFAULT_FALLBACK_PROVIDER}`, primaryError);
|
|
@@ -1463,7 +1477,7 @@ class TransactionSigningService {
|
|
|
1463
1477
|
provider = new JsonRpcProvider(DEFAULT_FALLBACK_PROVIDER);
|
|
1464
1478
|
// Test the fallback connection
|
|
1465
1479
|
await provider.getNetwork();
|
|
1466
|
-
console.info(`[TransactionSigningService] Successfully connected to fallback provider`);
|
|
1480
|
+
//console.info(`[TransactionSigningService] Successfully connected to fallback provider`);
|
|
1467
1481
|
}
|
|
1468
1482
|
catch (fallbackError) {
|
|
1469
1483
|
console.error(`[TransactionSigningService] Both primary and fallback providers failed`, { primaryError, fallbackError });
|
|
@@ -1527,13 +1541,13 @@ class TransactionSigningService {
|
|
|
1527
1541
|
// Validate input parameters first using TransactionValidator
|
|
1528
1542
|
TransactionValidator.validateSigningParams(params);
|
|
1529
1543
|
const { transactionId, authTokens, ethersProviderUrl } = params;
|
|
1530
|
-
console.info(`[TransactionSigningService] Starting signature process for ${transactionId}`);
|
|
1544
|
+
// console.info(`[TransactionSigningService] Starting signature process for ${transactionId}`);
|
|
1531
1545
|
try {
|
|
1532
1546
|
// Step 2: Prepare wallet for signing
|
|
1533
1547
|
const wallet = await this.prepareWallet(authTokens, ethersProviderUrl);
|
|
1534
1548
|
// Step 3: Execute transaction signing
|
|
1535
1549
|
const signature = await this.executeTransactionSigning(wallet, signingData);
|
|
1536
|
-
console.info(`[TransactionSigningService] Completed signing successfully: ${transactionId}`);
|
|
1550
|
+
// console.info(`[TransactionSigningService] Completed signing successfully: ${transactionId}`);
|
|
1537
1551
|
return {
|
|
1538
1552
|
success: true,
|
|
1539
1553
|
transactionId,
|
|
@@ -1666,6 +1680,28 @@ function getServiceConfig() {
|
|
|
1666
1680
|
return getConfigProvider().getServiceConfig();
|
|
1667
1681
|
}
|
|
1668
1682
|
|
|
1683
|
+
/**
|
|
1684
|
+
* Get the WebAuthn configuration based on the current environment.
|
|
1685
|
+
* This logic is shared between browser and React Native implementations
|
|
1686
|
+
* to ensure consistent behavior while respecting platform differences.
|
|
1687
|
+
*/
|
|
1688
|
+
function getWebAuthnConfig() {
|
|
1689
|
+
// Check if running in a browser environment with window.location available
|
|
1690
|
+
// We use a safe check that won't crash in React Native
|
|
1691
|
+
const isBrowser = typeof window !== 'undefined' && !!window.location && !!window.location.hostname;
|
|
1692
|
+
return {
|
|
1693
|
+
relyingParty: {
|
|
1694
|
+
// In browser, prefer the actual hostname to avoid RP ID mismatch errors
|
|
1695
|
+
// In React Native, use the configured default RP ID
|
|
1696
|
+
id: isBrowser ? window.location.hostname : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
1697
|
+
name: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_NAME,
|
|
1698
|
+
// In browser, use the actual origin
|
|
1699
|
+
// In React Native, fallback to the default RP ID (or a configured origin if added later)
|
|
1700
|
+
origin: isBrowser ? window.location.origin : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
1701
|
+
}
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1669
1705
|
/**
|
|
1670
1706
|
* Base64URL encoding/decoding utilities
|
|
1671
1707
|
* Used for WebAuthn credential ID and challenge handling
|
|
@@ -1738,9 +1774,8 @@ class BrowserWebAuthnProvider {
|
|
|
1738
1774
|
// 1. Prepare options for navigator.credentials.create
|
|
1739
1775
|
// We construct authenticatorSelection manually to ensure no conflicting legacy properties are present
|
|
1740
1776
|
const authenticatorSelection = {
|
|
1741
|
-
residentKey:
|
|
1742
|
-
|
|
1743
|
-
userVerification: challenge.authenticatorSelection?.userVerification || 'preferred',
|
|
1777
|
+
residentKey: WEBAUTHN_CONFIG.RESIDENT_KEY, // Force Passkey (discoverable credential)
|
|
1778
|
+
userVerification: challenge.authenticatorSelection?.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
1744
1779
|
};
|
|
1745
1780
|
const publicKey = {
|
|
1746
1781
|
challenge: base64UrlToBuffer(challenge.challenge),
|
|
@@ -1756,16 +1791,13 @@ class BrowserWebAuthnProvider {
|
|
|
1756
1791
|
pubKeyCredParams: challenge.pubKeyCredParams,
|
|
1757
1792
|
authenticatorSelection,
|
|
1758
1793
|
attestation: 'none',
|
|
1759
|
-
timeout: challenge.timeout ||
|
|
1794
|
+
timeout: challenge.timeout || WEBAUTHN_CONFIG.TIMEOUT,
|
|
1760
1795
|
excludeCredentials: challenge.excludeCredentials?.map((cred) => ({
|
|
1761
1796
|
id: base64UrlToBuffer(cred.id),
|
|
1762
1797
|
type: 'public-key',
|
|
1763
1798
|
transports: cred.transports,
|
|
1764
1799
|
})),
|
|
1765
1800
|
};
|
|
1766
|
-
// console.log('WebAuthn create options:', publicKey);
|
|
1767
|
-
// console.log('WebAuthn create challenge:', challenge);
|
|
1768
|
-
// console.log('this.config', this.config)
|
|
1769
1801
|
// 2. Call the browser's native WebAuthn API
|
|
1770
1802
|
const credential = await navigator.credentials.create({ publicKey });
|
|
1771
1803
|
if (!credential)
|
|
@@ -1789,8 +1821,8 @@ class BrowserWebAuthnProvider {
|
|
|
1789
1821
|
const publicKey = {
|
|
1790
1822
|
challenge: base64UrlToBuffer(challenge.challenge),
|
|
1791
1823
|
rpId: challenge.rpId || this.config.relyingParty.id,
|
|
1792
|
-
userVerification: challenge.userVerification ||
|
|
1793
|
-
timeout:
|
|
1824
|
+
userVerification: challenge.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
1825
|
+
timeout: WEBAUTHN_CONFIG.TIMEOUT,
|
|
1794
1826
|
allowCredentials: challenge.allowCredentials?.webauthn?.map((cred) => ({
|
|
1795
1827
|
id: base64UrlToBuffer(cred.id),
|
|
1796
1828
|
type: 'public-key',
|
|
@@ -1829,13 +1861,7 @@ class BrowserWebAuthnProvider {
|
|
|
1829
1861
|
* Get WebAuthn provider for browser environments
|
|
1830
1862
|
*/
|
|
1831
1863
|
async function getBrowserWebAuthnProvider() {
|
|
1832
|
-
const config =
|
|
1833
|
-
relyingParty: {
|
|
1834
|
-
id: typeof window !== 'undefined' ? window.location.hostname : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
1835
|
-
name: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_NAME,
|
|
1836
|
-
origin: typeof window !== 'undefined' ? window.location.origin : SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
1837
|
-
}
|
|
1838
|
-
};
|
|
1864
|
+
const config = getWebAuthnConfig();
|
|
1839
1865
|
return new BrowserWebAuthnProvider(config);
|
|
1840
1866
|
}
|
|
1841
1867
|
|
|
@@ -1851,13 +1877,18 @@ var WebAuthnProvider_browser = /*#__PURE__*/Object.freeze({
|
|
|
1851
1877
|
*/
|
|
1852
1878
|
class ReactNativeWebAuthnProvider {
|
|
1853
1879
|
constructor(config) {
|
|
1880
|
+
this.passkeyLibrary = null;
|
|
1854
1881
|
this.config = config;
|
|
1855
1882
|
}
|
|
1856
1883
|
async getPasskeyLibrary() {
|
|
1884
|
+
if (this.passkeyLibrary) {
|
|
1885
|
+
return this.passkeyLibrary;
|
|
1886
|
+
}
|
|
1857
1887
|
try {
|
|
1858
1888
|
// Dynamic import to avoid hard dependency
|
|
1859
1889
|
// @ts-ignore - Optional dependency
|
|
1860
1890
|
const { Passkey } = await import('react-native-passkey');
|
|
1891
|
+
this.passkeyLibrary = Passkey;
|
|
1861
1892
|
return Passkey;
|
|
1862
1893
|
}
|
|
1863
1894
|
catch (error) {
|
|
@@ -1873,7 +1904,6 @@ class ReactNativeWebAuthnProvider {
|
|
|
1873
1904
|
}
|
|
1874
1905
|
}
|
|
1875
1906
|
async handleWebFallback(operation, challenge) {
|
|
1876
|
-
console.log(`Falling back to browser WebAuthn for React Native Web (${operation})...`);
|
|
1877
1907
|
try {
|
|
1878
1908
|
// Import and use browser WebAuthn provider
|
|
1879
1909
|
const { getBrowserWebAuthnProvider } = await Promise.resolve().then(function () { return WebAuthnProvider_browser; });
|
|
@@ -1896,8 +1926,8 @@ class ReactNativeWebAuthnProvider {
|
|
|
1896
1926
|
// If it's a very long string, it might be an issue.
|
|
1897
1927
|
// But let's focus on aligning the authenticatorSelection first.
|
|
1898
1928
|
const authenticatorSelection = {
|
|
1899
|
-
residentKey:
|
|
1900
|
-
userVerification: challenge.authenticatorSelection?.userVerification ||
|
|
1929
|
+
residentKey: WEBAUTHN_CONFIG.RESIDENT_KEY, // Force Passkey (discoverable credential)
|
|
1930
|
+
userVerification: challenge.authenticatorSelection?.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
1901
1931
|
// Explicitly undefined to avoid issues, though JS objects don't usually include undefined keys in JSON
|
|
1902
1932
|
// But react-native-passkey might handle it differently.
|
|
1903
1933
|
};
|
|
@@ -1926,11 +1956,9 @@ class ReactNativeWebAuthnProvider {
|
|
|
1926
1956
|
transports: v.transports
|
|
1927
1957
|
})), // Cast to any to avoid strict type mismatch with react-native-passkey types
|
|
1928
1958
|
authenticatorSelection,
|
|
1929
|
-
timeout: challenge.timeout ||
|
|
1959
|
+
timeout: challenge.timeout || WEBAUTHN_CONFIG.TIMEOUT,
|
|
1930
1960
|
};
|
|
1931
|
-
console.log('[RNWebAuthn] Calling Passkey.create with:', JSON.stringify(request, null, 2));
|
|
1932
1961
|
const result = await Passkey.create(request);
|
|
1933
|
-
console.log('[RNWebAuthn] Passkey.create success:', JSON.stringify(result, null, 2));
|
|
1934
1962
|
return {
|
|
1935
1963
|
id: result.id,
|
|
1936
1964
|
clientDataJSON: result.response.clientDataJSON,
|
|
@@ -1958,12 +1986,10 @@ class ReactNativeWebAuthnProvider {
|
|
|
1958
1986
|
// transports: cred.transports,
|
|
1959
1987
|
})),
|
|
1960
1988
|
rpId: challenge.rpId || this.config.relyingParty.id,
|
|
1961
|
-
userVerification: challenge.userVerification ||
|
|
1962
|
-
timeout: challenge.timeout ||
|
|
1989
|
+
userVerification: challenge.userVerification || WEBAUTHN_CONFIG.USER_VERIFICATION,
|
|
1990
|
+
timeout: challenge.timeout || WEBAUTHN_CONFIG.TIMEOUT,
|
|
1963
1991
|
};
|
|
1964
|
-
console.log('[RNWebAuthn] Calling Passkey.get (sign) with:', JSON.stringify(request, null, 2));
|
|
1965
1992
|
const credential = await Passkey.get(request);
|
|
1966
|
-
console.log('[RNWebAuthn] Passkey.get success:', JSON.stringify(credential, null, 2));
|
|
1967
1993
|
return {
|
|
1968
1994
|
kind: 'Fido2',
|
|
1969
1995
|
credentialAssertion: {
|
|
@@ -1988,12 +2014,7 @@ class ReactNativeWebAuthnProvider {
|
|
|
1988
2014
|
* Get WebAuthn provider for React Native environments
|
|
1989
2015
|
*/
|
|
1990
2016
|
async function getReactNativeWebAuthnProvider() {
|
|
1991
|
-
const config =
|
|
1992
|
-
relyingParty: {
|
|
1993
|
-
id: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_ID,
|
|
1994
|
-
name: SIGNER_CONFIG.DEFAULT_RELYING_PARTY_NAME,
|
|
1995
|
-
}
|
|
1996
|
-
};
|
|
2017
|
+
const config = getWebAuthnConfig();
|
|
1997
2018
|
return new ReactNativeWebAuthnProvider(config);
|
|
1998
2019
|
}
|
|
1999
2020
|
|
|
@@ -2125,7 +2146,6 @@ class PersSignerSDK {
|
|
|
2125
2146
|
* @throws {Error} If required configuration is missing
|
|
2126
2147
|
*/
|
|
2127
2148
|
constructor(config) {
|
|
2128
|
-
console.log('DEBUG: v1.2.0');
|
|
2129
2149
|
this.config = config;
|
|
2130
2150
|
setConfigProvider(new WebConfigProvider({
|
|
2131
2151
|
apiUrl: config.apiUrl || SIGNER_CONFIG.DEFAULT_SIGNER_API_URL,
|
|
@@ -2334,10 +2354,12 @@ class PersSignerSDK {
|
|
|
2334
2354
|
authTokens,
|
|
2335
2355
|
ethersProviderUrl: this.config.ethersProviderUrl ?? DEFAULT_FALLBACK_PROVIDER
|
|
2336
2356
|
}, signingData);
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2357
|
+
if (result.success) {
|
|
2358
|
+
this.triggerStatusUpdate(SigningStatus.COMPLETED, 'Transaction signed successfully', {
|
|
2359
|
+
transactionId: payload.transactionId,
|
|
2360
|
+
signature: result.signature
|
|
2361
|
+
}, statusCallback);
|
|
2362
|
+
}
|
|
2341
2363
|
return result;
|
|
2342
2364
|
}
|
|
2343
2365
|
catch (error) {
|