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