@neus/sdk 1.0.3 → 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 +90 -150
- package/SECURITY.md +33 -29
- package/cjs/client.cjs +235 -264
- package/cjs/index.cjs +330 -310
- package/cjs/utils.cjs +138 -97
- package/cli/neus.mjs +58 -0
- package/client.js +464 -457
- package/errors.js +5 -5
- package/gates.js +18 -18
- package/index.js +79 -75
- package/package.json +16 -10
- package/types.d.ts +124 -59
- package/utils.js +1291 -1180
- package/widgets/README.md +45 -64
- package/widgets/index.js +1 -1
- package/widgets/verify-gate/dist/ProofBadge.js +10 -18
- package/widgets/verify-gate/dist/VerifyGate.js +108 -97
- package/widgets/verify-gate/index.js +5 -5
package/cjs/index.cjs
CHANGED
|
@@ -181,8 +181,7 @@ function encodeBase58Bytes(input) {
|
|
|
181
181
|
} else {
|
|
182
182
|
throw new SDKError("Unsupported non-EVM signature byte format", "INVALID_SIGNATURE_FORMAT");
|
|
183
183
|
}
|
|
184
|
-
if (source.length === 0)
|
|
185
|
-
return "";
|
|
184
|
+
if (source.length === 0) return "";
|
|
186
185
|
let zeroes = 0;
|
|
187
186
|
while (zeroes < source.length && source[zeroes] === 0) {
|
|
188
187
|
zeroes++;
|
|
@@ -216,16 +215,28 @@ function deterministicStringify(obj) {
|
|
|
216
215
|
return JSON.stringify(obj);
|
|
217
216
|
}
|
|
218
217
|
if (typeof obj !== "object") {
|
|
218
|
+
if (typeof obj === "string") return JSON.stringify(obj.normalize("NFC"));
|
|
219
219
|
return JSON.stringify(obj);
|
|
220
220
|
}
|
|
221
221
|
if (Array.isArray(obj)) {
|
|
222
|
-
return
|
|
222
|
+
return `[${obj.map((item) => item === void 0 ? "null" : deterministicStringify(item)).join(",")}]`;
|
|
223
223
|
}
|
|
224
|
-
const sortedKeys = Object.keys(obj).sort();
|
|
224
|
+
const sortedKeys = Object.keys(obj).filter((k) => obj[k] !== void 0).sort();
|
|
225
225
|
const pairs = sortedKeys.map(
|
|
226
|
-
(key) => JSON.stringify(key)
|
|
226
|
+
(key) => `${JSON.stringify(key)}:${deterministicStringify(obj[key])}`
|
|
227
227
|
);
|
|
228
|
-
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");
|
|
229
240
|
}
|
|
230
241
|
function constructVerificationMessage({ walletAddress, signedTimestamp, data, verifierIds, chainId, chain }) {
|
|
231
242
|
if (!walletAddress || typeof walletAddress !== "string") {
|
|
@@ -240,28 +251,28 @@ function constructVerificationMessage({ walletAddress, signedTimestamp, data, ve
|
|
|
240
251
|
if (!Array.isArray(verifierIds) || verifierIds.length === 0) {
|
|
241
252
|
throw new SDKError("verifierIds is required and must be a non-empty array", "INVALID_VERIFIER_IDS");
|
|
242
253
|
}
|
|
243
|
-
|
|
244
|
-
if (!chainContext) {
|
|
254
|
+
if ((typeof chain !== "string" || !chain.length) && !(typeof chainId === "number" && chainId > 0)) {
|
|
245
255
|
throw new SDKError("chainId is required (or provide chain for universal mode)", "INVALID_CHAIN_CONTEXT");
|
|
246
256
|
}
|
|
247
|
-
if (
|
|
248
|
-
throw new SDKError("chainId must be a number when provided", "INVALID_CHAIN_ID");
|
|
249
|
-
}
|
|
250
|
-
if (chainContext === chain && (typeof chain !== "string" || !chain.includes(":"))) {
|
|
257
|
+
if (typeof chain === "string" && chain.length > 0 && !chain.includes(":")) {
|
|
251
258
|
throw new SDKError('chain must be a "namespace:reference" string', "INVALID_CHAIN");
|
|
252
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);
|
|
253
264
|
const namespace = typeof chain === "string" && chain.includes(":") ? chain.split(":")[0] : "eip155";
|
|
254
265
|
const normalizedWalletAddress = namespace === "eip155" ? walletAddress.toLowerCase() : walletAddress;
|
|
255
266
|
const dataString = deterministicStringify(data);
|
|
256
267
|
const messageComponents = [
|
|
257
|
-
|
|
268
|
+
PORTABLE_PROOF_SIGNER_HEADER,
|
|
258
269
|
`Wallet: ${normalizedWalletAddress}`,
|
|
259
|
-
`Chain: ${
|
|
270
|
+
`Chain: ${chainLine}`,
|
|
260
271
|
`Verifiers: ${verifierIds.join(",")}`,
|
|
261
272
|
`Data: ${dataString}`,
|
|
262
273
|
`Timestamp: ${signedTimestamp}`
|
|
263
274
|
];
|
|
264
|
-
return messageComponents.join("\n");
|
|
275
|
+
return messageComponents.join("\n").normalize("NFC");
|
|
265
276
|
}
|
|
266
277
|
function validateWalletAddress(address) {
|
|
267
278
|
if (!address || typeof address !== "string") {
|
|
@@ -270,17 +281,13 @@ function validateWalletAddress(address) {
|
|
|
270
281
|
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
271
282
|
}
|
|
272
283
|
function validateUniversalAddress(address, chain) {
|
|
273
|
-
if (!address || typeof address !== "string")
|
|
274
|
-
return false;
|
|
284
|
+
if (!address || typeof address !== "string") return false;
|
|
275
285
|
const value = address.trim();
|
|
276
|
-
if (!value)
|
|
277
|
-
return false;
|
|
286
|
+
if (!value) return false;
|
|
278
287
|
const chainRef = typeof chain === "string" ? chain.trim().toLowerCase() : "";
|
|
279
288
|
const namespace = chainRef.includes(":") ? chainRef.split(":")[0] : "";
|
|
280
|
-
if (validateWalletAddress(value))
|
|
281
|
-
|
|
282
|
-
if (namespace === "eip155")
|
|
283
|
-
return false;
|
|
289
|
+
if (validateWalletAddress(value)) return true;
|
|
290
|
+
if (namespace === "eip155") return false;
|
|
284
291
|
if (namespace === "solana") {
|
|
285
292
|
return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value);
|
|
286
293
|
}
|
|
@@ -342,16 +349,12 @@ async function resolveDID(params, options = {}) {
|
|
|
342
349
|
const endpointPath = options.endpoint || "/api/v1/profile/did/resolve";
|
|
343
350
|
const apiUrl = typeof options.apiUrl === "string" ? options.apiUrl.trim() : "";
|
|
344
351
|
const resolveEndpoint = (path) => {
|
|
345
|
-
if (!path || typeof path !== "string")
|
|
346
|
-
return null;
|
|
352
|
+
if (!path || typeof path !== "string") return null;
|
|
347
353
|
const trimmedPath = path.trim();
|
|
348
|
-
if (!trimmedPath)
|
|
349
|
-
|
|
350
|
-
if (/^https?:\/\//i.test(trimmedPath))
|
|
351
|
-
return trimmedPath;
|
|
354
|
+
if (!trimmedPath) return null;
|
|
355
|
+
if (/^https?:\/\//i.test(trimmedPath)) return trimmedPath;
|
|
352
356
|
if (trimmedPath.startsWith("/")) {
|
|
353
|
-
if (!apiUrl)
|
|
354
|
-
return trimmedPath;
|
|
357
|
+
if (!apiUrl) return trimmedPath;
|
|
355
358
|
try {
|
|
356
359
|
return new URL(trimmedPath, apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`).toString();
|
|
357
360
|
} catch {
|
|
@@ -359,8 +362,7 @@ async function resolveDID(params, options = {}) {
|
|
|
359
362
|
}
|
|
360
363
|
}
|
|
361
364
|
const base = apiUrl || NEUS_CONSTANTS.API_BASE_URL;
|
|
362
|
-
if (!base || typeof base !== "string")
|
|
363
|
-
return null;
|
|
365
|
+
if (!base || typeof base !== "string") return null;
|
|
364
366
|
try {
|
|
365
367
|
return new URL(trimmedPath, base.endsWith("/") ? base : `${base}/`).toString();
|
|
366
368
|
} catch {
|
|
@@ -400,8 +402,7 @@ async function resolveDID(params, options = {}) {
|
|
|
400
402
|
}
|
|
401
403
|
return { did, data: json?.data || null, raw: json };
|
|
402
404
|
} catch (error) {
|
|
403
|
-
if (error instanceof SDKError)
|
|
404
|
-
throw error;
|
|
405
|
+
if (error instanceof SDKError) throw error;
|
|
405
406
|
throw new SDKError(`DID resolution failed: ${error?.message || error}`, "DID_RESOLVE_FAILED");
|
|
406
407
|
}
|
|
407
408
|
}
|
|
@@ -409,16 +410,12 @@ async function standardizeVerificationRequest(params, options = {}) {
|
|
|
409
410
|
const endpointPath = options.endpoint || "/api/v1/verification/standardize";
|
|
410
411
|
const apiUrl = typeof options.apiUrl === "string" ? options.apiUrl.trim() : "";
|
|
411
412
|
const resolveEndpoint = (path) => {
|
|
412
|
-
if (!path || typeof path !== "string")
|
|
413
|
-
return null;
|
|
413
|
+
if (!path || typeof path !== "string") return null;
|
|
414
414
|
const trimmedPath = path.trim();
|
|
415
|
-
if (!trimmedPath)
|
|
416
|
-
|
|
417
|
-
if (/^https?:\/\//i.test(trimmedPath))
|
|
418
|
-
return trimmedPath;
|
|
415
|
+
if (!trimmedPath) return null;
|
|
416
|
+
if (/^https?:\/\//i.test(trimmedPath)) return trimmedPath;
|
|
419
417
|
if (trimmedPath.startsWith("/")) {
|
|
420
|
-
if (!apiUrl)
|
|
421
|
-
return trimmedPath;
|
|
418
|
+
if (!apiUrl) return trimmedPath;
|
|
422
419
|
try {
|
|
423
420
|
return new URL(trimmedPath, apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`).toString();
|
|
424
421
|
} catch {
|
|
@@ -426,8 +423,7 @@ async function standardizeVerificationRequest(params, options = {}) {
|
|
|
426
423
|
}
|
|
427
424
|
}
|
|
428
425
|
const base = apiUrl || NEUS_CONSTANTS.API_BASE_URL;
|
|
429
|
-
if (!base || typeof base !== "string")
|
|
430
|
-
return null;
|
|
426
|
+
if (!base || typeof base !== "string") return null;
|
|
431
427
|
try {
|
|
432
428
|
return new URL(trimmedPath, base.endsWith("/") ? base : `${base}/`).toString();
|
|
433
429
|
} catch {
|
|
@@ -458,8 +454,7 @@ async function standardizeVerificationRequest(params, options = {}) {
|
|
|
458
454
|
}
|
|
459
455
|
return json?.data || json;
|
|
460
456
|
} catch (error) {
|
|
461
|
-
if (error instanceof SDKError)
|
|
462
|
-
throw error;
|
|
457
|
+
if (error instanceof SDKError) throw error;
|
|
463
458
|
throw new SDKError(`Standardize request failed: ${error?.message || error}`, "STANDARDIZE_FAILED");
|
|
464
459
|
}
|
|
465
460
|
}
|
|
@@ -493,34 +488,27 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
493
488
|
const chainStr = typeof chain === "string" && chain.trim().length > 0 ? chain.trim() : "eip155";
|
|
494
489
|
const namespace = chainStr.includes(":") ? chainStr.split(":")[0] || "eip155" : "eip155";
|
|
495
490
|
const resolveAddress = async () => {
|
|
496
|
-
if (typeof walletAddress === "string" && walletAddress.trim().length > 0)
|
|
497
|
-
return walletAddress;
|
|
491
|
+
if (typeof walletAddress === "string" && walletAddress.trim().length > 0) return walletAddress;
|
|
498
492
|
if (namespace === "solana") {
|
|
499
493
|
if (resolvedProvider?.publicKey && typeof resolvedProvider.publicKey.toBase58 === "function") {
|
|
500
494
|
const pk = resolvedProvider.publicKey.toBase58();
|
|
501
|
-
if (typeof pk === "string" && pk)
|
|
502
|
-
return pk;
|
|
495
|
+
if (typeof pk === "string" && pk) return pk;
|
|
503
496
|
}
|
|
504
497
|
if (typeof resolvedProvider.getAddress === "function") {
|
|
505
498
|
const addr = await resolvedProvider.getAddress().catch(() => null);
|
|
506
|
-
if (typeof addr === "string" && addr)
|
|
507
|
-
return addr;
|
|
499
|
+
if (typeof addr === "string" && addr) return addr;
|
|
508
500
|
}
|
|
509
|
-
if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
|
|
510
|
-
return resolvedProvider.address;
|
|
501
|
+
if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
|
|
511
502
|
return null;
|
|
512
503
|
}
|
|
513
|
-
if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
|
|
514
|
-
|
|
515
|
-
if (typeof resolvedProvider.getAddress === "function")
|
|
516
|
-
return await resolvedProvider.getAddress();
|
|
504
|
+
if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
|
|
505
|
+
if (typeof resolvedProvider.getAddress === "function") return resolvedProvider.getAddress();
|
|
517
506
|
if (typeof resolvedProvider.request === "function") {
|
|
518
507
|
let accounts = await resolvedProvider.request({ method: "eth_accounts" }).catch(() => []);
|
|
519
508
|
if (!Array.isArray(accounts) || accounts.length === 0) {
|
|
520
509
|
accounts = await resolvedProvider.request({ method: "eth_requestAccounts" }).catch(() => []);
|
|
521
510
|
}
|
|
522
|
-
if (Array.isArray(accounts) && accounts[0])
|
|
523
|
-
return accounts[0];
|
|
511
|
+
if (Array.isArray(accounts) && accounts[0]) return accounts[0];
|
|
524
512
|
}
|
|
525
513
|
return null;
|
|
526
514
|
};
|
|
@@ -528,16 +516,11 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
528
516
|
if (typeof resolvedProvider.signMessage === "function") {
|
|
529
517
|
const encoded = typeof msg === "string" ? new TextEncoder().encode(msg) : msg;
|
|
530
518
|
const result = await resolvedProvider.signMessage(encoded);
|
|
531
|
-
if (typeof result === "string" && result)
|
|
532
|
-
|
|
533
|
-
if (result instanceof Uint8Array)
|
|
534
|
-
|
|
535
|
-
if (result
|
|
536
|
-
return encodeBase58Bytes(new Uint8Array(result));
|
|
537
|
-
if (ArrayBuffer.isView(result))
|
|
538
|
-
return encodeBase58Bytes(result);
|
|
539
|
-
if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(result))
|
|
540
|
-
return encodeBase58Bytes(result);
|
|
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);
|
|
541
524
|
}
|
|
542
525
|
throw new SDKError("Non-EVM signing requires provider.signMessage", "SIGNER_UNAVAILABLE");
|
|
543
526
|
}
|
|
@@ -546,16 +529,14 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
546
529
|
let firstPersonalSignError = null;
|
|
547
530
|
try {
|
|
548
531
|
const sig = await resolvedProvider.request({ method: "personal_sign", params: [msg, address] });
|
|
549
|
-
if (typeof sig === "string" && sig)
|
|
550
|
-
return sig;
|
|
532
|
+
if (typeof sig === "string" && sig) return sig;
|
|
551
533
|
} catch (error) {
|
|
552
534
|
firstPersonalSignError = error;
|
|
553
535
|
}
|
|
554
536
|
let secondPersonalSignError = null;
|
|
555
537
|
try {
|
|
556
538
|
const sig = await resolvedProvider.request({ method: "personal_sign", params: [address, msg] });
|
|
557
|
-
if (typeof sig === "string" && sig)
|
|
558
|
-
return sig;
|
|
539
|
+
if (typeof sig === "string" && sig) return sig;
|
|
559
540
|
} catch (error) {
|
|
560
541
|
secondPersonalSignError = error;
|
|
561
542
|
const signatureErrorMessage = String(
|
|
@@ -566,16 +547,14 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
566
547
|
try {
|
|
567
548
|
const hexMsg = toHexUtf8(msg);
|
|
568
549
|
const sig = await resolvedProvider.request({ method: "personal_sign", params: [hexMsg, address] });
|
|
569
|
-
if (typeof sig === "string" && sig)
|
|
570
|
-
return sig;
|
|
550
|
+
if (typeof sig === "string" && sig) return sig;
|
|
571
551
|
} catch {
|
|
572
552
|
}
|
|
573
553
|
}
|
|
574
554
|
}
|
|
575
555
|
try {
|
|
576
556
|
const sig = await resolvedProvider.request({ method: "eth_sign", params: [address, msg] });
|
|
577
|
-
if (typeof sig === "string" && sig)
|
|
578
|
-
return sig;
|
|
557
|
+
if (typeof sig === "string" && sig) return sig;
|
|
579
558
|
} catch {
|
|
580
559
|
}
|
|
581
560
|
if (secondPersonalSignError || firstPersonalSignError) {
|
|
@@ -588,14 +567,12 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
588
567
|
}
|
|
589
568
|
if (typeof resolvedProvider.signMessage === "function") {
|
|
590
569
|
const result = await resolvedProvider.signMessage(msg);
|
|
591
|
-
if (typeof result === "string" && result)
|
|
592
|
-
return result;
|
|
570
|
+
if (typeof result === "string" && result) return result;
|
|
593
571
|
}
|
|
594
572
|
throw new SDKError("Unable to sign message with provided wallet/provider", "SIGNER_UNAVAILABLE");
|
|
595
573
|
}
|
|
596
574
|
function isTerminalStatus(status) {
|
|
597
|
-
if (!status || typeof status !== "string")
|
|
598
|
-
return false;
|
|
575
|
+
if (!status || typeof status !== "string") return false;
|
|
599
576
|
const successStates = [
|
|
600
577
|
"verified",
|
|
601
578
|
"verified_no_verifiers",
|
|
@@ -616,8 +593,7 @@ function isTerminalStatus(status) {
|
|
|
616
593
|
return successStates.includes(status) || failureStates.includes(status);
|
|
617
594
|
}
|
|
618
595
|
function isSuccessStatus(status) {
|
|
619
|
-
if (!status || typeof status !== "string")
|
|
620
|
-
return false;
|
|
596
|
+
if (!status || typeof status !== "string") return false;
|
|
621
597
|
const successStates = [
|
|
622
598
|
"verified",
|
|
623
599
|
"verified_no_verifiers",
|
|
@@ -628,8 +604,7 @@ function isSuccessStatus(status) {
|
|
|
628
604
|
return successStates.includes(status);
|
|
629
605
|
}
|
|
630
606
|
function isFailureStatus(status) {
|
|
631
|
-
if (!status || typeof status !== "string")
|
|
632
|
-
return false;
|
|
607
|
+
if (!status || typeof status !== "string") return false;
|
|
633
608
|
const failureStates = [
|
|
634
609
|
"rejected",
|
|
635
610
|
"rejected_verifier_failure",
|
|
@@ -780,23 +755,20 @@ function validateVerifierPayload(verifierId, data) {
|
|
|
780
755
|
const id = verifierId.replace(/@\d+$/, "");
|
|
781
756
|
if (id === "nft-ownership") {
|
|
782
757
|
["contractAddress", "tokenId", "chainId"].forEach((key) => {
|
|
783
|
-
if (!(key in data))
|
|
784
|
-
result.missing.push(key);
|
|
758
|
+
if (!(key in data)) result.missing.push(key);
|
|
785
759
|
});
|
|
786
760
|
if (!("ownerAddress" in data)) {
|
|
787
761
|
result.warnings.push("ownerAddress omitted (defaults to the signed walletAddress)");
|
|
788
762
|
}
|
|
789
763
|
} else if (id === "token-holding") {
|
|
790
764
|
["contractAddress", "minBalance", "chainId"].forEach((key) => {
|
|
791
|
-
if (!(key in data))
|
|
792
|
-
result.missing.push(key);
|
|
765
|
+
if (!(key in data)) result.missing.push(key);
|
|
793
766
|
});
|
|
794
767
|
if (!("ownerAddress" in data)) {
|
|
795
768
|
result.warnings.push("ownerAddress omitted (defaults to the signed walletAddress)");
|
|
796
769
|
}
|
|
797
770
|
} else if (id === "ownership-basic") {
|
|
798
|
-
if (!("owner" in data))
|
|
799
|
-
result.missing.push("owner");
|
|
771
|
+
if (!("owner" in data)) result.missing.push("owner");
|
|
800
772
|
const hasContent = typeof data.content === "string" && data.content.length > 0;
|
|
801
773
|
const hasContentHash = typeof data.contentHash === "string" && data.contentHash.length > 0;
|
|
802
774
|
const hasRefId = typeof data.reference?.id === "string" && data.reference.id.length > 0;
|
|
@@ -860,8 +832,7 @@ async function withRetry(fn, options = {}) {
|
|
|
860
832
|
return await fn();
|
|
861
833
|
} catch (error) {
|
|
862
834
|
lastError = error;
|
|
863
|
-
if (attempt === maxAttempts)
|
|
864
|
-
break;
|
|
835
|
+
if (attempt === maxAttempts) break;
|
|
865
836
|
const delayMs = Math.min(
|
|
866
837
|
baseDelay * Math.pow(backoffFactor, attempt - 1),
|
|
867
838
|
maxDelay
|
|
@@ -929,11 +900,72 @@ function validateSignatureComponents({ walletAddress, signature, signedTimestamp
|
|
|
929
900
|
}
|
|
930
901
|
return result;
|
|
931
902
|
}
|
|
932
|
-
|
|
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;
|
|
933
964
|
var init_utils = __esm({
|
|
934
965
|
"utils.js"() {
|
|
935
966
|
"use strict";
|
|
936
967
|
init_errors();
|
|
968
|
+
PORTABLE_PROOF_SIGNER_HEADER = "Portable Proof Verification Request";
|
|
937
969
|
BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
938
970
|
StatusPoller = class {
|
|
939
971
|
constructor(client, qHash, options = {}) {
|
|
@@ -957,7 +989,7 @@ var init_utils = __esm({
|
|
|
957
989
|
const pollAttempt = async () => {
|
|
958
990
|
try {
|
|
959
991
|
this.attempt++;
|
|
960
|
-
const response = await this.client.
|
|
992
|
+
const response = await this.client.getProof(this.qHash);
|
|
961
993
|
if (isTerminalStatus(response.status)) {
|
|
962
994
|
resolve(response);
|
|
963
995
|
return;
|
|
@@ -1002,7 +1034,7 @@ var init_utils = __esm({
|
|
|
1002
1034
|
}
|
|
1003
1035
|
};
|
|
1004
1036
|
NEUS_CONSTANTS = {
|
|
1005
|
-
|
|
1037
|
+
/** Default EVM chain id for NEUS protocol signing context (`HUB_CHAIN_ID` name kept for compatibility). */
|
|
1006
1038
|
HUB_CHAIN_ID: 84532,
|
|
1007
1039
|
// Supported target chains for cross-chain propagation
|
|
1008
1040
|
TESTNET_CHAINS: [
|
|
@@ -1030,6 +1062,7 @@ var init_utils = __esm({
|
|
|
1030
1062
|
"token-holding"
|
|
1031
1063
|
]
|
|
1032
1064
|
};
|
|
1065
|
+
DEFAULT_HOSTED_VERIFY_URL = "https://neus.network/verify";
|
|
1033
1066
|
}
|
|
1034
1067
|
});
|
|
1035
1068
|
|
|
@@ -1037,35 +1070,31 @@ var init_utils = __esm({
|
|
|
1037
1070
|
var client_exports = {};
|
|
1038
1071
|
__export(client_exports, {
|
|
1039
1072
|
NeusClient: () => NeusClient,
|
|
1073
|
+
PORTABLE_PROOF_SIGNER_HEADER: () => PORTABLE_PROOF_SIGNER_HEADER,
|
|
1040
1074
|
constructVerificationMessage: () => constructVerificationMessage
|
|
1041
1075
|
});
|
|
1042
|
-
var
|
|
1076
|
+
var FALLBACK_PUBLIC_VERIFIER_CATALOG, EVM_ADDRESS_RE, validateVerifierData, NeusClient;
|
|
1043
1077
|
var init_client = __esm({
|
|
1044
1078
|
"client.js"() {
|
|
1045
1079
|
"use strict";
|
|
1046
1080
|
init_errors();
|
|
1047
1081
|
init_utils();
|
|
1048
|
-
|
|
1049
|
-
"ownership-basic",
|
|
1050
|
-
"ownership-pseudonym",
|
|
1051
|
-
"ownership-dns-txt",
|
|
1052
|
-
"ownership-social",
|
|
1053
|
-
"ownership-org-oauth",
|
|
1054
|
-
"contract-ownership",
|
|
1055
|
-
"nft-ownership",
|
|
1056
|
-
"token-holding",
|
|
1057
|
-
"wallet-link",
|
|
1058
|
-
"wallet-risk",
|
|
1059
|
-
"proof-of-human",
|
|
1060
|
-
"agent-identity",
|
|
1061
|
-
"agent-delegation",
|
|
1062
|
-
"ai-content-moderation"
|
|
1063
|
-
|
|
1064
|
-
INTERACTIVE_VERIFIERS = /* @__PURE__ */ new Set([
|
|
1065
|
-
"ownership-social",
|
|
1066
|
-
"ownership-org-oauth",
|
|
1067
|
-
"proof-of-human"
|
|
1068
|
-
]);
|
|
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
|
+
};
|
|
1069
1098
|
EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
1070
1099
|
validateVerifierData = (verifierId, data) => {
|
|
1071
1100
|
if (!data || typeof data !== "object") {
|
|
@@ -1284,7 +1313,10 @@ var init_client = __esm({
|
|
|
1284
1313
|
const maxBytes = 50 * 1024;
|
|
1285
1314
|
const bytes = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(data.content).length : String(data.content).length;
|
|
1286
1315
|
if (bytes > maxBytes) {
|
|
1287
|
-
return {
|
|
1316
|
+
return {
|
|
1317
|
+
valid: false,
|
|
1318
|
+
error: `content exceeds ${maxBytes} bytes limit for ai-content-moderation verifier (text)`
|
|
1319
|
+
};
|
|
1288
1320
|
}
|
|
1289
1321
|
} catch {
|
|
1290
1322
|
}
|
|
@@ -1343,20 +1375,15 @@ var init_client = __esm({
|
|
|
1343
1375
|
if (typeof this.config.appId === "string" && this.config.appId.trim().length > 0) {
|
|
1344
1376
|
this.defaultHeaders["X-Neus-App"] = this.config.appId.trim();
|
|
1345
1377
|
}
|
|
1346
|
-
if (typeof this.config.sponsorGrant === "string" && this.config.sponsorGrant.trim().length > 0) {
|
|
1347
|
-
this.defaultHeaders["X-Sponsor-Grant"] = this.config.sponsorGrant.trim();
|
|
1348
|
-
}
|
|
1349
1378
|
if (typeof this.config.paymentSignature === "string" && this.config.paymentSignature.trim().length > 0) {
|
|
1350
1379
|
this.defaultHeaders["PAYMENT-SIGNATURE"] = this.config.paymentSignature.trim();
|
|
1351
1380
|
}
|
|
1352
1381
|
if (this.config.extraHeaders && typeof this.config.extraHeaders === "object") {
|
|
1353
1382
|
for (const [k, v] of Object.entries(this.config.extraHeaders)) {
|
|
1354
|
-
if (!k || v === void 0 || v === null)
|
|
1355
|
-
continue;
|
|
1383
|
+
if (!k || v === void 0 || v === null) continue;
|
|
1356
1384
|
const key = String(k).trim();
|
|
1357
1385
|
const value = String(v).trim();
|
|
1358
|
-
if (!key || !value)
|
|
1359
|
-
continue;
|
|
1386
|
+
if (!key || !value) continue;
|
|
1360
1387
|
this.defaultHeaders[key] = value;
|
|
1361
1388
|
}
|
|
1362
1389
|
}
|
|
@@ -1369,14 +1396,12 @@ var init_client = __esm({
|
|
|
1369
1396
|
}
|
|
1370
1397
|
_getHubChainId() {
|
|
1371
1398
|
const configured = Number(this.config?.hubChainId);
|
|
1372
|
-
if (Number.isFinite(configured) && configured > 0)
|
|
1373
|
-
return Math.floor(configured);
|
|
1399
|
+
if (Number.isFinite(configured) && configured > 0) return Math.floor(configured);
|
|
1374
1400
|
return NEUS_CONSTANTS.HUB_CHAIN_ID;
|
|
1375
1401
|
}
|
|
1376
1402
|
_normalizeIdentity(value) {
|
|
1377
1403
|
let raw = String(value || "").trim();
|
|
1378
|
-
if (!raw)
|
|
1379
|
-
return "";
|
|
1404
|
+
if (!raw) return "";
|
|
1380
1405
|
const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
|
|
1381
1406
|
if (didMatch && didMatch[3]) {
|
|
1382
1407
|
raw = String(didMatch[3]).trim();
|
|
@@ -1384,8 +1409,7 @@ var init_client = __esm({
|
|
|
1384
1409
|
return EVM_ADDRESS_RE.test(raw) ? raw.toLowerCase() : raw;
|
|
1385
1410
|
}
|
|
1386
1411
|
_inferChainForAddress(address, explicitChain) {
|
|
1387
|
-
if (typeof explicitChain === "string" && explicitChain.includes(":"))
|
|
1388
|
-
return explicitChain.trim();
|
|
1412
|
+
if (typeof explicitChain === "string" && explicitChain.includes(":")) return explicitChain.trim();
|
|
1389
1413
|
const raw = String(address || "").trim();
|
|
1390
1414
|
const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
|
|
1391
1415
|
if (didMatch && didMatch[1] && didMatch[2]) {
|
|
@@ -1424,8 +1448,7 @@ var init_client = __esm({
|
|
|
1424
1448
|
throw new ConfigurationError("Invalid wallet provider");
|
|
1425
1449
|
}
|
|
1426
1450
|
_getDefaultBrowserWallet() {
|
|
1427
|
-
if (typeof window === "undefined")
|
|
1428
|
-
return null;
|
|
1451
|
+
if (typeof window === "undefined") return null;
|
|
1429
1452
|
return window.ethereum || window.solana || window.phantom && window.phantom.solana || null;
|
|
1430
1453
|
}
|
|
1431
1454
|
async _buildPrivateGateAuth({ address, wallet, chain, signatureMethod } = {}) {
|
|
@@ -1483,80 +1506,66 @@ var init_client = __esm({
|
|
|
1483
1506
|
signatureMethod: params.signatureMethod
|
|
1484
1507
|
});
|
|
1485
1508
|
}
|
|
1486
|
-
// ============================================================================
|
|
1487
|
-
// CORE VERIFICATION METHODS
|
|
1488
|
-
// ============================================================================
|
|
1489
1509
|
/**
|
|
1490
|
-
*
|
|
1491
|
-
*
|
|
1492
|
-
*
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
*
|
|
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
|
+
*
|
|
1496
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
|
|
1497
1524
|
* @param {Array<string>} [params.verifierIds] - Array of verifier IDs (manual path)
|
|
1498
|
-
* @param {Object} [params.data] - Verification data object (manual path)
|
|
1499
1525
|
* @param {string} [params.walletAddress] - Wallet address that signed the request (manual path)
|
|
1500
1526
|
* @param {string} [params.signature] - EIP-191 signature (manual path)
|
|
1501
1527
|
* @param {number} [params.signedTimestamp] - Unix timestamp when signature was created (manual path)
|
|
1502
|
-
* @param {number} [params.chainId] -
|
|
1503
|
-
* @
|
|
1504
|
-
*
|
|
1505
|
-
* @param {string} [params.content] - Content/description (auto path)
|
|
1506
|
-
* @param {Object} [params.wallet] - Optional injected wallet/provider (auto path)
|
|
1507
|
-
* @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
|
|
1508
|
-
*
|
|
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
|
+
*
|
|
1509
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
|
+
*
|
|
1539
|
+
* @example
|
|
1540
|
+
* // Manual path
|
|
1510
1541
|
* const proof = await client.verify({
|
|
1511
1542
|
* verifierIds: ['ownership-basic'],
|
|
1512
|
-
* data: {
|
|
1513
|
-
* content: "My content",
|
|
1514
|
-
* owner: walletAddress, // or ownerAddress for nft-ownership/token-holding
|
|
1515
|
-
* reference: { type: 'other', id: 'my-unique-identifier' }
|
|
1516
|
-
* },
|
|
1543
|
+
* data: { content: "My content", owner: walletAddress },
|
|
1517
1544
|
* walletAddress: '0x...',
|
|
1518
1545
|
* signature: '0x...',
|
|
1519
1546
|
* signedTimestamp: Date.now(),
|
|
1520
1547
|
* options: { targetChains: [421614, 11155111] }
|
|
1521
1548
|
* });
|
|
1522
1549
|
*/
|
|
1523
|
-
/**
|
|
1524
|
-
* Create a verification proof
|
|
1525
|
-
*
|
|
1526
|
-
* @param {Object} params - Verification parameters
|
|
1527
|
-
* @param {string} [params.verifier] - Verifier ID (e.g., 'ownership-basic')
|
|
1528
|
-
* @param {string} [params.content] - Content to verify
|
|
1529
|
-
* @param {Object} [params.data] - Structured verification data
|
|
1530
|
-
* @param {Object} [params.wallet] - Wallet provider
|
|
1531
|
-
* @param {Object} [params.options] - Additional options
|
|
1532
|
-
* @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
|
|
1533
|
-
*
|
|
1534
|
-
* @example
|
|
1535
|
-
* // Simple ownership proof
|
|
1536
|
-
* const proof = await client.verify({
|
|
1537
|
-
* verifier: 'ownership-basic',
|
|
1538
|
-
* content: 'Hello World',
|
|
1539
|
-
* wallet: window.ethereum
|
|
1540
|
-
* });
|
|
1541
|
-
*/
|
|
1542
1550
|
async verify(params) {
|
|
1543
1551
|
if ((!params?.signature || !params?.walletAddress) && (params?.verifier || params?.content || params?.data)) {
|
|
1544
1552
|
const { content, verifier = "ownership-basic", data: data2 = null, wallet = null, options: options2 = {} } = params;
|
|
1545
1553
|
if (verifier === "ownership-basic" && !data2 && (!content || typeof content !== "string")) {
|
|
1546
1554
|
throw new ValidationError("content is required and must be a string (or use data param with owner + reference)");
|
|
1547
1555
|
}
|
|
1548
|
-
let
|
|
1556
|
+
let verifierCatalog = FALLBACK_PUBLIC_VERIFIER_CATALOG;
|
|
1549
1557
|
try {
|
|
1550
|
-
const discovered = await this.
|
|
1551
|
-
if (
|
|
1552
|
-
|
|
1558
|
+
const discovered = await this.getVerifierCatalog();
|
|
1559
|
+
if (discovered && discovered.metadata && Object.keys(discovered.metadata).length > 0) {
|
|
1560
|
+
verifierCatalog = discovered.metadata;
|
|
1553
1561
|
}
|
|
1554
1562
|
} catch {
|
|
1555
1563
|
}
|
|
1564
|
+
const validVerifiers = Object.keys(verifierCatalog);
|
|
1556
1565
|
if (!validVerifiers.includes(verifier)) {
|
|
1557
1566
|
throw new ValidationError(`Invalid verifier '${verifier}'. Must be one of: ${validVerifiers.join(", ")}.`);
|
|
1558
1567
|
}
|
|
1559
|
-
if (
|
|
1568
|
+
if (verifierCatalog?.[verifier]?.supportsDirectApi === false) {
|
|
1560
1569
|
const hostedCheckoutUrl = options2?.hostedCheckoutUrl || "https://neus.network/verify";
|
|
1561
1570
|
throw new ValidationError(
|
|
1562
1571
|
`${verifier} requires hosted interactive checkout. Use VerifyGate or redirect to ${hostedCheckoutUrl}.`
|
|
@@ -1697,7 +1706,10 @@ var init_client = __esm({
|
|
|
1697
1706
|
...data2?.agentLabel && { agentLabel: data2.agentLabel },
|
|
1698
1707
|
...data2?.agentType && { agentType: data2.agentType },
|
|
1699
1708
|
...data2?.description && { description: data2.description },
|
|
1700
|
-
...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 }
|
|
1701
1713
|
};
|
|
1702
1714
|
} else if (verifier === "agent-delegation") {
|
|
1703
1715
|
if (!data2?.agentWallet) {
|
|
@@ -1710,7 +1722,11 @@ var init_client = __esm({
|
|
|
1710
1722
|
...data2?.scope && { scope: data2.scope },
|
|
1711
1723
|
...data2?.permissions && { permissions: data2.permissions },
|
|
1712
1724
|
...data2?.maxSpend && { maxSpend: data2.maxSpend },
|
|
1713
|
-
...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 }
|
|
1714
1730
|
};
|
|
1715
1731
|
} else if (verifier === "ai-content-moderation") {
|
|
1716
1732
|
if (!data2?.content) {
|
|
@@ -1770,31 +1786,24 @@ var init_client = __esm({
|
|
|
1770
1786
|
const enc = new TextEncoder();
|
|
1771
1787
|
const bytes = enc.encode(s);
|
|
1772
1788
|
let hex = "0x";
|
|
1773
|
-
for (let i = 0; i < bytes.length; i++)
|
|
1774
|
-
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");
|
|
1775
1790
|
return hex;
|
|
1776
1791
|
} catch {
|
|
1777
1792
|
let hex = "0x";
|
|
1778
|
-
for (let i = 0; i < s.length; i++)
|
|
1779
|
-
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");
|
|
1780
1794
|
return hex;
|
|
1781
1795
|
}
|
|
1782
1796
|
};
|
|
1783
1797
|
const isFarcasterWallet = (() => {
|
|
1784
|
-
if (typeof window === "undefined")
|
|
1785
|
-
return false;
|
|
1798
|
+
if (typeof window === "undefined") return false;
|
|
1786
1799
|
try {
|
|
1787
1800
|
const w = window;
|
|
1788
1801
|
const fc = w.farcaster;
|
|
1789
|
-
if (!fc || !fc.context)
|
|
1790
|
-
return false;
|
|
1802
|
+
if (!fc || !fc.context) return false;
|
|
1791
1803
|
const fcProvider = fc.provider || fc.walletProvider || fc.context && fc.context.walletProvider;
|
|
1792
|
-
if (fcProvider === provider)
|
|
1793
|
-
|
|
1794
|
-
if (w.
|
|
1795
|
-
return true;
|
|
1796
|
-
if (w.ethereum === provider && fc && fc.context)
|
|
1797
|
-
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;
|
|
1798
1807
|
} catch {
|
|
1799
1808
|
}
|
|
1800
1809
|
return false;
|
|
@@ -1813,7 +1822,8 @@ var init_client = __esm({
|
|
|
1813
1822
|
const msg = String(e && (e.message || e.reason) || e || "").toLowerCase();
|
|
1814
1823
|
const errCode = e && (e.code || e.error && e.error.code) || null;
|
|
1815
1824
|
const needsHex = /byte|bytes|invalid byte sequence|encoding|non-hex/i.test(msg);
|
|
1816
|
-
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");
|
|
1817
1827
|
if (methodUnsupported) {
|
|
1818
1828
|
this._log("personal_sign not supported; attempting eth_sign fallback");
|
|
1819
1829
|
try {
|
|
@@ -1822,28 +1832,23 @@ var init_client = __esm({
|
|
|
1822
1832
|
const prefix = `Ethereum Signed Message:
|
|
1823
1833
|
${bytes.length}`;
|
|
1824
1834
|
const full = new Uint8Array(prefix.length + bytes.length);
|
|
1825
|
-
for (let i = 0; i < prefix.length; i++)
|
|
1826
|
-
full[i] = prefix.charCodeAt(i);
|
|
1835
|
+
for (let i = 0; i < prefix.length; i++) full[i] = prefix.charCodeAt(i);
|
|
1827
1836
|
full.set(bytes, prefix.length);
|
|
1828
1837
|
let payloadHex = "0x";
|
|
1829
|
-
for (let i = 0; i < full.length; i++)
|
|
1830
|
-
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");
|
|
1831
1839
|
try {
|
|
1832
|
-
if (typeof window !== "undefined")
|
|
1833
|
-
window.__NEUS_ALLOW_ETH_SIGN__ = true;
|
|
1840
|
+
if (typeof window !== "undefined") window.__NEUS_ALLOW_ETH_SIGN__ = true;
|
|
1834
1841
|
} catch {
|
|
1835
1842
|
}
|
|
1836
1843
|
signature2 = await provider.request({ method: "eth_sign", params: [walletAddress2, payloadHex], neusAllowEthSign: true });
|
|
1837
1844
|
try {
|
|
1838
|
-
if (typeof window !== "undefined")
|
|
1839
|
-
delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1845
|
+
if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1840
1846
|
} catch {
|
|
1841
1847
|
}
|
|
1842
1848
|
} catch (fallbackErr) {
|
|
1843
1849
|
this._log("eth_sign fallback failed", { message: fallbackErr?.message || String(fallbackErr) });
|
|
1844
1850
|
try {
|
|
1845
|
-
if (typeof window !== "undefined")
|
|
1846
|
-
delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1851
|
+
if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1847
1852
|
} catch {
|
|
1848
1853
|
}
|
|
1849
1854
|
throw e;
|
|
@@ -1885,8 +1890,7 @@ ${bytes.length}`;
|
|
|
1885
1890
|
} = params;
|
|
1886
1891
|
const resolvedChainId = chainId || (chain ? null : NEUS_CONSTANTS.HUB_CHAIN_ID);
|
|
1887
1892
|
const normalizeVerifierId = (id) => {
|
|
1888
|
-
if (typeof id !== "string")
|
|
1889
|
-
return id;
|
|
1893
|
+
if (typeof id !== "string") return id;
|
|
1890
1894
|
const match = id.match(/^(.*)@\d+$/);
|
|
1891
1895
|
return match ? match[1] : id;
|
|
1892
1896
|
};
|
|
@@ -1921,10 +1925,9 @@ ${bytes.length}`;
|
|
|
1921
1925
|
// Privacy and storage options (defaults)
|
|
1922
1926
|
privacyLevel: options?.privacyLevel || "private",
|
|
1923
1927
|
publicDisplay: options?.publicDisplay || false,
|
|
1924
|
-
storeOriginalContent: options?.storeOriginalContent
|
|
1928
|
+
storeOriginalContent: typeof options?.storeOriginalContent === "boolean" ? options.storeOriginalContent : true
|
|
1925
1929
|
};
|
|
1926
|
-
if (typeof options?.enableIpfs === "boolean")
|
|
1927
|
-
optionsPayload.enableIpfs = options.enableIpfs;
|
|
1930
|
+
if (typeof options?.enableIpfs === "boolean") optionsPayload.enableIpfs = options.enableIpfs;
|
|
1928
1931
|
const requestData = {
|
|
1929
1932
|
verifierIds: normalizedVerifierIds,
|
|
1930
1933
|
data,
|
|
@@ -1942,41 +1945,37 @@ ${bytes.length}`;
|
|
|
1942
1945
|
}
|
|
1943
1946
|
return this._formatResponse(response);
|
|
1944
1947
|
}
|
|
1945
|
-
// ============================================================================
|
|
1946
|
-
// STATUS AND UTILITY METHODS
|
|
1947
|
-
// ============================================================================
|
|
1948
1948
|
/**
|
|
1949
|
-
* Get
|
|
1949
|
+
* Get proof record by proof receipt id.
|
|
1950
1950
|
*
|
|
1951
|
-
* @param {string} proofId - Proof ID (
|
|
1952
|
-
* @returns {Promise<Object>}
|
|
1951
|
+
* @param {string} proofId - Proof receipt ID (0x + 64 hex).
|
|
1952
|
+
* @returns {Promise<Object>} Proof record and verification state
|
|
1953
1953
|
*
|
|
1954
1954
|
* @example
|
|
1955
|
-
* const result = await client.
|
|
1955
|
+
* const result = await client.getProof('0x...');
|
|
1956
1956
|
* console.log('Status:', result.status);
|
|
1957
1957
|
*/
|
|
1958
|
-
async
|
|
1958
|
+
async getProof(proofId) {
|
|
1959
1959
|
if (!proofId || typeof proofId !== "string") {
|
|
1960
1960
|
throw new ValidationError("proofId is required");
|
|
1961
1961
|
}
|
|
1962
|
-
const response = await this._makeRequest("GET", `/api/v1/
|
|
1962
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`);
|
|
1963
1963
|
if (!response.success) {
|
|
1964
|
-
throw new ApiError(`Failed to get
|
|
1964
|
+
throw new ApiError(`Failed to get proof: ${response.error?.message || "Unknown error"}`, response.error);
|
|
1965
1965
|
}
|
|
1966
1966
|
return this._formatResponse(response);
|
|
1967
1967
|
}
|
|
1968
1968
|
/**
|
|
1969
|
-
* Get private proof
|
|
1969
|
+
* Get private proof record with wallet signature
|
|
1970
1970
|
*
|
|
1971
|
-
* @param {string} proofId - Proof ID
|
|
1971
|
+
* @param {string} proofId - Proof receipt ID.
|
|
1972
1972
|
* @param {Object} wallet - Wallet provider (window.ethereum or ethers Wallet)
|
|
1973
|
-
* @returns {Promise<Object>} Private
|
|
1973
|
+
* @returns {Promise<Object>} Private proof record and verification state
|
|
1974
1974
|
*
|
|
1975
1975
|
* @example
|
|
1976
|
-
*
|
|
1977
|
-
* const privateData = await client.getPrivateStatus(proofId, window.ethereum);
|
|
1976
|
+
* const privateData = await client.getPrivateProof(proofId, window.ethereum);
|
|
1978
1977
|
*/
|
|
1979
|
-
async
|
|
1978
|
+
async getPrivateProof(proofId, wallet = null) {
|
|
1980
1979
|
if (!proofId || typeof proofId !== "string") {
|
|
1981
1980
|
throw new ValidationError("proofId is required");
|
|
1982
1981
|
}
|
|
@@ -1990,7 +1989,7 @@ ${bytes.length}`;
|
|
|
1990
1989
|
...typeof auth.chain === "string" && auth.chain.trim() ? { "x-chain": auth.chain.trim() } : {},
|
|
1991
1990
|
...typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? { "x-signature-method": auth.signatureMethod.trim() } : {}
|
|
1992
1991
|
};
|
|
1993
|
-
const response2 = await this._makeRequest("GET", `/api/v1/
|
|
1992
|
+
const response2 = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, headers);
|
|
1994
1993
|
if (!response2.success) {
|
|
1995
1994
|
throw new ApiError(
|
|
1996
1995
|
`Failed to access private proof: ${response2.error?.message || "Unauthorized"}`,
|
|
@@ -2029,7 +2028,7 @@ ${bytes.length}`;
|
|
|
2029
2028
|
}
|
|
2030
2029
|
throw new ValidationError(`Failed to sign message: ${error.message}`);
|
|
2031
2030
|
}
|
|
2032
|
-
const response = await this._makeRequest("GET", `/api/v1/
|
|
2031
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, {
|
|
2033
2032
|
"x-wallet-address": walletAddress,
|
|
2034
2033
|
"x-signature": signature,
|
|
2035
2034
|
"x-signed-timestamp": signedTimestamp.toString(),
|
|
@@ -2062,25 +2061,37 @@ ${bytes.length}`;
|
|
|
2062
2061
|
* @returns {Promise<string[]>} Array of verifier IDs
|
|
2063
2062
|
*/
|
|
2064
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() {
|
|
2065
2072
|
const response = await this._makeRequest("GET", "/api/v1/verification/verifiers");
|
|
2066
2073
|
if (!response.success) {
|
|
2067
2074
|
throw new ApiError(`Failed to get verifiers: ${response.error?.message || "Unknown error"}`, response.error);
|
|
2068
2075
|
}
|
|
2069
|
-
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
|
+
};
|
|
2070
2081
|
}
|
|
2071
2082
|
/**
|
|
2072
2083
|
* POLL PROOF STATUS - Wait for verification completion
|
|
2073
|
-
*
|
|
2084
|
+
*
|
|
2074
2085
|
* Polls the verification status until it reaches a terminal state (completed or failed).
|
|
2075
2086
|
* Useful for providing real-time feedback to users during verification.
|
|
2076
|
-
*
|
|
2077
|
-
* @param {string} proofId - Proof ID to poll
|
|
2087
|
+
*
|
|
2088
|
+
* @param {string} proofId - Proof ID to poll.
|
|
2078
2089
|
* @param {Object} [options] - Polling options
|
|
2079
2090
|
* @param {number} [options.interval=5000] - Polling interval in ms
|
|
2080
2091
|
* @param {number} [options.timeout=120000] - Total timeout in ms
|
|
2081
2092
|
* @param {Function} [options.onProgress] - Progress callback function
|
|
2082
2093
|
* @returns {Promise<Object>} Final verification status
|
|
2083
|
-
*
|
|
2094
|
+
*
|
|
2084
2095
|
* @example
|
|
2085
2096
|
* const finalStatus = await client.pollProofStatus(proofId, {
|
|
2086
2097
|
* interval: 3000,
|
|
@@ -2106,7 +2117,7 @@ ${bytes.length}`;
|
|
|
2106
2117
|
let consecutiveRateLimits = 0;
|
|
2107
2118
|
while (Date.now() - startTime < timeout) {
|
|
2108
2119
|
try {
|
|
2109
|
-
const status = await this.
|
|
2120
|
+
const status = await this.getProof(proofId);
|
|
2110
2121
|
consecutiveRateLimits = 0;
|
|
2111
2122
|
if (onProgress && typeof onProgress === "function") {
|
|
2112
2123
|
onProgress(status.data || status);
|
|
@@ -2139,7 +2150,7 @@ ${bytes.length}`;
|
|
|
2139
2150
|
}
|
|
2140
2151
|
/**
|
|
2141
2152
|
* DETECT CHAIN ID - Get current wallet chain
|
|
2142
|
-
*
|
|
2153
|
+
*
|
|
2143
2154
|
* @returns {Promise<number>} Current chain ID
|
|
2144
2155
|
*/
|
|
2145
2156
|
async detectChainId() {
|
|
@@ -2170,7 +2181,6 @@ ${bytes.length}`;
|
|
|
2170
2181
|
const message = constructVerificationMessage({
|
|
2171
2182
|
walletAddress: address,
|
|
2172
2183
|
signedTimestamp,
|
|
2173
|
-
// Keep wire payload key `qHash` for backwards compatibility.
|
|
2174
2184
|
data: { action: "revoke_proof", qHash: proofId },
|
|
2175
2185
|
verifierIds: ["ownership-basic"],
|
|
2176
2186
|
...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
|
|
@@ -2189,9 +2199,8 @@ ${bytes.length}`;
|
|
|
2189
2199
|
}
|
|
2190
2200
|
throw new ValidationError(`Failed to sign revocation: ${error.message}`);
|
|
2191
2201
|
}
|
|
2192
|
-
const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/${proofId}
|
|
2202
|
+
const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/revoke-self/${proofId}`, {
|
|
2193
2203
|
method: "POST",
|
|
2194
|
-
// SECURITY: Do not put proof signatures into Authorization headers.
|
|
2195
2204
|
headers: { "Content-Type": "application/json" },
|
|
2196
2205
|
body: JSON.stringify({
|
|
2197
2206
|
walletAddress: address,
|
|
@@ -2206,18 +2215,16 @@ ${bytes.length}`;
|
|
|
2206
2215
|
}
|
|
2207
2216
|
return true;
|
|
2208
2217
|
}
|
|
2209
|
-
// ============================================================================
|
|
2210
|
-
// PROOFS & GATING METHODS
|
|
2211
|
-
// ============================================================================
|
|
2212
2218
|
/**
|
|
2213
2219
|
* GET PROOFS BY WALLET - Fetch proofs for a wallet address
|
|
2214
|
-
*
|
|
2220
|
+
*
|
|
2215
2221
|
* @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
|
|
2216
2222
|
* @param {Object} [options] - Filter options
|
|
2217
2223
|
* @param {number} [options.limit] - Max results (default: 50; higher limits require owner access)
|
|
2218
2224
|
* @param {number} [options.offset] - Pagination offset (default: 0)
|
|
2225
|
+
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
2219
2226
|
* @returns {Promise<Object>} Proofs result
|
|
2220
|
-
*
|
|
2227
|
+
*
|
|
2221
2228
|
* @example
|
|
2222
2229
|
* const result = await client.getProofsByWallet('0x...', {
|
|
2223
2230
|
* limit: 50,
|
|
@@ -2231,14 +2238,13 @@ ${bytes.length}`;
|
|
|
2231
2238
|
const id = walletAddress.trim();
|
|
2232
2239
|
const pathId = /^0x[a-fA-F0-9]{40}$/i.test(id) ? id.toLowerCase() : id;
|
|
2233
2240
|
const qs = [];
|
|
2234
|
-
if (options.limit)
|
|
2235
|
-
|
|
2236
|
-
if (options.
|
|
2237
|
-
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())}`);
|
|
2238
2244
|
const query = qs.length ? `?${qs.join("&")}` : "";
|
|
2239
2245
|
const response = await this._makeRequest(
|
|
2240
2246
|
"GET",
|
|
2241
|
-
`/api/v1/proofs/
|
|
2247
|
+
`/api/v1/proofs/by-wallet/${encodeURIComponent(pathId)}${query}`
|
|
2242
2248
|
);
|
|
2243
2249
|
if (!response.success) {
|
|
2244
2250
|
throw new ApiError(`Failed to get proofs: ${response.error?.message || "Unknown error"}`, response.error);
|
|
@@ -2261,6 +2267,7 @@ ${bytes.length}`;
|
|
|
2261
2267
|
* @param {Object} [options]
|
|
2262
2268
|
* @param {number} [options.limit] - Max results (server enforces caps)
|
|
2263
2269
|
* @param {number} [options.offset] - Pagination offset
|
|
2270
|
+
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
2264
2271
|
* @param {Object} [wallet] - Optional injected wallet/provider (MetaMask/ethers Wallet)
|
|
2265
2272
|
*/
|
|
2266
2273
|
async getPrivateProofsByWallet(walletAddress, options = {}, wallet = null) {
|
|
@@ -2311,12 +2318,11 @@ ${bytes.length}`;
|
|
|
2311
2318
|
throw new ValidationError(`Failed to sign message: ${error.message}`);
|
|
2312
2319
|
}
|
|
2313
2320
|
const qs = [];
|
|
2314
|
-
if (options.limit)
|
|
2315
|
-
|
|
2316
|
-
if (options.
|
|
2317
|
-
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())}`);
|
|
2318
2324
|
const query = qs.length ? `?${qs.join("&")}` : "";
|
|
2319
|
-
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, {
|
|
2320
2326
|
"x-wallet-address": signerWalletAddress,
|
|
2321
2327
|
"x-signature": signature,
|
|
2322
2328
|
"x-signed-timestamp": signedTimestamp.toString(),
|
|
@@ -2335,16 +2341,16 @@ ${bytes.length}`;
|
|
|
2335
2341
|
};
|
|
2336
2342
|
}
|
|
2337
2343
|
/**
|
|
2338
|
-
*
|
|
2344
|
+
* Gate check (HTTP API) — minimal eligibility response.
|
|
2339
2345
|
*
|
|
2340
2346
|
* Calls the gate endpoint and returns a **minimal** yes/no response.
|
|
2341
|
-
* By default this checks **public +
|
|
2347
|
+
* By default this checks **public + unlisted** proofs.
|
|
2342
2348
|
*
|
|
2343
2349
|
* When `includePrivate=true`, this can perform owner-signed private checks
|
|
2344
2350
|
* (no full proof payloads returned) by providing a wallet/provider.
|
|
2345
2351
|
*
|
|
2346
|
-
* Prefer this over `checkGate()`
|
|
2347
|
-
*
|
|
2352
|
+
* Prefer this over `checkGate()` when you need the smallest, most stable
|
|
2353
|
+
* response shape and do not need full proof payloads.
|
|
2348
2354
|
*
|
|
2349
2355
|
* @param {Object} params - Gate check query params
|
|
2350
2356
|
* @param {string} params.address - Wallet identity to check (EVM/Solana/DID)
|
|
@@ -2367,25 +2373,20 @@ ${bytes.length}`;
|
|
|
2367
2373
|
const qs = new URLSearchParams();
|
|
2368
2374
|
qs.set("address", address);
|
|
2369
2375
|
const setIfPresent = (key, value) => {
|
|
2370
|
-
if (value === void 0 || value === null)
|
|
2371
|
-
return;
|
|
2376
|
+
if (value === void 0 || value === null) return;
|
|
2372
2377
|
const str = typeof value === "string" ? value : String(value);
|
|
2373
|
-
if (str.length === 0)
|
|
2374
|
-
return;
|
|
2378
|
+
if (str.length === 0) return;
|
|
2375
2379
|
qs.set(key, str);
|
|
2376
2380
|
};
|
|
2377
2381
|
const setBoolIfPresent = (key, value) => {
|
|
2378
|
-
if (value === void 0 || value === null)
|
|
2379
|
-
return;
|
|
2382
|
+
if (value === void 0 || value === null) return;
|
|
2380
2383
|
qs.set(key, value ? "true" : "false");
|
|
2381
2384
|
};
|
|
2382
2385
|
const setCsvIfPresent = (key, value) => {
|
|
2383
|
-
if (value === void 0 || value === null)
|
|
2384
|
-
return;
|
|
2386
|
+
if (value === void 0 || value === null) return;
|
|
2385
2387
|
if (Array.isArray(value)) {
|
|
2386
2388
|
const items = value.map((v) => String(v).trim()).filter(Boolean);
|
|
2387
|
-
if (items.length)
|
|
2388
|
-
qs.set(key, items.join(","));
|
|
2389
|
+
if (items.length) qs.set(key, items.join(","));
|
|
2389
2390
|
return;
|
|
2390
2391
|
}
|
|
2391
2392
|
setIfPresent(key, value);
|
|
@@ -2411,6 +2412,8 @@ ${bytes.length}`;
|
|
|
2411
2412
|
setIfPresent("domain", params.domain);
|
|
2412
2413
|
setIfPresent("minBalance", params.minBalance);
|
|
2413
2414
|
setIfPresent("provider", params.provider);
|
|
2415
|
+
setIfPresent("handle", params.handle);
|
|
2416
|
+
setIfPresent("namespace", params.namespace);
|
|
2414
2417
|
setIfPresent("ownerAddress", params.ownerAddress);
|
|
2415
2418
|
setIfPresent("riskLevel", params.riskLevel);
|
|
2416
2419
|
setBoolIfPresent("sanctioned", params.sanctioned);
|
|
@@ -2458,11 +2461,17 @@ ${bytes.length}`;
|
|
|
2458
2461
|
return response;
|
|
2459
2462
|
}
|
|
2460
2463
|
/**
|
|
2461
|
-
* CHECK GATE
|
|
2462
|
-
*
|
|
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
|
+
*
|
|
2463
2472
|
* Gate-first verification: checks if wallet has valid proofs satisfying requirements.
|
|
2464
2473
|
* Returns which requirements are missing/expired.
|
|
2465
|
-
*
|
|
2474
|
+
*
|
|
2466
2475
|
* @param {Object} params - Gate check parameters
|
|
2467
2476
|
* @param {string} params.walletAddress - Target wallet
|
|
2468
2477
|
* @param {Array<Object>} params.requirements - Array of gate requirements
|
|
@@ -2480,7 +2489,7 @@ ${bytes.length}`;
|
|
|
2480
2489
|
* Note: contentHash matching uses approximation in SDK; for exact SHA-256 matching, use backend API
|
|
2481
2490
|
* @param {Array} [params.proofs] - Pre-fetched proofs (skip API call)
|
|
2482
2491
|
* @returns {Promise<Object>} Gate result with satisfied, missing, existing
|
|
2483
|
-
*
|
|
2492
|
+
*
|
|
2484
2493
|
* @example
|
|
2485
2494
|
* // Basic gate check
|
|
2486
2495
|
* const result = await client.checkGate({
|
|
@@ -2513,20 +2522,20 @@ ${bytes.length}`;
|
|
|
2513
2522
|
const verifier = verifiedVerifiers.find(
|
|
2514
2523
|
(v) => v.verifierId === verifierId && v.verified === true
|
|
2515
2524
|
);
|
|
2516
|
-
if (!verifier)
|
|
2517
|
-
|
|
2518
|
-
if (proof.revokedAt)
|
|
2519
|
-
return false;
|
|
2525
|
+
if (!verifier) return false;
|
|
2526
|
+
if (proof.revokedAt) return false;
|
|
2520
2527
|
if (maxAgeMs) {
|
|
2521
2528
|
const proofTimestamp = proof.createdAt || proof.signedTimestamp || 0;
|
|
2522
2529
|
const proofAge = now - proofTimestamp;
|
|
2523
|
-
if (proofAge > maxAgeMs)
|
|
2524
|
-
return false;
|
|
2530
|
+
if (proofAge > maxAgeMs) return false;
|
|
2525
2531
|
}
|
|
2526
2532
|
if (match && typeof match === "object") {
|
|
2527
2533
|
const data = verifier.data || {};
|
|
2528
2534
|
const input = data.input || {};
|
|
2529
|
-
|
|
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)) {
|
|
2530
2539
|
let actualValue = null;
|
|
2531
2540
|
if (key.includes(".")) {
|
|
2532
2541
|
const parts = key.split(".");
|
|
@@ -2551,6 +2560,7 @@ ${bytes.length}`;
|
|
|
2551
2560
|
actualValue = data.reference?.id || data.content;
|
|
2552
2561
|
}
|
|
2553
2562
|
if (actualValue === void 0) {
|
|
2563
|
+
const claims = data.claims || {};
|
|
2554
2564
|
if (key === "contractAddress") {
|
|
2555
2565
|
actualValue = input.contractAddress || data.contractAddress;
|
|
2556
2566
|
} else if (key === "tokenId") {
|
|
@@ -2569,6 +2579,22 @@ ${bytes.length}`;
|
|
|
2569
2579
|
actualValue = data.verificationMethod;
|
|
2570
2580
|
} else if (key === "domain") {
|
|
2571
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;
|
|
2572
2598
|
}
|
|
2573
2599
|
}
|
|
2574
2600
|
if (key === "contentHash" && actualValue === void 0 && data.content) {
|
|
@@ -2580,7 +2606,7 @@ ${bytes.length}`;
|
|
|
2580
2606
|
hash = (hash << 5) - hash + char;
|
|
2581
2607
|
hash = hash & hash;
|
|
2582
2608
|
}
|
|
2583
|
-
actualValue =
|
|
2609
|
+
actualValue = `0x${Math.abs(hash).toString(16).padStart(64, "0").substring(0, 66)}`;
|
|
2584
2610
|
} catch {
|
|
2585
2611
|
actualValue = String(data.content);
|
|
2586
2612
|
}
|
|
@@ -2590,11 +2616,16 @@ ${bytes.length}`;
|
|
|
2590
2616
|
if (actualValue === void 0 || actualValue === null) {
|
|
2591
2617
|
return false;
|
|
2592
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
|
+
}
|
|
2593
2625
|
if (key === "chainId" || key === "tokenId" && (typeof actualValue === "number" || !isNaN(Number(actualValue)))) {
|
|
2594
2626
|
normalizedActual = Number(actualValue);
|
|
2595
2627
|
normalizedExpected = Number(expected);
|
|
2596
|
-
if (isNaN(normalizedActual) || isNaN(normalizedExpected))
|
|
2597
|
-
return false;
|
|
2628
|
+
if (isNaN(normalizedActual) || isNaN(normalizedExpected)) return false;
|
|
2598
2629
|
} else if (typeof actualValue === "string" && (actualValue.startsWith("0x") || actualValue.length > 20)) {
|
|
2599
2630
|
normalizedActual = actualValue.toLowerCase();
|
|
2600
2631
|
normalizedExpected = typeof expected === "string" ? String(expected).toLowerCase() : expected;
|
|
@@ -2623,13 +2654,6 @@ ${bytes.length}`;
|
|
|
2623
2654
|
allProofs: proofs
|
|
2624
2655
|
};
|
|
2625
2656
|
}
|
|
2626
|
-
// ============================================================================
|
|
2627
|
-
// PRIVATE UTILITY METHODS
|
|
2628
|
-
// ============================================================================
|
|
2629
|
-
/**
|
|
2630
|
-
* Get connected wallet address
|
|
2631
|
-
* @private
|
|
2632
|
-
*/
|
|
2633
2657
|
async _getWalletAddress() {
|
|
2634
2658
|
if (typeof window === "undefined" || !window.ethereum) {
|
|
2635
2659
|
throw new ConfigurationError("No Web3 wallet detected");
|
|
@@ -2640,10 +2664,6 @@ ${bytes.length}`;
|
|
|
2640
2664
|
}
|
|
2641
2665
|
return accounts[0];
|
|
2642
2666
|
}
|
|
2643
|
-
/**
|
|
2644
|
-
* Make HTTP request to API
|
|
2645
|
-
* @private
|
|
2646
|
-
*/
|
|
2647
2667
|
async _makeRequest(method, endpoint, data = null, headersOverride = null) {
|
|
2648
2668
|
const url = `${this.baseUrl}${endpoint}`;
|
|
2649
2669
|
const controller = new AbortController();
|
|
@@ -2681,10 +2701,6 @@ ${bytes.length}`;
|
|
|
2681
2701
|
throw new NetworkError(`Network error: ${error.message}`);
|
|
2682
2702
|
}
|
|
2683
2703
|
}
|
|
2684
|
-
/**
|
|
2685
|
-
* Format API response for consistent structure
|
|
2686
|
-
* @private
|
|
2687
|
-
*/
|
|
2688
2704
|
_formatResponse(response) {
|
|
2689
2705
|
const proofId = response?.data?.proofId || response?.proofId || response?.data?.resource?.proofId || response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.id;
|
|
2690
2706
|
const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || proofId || response?.data?.id;
|
|
@@ -2699,13 +2715,9 @@ ${bytes.length}`;
|
|
|
2699
2715
|
data: response.data,
|
|
2700
2716
|
message: response.message,
|
|
2701
2717
|
timestamp: Date.now(),
|
|
2702
|
-
|
|
2718
|
+
proofUrl: finalProofId ? `${this.baseUrl}/api/v1/proofs/${finalProofId}` : null
|
|
2703
2719
|
};
|
|
2704
2720
|
}
|
|
2705
|
-
/**
|
|
2706
|
-
* Check if status is terminal (completed or failed)
|
|
2707
|
-
* @private
|
|
2708
|
-
*/
|
|
2709
2721
|
_isTerminalStatus(status) {
|
|
2710
2722
|
const terminalStates = [
|
|
2711
2723
|
"verified",
|
|
@@ -2737,12 +2749,13 @@ ${bytes.length}`;
|
|
|
2737
2749
|
});
|
|
2738
2750
|
|
|
2739
2751
|
// index.js
|
|
2740
|
-
var
|
|
2741
|
-
__export(
|
|
2752
|
+
var index_exports = {};
|
|
2753
|
+
__export(index_exports, {
|
|
2742
2754
|
ApiError: () => ApiError,
|
|
2743
2755
|
AuthenticationError: () => AuthenticationError,
|
|
2744
2756
|
ConfigurationError: () => ConfigurationError,
|
|
2745
2757
|
DAY: () => DAY,
|
|
2758
|
+
DEFAULT_HOSTED_VERIFY_URL: () => DEFAULT_HOSTED_VERIFY_URL,
|
|
2746
2759
|
GATE_AGENT_DELEGATION: () => GATE_AGENT_DELEGATION,
|
|
2747
2760
|
GATE_AGENT_IDENTITY: () => GATE_AGENT_IDENTITY,
|
|
2748
2761
|
GATE_CONTENT_MODERATION: () => GATE_CONTENT_MODERATION,
|
|
@@ -2758,6 +2771,7 @@ __export(sdk_exports, {
|
|
|
2758
2771
|
NEUS_CONSTANTS: () => NEUS_CONSTANTS,
|
|
2759
2772
|
NetworkError: () => NetworkError,
|
|
2760
2773
|
NeusClient: () => NeusClient,
|
|
2774
|
+
PORTABLE_PROOF_SIGNER_HEADER: () => PORTABLE_PROOF_SIGNER_HEADER,
|
|
2761
2775
|
SDKError: () => SDKError,
|
|
2762
2776
|
StatusPoller: () => StatusPoller,
|
|
2763
2777
|
ValidationError: () => ValidationError,
|
|
@@ -2770,11 +2784,12 @@ __export(sdk_exports, {
|
|
|
2770
2784
|
constructVerificationMessage: () => constructVerificationMessage,
|
|
2771
2785
|
createGate: () => createGate,
|
|
2772
2786
|
createVerificationData: () => createVerificationData,
|
|
2773
|
-
default: () =>
|
|
2787
|
+
default: () => index_default,
|
|
2774
2788
|
delay: () => delay,
|
|
2775
2789
|
deriveDid: () => deriveDid,
|
|
2776
2790
|
formatTimestamp: () => formatTimestamp,
|
|
2777
2791
|
formatVerificationStatus: () => formatVerificationStatus,
|
|
2792
|
+
getHostedCheckoutUrl: () => getHostedCheckoutUrl,
|
|
2778
2793
|
isFailureStatus: () => isFailureStatus,
|
|
2779
2794
|
isSuccessStatus: () => isSuccessStatus,
|
|
2780
2795
|
isSupportedChain: () => isSupportedChain,
|
|
@@ -2784,6 +2799,7 @@ __export(sdk_exports, {
|
|
|
2784
2799
|
resolveZkPassportConfig: () => resolveZkPassportConfig,
|
|
2785
2800
|
signMessage: () => signMessage,
|
|
2786
2801
|
standardizeVerificationRequest: () => standardizeVerificationRequest,
|
|
2802
|
+
toAgentDelegationMaxSpend: () => toAgentDelegationMaxSpend,
|
|
2787
2803
|
toHexUtf8: () => toHexUtf8,
|
|
2788
2804
|
validateQHash: () => validateQHash,
|
|
2789
2805
|
validateSignatureComponents: () => validateSignatureComponents,
|
|
@@ -2793,7 +2809,7 @@ __export(sdk_exports, {
|
|
|
2793
2809
|
validateWalletAddress: () => validateWalletAddress,
|
|
2794
2810
|
withRetry: () => withRetry
|
|
2795
2811
|
});
|
|
2796
|
-
module.exports = __toCommonJS(
|
|
2812
|
+
module.exports = __toCommonJS(index_exports);
|
|
2797
2813
|
init_client();
|
|
2798
2814
|
init_utils();
|
|
2799
2815
|
|
|
@@ -2858,7 +2874,7 @@ function combineGates(...gates) {
|
|
|
2858
2874
|
|
|
2859
2875
|
// index.js
|
|
2860
2876
|
init_errors();
|
|
2861
|
-
var
|
|
2877
|
+
var index_default = {
|
|
2862
2878
|
NeusClient: () => Promise.resolve().then(() => (init_client(), client_exports)).then((m) => m.NeusClient),
|
|
2863
2879
|
toString: () => "[neus/sdk]"
|
|
2864
2880
|
};
|
|
@@ -2868,6 +2884,7 @@ var sdk_default = {
|
|
|
2868
2884
|
AuthenticationError,
|
|
2869
2885
|
ConfigurationError,
|
|
2870
2886
|
DAY,
|
|
2887
|
+
DEFAULT_HOSTED_VERIFY_URL,
|
|
2871
2888
|
GATE_AGENT_DELEGATION,
|
|
2872
2889
|
GATE_AGENT_IDENTITY,
|
|
2873
2890
|
GATE_CONTENT_MODERATION,
|
|
@@ -2883,6 +2900,7 @@ var sdk_default = {
|
|
|
2883
2900
|
NEUS_CONSTANTS,
|
|
2884
2901
|
NetworkError,
|
|
2885
2902
|
NeusClient,
|
|
2903
|
+
PORTABLE_PROOF_SIGNER_HEADER,
|
|
2886
2904
|
SDKError,
|
|
2887
2905
|
StatusPoller,
|
|
2888
2906
|
ValidationError,
|
|
@@ -2899,6 +2917,7 @@ var sdk_default = {
|
|
|
2899
2917
|
deriveDid,
|
|
2900
2918
|
formatTimestamp,
|
|
2901
2919
|
formatVerificationStatus,
|
|
2920
|
+
getHostedCheckoutUrl,
|
|
2902
2921
|
isFailureStatus,
|
|
2903
2922
|
isSuccessStatus,
|
|
2904
2923
|
isSupportedChain,
|
|
@@ -2908,6 +2927,7 @@ var sdk_default = {
|
|
|
2908
2927
|
resolveZkPassportConfig,
|
|
2909
2928
|
signMessage,
|
|
2910
2929
|
standardizeVerificationRequest,
|
|
2930
|
+
toAgentDelegationMaxSpend,
|
|
2911
2931
|
toHexUtf8,
|
|
2912
2932
|
validateQHash,
|
|
2913
2933
|
validateSignatureComponents,
|