@neus/sdk 1.0.3 → 1.0.5
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 +127 -150
- package/SECURITY.md +33 -29
- package/cjs/client.cjs +308 -264
- package/cjs/index.cjs +403 -310
- package/cjs/utils.cjs +138 -97
- package/cli/neus.mjs +606 -0
- package/client.js +559 -470
- package/errors.js +5 -5
- package/gates.js +18 -18
- package/index.js +79 -75
- package/package.json +16 -10
- package/types.d.ts +138 -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 +109 -98
- package/widgets/verify-gate/index.js +5 -5
package/cjs/client.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var client_exports = {};
|
|
22
22
|
__export(client_exports, {
|
|
23
23
|
NeusClient: () => NeusClient,
|
|
24
|
+
PORTABLE_PROOF_SIGNER_HEADER: () => PORTABLE_PROOF_SIGNER_HEADER,
|
|
24
25
|
constructVerificationMessage: () => constructVerificationMessage
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(client_exports);
|
|
@@ -129,6 +130,7 @@ var ConfigurationError = class extends SDKError {
|
|
|
129
130
|
};
|
|
130
131
|
|
|
131
132
|
// utils.js
|
|
133
|
+
var PORTABLE_PROOF_SIGNER_HEADER = "Portable Proof Verification Request";
|
|
132
134
|
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
133
135
|
function encodeBase58Bytes(input) {
|
|
134
136
|
let source;
|
|
@@ -143,8 +145,7 @@ function encodeBase58Bytes(input) {
|
|
|
143
145
|
} else {
|
|
144
146
|
throw new SDKError("Unsupported non-EVM signature byte format", "INVALID_SIGNATURE_FORMAT");
|
|
145
147
|
}
|
|
146
|
-
if (source.length === 0)
|
|
147
|
-
return "";
|
|
148
|
+
if (source.length === 0) return "";
|
|
148
149
|
let zeroes = 0;
|
|
149
150
|
while (zeroes < source.length && source[zeroes] === 0) {
|
|
150
151
|
zeroes++;
|
|
@@ -178,16 +179,28 @@ function deterministicStringify(obj) {
|
|
|
178
179
|
return JSON.stringify(obj);
|
|
179
180
|
}
|
|
180
181
|
if (typeof obj !== "object") {
|
|
182
|
+
if (typeof obj === "string") return JSON.stringify(obj.normalize("NFC"));
|
|
181
183
|
return JSON.stringify(obj);
|
|
182
184
|
}
|
|
183
185
|
if (Array.isArray(obj)) {
|
|
184
|
-
return
|
|
186
|
+
return `[${obj.map((item) => item === void 0 ? "null" : deterministicStringify(item)).join(",")}]`;
|
|
185
187
|
}
|
|
186
|
-
const sortedKeys = Object.keys(obj).sort();
|
|
188
|
+
const sortedKeys = Object.keys(obj).filter((k) => obj[k] !== void 0).sort();
|
|
187
189
|
const pairs = sortedKeys.map(
|
|
188
|
-
(key) => JSON.stringify(key)
|
|
190
|
+
(key) => `${JSON.stringify(key)}:${deterministicStringify(obj[key])}`
|
|
189
191
|
);
|
|
190
|
-
return
|
|
192
|
+
return `{${pairs.join(",")}}`;
|
|
193
|
+
}
|
|
194
|
+
function chainLineForPortableProofSigner(chain, chainId) {
|
|
195
|
+
if (typeof chain === "string" && chain.length > 0) {
|
|
196
|
+
const m = chain.match(/^eip155:(\d+)$/);
|
|
197
|
+
if (m) return Number(m[1]);
|
|
198
|
+
return chain;
|
|
199
|
+
}
|
|
200
|
+
if (typeof chainId === "number" && Number.isFinite(chainId) && chainId > 0) {
|
|
201
|
+
return chainId;
|
|
202
|
+
}
|
|
203
|
+
throw new SDKError("chainId is required (or provide chain for universal mode)", "INVALID_CHAIN_CONTEXT");
|
|
191
204
|
}
|
|
192
205
|
function constructVerificationMessage({ walletAddress, signedTimestamp, data, verifierIds, chainId, chain }) {
|
|
193
206
|
if (!walletAddress || typeof walletAddress !== "string") {
|
|
@@ -202,28 +215,28 @@ function constructVerificationMessage({ walletAddress, signedTimestamp, data, ve
|
|
|
202
215
|
if (!Array.isArray(verifierIds) || verifierIds.length === 0) {
|
|
203
216
|
throw new SDKError("verifierIds is required and must be a non-empty array", "INVALID_VERIFIER_IDS");
|
|
204
217
|
}
|
|
205
|
-
|
|
206
|
-
if (!chainContext) {
|
|
218
|
+
if ((typeof chain !== "string" || !chain.length) && !(typeof chainId === "number" && chainId > 0)) {
|
|
207
219
|
throw new SDKError("chainId is required (or provide chain for universal mode)", "INVALID_CHAIN_CONTEXT");
|
|
208
220
|
}
|
|
209
|
-
if (
|
|
210
|
-
throw new SDKError("chainId must be a number when provided", "INVALID_CHAIN_ID");
|
|
211
|
-
}
|
|
212
|
-
if (chainContext === chain && (typeof chain !== "string" || !chain.includes(":"))) {
|
|
221
|
+
if (typeof chain === "string" && chain.length > 0 && !chain.includes(":")) {
|
|
213
222
|
throw new SDKError('chain must be a "namespace:reference" string', "INVALID_CHAIN");
|
|
214
223
|
}
|
|
224
|
+
if ((!chain || !chain.length) && typeof chainId !== "number") {
|
|
225
|
+
throw new SDKError("chainId must be a number when provided", "INVALID_CHAIN_ID");
|
|
226
|
+
}
|
|
227
|
+
const chainLine = chainLineForPortableProofSigner(chain, chainId);
|
|
215
228
|
const namespace = typeof chain === "string" && chain.includes(":") ? chain.split(":")[0] : "eip155";
|
|
216
229
|
const normalizedWalletAddress = namespace === "eip155" ? walletAddress.toLowerCase() : walletAddress;
|
|
217
230
|
const dataString = deterministicStringify(data);
|
|
218
231
|
const messageComponents = [
|
|
219
|
-
|
|
232
|
+
PORTABLE_PROOF_SIGNER_HEADER,
|
|
220
233
|
`Wallet: ${normalizedWalletAddress}`,
|
|
221
|
-
`Chain: ${
|
|
234
|
+
`Chain: ${chainLine}`,
|
|
222
235
|
`Verifiers: ${verifierIds.join(",")}`,
|
|
223
236
|
`Data: ${dataString}`,
|
|
224
237
|
`Timestamp: ${signedTimestamp}`
|
|
225
238
|
];
|
|
226
|
-
return messageComponents.join("\n");
|
|
239
|
+
return messageComponents.join("\n").normalize("NFC");
|
|
227
240
|
}
|
|
228
241
|
function validateWalletAddress(address) {
|
|
229
242
|
if (!address || typeof address !== "string") {
|
|
@@ -232,17 +245,13 @@ function validateWalletAddress(address) {
|
|
|
232
245
|
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
233
246
|
}
|
|
234
247
|
function validateUniversalAddress(address, chain) {
|
|
235
|
-
if (!address || typeof address !== "string")
|
|
236
|
-
return false;
|
|
248
|
+
if (!address || typeof address !== "string") return false;
|
|
237
249
|
const value = address.trim();
|
|
238
|
-
if (!value)
|
|
239
|
-
return false;
|
|
250
|
+
if (!value) return false;
|
|
240
251
|
const chainRef = typeof chain === "string" ? chain.trim().toLowerCase() : "";
|
|
241
252
|
const namespace = chainRef.includes(":") ? chainRef.split(":")[0] : "";
|
|
242
|
-
if (validateWalletAddress(value))
|
|
243
|
-
|
|
244
|
-
if (namespace === "eip155")
|
|
245
|
-
return false;
|
|
253
|
+
if (validateWalletAddress(value)) return true;
|
|
254
|
+
if (namespace === "eip155") return false;
|
|
246
255
|
if (namespace === "solana") {
|
|
247
256
|
return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value);
|
|
248
257
|
}
|
|
@@ -271,34 +280,27 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
271
280
|
const chainStr = typeof chain === "string" && chain.trim().length > 0 ? chain.trim() : "eip155";
|
|
272
281
|
const namespace = chainStr.includes(":") ? chainStr.split(":")[0] || "eip155" : "eip155";
|
|
273
282
|
const resolveAddress = async () => {
|
|
274
|
-
if (typeof walletAddress === "string" && walletAddress.trim().length > 0)
|
|
275
|
-
return walletAddress;
|
|
283
|
+
if (typeof walletAddress === "string" && walletAddress.trim().length > 0) return walletAddress;
|
|
276
284
|
if (namespace === "solana") {
|
|
277
285
|
if (resolvedProvider?.publicKey && typeof resolvedProvider.publicKey.toBase58 === "function") {
|
|
278
286
|
const pk = resolvedProvider.publicKey.toBase58();
|
|
279
|
-
if (typeof pk === "string" && pk)
|
|
280
|
-
return pk;
|
|
287
|
+
if (typeof pk === "string" && pk) return pk;
|
|
281
288
|
}
|
|
282
289
|
if (typeof resolvedProvider.getAddress === "function") {
|
|
283
290
|
const addr = await resolvedProvider.getAddress().catch(() => null);
|
|
284
|
-
if (typeof addr === "string" && addr)
|
|
285
|
-
return addr;
|
|
291
|
+
if (typeof addr === "string" && addr) return addr;
|
|
286
292
|
}
|
|
287
|
-
if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
|
|
288
|
-
return resolvedProvider.address;
|
|
293
|
+
if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
|
|
289
294
|
return null;
|
|
290
295
|
}
|
|
291
|
-
if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
|
|
292
|
-
|
|
293
|
-
if (typeof resolvedProvider.getAddress === "function")
|
|
294
|
-
return await resolvedProvider.getAddress();
|
|
296
|
+
if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
|
|
297
|
+
if (typeof resolvedProvider.getAddress === "function") return resolvedProvider.getAddress();
|
|
295
298
|
if (typeof resolvedProvider.request === "function") {
|
|
296
299
|
let accounts = await resolvedProvider.request({ method: "eth_accounts" }).catch(() => []);
|
|
297
300
|
if (!Array.isArray(accounts) || accounts.length === 0) {
|
|
298
301
|
accounts = await resolvedProvider.request({ method: "eth_requestAccounts" }).catch(() => []);
|
|
299
302
|
}
|
|
300
|
-
if (Array.isArray(accounts) && accounts[0])
|
|
301
|
-
return accounts[0];
|
|
303
|
+
if (Array.isArray(accounts) && accounts[0]) return accounts[0];
|
|
302
304
|
}
|
|
303
305
|
return null;
|
|
304
306
|
};
|
|
@@ -306,16 +308,11 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
306
308
|
if (typeof resolvedProvider.signMessage === "function") {
|
|
307
309
|
const encoded = typeof msg === "string" ? new TextEncoder().encode(msg) : msg;
|
|
308
310
|
const result = await resolvedProvider.signMessage(encoded);
|
|
309
|
-
if (typeof result === "string" && result)
|
|
310
|
-
|
|
311
|
-
if (result instanceof Uint8Array)
|
|
312
|
-
|
|
313
|
-
if (result
|
|
314
|
-
return encodeBase58Bytes(new Uint8Array(result));
|
|
315
|
-
if (ArrayBuffer.isView(result))
|
|
316
|
-
return encodeBase58Bytes(result);
|
|
317
|
-
if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(result))
|
|
318
|
-
return encodeBase58Bytes(result);
|
|
311
|
+
if (typeof result === "string" && result) return result;
|
|
312
|
+
if (result instanceof Uint8Array) return encodeBase58Bytes(result);
|
|
313
|
+
if (result instanceof ArrayBuffer) return encodeBase58Bytes(new Uint8Array(result));
|
|
314
|
+
if (ArrayBuffer.isView(result)) return encodeBase58Bytes(result);
|
|
315
|
+
if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(result)) return encodeBase58Bytes(result);
|
|
319
316
|
}
|
|
320
317
|
throw new SDKError("Non-EVM signing requires provider.signMessage", "SIGNER_UNAVAILABLE");
|
|
321
318
|
}
|
|
@@ -324,16 +321,14 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
324
321
|
let firstPersonalSignError = null;
|
|
325
322
|
try {
|
|
326
323
|
const sig = await resolvedProvider.request({ method: "personal_sign", params: [msg, address] });
|
|
327
|
-
if (typeof sig === "string" && sig)
|
|
328
|
-
return sig;
|
|
324
|
+
if (typeof sig === "string" && sig) return sig;
|
|
329
325
|
} catch (error) {
|
|
330
326
|
firstPersonalSignError = error;
|
|
331
327
|
}
|
|
332
328
|
let secondPersonalSignError = null;
|
|
333
329
|
try {
|
|
334
330
|
const sig = await resolvedProvider.request({ method: "personal_sign", params: [address, msg] });
|
|
335
|
-
if (typeof sig === "string" && sig)
|
|
336
|
-
return sig;
|
|
331
|
+
if (typeof sig === "string" && sig) return sig;
|
|
337
332
|
} catch (error) {
|
|
338
333
|
secondPersonalSignError = error;
|
|
339
334
|
const signatureErrorMessage = String(
|
|
@@ -344,16 +339,14 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
344
339
|
try {
|
|
345
340
|
const hexMsg = toHexUtf8(msg);
|
|
346
341
|
const sig = await resolvedProvider.request({ method: "personal_sign", params: [hexMsg, address] });
|
|
347
|
-
if (typeof sig === "string" && sig)
|
|
348
|
-
return sig;
|
|
342
|
+
if (typeof sig === "string" && sig) return sig;
|
|
349
343
|
} catch {
|
|
350
344
|
}
|
|
351
345
|
}
|
|
352
346
|
}
|
|
353
347
|
try {
|
|
354
348
|
const sig = await resolvedProvider.request({ method: "eth_sign", params: [address, msg] });
|
|
355
|
-
if (typeof sig === "string" && sig)
|
|
356
|
-
return sig;
|
|
349
|
+
if (typeof sig === "string" && sig) return sig;
|
|
357
350
|
} catch {
|
|
358
351
|
}
|
|
359
352
|
if (secondPersonalSignError || firstPersonalSignError) {
|
|
@@ -366,13 +359,12 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
366
359
|
}
|
|
367
360
|
if (typeof resolvedProvider.signMessage === "function") {
|
|
368
361
|
const result = await resolvedProvider.signMessage(msg);
|
|
369
|
-
if (typeof result === "string" && result)
|
|
370
|
-
return result;
|
|
362
|
+
if (typeof result === "string" && result) return result;
|
|
371
363
|
}
|
|
372
364
|
throw new SDKError("Unable to sign message with provided wallet/provider", "SIGNER_UNAVAILABLE");
|
|
373
365
|
}
|
|
374
366
|
var NEUS_CONSTANTS = {
|
|
375
|
-
|
|
367
|
+
/** Default EVM chain id for NEUS protocol signing context (`HUB_CHAIN_ID` name kept for compatibility). */
|
|
376
368
|
HUB_CHAIN_ID: 84532,
|
|
377
369
|
// Supported target chains for cross-chain propagation
|
|
378
370
|
TESTNET_CHAINS: [
|
|
@@ -402,28 +394,28 @@ var NEUS_CONSTANTS = {
|
|
|
402
394
|
};
|
|
403
395
|
|
|
404
396
|
// client.js
|
|
405
|
-
var
|
|
406
|
-
"ownership-basic",
|
|
407
|
-
"ownership-pseudonym",
|
|
408
|
-
"ownership-dns-txt",
|
|
409
|
-
"ownership-social",
|
|
410
|
-
"ownership-org-oauth",
|
|
411
|
-
"contract-ownership",
|
|
412
|
-
"nft-ownership",
|
|
413
|
-
"token-holding",
|
|
414
|
-
"wallet-link",
|
|
415
|
-
"wallet-risk",
|
|
416
|
-
"proof-of-human",
|
|
417
|
-
"agent-identity",
|
|
418
|
-
"agent-delegation",
|
|
419
|
-
"ai-content-moderation"
|
|
420
|
-
|
|
421
|
-
var INTERACTIVE_VERIFIERS = /* @__PURE__ */ new Set([
|
|
422
|
-
"ownership-social",
|
|
423
|
-
"ownership-org-oauth",
|
|
424
|
-
"proof-of-human"
|
|
425
|
-
]);
|
|
397
|
+
var FALLBACK_PUBLIC_VERIFIER_CATALOG = {
|
|
398
|
+
"ownership-basic": { supportsDirectApi: true },
|
|
399
|
+
"ownership-pseudonym": { supportsDirectApi: true },
|
|
400
|
+
"ownership-dns-txt": { supportsDirectApi: true },
|
|
401
|
+
"ownership-social": { supportsDirectApi: false },
|
|
402
|
+
"ownership-org-oauth": { supportsDirectApi: false },
|
|
403
|
+
"contract-ownership": { supportsDirectApi: true },
|
|
404
|
+
"nft-ownership": { supportsDirectApi: true },
|
|
405
|
+
"token-holding": { supportsDirectApi: true },
|
|
406
|
+
"wallet-link": { supportsDirectApi: true },
|
|
407
|
+
"wallet-risk": { supportsDirectApi: true },
|
|
408
|
+
"proof-of-human": { supportsDirectApi: false },
|
|
409
|
+
"agent-identity": { supportsDirectApi: true },
|
|
410
|
+
"agent-delegation": { supportsDirectApi: true },
|
|
411
|
+
"ai-content-moderation": { supportsDirectApi: true }
|
|
412
|
+
};
|
|
426
413
|
var EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
414
|
+
var WALLET_LINK_RELATIONSHIP_TYPES = /* @__PURE__ */ new Set(["primary", "personal", "org", "affiliate", "agent", "linked"]);
|
|
415
|
+
function normalizeWalletLinkRelationshipType(value) {
|
|
416
|
+
const normalized = String(value || "").trim().toLowerCase();
|
|
417
|
+
return WALLET_LINK_RELATIONSHIP_TYPES.has(normalized) ? normalized : "linked";
|
|
418
|
+
}
|
|
427
419
|
var validateVerifierData = (verifierId, data) => {
|
|
428
420
|
if (!data || typeof data !== "object") {
|
|
429
421
|
return { valid: false, error: "Data object is required" };
|
|
@@ -641,7 +633,10 @@ var validateVerifierData = (verifierId, data) => {
|
|
|
641
633
|
const maxBytes = 50 * 1024;
|
|
642
634
|
const bytes = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(data.content).length : String(data.content).length;
|
|
643
635
|
if (bytes > maxBytes) {
|
|
644
|
-
return {
|
|
636
|
+
return {
|
|
637
|
+
valid: false,
|
|
638
|
+
error: `content exceeds ${maxBytes} bytes limit for ai-content-moderation verifier (text)`
|
|
639
|
+
};
|
|
645
640
|
}
|
|
646
641
|
} catch {
|
|
647
642
|
}
|
|
@@ -700,20 +695,15 @@ var NeusClient = class {
|
|
|
700
695
|
if (typeof this.config.appId === "string" && this.config.appId.trim().length > 0) {
|
|
701
696
|
this.defaultHeaders["X-Neus-App"] = this.config.appId.trim();
|
|
702
697
|
}
|
|
703
|
-
if (typeof this.config.sponsorGrant === "string" && this.config.sponsorGrant.trim().length > 0) {
|
|
704
|
-
this.defaultHeaders["X-Sponsor-Grant"] = this.config.sponsorGrant.trim();
|
|
705
|
-
}
|
|
706
698
|
if (typeof this.config.paymentSignature === "string" && this.config.paymentSignature.trim().length > 0) {
|
|
707
699
|
this.defaultHeaders["PAYMENT-SIGNATURE"] = this.config.paymentSignature.trim();
|
|
708
700
|
}
|
|
709
701
|
if (this.config.extraHeaders && typeof this.config.extraHeaders === "object") {
|
|
710
702
|
for (const [k, v] of Object.entries(this.config.extraHeaders)) {
|
|
711
|
-
if (!k || v === void 0 || v === null)
|
|
712
|
-
continue;
|
|
703
|
+
if (!k || v === void 0 || v === null) continue;
|
|
713
704
|
const key = String(k).trim();
|
|
714
705
|
const value = String(v).trim();
|
|
715
|
-
if (!key || !value)
|
|
716
|
-
continue;
|
|
706
|
+
if (!key || !value) continue;
|
|
717
707
|
this.defaultHeaders[key] = value;
|
|
718
708
|
}
|
|
719
709
|
}
|
|
@@ -726,14 +716,12 @@ var NeusClient = class {
|
|
|
726
716
|
}
|
|
727
717
|
_getHubChainId() {
|
|
728
718
|
const configured = Number(this.config?.hubChainId);
|
|
729
|
-
if (Number.isFinite(configured) && configured > 0)
|
|
730
|
-
return Math.floor(configured);
|
|
719
|
+
if (Number.isFinite(configured) && configured > 0) return Math.floor(configured);
|
|
731
720
|
return NEUS_CONSTANTS.HUB_CHAIN_ID;
|
|
732
721
|
}
|
|
733
722
|
_normalizeIdentity(value) {
|
|
734
723
|
let raw = String(value || "").trim();
|
|
735
|
-
if (!raw)
|
|
736
|
-
return "";
|
|
724
|
+
if (!raw) return "";
|
|
737
725
|
const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
|
|
738
726
|
if (didMatch && didMatch[3]) {
|
|
739
727
|
raw = String(didMatch[3]).trim();
|
|
@@ -741,8 +729,7 @@ var NeusClient = class {
|
|
|
741
729
|
return EVM_ADDRESS_RE.test(raw) ? raw.toLowerCase() : raw;
|
|
742
730
|
}
|
|
743
731
|
_inferChainForAddress(address, explicitChain) {
|
|
744
|
-
if (typeof explicitChain === "string" && explicitChain.includes(":"))
|
|
745
|
-
return explicitChain.trim();
|
|
732
|
+
if (typeof explicitChain === "string" && explicitChain.includes(":")) return explicitChain.trim();
|
|
746
733
|
const raw = String(address || "").trim();
|
|
747
734
|
const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
|
|
748
735
|
if (didMatch && didMatch[1] && didMatch[2]) {
|
|
@@ -781,8 +768,7 @@ var NeusClient = class {
|
|
|
781
768
|
throw new ConfigurationError("Invalid wallet provider");
|
|
782
769
|
}
|
|
783
770
|
_getDefaultBrowserWallet() {
|
|
784
|
-
if (typeof window === "undefined")
|
|
785
|
-
return null;
|
|
771
|
+
if (typeof window === "undefined") return null;
|
|
786
772
|
return window.ethereum || window.solana || window.phantom && window.phantom.solana || null;
|
|
787
773
|
}
|
|
788
774
|
async _buildPrivateGateAuth({ address, wallet, chain, signatureMethod } = {}) {
|
|
@@ -840,80 +826,134 @@ var NeusClient = class {
|
|
|
840
826
|
signatureMethod: params.signatureMethod
|
|
841
827
|
});
|
|
842
828
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
829
|
+
async createWalletLinkData(params = {}) {
|
|
830
|
+
const normalizedPrimary = this._normalizeIdentity(params.primaryWalletAddress);
|
|
831
|
+
const normalizedSecondary = this._normalizeIdentity(params.secondaryWalletAddress);
|
|
832
|
+
if (!EVM_ADDRESS_RE.test(normalizedPrimary)) {
|
|
833
|
+
throw new ValidationError("wallet-link requires a valid primaryWalletAddress");
|
|
834
|
+
}
|
|
835
|
+
if (!EVM_ADDRESS_RE.test(normalizedSecondary)) {
|
|
836
|
+
throw new ValidationError("wallet-link requires a valid secondaryWalletAddress");
|
|
837
|
+
}
|
|
838
|
+
if (normalizedPrimary === normalizedSecondary) {
|
|
839
|
+
throw new ValidationError("wallet-link secondaryWalletAddress must differ from primaryWalletAddress");
|
|
840
|
+
}
|
|
841
|
+
const providerWallet = params.wallet || this._getDefaultBrowserWallet();
|
|
842
|
+
const { signerWalletAddress, provider } = await this._resolveWalletSigner(providerWallet);
|
|
843
|
+
const normalizedSigner = this._normalizeIdentity(signerWalletAddress);
|
|
844
|
+
if (!EVM_ADDRESS_RE.test(normalizedSigner)) {
|
|
845
|
+
throw new ValidationError("wallet-link requires an EVM wallet/provider for the secondary wallet");
|
|
846
|
+
}
|
|
847
|
+
if (normalizedSigner !== normalizedSecondary) {
|
|
848
|
+
throw new ValidationError("wallet-link wallet/provider must be connected to secondaryWalletAddress");
|
|
849
|
+
}
|
|
850
|
+
const resolvedChain = (() => {
|
|
851
|
+
const raw = String(params.chain || "").trim();
|
|
852
|
+
if (!raw) return `eip155:${this._getHubChainId()}`;
|
|
853
|
+
if (!/^eip155:\d+$/.test(raw)) {
|
|
854
|
+
throw new ValidationError("wallet-link requires chain in the form eip155:<chainId>");
|
|
855
|
+
}
|
|
856
|
+
return raw;
|
|
857
|
+
})();
|
|
858
|
+
const signedTimestamp = Number.isFinite(Number(params.signedTimestamp)) && Number(params.signedTimestamp) > 0 ? Number(params.signedTimestamp) : Date.now();
|
|
859
|
+
const linkData = {
|
|
860
|
+
primaryAccountId: `${resolvedChain}:${normalizedPrimary}`,
|
|
861
|
+
secondaryAccountId: `${resolvedChain}:${normalizedSecondary}`,
|
|
862
|
+
primaryWalletAddress: normalizedPrimary,
|
|
863
|
+
secondaryWalletAddress: normalizedSecondary
|
|
864
|
+
};
|
|
865
|
+
const message = constructVerificationMessage({
|
|
866
|
+
walletAddress: normalizedSecondary,
|
|
867
|
+
signedTimestamp,
|
|
868
|
+
data: linkData,
|
|
869
|
+
verifierIds: ["wallet-link"],
|
|
870
|
+
chain: resolvedChain
|
|
871
|
+
});
|
|
872
|
+
let signature;
|
|
873
|
+
try {
|
|
874
|
+
signature = await signMessage({
|
|
875
|
+
provider,
|
|
876
|
+
message,
|
|
877
|
+
walletAddress: signerWalletAddress
|
|
878
|
+
});
|
|
879
|
+
} catch (error) {
|
|
880
|
+
if (error?.code === 4001) {
|
|
881
|
+
throw new ValidationError("User rejected wallet-link signature request");
|
|
882
|
+
}
|
|
883
|
+
throw new ValidationError(`Failed to sign wallet-link message: ${error?.message || String(error)}`);
|
|
884
|
+
}
|
|
885
|
+
const label = String(params.label || "").trim().slice(0, 64);
|
|
886
|
+
return {
|
|
887
|
+
primaryWalletAddress: normalizedPrimary,
|
|
888
|
+
secondaryWalletAddress: normalizedSecondary,
|
|
889
|
+
signature,
|
|
890
|
+
chain: resolvedChain,
|
|
891
|
+
signatureMethod: "eip191",
|
|
892
|
+
signedTimestamp,
|
|
893
|
+
relationshipType: normalizeWalletLinkRelationshipType(params.relationshipType),
|
|
894
|
+
...label ? { label } : {}
|
|
895
|
+
};
|
|
896
|
+
}
|
|
846
897
|
/**
|
|
847
|
-
*
|
|
848
|
-
*
|
|
849
|
-
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
898
|
+
* Create a verification proof.
|
|
899
|
+
*
|
|
900
|
+
* Supports two paths:
|
|
901
|
+
* - **Auto:** Supply `verifier`, `content`, and/or `data` with an optional
|
|
902
|
+
* `wallet` provider. The SDK performs signing in the client.
|
|
903
|
+
* - **Manual:** Supply pre-signed `verifierIds`, `data`, `walletAddress`,
|
|
904
|
+
* `signature`, and `signedTimestamp`.
|
|
905
|
+
*
|
|
853
906
|
* @param {Object} params - Verification parameters
|
|
907
|
+
* @param {string} [params.verifier] - Verifier ID (auto path, e.g. 'ownership-basic')
|
|
908
|
+
* @param {string} [params.content] - Content to verify (auto path)
|
|
909
|
+
* @param {Object} [params.data] - Structured verification data
|
|
910
|
+
* @param {Object} [params.wallet] - Wallet provider (auto path)
|
|
911
|
+
* @param {Object} [params.options] - Additional options
|
|
854
912
|
* @param {Array<string>} [params.verifierIds] - Array of verifier IDs (manual path)
|
|
855
|
-
* @param {Object} [params.data] - Verification data object (manual path)
|
|
856
913
|
* @param {string} [params.walletAddress] - Wallet address that signed the request (manual path)
|
|
857
914
|
* @param {string} [params.signature] - EIP-191 signature (manual path)
|
|
858
915
|
* @param {number} [params.signedTimestamp] - Unix timestamp when signature was created (manual path)
|
|
859
|
-
* @param {number} [params.chainId] -
|
|
860
|
-
* @
|
|
861
|
-
*
|
|
862
|
-
* @param {string} [params.content] - Content/description (auto path)
|
|
863
|
-
* @param {Object} [params.wallet] - Optional injected wallet/provider (auto path)
|
|
864
|
-
* @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
|
|
865
|
-
*
|
|
916
|
+
* @param {number} [params.chainId] - EVM signing-context hint; when omitted, resolved to the NEUS protocol primary chain for signing
|
|
917
|
+
* @returns {Promise<Object>} Verification result with proofId
|
|
918
|
+
*
|
|
866
919
|
* @example
|
|
920
|
+
* // Auto path
|
|
921
|
+
* const proof = await client.verify({
|
|
922
|
+
* verifier: 'ownership-basic',
|
|
923
|
+
* content: 'Hello World',
|
|
924
|
+
* wallet: window.ethereum
|
|
925
|
+
* });
|
|
926
|
+
*
|
|
927
|
+
* @example
|
|
928
|
+
* // Manual path
|
|
867
929
|
* const proof = await client.verify({
|
|
868
930
|
* verifierIds: ['ownership-basic'],
|
|
869
|
-
* data: {
|
|
870
|
-
* content: "My content",
|
|
871
|
-
* owner: walletAddress, // or ownerAddress for nft-ownership/token-holding
|
|
872
|
-
* reference: { type: 'other', id: 'my-unique-identifier' }
|
|
873
|
-
* },
|
|
931
|
+
* data: { content: "My content", owner: walletAddress },
|
|
874
932
|
* walletAddress: '0x...',
|
|
875
933
|
* signature: '0x...',
|
|
876
934
|
* signedTimestamp: Date.now(),
|
|
877
935
|
* options: { targetChains: [421614, 11155111] }
|
|
878
936
|
* });
|
|
879
937
|
*/
|
|
880
|
-
/**
|
|
881
|
-
* Create a verification proof
|
|
882
|
-
*
|
|
883
|
-
* @param {Object} params - Verification parameters
|
|
884
|
-
* @param {string} [params.verifier] - Verifier ID (e.g., 'ownership-basic')
|
|
885
|
-
* @param {string} [params.content] - Content to verify
|
|
886
|
-
* @param {Object} [params.data] - Structured verification data
|
|
887
|
-
* @param {Object} [params.wallet] - Wallet provider
|
|
888
|
-
* @param {Object} [params.options] - Additional options
|
|
889
|
-
* @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
|
|
890
|
-
*
|
|
891
|
-
* @example
|
|
892
|
-
* // Simple ownership proof
|
|
893
|
-
* const proof = await client.verify({
|
|
894
|
-
* verifier: 'ownership-basic',
|
|
895
|
-
* content: 'Hello World',
|
|
896
|
-
* wallet: window.ethereum
|
|
897
|
-
* });
|
|
898
|
-
*/
|
|
899
938
|
async verify(params) {
|
|
900
939
|
if ((!params?.signature || !params?.walletAddress) && (params?.verifier || params?.content || params?.data)) {
|
|
901
940
|
const { content, verifier = "ownership-basic", data: data2 = null, wallet = null, options: options2 = {} } = params;
|
|
902
941
|
if (verifier === "ownership-basic" && !data2 && (!content || typeof content !== "string")) {
|
|
903
942
|
throw new ValidationError("content is required and must be a string (or use data param with owner + reference)");
|
|
904
943
|
}
|
|
905
|
-
let
|
|
944
|
+
let verifierCatalog = FALLBACK_PUBLIC_VERIFIER_CATALOG;
|
|
906
945
|
try {
|
|
907
|
-
const discovered = await this.
|
|
908
|
-
if (
|
|
909
|
-
|
|
946
|
+
const discovered = await this.getVerifierCatalog();
|
|
947
|
+
if (discovered && discovered.metadata && Object.keys(discovered.metadata).length > 0) {
|
|
948
|
+
verifierCatalog = discovered.metadata;
|
|
910
949
|
}
|
|
911
950
|
} catch {
|
|
912
951
|
}
|
|
952
|
+
const validVerifiers = Object.keys(verifierCatalog);
|
|
913
953
|
if (!validVerifiers.includes(verifier)) {
|
|
914
954
|
throw new ValidationError(`Invalid verifier '${verifier}'. Must be one of: ${validVerifiers.join(", ")}.`);
|
|
915
955
|
}
|
|
916
|
-
if (
|
|
956
|
+
if (verifierCatalog?.[verifier]?.supportsDirectApi === false) {
|
|
917
957
|
const hostedCheckoutUrl = options2?.hostedCheckoutUrl || "https://neus.network/verify";
|
|
918
958
|
throw new ValidationError(
|
|
919
959
|
`${verifier} requires hosted interactive checkout. Use VerifyGate or redirect to ${hostedCheckoutUrl}.`
|
|
@@ -1054,7 +1094,10 @@ var NeusClient = class {
|
|
|
1054
1094
|
...data2?.agentLabel && { agentLabel: data2.agentLabel },
|
|
1055
1095
|
...data2?.agentType && { agentType: data2.agentType },
|
|
1056
1096
|
...data2?.description && { description: data2.description },
|
|
1057
|
-
...data2?.capabilities && { capabilities: data2.capabilities }
|
|
1097
|
+
...data2?.capabilities && { capabilities: data2.capabilities },
|
|
1098
|
+
...data2?.instructions && { instructions: data2.instructions },
|
|
1099
|
+
...data2?.skills && { skills: data2.skills },
|
|
1100
|
+
...data2?.services && { services: data2.services }
|
|
1058
1101
|
};
|
|
1059
1102
|
} else if (verifier === "agent-delegation") {
|
|
1060
1103
|
if (!data2?.agentWallet) {
|
|
@@ -1067,7 +1110,11 @@ var NeusClient = class {
|
|
|
1067
1110
|
...data2?.scope && { scope: data2.scope },
|
|
1068
1111
|
...data2?.permissions && { permissions: data2.permissions },
|
|
1069
1112
|
...data2?.maxSpend && { maxSpend: data2.maxSpend },
|
|
1070
|
-
...data2?.
|
|
1113
|
+
...data2?.allowedPaymentTypes && { allowedPaymentTypes: data2.allowedPaymentTypes },
|
|
1114
|
+
...data2?.receiptDisclosure && { receiptDisclosure: data2.receiptDisclosure },
|
|
1115
|
+
...data2?.expiresAt && { expiresAt: data2.expiresAt },
|
|
1116
|
+
...data2?.instructions && { instructions: data2.instructions },
|
|
1117
|
+
...data2?.skills && { skills: data2.skills }
|
|
1071
1118
|
};
|
|
1072
1119
|
} else if (verifier === "ai-content-moderation") {
|
|
1073
1120
|
if (!data2?.content) {
|
|
@@ -1127,31 +1174,24 @@ var NeusClient = class {
|
|
|
1127
1174
|
const enc = new TextEncoder();
|
|
1128
1175
|
const bytes = enc.encode(s);
|
|
1129
1176
|
let hex = "0x";
|
|
1130
|
-
for (let i = 0; i < bytes.length; i++)
|
|
1131
|
-
hex += bytes[i].toString(16).padStart(2, "0");
|
|
1177
|
+
for (let i = 0; i < bytes.length; i++) hex += bytes[i].toString(16).padStart(2, "0");
|
|
1132
1178
|
return hex;
|
|
1133
1179
|
} catch {
|
|
1134
1180
|
let hex = "0x";
|
|
1135
|
-
for (let i = 0; i < s.length; i++)
|
|
1136
|
-
hex += s.charCodeAt(i).toString(16).padStart(2, "0");
|
|
1181
|
+
for (let i = 0; i < s.length; i++) hex += s.charCodeAt(i).toString(16).padStart(2, "0");
|
|
1137
1182
|
return hex;
|
|
1138
1183
|
}
|
|
1139
1184
|
};
|
|
1140
1185
|
const isFarcasterWallet = (() => {
|
|
1141
|
-
if (typeof window === "undefined")
|
|
1142
|
-
return false;
|
|
1186
|
+
if (typeof window === "undefined") return false;
|
|
1143
1187
|
try {
|
|
1144
1188
|
const w = window;
|
|
1145
1189
|
const fc = w.farcaster;
|
|
1146
|
-
if (!fc || !fc.context)
|
|
1147
|
-
return false;
|
|
1190
|
+
if (!fc || !fc.context) return false;
|
|
1148
1191
|
const fcProvider = fc.provider || fc.walletProvider || fc.context && fc.context.walletProvider;
|
|
1149
|
-
if (fcProvider === provider)
|
|
1150
|
-
|
|
1151
|
-
if (w.
|
|
1152
|
-
return true;
|
|
1153
|
-
if (w.ethereum === provider && fc && fc.context)
|
|
1154
|
-
return true;
|
|
1192
|
+
if (fcProvider === provider) return true;
|
|
1193
|
+
if (w.mini && w.mini.wallet === provider && fc && fc.context) return true;
|
|
1194
|
+
if (w.ethereum === provider && fc && fc.context) return true;
|
|
1155
1195
|
} catch {
|
|
1156
1196
|
}
|
|
1157
1197
|
return false;
|
|
@@ -1170,7 +1210,8 @@ var NeusClient = class {
|
|
|
1170
1210
|
const msg = String(e && (e.message || e.reason) || e || "").toLowerCase();
|
|
1171
1211
|
const errCode = e && (e.code || e.error && e.error.code) || null;
|
|
1172
1212
|
const needsHex = /byte|bytes|invalid byte sequence|encoding|non-hex/i.test(msg);
|
|
1173
|
-
const
|
|
1213
|
+
const unsupportedRe = /method.*not.*supported|unsupported|not implemented|method not found|unknown method|does not support/i;
|
|
1214
|
+
const methodUnsupported = unsupportedRe.test(msg) || errCode === -32601 || errCode === 4200 || msg.includes("personal_sign") && msg.includes("not") || msg.includes("request method") && msg.includes("not supported");
|
|
1174
1215
|
if (methodUnsupported) {
|
|
1175
1216
|
this._log("personal_sign not supported; attempting eth_sign fallback");
|
|
1176
1217
|
try {
|
|
@@ -1179,28 +1220,23 @@ var NeusClient = class {
|
|
|
1179
1220
|
const prefix = `Ethereum Signed Message:
|
|
1180
1221
|
${bytes.length}`;
|
|
1181
1222
|
const full = new Uint8Array(prefix.length + bytes.length);
|
|
1182
|
-
for (let i = 0; i < prefix.length; i++)
|
|
1183
|
-
full[i] = prefix.charCodeAt(i);
|
|
1223
|
+
for (let i = 0; i < prefix.length; i++) full[i] = prefix.charCodeAt(i);
|
|
1184
1224
|
full.set(bytes, prefix.length);
|
|
1185
1225
|
let payloadHex = "0x";
|
|
1186
|
-
for (let i = 0; i < full.length; i++)
|
|
1187
|
-
payloadHex += full[i].toString(16).padStart(2, "0");
|
|
1226
|
+
for (let i = 0; i < full.length; i++) payloadHex += full[i].toString(16).padStart(2, "0");
|
|
1188
1227
|
try {
|
|
1189
|
-
if (typeof window !== "undefined")
|
|
1190
|
-
window.__NEUS_ALLOW_ETH_SIGN__ = true;
|
|
1228
|
+
if (typeof window !== "undefined") window.__NEUS_ALLOW_ETH_SIGN__ = true;
|
|
1191
1229
|
} catch {
|
|
1192
1230
|
}
|
|
1193
1231
|
signature2 = await provider.request({ method: "eth_sign", params: [walletAddress2, payloadHex], neusAllowEthSign: true });
|
|
1194
1232
|
try {
|
|
1195
|
-
if (typeof window !== "undefined")
|
|
1196
|
-
delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1233
|
+
if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1197
1234
|
} catch {
|
|
1198
1235
|
}
|
|
1199
1236
|
} catch (fallbackErr) {
|
|
1200
1237
|
this._log("eth_sign fallback failed", { message: fallbackErr?.message || String(fallbackErr) });
|
|
1201
1238
|
try {
|
|
1202
|
-
if (typeof window !== "undefined")
|
|
1203
|
-
delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1239
|
+
if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
|
|
1204
1240
|
} catch {
|
|
1205
1241
|
}
|
|
1206
1242
|
throw e;
|
|
@@ -1242,8 +1278,7 @@ ${bytes.length}`;
|
|
|
1242
1278
|
} = params;
|
|
1243
1279
|
const resolvedChainId = chainId || (chain ? null : NEUS_CONSTANTS.HUB_CHAIN_ID);
|
|
1244
1280
|
const normalizeVerifierId = (id) => {
|
|
1245
|
-
if (typeof id !== "string")
|
|
1246
|
-
return id;
|
|
1281
|
+
if (typeof id !== "string") return id;
|
|
1247
1282
|
const match = id.match(/^(.*)@\d+$/);
|
|
1248
1283
|
return match ? match[1] : id;
|
|
1249
1284
|
};
|
|
@@ -1278,10 +1313,9 @@ ${bytes.length}`;
|
|
|
1278
1313
|
// Privacy and storage options (defaults)
|
|
1279
1314
|
privacyLevel: options?.privacyLevel || "private",
|
|
1280
1315
|
publicDisplay: options?.publicDisplay || false,
|
|
1281
|
-
storeOriginalContent: options?.storeOriginalContent
|
|
1316
|
+
storeOriginalContent: typeof options?.storeOriginalContent === "boolean" ? options.storeOriginalContent : true
|
|
1282
1317
|
};
|
|
1283
|
-
if (typeof options?.enableIpfs === "boolean")
|
|
1284
|
-
optionsPayload.enableIpfs = options.enableIpfs;
|
|
1318
|
+
if (typeof options?.enableIpfs === "boolean") optionsPayload.enableIpfs = options.enableIpfs;
|
|
1285
1319
|
const requestData = {
|
|
1286
1320
|
verifierIds: normalizedVerifierIds,
|
|
1287
1321
|
data,
|
|
@@ -1299,41 +1333,37 @@ ${bytes.length}`;
|
|
|
1299
1333
|
}
|
|
1300
1334
|
return this._formatResponse(response);
|
|
1301
1335
|
}
|
|
1302
|
-
// ============================================================================
|
|
1303
|
-
// STATUS AND UTILITY METHODS
|
|
1304
|
-
// ============================================================================
|
|
1305
1336
|
/**
|
|
1306
|
-
* Get
|
|
1337
|
+
* Get proof record by proof receipt id.
|
|
1307
1338
|
*
|
|
1308
|
-
* @param {string} proofId - Proof ID (
|
|
1309
|
-
* @returns {Promise<Object>}
|
|
1339
|
+
* @param {string} proofId - Proof receipt ID (0x + 64 hex).
|
|
1340
|
+
* @returns {Promise<Object>} Proof record and verification state
|
|
1310
1341
|
*
|
|
1311
1342
|
* @example
|
|
1312
|
-
* const result = await client.
|
|
1343
|
+
* const result = await client.getProof('0x...');
|
|
1313
1344
|
* console.log('Status:', result.status);
|
|
1314
1345
|
*/
|
|
1315
|
-
async
|
|
1346
|
+
async getProof(proofId) {
|
|
1316
1347
|
if (!proofId || typeof proofId !== "string") {
|
|
1317
1348
|
throw new ValidationError("proofId is required");
|
|
1318
1349
|
}
|
|
1319
|
-
const response = await this._makeRequest("GET", `/api/v1/
|
|
1350
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`);
|
|
1320
1351
|
if (!response.success) {
|
|
1321
|
-
throw new ApiError(`Failed to get
|
|
1352
|
+
throw new ApiError(`Failed to get proof: ${response.error?.message || "Unknown error"}`, response.error);
|
|
1322
1353
|
}
|
|
1323
1354
|
return this._formatResponse(response);
|
|
1324
1355
|
}
|
|
1325
1356
|
/**
|
|
1326
|
-
* Get private proof
|
|
1357
|
+
* Get private proof record with wallet signature
|
|
1327
1358
|
*
|
|
1328
|
-
* @param {string} proofId - Proof ID
|
|
1359
|
+
* @param {string} proofId - Proof receipt ID.
|
|
1329
1360
|
* @param {Object} wallet - Wallet provider (window.ethereum or ethers Wallet)
|
|
1330
|
-
* @returns {Promise<Object>} Private
|
|
1361
|
+
* @returns {Promise<Object>} Private proof record and verification state
|
|
1331
1362
|
*
|
|
1332
1363
|
* @example
|
|
1333
|
-
*
|
|
1334
|
-
* const privateData = await client.getPrivateStatus(proofId, window.ethereum);
|
|
1364
|
+
* const privateData = await client.getPrivateProof(proofId, window.ethereum);
|
|
1335
1365
|
*/
|
|
1336
|
-
async
|
|
1366
|
+
async getPrivateProof(proofId, wallet = null) {
|
|
1337
1367
|
if (!proofId || typeof proofId !== "string") {
|
|
1338
1368
|
throw new ValidationError("proofId is required");
|
|
1339
1369
|
}
|
|
@@ -1347,7 +1377,7 @@ ${bytes.length}`;
|
|
|
1347
1377
|
...typeof auth.chain === "string" && auth.chain.trim() ? { "x-chain": auth.chain.trim() } : {},
|
|
1348
1378
|
...typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? { "x-signature-method": auth.signatureMethod.trim() } : {}
|
|
1349
1379
|
};
|
|
1350
|
-
const response2 = await this._makeRequest("GET", `/api/v1/
|
|
1380
|
+
const response2 = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, headers);
|
|
1351
1381
|
if (!response2.success) {
|
|
1352
1382
|
throw new ApiError(
|
|
1353
1383
|
`Failed to access private proof: ${response2.error?.message || "Unauthorized"}`,
|
|
@@ -1386,7 +1416,7 @@ ${bytes.length}`;
|
|
|
1386
1416
|
}
|
|
1387
1417
|
throw new ValidationError(`Failed to sign message: ${error.message}`);
|
|
1388
1418
|
}
|
|
1389
|
-
const response = await this._makeRequest("GET", `/api/v1/
|
|
1419
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, {
|
|
1390
1420
|
"x-wallet-address": walletAddress,
|
|
1391
1421
|
"x-signature": signature,
|
|
1392
1422
|
"x-signed-timestamp": signedTimestamp.toString(),
|
|
@@ -1419,25 +1449,37 @@ ${bytes.length}`;
|
|
|
1419
1449
|
* @returns {Promise<string[]>} Array of verifier IDs
|
|
1420
1450
|
*/
|
|
1421
1451
|
async getVerifiers() {
|
|
1452
|
+
const catalog = await this.getVerifierCatalog();
|
|
1453
|
+
return Array.isArray(catalog?.data) ? catalog.data : [];
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Get the public verifier catalog with per-verifier capabilities.
|
|
1457
|
+
* @returns {Promise<{data: string[], metadata: Record<string, { supportsDirectApi?: boolean }>, meta?: object}>}
|
|
1458
|
+
*/
|
|
1459
|
+
async getVerifierCatalog() {
|
|
1422
1460
|
const response = await this._makeRequest("GET", "/api/v1/verification/verifiers");
|
|
1423
1461
|
if (!response.success) {
|
|
1424
1462
|
throw new ApiError(`Failed to get verifiers: ${response.error?.message || "Unknown error"}`, response.error);
|
|
1425
1463
|
}
|
|
1426
|
-
return
|
|
1464
|
+
return {
|
|
1465
|
+
data: Array.isArray(response.data) ? response.data : [],
|
|
1466
|
+
metadata: response.metadata && typeof response.metadata === "object" && !Array.isArray(response.metadata) ? response.metadata : {},
|
|
1467
|
+
meta: response.meta && typeof response.meta === "object" && !Array.isArray(response.meta) ? response.meta : {}
|
|
1468
|
+
};
|
|
1427
1469
|
}
|
|
1428
1470
|
/**
|
|
1429
1471
|
* POLL PROOF STATUS - Wait for verification completion
|
|
1430
|
-
*
|
|
1472
|
+
*
|
|
1431
1473
|
* Polls the verification status until it reaches a terminal state (completed or failed).
|
|
1432
1474
|
* Useful for providing real-time feedback to users during verification.
|
|
1433
|
-
*
|
|
1434
|
-
* @param {string} proofId - Proof ID to poll
|
|
1475
|
+
*
|
|
1476
|
+
* @param {string} proofId - Proof ID to poll.
|
|
1435
1477
|
* @param {Object} [options] - Polling options
|
|
1436
1478
|
* @param {number} [options.interval=5000] - Polling interval in ms
|
|
1437
1479
|
* @param {number} [options.timeout=120000] - Total timeout in ms
|
|
1438
1480
|
* @param {Function} [options.onProgress] - Progress callback function
|
|
1439
1481
|
* @returns {Promise<Object>} Final verification status
|
|
1440
|
-
*
|
|
1482
|
+
*
|
|
1441
1483
|
* @example
|
|
1442
1484
|
* const finalStatus = await client.pollProofStatus(proofId, {
|
|
1443
1485
|
* interval: 3000,
|
|
@@ -1463,7 +1505,7 @@ ${bytes.length}`;
|
|
|
1463
1505
|
let consecutiveRateLimits = 0;
|
|
1464
1506
|
while (Date.now() - startTime < timeout) {
|
|
1465
1507
|
try {
|
|
1466
|
-
const status = await this.
|
|
1508
|
+
const status = await this.getProof(proofId);
|
|
1467
1509
|
consecutiveRateLimits = 0;
|
|
1468
1510
|
if (onProgress && typeof onProgress === "function") {
|
|
1469
1511
|
onProgress(status.data || status);
|
|
@@ -1496,7 +1538,7 @@ ${bytes.length}`;
|
|
|
1496
1538
|
}
|
|
1497
1539
|
/**
|
|
1498
1540
|
* DETECT CHAIN ID - Get current wallet chain
|
|
1499
|
-
*
|
|
1541
|
+
*
|
|
1500
1542
|
* @returns {Promise<number>} Current chain ID
|
|
1501
1543
|
*/
|
|
1502
1544
|
async detectChainId() {
|
|
@@ -1527,7 +1569,6 @@ ${bytes.length}`;
|
|
|
1527
1569
|
const message = constructVerificationMessage({
|
|
1528
1570
|
walletAddress: address,
|
|
1529
1571
|
signedTimestamp,
|
|
1530
|
-
// Keep wire payload key `qHash` for backwards compatibility.
|
|
1531
1572
|
data: { action: "revoke_proof", qHash: proofId },
|
|
1532
1573
|
verifierIds: ["ownership-basic"],
|
|
1533
1574
|
...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
|
|
@@ -1546,9 +1587,8 @@ ${bytes.length}`;
|
|
|
1546
1587
|
}
|
|
1547
1588
|
throw new ValidationError(`Failed to sign revocation: ${error.message}`);
|
|
1548
1589
|
}
|
|
1549
|
-
const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/${proofId}
|
|
1590
|
+
const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/revoke-self/${proofId}`, {
|
|
1550
1591
|
method: "POST",
|
|
1551
|
-
// SECURITY: Do not put proof signatures into Authorization headers.
|
|
1552
1592
|
headers: { "Content-Type": "application/json" },
|
|
1553
1593
|
body: JSON.stringify({
|
|
1554
1594
|
walletAddress: address,
|
|
@@ -1563,18 +1603,16 @@ ${bytes.length}`;
|
|
|
1563
1603
|
}
|
|
1564
1604
|
return true;
|
|
1565
1605
|
}
|
|
1566
|
-
// ============================================================================
|
|
1567
|
-
// PROOFS & GATING METHODS
|
|
1568
|
-
// ============================================================================
|
|
1569
1606
|
/**
|
|
1570
1607
|
* GET PROOFS BY WALLET - Fetch proofs for a wallet address
|
|
1571
|
-
*
|
|
1608
|
+
*
|
|
1572
1609
|
* @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
|
|
1573
1610
|
* @param {Object} [options] - Filter options
|
|
1574
1611
|
* @param {number} [options.limit] - Max results (default: 50; higher limits require owner access)
|
|
1575
1612
|
* @param {number} [options.offset] - Pagination offset (default: 0)
|
|
1613
|
+
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
1576
1614
|
* @returns {Promise<Object>} Proofs result
|
|
1577
|
-
*
|
|
1615
|
+
*
|
|
1578
1616
|
* @example
|
|
1579
1617
|
* const result = await client.getProofsByWallet('0x...', {
|
|
1580
1618
|
* limit: 50,
|
|
@@ -1588,14 +1626,13 @@ ${bytes.length}`;
|
|
|
1588
1626
|
const id = walletAddress.trim();
|
|
1589
1627
|
const pathId = /^0x[a-fA-F0-9]{40}$/i.test(id) ? id.toLowerCase() : id;
|
|
1590
1628
|
const qs = [];
|
|
1591
|
-
if (options.limit)
|
|
1592
|
-
|
|
1593
|
-
if (options.
|
|
1594
|
-
qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
1629
|
+
if (options.limit) qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
|
|
1630
|
+
if (options.offset) qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
1631
|
+
if (options.qHash) qs.push(`qHash=${encodeURIComponent(options.qHash.toLowerCase())}`);
|
|
1595
1632
|
const query = qs.length ? `?${qs.join("&")}` : "";
|
|
1596
1633
|
const response = await this._makeRequest(
|
|
1597
1634
|
"GET",
|
|
1598
|
-
`/api/v1/proofs/
|
|
1635
|
+
`/api/v1/proofs/by-wallet/${encodeURIComponent(pathId)}${query}`
|
|
1599
1636
|
);
|
|
1600
1637
|
if (!response.success) {
|
|
1601
1638
|
throw new ApiError(`Failed to get proofs: ${response.error?.message || "Unknown error"}`, response.error);
|
|
@@ -1618,6 +1655,7 @@ ${bytes.length}`;
|
|
|
1618
1655
|
* @param {Object} [options]
|
|
1619
1656
|
* @param {number} [options.limit] - Max results (server enforces caps)
|
|
1620
1657
|
* @param {number} [options.offset] - Pagination offset
|
|
1658
|
+
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
1621
1659
|
* @param {Object} [wallet] - Optional injected wallet/provider (MetaMask/ethers Wallet)
|
|
1622
1660
|
*/
|
|
1623
1661
|
async getPrivateProofsByWallet(walletAddress, options = {}, wallet = null) {
|
|
@@ -1668,12 +1706,11 @@ ${bytes.length}`;
|
|
|
1668
1706
|
throw new ValidationError(`Failed to sign message: ${error.message}`);
|
|
1669
1707
|
}
|
|
1670
1708
|
const qs = [];
|
|
1671
|
-
if (options.limit)
|
|
1672
|
-
|
|
1673
|
-
if (options.
|
|
1674
|
-
qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
1709
|
+
if (options.limit) qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
|
|
1710
|
+
if (options.offset) qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
|
|
1711
|
+
if (options.qHash) qs.push(`qHash=${encodeURIComponent(options.qHash.toLowerCase())}`);
|
|
1675
1712
|
const query = qs.length ? `?${qs.join("&")}` : "";
|
|
1676
|
-
const response = await this._makeRequest("GET", `/api/v1/proofs/
|
|
1713
|
+
const response = await this._makeRequest("GET", `/api/v1/proofs/by-wallet/${encodeURIComponent(pathId)}${query}`, null, {
|
|
1677
1714
|
"x-wallet-address": signerWalletAddress,
|
|
1678
1715
|
"x-signature": signature,
|
|
1679
1716
|
"x-signed-timestamp": signedTimestamp.toString(),
|
|
@@ -1692,16 +1729,16 @@ ${bytes.length}`;
|
|
|
1692
1729
|
};
|
|
1693
1730
|
}
|
|
1694
1731
|
/**
|
|
1695
|
-
*
|
|
1732
|
+
* Gate check (HTTP API) — minimal eligibility response.
|
|
1696
1733
|
*
|
|
1697
1734
|
* Calls the gate endpoint and returns a **minimal** yes/no response.
|
|
1698
|
-
* By default this checks **public +
|
|
1735
|
+
* By default this checks **public + unlisted** proofs.
|
|
1699
1736
|
*
|
|
1700
1737
|
* When `includePrivate=true`, this can perform owner-signed private checks
|
|
1701
1738
|
* (no full proof payloads returned) by providing a wallet/provider.
|
|
1702
1739
|
*
|
|
1703
|
-
* Prefer this over `checkGate()`
|
|
1704
|
-
*
|
|
1740
|
+
* Prefer this over `checkGate()` when you need the smallest, most stable
|
|
1741
|
+
* response shape and do not need full proof payloads.
|
|
1705
1742
|
*
|
|
1706
1743
|
* @param {Object} params - Gate check query params
|
|
1707
1744
|
* @param {string} params.address - Wallet identity to check (EVM/Solana/DID)
|
|
@@ -1724,25 +1761,20 @@ ${bytes.length}`;
|
|
|
1724
1761
|
const qs = new URLSearchParams();
|
|
1725
1762
|
qs.set("address", address);
|
|
1726
1763
|
const setIfPresent = (key, value) => {
|
|
1727
|
-
if (value === void 0 || value === null)
|
|
1728
|
-
return;
|
|
1764
|
+
if (value === void 0 || value === null) return;
|
|
1729
1765
|
const str = typeof value === "string" ? value : String(value);
|
|
1730
|
-
if (str.length === 0)
|
|
1731
|
-
return;
|
|
1766
|
+
if (str.length === 0) return;
|
|
1732
1767
|
qs.set(key, str);
|
|
1733
1768
|
};
|
|
1734
1769
|
const setBoolIfPresent = (key, value) => {
|
|
1735
|
-
if (value === void 0 || value === null)
|
|
1736
|
-
return;
|
|
1770
|
+
if (value === void 0 || value === null) return;
|
|
1737
1771
|
qs.set(key, value ? "true" : "false");
|
|
1738
1772
|
};
|
|
1739
1773
|
const setCsvIfPresent = (key, value) => {
|
|
1740
|
-
if (value === void 0 || value === null)
|
|
1741
|
-
return;
|
|
1774
|
+
if (value === void 0 || value === null) return;
|
|
1742
1775
|
if (Array.isArray(value)) {
|
|
1743
1776
|
const items = value.map((v) => String(v).trim()).filter(Boolean);
|
|
1744
|
-
if (items.length)
|
|
1745
|
-
qs.set(key, items.join(","));
|
|
1777
|
+
if (items.length) qs.set(key, items.join(","));
|
|
1746
1778
|
return;
|
|
1747
1779
|
}
|
|
1748
1780
|
setIfPresent(key, value);
|
|
@@ -1768,6 +1800,8 @@ ${bytes.length}`;
|
|
|
1768
1800
|
setIfPresent("domain", params.domain);
|
|
1769
1801
|
setIfPresent("minBalance", params.minBalance);
|
|
1770
1802
|
setIfPresent("provider", params.provider);
|
|
1803
|
+
setIfPresent("handle", params.handle);
|
|
1804
|
+
setIfPresent("namespace", params.namespace);
|
|
1771
1805
|
setIfPresent("ownerAddress", params.ownerAddress);
|
|
1772
1806
|
setIfPresent("riskLevel", params.riskLevel);
|
|
1773
1807
|
setBoolIfPresent("sanctioned", params.sanctioned);
|
|
@@ -1815,11 +1849,17 @@ ${bytes.length}`;
|
|
|
1815
1849
|
return response;
|
|
1816
1850
|
}
|
|
1817
1851
|
/**
|
|
1818
|
-
* CHECK GATE
|
|
1819
|
-
*
|
|
1852
|
+
* CHECK GATE — Local preview against proofs you already have in memory or from `getProofsByWallet`.
|
|
1853
|
+
*
|
|
1854
|
+
* **Not authoritative for access control.** For production allow/deny, use {@link NeusClient#gateCheck}
|
|
1855
|
+
* (`GET /api/v1/proofs/check`), which applies the same rules as the NEUS API. This method is useful for
|
|
1856
|
+
* UI previews, offline-ish flows, or when you already fetched proofs and want a quick match without
|
|
1857
|
+
* another round trip — but it can disagree with the server (e.g. `contentHash` matching uses a local
|
|
1858
|
+
* approximation when proof data only has inline `content`; the API uses the standard server-side hash).
|
|
1859
|
+
*
|
|
1820
1860
|
* Gate-first verification: checks if wallet has valid proofs satisfying requirements.
|
|
1821
1861
|
* Returns which requirements are missing/expired.
|
|
1822
|
-
*
|
|
1862
|
+
*
|
|
1823
1863
|
* @param {Object} params - Gate check parameters
|
|
1824
1864
|
* @param {string} params.walletAddress - Target wallet
|
|
1825
1865
|
* @param {Array<Object>} params.requirements - Array of gate requirements
|
|
@@ -1837,7 +1877,7 @@ ${bytes.length}`;
|
|
|
1837
1877
|
* Note: contentHash matching uses approximation in SDK; for exact SHA-256 matching, use backend API
|
|
1838
1878
|
* @param {Array} [params.proofs] - Pre-fetched proofs (skip API call)
|
|
1839
1879
|
* @returns {Promise<Object>} Gate result with satisfied, missing, existing
|
|
1840
|
-
*
|
|
1880
|
+
*
|
|
1841
1881
|
* @example
|
|
1842
1882
|
* // Basic gate check
|
|
1843
1883
|
* const result = await client.checkGate({
|
|
@@ -1870,20 +1910,20 @@ ${bytes.length}`;
|
|
|
1870
1910
|
const verifier = verifiedVerifiers.find(
|
|
1871
1911
|
(v) => v.verifierId === verifierId && v.verified === true
|
|
1872
1912
|
);
|
|
1873
|
-
if (!verifier)
|
|
1874
|
-
|
|
1875
|
-
if (proof.revokedAt)
|
|
1876
|
-
return false;
|
|
1913
|
+
if (!verifier) return false;
|
|
1914
|
+
if (proof.revokedAt) return false;
|
|
1877
1915
|
if (maxAgeMs) {
|
|
1878
1916
|
const proofTimestamp = proof.createdAt || proof.signedTimestamp || 0;
|
|
1879
1917
|
const proofAge = now - proofTimestamp;
|
|
1880
|
-
if (proofAge > maxAgeMs)
|
|
1881
|
-
return false;
|
|
1918
|
+
if (proofAge > maxAgeMs) return false;
|
|
1882
1919
|
}
|
|
1883
1920
|
if (match && typeof match === "object") {
|
|
1884
1921
|
const data = verifier.data || {};
|
|
1885
1922
|
const input = data.input || {};
|
|
1886
|
-
|
|
1923
|
+
const matchObj = Array.isArray(match) ? Object.fromEntries(
|
|
1924
|
+
match.filter((m) => m && m.path && String(m.value ?? "").trim() !== "").map((m) => [String(m.path).trim(), m.value])
|
|
1925
|
+
) : match;
|
|
1926
|
+
for (const [key, expected] of Object.entries(matchObj)) {
|
|
1887
1927
|
let actualValue = null;
|
|
1888
1928
|
if (key.includes(".")) {
|
|
1889
1929
|
const parts = key.split(".");
|
|
@@ -1908,6 +1948,7 @@ ${bytes.length}`;
|
|
|
1908
1948
|
actualValue = data.reference?.id || data.content;
|
|
1909
1949
|
}
|
|
1910
1950
|
if (actualValue === void 0) {
|
|
1951
|
+
const claims = data.claims || {};
|
|
1911
1952
|
if (key === "contractAddress") {
|
|
1912
1953
|
actualValue = input.contractAddress || data.contractAddress;
|
|
1913
1954
|
} else if (key === "tokenId") {
|
|
@@ -1926,6 +1967,22 @@ ${bytes.length}`;
|
|
|
1926
1967
|
actualValue = data.verificationMethod;
|
|
1927
1968
|
} else if (key === "domain") {
|
|
1928
1969
|
actualValue = data.domain;
|
|
1970
|
+
} else if (key === "handle") {
|
|
1971
|
+
actualValue = data.handle || data.pseudonymId;
|
|
1972
|
+
} else if (key === "namespace") {
|
|
1973
|
+
actualValue = data.namespace !== void 0 && data.namespace !== null && data.namespace !== "" ? data.namespace : "neus";
|
|
1974
|
+
} else if (key === "claims.sanctions_passed") {
|
|
1975
|
+
actualValue = claims.sanctions_passed ?? claims.sanctionsPassed;
|
|
1976
|
+
} else if (key === "claims.age_min") {
|
|
1977
|
+
actualValue = claims.age_min ?? claims.ageMin;
|
|
1978
|
+
} else if (key === "neusPersonhoodId") {
|
|
1979
|
+
actualValue = data.neusPersonhoodId;
|
|
1980
|
+
} else if (key === "riskLevel") {
|
|
1981
|
+
actualValue = data.riskLevel;
|
|
1982
|
+
} else if (key === "sanctioned") {
|
|
1983
|
+
actualValue = data.sanctioned;
|
|
1984
|
+
} else if (key === "poisoned") {
|
|
1985
|
+
actualValue = data.poisoned;
|
|
1929
1986
|
}
|
|
1930
1987
|
}
|
|
1931
1988
|
if (key === "contentHash" && actualValue === void 0 && data.content) {
|
|
@@ -1937,7 +1994,7 @@ ${bytes.length}`;
|
|
|
1937
1994
|
hash = (hash << 5) - hash + char;
|
|
1938
1995
|
hash = hash & hash;
|
|
1939
1996
|
}
|
|
1940
|
-
actualValue =
|
|
1997
|
+
actualValue = `0x${Math.abs(hash).toString(16).padStart(64, "0").substring(0, 66)}`;
|
|
1941
1998
|
} catch {
|
|
1942
1999
|
actualValue = String(data.content);
|
|
1943
2000
|
}
|
|
@@ -1947,11 +2004,16 @@ ${bytes.length}`;
|
|
|
1947
2004
|
if (actualValue === void 0 || actualValue === null) {
|
|
1948
2005
|
return false;
|
|
1949
2006
|
}
|
|
2007
|
+
if (typeof actualValue === "boolean" || key && (key.includes("sanctions") || key.includes("sanctioned") || key.includes("poisoned"))) {
|
|
2008
|
+
const bActual = Boolean(actualValue);
|
|
2009
|
+
const bExpected = expected === true || expected === "true" || String(expected).toLowerCase() === "true";
|
|
2010
|
+
if (bActual !== bExpected) return false;
|
|
2011
|
+
continue;
|
|
2012
|
+
}
|
|
1950
2013
|
if (key === "chainId" || key === "tokenId" && (typeof actualValue === "number" || !isNaN(Number(actualValue)))) {
|
|
1951
2014
|
normalizedActual = Number(actualValue);
|
|
1952
2015
|
normalizedExpected = Number(expected);
|
|
1953
|
-
if (isNaN(normalizedActual) || isNaN(normalizedExpected))
|
|
1954
|
-
return false;
|
|
2016
|
+
if (isNaN(normalizedActual) || isNaN(normalizedExpected)) return false;
|
|
1955
2017
|
} else if (typeof actualValue === "string" && (actualValue.startsWith("0x") || actualValue.length > 20)) {
|
|
1956
2018
|
normalizedActual = actualValue.toLowerCase();
|
|
1957
2019
|
normalizedExpected = typeof expected === "string" ? String(expected).toLowerCase() : expected;
|
|
@@ -1980,13 +2042,6 @@ ${bytes.length}`;
|
|
|
1980
2042
|
allProofs: proofs
|
|
1981
2043
|
};
|
|
1982
2044
|
}
|
|
1983
|
-
// ============================================================================
|
|
1984
|
-
// PRIVATE UTILITY METHODS
|
|
1985
|
-
// ============================================================================
|
|
1986
|
-
/**
|
|
1987
|
-
* Get connected wallet address
|
|
1988
|
-
* @private
|
|
1989
|
-
*/
|
|
1990
2045
|
async _getWalletAddress() {
|
|
1991
2046
|
if (typeof window === "undefined" || !window.ethereum) {
|
|
1992
2047
|
throw new ConfigurationError("No Web3 wallet detected");
|
|
@@ -1997,10 +2052,6 @@ ${bytes.length}`;
|
|
|
1997
2052
|
}
|
|
1998
2053
|
return accounts[0];
|
|
1999
2054
|
}
|
|
2000
|
-
/**
|
|
2001
|
-
* Make HTTP request to API
|
|
2002
|
-
* @private
|
|
2003
|
-
*/
|
|
2004
2055
|
async _makeRequest(method, endpoint, data = null, headersOverride = null) {
|
|
2005
2056
|
const url = `${this.baseUrl}${endpoint}`;
|
|
2006
2057
|
const controller = new AbortController();
|
|
@@ -2038,10 +2089,6 @@ ${bytes.length}`;
|
|
|
2038
2089
|
throw new NetworkError(`Network error: ${error.message}`);
|
|
2039
2090
|
}
|
|
2040
2091
|
}
|
|
2041
|
-
/**
|
|
2042
|
-
* Format API response for consistent structure
|
|
2043
|
-
* @private
|
|
2044
|
-
*/
|
|
2045
2092
|
_formatResponse(response) {
|
|
2046
2093
|
const proofId = response?.data?.proofId || response?.proofId || response?.data?.resource?.proofId || response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.id;
|
|
2047
2094
|
const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || proofId || response?.data?.id;
|
|
@@ -2056,13 +2103,9 @@ ${bytes.length}`;
|
|
|
2056
2103
|
data: response.data,
|
|
2057
2104
|
message: response.message,
|
|
2058
2105
|
timestamp: Date.now(),
|
|
2059
|
-
|
|
2106
|
+
proofUrl: finalProofId ? `${this.baseUrl}/api/v1/proofs/${finalProofId}` : null
|
|
2060
2107
|
};
|
|
2061
2108
|
}
|
|
2062
|
-
/**
|
|
2063
|
-
* Check if status is terminal (completed or failed)
|
|
2064
|
-
* @private
|
|
2065
|
-
*/
|
|
2066
2109
|
_isTerminalStatus(status) {
|
|
2067
2110
|
const terminalStates = [
|
|
2068
2111
|
"verified",
|
|
@@ -2093,5 +2136,6 @@ ${bytes.length}`;
|
|
|
2093
2136
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2094
2137
|
0 && (module.exports = {
|
|
2095
2138
|
NeusClient,
|
|
2139
|
+
PORTABLE_PROOF_SIGNER_HEADER,
|
|
2096
2140
|
constructVerificationMessage
|
|
2097
2141
|
});
|