@zkproofport-app/sdk 0.1.2-beta.1 → 0.2.0
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/README.md +67 -98
- package/dist/ProofportSDK.d.ts +24 -138
- package/dist/constants.d.ts +0 -42
- package/dist/index.d.ts +3 -3
- package/dist/index.esm.js +42 -354
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +42 -354
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -354
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.ts +22 -104
- package/dist/verifier.d.ts +0 -77
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -140,51 +140,6 @@ const DEFAULT_REQUEST_EXPIRY_MS = 10 * 60 * 1000;
|
|
|
140
140
|
* ```
|
|
141
141
|
*/
|
|
142
142
|
const MAX_QR_DATA_SIZE = 2953; // Version 40 with L error correction
|
|
143
|
-
/**
|
|
144
|
-
* ZKProofportNullifierRegistry contract ABI (V2).
|
|
145
|
-
*
|
|
146
|
-
* This is the current nullifier registry interface with relayer-only registration.
|
|
147
|
-
* Public view functions allow checking nullifier status and verifying proofs without registration.
|
|
148
|
-
*
|
|
149
|
-
* Key functions:
|
|
150
|
-
* - `isNullifierRegistered`: Check if a nullifier has been used
|
|
151
|
-
* - `getNullifierInfo`: Get registration details for a nullifier
|
|
152
|
-
* - `verifyOnly`: Verify a proof without registering the nullifier
|
|
153
|
-
*
|
|
154
|
-
* Note: Registration functions (verifyAndRegister) are relayer-only and not exposed in this ABI.
|
|
155
|
-
*
|
|
156
|
-
* @example
|
|
157
|
-
* ```typescript
|
|
158
|
-
* import { Contract } from 'ethers';
|
|
159
|
-
*
|
|
160
|
-
* const registry = new Contract(
|
|
161
|
-
* registryAddress,
|
|
162
|
-
* ZKPROOFPORT_NULLIFIER_REGISTRY_ABI,
|
|
163
|
-
* provider
|
|
164
|
-
* );
|
|
165
|
-
*
|
|
166
|
-
* const isUsed = await registry.isNullifierRegistered(nullifier);
|
|
167
|
-
* ```
|
|
168
|
-
*/
|
|
169
|
-
const ZKPROOFPORT_NULLIFIER_REGISTRY_ABI = [
|
|
170
|
-
'function isNullifierRegistered(bytes32 _nullifier) external view returns (bool)',
|
|
171
|
-
'function getNullifierInfo(bytes32 _nullifier) external view returns (uint64 registeredAt, bytes32 scope, bytes32 circuitId)',
|
|
172
|
-
'function verifyOnly(bytes32 _circuitId, bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool)',
|
|
173
|
-
'event NullifierRegistered(bytes32 indexed nullifier, bytes32 indexed scope, bytes32 indexed circuitId)',
|
|
174
|
-
];
|
|
175
|
-
|
|
176
|
-
var constants = /*#__PURE__*/Object.freeze({
|
|
177
|
-
__proto__: null,
|
|
178
|
-
CIRCUIT_METADATA: CIRCUIT_METADATA,
|
|
179
|
-
DEEP_LINK_HOSTS: DEEP_LINK_HOSTS,
|
|
180
|
-
DEFAULT_REQUEST_EXPIRY_MS: DEFAULT_REQUEST_EXPIRY_MS,
|
|
181
|
-
DEFAULT_SCHEME: DEFAULT_SCHEME,
|
|
182
|
-
MAX_QR_DATA_SIZE: MAX_QR_DATA_SIZE,
|
|
183
|
-
RELAY_URLS: RELAY_URLS,
|
|
184
|
-
RPC_ENDPOINTS: RPC_ENDPOINTS,
|
|
185
|
-
VERIFIER_ABI: VERIFIER_ABI,
|
|
186
|
-
ZKPROOFPORT_NULLIFIER_REGISTRY_ABI: ZKPROOFPORT_NULLIFIER_REGISTRY_ABI
|
|
187
|
-
});
|
|
188
143
|
|
|
189
144
|
/**
|
|
190
145
|
* Deep Link utilities for ZKProofport SDK
|
|
@@ -383,7 +338,6 @@ function parseProofResponseUrl(url) {
|
|
|
383
338
|
if (timestamp) {
|
|
384
339
|
response.timestamp = parseInt(timestamp, 10);
|
|
385
340
|
}
|
|
386
|
-
response.nullifier = urlObj.searchParams.get('nullifier') || undefined;
|
|
387
341
|
}
|
|
388
342
|
else if (status === 'error') {
|
|
389
343
|
response.error = urlObj.searchParams.get('error') || undefined;
|
|
@@ -911,41 +865,6 @@ function extractScopeFromPublicInputs(publicInputsHex, circuit) {
|
|
|
911
865
|
const scopeFields = publicInputsHex.slice(start, end + 1);
|
|
912
866
|
return reconstructBytes32FromFields(scopeFields);
|
|
913
867
|
}
|
|
914
|
-
/**
|
|
915
|
-
* Extract nullifier value from public inputs array.
|
|
916
|
-
*
|
|
917
|
-
* The nullifier is a bytes32 value encoded across 32 consecutive field elements
|
|
918
|
-
* in the public inputs. The exact position depends on the circuit type.
|
|
919
|
-
* Nullifiers are used for duplicate proof detection and must be unique per user+scope.
|
|
920
|
-
*
|
|
921
|
-
* @param publicInputsHex - Array of public input hex strings (zero-padded to 32 bytes)
|
|
922
|
-
* @param circuit - Optional circuit identifier to determine field positions
|
|
923
|
-
* @returns Reconstructed nullifier as hex string with 0x prefix, or null if inputs are insufficient
|
|
924
|
-
*
|
|
925
|
-
* @example
|
|
926
|
-
* ```typescript
|
|
927
|
-
* const nullifier = extractNullifierFromPublicInputs(publicInputsHex, 'coinbase_attestation');
|
|
928
|
-
* console.log(nullifier); // '0xabcd1234...'
|
|
929
|
-
*
|
|
930
|
-
* // Check if nullifier is already registered
|
|
931
|
-
* const isRegistered = await isNullifierRegistered(nullifier, registryAddress, provider);
|
|
932
|
-
* ```
|
|
933
|
-
*/
|
|
934
|
-
function extractNullifierFromPublicInputs(publicInputsHex, circuit) {
|
|
935
|
-
let start, end;
|
|
936
|
-
if (circuit === 'coinbase_country_attestation') {
|
|
937
|
-
start = 118;
|
|
938
|
-
end = 149;
|
|
939
|
-
}
|
|
940
|
-
else {
|
|
941
|
-
start = 96;
|
|
942
|
-
end = 127;
|
|
943
|
-
}
|
|
944
|
-
if (publicInputsHex.length <= end)
|
|
945
|
-
return null;
|
|
946
|
-
const nullifierFields = publicInputsHex.slice(start, end + 1);
|
|
947
|
-
return reconstructBytes32FromFields(nullifierFields);
|
|
948
|
-
}
|
|
949
868
|
/** @internal Reconstruct a bytes32 value from 32 individual field elements */
|
|
950
869
|
function reconstructBytes32FromFields(fields) {
|
|
951
870
|
if (fields.length !== 32) {
|
|
@@ -957,83 +876,6 @@ function reconstructBytes32FromFields(fields) {
|
|
|
957
876
|
}).join('');
|
|
958
877
|
return '0x' + bytes;
|
|
959
878
|
}
|
|
960
|
-
/**
|
|
961
|
-
* Check if a nullifier is already registered on-chain in the ZKProofport nullifier registry.
|
|
962
|
-
*
|
|
963
|
-
* This function queries the on-chain nullifier registry contract to determine if a nullifier
|
|
964
|
-
* has been used before. This is used to prevent duplicate proof submissions from the same user
|
|
965
|
-
* for the same scope.
|
|
966
|
-
*
|
|
967
|
-
* @param nullifier - The nullifier hash as hex string with 0x prefix
|
|
968
|
-
* @param registryAddress - ZKProofportNullifierRegistry contract address
|
|
969
|
-
* @param provider - ethers.js Provider instance (v5 or v6 compatible)
|
|
970
|
-
* @returns Promise resolving to true if nullifier is registered, false otherwise
|
|
971
|
-
*
|
|
972
|
-
* @example
|
|
973
|
-
* ```typescript
|
|
974
|
-
* const nullifier = extractNullifierFromPublicInputs(publicInputsHex, circuit);
|
|
975
|
-
* const isRegistered = await isNullifierRegistered(
|
|
976
|
-
* nullifier,
|
|
977
|
-
* '0x...',
|
|
978
|
-
* provider
|
|
979
|
-
* );
|
|
980
|
-
*
|
|
981
|
-
* if (isRegistered) {
|
|
982
|
-
* console.log('This nullifier has already been used');
|
|
983
|
-
* }
|
|
984
|
-
* ```
|
|
985
|
-
*/
|
|
986
|
-
async function isNullifierRegistered(nullifier, registryAddress, provider) {
|
|
987
|
-
const { ZKPROOFPORT_NULLIFIER_REGISTRY_ABI } = await Promise.resolve().then(function () { return constants; });
|
|
988
|
-
const contract = new ethers.ethers.Contract(registryAddress, ZKPROOFPORT_NULLIFIER_REGISTRY_ABI, provider);
|
|
989
|
-
try {
|
|
990
|
-
return await contract.isNullifierRegistered(nullifier);
|
|
991
|
-
}
|
|
992
|
-
catch {
|
|
993
|
-
return false;
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
/**
|
|
997
|
-
* Get detailed information about a registered nullifier from the on-chain registry.
|
|
998
|
-
*
|
|
999
|
-
* This function retrieves the registration timestamp, scope, and circuit ID for a nullifier
|
|
1000
|
-
* that has been registered on-chain. This metadata is useful for auditing and analytics.
|
|
1001
|
-
*
|
|
1002
|
-
* @param nullifier - The nullifier hash as hex string with 0x prefix
|
|
1003
|
-
* @param registryAddress - ZKProofportNullifierRegistry contract address
|
|
1004
|
-
* @param provider - ethers.js Provider instance (v5 or v6 compatible)
|
|
1005
|
-
* @returns Promise resolving to nullifier info object, or null if not registered
|
|
1006
|
-
*
|
|
1007
|
-
* @example
|
|
1008
|
-
* ```typescript
|
|
1009
|
-
* const info = await getNullifierInfo(nullifier, registryAddress, provider);
|
|
1010
|
-
*
|
|
1011
|
-
* if (info) {
|
|
1012
|
-
* console.log('Registered at:', new Date(info.registeredAt * 1000));
|
|
1013
|
-
* console.log('Scope:', info.scope);
|
|
1014
|
-
* console.log('Circuit:', info.circuitId);
|
|
1015
|
-
* } else {
|
|
1016
|
-
* console.log('Nullifier not registered');
|
|
1017
|
-
* }
|
|
1018
|
-
* ```
|
|
1019
|
-
*/
|
|
1020
|
-
async function getNullifierInfo(nullifier, registryAddress, provider) {
|
|
1021
|
-
const { ZKPROOFPORT_NULLIFIER_REGISTRY_ABI } = await Promise.resolve().then(function () { return constants; });
|
|
1022
|
-
const contract = new ethers.ethers.Contract(registryAddress, ZKPROOFPORT_NULLIFIER_REGISTRY_ABI, provider);
|
|
1023
|
-
try {
|
|
1024
|
-
const [registeredAt, scope, circuitId] = await contract.getNullifierInfo(nullifier);
|
|
1025
|
-
if (BigInt(registeredAt) === 0n)
|
|
1026
|
-
return null;
|
|
1027
|
-
return {
|
|
1028
|
-
registeredAt: Number(registeredAt),
|
|
1029
|
-
scope: scope,
|
|
1030
|
-
circuitId: circuitId,
|
|
1031
|
-
};
|
|
1032
|
-
}
|
|
1033
|
-
catch {
|
|
1034
|
-
return null;
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
879
|
|
|
1038
880
|
/**
|
|
1039
881
|
* Proofport SDK - Main class
|
|
@@ -1047,12 +889,15 @@ async function getNullifierInfo(nullifier, registryAddress, provider) {
|
|
|
1047
889
|
* @example
|
|
1048
890
|
* ```typescript
|
|
1049
891
|
* import { ProofportSDK } from '@zkproofport-app/sdk';
|
|
892
|
+
* import { BrowserProvider } from 'ethers';
|
|
1050
893
|
*
|
|
1051
894
|
* // Initialize SDK (uses production relay by default)
|
|
1052
895
|
* const sdk = ProofportSDK.create();
|
|
1053
896
|
*
|
|
1054
|
-
* //
|
|
1055
|
-
*
|
|
897
|
+
* // Set wallet signer for challenge-signature auth
|
|
898
|
+
* const provider = new BrowserProvider(window.ethereum);
|
|
899
|
+
* const signer = await provider.getSigner();
|
|
900
|
+
* sdk.setSigner(signer);
|
|
1056
901
|
*
|
|
1057
902
|
* // Create proof request via relay
|
|
1058
903
|
* const relay = await sdk.createRelayRequest('coinbase_attestation', {
|
|
@@ -1098,14 +943,13 @@ class ProofportSDK {
|
|
|
1098
943
|
*/
|
|
1099
944
|
constructor(config = {}) {
|
|
1100
945
|
this.pendingRequests = new Map();
|
|
1101
|
-
this.
|
|
946
|
+
this.signer = null;
|
|
1102
947
|
this.socket = null;
|
|
1103
948
|
this.config = {
|
|
1104
949
|
scheme: config.scheme || DEFAULT_SCHEME,
|
|
1105
950
|
verifiers: config.verifiers || {},
|
|
1106
951
|
};
|
|
1107
952
|
this.relayUrl = config.relayUrl || '';
|
|
1108
|
-
this.nullifierRegistry = config.nullifierRegistry;
|
|
1109
953
|
}
|
|
1110
954
|
// ============ Request Creation ============
|
|
1111
955
|
/**
|
|
@@ -1866,115 +1710,42 @@ class ProofportSDK {
|
|
|
1866
1710
|
return false;
|
|
1867
1711
|
return /Android|iPhone|iPad|iPod|webOS|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
1868
1712
|
}
|
|
1713
|
+
// ============ Relay Integration ============
|
|
1869
1714
|
/**
|
|
1870
|
-
*
|
|
1871
|
-
*
|
|
1872
|
-
* Exchanges a client_id and api_key pair for a short-lived JWT token
|
|
1873
|
-
* that can be used to authenticate relay requests.
|
|
1715
|
+
* Sets the wallet signer for challenge-signature authentication.
|
|
1716
|
+
* The signer will be used to sign challenges from the relay server.
|
|
1874
1717
|
*
|
|
1875
|
-
* @param
|
|
1876
|
-
* @param relayUrl - Relay server URL (e.g., 'https://relay.zkproofport.app')
|
|
1877
|
-
* @returns Promise resolving to AuthToken with JWT token and metadata
|
|
1878
|
-
* @throws Error if authentication fails
|
|
1718
|
+
* @param signer - Wallet signer (ethers v6 Signer or compatible object with signMessage/getAddress)
|
|
1879
1719
|
*
|
|
1880
1720
|
* @example
|
|
1881
1721
|
* ```typescript
|
|
1882
|
-
*
|
|
1883
|
-
* { clientId: 'your-client-id', apiKey: 'your-api-key' },
|
|
1884
|
-
* 'https://relay.zkproofport.app'
|
|
1885
|
-
* );
|
|
1886
|
-
* console.log('Token:', auth.token);
|
|
1887
|
-
* console.log('Expires in:', auth.expiresIn, 'seconds');
|
|
1888
|
-
* ```
|
|
1889
|
-
*/
|
|
1890
|
-
static async authenticate(credentials, relayUrl) {
|
|
1891
|
-
if (!credentials.clientId || !credentials.apiKey) {
|
|
1892
|
-
throw new Error('clientId and apiKey are required');
|
|
1893
|
-
}
|
|
1894
|
-
if (!relayUrl) {
|
|
1895
|
-
throw new Error('relayUrl is required');
|
|
1896
|
-
}
|
|
1897
|
-
const response = await fetch(`${relayUrl}/api/v1/auth/token`, {
|
|
1898
|
-
method: 'POST',
|
|
1899
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1900
|
-
body: JSON.stringify({
|
|
1901
|
-
client_id: credentials.clientId,
|
|
1902
|
-
api_key: credentials.apiKey,
|
|
1903
|
-
}),
|
|
1904
|
-
});
|
|
1905
|
-
if (!response.ok) {
|
|
1906
|
-
const error = await response.json().catch(() => ({ error: `HTTP ${response.status}` }));
|
|
1907
|
-
throw new Error(error.error || `Authentication failed: HTTP ${response.status}`);
|
|
1908
|
-
}
|
|
1909
|
-
const data = await response.json();
|
|
1910
|
-
return {
|
|
1911
|
-
token: data.token,
|
|
1912
|
-
clientId: data.client_id,
|
|
1913
|
-
dappId: data.dapp_id,
|
|
1914
|
-
tier: data.tier,
|
|
1915
|
-
expiresIn: data.expires_in,
|
|
1916
|
-
expiresAt: Date.now() + (data.expires_in * 1000),
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
/**
|
|
1920
|
-
* Checks if an auth token is still valid (not expired).
|
|
1722
|
+
* import { BrowserProvider } from 'ethers';
|
|
1921
1723
|
*
|
|
1922
|
-
*
|
|
1923
|
-
*
|
|
1924
|
-
*
|
|
1925
|
-
* @example
|
|
1926
|
-
* ```typescript
|
|
1927
|
-
* if (!ProofportSDK.isTokenValid(auth)) {
|
|
1928
|
-
* auth = await ProofportSDK.authenticate(credentials, relayUrl);
|
|
1929
|
-
* }
|
|
1724
|
+
* const provider = new BrowserProvider(window.ethereum);
|
|
1725
|
+
* const signer = await provider.getSigner();
|
|
1726
|
+
* sdk.setSigner(signer);
|
|
1930
1727
|
* ```
|
|
1931
1728
|
*/
|
|
1932
|
-
|
|
1933
|
-
|
|
1729
|
+
setSigner(signer) {
|
|
1730
|
+
this.signer = signer;
|
|
1934
1731
|
}
|
|
1935
|
-
// ============ Relay Integration ============
|
|
1936
1732
|
/**
|
|
1937
|
-
*
|
|
1938
|
-
*
|
|
1939
|
-
* Instance method that authenticates via the relay server and stores
|
|
1940
|
-
* the JWT token internally, so subsequent relay requests are automatically authenticated.
|
|
1941
|
-
*
|
|
1942
|
-
* @param credentials - Client ID and API key
|
|
1943
|
-
* @returns Promise resolving to AuthToken
|
|
1944
|
-
* @throws Error if authentication fails or relayUrl is not configured
|
|
1945
|
-
*
|
|
1946
|
-
* @example
|
|
1947
|
-
* ```typescript
|
|
1948
|
-
* const sdk = ProofportSDK.create('production');
|
|
1733
|
+
* Fetches a random challenge from the relay server.
|
|
1734
|
+
* The challenge must be signed and included in proof requests.
|
|
1949
1735
|
*
|
|
1950
|
-
*
|
|
1951
|
-
*
|
|
1952
|
-
* ```
|
|
1736
|
+
* @returns Promise resolving to ChallengeResponse with challenge hex and expiry
|
|
1737
|
+
* @throws Error if relayUrl is not configured
|
|
1953
1738
|
*/
|
|
1954
|
-
async
|
|
1739
|
+
async getChallenge() {
|
|
1955
1740
|
if (!this.relayUrl) {
|
|
1956
|
-
throw new Error('relayUrl is required
|
|
1741
|
+
throw new Error('relayUrl is required. Set it in ProofportSDK config.');
|
|
1957
1742
|
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
logout() {
|
|
1965
|
-
this.authToken = null;
|
|
1966
|
-
}
|
|
1967
|
-
/**
|
|
1968
|
-
* Returns whether the SDK instance is currently authenticated with a valid token.
|
|
1969
|
-
*/
|
|
1970
|
-
isAuthenticated() {
|
|
1971
|
-
return this.authToken !== null && ProofportSDK.isTokenValid(this.authToken);
|
|
1972
|
-
}
|
|
1973
|
-
/**
|
|
1974
|
-
* Returns the current auth token, or null if not authenticated.
|
|
1975
|
-
*/
|
|
1976
|
-
getAuthToken() {
|
|
1977
|
-
return this.authToken;
|
|
1743
|
+
const response = await fetch(`${this.relayUrl}/api/v1/challenge`);
|
|
1744
|
+
if (!response.ok) {
|
|
1745
|
+
const error = await response.json().catch(() => ({ error: `HTTP ${response.status}` }));
|
|
1746
|
+
throw new Error(error.error || `Failed to get challenge: HTTP ${response.status}`);
|
|
1747
|
+
}
|
|
1748
|
+
return await response.json();
|
|
1978
1749
|
}
|
|
1979
1750
|
/**
|
|
1980
1751
|
* Creates a proof request through the relay server.
|
|
@@ -1982,19 +1753,19 @@ class ProofportSDK {
|
|
|
1982
1753
|
* This is the recommended way to create proof requests. The relay server:
|
|
1983
1754
|
* - Issues a server-side requestId (validated by the mobile app)
|
|
1984
1755
|
* - Tracks request status in Redis
|
|
1985
|
-
* - Handles credit deduction and tier enforcement
|
|
1986
1756
|
* - Builds the deep link with relay callback URL
|
|
1757
|
+
* - Stores inputs hash for deep link integrity verification
|
|
1987
1758
|
*
|
|
1988
1759
|
* @param circuit - Circuit type identifier
|
|
1989
1760
|
* @param inputs - Circuit-specific inputs
|
|
1990
1761
|
* @param options - Request options (message, dappName, dappIcon, nonce)
|
|
1991
1762
|
* @returns Promise resolving to RelayProofRequest with requestId, deepLink, pollUrl
|
|
1992
|
-
* @throws Error if not
|
|
1763
|
+
* @throws Error if signer not set or relay request fails
|
|
1993
1764
|
*
|
|
1994
1765
|
* @example
|
|
1995
1766
|
* ```typescript
|
|
1996
1767
|
* const sdk = ProofportSDK.create();
|
|
1997
|
-
*
|
|
1768
|
+
* sdk.setSigner(signer);
|
|
1998
1769
|
*
|
|
1999
1770
|
* const relay = await sdk.createRelayRequest('coinbase_attestation', {
|
|
2000
1771
|
* scope: 'myapp.com'
|
|
@@ -2008,15 +1779,20 @@ class ProofportSDK {
|
|
|
2008
1779
|
* ```
|
|
2009
1780
|
*/
|
|
2010
1781
|
async createRelayRequest(circuit, inputs, options = {}) {
|
|
2011
|
-
if (!this.
|
|
2012
|
-
throw new Error('
|
|
1782
|
+
if (!this.signer) {
|
|
1783
|
+
throw new Error('Signer not set. Call setSigner() first.');
|
|
2013
1784
|
}
|
|
2014
1785
|
if (!this.relayUrl) {
|
|
2015
1786
|
throw new Error('relayUrl is required. Set it in ProofportSDK config.');
|
|
2016
1787
|
}
|
|
1788
|
+
// Get challenge from relay and sign it
|
|
1789
|
+
const { challenge } = await this.getChallenge();
|
|
1790
|
+
const signature = await this.signer.signMessage(challenge);
|
|
2017
1791
|
const body = {
|
|
2018
1792
|
circuitId: circuit,
|
|
2019
1793
|
inputs,
|
|
1794
|
+
challenge,
|
|
1795
|
+
signature,
|
|
2020
1796
|
};
|
|
2021
1797
|
if (options.message)
|
|
2022
1798
|
body.message = options.message;
|
|
@@ -2030,7 +1806,6 @@ class ProofportSDK {
|
|
|
2030
1806
|
method: 'POST',
|
|
2031
1807
|
headers: {
|
|
2032
1808
|
'Content-Type': 'application/json',
|
|
2033
|
-
'Authorization': `Bearer ${this.authToken.token}`,
|
|
2034
1809
|
},
|
|
2035
1810
|
body: JSON.stringify(body),
|
|
2036
1811
|
});
|
|
@@ -2113,7 +1888,7 @@ class ProofportSDK {
|
|
|
2113
1888
|
* @param callbacks.onResult - Called when proof is completed or failed
|
|
2114
1889
|
* @param callbacks.onError - Called on errors
|
|
2115
1890
|
* @returns Unsubscribe function to clean up the connection
|
|
2116
|
-
* @throws Error if
|
|
1891
|
+
* @throws Error if relayUrl not set or socket.io-client not installed
|
|
2117
1892
|
*
|
|
2118
1893
|
* @example
|
|
2119
1894
|
* ```typescript
|
|
@@ -2134,9 +1909,6 @@ class ProofportSDK {
|
|
|
2134
1909
|
* ```
|
|
2135
1910
|
*/
|
|
2136
1911
|
async subscribe(requestId, callbacks) {
|
|
2137
|
-
if (!this.authToken || !ProofportSDK.isTokenValid(this.authToken)) {
|
|
2138
|
-
throw new Error('Not authenticated. Call login() first.');
|
|
2139
|
-
}
|
|
2140
1912
|
if (!this.relayUrl) {
|
|
2141
1913
|
throw new Error('relayUrl is required. Set it in ProofportSDK config.');
|
|
2142
1914
|
}
|
|
@@ -2151,10 +1923,9 @@ class ProofportSDK {
|
|
|
2151
1923
|
if (typeof ioConnect !== 'function') {
|
|
2152
1924
|
throw new Error('Failed to load socket.io-client: io function not found');
|
|
2153
1925
|
}
|
|
2154
|
-
// Connect to relay /proof namespace
|
|
1926
|
+
// Connect to relay /proof namespace (no JWT — open connections)
|
|
2155
1927
|
const socket = ioConnect(`${this.relayUrl}/proof`, {
|
|
2156
1928
|
path: '/socket.io',
|
|
2157
|
-
auth: { token: this.authToken.token },
|
|
2158
1929
|
transports: ['websocket', 'polling'],
|
|
2159
1930
|
});
|
|
2160
1931
|
this.socket = socket;
|
|
@@ -2203,7 +1974,7 @@ class ProofportSDK {
|
|
|
2203
1974
|
async waitForProof(requestId, options = {}) {
|
|
2204
1975
|
const timeout = options.timeoutMs || 300000;
|
|
2205
1976
|
// Try Socket.IO first
|
|
2206
|
-
if (this.
|
|
1977
|
+
if (this.relayUrl) {
|
|
2207
1978
|
try {
|
|
2208
1979
|
return await new Promise((resolve, reject) => {
|
|
2209
1980
|
const timer = setTimeout(() => {
|
|
@@ -2251,30 +2022,7 @@ class ProofportSDK {
|
|
|
2251
2022
|
this.socket = null;
|
|
2252
2023
|
}
|
|
2253
2024
|
}
|
|
2254
|
-
// ============
|
|
2255
|
-
/**
|
|
2256
|
-
* Extracts the nullifier from proof public inputs.
|
|
2257
|
-
*
|
|
2258
|
-
* The nullifier is a bytes32 value derived from the user's address and scope,
|
|
2259
|
-
* used to prevent duplicate proof submissions. Each user+scope combination
|
|
2260
|
-
* produces a unique nullifier.
|
|
2261
|
-
*
|
|
2262
|
-
* @param publicInputs - Array of public input hex strings from proof response
|
|
2263
|
-
* @param circuit - Circuit type to determine field positions
|
|
2264
|
-
* @returns Nullifier as hex string (0x...), or null if inputs are insufficient
|
|
2265
|
-
*
|
|
2266
|
-
* @example
|
|
2267
|
-
* ```typescript
|
|
2268
|
-
* const result = await sdk.waitForProof(relay.requestId);
|
|
2269
|
-
* if (result.status === 'completed') {
|
|
2270
|
-
* const nullifier = sdk.extractNullifier(result.publicInputs, result.circuit);
|
|
2271
|
-
* console.log('Nullifier:', nullifier);
|
|
2272
|
-
* }
|
|
2273
|
-
* ```
|
|
2274
|
-
*/
|
|
2275
|
-
extractNullifier(publicInputs, circuit) {
|
|
2276
|
-
return extractNullifierFromPublicInputs(publicInputs, circuit);
|
|
2277
|
-
}
|
|
2025
|
+
// ============ Public Input Utilities ============
|
|
2278
2026
|
/**
|
|
2279
2027
|
* Extracts the scope from proof public inputs.
|
|
2280
2028
|
*
|
|
@@ -2297,66 +2045,6 @@ class ProofportSDK {
|
|
|
2297
2045
|
extractScope(publicInputs, circuit) {
|
|
2298
2046
|
return extractScopeFromPublicInputs(publicInputs, circuit);
|
|
2299
2047
|
}
|
|
2300
|
-
/**
|
|
2301
|
-
* Checks if a nullifier is already registered on-chain.
|
|
2302
|
-
*
|
|
2303
|
-
* Queries the ZKProofportNullifierRegistry contract to determine if the
|
|
2304
|
-
* nullifier has been used before. Used to prevent duplicate proof submissions.
|
|
2305
|
-
*
|
|
2306
|
-
* Requires `nullifierRegistry` in SDK config.
|
|
2307
|
-
*
|
|
2308
|
-
* @param nullifier - Nullifier hex string from extractNullifier()
|
|
2309
|
-
* @param provider - Optional ethers provider (defaults to public RPC for configured chain)
|
|
2310
|
-
* @returns True if nullifier is already registered
|
|
2311
|
-
* @throws Error if nullifierRegistry is not configured
|
|
2312
|
-
*
|
|
2313
|
-
* @example
|
|
2314
|
-
* ```typescript
|
|
2315
|
-
* const sdk = ProofportSDK.create({
|
|
2316
|
-
* relayUrl: 'https://relay.zkproofport.app',
|
|
2317
|
-
* nullifierRegistry: { address: '0x...', chainId: 8453 }
|
|
2318
|
-
* });
|
|
2319
|
-
*
|
|
2320
|
-
* const nullifier = sdk.extractNullifier(publicInputs, circuit);
|
|
2321
|
-
* const isDuplicate = await sdk.checkNullifier(nullifier);
|
|
2322
|
-
* ```
|
|
2323
|
-
*/
|
|
2324
|
-
async checkNullifier(nullifier, provider) {
|
|
2325
|
-
if (!this.nullifierRegistry) {
|
|
2326
|
-
throw new Error('nullifierRegistry is required. Set it in ProofportSDK config.');
|
|
2327
|
-
}
|
|
2328
|
-
const p = provider || getDefaultProvider(this.nullifierRegistry.chainId);
|
|
2329
|
-
return isNullifierRegistered(nullifier, this.nullifierRegistry.address, p);
|
|
2330
|
-
}
|
|
2331
|
-
/**
|
|
2332
|
-
* Gets detailed information about a registered nullifier from on-chain registry.
|
|
2333
|
-
*
|
|
2334
|
-
* Retrieves the registration timestamp, scope, and circuit ID for a nullifier.
|
|
2335
|
-
* Returns null if the nullifier is not registered.
|
|
2336
|
-
*
|
|
2337
|
-
* Requires `nullifierRegistry` in SDK config.
|
|
2338
|
-
*
|
|
2339
|
-
* @param nullifier - Nullifier hex string from extractNullifier()
|
|
2340
|
-
* @param provider - Optional ethers provider (defaults to public RPC for configured chain)
|
|
2341
|
-
* @returns Nullifier info or null if not registered
|
|
2342
|
-
* @throws Error if nullifierRegistry is not configured
|
|
2343
|
-
*
|
|
2344
|
-
* @example
|
|
2345
|
-
* ```typescript
|
|
2346
|
-
* const info = await sdk.getNullifierDetails(nullifier);
|
|
2347
|
-
* if (info) {
|
|
2348
|
-
* console.log('Registered at:', new Date(info.registeredAt * 1000));
|
|
2349
|
-
* console.log('Circuit:', info.circuitId);
|
|
2350
|
-
* }
|
|
2351
|
-
* ```
|
|
2352
|
-
*/
|
|
2353
|
-
async getNullifierDetails(nullifier, provider) {
|
|
2354
|
-
if (!this.nullifierRegistry) {
|
|
2355
|
-
throw new Error('nullifierRegistry is required. Set it in ProofportSDK config.');
|
|
2356
|
-
}
|
|
2357
|
-
const p = provider || getDefaultProvider(this.nullifierRegistry.chainId);
|
|
2358
|
-
return getNullifierInfo(nullifier, this.nullifierRegistry.address, p);
|
|
2359
|
-
}
|
|
2360
2048
|
}
|
|
2361
2049
|
|
|
2362
2050
|
exports.ProofportSDK = ProofportSDK;
|