@zkpassport/sdk 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/encryption.d.ts +4 -4
- package/dist/cjs/encryption.js +10 -20
- package/dist/cjs/index.d.ts +7 -7
- package/dist/cjs/index.js +150 -124
- package/dist/cjs/json-rpc.d.ts +2 -2
- package/dist/cjs/json-rpc.js +11 -12
- package/dist/cjs/logger.d.ts +7 -2
- package/dist/cjs/logger.js +8 -32
- package/dist/cjs/mobile.js +23 -24
- package/dist/cjs/websocket.js +3 -3
- package/dist/esm/encryption.d.ts +4 -4
- package/dist/esm/encryption.js +5 -5
- package/dist/esm/index.d.ts +7 -7
- package/dist/esm/index.js +132 -128
- package/dist/esm/json-rpc.d.ts +2 -2
- package/dist/esm/json-rpc.js +13 -13
- package/dist/esm/logger.d.ts +7 -2
- package/dist/esm/logger.js +7 -32
- package/dist/esm/mobile.js +25 -25
- package/dist/esm/websocket.js +3 -3
- package/package.json +17 -7
- package/src/encryption.ts +5 -5
- package/src/index.ts +144 -140
- package/src/json-rpc.ts +15 -15
- package/src/logger.ts +7 -38
- package/src/mobile.ts +26 -26
- package/src/websocket.ts +4 -4
package/dist/cjs/json-rpc.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { JsonRpcRequest, JsonRpcResponse } from
|
|
2
|
-
import { WebSocketClient } from
|
|
1
|
+
import type { JsonRpcRequest, JsonRpcResponse } from "@zkpassport/utils";
|
|
2
|
+
import { WebSocketClient } from "./websocket";
|
|
3
3
|
export declare function createJsonRpcRequest(method: string, params: any): JsonRpcRequest;
|
|
4
4
|
export declare function createEncryptedJsonRpcRequest(method: string, params: any, sharedSecret: Uint8Array, topic: string): Promise<JsonRpcRequest>;
|
|
5
5
|
export declare function sendEncryptedJsonRpcRequest(method: string, params: any, sharedSecret: Uint8Array, topic: string, wsClient: WebSocketClient): Promise<boolean>;
|
package/dist/cjs/json-rpc.js
CHANGED
|
@@ -4,44 +4,43 @@ exports.createJsonRpcRequest = createJsonRpcRequest;
|
|
|
4
4
|
exports.createEncryptedJsonRpcRequest = createEncryptedJsonRpcRequest;
|
|
5
5
|
exports.sendEncryptedJsonRpcRequest = sendEncryptedJsonRpcRequest;
|
|
6
6
|
exports.createJsonRpcResponse = createJsonRpcResponse;
|
|
7
|
-
const tslib_1 = require("tslib");
|
|
8
7
|
const crypto_1 = require("crypto");
|
|
9
8
|
const encryption_1 = require("./encryption");
|
|
10
|
-
const logger_1 =
|
|
9
|
+
const logger_1 = require("./logger");
|
|
11
10
|
function createJsonRpcRequest(method, params) {
|
|
12
11
|
return {
|
|
13
|
-
jsonrpc:
|
|
14
|
-
id: (0, crypto_1.randomBytes)(16).toString(
|
|
12
|
+
jsonrpc: "2.0",
|
|
13
|
+
id: (0, crypto_1.randomBytes)(16).toString("hex"),
|
|
15
14
|
method,
|
|
16
15
|
params,
|
|
17
16
|
};
|
|
18
17
|
}
|
|
19
18
|
async function createEncryptedJsonRpcRequest(method, params, sharedSecret, topic) {
|
|
20
19
|
const encryptedMessage = await (0, encryption_1.encrypt)(JSON.stringify({ method, params: params || {} }), sharedSecret, topic);
|
|
21
|
-
return createJsonRpcRequest(
|
|
22
|
-
payload: Buffer.from(encryptedMessage).toString(
|
|
20
|
+
return createJsonRpcRequest("encryptedMessage", {
|
|
21
|
+
payload: Buffer.from(encryptedMessage).toString("base64"),
|
|
23
22
|
});
|
|
24
23
|
}
|
|
25
24
|
async function sendEncryptedJsonRpcRequest(method, params, sharedSecret, topic, wsClient) {
|
|
26
25
|
try {
|
|
27
26
|
const message = { method, params: params || {} };
|
|
28
27
|
const encryptedMessage = await (0, encryption_1.encrypt)(JSON.stringify(message), sharedSecret, topic);
|
|
29
|
-
const request = createJsonRpcRequest(
|
|
30
|
-
payload: Buffer.from(encryptedMessage).toString(
|
|
28
|
+
const request = createJsonRpcRequest("encryptedMessage", {
|
|
29
|
+
payload: Buffer.from(encryptedMessage).toString("base64"),
|
|
31
30
|
});
|
|
32
|
-
logger_1.
|
|
33
|
-
logger_1.
|
|
31
|
+
logger_1.noLogger.debug("Sending encrypted message (original):", message);
|
|
32
|
+
logger_1.noLogger.debug("Sending encrypted message (encrypted):", request);
|
|
34
33
|
wsClient.send(JSON.stringify(request));
|
|
35
34
|
return true;
|
|
36
35
|
}
|
|
37
36
|
catch (error) {
|
|
38
|
-
logger_1.
|
|
37
|
+
logger_1.noLogger.error("Error sending encrypted message:", error);
|
|
39
38
|
return false;
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
function createJsonRpcResponse(id, result) {
|
|
43
42
|
return {
|
|
44
|
-
jsonrpc:
|
|
43
|
+
jsonrpc: "2.0",
|
|
45
44
|
id,
|
|
46
45
|
result,
|
|
47
46
|
};
|
package/dist/cjs/logger.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
declare const customLogger: {
|
|
1
|
+
export declare const customLogger: {
|
|
2
2
|
debug: (message: string, ...args: any[]) => void;
|
|
3
3
|
info: (message: string, ...args: any[]) => void;
|
|
4
4
|
warn: (message: string, ...args: any[]) => void;
|
|
5
5
|
error: (message: string, ...args: any[]) => void;
|
|
6
6
|
};
|
|
7
|
-
export
|
|
7
|
+
export declare const noLogger: {
|
|
8
|
+
debug: (..._: any[]) => void;
|
|
9
|
+
info: (..._: any[]) => void;
|
|
10
|
+
warn: (..._: any[]) => void;
|
|
11
|
+
error: (..._: any[]) => void;
|
|
12
|
+
};
|
package/dist/cjs/logger.js
CHANGED
|
@@ -1,39 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import { createLogger, transports, format } from 'winston'
|
|
3
|
-
// import colors from 'colors/safe'
|
|
4
|
-
// import util from 'util'
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// format: format.combine(
|
|
9
|
-
// format.timestamp({ format: 'HH:mm' }),
|
|
10
|
-
// format.printf(({ timestamp, level, message, additionalInfo }) => {
|
|
11
|
-
// const colorMap = {
|
|
12
|
-
// debug: colors.cyan,
|
|
13
|
-
// info: colors.green,
|
|
14
|
-
// warn: colors.yellow,
|
|
15
|
-
// error: colors.red,
|
|
16
|
-
// } as const
|
|
17
|
-
// const coloredLevel = (colorMap[level as keyof typeof colorMap] || colors.white)(level.toUpperCase())
|
|
18
|
-
// let logMessage = `${timestamp} [${coloredLevel}] ${message}`
|
|
19
|
-
// if (additionalInfo && additionalInfo.length > 0) {
|
|
20
|
-
// logMessage += ' ' + util.inspect(additionalInfo, { depth: null, colors: true })
|
|
21
|
-
// }
|
|
22
|
-
// return logMessage
|
|
23
|
-
// }),
|
|
24
|
-
// ),
|
|
25
|
-
// transports: [new transports.Console()],
|
|
26
|
-
// })
|
|
27
|
-
// const customLogger = {
|
|
28
|
-
// debug: (message: string, ...args: any[]) => logger.debug(message, { additionalInfo: args }),
|
|
29
|
-
// info: (message: string, ...args: any[]) => logger.info(message, { additionalInfo: args }),
|
|
30
|
-
// warn: (message: string, ...args: any[]) => logger.warn(message, { additionalInfo: args }),
|
|
31
|
-
// error: (message: string, ...args: any[]) => logger.error(message, { additionalInfo: args }),
|
|
32
|
-
// }
|
|
33
|
-
const customLogger = {
|
|
3
|
+
exports.noLogger = exports.customLogger = void 0;
|
|
4
|
+
exports.customLogger = {
|
|
34
5
|
debug: (message, ...args) => console.debug(message, ...args),
|
|
35
6
|
info: (message, ...args) => console.info(message, ...args),
|
|
36
7
|
warn: (message, ...args) => console.warn(message, ...args),
|
|
37
8
|
error: (message, ...args) => console.error(message, ...args),
|
|
38
9
|
};
|
|
39
|
-
exports.
|
|
10
|
+
exports.noLogger = {
|
|
11
|
+
debug: (..._) => { },
|
|
12
|
+
info: (..._) => { },
|
|
13
|
+
warn: (..._) => { },
|
|
14
|
+
error: (..._) => { },
|
|
15
|
+
};
|
package/dist/cjs/mobile.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZkPassportProver = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
4
|
const utils_1 = require("@noble/ciphers/utils");
|
|
6
5
|
const websocket_1 = require("./websocket");
|
|
7
6
|
const json_rpc_1 = require("./json-rpc");
|
|
8
7
|
const encryption_1 = require("./encryption");
|
|
9
|
-
const logger_1 =
|
|
8
|
+
const logger_1 = require("./logger");
|
|
10
9
|
class ZkPassportProver {
|
|
11
10
|
constructor() {
|
|
12
11
|
this.topicToKeyPair = {};
|
|
@@ -24,13 +23,13 @@ class ZkPassportProver {
|
|
|
24
23
|
* @param outerRequest The outer request.
|
|
25
24
|
*/
|
|
26
25
|
async handleEncryptedMessage(topic, request, outerRequest) {
|
|
27
|
-
logger_1.
|
|
28
|
-
if (request.method ===
|
|
29
|
-
logger_1.
|
|
26
|
+
logger_1.noLogger.debug("Received encrypted message:", request);
|
|
27
|
+
if (request.method === "hello") {
|
|
28
|
+
logger_1.noLogger.info(`Successfully verified origin domain name: ${outerRequest.origin}`);
|
|
30
29
|
this.topicToRemoteDomainVerified[topic] = true;
|
|
31
30
|
await Promise.all(this.onDomainVerifiedCallbacks[topic].map((callback) => callback()));
|
|
32
31
|
}
|
|
33
|
-
else if (request.method ===
|
|
32
|
+
else if (request.method === "closed_page") {
|
|
34
33
|
// TODO: Implement
|
|
35
34
|
}
|
|
36
35
|
}
|
|
@@ -40,13 +39,13 @@ class ZkPassportProver {
|
|
|
40
39
|
*/
|
|
41
40
|
async scan(url, { keyPairOverride, } = {}) {
|
|
42
41
|
const parsedUrl = new URL(url);
|
|
43
|
-
const domain = parsedUrl.searchParams.get(
|
|
44
|
-
const topic = parsedUrl.searchParams.get(
|
|
45
|
-
const pubkeyHex = parsedUrl.searchParams.get(
|
|
42
|
+
const domain = parsedUrl.searchParams.get("d");
|
|
43
|
+
const topic = parsedUrl.searchParams.get("t");
|
|
44
|
+
const pubkeyHex = parsedUrl.searchParams.get("p");
|
|
46
45
|
if (!domain || !topic || !pubkeyHex) {
|
|
47
|
-
throw new Error(
|
|
46
|
+
throw new Error("Invalid URL: missing required parameters");
|
|
48
47
|
}
|
|
49
|
-
const pubkey = new Uint8Array(Buffer.from(pubkeyHex,
|
|
48
|
+
const pubkey = new Uint8Array(Buffer.from(pubkeyHex, "hex"));
|
|
50
49
|
this.domain = domain;
|
|
51
50
|
const keyPair = keyPairOverride || (await (0, encryption_1.generateECDHKeyPair)());
|
|
52
51
|
this.topicToKeyPair[topic] = {
|
|
@@ -62,7 +61,7 @@ class ZkPassportProver {
|
|
|
62
61
|
const wsClient = (0, websocket_1.getWebSocketClient)(`wss://bridge.zkpassport.id?topic=${topic}&pubkey=${(0, utils_1.bytesToHex)(keyPair.publicKey)}`);
|
|
63
62
|
this.topicToWebSocketClient[topic] = wsClient;
|
|
64
63
|
wsClient.onopen = async () => {
|
|
65
|
-
logger_1.
|
|
64
|
+
logger_1.noLogger.info("[mobile] WebSocket connection established");
|
|
66
65
|
await Promise.all(this.onBridgeConnectCallbacks[topic].map((callback) => callback()));
|
|
67
66
|
// Server sends handshake automatically (when it sees a pubkey in websocket URI)
|
|
68
67
|
// wsClient.send(
|
|
@@ -73,20 +72,20 @@ class ZkPassportProver {
|
|
|
73
72
|
// ),
|
|
74
73
|
// )
|
|
75
74
|
};
|
|
76
|
-
wsClient.addEventListener(
|
|
77
|
-
logger_1.
|
|
75
|
+
wsClient.addEventListener("message", async (event) => {
|
|
76
|
+
logger_1.noLogger.info("[mobile] Received message:", event.data);
|
|
78
77
|
try {
|
|
79
78
|
const data = JSON.parse(event.data);
|
|
80
79
|
const originDomain = data.origin ? new URL(data.origin).hostname : undefined;
|
|
81
80
|
// Origin domain must match domain in QR code
|
|
82
81
|
if (originDomain !== this.domain) {
|
|
83
|
-
logger_1.
|
|
82
|
+
logger_1.noLogger.warn(`[mobile] Origin does not match domain in QR code. Expected ${this.domain} but got ${originDomain}`);
|
|
84
83
|
return;
|
|
85
84
|
}
|
|
86
|
-
if (data.method ===
|
|
85
|
+
if (data.method === "encryptedMessage") {
|
|
87
86
|
// Decode the payload from base64 to Uint8Array
|
|
88
87
|
const payload = new Uint8Array(atob(data.params.payload)
|
|
89
|
-
.split(
|
|
88
|
+
.split("")
|
|
90
89
|
.map((c) => c.charCodeAt(0)));
|
|
91
90
|
try {
|
|
92
91
|
// Decrypt the payload using the shared secret
|
|
@@ -95,16 +94,16 @@ class ZkPassportProver {
|
|
|
95
94
|
await this.handleEncryptedMessage(topic, decryptedJson, data);
|
|
96
95
|
}
|
|
97
96
|
catch (error) {
|
|
98
|
-
logger_1.
|
|
97
|
+
logger_1.noLogger.error("[mobile] Error decrypting message:", error);
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
catch (error) {
|
|
103
|
-
logger_1.
|
|
102
|
+
logger_1.noLogger.error("[mobile] Error:", error);
|
|
104
103
|
}
|
|
105
104
|
});
|
|
106
105
|
wsClient.onerror = (error) => {
|
|
107
|
-
logger_1.
|
|
106
|
+
logger_1.noLogger.error("[mobile] WebSocket error:", error);
|
|
108
107
|
};
|
|
109
108
|
return {
|
|
110
109
|
domain: this.domain,
|
|
@@ -114,16 +113,16 @@ class ZkPassportProver {
|
|
|
114
113
|
onDomainVerified: (callback) => this.onDomainVerifiedCallbacks[topic].push(callback),
|
|
115
114
|
onBridgeConnect: (callback) => this.onBridgeConnectCallbacks[topic].push(callback),
|
|
116
115
|
notifyReject: async () => {
|
|
117
|
-
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)(
|
|
116
|
+
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)("reject", null, this.topicToSharedSecret[topic], topic, this.topicToWebSocketClient[topic]);
|
|
118
117
|
},
|
|
119
118
|
notifyAccept: async () => {
|
|
120
|
-
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)(
|
|
119
|
+
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)("accept", null, this.topicToSharedSecret[topic], topic, this.topicToWebSocketClient[topic]);
|
|
121
120
|
},
|
|
122
121
|
notifyDone: async (proof) => {
|
|
123
|
-
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)(
|
|
122
|
+
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)("done", { proof }, this.topicToSharedSecret[topic], topic, this.topicToWebSocketClient[topic]);
|
|
124
123
|
},
|
|
125
124
|
notifyError: async (error) => {
|
|
126
|
-
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)(
|
|
125
|
+
await (0, json_rpc_1.sendEncryptedJsonRpcRequest)("error", { error }, this.topicToSharedSecret[topic], topic, this.topicToWebSocketClient[topic]);
|
|
127
126
|
},
|
|
128
127
|
};
|
|
129
128
|
}
|
package/dist/cjs/websocket.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getWebSocketClient = getWebSocketClient;
|
|
4
4
|
function getWebSocketClient(url, origin) {
|
|
5
|
-
if (typeof window !==
|
|
5
|
+
if (typeof window !== "undefined" && window.WebSocket) {
|
|
6
6
|
// Browser environment
|
|
7
7
|
return new WebSocket(url);
|
|
8
8
|
}
|
|
9
9
|
else {
|
|
10
10
|
// Node.js environment
|
|
11
|
-
const WebSocket = require(
|
|
11
|
+
const WebSocket = require("ws");
|
|
12
12
|
return new WebSocket(url, {
|
|
13
13
|
headers: {
|
|
14
|
-
Origin: origin ||
|
|
14
|
+
Origin: origin || "nodejs",
|
|
15
15
|
},
|
|
16
16
|
});
|
|
17
17
|
}
|
package/dist/esm/encryption.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare function generateECDHKeyPair(): Promise<{
|
|
2
|
-
privateKey:
|
|
3
|
-
publicKey:
|
|
2
|
+
privateKey: Uint8Array;
|
|
3
|
+
publicKey: Uint8Array;
|
|
4
4
|
}>;
|
|
5
|
-
export declare function getSharedSecret(privateKey: string, publicKey: string): Promise<Uint8Array
|
|
6
|
-
export declare function encrypt(message: string, sharedSecret: Uint8Array, topic: string): Promise<Uint8Array
|
|
5
|
+
export declare function getSharedSecret(privateKey: string, publicKey: string): Promise<Uint8Array>;
|
|
6
|
+
export declare function encrypt(message: string, sharedSecret: Uint8Array, topic: string): Promise<Uint8Array>;
|
|
7
7
|
export declare function decrypt(ciphertext: Uint8Array, sharedSecret: Uint8Array, topic: string): Promise<string>;
|
package/dist/esm/encryption.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { gcm } from
|
|
2
|
-
import { utf8ToBytes } from
|
|
1
|
+
import { gcm } from "@noble/ciphers/aes";
|
|
2
|
+
import { utf8ToBytes } from "@noble/ciphers/utils";
|
|
3
3
|
async function sha256Truncate(topic) {
|
|
4
4
|
const encoder = new TextEncoder();
|
|
5
5
|
const data = encoder.encode(topic);
|
|
6
|
-
const hashBuffer = await crypto.subtle.digest(
|
|
6
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
7
7
|
const fullHashArray = new Uint8Array(hashBuffer);
|
|
8
8
|
const truncatedHashArray = fullHashArray.slice(0, 12);
|
|
9
9
|
return truncatedHashArray;
|
|
10
10
|
}
|
|
11
11
|
export async function generateECDHKeyPair() {
|
|
12
|
-
const secp256k1 = await import(
|
|
12
|
+
const secp256k1 = await import("@noble/secp256k1");
|
|
13
13
|
const privKey = secp256k1.utils.randomPrivateKey();
|
|
14
14
|
const pubKey = secp256k1.getPublicKey(privKey);
|
|
15
15
|
return {
|
|
@@ -18,7 +18,7 @@ export async function generateECDHKeyPair() {
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
export async function getSharedSecret(privateKey, publicKey) {
|
|
21
|
-
const secp256k1 = await import(
|
|
21
|
+
const secp256k1 = await import("@noble/secp256k1");
|
|
22
22
|
const sharedSecret = secp256k1.getSharedSecret(privateKey, publicKey);
|
|
23
23
|
return sharedSecret.slice(0, 32);
|
|
24
24
|
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type DisclosableIDCredential, type IDCredential, type IDCredentialValue, type NumericalIDCredential, type ProofResult, type QueryResult } from
|
|
2
|
-
export type * from
|
|
3
|
-
export { SANCTIONED_COUNTRIES, EU_COUNTRIES, EEA_COUNTRIES, SCHENGEN_COUNTRIES, ASEAN_COUNTRIES, MERCOSUR_COUNTRIES, } from
|
|
1
|
+
import { type DisclosableIDCredential, type IDCredential, type IDCredentialValue, type NumericalIDCredential, type ProofResult, type QueryResult } from "@zkpassport/utils";
|
|
2
|
+
export type * from "@zkpassport/utils";
|
|
3
|
+
export { SANCTIONED_COUNTRIES, EU_COUNTRIES, EEA_COUNTRIES, SCHENGEN_COUNTRIES, ASEAN_COUNTRIES, MERCOSUR_COUNTRIES, } from "@zkpassport/utils";
|
|
4
4
|
export type QueryBuilderResult = {
|
|
5
5
|
/**
|
|
6
6
|
* The URL of the request.
|
|
@@ -85,13 +85,13 @@ export type QueryBuilder = {
|
|
|
85
85
|
* @param key The attribute to compare.
|
|
86
86
|
* @param value The value of the attribute you require.
|
|
87
87
|
*/
|
|
88
|
-
lte: <T extends
|
|
88
|
+
lte: <T extends "birthdate" | "expiry_date">(key: T, value: IDCredentialValue<T>) => QueryBuilder;
|
|
89
89
|
/**
|
|
90
90
|
* Requires this attribute to be less than the provided value.
|
|
91
91
|
* @param key The attribute to compare.
|
|
92
92
|
* @param value The value of the attribute you require.
|
|
93
93
|
*/
|
|
94
|
-
lt: <T extends
|
|
94
|
+
lt: <T extends "age">(key: T, value: IDCredentialValue<T>) => QueryBuilder;
|
|
95
95
|
/**
|
|
96
96
|
* Requires this attribute to be included in the provided range.
|
|
97
97
|
* @param key The attribute to compare.
|
|
@@ -104,13 +104,13 @@ export type QueryBuilder = {
|
|
|
104
104
|
* @param key The attribute to compare.
|
|
105
105
|
* @param value The list of values to check inclusion against.
|
|
106
106
|
*/
|
|
107
|
-
in: <T extends
|
|
107
|
+
in: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
|
|
108
108
|
/**
|
|
109
109
|
* Requires this attribute to be excluded from the provided list.
|
|
110
110
|
* @param key The attribute to compare.
|
|
111
111
|
* @param value The list of values to check exclusion against.
|
|
112
112
|
*/
|
|
113
|
-
out: <T extends
|
|
113
|
+
out: <T extends "nationality">(key: T, value: IDCredentialValue<T>[]) => QueryBuilder;
|
|
114
114
|
/**
|
|
115
115
|
* Requires this attribute to be disclosed.
|
|
116
116
|
* @param key The attribute to disclose.
|