@neus/sdk 1.0.2 → 1.0.4
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 +53 -75
- package/SECURITY.md +33 -29
- package/cjs/client.cjs +678 -337
- package/cjs/errors.cjs +1 -0
- package/cjs/gates.cjs +1 -0
- package/cjs/index.cjs +927 -362
- package/cjs/utils.cjs +408 -32
- package/cli/neus.mjs +58 -0
- package/client.js +1957 -1728
- package/errors.js +5 -5
- package/gates.js +18 -18
- package/index.js +18 -3
- package/neus-logo.svg +3 -0
- package/package.json +21 -11
- package/types.d.ts +303 -53
- package/utils.js +1291 -777
- package/widgets/README.md +12 -20
- package/widgets/index.js +9 -9
- package/widgets/verify-gate/dist/ProofBadge.js +57 -52
- package/widgets/verify-gate/dist/VerifyGate.js +357 -121
- package/widgets/verify-gate/index.js +13 -13
package/cjs/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -33,6 +34,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
33
34
|
var SDKError, ApiError, ValidationError, NetworkError, ConfigurationError, VerificationError, AuthenticationError;
|
|
34
35
|
var init_errors = __esm({
|
|
35
36
|
"errors.js"() {
|
|
37
|
+
"use strict";
|
|
36
38
|
SDKError = class _SDKError extends Error {
|
|
37
39
|
constructor(message, code = "SDK_ERROR", details = {}) {
|
|
38
40
|
super(message);
|
|
@@ -166,21 +168,75 @@ var init_errors = __esm({
|
|
|
166
168
|
});
|
|
167
169
|
|
|
168
170
|
// utils.js
|
|
171
|
+
function encodeBase58Bytes(input) {
|
|
172
|
+
let source;
|
|
173
|
+
if (input instanceof Uint8Array) {
|
|
174
|
+
source = input;
|
|
175
|
+
} else if (input instanceof ArrayBuffer) {
|
|
176
|
+
source = new Uint8Array(input);
|
|
177
|
+
} else if (ArrayBuffer.isView(input)) {
|
|
178
|
+
source = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
179
|
+
} else if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(input)) {
|
|
180
|
+
source = new Uint8Array(input);
|
|
181
|
+
} else {
|
|
182
|
+
throw new SDKError("Unsupported non-EVM signature byte format", "INVALID_SIGNATURE_FORMAT");
|
|
183
|
+
}
|
|
184
|
+
if (source.length === 0) return "";
|
|
185
|
+
let zeroes = 0;
|
|
186
|
+
while (zeroes < source.length && source[zeroes] === 0) {
|
|
187
|
+
zeroes++;
|
|
188
|
+
}
|
|
189
|
+
const iFactor = Math.log(256) / Math.log(58);
|
|
190
|
+
const size = (source.length - zeroes) * iFactor + 1 >>> 0;
|
|
191
|
+
const b58 = new Uint8Array(size);
|
|
192
|
+
let length = 0;
|
|
193
|
+
for (let i = zeroes; i < source.length; i++) {
|
|
194
|
+
let carry = source[i];
|
|
195
|
+
let j = 0;
|
|
196
|
+
for (let k = size - 1; (carry !== 0 || j < length) && k >= 0; k--, j++) {
|
|
197
|
+
carry += 256 * b58[k];
|
|
198
|
+
b58[k] = carry % 58;
|
|
199
|
+
carry = carry / 58 | 0;
|
|
200
|
+
}
|
|
201
|
+
length = j;
|
|
202
|
+
}
|
|
203
|
+
let it = size - length;
|
|
204
|
+
while (it < size && b58[it] === 0) {
|
|
205
|
+
it++;
|
|
206
|
+
}
|
|
207
|
+
let out = BASE58_ALPHABET[0].repeat(zeroes);
|
|
208
|
+
for (; it < size; it++) {
|
|
209
|
+
out += BASE58_ALPHABET[b58[it]];
|
|
210
|
+
}
|
|
211
|
+
return out;
|
|
212
|
+
}
|
|
169
213
|
function deterministicStringify(obj) {
|
|
170
214
|
if (obj === null || obj === void 0) {
|
|
171
215
|
return JSON.stringify(obj);
|
|
172
216
|
}
|
|
173
217
|
if (typeof obj !== "object") {
|
|
218
|
+
if (typeof obj === "string") return JSON.stringify(obj.normalize("NFC"));
|
|
174
219
|
return JSON.stringify(obj);
|
|
175
220
|
}
|
|
176
221
|
if (Array.isArray(obj)) {
|
|
177
|
-
return
|
|
222
|
+
return `[${obj.map((item) => item === void 0 ? "null" : deterministicStringify(item)).join(",")}]`;
|
|
178
223
|
}
|
|
179
|
-
const sortedKeys = Object.keys(obj).sort();
|
|
224
|
+
const sortedKeys = Object.keys(obj).filter((k) => obj[k] !== void 0).sort();
|
|
180
225
|
const pairs = sortedKeys.map(
|
|
181
|
-
(key) => JSON.stringify(key)
|
|
226
|
+
(key) => `${JSON.stringify(key)}:${deterministicStringify(obj[key])}`
|
|
182
227
|
);
|
|
183
|
-
return
|
|
228
|
+
return `{${pairs.join(",")}}`;
|
|
229
|
+
}
|
|
230
|
+
function chainLineForPortableProofSigner(chain, chainId) {
|
|
231
|
+
if (typeof chain === "string" && chain.length > 0) {
|
|
232
|
+
const m = chain.match(/^eip155:(\d+)$/);
|
|
233
|
+
if (m) return Number(m[1]);
|
|
234
|
+
return chain;
|
|
235
|
+
}
|
|
236
|
+
if (typeof chainId === "number" && Number.isFinite(chainId) && chainId > 0) {
|
|
237
|
+
return chainId;
|
|
238
|
+
}
|
|
239
|
+
throw new SDKError("chainId is required (or provide chain for universal mode)", "INVALID_CHAIN_CONTEXT");
|
|
184
240
|
}
|
|
185
241
|
function constructVerificationMessage({ walletAddress, signedTimestamp, data, verifierIds, chainId, chain }) {
|
|
186
242
|
if (!walletAddress || typeof walletAddress !== "string") {
|
|
@@ -195,28 +251,28 @@ function constructVerificationMessage({ walletAddress, signedTimestamp, data, ve
|
|
|
195
251
|
if (!Array.isArray(verifierIds) || verifierIds.length === 0) {
|
|
196
252
|
throw new SDKError("verifierIds is required and must be a non-empty array", "INVALID_VERIFIER_IDS");
|
|
197
253
|
}
|
|
198
|
-
|
|
199
|
-
if (!chainContext) {
|
|
254
|
+
if ((typeof chain !== "string" || !chain.length) && !(typeof chainId === "number" && chainId > 0)) {
|
|
200
255
|
throw new SDKError("chainId is required (or provide chain for universal mode)", "INVALID_CHAIN_CONTEXT");
|
|
201
256
|
}
|
|
202
|
-
if (
|
|
203
|
-
throw new SDKError("chainId must be a number when provided", "INVALID_CHAIN_ID");
|
|
204
|
-
}
|
|
205
|
-
if (chainContext === chain && (typeof chain !== "string" || !chain.includes(":"))) {
|
|
257
|
+
if (typeof chain === "string" && chain.length > 0 && !chain.includes(":")) {
|
|
206
258
|
throw new SDKError('chain must be a "namespace:reference" string', "INVALID_CHAIN");
|
|
207
259
|
}
|
|
260
|
+
if ((!chain || !chain.length) && typeof chainId !== "number") {
|
|
261
|
+
throw new SDKError("chainId must be a number when provided", "INVALID_CHAIN_ID");
|
|
262
|
+
}
|
|
263
|
+
const chainLine = chainLineForPortableProofSigner(chain, chainId);
|
|
208
264
|
const namespace = typeof chain === "string" && chain.includes(":") ? chain.split(":")[0] : "eip155";
|
|
209
265
|
const normalizedWalletAddress = namespace === "eip155" ? walletAddress.toLowerCase() : walletAddress;
|
|
210
266
|
const dataString = deterministicStringify(data);
|
|
211
267
|
const messageComponents = [
|
|
212
|
-
|
|
268
|
+
PORTABLE_PROOF_SIGNER_HEADER,
|
|
213
269
|
`Wallet: ${normalizedWalletAddress}`,
|
|
214
|
-
`Chain: ${
|
|
270
|
+
`Chain: ${chainLine}`,
|
|
215
271
|
`Verifiers: ${verifierIds.join(",")}`,
|
|
216
272
|
`Data: ${dataString}`,
|
|
217
273
|
`Timestamp: ${signedTimestamp}`
|
|
218
274
|
];
|
|
219
|
-
return messageComponents.join("\n");
|
|
275
|
+
return messageComponents.join("\n").normalize("NFC");
|
|
220
276
|
}
|
|
221
277
|
function validateWalletAddress(address) {
|
|
222
278
|
if (!address || typeof address !== "string") {
|
|
@@ -224,6 +280,25 @@ function validateWalletAddress(address) {
|
|
|
224
280
|
}
|
|
225
281
|
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
226
282
|
}
|
|
283
|
+
function validateUniversalAddress(address, chain) {
|
|
284
|
+
if (!address || typeof address !== "string") return false;
|
|
285
|
+
const value = address.trim();
|
|
286
|
+
if (!value) return false;
|
|
287
|
+
const chainRef = typeof chain === "string" ? chain.trim().toLowerCase() : "";
|
|
288
|
+
const namespace = chainRef.includes(":") ? chainRef.split(":")[0] : "";
|
|
289
|
+
if (validateWalletAddress(value)) return true;
|
|
290
|
+
if (namespace === "eip155") return false;
|
|
291
|
+
if (namespace === "solana") {
|
|
292
|
+
return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value);
|
|
293
|
+
}
|
|
294
|
+
if (namespace === "bip122") {
|
|
295
|
+
return /^(bc1|tb1|bcrt1)[a-z0-9]{11,87}$/.test(value.toLowerCase()) || /^[13mn2][a-km-zA-HJ-NP-Z1-9]{25,62}$/.test(value);
|
|
296
|
+
}
|
|
297
|
+
if (namespace === "near") {
|
|
298
|
+
return /^[a-z0-9._-]{2,64}$/.test(value);
|
|
299
|
+
}
|
|
300
|
+
return /^[A-Za-z0-9][A-Za-z0-9._:-]{1,127}$/.test(value);
|
|
301
|
+
}
|
|
227
302
|
function validateTimestamp(timestamp, maxAgeMs = 5 * 60 * 1e3) {
|
|
228
303
|
if (!timestamp || typeof timestamp !== "number") {
|
|
229
304
|
return false;
|
|
@@ -245,7 +320,7 @@ function createVerificationData(content, owner, reference = null) {
|
|
|
245
320
|
};
|
|
246
321
|
return {
|
|
247
322
|
content,
|
|
248
|
-
owner: owner.toLowerCase(),
|
|
323
|
+
owner: validateWalletAddress(owner) ? owner.toLowerCase() : owner,
|
|
249
324
|
reference: reference || {
|
|
250
325
|
// Must be a valid backend enum value; 'content' is not supported.
|
|
251
326
|
type: "other",
|
|
@@ -270,9 +345,234 @@ function deriveDid(address, chainIdOrChain) {
|
|
|
270
345
|
return `did:pkh:eip155:${chainContext}:${address.toLowerCase()}`;
|
|
271
346
|
}
|
|
272
347
|
}
|
|
348
|
+
async function resolveDID(params, options = {}) {
|
|
349
|
+
const endpointPath = options.endpoint || "/api/v1/profile/did/resolve";
|
|
350
|
+
const apiUrl = typeof options.apiUrl === "string" ? options.apiUrl.trim() : "";
|
|
351
|
+
const resolveEndpoint = (path) => {
|
|
352
|
+
if (!path || typeof path !== "string") return null;
|
|
353
|
+
const trimmedPath = path.trim();
|
|
354
|
+
if (!trimmedPath) return null;
|
|
355
|
+
if (/^https?:\/\//i.test(trimmedPath)) return trimmedPath;
|
|
356
|
+
if (trimmedPath.startsWith("/")) {
|
|
357
|
+
if (!apiUrl) return trimmedPath;
|
|
358
|
+
try {
|
|
359
|
+
return new URL(trimmedPath, apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`).toString();
|
|
360
|
+
} catch {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const base = apiUrl || NEUS_CONSTANTS.API_BASE_URL;
|
|
365
|
+
if (!base || typeof base !== "string") return null;
|
|
366
|
+
try {
|
|
367
|
+
return new URL(trimmedPath, base.endsWith("/") ? base : `${base}/`).toString();
|
|
368
|
+
} catch {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const endpoint = resolveEndpoint(endpointPath);
|
|
373
|
+
if (!endpoint) {
|
|
374
|
+
throw new SDKError("resolveDID requires a valid endpoint", "INVALID_ENDPOINT");
|
|
375
|
+
}
|
|
376
|
+
const payload = {
|
|
377
|
+
walletAddress: params?.walletAddress,
|
|
378
|
+
chainId: params?.chainId,
|
|
379
|
+
chain: params?.chain
|
|
380
|
+
};
|
|
381
|
+
const isRelative = endpoint.startsWith("/") || !/^https?:\/\//i.test(endpoint);
|
|
382
|
+
const credentialsMode = options.credentials !== void 0 ? options.credentials : isRelative ? "same-origin" : "omit";
|
|
383
|
+
try {
|
|
384
|
+
const response = await fetch(endpoint, {
|
|
385
|
+
method: "POST",
|
|
386
|
+
headers: {
|
|
387
|
+
"Content-Type": "application/json",
|
|
388
|
+
Accept: "application/json",
|
|
389
|
+
...options.headers || {}
|
|
390
|
+
},
|
|
391
|
+
body: JSON.stringify(payload),
|
|
392
|
+
credentials: credentialsMode
|
|
393
|
+
});
|
|
394
|
+
const json = await response.json().catch(() => null);
|
|
395
|
+
if (!response.ok) {
|
|
396
|
+
const msg = json?.error?.message || json?.error || json?.message || "DID resolution failed";
|
|
397
|
+
throw new SDKError(msg, "DID_RESOLVE_FAILED", json);
|
|
398
|
+
}
|
|
399
|
+
const did = json?.data?.did || json?.did;
|
|
400
|
+
if (!did || typeof did !== "string") {
|
|
401
|
+
throw new SDKError("DID resolution missing DID", "DID_RESOLVE_MISSING", json);
|
|
402
|
+
}
|
|
403
|
+
return { did, data: json?.data || null, raw: json };
|
|
404
|
+
} catch (error) {
|
|
405
|
+
if (error instanceof SDKError) throw error;
|
|
406
|
+
throw new SDKError(`DID resolution failed: ${error?.message || error}`, "DID_RESOLVE_FAILED");
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
async function standardizeVerificationRequest(params, options = {}) {
|
|
410
|
+
const endpointPath = options.endpoint || "/api/v1/verification/standardize";
|
|
411
|
+
const apiUrl = typeof options.apiUrl === "string" ? options.apiUrl.trim() : "";
|
|
412
|
+
const resolveEndpoint = (path) => {
|
|
413
|
+
if (!path || typeof path !== "string") return null;
|
|
414
|
+
const trimmedPath = path.trim();
|
|
415
|
+
if (!trimmedPath) return null;
|
|
416
|
+
if (/^https?:\/\//i.test(trimmedPath)) return trimmedPath;
|
|
417
|
+
if (trimmedPath.startsWith("/")) {
|
|
418
|
+
if (!apiUrl) return trimmedPath;
|
|
419
|
+
try {
|
|
420
|
+
return new URL(trimmedPath, apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`).toString();
|
|
421
|
+
} catch {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const base = apiUrl || NEUS_CONSTANTS.API_BASE_URL;
|
|
426
|
+
if (!base || typeof base !== "string") return null;
|
|
427
|
+
try {
|
|
428
|
+
return new URL(trimmedPath, base.endsWith("/") ? base : `${base}/`).toString();
|
|
429
|
+
} catch {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
const endpoint = resolveEndpoint(endpointPath);
|
|
434
|
+
if (!endpoint) {
|
|
435
|
+
throw new SDKError("standardizeVerificationRequest requires a valid endpoint", "INVALID_ENDPOINT");
|
|
436
|
+
}
|
|
437
|
+
const isRelative = endpoint.startsWith("/") || !/^https?:\/\//i.test(endpoint);
|
|
438
|
+
const credentialsMode = options.credentials !== void 0 ? options.credentials : isRelative ? "same-origin" : "omit";
|
|
439
|
+
try {
|
|
440
|
+
const response = await fetch(endpoint, {
|
|
441
|
+
method: "POST",
|
|
442
|
+
headers: {
|
|
443
|
+
"Content-Type": "application/json",
|
|
444
|
+
Accept: "application/json",
|
|
445
|
+
...options.headers || {}
|
|
446
|
+
},
|
|
447
|
+
body: JSON.stringify(params || {}),
|
|
448
|
+
credentials: credentialsMode
|
|
449
|
+
});
|
|
450
|
+
const json = await response.json().catch(() => null);
|
|
451
|
+
if (!response.ok) {
|
|
452
|
+
const msg = json?.error?.message || json?.error || json?.message || "Standardize request failed";
|
|
453
|
+
throw new SDKError(msg, "STANDARDIZE_FAILED", json);
|
|
454
|
+
}
|
|
455
|
+
return json?.data || json;
|
|
456
|
+
} catch (error) {
|
|
457
|
+
if (error instanceof SDKError) throw error;
|
|
458
|
+
throw new SDKError(`Standardize request failed: ${error?.message || error}`, "STANDARDIZE_FAILED");
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function resolveZkPassportConfig(overrides = {}) {
|
|
462
|
+
const defaults = {
|
|
463
|
+
provider: "zkpassport",
|
|
464
|
+
scope: "basic_kyc",
|
|
465
|
+
checkSanctions: true,
|
|
466
|
+
requireFaceMatch: true,
|
|
467
|
+
faceMatchMode: "strict"
|
|
468
|
+
};
|
|
469
|
+
return {
|
|
470
|
+
...defaults,
|
|
471
|
+
...overrides && typeof overrides === "object" ? overrides : {}
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
function toHexUtf8(value) {
|
|
475
|
+
const input = typeof value === "string" ? value : String(value || "");
|
|
476
|
+
const bytes = new TextEncoder().encode(input);
|
|
477
|
+
return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
478
|
+
}
|
|
479
|
+
async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
480
|
+
const msg = typeof message === "string" ? message : String(message || "");
|
|
481
|
+
if (!msg) {
|
|
482
|
+
throw new SDKError("signMessage: message is required", "INVALID_ARGUMENT");
|
|
483
|
+
}
|
|
484
|
+
const resolvedProvider = provider || (typeof window !== "undefined" && window?.ethereum ? window.ethereum : null);
|
|
485
|
+
if (!resolvedProvider) {
|
|
486
|
+
throw new SDKError("signMessage: provider is required", "SIGNER_UNAVAILABLE");
|
|
487
|
+
}
|
|
488
|
+
const chainStr = typeof chain === "string" && chain.trim().length > 0 ? chain.trim() : "eip155";
|
|
489
|
+
const namespace = chainStr.includes(":") ? chainStr.split(":")[0] || "eip155" : "eip155";
|
|
490
|
+
const resolveAddress = async () => {
|
|
491
|
+
if (typeof walletAddress === "string" && walletAddress.trim().length > 0) return walletAddress;
|
|
492
|
+
if (namespace === "solana") {
|
|
493
|
+
if (resolvedProvider?.publicKey && typeof resolvedProvider.publicKey.toBase58 === "function") {
|
|
494
|
+
const pk = resolvedProvider.publicKey.toBase58();
|
|
495
|
+
if (typeof pk === "string" && pk) return pk;
|
|
496
|
+
}
|
|
497
|
+
if (typeof resolvedProvider.getAddress === "function") {
|
|
498
|
+
const addr = await resolvedProvider.getAddress().catch(() => null);
|
|
499
|
+
if (typeof addr === "string" && addr) return addr;
|
|
500
|
+
}
|
|
501
|
+
if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
|
|
505
|
+
if (typeof resolvedProvider.getAddress === "function") return resolvedProvider.getAddress();
|
|
506
|
+
if (typeof resolvedProvider.request === "function") {
|
|
507
|
+
let accounts = await resolvedProvider.request({ method: "eth_accounts" }).catch(() => []);
|
|
508
|
+
if (!Array.isArray(accounts) || accounts.length === 0) {
|
|
509
|
+
accounts = await resolvedProvider.request({ method: "eth_requestAccounts" }).catch(() => []);
|
|
510
|
+
}
|
|
511
|
+
if (Array.isArray(accounts) && accounts[0]) return accounts[0];
|
|
512
|
+
}
|
|
513
|
+
return null;
|
|
514
|
+
};
|
|
515
|
+
if (namespace !== "eip155") {
|
|
516
|
+
if (typeof resolvedProvider.signMessage === "function") {
|
|
517
|
+
const encoded = typeof msg === "string" ? new TextEncoder().encode(msg) : msg;
|
|
518
|
+
const result = await resolvedProvider.signMessage(encoded);
|
|
519
|
+
if (typeof result === "string" && result) return result;
|
|
520
|
+
if (result instanceof Uint8Array) return encodeBase58Bytes(result);
|
|
521
|
+
if (result instanceof ArrayBuffer) return encodeBase58Bytes(new Uint8Array(result));
|
|
522
|
+
if (ArrayBuffer.isView(result)) return encodeBase58Bytes(result);
|
|
523
|
+
if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(result)) return encodeBase58Bytes(result);
|
|
524
|
+
}
|
|
525
|
+
throw new SDKError("Non-EVM signing requires provider.signMessage", "SIGNER_UNAVAILABLE");
|
|
526
|
+
}
|
|
527
|
+
const address = await resolveAddress();
|
|
528
|
+
if (typeof resolvedProvider.request === "function" && address) {
|
|
529
|
+
let firstPersonalSignError = null;
|
|
530
|
+
try {
|
|
531
|
+
const sig = await resolvedProvider.request({ method: "personal_sign", params: [msg, address] });
|
|
532
|
+
if (typeof sig === "string" && sig) return sig;
|
|
533
|
+
} catch (error) {
|
|
534
|
+
firstPersonalSignError = error;
|
|
535
|
+
}
|
|
536
|
+
let secondPersonalSignError = null;
|
|
537
|
+
try {
|
|
538
|
+
const sig = await resolvedProvider.request({ method: "personal_sign", params: [address, msg] });
|
|
539
|
+
if (typeof sig === "string" && sig) return sig;
|
|
540
|
+
} catch (error) {
|
|
541
|
+
secondPersonalSignError = error;
|
|
542
|
+
const signatureErrorMessage = String(
|
|
543
|
+
error?.message || error?.reason || firstPersonalSignError?.message || firstPersonalSignError?.reason || ""
|
|
544
|
+
).toLowerCase();
|
|
545
|
+
const needsHex = /byte|bytes|invalid byte sequence|encoding|non-hex/i.test(signatureErrorMessage);
|
|
546
|
+
if (needsHex) {
|
|
547
|
+
try {
|
|
548
|
+
const hexMsg = toHexUtf8(msg);
|
|
549
|
+
const sig = await resolvedProvider.request({ method: "personal_sign", params: [hexMsg, address] });
|
|
550
|
+
if (typeof sig === "string" && sig) return sig;
|
|
551
|
+
} catch {
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
const sig = await resolvedProvider.request({ method: "eth_sign", params: [address, msg] });
|
|
557
|
+
if (typeof sig === "string" && sig) return sig;
|
|
558
|
+
} catch {
|
|
559
|
+
}
|
|
560
|
+
if (secondPersonalSignError || firstPersonalSignError) {
|
|
561
|
+
const lastError = secondPersonalSignError || firstPersonalSignError;
|
|
562
|
+
const isUserRejection = [4001, "ACTION_REJECTED"].includes(lastError?.code);
|
|
563
|
+
if (isUserRejection) {
|
|
564
|
+
throw lastError;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (typeof resolvedProvider.signMessage === "function") {
|
|
569
|
+
const result = await resolvedProvider.signMessage(msg);
|
|
570
|
+
if (typeof result === "string" && result) return result;
|
|
571
|
+
}
|
|
572
|
+
throw new SDKError("Unable to sign message with provided wallet/provider", "SIGNER_UNAVAILABLE");
|
|
573
|
+
}
|
|
273
574
|
function isTerminalStatus(status) {
|
|
274
|
-
if (!status || typeof status !== "string")
|
|
275
|
-
return false;
|
|
575
|
+
if (!status || typeof status !== "string") return false;
|
|
276
576
|
const successStates = [
|
|
277
577
|
"verified",
|
|
278
578
|
"verified_no_verifiers",
|
|
@@ -293,8 +593,7 @@ function isTerminalStatus(status) {
|
|
|
293
593
|
return successStates.includes(status) || failureStates.includes(status);
|
|
294
594
|
}
|
|
295
595
|
function isSuccessStatus(status) {
|
|
296
|
-
if (!status || typeof status !== "string")
|
|
297
|
-
return false;
|
|
596
|
+
if (!status || typeof status !== "string") return false;
|
|
298
597
|
const successStates = [
|
|
299
598
|
"verified",
|
|
300
599
|
"verified_no_verifiers",
|
|
@@ -305,8 +604,7 @@ function isSuccessStatus(status) {
|
|
|
305
604
|
return successStates.includes(status);
|
|
306
605
|
}
|
|
307
606
|
function isFailureStatus(status) {
|
|
308
|
-
if (!status || typeof status !== "string")
|
|
309
|
-
return false;
|
|
607
|
+
if (!status || typeof status !== "string") return false;
|
|
310
608
|
const failureStates = [
|
|
311
609
|
"rejected",
|
|
312
610
|
"rejected_verifier_failure",
|
|
@@ -457,23 +755,20 @@ function validateVerifierPayload(verifierId, data) {
|
|
|
457
755
|
const id = verifierId.replace(/@\d+$/, "");
|
|
458
756
|
if (id === "nft-ownership") {
|
|
459
757
|
["contractAddress", "tokenId", "chainId"].forEach((key) => {
|
|
460
|
-
if (!(key in data))
|
|
461
|
-
result.missing.push(key);
|
|
758
|
+
if (!(key in data)) result.missing.push(key);
|
|
462
759
|
});
|
|
463
760
|
if (!("ownerAddress" in data)) {
|
|
464
|
-
result.warnings.push("ownerAddress omitted (
|
|
761
|
+
result.warnings.push("ownerAddress omitted (defaults to the signed walletAddress)");
|
|
465
762
|
}
|
|
466
763
|
} else if (id === "token-holding") {
|
|
467
764
|
["contractAddress", "minBalance", "chainId"].forEach((key) => {
|
|
468
|
-
if (!(key in data))
|
|
469
|
-
result.missing.push(key);
|
|
765
|
+
if (!(key in data)) result.missing.push(key);
|
|
470
766
|
});
|
|
471
767
|
if (!("ownerAddress" in data)) {
|
|
472
|
-
result.warnings.push("ownerAddress omitted (
|
|
768
|
+
result.warnings.push("ownerAddress omitted (defaults to the signed walletAddress)");
|
|
473
769
|
}
|
|
474
770
|
} else if (id === "ownership-basic") {
|
|
475
|
-
if (!("owner" in data))
|
|
476
|
-
result.missing.push("owner");
|
|
771
|
+
if (!("owner" in data)) result.missing.push("owner");
|
|
477
772
|
const hasContent = typeof data.content === "string" && data.content.length > 0;
|
|
478
773
|
const hasContentHash = typeof data.contentHash === "string" && data.contentHash.length > 0;
|
|
479
774
|
const hasRefId = typeof data.reference?.id === "string" && data.reference.id.length > 0;
|
|
@@ -537,8 +832,7 @@ async function withRetry(fn, options = {}) {
|
|
|
537
832
|
return await fn();
|
|
538
833
|
} catch (error) {
|
|
539
834
|
lastError = error;
|
|
540
|
-
if (attempt === maxAttempts)
|
|
541
|
-
break;
|
|
835
|
+
if (attempt === maxAttempts) break;
|
|
542
836
|
const delayMs = Math.min(
|
|
543
837
|
baseDelay * Math.pow(backoffFactor, attempt - 1),
|
|
544
838
|
maxDelay
|
|
@@ -606,10 +900,73 @@ function validateSignatureComponents({ walletAddress, signature, signedTimestamp
|
|
|
606
900
|
}
|
|
607
901
|
return result;
|
|
608
902
|
}
|
|
609
|
-
|
|
903
|
+
function toAgentDelegationMaxSpend(humanAmount, decimals) {
|
|
904
|
+
if (humanAmount === void 0 || humanAmount === null) {
|
|
905
|
+
throw new ValidationError("humanAmount is required", "humanAmount", humanAmount);
|
|
906
|
+
}
|
|
907
|
+
const s0 = String(humanAmount).trim();
|
|
908
|
+
if (!s0) {
|
|
909
|
+
throw new ValidationError("humanAmount must be non-empty", "humanAmount", humanAmount);
|
|
910
|
+
}
|
|
911
|
+
if (s0.startsWith("-") || s0.startsWith("+")) {
|
|
912
|
+
throw new ValidationError("humanAmount must be non-negative", "humanAmount", humanAmount);
|
|
913
|
+
}
|
|
914
|
+
const d = Number(decimals);
|
|
915
|
+
if (!Number.isInteger(d) || d < 0 || d > 78) {
|
|
916
|
+
throw new ValidationError("decimalPlaces must be an integer from 0 to 78", "decimals", decimals);
|
|
917
|
+
}
|
|
918
|
+
if (!/^(?:\d+\.?\d*|\.\d+)$/.test(s0)) {
|
|
919
|
+
throw new ValidationError(
|
|
920
|
+
'humanAmount must be a decimal string (e.g. "100" or "100.50")',
|
|
921
|
+
"humanAmount",
|
|
922
|
+
humanAmount
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
const dot = s0.indexOf(".");
|
|
926
|
+
const intPart = dot === -1 ? s0 : s0.slice(0, dot);
|
|
927
|
+
const fracRaw = dot === -1 ? "" : s0.slice(dot + 1);
|
|
928
|
+
const intNormalized = intPart === "" ? "0" : (() => {
|
|
929
|
+
const s = intPart.replace(/^0+/, "");
|
|
930
|
+
return s === "" ? "0" : s;
|
|
931
|
+
})();
|
|
932
|
+
if (!/^\d+$/.test(intNormalized)) {
|
|
933
|
+
throw new ValidationError("humanAmount has an invalid integer part", "humanAmount", humanAmount);
|
|
934
|
+
}
|
|
935
|
+
if (fracRaw && !/^\d*$/.test(fracRaw)) {
|
|
936
|
+
throw new ValidationError("humanAmount has an invalid fractional part", "humanAmount", humanAmount);
|
|
937
|
+
}
|
|
938
|
+
const fracPadded = `${fracRaw}${"0".repeat(d)}`.slice(0, d);
|
|
939
|
+
const base = BigInt(10) ** BigInt(d);
|
|
940
|
+
const value = BigInt(intNormalized) * base + BigInt(fracPadded || "0");
|
|
941
|
+
const out = value.toString();
|
|
942
|
+
if (out.length > 78) {
|
|
943
|
+
throw new ValidationError("maxSpend exceeds 78-digit limit after conversion", "humanAmount", humanAmount);
|
|
944
|
+
}
|
|
945
|
+
return out;
|
|
946
|
+
}
|
|
947
|
+
function getHostedCheckoutUrl(opts = {}) {
|
|
948
|
+
const base = typeof opts.baseUrl === "string" && opts.baseUrl.trim() ? opts.baseUrl.replace(/\/+$/, "") : DEFAULT_HOSTED_VERIFY_URL;
|
|
949
|
+
const params = new URLSearchParams();
|
|
950
|
+
if (opts.gateId) params.set("gateId", String(opts.gateId));
|
|
951
|
+
if (opts.returnUrl) params.set("returnUrl", String(opts.returnUrl));
|
|
952
|
+
if (Array.isArray(opts.verifiers) && opts.verifiers.length > 0) {
|
|
953
|
+
params.set("verifiers", opts.verifiers.filter(Boolean).join(","));
|
|
954
|
+
}
|
|
955
|
+
if (opts.preset) params.set("preset", String(opts.preset));
|
|
956
|
+
if (opts.mode) params.set("mode", String(opts.mode));
|
|
957
|
+
if (opts.intent) params.set("intent", String(opts.intent));
|
|
958
|
+
if (opts.origin) params.set("origin", String(opts.origin));
|
|
959
|
+
if (opts.oauthProvider) params.set("oauthProvider", String(opts.oauthProvider));
|
|
960
|
+
const qs = params.toString();
|
|
961
|
+
return qs ? `${base}?${qs}` : base;
|
|
962
|
+
}
|
|
963
|
+
var PORTABLE_PROOF_SIGNER_HEADER, BASE58_ALPHABET, StatusPoller, NEUS_CONSTANTS, DEFAULT_HOSTED_VERIFY_URL;
|
|
610
964
|
var init_utils = __esm({
|
|
611
965
|
"utils.js"() {
|
|
966
|
+
"use strict";
|
|
612
967
|
init_errors();
|
|
968
|
+
PORTABLE_PROOF_SIGNER_HEADER = "Portable Proof Verification Request";
|
|
969
|
+
BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
613
970
|
StatusPoller = class {
|
|
614
971
|
constructor(client, qHash, options = {}) {
|
|
615
972
|
this.client = client;
|
|
@@ -632,7 +989,7 @@ var init_utils = __esm({
|
|
|
632
989
|
const pollAttempt = async () => {
|
|
633
990
|
try {
|
|
634
991
|
this.attempt++;
|
|
635
|
-
const response = await this.client.
|
|
992
|
+
const response = await this.client.getProof(this.qHash);
|
|
636
993
|
if (isTerminalStatus(response.status)) {
|
|
637
994
|
resolve(response);
|
|
638
995
|
return;
|
|
@@ -677,7 +1034,7 @@ var init_utils = __esm({
|
|
|
677
1034
|
}
|
|
678
1035
|
};
|
|
679
1036
|
NEUS_CONSTANTS = {
|
|
680
|
-
|
|
1037
|
+
/** Default EVM chain id for NEUS protocol signing context (`HUB_CHAIN_ID` name kept for compatibility). */
|
|
681
1038
|
HUB_CHAIN_ID: 84532,
|
|
682
1039
|
// Supported target chains for cross-chain propagation
|
|
683
1040
|
TESTNET_CHAINS: [
|
|
@@ -705,6 +1062,7 @@ var init_utils = __esm({
|
|
|
705
1062
|
"token-holding"
|
|
706
1063
|
]
|
|
707
1064
|
};
|
|
1065
|
+
DEFAULT_HOSTED_VERIFY_URL = "https://neus.network/verify";
|
|
708
1066
|
}
|
|
709
1067
|
});
|
|
710
1068
|
|
|
@@ -712,25 +1070,40 @@ var init_utils = __esm({
|
|
|
712
1070
|
var client_exports = {};
|
|
713
1071
|
__export(client_exports, {
|
|
714
1072
|
NeusClient: () => NeusClient,
|
|
1073
|
+
PORTABLE_PROOF_SIGNER_HEADER: () => PORTABLE_PROOF_SIGNER_HEADER,
|
|
715
1074
|
constructVerificationMessage: () => constructVerificationMessage
|
|
716
1075
|
});
|
|
717
|
-
var validateVerifierData, NeusClient;
|
|
1076
|
+
var FALLBACK_PUBLIC_VERIFIER_CATALOG, EVM_ADDRESS_RE, validateVerifierData, NeusClient;
|
|
718
1077
|
var init_client = __esm({
|
|
719
1078
|
"client.js"() {
|
|
1079
|
+
"use strict";
|
|
720
1080
|
init_errors();
|
|
721
1081
|
init_utils();
|
|
1082
|
+
FALLBACK_PUBLIC_VERIFIER_CATALOG = {
|
|
1083
|
+
"ownership-basic": { supportsDirectApi: true },
|
|
1084
|
+
"ownership-pseudonym": { supportsDirectApi: true },
|
|
1085
|
+
"ownership-dns-txt": { supportsDirectApi: true },
|
|
1086
|
+
"ownership-social": { supportsDirectApi: false },
|
|
1087
|
+
"ownership-org-oauth": { supportsDirectApi: false },
|
|
1088
|
+
"contract-ownership": { supportsDirectApi: true },
|
|
1089
|
+
"nft-ownership": { supportsDirectApi: true },
|
|
1090
|
+
"token-holding": { supportsDirectApi: true },
|
|
1091
|
+
"wallet-link": { supportsDirectApi: true },
|
|
1092
|
+
"wallet-risk": { supportsDirectApi: true },
|
|
1093
|
+
"proof-of-human": { supportsDirectApi: false },
|
|
1094
|
+
"agent-identity": { supportsDirectApi: true },
|
|
1095
|
+
"agent-delegation": { supportsDirectApi: true },
|
|
1096
|
+
"ai-content-moderation": { supportsDirectApi: true }
|
|
1097
|
+
};
|
|
1098
|
+
EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
722
1099
|
validateVerifierData = (verifierId, data) => {
|
|
723
1100
|
if (!data || typeof data !== "object") {
|
|
724
1101
|
return { valid: false, error: "Data object is required" };
|
|
725
1102
|
}
|
|
726
|
-
const ownerField = verifierId === "nft-ownership" || verifierId === "token-holding" ? "ownerAddress" : "owner";
|
|
727
|
-
if (data[ownerField] && !validateWalletAddress(data[ownerField])) {
|
|
728
|
-
return { valid: false, error: `Invalid ${ownerField} address` };
|
|
729
|
-
}
|
|
730
1103
|
switch (verifierId) {
|
|
731
1104
|
case "ownership-basic":
|
|
732
|
-
if (!data.owner || !
|
|
733
|
-
return { valid: false, error: "owner (wallet address) is required" };
|
|
1105
|
+
if (!data.owner || !validateUniversalAddress(data.owner, typeof data.chain === "string" ? data.chain : void 0)) {
|
|
1106
|
+
return { valid: false, error: "owner (universal wallet address) is required" };
|
|
734
1107
|
}
|
|
735
1108
|
if (data.content !== void 0 && data.content !== null) {
|
|
736
1109
|
if (typeof data.content !== "string") {
|
|
@@ -856,17 +1229,20 @@ var init_client = __esm({
|
|
|
856
1229
|
}
|
|
857
1230
|
break;
|
|
858
1231
|
case "wallet-link":
|
|
859
|
-
if (!data.primaryWalletAddress || !
|
|
1232
|
+
if (!data.primaryWalletAddress || !validateUniversalAddress(data.primaryWalletAddress, data.chain)) {
|
|
860
1233
|
return { valid: false, error: "primaryWalletAddress is required" };
|
|
861
1234
|
}
|
|
862
|
-
if (!data.secondaryWalletAddress || !
|
|
1235
|
+
if (!data.secondaryWalletAddress || !validateUniversalAddress(data.secondaryWalletAddress, data.chain)) {
|
|
863
1236
|
return { valid: false, error: "secondaryWalletAddress is required" };
|
|
864
1237
|
}
|
|
865
1238
|
if (!data.signature || typeof data.signature !== "string") {
|
|
866
1239
|
return { valid: false, error: "signature is required (signed by secondary wallet)" };
|
|
867
1240
|
}
|
|
868
|
-
if (typeof data.
|
|
869
|
-
return { valid: false, error: "
|
|
1241
|
+
if (typeof data.chain !== "string" || !/^[a-z0-9]+:[^\s]+$/.test(data.chain)) {
|
|
1242
|
+
return { valid: false, error: "chain is required (namespace:reference)" };
|
|
1243
|
+
}
|
|
1244
|
+
if (typeof data.signatureMethod !== "string" || !data.signatureMethod.trim()) {
|
|
1245
|
+
return { valid: false, error: "signatureMethod is required" };
|
|
870
1246
|
}
|
|
871
1247
|
if (typeof data.signedTimestamp !== "number") {
|
|
872
1248
|
return { valid: false, error: "signedTimestamp is required" };
|
|
@@ -937,7 +1313,10 @@ var init_client = __esm({
|
|
|
937
1313
|
const maxBytes = 50 * 1024;
|
|
938
1314
|
const bytes = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(data.content).length : String(data.content).length;
|
|
939
1315
|
if (bytes > maxBytes) {
|
|
940
|
-
return {
|
|
1316
|
+
return {
|
|
1317
|
+
valid: false,
|
|
1318
|
+
error: `content exceeds ${maxBytes} bytes limit for ai-content-moderation verifier (text)`
|
|
1319
|
+
};
|
|
941
1320
|
}
|
|
942
1321
|
} catch {
|
|
943
1322
|
}
|
|
@@ -961,7 +1340,7 @@ var init_client = __esm({
|
|
|
961
1340
|
}
|
|
962
1341
|
break;
|
|
963
1342
|
case "wallet-risk":
|
|
964
|
-
if (data.walletAddress && !
|
|
1343
|
+
if (data.walletAddress && !validateUniversalAddress(data.walletAddress, data.chain)) {
|
|
965
1344
|
return { valid: false, error: "Invalid walletAddress" };
|
|
966
1345
|
}
|
|
967
1346
|
break;
|
|
@@ -993,6 +1372,21 @@ var init_client = __esm({
|
|
|
993
1372
|
if (typeof this.config.apiKey === "string" && this.config.apiKey.trim().length > 0) {
|
|
994
1373
|
this.defaultHeaders["Authorization"] = `Bearer ${this.config.apiKey.trim()}`;
|
|
995
1374
|
}
|
|
1375
|
+
if (typeof this.config.appId === "string" && this.config.appId.trim().length > 0) {
|
|
1376
|
+
this.defaultHeaders["X-Neus-App"] = this.config.appId.trim();
|
|
1377
|
+
}
|
|
1378
|
+
if (typeof this.config.paymentSignature === "string" && this.config.paymentSignature.trim().length > 0) {
|
|
1379
|
+
this.defaultHeaders["PAYMENT-SIGNATURE"] = this.config.paymentSignature.trim();
|
|
1380
|
+
}
|
|
1381
|
+
if (this.config.extraHeaders && typeof this.config.extraHeaders === "object") {
|
|
1382
|
+
for (const [k, v] of Object.entries(this.config.extraHeaders)) {
|
|
1383
|
+
if (!k || v === void 0 || v === null) continue;
|
|
1384
|
+
const key = String(k).trim();
|
|
1385
|
+
const value = String(v).trim();
|
|
1386
|
+
if (!key || !value) continue;
|
|
1387
|
+
this.defaultHeaders[key] = value;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
996
1390
|
try {
|
|
997
1391
|
if (typeof window !== "undefined" && window.location && window.location.origin) {
|
|
998
1392
|
this.defaultHeaders["X-Client-Origin"] = window.location.origin;
|
|
@@ -1000,87 +1394,183 @@ var init_client = __esm({
|
|
|
1000
1394
|
} catch {
|
|
1001
1395
|
}
|
|
1002
1396
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1397
|
+
_getHubChainId() {
|
|
1398
|
+
const configured = Number(this.config?.hubChainId);
|
|
1399
|
+
if (Number.isFinite(configured) && configured > 0) return Math.floor(configured);
|
|
1400
|
+
return NEUS_CONSTANTS.HUB_CHAIN_ID;
|
|
1401
|
+
}
|
|
1402
|
+
_normalizeIdentity(value) {
|
|
1403
|
+
let raw = String(value || "").trim();
|
|
1404
|
+
if (!raw) return "";
|
|
1405
|
+
const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
|
|
1406
|
+
if (didMatch && didMatch[3]) {
|
|
1407
|
+
raw = String(didMatch[3]).trim();
|
|
1408
|
+
}
|
|
1409
|
+
return EVM_ADDRESS_RE.test(raw) ? raw.toLowerCase() : raw;
|
|
1410
|
+
}
|
|
1411
|
+
_inferChainForAddress(address, explicitChain) {
|
|
1412
|
+
if (typeof explicitChain === "string" && explicitChain.includes(":")) return explicitChain.trim();
|
|
1413
|
+
const raw = String(address || "").trim();
|
|
1414
|
+
const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
|
|
1415
|
+
if (didMatch && didMatch[1] && didMatch[2]) {
|
|
1416
|
+
return `${didMatch[1]}:${didMatch[2]}`;
|
|
1417
|
+
}
|
|
1418
|
+
if (EVM_ADDRESS_RE.test(raw)) {
|
|
1419
|
+
return `eip155:${this._getHubChainId()}`;
|
|
1420
|
+
}
|
|
1421
|
+
return "solana:mainnet";
|
|
1422
|
+
}
|
|
1423
|
+
async _resolveWalletSigner(wallet) {
|
|
1424
|
+
if (!wallet) {
|
|
1425
|
+
throw new ConfigurationError("No wallet provider available");
|
|
1426
|
+
}
|
|
1427
|
+
if (wallet.address) {
|
|
1428
|
+
return { signerWalletAddress: wallet.address, provider: wallet };
|
|
1429
|
+
}
|
|
1430
|
+
if (wallet.publicKey && typeof wallet.publicKey.toBase58 === "function") {
|
|
1431
|
+
return { signerWalletAddress: wallet.publicKey.toBase58(), provider: wallet };
|
|
1432
|
+
}
|
|
1433
|
+
if (typeof wallet.getAddress === "function") {
|
|
1434
|
+
const signerWalletAddress = await wallet.getAddress().catch(() => null);
|
|
1435
|
+
return { signerWalletAddress, provider: wallet };
|
|
1436
|
+
}
|
|
1437
|
+
if (wallet.selectedAddress || wallet.request) {
|
|
1438
|
+
const provider = wallet;
|
|
1439
|
+
if (wallet.selectedAddress) {
|
|
1440
|
+
return { signerWalletAddress: wallet.selectedAddress, provider };
|
|
1441
|
+
}
|
|
1442
|
+
const accounts = await provider.request({ method: "eth_accounts" });
|
|
1443
|
+
if (!accounts || accounts.length === 0) {
|
|
1444
|
+
throw new ConfigurationError("No wallet accounts available");
|
|
1445
|
+
}
|
|
1446
|
+
return { signerWalletAddress: accounts[0], provider };
|
|
1447
|
+
}
|
|
1448
|
+
throw new ConfigurationError("Invalid wallet provider");
|
|
1449
|
+
}
|
|
1450
|
+
_getDefaultBrowserWallet() {
|
|
1451
|
+
if (typeof window === "undefined") return null;
|
|
1452
|
+
return window.ethereum || window.solana || window.phantom && window.phantom.solana || null;
|
|
1453
|
+
}
|
|
1454
|
+
async _buildPrivateGateAuth({ address, wallet, chain, signatureMethod } = {}) {
|
|
1455
|
+
const providerWallet = wallet || this._getDefaultBrowserWallet();
|
|
1456
|
+
const { signerWalletAddress, provider } = await this._resolveWalletSigner(providerWallet);
|
|
1457
|
+
if (!signerWalletAddress || typeof signerWalletAddress !== "string") {
|
|
1458
|
+
throw new ConfigurationError("No wallet accounts available");
|
|
1459
|
+
}
|
|
1460
|
+
const normalizedSigner = this._normalizeIdentity(signerWalletAddress);
|
|
1461
|
+
const normalizedAddress = this._normalizeIdentity(address);
|
|
1462
|
+
if (!normalizedSigner || normalizedSigner !== normalizedAddress) {
|
|
1463
|
+
throw new ValidationError("wallet must match address when includePrivate=true");
|
|
1464
|
+
}
|
|
1465
|
+
const signerIsEvm = EVM_ADDRESS_RE.test(normalizedSigner);
|
|
1466
|
+
const resolvedChain = this._inferChainForAddress(normalizedSigner, chain);
|
|
1467
|
+
const resolvedSignatureMethod = typeof signatureMethod === "string" && signatureMethod.trim() ? signatureMethod.trim() : signerIsEvm ? "eip191" : "ed25519";
|
|
1468
|
+
const signedTimestamp = Date.now();
|
|
1469
|
+
const message = constructVerificationMessage({
|
|
1470
|
+
walletAddress: signerWalletAddress,
|
|
1471
|
+
signedTimestamp,
|
|
1472
|
+
data: { action: "gate_check_private_proofs", walletAddress: normalizedAddress },
|
|
1473
|
+
verifierIds: ["ownership-basic"],
|
|
1474
|
+
...signerIsEvm ? { chainId: this._getHubChainId() } : { chain: resolvedChain }
|
|
1475
|
+
});
|
|
1476
|
+
let signature;
|
|
1477
|
+
try {
|
|
1478
|
+
signature = await signMessage({
|
|
1479
|
+
provider,
|
|
1480
|
+
message,
|
|
1481
|
+
walletAddress: signerWalletAddress,
|
|
1482
|
+
...signerIsEvm ? {} : { chain: resolvedChain }
|
|
1483
|
+
});
|
|
1484
|
+
} catch (error) {
|
|
1485
|
+
if (error.code === 4001) {
|
|
1486
|
+
throw new ValidationError("User rejected signature request");
|
|
1487
|
+
}
|
|
1488
|
+
throw new ValidationError(`Failed to sign message: ${error.message}`);
|
|
1489
|
+
}
|
|
1490
|
+
return {
|
|
1491
|
+
walletAddress: signerWalletAddress,
|
|
1492
|
+
signature,
|
|
1493
|
+
signedTimestamp,
|
|
1494
|
+
...signerIsEvm ? {} : { chain: resolvedChain, signatureMethod: resolvedSignatureMethod }
|
|
1495
|
+
};
|
|
1496
|
+
}
|
|
1497
|
+
async createGatePrivateAuth(params = {}) {
|
|
1498
|
+
const address = (params.address || "").toString();
|
|
1499
|
+
if (!validateUniversalAddress(address, params.chain)) {
|
|
1500
|
+
throw new ValidationError("Valid address is required");
|
|
1501
|
+
}
|
|
1502
|
+
return this._buildPrivateGateAuth({
|
|
1503
|
+
address,
|
|
1504
|
+
wallet: params.wallet,
|
|
1505
|
+
chain: params.chain,
|
|
1506
|
+
signatureMethod: params.signatureMethod
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1006
1509
|
/**
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1012
|
-
*
|
|
1510
|
+
* Create a verification proof.
|
|
1511
|
+
*
|
|
1512
|
+
* Supports two paths:
|
|
1513
|
+
* - **Auto:** Supply `verifier`, `content`, and/or `data` with an optional
|
|
1514
|
+
* `wallet` provider. The SDK performs signing in the client.
|
|
1515
|
+
* - **Manual:** Supply pre-signed `verifierIds`, `data`, `walletAddress`,
|
|
1516
|
+
* `signature`, and `signedTimestamp`.
|
|
1517
|
+
*
|
|
1013
1518
|
* @param {Object} params - Verification parameters
|
|
1519
|
+
* @param {string} [params.verifier] - Verifier ID (auto path, e.g. 'ownership-basic')
|
|
1520
|
+
* @param {string} [params.content] - Content to verify (auto path)
|
|
1521
|
+
* @param {Object} [params.data] - Structured verification data
|
|
1522
|
+
* @param {Object} [params.wallet] - Wallet provider (auto path)
|
|
1523
|
+
* @param {Object} [params.options] - Additional options
|
|
1014
1524
|
* @param {Array<string>} [params.verifierIds] - Array of verifier IDs (manual path)
|
|
1015
|
-
* @param {Object} [params.data] - Verification data object (manual path)
|
|
1016
1525
|
* @param {string} [params.walletAddress] - Wallet address that signed the request (manual path)
|
|
1017
1526
|
* @param {string} [params.signature] - EIP-191 signature (manual path)
|
|
1018
1527
|
* @param {number} [params.signedTimestamp] - Unix timestamp when signature was created (manual path)
|
|
1019
|
-
* @param {number} [params.chainId] -
|
|
1020
|
-
* @
|
|
1021
|
-
*
|
|
1022
|
-
* @
|
|
1023
|
-
*
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1528
|
+
* @param {number} [params.chainId] - EVM signing-context hint; when omitted, resolved to the NEUS protocol primary chain for signing
|
|
1529
|
+
* @returns {Promise<Object>} Verification result with proofId
|
|
1530
|
+
*
|
|
1531
|
+
* @example
|
|
1532
|
+
* // Auto path
|
|
1533
|
+
* const proof = await client.verify({
|
|
1534
|
+
* verifier: 'ownership-basic',
|
|
1535
|
+
* content: 'Hello World',
|
|
1536
|
+
* wallet: window.ethereum
|
|
1537
|
+
* });
|
|
1538
|
+
*
|
|
1026
1539
|
* @example
|
|
1540
|
+
* // Manual path
|
|
1027
1541
|
* const proof = await client.verify({
|
|
1028
1542
|
* verifierIds: ['ownership-basic'],
|
|
1029
|
-
* data: {
|
|
1030
|
-
* content: "My content",
|
|
1031
|
-
* owner: walletAddress, // or ownerAddress for nft-ownership/token-holding
|
|
1032
|
-
* reference: { type: 'other', id: 'my-unique-identifier' }
|
|
1033
|
-
* },
|
|
1543
|
+
* data: { content: "My content", owner: walletAddress },
|
|
1034
1544
|
* walletAddress: '0x...',
|
|
1035
1545
|
* signature: '0x...',
|
|
1036
1546
|
* signedTimestamp: Date.now(),
|
|
1037
1547
|
* options: { targetChains: [421614, 11155111] }
|
|
1038
1548
|
* });
|
|
1039
1549
|
*/
|
|
1040
|
-
/**
|
|
1041
|
-
* Create a verification proof
|
|
1042
|
-
*
|
|
1043
|
-
* @param {Object} params - Verification parameters
|
|
1044
|
-
* @param {string} [params.verifier] - Verifier ID (e.g., 'ownership-basic')
|
|
1045
|
-
* @param {string} [params.content] - Content to verify
|
|
1046
|
-
* @param {Object} [params.data] - Structured verification data
|
|
1047
|
-
* @param {Object} [params.wallet] - Wallet provider
|
|
1048
|
-
* @param {Object} [params.options] - Additional options
|
|
1049
|
-
* @returns {Promise<Object>} Verification result with qHash
|
|
1050
|
-
*
|
|
1051
|
-
* @example
|
|
1052
|
-
* // Simple ownership proof
|
|
1053
|
-
* const proof = await client.verify({
|
|
1054
|
-
* verifier: 'ownership-basic',
|
|
1055
|
-
* content: 'Hello World',
|
|
1056
|
-
* wallet: window.ethereum
|
|
1057
|
-
* });
|
|
1058
|
-
*/
|
|
1059
1550
|
async verify(params) {
|
|
1060
1551
|
if ((!params?.signature || !params?.walletAddress) && (params?.verifier || params?.content || params?.data)) {
|
|
1061
1552
|
const { content, verifier = "ownership-basic", data: data2 = null, wallet = null, options: options2 = {} } = params;
|
|
1062
1553
|
if (verifier === "ownership-basic" && !data2 && (!content || typeof content !== "string")) {
|
|
1063
1554
|
throw new ValidationError("content is required and must be a string (or use data param with owner + reference)");
|
|
1064
1555
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
"wallet-risk",
|
|
1075
|
-
// Wallet risk assessment (public)
|
|
1076
|
-
// AI & Agent verifiers (ERC-8004 aligned)
|
|
1077
|
-
"agent-identity",
|
|
1078
|
-
"agent-delegation",
|
|
1079
|
-
"ai-content-moderation"
|
|
1080
|
-
];
|
|
1556
|
+
let verifierCatalog = FALLBACK_PUBLIC_VERIFIER_CATALOG;
|
|
1557
|
+
try {
|
|
1558
|
+
const discovered = await this.getVerifierCatalog();
|
|
1559
|
+
if (discovered && discovered.metadata && Object.keys(discovered.metadata).length > 0) {
|
|
1560
|
+
verifierCatalog = discovered.metadata;
|
|
1561
|
+
}
|
|
1562
|
+
} catch {
|
|
1563
|
+
}
|
|
1564
|
+
const validVerifiers = Object.keys(verifierCatalog);
|
|
1081
1565
|
if (!validVerifiers.includes(verifier)) {
|
|
1082
1566
|
throw new ValidationError(`Invalid verifier '${verifier}'. Must be one of: ${validVerifiers.join(", ")}.`);
|
|
1083
1567
|
}
|
|
1568
|
+
if (verifierCatalog?.[verifier]?.supportsDirectApi === false) {
|
|
1569
|
+
const hostedCheckoutUrl = options2?.hostedCheckoutUrl || "https://neus.network/verify";
|
|
1570
|
+
throw new ValidationError(
|
|
1571
|
+
`${verifier} requires hosted interactive checkout. Use VerifyGate or redirect to ${hostedCheckoutUrl}.`
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1084
1574
|
const requiresDataParam = [
|
|
1085
1575
|
"ownership-dns-txt",
|
|
1086
1576
|
"wallet-link",
|
|
@@ -1098,8 +1588,12 @@ var init_client = __esm({
|
|
|
1098
1588
|
}
|
|
1099
1589
|
let walletAddress2, provider;
|
|
1100
1590
|
if (wallet) {
|
|
1101
|
-
walletAddress2 = wallet.address || wallet.selectedAddress;
|
|
1591
|
+
walletAddress2 = wallet.address || wallet.selectedAddress || wallet.walletAddress || (typeof wallet.getAddress === "function" ? await wallet.getAddress() : null);
|
|
1102
1592
|
provider = wallet.provider || wallet;
|
|
1593
|
+
if (!walletAddress2 && provider && typeof provider.request === "function") {
|
|
1594
|
+
const accounts = await provider.request({ method: "eth_accounts" });
|
|
1595
|
+
walletAddress2 = Array.isArray(accounts) ? accounts[0] : null;
|
|
1596
|
+
}
|
|
1103
1597
|
} else {
|
|
1104
1598
|
if (typeof window === "undefined" || !window.ethereum) {
|
|
1105
1599
|
throw new ConfigurationError("No Web3 wallet detected. Please install MetaMask or provide wallet parameter.");
|
|
@@ -1175,14 +1669,18 @@ var init_client = __esm({
|
|
|
1175
1669
|
if (!data2?.signature) {
|
|
1176
1670
|
throw new ValidationError("wallet-link requires signature in data parameter (signed by secondary wallet)");
|
|
1177
1671
|
}
|
|
1178
|
-
if (typeof data2?.
|
|
1179
|
-
throw new ValidationError("wallet-link requires
|
|
1672
|
+
if (typeof data2?.chain !== "string" || !/^[a-z0-9]+:[^\s]+$/.test(data2.chain)) {
|
|
1673
|
+
throw new ValidationError("wallet-link requires chain (namespace:reference) in data parameter");
|
|
1674
|
+
}
|
|
1675
|
+
if (typeof data2?.signatureMethod !== "string" || !data2.signatureMethod.trim()) {
|
|
1676
|
+
throw new ValidationError("wallet-link requires signatureMethod in data parameter");
|
|
1180
1677
|
}
|
|
1181
1678
|
verificationData = {
|
|
1182
1679
|
primaryWalletAddress: walletAddress2,
|
|
1183
1680
|
secondaryWalletAddress: data2.secondaryWalletAddress,
|
|
1184
1681
|
signature: data2.signature,
|
|
1185
|
-
|
|
1682
|
+
chain: data2.chain,
|
|
1683
|
+
signatureMethod: data2.signatureMethod,
|
|
1186
1684
|
signedTimestamp: data2?.signedTimestamp || Date.now()
|
|
1187
1685
|
};
|
|
1188
1686
|
} else if (verifier === "contract-ownership") {
|
|
@@ -1208,7 +1706,10 @@ var init_client = __esm({
|
|
|
1208
1706
|
...data2?.agentLabel && { agentLabel: data2.agentLabel },
|
|
1209
1707
|
...data2?.agentType && { agentType: data2.agentType },
|
|
1210
1708
|
...data2?.description && { description: data2.description },
|
|
1211
|
-
...data2?.capabilities && { capabilities: data2.capabilities }
|
|
1709
|
+
...data2?.capabilities && { capabilities: data2.capabilities },
|
|
1710
|
+
...data2?.instructions && { instructions: data2.instructions },
|
|
1711
|
+
...data2?.skills && { skills: data2.skills },
|
|
1712
|
+
...data2?.services && { services: data2.services }
|
|
1212
1713
|
};
|
|
1213
1714
|
} else if (verifier === "agent-delegation") {
|
|
1214
1715
|
if (!data2?.agentWallet) {
|
|
@@ -1221,7 +1722,11 @@ var init_client = __esm({
|
|
|
1221
1722
|
...data2?.scope && { scope: data2.scope },
|
|
1222
1723
|
...data2?.permissions && { permissions: data2.permissions },
|
|
1223
1724
|
...data2?.maxSpend && { maxSpend: data2.maxSpend },
|
|
1224
|
-
...data2?.
|
|
1725
|
+
...data2?.allowedPaymentTypes && { allowedPaymentTypes: data2.allowedPaymentTypes },
|
|
1726
|
+
...data2?.receiptDisclosure && { receiptDisclosure: data2.receiptDisclosure },
|
|
1727
|
+
...data2?.expiresAt && { expiresAt: data2.expiresAt },
|
|
1728
|
+
...data2?.instructions && { instructions: data2.instructions },
|
|
1729
|
+
...data2?.skills && { skills: data2.skills }
|
|
1225
1730
|
};
|
|
1226
1731
|
} else if (verifier === "ai-content-moderation") {
|
|
1227
1732
|
if (!data2?.content) {
|
|
@@ -1271,48 +1776,41 @@ var init_client = __esm({
|
|
|
1271
1776
|
signedTimestamp: signedTimestamp2,
|
|
1272
1777
|
data: verificationData,
|
|
1273
1778
|
verifierIds: verifierIds2,
|
|
1274
|
-
chainId:
|
|
1779
|
+
chainId: this._getHubChainId()
|
|
1275
1780
|
// Protocol-managed chain
|
|
1276
1781
|
});
|
|
1277
1782
|
let signature2;
|
|
1278
1783
|
try {
|
|
1279
|
-
const
|
|
1784
|
+
const toHexUtf82 = (s) => {
|
|
1280
1785
|
try {
|
|
1281
1786
|
const enc = new TextEncoder();
|
|
1282
1787
|
const bytes = enc.encode(s);
|
|
1283
1788
|
let hex = "0x";
|
|
1284
|
-
for (let i = 0; i < bytes.length; i++)
|
|
1285
|
-
hex += bytes[i].toString(16).padStart(2, "0");
|
|
1789
|
+
for (let i = 0; i < bytes.length; i++) hex += bytes[i].toString(16).padStart(2, "0");
|
|
1286
1790
|
return hex;
|
|
1287
1791
|
} catch {
|
|
1288
1792
|
let hex = "0x";
|
|
1289
|
-
for (let i = 0; i < s.length; i++)
|
|
1290
|
-
hex += s.charCodeAt(i).toString(16).padStart(2, "0");
|
|
1793
|
+
for (let i = 0; i < s.length; i++) hex += s.charCodeAt(i).toString(16).padStart(2, "0");
|
|
1291
1794
|
return hex;
|
|
1292
1795
|
}
|
|
1293
1796
|
};
|
|
1294
1797
|
const isFarcasterWallet = (() => {
|
|
1295
|
-
if (typeof window === "undefined")
|
|
1296
|
-
return false;
|
|
1798
|
+
if (typeof window === "undefined") return false;
|
|
1297
1799
|
try {
|
|
1298
1800
|
const w = window;
|
|
1299
1801
|
const fc = w.farcaster;
|
|
1300
|
-
if (!fc || !fc.context)
|
|
1301
|
-
return false;
|
|
1802
|
+
if (!fc || !fc.context) return false;
|
|
1302
1803
|
const fcProvider = fc.provider || fc.walletProvider || fc.context && fc.context.walletProvider;
|
|
1303
|
-
if (fcProvider === provider)
|
|
1304
|
-
|
|
1305
|
-
if (w.
|
|
1306
|
-
return true;
|
|
1307
|
-
if (w.ethereum === provider && fc && fc.context)
|
|
1308
|
-
return true;
|
|
1804
|
+
if (fcProvider === provider) return true;
|
|
1805
|
+
if (w.mini && w.mini.wallet === provider && fc && fc.context) return true;
|
|
1806
|
+
if (w.ethereum === provider && fc && fc.context) return true;
|
|
1309
1807
|
} catch {
|
|
1310
1808
|
}
|
|
1311
1809
|
return false;
|
|
1312
1810
|
})();
|
|
1313
1811
|
if (isFarcasterWallet) {
|
|
1314
1812
|
try {
|
|
1315
|
-
const hexMsg =
|
|
1813
|
+
const hexMsg = toHexUtf82(message);
|
|
1316
1814
|
signature2 = await provider.request({ method: "personal_sign", params: [hexMsg, walletAddress2] });
|
|
1317
1815
|
} catch (e) {
|
|
1318
1816
|
}
|
|
@@ -1324,7 +1822,8 @@ var init_client = __esm({
|
|
|
1324
1822
|
const msg = String(e && (e.message || e.reason) || e || "").toLowerCase();
|
|
1325
1823
|
const errCode = e && (e.code || e.error && e.error.code) || null;
|
|
1326
1824
|
const needsHex = /byte|bytes|invalid byte sequence|encoding|non-hex/i.test(msg);
|
|
1327
|
-
const
|
|
1825
|
+
const unsupportedRe = /method.*not.*supported|unsupported|not implemented|method not found|unknown method|does not support/i;
|
|
1826
|
+
const methodUnsupported = unsupportedRe.test(msg) || errCode === -32601 || errCode === 4200 || msg.includes("personal_sign") && msg.includes("not") || msg.includes("request method") && msg.includes("not supported");
|
|
1328
1827
|
if (methodUnsupported) {
|
|
1329
1828
|
this._log("personal_sign not supported; attempting eth_sign fallback");
|
|
1330
1829
|
try {
|
|
@@ -1333,35 +1832,30 @@ var init_client = __esm({
|
|
|
1333
1832
|
const prefix = `Ethereum Signed Message:
|
|
1334
1833
|
${bytes.length}`;
|
|
1335
1834
|
const full = new Uint8Array(prefix.length + bytes.length);
|
|
1336
|
-
for (let i = 0; i < prefix.length; i++)
|
|
1337
|
-
full[i] = prefix.charCodeAt(i);
|
|
1835
|
+
for (let i = 0; i < prefix.length; i++) full[i] = prefix.charCodeAt(i);
|
|
1338
1836
|
full.set(bytes, prefix.length);
|
|
1339
1837
|
let payloadHex = "0x";
|
|
1340
|
-
for (let i = 0; i < full.length; i++)
|
|
1341
|
-
payloadHex += full[i].toString(16).padStart(2, "0");
|
|
1838
|
+
for (let i = 0; i < full.length; i++) payloadHex += full[i].toString(16).padStart(2, "0");
|
|
1342
1839
|
try {
|
|
1343
|
-
if (typeof window !== "undefined")
|
|
1344
|
-
window.__NEUS_ALLOW_ETH_SIGN__ = true;
|
|
1840
|
+
if (typeof window !== "undefined") window.__NEUS_ALLOW_ETH_SIGN__ = true;
|
|
1345
1841
|
} catch {
|
|
1346
1842
|
}
|
|
1347
1843
|
signature2 = await provider.request({ method: "eth_sign", params: [walletAddress2, payloadHex], neusAllowEthSign: true });
|
|
1348
1844
|
try {
|
|
1349
|
-
if (typeof window !== "undefined")
|
|
1350
|
-
delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1845
|
+
if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1351
1846
|
} catch {
|
|
1352
1847
|
}
|
|
1353
1848
|
} catch (fallbackErr) {
|
|
1354
1849
|
this._log("eth_sign fallback failed", { message: fallbackErr?.message || String(fallbackErr) });
|
|
1355
1850
|
try {
|
|
1356
|
-
if (typeof window !== "undefined")
|
|
1357
|
-
delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1851
|
+
if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1358
1852
|
} catch {
|
|
1359
1853
|
}
|
|
1360
1854
|
throw e;
|
|
1361
1855
|
}
|
|
1362
1856
|
} else if (needsHex) {
|
|
1363
1857
|
this._log("Retrying personal_sign with hex-encoded message");
|
|
1364
|
-
const hexMsg =
|
|
1858
|
+
const hexMsg = toHexUtf82(message);
|
|
1365
1859
|
signature2 = await provider.request({ method: "personal_sign", params: [hexMsg, walletAddress2] });
|
|
1366
1860
|
} else {
|
|
1367
1861
|
throw e;
|
|
@@ -1396,8 +1890,7 @@ ${bytes.length}`;
|
|
|
1396
1890
|
} = params;
|
|
1397
1891
|
const resolvedChainId = chainId || (chain ? null : NEUS_CONSTANTS.HUB_CHAIN_ID);
|
|
1398
1892
|
const normalizeVerifierId = (id) => {
|
|
1399
|
-
if (typeof id !== "string")
|
|
1400
|
-
return id;
|
|
1893
|
+
if (typeof id !== "string") return id;
|
|
1401
1894
|
const match = id.match(/^(.*)@\d+$/);
|
|
1402
1895
|
return match ? match[1] : id;
|
|
1403
1896
|
};
|
|
@@ -1432,10 +1925,9 @@ ${bytes.length}`;
|
|
|
1432
1925
|
// Privacy and storage options (defaults)
|
|
1433
1926
|
privacyLevel: options?.privacyLevel || "private",
|
|
1434
1927
|
publicDisplay: options?.publicDisplay || false,
|
|
1435
|
-
storeOriginalContent: options?.storeOriginalContent
|
|
1928
|
+
storeOriginalContent: typeof options?.storeOriginalContent === "boolean" ? options.storeOriginalContent : true
|
|
1436
1929
|
};
|
|
1437
|
-
if (typeof options?.enableIpfs === "boolean")
|
|
1438
|
-
optionsPayload.enableIpfs = options.enableIpfs;
|
|
1930
|
+
if (typeof options?.enableIpfs === "boolean") optionsPayload.enableIpfs = options.enableIpfs;
|
|
1439
1931
|
const requestData = {
|
|
1440
1932
|
verifierIds: normalizedVerifierIds,
|
|
1441
1933
|
data,
|
|
@@ -1453,96 +1945,94 @@ ${bytes.length}`;
|
|
|
1453
1945
|
}
|
|
1454
1946
|
return this._formatResponse(response);
|
|
1455
1947
|
}
|
|
1456
|
-
// ============================================================================
|
|
1457
|
-
// STATUS AND UTILITY METHODS
|
|
1458
|
-
// ============================================================================
|
|
1459
1948
|
/**
|
|
1460
|
-
* Get
|
|
1949
|
+
* Get proof record by proof receipt id.
|
|
1461
1950
|
*
|
|
1462
|
-
* @param {string}
|
|
1463
|
-
* @returns {Promise<Object>}
|
|
1951
|
+
* @param {string} proofId - Proof receipt ID (0x + 64 hex).
|
|
1952
|
+
* @returns {Promise<Object>} Proof record and verification state
|
|
1464
1953
|
*
|
|
1465
1954
|
* @example
|
|
1466
|
-
* const result = await client.
|
|
1955
|
+
* const result = await client.getProof('0x...');
|
|
1467
1956
|
* console.log('Status:', result.status);
|
|
1468
1957
|
*/
|
|
1469
|
-
async
|
|
1470
|
-
if (!
|
|
1471
|
-
throw new ValidationError("
|
|
1958
|
+
async getProof(proofId) {
|
|
1959
|
+
if (!proofId || typeof proofId !== "string") {
|
|
1960
|
+
throw new ValidationError("proofId is required");
|
|
1472
1961
|
}
|
|
1473
|
-
const response = await this._makeRequest("GET", `/api/v1/
|
|
1962
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`);
|
|
1474
1963
|
if (!response.success) {
|
|
1475
|
-
throw new ApiError(`Failed to get
|
|
1964
|
+
throw new ApiError(`Failed to get proof: ${response.error?.message || "Unknown error"}`, response.error);
|
|
1476
1965
|
}
|
|
1477
1966
|
return this._formatResponse(response);
|
|
1478
1967
|
}
|
|
1479
1968
|
/**
|
|
1480
|
-
* Get private proof
|
|
1969
|
+
* Get private proof record with wallet signature
|
|
1481
1970
|
*
|
|
1482
|
-
* @param {string}
|
|
1971
|
+
* @param {string} proofId - Proof receipt ID.
|
|
1483
1972
|
* @param {Object} wallet - Wallet provider (window.ethereum or ethers Wallet)
|
|
1484
|
-
* @returns {Promise<Object>} Private
|
|
1973
|
+
* @returns {Promise<Object>} Private proof record and verification state
|
|
1485
1974
|
*
|
|
1486
1975
|
* @example
|
|
1487
|
-
*
|
|
1488
|
-
* const privateData = await client.getPrivateStatus(qHash, window.ethereum);
|
|
1976
|
+
* const privateData = await client.getPrivateProof(proofId, window.ethereum);
|
|
1489
1977
|
*/
|
|
1490
|
-
async
|
|
1491
|
-
if (!
|
|
1492
|
-
throw new ValidationError("
|
|
1978
|
+
async getPrivateProof(proofId, wallet = null) {
|
|
1979
|
+
if (!proofId || typeof proofId !== "string") {
|
|
1980
|
+
throw new ValidationError("proofId is required");
|
|
1493
1981
|
}
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1982
|
+
const isPreSignedAuth = wallet && typeof wallet === "object" && typeof wallet.walletAddress === "string" && typeof wallet.signature === "string" && typeof wallet.signedTimestamp === "number";
|
|
1983
|
+
if (isPreSignedAuth) {
|
|
1984
|
+
const auth = wallet;
|
|
1985
|
+
const headers = {
|
|
1986
|
+
"x-wallet-address": String(auth.walletAddress),
|
|
1987
|
+
"x-signature": String(auth.signature),
|
|
1988
|
+
"x-signed-timestamp": String(auth.signedTimestamp),
|
|
1989
|
+
...typeof auth.chain === "string" && auth.chain.trim() ? { "x-chain": auth.chain.trim() } : {},
|
|
1990
|
+
...typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? { "x-signature-method": auth.signatureMethod.trim() } : {}
|
|
1991
|
+
};
|
|
1992
|
+
const response2 = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, headers);
|
|
1993
|
+
if (!response2.success) {
|
|
1994
|
+
throw new ApiError(
|
|
1995
|
+
`Failed to access private proof: ${response2.error?.message || "Unauthorized"}`,
|
|
1996
|
+
response2.error
|
|
1997
|
+
);
|
|
1497
1998
|
}
|
|
1498
|
-
|
|
1999
|
+
return this._formatResponse(response2);
|
|
1499
2000
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
} else if (wallet.selectedAddress || wallet.request) {
|
|
1505
|
-
provider = wallet;
|
|
1506
|
-
if (wallet.selectedAddress) {
|
|
1507
|
-
walletAddress = wallet.selectedAddress;
|
|
1508
|
-
} else {
|
|
1509
|
-
const accounts = await provider.request({ method: "eth_accounts" });
|
|
1510
|
-
if (!accounts || accounts.length === 0) {
|
|
1511
|
-
throw new ConfigurationError("No wallet accounts available");
|
|
1512
|
-
}
|
|
1513
|
-
walletAddress = accounts[0];
|
|
1514
|
-
}
|
|
1515
|
-
} else {
|
|
1516
|
-
throw new ConfigurationError("Invalid wallet provider");
|
|
2001
|
+
const providerWallet = wallet || this._getDefaultBrowserWallet();
|
|
2002
|
+
const { signerWalletAddress: walletAddress, provider } = await this._resolveWalletSigner(providerWallet);
|
|
2003
|
+
if (!walletAddress || typeof walletAddress !== "string") {
|
|
2004
|
+
throw new ConfigurationError("No wallet accounts available");
|
|
1517
2005
|
}
|
|
2006
|
+
const signerIsEvm = EVM_ADDRESS_RE.test(this._normalizeIdentity(walletAddress));
|
|
2007
|
+
const chain = this._inferChainForAddress(walletAddress);
|
|
2008
|
+
const signatureMethod = signerIsEvm ? "eip191" : "ed25519";
|
|
1518
2009
|
const signedTimestamp = Date.now();
|
|
1519
2010
|
const message = constructVerificationMessage({
|
|
1520
2011
|
walletAddress,
|
|
1521
2012
|
signedTimestamp,
|
|
1522
|
-
data: { action: "access_private_proof", qHash },
|
|
2013
|
+
data: { action: "access_private_proof", qHash: proofId },
|
|
1523
2014
|
verifierIds: ["ownership-basic"],
|
|
1524
|
-
chainId:
|
|
2015
|
+
...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
|
|
1525
2016
|
});
|
|
1526
2017
|
let signature;
|
|
1527
2018
|
try {
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
});
|
|
1535
|
-
}
|
|
2019
|
+
signature = await signMessage({
|
|
2020
|
+
provider,
|
|
2021
|
+
message,
|
|
2022
|
+
walletAddress,
|
|
2023
|
+
...signerIsEvm ? {} : { chain }
|
|
2024
|
+
});
|
|
1536
2025
|
} catch (error) {
|
|
1537
2026
|
if (error.code === 4001) {
|
|
1538
2027
|
throw new ValidationError("User rejected signature request");
|
|
1539
2028
|
}
|
|
1540
2029
|
throw new ValidationError(`Failed to sign message: ${error.message}`);
|
|
1541
2030
|
}
|
|
1542
|
-
const response = await this._makeRequest("GET", `/api/v1/
|
|
2031
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, {
|
|
1543
2032
|
"x-wallet-address": walletAddress,
|
|
1544
2033
|
"x-signature": signature,
|
|
1545
|
-
"x-signed-timestamp": signedTimestamp.toString()
|
|
2034
|
+
"x-signed-timestamp": signedTimestamp.toString(),
|
|
2035
|
+
...signerIsEvm ? {} : { "x-chain": chain, "x-signature-method": signatureMethod }
|
|
1546
2036
|
});
|
|
1547
2037
|
if (!response.success) {
|
|
1548
2038
|
throw new ApiError(
|
|
@@ -1571,27 +2061,39 @@ ${bytes.length}`;
|
|
|
1571
2061
|
* @returns {Promise<string[]>} Array of verifier IDs
|
|
1572
2062
|
*/
|
|
1573
2063
|
async getVerifiers() {
|
|
2064
|
+
const catalog = await this.getVerifierCatalog();
|
|
2065
|
+
return Array.isArray(catalog?.data) ? catalog.data : [];
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Get the public verifier catalog with per-verifier capabilities.
|
|
2069
|
+
* @returns {Promise<{data: string[], metadata: Record<string, { supportsDirectApi?: boolean }>, meta?: object}>}
|
|
2070
|
+
*/
|
|
2071
|
+
async getVerifierCatalog() {
|
|
1574
2072
|
const response = await this._makeRequest("GET", "/api/v1/verification/verifiers");
|
|
1575
2073
|
if (!response.success) {
|
|
1576
2074
|
throw new ApiError(`Failed to get verifiers: ${response.error?.message || "Unknown error"}`, response.error);
|
|
1577
2075
|
}
|
|
1578
|
-
return
|
|
2076
|
+
return {
|
|
2077
|
+
data: Array.isArray(response.data) ? response.data : [],
|
|
2078
|
+
metadata: response.metadata && typeof response.metadata === "object" && !Array.isArray(response.metadata) ? response.metadata : {},
|
|
2079
|
+
meta: response.meta && typeof response.meta === "object" && !Array.isArray(response.meta) ? response.meta : {}
|
|
2080
|
+
};
|
|
1579
2081
|
}
|
|
1580
2082
|
/**
|
|
1581
2083
|
* POLL PROOF STATUS - Wait for verification completion
|
|
1582
|
-
*
|
|
2084
|
+
*
|
|
1583
2085
|
* Polls the verification status until it reaches a terminal state (completed or failed).
|
|
1584
2086
|
* Useful for providing real-time feedback to users during verification.
|
|
1585
|
-
*
|
|
1586
|
-
* @param {string}
|
|
2087
|
+
*
|
|
2088
|
+
* @param {string} proofId - Proof ID to poll.
|
|
1587
2089
|
* @param {Object} [options] - Polling options
|
|
1588
2090
|
* @param {number} [options.interval=5000] - Polling interval in ms
|
|
1589
2091
|
* @param {number} [options.timeout=120000] - Total timeout in ms
|
|
1590
2092
|
* @param {Function} [options.onProgress] - Progress callback function
|
|
1591
2093
|
* @returns {Promise<Object>} Final verification status
|
|
1592
|
-
*
|
|
2094
|
+
*
|
|
1593
2095
|
* @example
|
|
1594
|
-
* const finalStatus = await client.pollProofStatus(
|
|
2096
|
+
* const finalStatus = await client.pollProofStatus(proofId, {
|
|
1595
2097
|
* interval: 3000,
|
|
1596
2098
|
* timeout: 60000,
|
|
1597
2099
|
* onProgress: (status) => {
|
|
@@ -1602,20 +2104,20 @@ ${bytes.length}`;
|
|
|
1602
2104
|
* }
|
|
1603
2105
|
* });
|
|
1604
2106
|
*/
|
|
1605
|
-
async pollProofStatus(
|
|
2107
|
+
async pollProofStatus(proofId, options = {}) {
|
|
1606
2108
|
const {
|
|
1607
2109
|
interval = 5e3,
|
|
1608
2110
|
timeout = 12e4,
|
|
1609
2111
|
onProgress
|
|
1610
2112
|
} = options;
|
|
1611
|
-
if (!
|
|
1612
|
-
throw new ValidationError("
|
|
2113
|
+
if (!proofId || typeof proofId !== "string") {
|
|
2114
|
+
throw new ValidationError("proofId is required");
|
|
1613
2115
|
}
|
|
1614
2116
|
const startTime = Date.now();
|
|
1615
2117
|
let consecutiveRateLimits = 0;
|
|
1616
2118
|
while (Date.now() - startTime < timeout) {
|
|
1617
2119
|
try {
|
|
1618
|
-
const status = await this.
|
|
2120
|
+
const status = await this.getProof(proofId);
|
|
1619
2121
|
consecutiveRateLimits = 0;
|
|
1620
2122
|
if (onProgress && typeof onProgress === "function") {
|
|
1621
2123
|
onProgress(status.data || status);
|
|
@@ -1648,7 +2150,7 @@ ${bytes.length}`;
|
|
|
1648
2150
|
}
|
|
1649
2151
|
/**
|
|
1650
2152
|
* DETECT CHAIN ID - Get current wallet chain
|
|
1651
|
-
*
|
|
2153
|
+
*
|
|
1652
2154
|
* @returns {Promise<number>} Current chain ID
|
|
1653
2155
|
*/
|
|
1654
2156
|
async detectChainId() {
|
|
@@ -1663,70 +2165,49 @@ ${bytes.length}`;
|
|
|
1663
2165
|
}
|
|
1664
2166
|
}
|
|
1665
2167
|
/** Revoke your own proof (owner-signed) */
|
|
1666
|
-
async revokeOwnProof(
|
|
1667
|
-
if (!
|
|
1668
|
-
throw new ValidationError("
|
|
2168
|
+
async revokeOwnProof(proofId, wallet) {
|
|
2169
|
+
if (!proofId || typeof proofId !== "string") {
|
|
2170
|
+
throw new ValidationError("proofId is required");
|
|
2171
|
+
}
|
|
2172
|
+
const providerWallet = wallet || this._getDefaultBrowserWallet();
|
|
2173
|
+
const { signerWalletAddress: address, provider } = await this._resolveWalletSigner(providerWallet);
|
|
2174
|
+
if (!address || typeof address !== "string") {
|
|
2175
|
+
throw new ConfigurationError("No wallet accounts available");
|
|
1669
2176
|
}
|
|
1670
|
-
const
|
|
2177
|
+
const signerIsEvm = EVM_ADDRESS_RE.test(this._normalizeIdentity(address));
|
|
2178
|
+
const chain = this._inferChainForAddress(address);
|
|
2179
|
+
const signatureMethod = signerIsEvm ? "eip191" : "ed25519";
|
|
1671
2180
|
const signedTimestamp = Date.now();
|
|
1672
|
-
const hubChainId = NEUS_CONSTANTS.HUB_CHAIN_ID;
|
|
1673
2181
|
const message = constructVerificationMessage({
|
|
1674
2182
|
walletAddress: address,
|
|
1675
2183
|
signedTimestamp,
|
|
1676
|
-
data: { action: "revoke_proof", qHash },
|
|
2184
|
+
data: { action: "revoke_proof", qHash: proofId },
|
|
1677
2185
|
verifierIds: ["ownership-basic"],
|
|
1678
|
-
chainId:
|
|
2186
|
+
...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
|
|
1679
2187
|
});
|
|
1680
2188
|
let signature;
|
|
1681
2189
|
try {
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
return hex;
|
|
1689
|
-
};
|
|
1690
|
-
const isFarcasterWallet = (() => {
|
|
1691
|
-
if (typeof window === "undefined")
|
|
1692
|
-
return false;
|
|
1693
|
-
try {
|
|
1694
|
-
const w = window;
|
|
1695
|
-
const fc = w.farcaster;
|
|
1696
|
-
if (!fc || !fc.context)
|
|
1697
|
-
return false;
|
|
1698
|
-
const fcProvider = fc.provider || fc.walletProvider || fc.context && fc.context.walletProvider;
|
|
1699
|
-
if (fcProvider === w.ethereum)
|
|
1700
|
-
return true;
|
|
1701
|
-
if (w.mini && w.mini.wallet === w.ethereum && fc && fc.context)
|
|
1702
|
-
return true;
|
|
1703
|
-
if (w.ethereum && fc && fc.context)
|
|
1704
|
-
return true;
|
|
1705
|
-
} catch {
|
|
1706
|
-
}
|
|
1707
|
-
return false;
|
|
1708
|
-
})();
|
|
1709
|
-
if (isFarcasterWallet) {
|
|
1710
|
-
try {
|
|
1711
|
-
const hexMsg = toHexUtf8(message);
|
|
1712
|
-
signature = await window.ethereum.request({ method: "personal_sign", params: [hexMsg, address] });
|
|
1713
|
-
} catch {
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
if (!signature) {
|
|
1717
|
-
signature = await window.ethereum.request({ method: "personal_sign", params: [message, address] });
|
|
1718
|
-
}
|
|
2190
|
+
signature = await signMessage({
|
|
2191
|
+
provider,
|
|
2192
|
+
message,
|
|
2193
|
+
walletAddress: address,
|
|
2194
|
+
...signerIsEvm ? {} : { chain }
|
|
2195
|
+
});
|
|
1719
2196
|
} catch (error) {
|
|
1720
2197
|
if (error.code === 4001) {
|
|
1721
2198
|
throw new ValidationError("User rejected revocation signature");
|
|
1722
2199
|
}
|
|
1723
2200
|
throw new ValidationError(`Failed to sign revocation: ${error.message}`);
|
|
1724
2201
|
}
|
|
1725
|
-
const res = await fetch(`${this.config.apiUrl}/api/v1/proofs
|
|
2202
|
+
const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/revoke-self/${proofId}`, {
|
|
1726
2203
|
method: "POST",
|
|
1727
|
-
// SECURITY: Do not put proof signatures into Authorization headers.
|
|
1728
2204
|
headers: { "Content-Type": "application/json" },
|
|
1729
|
-
body: JSON.stringify({
|
|
2205
|
+
body: JSON.stringify({
|
|
2206
|
+
walletAddress: address,
|
|
2207
|
+
signature,
|
|
2208
|
+
signedTimestamp,
|
|
2209
|
+
...signerIsEvm ? {} : { chain, signatureMethod }
|
|
2210
|
+
})
|
|
1730
2211
|
});
|
|
1731
2212
|
const json = await res.json();
|
|
1732
2213
|
if (!json.success) {
|
|
@@ -1734,18 +2215,16 @@ ${bytes.length}`;
|
|
|
1734
2215
|
}
|
|
1735
2216
|
return true;
|
|
1736
2217
|
}
|
|
1737
|
-
// ============================================================================
|
|
1738
|
-
// PROOFS & GATING METHODS
|
|
1739
|
-
// ============================================================================
|
|
1740
2218
|
/**
|
|
1741
2219
|
* GET PROOFS BY WALLET - Fetch proofs for a wallet address
|
|
1742
|
-
*
|
|
1743
|
-
* @param {string} walletAddress - Wallet
|
|
2220
|
+
*
|
|
2221
|
+
* @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
|
|
1744
2222
|
* @param {Object} [options] - Filter options
|
|
1745
2223
|
* @param {number} [options.limit] - Max results (default: 50; higher limits require owner access)
|
|
1746
2224
|
* @param {number} [options.offset] - Pagination offset (default: 0)
|
|
2225
|
+
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
1747
2226
|
* @returns {Promise<Object>} Proofs result
|
|
1748
|
-
*
|
|
2227
|
+
*
|
|
1749
2228
|
* @example
|
|
1750
2229
|
* const result = await client.getProofsByWallet('0x...', {
|
|
1751
2230
|
* limit: 50,
|
|
@@ -1759,14 +2238,13 @@ ${bytes.length}`;
|
|
|
1759
2238
|
const id = walletAddress.trim();
|
|
1760
2239
|
const pathId = /^0x[a-fA-F0-9]{40}$/i.test(id) ? id.toLowerCase() : id;
|
|
1761
2240
|
const qs = [];
|
|
1762
|
-
if (options.limit)
|
|
1763
|
-
|
|
1764
|
-
if (options.
|
|
1765
|
-
qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
2241
|
+
if (options.limit) qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
|
|
2242
|
+
if (options.offset) qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
2243
|
+
if (options.qHash) qs.push(`qHash=${encodeURIComponent(options.qHash.toLowerCase())}`);
|
|
1766
2244
|
const query = qs.length ? `?${qs.join("&")}` : "";
|
|
1767
2245
|
const response = await this._makeRequest(
|
|
1768
2246
|
"GET",
|
|
1769
|
-
`/api/v1/proofs/
|
|
2247
|
+
`/api/v1/proofs/by-wallet/${encodeURIComponent(pathId)}${query}`
|
|
1770
2248
|
);
|
|
1771
2249
|
if (!response.success) {
|
|
1772
2250
|
throw new ApiError(`Failed to get proofs: ${response.error?.message || "Unknown error"}`, response.error);
|
|
@@ -1785,10 +2263,11 @@ ${bytes.length}`;
|
|
|
1785
2263
|
*
|
|
1786
2264
|
* Signs an owner-access intent and requests private proofs via signature headers.
|
|
1787
2265
|
*
|
|
1788
|
-
* @param {string} walletAddress - Wallet
|
|
2266
|
+
* @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
|
|
1789
2267
|
* @param {Object} [options]
|
|
1790
2268
|
* @param {number} [options.limit] - Max results (server enforces caps)
|
|
1791
2269
|
* @param {number} [options.offset] - Pagination offset
|
|
2270
|
+
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
1792
2271
|
* @param {Object} [wallet] - Optional injected wallet/provider (MetaMask/ethers Wallet)
|
|
1793
2272
|
*/
|
|
1794
2273
|
async getPrivateProofsByWallet(walletAddress, options = {}, wallet = null) {
|
|
@@ -1797,48 +2276,41 @@ ${bytes.length}`;
|
|
|
1797
2276
|
}
|
|
1798
2277
|
const id = walletAddress.trim();
|
|
1799
2278
|
const pathId = /^0x[a-fA-F0-9]{40}$/i.test(id) ? id.toLowerCase() : id;
|
|
2279
|
+
const requestedIdentity = this._normalizeIdentity(id);
|
|
1800
2280
|
if (!wallet) {
|
|
1801
|
-
|
|
2281
|
+
const defaultWallet = this._getDefaultBrowserWallet();
|
|
2282
|
+
if (!defaultWallet) {
|
|
1802
2283
|
throw new ConfigurationError("No wallet provider available");
|
|
1803
2284
|
}
|
|
1804
|
-
wallet =
|
|
2285
|
+
wallet = defaultWallet;
|
|
1805
2286
|
}
|
|
1806
|
-
|
|
1807
|
-
if (
|
|
1808
|
-
|
|
1809
|
-
provider = wallet;
|
|
1810
|
-
} else if (wallet.selectedAddress || wallet.request) {
|
|
1811
|
-
provider = wallet;
|
|
1812
|
-
if (wallet.selectedAddress) {
|
|
1813
|
-
signerWalletAddress = wallet.selectedAddress;
|
|
1814
|
-
} else {
|
|
1815
|
-
const accounts = await provider.request({ method: "eth_accounts" });
|
|
1816
|
-
if (!accounts || accounts.length === 0) {
|
|
1817
|
-
throw new ConfigurationError("No wallet accounts available");
|
|
1818
|
-
}
|
|
1819
|
-
signerWalletAddress = accounts[0];
|
|
1820
|
-
}
|
|
1821
|
-
} else {
|
|
1822
|
-
throw new ConfigurationError("Invalid wallet provider");
|
|
2287
|
+
const { signerWalletAddress, provider } = await this._resolveWalletSigner(wallet);
|
|
2288
|
+
if (!signerWalletAddress || typeof signerWalletAddress !== "string") {
|
|
2289
|
+
throw new ConfigurationError("No wallet accounts available");
|
|
1823
2290
|
}
|
|
2291
|
+
const normalizedSigner = this._normalizeIdentity(signerWalletAddress);
|
|
2292
|
+
if (!normalizedSigner || normalizedSigner !== requestedIdentity) {
|
|
2293
|
+
throw new ValidationError("wallet must match walletAddress for private proof access");
|
|
2294
|
+
}
|
|
2295
|
+
const signerIsEvm = EVM_ADDRESS_RE.test(normalizedSigner);
|
|
2296
|
+
const chain = this._inferChainForAddress(normalizedSigner, options?.chain);
|
|
2297
|
+
const signatureMethod = typeof options?.signatureMethod === "string" && options.signatureMethod.trim() ? options.signatureMethod.trim() : signerIsEvm ? "eip191" : "ed25519";
|
|
1824
2298
|
const signedTimestamp = Date.now();
|
|
1825
2299
|
const message = constructVerificationMessage({
|
|
1826
2300
|
walletAddress: signerWalletAddress,
|
|
1827
2301
|
signedTimestamp,
|
|
1828
|
-
data: { action: "access_private_proofs_by_wallet", walletAddress:
|
|
2302
|
+
data: { action: "access_private_proofs_by_wallet", walletAddress: normalizedSigner },
|
|
1829
2303
|
verifierIds: ["ownership-basic"],
|
|
1830
|
-
chainId:
|
|
2304
|
+
...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
|
|
1831
2305
|
});
|
|
1832
2306
|
let signature;
|
|
1833
2307
|
try {
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
});
|
|
1841
|
-
}
|
|
2308
|
+
signature = await signMessage({
|
|
2309
|
+
provider,
|
|
2310
|
+
message,
|
|
2311
|
+
walletAddress: signerWalletAddress,
|
|
2312
|
+
...signerIsEvm ? {} : { chain }
|
|
2313
|
+
});
|
|
1842
2314
|
} catch (error) {
|
|
1843
2315
|
if (error.code === 4001) {
|
|
1844
2316
|
throw new ValidationError("User rejected signature request");
|
|
@@ -1846,15 +2318,15 @@ ${bytes.length}`;
|
|
|
1846
2318
|
throw new ValidationError(`Failed to sign message: ${error.message}`);
|
|
1847
2319
|
}
|
|
1848
2320
|
const qs = [];
|
|
1849
|
-
if (options.limit)
|
|
1850
|
-
|
|
1851
|
-
if (options.
|
|
1852
|
-
qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
2321
|
+
if (options.limit) qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
|
|
2322
|
+
if (options.offset) qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
2323
|
+
if (options.qHash) qs.push(`qHash=${encodeURIComponent(options.qHash.toLowerCase())}`);
|
|
1853
2324
|
const query = qs.length ? `?${qs.join("&")}` : "";
|
|
1854
|
-
const response = await this._makeRequest("GET", `/api/v1/proofs/
|
|
2325
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/by-wallet/${encodeURIComponent(pathId)}${query}`, null, {
|
|
1855
2326
|
"x-wallet-address": signerWalletAddress,
|
|
1856
2327
|
"x-signature": signature,
|
|
1857
|
-
"x-signed-timestamp": signedTimestamp.toString()
|
|
2328
|
+
"x-signed-timestamp": signedTimestamp.toString(),
|
|
2329
|
+
...signerIsEvm ? {} : { "x-chain": chain, "x-signature-method": signatureMethod }
|
|
1858
2330
|
});
|
|
1859
2331
|
if (!response.success) {
|
|
1860
2332
|
throw new ApiError(`Failed to get proofs: ${response.error?.message || "Unauthorized"}`, response.error);
|
|
@@ -1869,51 +2341,52 @@ ${bytes.length}`;
|
|
|
1869
2341
|
};
|
|
1870
2342
|
}
|
|
1871
2343
|
/**
|
|
1872
|
-
*
|
|
2344
|
+
* Gate check (HTTP API) — minimal eligibility response.
|
|
2345
|
+
*
|
|
2346
|
+
* Calls the gate endpoint and returns a **minimal** yes/no response.
|
|
2347
|
+
* By default this checks **public + unlisted** proofs.
|
|
1873
2348
|
*
|
|
1874
|
-
*
|
|
1875
|
-
*
|
|
2349
|
+
* When `includePrivate=true`, this can perform owner-signed private checks
|
|
2350
|
+
* (no full proof payloads returned) by providing a wallet/provider.
|
|
1876
2351
|
*
|
|
1877
|
-
* Prefer this over `checkGate()`
|
|
1878
|
-
*
|
|
2352
|
+
* Prefer this over `checkGate()` when you need the smallest, most stable
|
|
2353
|
+
* response shape and do not need full proof payloads.
|
|
1879
2354
|
*
|
|
1880
2355
|
* @param {Object} params - Gate check query params
|
|
1881
|
-
* @param {string} params.address - Wallet
|
|
2356
|
+
* @param {string} params.address - Wallet identity to check (EVM/Solana/DID)
|
|
1882
2357
|
* @param {Array<string>|string} [params.verifierIds] - Verifier IDs to match (array or comma-separated)
|
|
1883
2358
|
* @param {boolean} [params.requireAll] - Require all verifierIds on a single proof
|
|
1884
2359
|
* @param {number} [params.minCount] - Minimum number of matching proofs
|
|
1885
2360
|
* @param {number} [params.sinceDays] - Optional time window in days
|
|
1886
2361
|
* @param {number} [params.since] - Optional unix timestamp in ms (lower bound)
|
|
1887
2362
|
* @param {number} [params.limit] - Max rows to scan (server may clamp)
|
|
2363
|
+
* @param {boolean} [params.includePrivate] - Include private proofs for owner-authenticated requests
|
|
2364
|
+
* @param {boolean} [params.includeQHashes] - Include matched qHashes in response (minimal IDs only)
|
|
2365
|
+
* @param {Object} [params.wallet] - Optional wallet/provider used to sign includePrivate owner checks
|
|
1888
2366
|
* @returns {Promise<Object>} API response ({ success, data })
|
|
1889
2367
|
*/
|
|
1890
2368
|
async gateCheck(params = {}) {
|
|
1891
2369
|
const address = (params.address || "").toString();
|
|
1892
|
-
if (!address
|
|
2370
|
+
if (!validateUniversalAddress(address, params.chain)) {
|
|
1893
2371
|
throw new ValidationError("Valid address is required");
|
|
1894
2372
|
}
|
|
1895
2373
|
const qs = new URLSearchParams();
|
|
1896
2374
|
qs.set("address", address);
|
|
1897
2375
|
const setIfPresent = (key, value) => {
|
|
1898
|
-
if (value === void 0 || value === null)
|
|
1899
|
-
return;
|
|
2376
|
+
if (value === void 0 || value === null) return;
|
|
1900
2377
|
const str = typeof value === "string" ? value : String(value);
|
|
1901
|
-
if (str.length === 0)
|
|
1902
|
-
return;
|
|
2378
|
+
if (str.length === 0) return;
|
|
1903
2379
|
qs.set(key, str);
|
|
1904
2380
|
};
|
|
1905
2381
|
const setBoolIfPresent = (key, value) => {
|
|
1906
|
-
if (value === void 0 || value === null)
|
|
1907
|
-
return;
|
|
2382
|
+
if (value === void 0 || value === null) return;
|
|
1908
2383
|
qs.set(key, value ? "true" : "false");
|
|
1909
2384
|
};
|
|
1910
2385
|
const setCsvIfPresent = (key, value) => {
|
|
1911
|
-
if (value === void 0 || value === null)
|
|
1912
|
-
return;
|
|
2386
|
+
if (value === void 0 || value === null) return;
|
|
1913
2387
|
if (Array.isArray(value)) {
|
|
1914
2388
|
const items = value.map((v) => String(v).trim()).filter(Boolean);
|
|
1915
|
-
if (items.length)
|
|
1916
|
-
qs.set(key, items.join(","));
|
|
2389
|
+
if (items.length) qs.set(key, items.join(","));
|
|
1917
2390
|
return;
|
|
1918
2391
|
}
|
|
1919
2392
|
setIfPresent(key, value);
|
|
@@ -1924,6 +2397,8 @@ ${bytes.length}`;
|
|
|
1924
2397
|
setIfPresent("sinceDays", params.sinceDays);
|
|
1925
2398
|
setIfPresent("since", params.since);
|
|
1926
2399
|
setIfPresent("limit", params.limit);
|
|
2400
|
+
setBoolIfPresent("includePrivate", params.includePrivate);
|
|
2401
|
+
setBoolIfPresent("includeQHashes", params.includeQHashes);
|
|
1927
2402
|
setIfPresent("referenceType", params.referenceType);
|
|
1928
2403
|
setIfPresent("referenceId", params.referenceId);
|
|
1929
2404
|
setIfPresent("tag", params.tag);
|
|
@@ -1937,6 +2412,8 @@ ${bytes.length}`;
|
|
|
1937
2412
|
setIfPresent("domain", params.domain);
|
|
1938
2413
|
setIfPresent("minBalance", params.minBalance);
|
|
1939
2414
|
setIfPresent("provider", params.provider);
|
|
2415
|
+
setIfPresent("handle", params.handle);
|
|
2416
|
+
setIfPresent("namespace", params.namespace);
|
|
1940
2417
|
setIfPresent("ownerAddress", params.ownerAddress);
|
|
1941
2418
|
setIfPresent("riskLevel", params.riskLevel);
|
|
1942
2419
|
setBoolIfPresent("sanctioned", params.sanctioned);
|
|
@@ -1944,18 +2421,57 @@ ${bytes.length}`;
|
|
|
1944
2421
|
setIfPresent("primaryWalletAddress", params.primaryWalletAddress);
|
|
1945
2422
|
setIfPresent("secondaryWalletAddress", params.secondaryWalletAddress);
|
|
1946
2423
|
setIfPresent("verificationMethod", params.verificationMethod);
|
|
1947
|
-
|
|
2424
|
+
let headersOverride = null;
|
|
2425
|
+
if (params.includePrivate === true) {
|
|
2426
|
+
const provided = params.privateAuth && typeof params.privateAuth === "object" ? params.privateAuth : null;
|
|
2427
|
+
let auth = provided;
|
|
2428
|
+
if (!auth) {
|
|
2429
|
+
const walletCandidate = params.wallet || this._getDefaultBrowserWallet();
|
|
2430
|
+
if (walletCandidate) {
|
|
2431
|
+
auth = await this._buildPrivateGateAuth({
|
|
2432
|
+
address,
|
|
2433
|
+
wallet: walletCandidate,
|
|
2434
|
+
chain: params.chain,
|
|
2435
|
+
signatureMethod: params.signatureMethod
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
if (!auth) {
|
|
2440
|
+
} else {
|
|
2441
|
+
const normalizedAuthWallet = this._normalizeIdentity(auth.walletAddress);
|
|
2442
|
+
const normalizedAddress = this._normalizeIdentity(address);
|
|
2443
|
+
if (!normalizedAuthWallet || normalizedAuthWallet !== normalizedAddress) {
|
|
2444
|
+
throw new ValidationError("privateAuth.walletAddress must match address when includePrivate=true");
|
|
2445
|
+
}
|
|
2446
|
+
const authChain = typeof auth.chain === "string" && auth.chain.includes(":") ? auth.chain.trim() : null;
|
|
2447
|
+
const authSignatureMethod = typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? auth.signatureMethod.trim() : null;
|
|
2448
|
+
headersOverride = {
|
|
2449
|
+
"x-wallet-address": String(auth.walletAddress),
|
|
2450
|
+
"x-signature": String(auth.signature),
|
|
2451
|
+
"x-signed-timestamp": String(auth.signedTimestamp),
|
|
2452
|
+
...authChain ? { "x-chain": authChain } : {},
|
|
2453
|
+
...authSignatureMethod ? { "x-signature-method": authSignatureMethod } : {}
|
|
2454
|
+
};
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/check?${qs.toString()}`, null, headersOverride);
|
|
1948
2458
|
if (!response.success) {
|
|
1949
2459
|
throw new ApiError(`Gate check failed: ${response.error?.message || "Unknown error"}`, response.error);
|
|
1950
2460
|
}
|
|
1951
2461
|
return response;
|
|
1952
2462
|
}
|
|
1953
2463
|
/**
|
|
1954
|
-
* CHECK GATE
|
|
1955
|
-
*
|
|
2464
|
+
* CHECK GATE — Local preview against proofs you already have in memory or from `getProofsByWallet`.
|
|
2465
|
+
*
|
|
2466
|
+
* **Not authoritative for access control.** For production allow/deny, use {@link NeusClient#gateCheck}
|
|
2467
|
+
* (`GET /api/v1/proofs/check`), which applies the same rules as the NEUS API. This method is useful for
|
|
2468
|
+
* UI previews, offline-ish flows, or when you already fetched proofs and want a quick match without
|
|
2469
|
+
* another round trip — but it can disagree with the server (e.g. `contentHash` matching uses a local
|
|
2470
|
+
* approximation when proof data only has inline `content`; the API uses the standard server-side hash).
|
|
2471
|
+
*
|
|
1956
2472
|
* Gate-first verification: checks if wallet has valid proofs satisfying requirements.
|
|
1957
2473
|
* Returns which requirements are missing/expired.
|
|
1958
|
-
*
|
|
2474
|
+
*
|
|
1959
2475
|
* @param {Object} params - Gate check parameters
|
|
1960
2476
|
* @param {string} params.walletAddress - Target wallet
|
|
1961
2477
|
* @param {Array<Object>} params.requirements - Array of gate requirements
|
|
@@ -1968,12 +2484,12 @@ ${bytes.length}`;
|
|
|
1968
2484
|
* Supports verifier-specific:
|
|
1969
2485
|
* - NFT/Token: 'contractAddress', 'tokenId', 'chainId', 'ownerAddress', 'minBalance'
|
|
1970
2486
|
* - DNS: 'domain', 'walletAddress'
|
|
1971
|
-
* - Wallet-link: 'primaryWalletAddress', 'secondaryWalletAddress', '
|
|
2487
|
+
* - Wallet-link: 'primaryWalletAddress', 'secondaryWalletAddress', 'chain', 'signatureMethod'
|
|
1972
2488
|
* - Contract-ownership: 'contractAddress', 'chainId', 'owner', 'verificationMethod'
|
|
1973
2489
|
* Note: contentHash matching uses approximation in SDK; for exact SHA-256 matching, use backend API
|
|
1974
2490
|
* @param {Array} [params.proofs] - Pre-fetched proofs (skip API call)
|
|
1975
2491
|
* @returns {Promise<Object>} Gate result with satisfied, missing, existing
|
|
1976
|
-
*
|
|
2492
|
+
*
|
|
1977
2493
|
* @example
|
|
1978
2494
|
* // Basic gate check
|
|
1979
2495
|
* const result = await client.checkGate({
|
|
@@ -1985,7 +2501,7 @@ ${bytes.length}`;
|
|
|
1985
2501
|
*/
|
|
1986
2502
|
async checkGate(params) {
|
|
1987
2503
|
const { walletAddress, requirements, proofs: preloadedProofs } = params;
|
|
1988
|
-
if (!
|
|
2504
|
+
if (!validateUniversalAddress(walletAddress)) {
|
|
1989
2505
|
throw new ValidationError("Valid walletAddress is required");
|
|
1990
2506
|
}
|
|
1991
2507
|
if (!Array.isArray(requirements) || requirements.length === 0) {
|
|
@@ -2006,20 +2522,20 @@ ${bytes.length}`;
|
|
|
2006
2522
|
const verifier = verifiedVerifiers.find(
|
|
2007
2523
|
(v) => v.verifierId === verifierId && v.verified === true
|
|
2008
2524
|
);
|
|
2009
|
-
if (!verifier)
|
|
2010
|
-
|
|
2011
|
-
if (proof.revokedAt)
|
|
2012
|
-
return false;
|
|
2525
|
+
if (!verifier) return false;
|
|
2526
|
+
if (proof.revokedAt) return false;
|
|
2013
2527
|
if (maxAgeMs) {
|
|
2014
2528
|
const proofTimestamp = proof.createdAt || proof.signedTimestamp || 0;
|
|
2015
2529
|
const proofAge = now - proofTimestamp;
|
|
2016
|
-
if (proofAge > maxAgeMs)
|
|
2017
|
-
return false;
|
|
2530
|
+
if (proofAge > maxAgeMs) return false;
|
|
2018
2531
|
}
|
|
2019
2532
|
if (match && typeof match === "object") {
|
|
2020
2533
|
const data = verifier.data || {};
|
|
2021
2534
|
const input = data.input || {};
|
|
2022
|
-
|
|
2535
|
+
const matchObj = Array.isArray(match) ? Object.fromEntries(
|
|
2536
|
+
match.filter((m) => m && m.path && String(m.value ?? "").trim() !== "").map((m) => [String(m.path).trim(), m.value])
|
|
2537
|
+
) : match;
|
|
2538
|
+
for (const [key, expected] of Object.entries(matchObj)) {
|
|
2023
2539
|
let actualValue = null;
|
|
2024
2540
|
if (key.includes(".")) {
|
|
2025
2541
|
const parts = key.split(".");
|
|
@@ -2044,6 +2560,7 @@ ${bytes.length}`;
|
|
|
2044
2560
|
actualValue = data.reference?.id || data.content;
|
|
2045
2561
|
}
|
|
2046
2562
|
if (actualValue === void 0) {
|
|
2563
|
+
const claims = data.claims || {};
|
|
2047
2564
|
if (key === "contractAddress") {
|
|
2048
2565
|
actualValue = input.contractAddress || data.contractAddress;
|
|
2049
2566
|
} else if (key === "tokenId") {
|
|
@@ -2062,6 +2579,22 @@ ${bytes.length}`;
|
|
|
2062
2579
|
actualValue = data.verificationMethod;
|
|
2063
2580
|
} else if (key === "domain") {
|
|
2064
2581
|
actualValue = data.domain;
|
|
2582
|
+
} else if (key === "handle") {
|
|
2583
|
+
actualValue = data.handle || data.pseudonymId;
|
|
2584
|
+
} else if (key === "namespace") {
|
|
2585
|
+
actualValue = data.namespace !== void 0 && data.namespace !== null && data.namespace !== "" ? data.namespace : "neus";
|
|
2586
|
+
} else if (key === "claims.sanctions_passed") {
|
|
2587
|
+
actualValue = claims.sanctions_passed ?? claims.sanctionsPassed;
|
|
2588
|
+
} else if (key === "claims.age_min") {
|
|
2589
|
+
actualValue = claims.age_min ?? claims.ageMin;
|
|
2590
|
+
} else if (key === "neusPersonhoodId") {
|
|
2591
|
+
actualValue = data.neusPersonhoodId;
|
|
2592
|
+
} else if (key === "riskLevel") {
|
|
2593
|
+
actualValue = data.riskLevel;
|
|
2594
|
+
} else if (key === "sanctioned") {
|
|
2595
|
+
actualValue = data.sanctioned;
|
|
2596
|
+
} else if (key === "poisoned") {
|
|
2597
|
+
actualValue = data.poisoned;
|
|
2065
2598
|
}
|
|
2066
2599
|
}
|
|
2067
2600
|
if (key === "contentHash" && actualValue === void 0 && data.content) {
|
|
@@ -2073,7 +2606,7 @@ ${bytes.length}`;
|
|
|
2073
2606
|
hash = (hash << 5) - hash + char;
|
|
2074
2607
|
hash = hash & hash;
|
|
2075
2608
|
}
|
|
2076
|
-
actualValue =
|
|
2609
|
+
actualValue = `0x${Math.abs(hash).toString(16).padStart(64, "0").substring(0, 66)}`;
|
|
2077
2610
|
} catch {
|
|
2078
2611
|
actualValue = String(data.content);
|
|
2079
2612
|
}
|
|
@@ -2083,11 +2616,16 @@ ${bytes.length}`;
|
|
|
2083
2616
|
if (actualValue === void 0 || actualValue === null) {
|
|
2084
2617
|
return false;
|
|
2085
2618
|
}
|
|
2619
|
+
if (typeof actualValue === "boolean" || key && (key.includes("sanctions") || key.includes("sanctioned") || key.includes("poisoned"))) {
|
|
2620
|
+
const bActual = Boolean(actualValue);
|
|
2621
|
+
const bExpected = expected === true || expected === "true" || String(expected).toLowerCase() === "true";
|
|
2622
|
+
if (bActual !== bExpected) return false;
|
|
2623
|
+
continue;
|
|
2624
|
+
}
|
|
2086
2625
|
if (key === "chainId" || key === "tokenId" && (typeof actualValue === "number" || !isNaN(Number(actualValue)))) {
|
|
2087
2626
|
normalizedActual = Number(actualValue);
|
|
2088
2627
|
normalizedExpected = Number(expected);
|
|
2089
|
-
if (isNaN(normalizedActual) || isNaN(normalizedExpected))
|
|
2090
|
-
return false;
|
|
2628
|
+
if (isNaN(normalizedActual) || isNaN(normalizedExpected)) return false;
|
|
2091
2629
|
} else if (typeof actualValue === "string" && (actualValue.startsWith("0x") || actualValue.length > 20)) {
|
|
2092
2630
|
normalizedActual = actualValue.toLowerCase();
|
|
2093
2631
|
normalizedExpected = typeof expected === "string" ? String(expected).toLowerCase() : expected;
|
|
@@ -2116,13 +2654,6 @@ ${bytes.length}`;
|
|
|
2116
2654
|
allProofs: proofs
|
|
2117
2655
|
};
|
|
2118
2656
|
}
|
|
2119
|
-
// ============================================================================
|
|
2120
|
-
// PRIVATE UTILITY METHODS
|
|
2121
|
-
// ============================================================================
|
|
2122
|
-
/**
|
|
2123
|
-
* Get connected wallet address
|
|
2124
|
-
* @private
|
|
2125
|
-
*/
|
|
2126
2657
|
async _getWalletAddress() {
|
|
2127
2658
|
if (typeof window === "undefined" || !window.ethereum) {
|
|
2128
2659
|
throw new ConfigurationError("No Web3 wallet detected");
|
|
@@ -2133,10 +2664,6 @@ ${bytes.length}`;
|
|
|
2133
2664
|
}
|
|
2134
2665
|
return accounts[0];
|
|
2135
2666
|
}
|
|
2136
|
-
/**
|
|
2137
|
-
* Make HTTP request to API
|
|
2138
|
-
* @private
|
|
2139
|
-
*/
|
|
2140
2667
|
async _makeRequest(method, endpoint, data = null, headersOverride = null) {
|
|
2141
2668
|
const url = `${this.baseUrl}${endpoint}`;
|
|
2142
2669
|
const controller = new AbortController();
|
|
@@ -2174,27 +2701,23 @@ ${bytes.length}`;
|
|
|
2174
2701
|
throw new NetworkError(`Network error: ${error.message}`);
|
|
2175
2702
|
}
|
|
2176
2703
|
}
|
|
2177
|
-
/**
|
|
2178
|
-
* Format API response for consistent structure
|
|
2179
|
-
* @private
|
|
2180
|
-
*/
|
|
2181
2704
|
_formatResponse(response) {
|
|
2182
|
-
const
|
|
2705
|
+
const proofId = response?.data?.proofId || response?.proofId || response?.data?.resource?.proofId || response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.id;
|
|
2706
|
+
const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || proofId || response?.data?.id;
|
|
2707
|
+
const finalProofId = proofId || qHash || null;
|
|
2708
|
+
const finalQHash = qHash || proofId || finalProofId;
|
|
2183
2709
|
const status = response?.data?.status || response?.status || response?.data?.resource?.status || (response?.success ? "completed" : "unknown");
|
|
2184
2710
|
return {
|
|
2185
2711
|
success: response.success,
|
|
2186
|
-
|
|
2712
|
+
proofId: finalProofId,
|
|
2713
|
+
qHash: finalQHash,
|
|
2187
2714
|
status,
|
|
2188
2715
|
data: response.data,
|
|
2189
2716
|
message: response.message,
|
|
2190
2717
|
timestamp: Date.now(),
|
|
2191
|
-
|
|
2718
|
+
proofUrl: finalProofId ? `${this.baseUrl}/api/v1/proofs/${finalProofId}` : null
|
|
2192
2719
|
};
|
|
2193
2720
|
}
|
|
2194
|
-
/**
|
|
2195
|
-
* Check if status is terminal (completed or failed)
|
|
2196
|
-
* @private
|
|
2197
|
-
*/
|
|
2198
2721
|
_isTerminalStatus(status) {
|
|
2199
2722
|
const terminalStates = [
|
|
2200
2723
|
"verified",
|
|
@@ -2226,22 +2749,29 @@ ${bytes.length}`;
|
|
|
2226
2749
|
});
|
|
2227
2750
|
|
|
2228
2751
|
// index.js
|
|
2229
|
-
var
|
|
2230
|
-
__export(
|
|
2752
|
+
var index_exports = {};
|
|
2753
|
+
__export(index_exports, {
|
|
2231
2754
|
ApiError: () => ApiError,
|
|
2232
2755
|
AuthenticationError: () => AuthenticationError,
|
|
2233
2756
|
ConfigurationError: () => ConfigurationError,
|
|
2234
2757
|
DAY: () => DAY,
|
|
2758
|
+
DEFAULT_HOSTED_VERIFY_URL: () => DEFAULT_HOSTED_VERIFY_URL,
|
|
2759
|
+
GATE_AGENT_DELEGATION: () => GATE_AGENT_DELEGATION,
|
|
2760
|
+
GATE_AGENT_IDENTITY: () => GATE_AGENT_IDENTITY,
|
|
2761
|
+
GATE_CONTENT_MODERATION: () => GATE_CONTENT_MODERATION,
|
|
2235
2762
|
GATE_CONTRACT_ADMIN: () => GATE_CONTRACT_ADMIN,
|
|
2236
2763
|
GATE_DOMAIN_OWNER: () => GATE_DOMAIN_OWNER,
|
|
2237
2764
|
GATE_LINKED_WALLETS: () => GATE_LINKED_WALLETS,
|
|
2238
2765
|
GATE_NFT_HOLDER: () => GATE_NFT_HOLDER,
|
|
2766
|
+
GATE_PSEUDONYM: () => GATE_PSEUDONYM,
|
|
2239
2767
|
GATE_TOKEN_HOLDER: () => GATE_TOKEN_HOLDER,
|
|
2768
|
+
GATE_WALLET_RISK: () => GATE_WALLET_RISK,
|
|
2240
2769
|
HOUR: () => HOUR,
|
|
2241
2770
|
MONTH: () => MONTH,
|
|
2242
2771
|
NEUS_CONSTANTS: () => NEUS_CONSTANTS,
|
|
2243
2772
|
NetworkError: () => NetworkError,
|
|
2244
2773
|
NeusClient: () => NeusClient,
|
|
2774
|
+
PORTABLE_PROOF_SIGNER_HEADER: () => PORTABLE_PROOF_SIGNER_HEADER,
|
|
2245
2775
|
SDKError: () => SDKError,
|
|
2246
2776
|
StatusPoller: () => StatusPoller,
|
|
2247
2777
|
ValidationError: () => ValidationError,
|
|
@@ -2254,24 +2784,32 @@ __export(sdk_exports, {
|
|
|
2254
2784
|
constructVerificationMessage: () => constructVerificationMessage,
|
|
2255
2785
|
createGate: () => createGate,
|
|
2256
2786
|
createVerificationData: () => createVerificationData,
|
|
2257
|
-
default: () =>
|
|
2787
|
+
default: () => index_default,
|
|
2258
2788
|
delay: () => delay,
|
|
2259
2789
|
deriveDid: () => deriveDid,
|
|
2260
2790
|
formatTimestamp: () => formatTimestamp,
|
|
2261
2791
|
formatVerificationStatus: () => formatVerificationStatus,
|
|
2792
|
+
getHostedCheckoutUrl: () => getHostedCheckoutUrl,
|
|
2262
2793
|
isFailureStatus: () => isFailureStatus,
|
|
2263
2794
|
isSuccessStatus: () => isSuccessStatus,
|
|
2264
2795
|
isSupportedChain: () => isSupportedChain,
|
|
2265
2796
|
isTerminalStatus: () => isTerminalStatus,
|
|
2266
2797
|
normalizeAddress: () => normalizeAddress,
|
|
2798
|
+
resolveDID: () => resolveDID,
|
|
2799
|
+
resolveZkPassportConfig: () => resolveZkPassportConfig,
|
|
2800
|
+
signMessage: () => signMessage,
|
|
2801
|
+
standardizeVerificationRequest: () => standardizeVerificationRequest,
|
|
2802
|
+
toAgentDelegationMaxSpend: () => toAgentDelegationMaxSpend,
|
|
2803
|
+
toHexUtf8: () => toHexUtf8,
|
|
2267
2804
|
validateQHash: () => validateQHash,
|
|
2268
2805
|
validateSignatureComponents: () => validateSignatureComponents,
|
|
2269
2806
|
validateTimestamp: () => validateTimestamp,
|
|
2807
|
+
validateUniversalAddress: () => validateUniversalAddress,
|
|
2270
2808
|
validateVerifierPayload: () => validateVerifierPayload,
|
|
2271
2809
|
validateWalletAddress: () => validateWalletAddress,
|
|
2272
2810
|
withRetry: () => withRetry
|
|
2273
2811
|
});
|
|
2274
|
-
module.exports = __toCommonJS(
|
|
2812
|
+
module.exports = __toCommonJS(index_exports);
|
|
2275
2813
|
init_client();
|
|
2276
2814
|
init_utils();
|
|
2277
2815
|
|
|
@@ -2296,9 +2834,21 @@ var GATE_DOMAIN_OWNER = [
|
|
|
2296
2834
|
var GATE_LINKED_WALLETS = [
|
|
2297
2835
|
{ verifierId: "wallet-link" }
|
|
2298
2836
|
];
|
|
2837
|
+
var GATE_AGENT_IDENTITY = [
|
|
2838
|
+
{ verifierId: "agent-identity" }
|
|
2839
|
+
];
|
|
2299
2840
|
var GATE_AGENT_DELEGATION = [
|
|
2300
2841
|
{ verifierId: "agent-delegation", maxAgeMs: 7 * DAY }
|
|
2301
2842
|
];
|
|
2843
|
+
var GATE_CONTENT_MODERATION = [
|
|
2844
|
+
{ verifierId: "ai-content-moderation" }
|
|
2845
|
+
];
|
|
2846
|
+
var GATE_WALLET_RISK = [
|
|
2847
|
+
{ verifierId: "wallet-risk" }
|
|
2848
|
+
];
|
|
2849
|
+
var GATE_PSEUDONYM = [
|
|
2850
|
+
{ verifierId: "ownership-pseudonym" }
|
|
2851
|
+
];
|
|
2302
2852
|
function createGate(requirements) {
|
|
2303
2853
|
return requirements.map((req) => {
|
|
2304
2854
|
if (typeof req === "string") {
|
|
@@ -2324,7 +2874,7 @@ function combineGates(...gates) {
|
|
|
2324
2874
|
|
|
2325
2875
|
// index.js
|
|
2326
2876
|
init_errors();
|
|
2327
|
-
var
|
|
2877
|
+
var index_default = {
|
|
2328
2878
|
NeusClient: () => Promise.resolve().then(() => (init_client(), client_exports)).then((m) => m.NeusClient),
|
|
2329
2879
|
toString: () => "[neus/sdk]"
|
|
2330
2880
|
};
|
|
@@ -2334,16 +2884,23 @@ var sdk_default = {
|
|
|
2334
2884
|
AuthenticationError,
|
|
2335
2885
|
ConfigurationError,
|
|
2336
2886
|
DAY,
|
|
2887
|
+
DEFAULT_HOSTED_VERIFY_URL,
|
|
2888
|
+
GATE_AGENT_DELEGATION,
|
|
2889
|
+
GATE_AGENT_IDENTITY,
|
|
2890
|
+
GATE_CONTENT_MODERATION,
|
|
2337
2891
|
GATE_CONTRACT_ADMIN,
|
|
2338
2892
|
GATE_DOMAIN_OWNER,
|
|
2339
2893
|
GATE_LINKED_WALLETS,
|
|
2340
2894
|
GATE_NFT_HOLDER,
|
|
2895
|
+
GATE_PSEUDONYM,
|
|
2341
2896
|
GATE_TOKEN_HOLDER,
|
|
2897
|
+
GATE_WALLET_RISK,
|
|
2342
2898
|
HOUR,
|
|
2343
2899
|
MONTH,
|
|
2344
2900
|
NEUS_CONSTANTS,
|
|
2345
2901
|
NetworkError,
|
|
2346
2902
|
NeusClient,
|
|
2903
|
+
PORTABLE_PROOF_SIGNER_HEADER,
|
|
2347
2904
|
SDKError,
|
|
2348
2905
|
StatusPoller,
|
|
2349
2906
|
ValidationError,
|
|
@@ -2360,14 +2917,22 @@ var sdk_default = {
|
|
|
2360
2917
|
deriveDid,
|
|
2361
2918
|
formatTimestamp,
|
|
2362
2919
|
formatVerificationStatus,
|
|
2920
|
+
getHostedCheckoutUrl,
|
|
2363
2921
|
isFailureStatus,
|
|
2364
2922
|
isSuccessStatus,
|
|
2365
2923
|
isSupportedChain,
|
|
2366
2924
|
isTerminalStatus,
|
|
2367
2925
|
normalizeAddress,
|
|
2926
|
+
resolveDID,
|
|
2927
|
+
resolveZkPassportConfig,
|
|
2928
|
+
signMessage,
|
|
2929
|
+
standardizeVerificationRequest,
|
|
2930
|
+
toAgentDelegationMaxSpend,
|
|
2931
|
+
toHexUtf8,
|
|
2368
2932
|
validateQHash,
|
|
2369
2933
|
validateSignatureComponents,
|
|
2370
2934
|
validateTimestamp,
|
|
2935
|
+
validateUniversalAddress,
|
|
2371
2936
|
validateVerifierPayload,
|
|
2372
2937
|
validateWalletAddress,
|
|
2373
2938
|
withRetry
|