@bind-protocol/sdk 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/{index-CASjN9Qe.d.ts → adapter-53dB8ogG.d.ts} +3 -67
- package/dist/{index-5j-fuebC.d.cts → adapter-DyAYLtIy.d.cts} +3 -67
- package/dist/adapters/dimo/index.d.cts +3 -2
- package/dist/adapters/dimo/index.d.ts +3 -2
- package/dist/adapters/index.cjs +499 -0
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +6 -2
- package/dist/adapters/index.d.ts +6 -2
- package/dist/adapters/index.js +497 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/zktls/index.cjs +503 -0
- package/dist/adapters/zktls/index.cjs.map +1 -0
- package/dist/adapters/zktls/index.d.cts +117 -0
- package/dist/adapters/zktls/index.d.ts +117 -0
- package/dist/adapters/zktls/index.js +499 -0
- package/dist/adapters/zktls/index.js.map +1 -0
- package/dist/client-BSwO4sTC.d.ts +135 -0
- package/dist/client-Bh8Di-5n.d.cts +135 -0
- package/dist/core/index.cjs +162 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +25 -61
- package/dist/core/index.d.ts +25 -61
- package/dist/core/index.js +159 -2
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +315 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +309 -2
- package/dist/index.js.map +1 -1
- package/dist/types-B6S0axfE.d.cts +200 -0
- package/dist/types-B6S0axfE.d.ts +200 -0
- package/dist/types-Be7Jc5V8.d.cts +68 -0
- package/dist/types-D1-qiyJO.d.ts +68 -0
- package/package.json +10 -2
- package/dist/types-o4sbOK_a.d.cts +0 -101
- package/dist/types-o4sbOK_a.d.ts +0 -101
package/README.md
CHANGED
|
@@ -1,69 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Base types for data source adapters
|
|
5
|
-
*
|
|
6
|
-
* Adapters abstract away the data source specifics and provide a uniform
|
|
7
|
-
* interface for fetching data that can be used as circuit inputs.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Base interface for all data source adapters
|
|
12
|
-
* Each adapter knows how to fetch data from a specific source
|
|
13
|
-
* and transform it into circuit inputs.
|
|
14
|
-
*/
|
|
15
|
-
interface DataAdapter<TConfig = unknown, TQuery = unknown, TData = unknown> {
|
|
16
|
-
/** Unique identifier for this adapter */
|
|
17
|
-
readonly id: string;
|
|
18
|
-
/** Human-readable name */
|
|
19
|
-
readonly name: string;
|
|
20
|
-
/** Description of what data source this adapter connects to */
|
|
21
|
-
readonly description: string;
|
|
22
|
-
/**
|
|
23
|
-
* Fetch raw data from the data source
|
|
24
|
-
* @param query - Adapter-specific query parameters
|
|
25
|
-
* @returns Raw data from the source
|
|
26
|
-
*/
|
|
27
|
-
fetchData(query: TQuery): Promise<TData>;
|
|
28
|
-
/**
|
|
29
|
-
* Transform raw data into circuit inputs
|
|
30
|
-
* @param data - Raw data from fetchData
|
|
31
|
-
* @param circuitId - Target circuit ID (adapters may support multiple circuits)
|
|
32
|
-
* @returns Inputs ready for prove job submission
|
|
33
|
-
*/
|
|
34
|
-
toCircuitInputs(data: TData, circuitId: string): ProveJobInputs;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Adapter registration entry
|
|
38
|
-
*/
|
|
39
|
-
interface AdapterRegistration<TConfig = unknown> {
|
|
40
|
-
/** Adapter factory function */
|
|
41
|
-
create: (config: TConfig) => DataAdapter;
|
|
42
|
-
/** Default configuration */
|
|
43
|
-
defaultConfig?: Partial<TConfig>;
|
|
44
|
-
/** Supported circuit IDs */
|
|
45
|
-
supportedCircuits: string[];
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Common telemetry data structure that adapters can transform their data into
|
|
49
|
-
*/
|
|
50
|
-
interface TelemetryData {
|
|
51
|
-
/** Array of telemetry signal readings */
|
|
52
|
-
signals: TelemetrySignal[];
|
|
53
|
-
/** Timestamp of the data collection period start */
|
|
54
|
-
periodStart: string;
|
|
55
|
-
/** Timestamp of the data collection period end */
|
|
56
|
-
periodEnd: string;
|
|
57
|
-
/** Subject identifier (e.g., vehicle ID) */
|
|
58
|
-
subjectId: string;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Individual telemetry signal reading
|
|
62
|
-
*/
|
|
63
|
-
interface TelemetrySignal {
|
|
64
|
-
timestamp: string;
|
|
65
|
-
[key: string]: string | number | boolean | string[] | null;
|
|
66
|
-
}
|
|
1
|
+
import { D as DataAdapter } from './types-D1-qiyJO.js';
|
|
2
|
+
import { a as ProveJobInputs } from './types-B6S0axfE.js';
|
|
67
3
|
|
|
68
4
|
/**
|
|
69
5
|
* DIMO Adapter Types
|
|
@@ -152,4 +88,4 @@ declare class DimoAdapter implements DataAdapter<DimoAdapterConfig, DimoQuery, D
|
|
|
152
88
|
*/
|
|
153
89
|
declare function createDimoAdapter(config: DimoAdapterConfig): DimoAdapter;
|
|
154
90
|
|
|
155
|
-
export {
|
|
91
|
+
export { DimoAdapter as D, type DimoAdapterConfig as a, type DimoQuery as b, createDimoAdapter as c, type DimoTelemetryData as d, type DimoSignal as e, type DimoClient as f };
|
|
@@ -1,69 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Base types for data source adapters
|
|
5
|
-
*
|
|
6
|
-
* Adapters abstract away the data source specifics and provide a uniform
|
|
7
|
-
* interface for fetching data that can be used as circuit inputs.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Base interface for all data source adapters
|
|
12
|
-
* Each adapter knows how to fetch data from a specific source
|
|
13
|
-
* and transform it into circuit inputs.
|
|
14
|
-
*/
|
|
15
|
-
interface DataAdapter<TConfig = unknown, TQuery = unknown, TData = unknown> {
|
|
16
|
-
/** Unique identifier for this adapter */
|
|
17
|
-
readonly id: string;
|
|
18
|
-
/** Human-readable name */
|
|
19
|
-
readonly name: string;
|
|
20
|
-
/** Description of what data source this adapter connects to */
|
|
21
|
-
readonly description: string;
|
|
22
|
-
/**
|
|
23
|
-
* Fetch raw data from the data source
|
|
24
|
-
* @param query - Adapter-specific query parameters
|
|
25
|
-
* @returns Raw data from the source
|
|
26
|
-
*/
|
|
27
|
-
fetchData(query: TQuery): Promise<TData>;
|
|
28
|
-
/**
|
|
29
|
-
* Transform raw data into circuit inputs
|
|
30
|
-
* @param data - Raw data from fetchData
|
|
31
|
-
* @param circuitId - Target circuit ID (adapters may support multiple circuits)
|
|
32
|
-
* @returns Inputs ready for prove job submission
|
|
33
|
-
*/
|
|
34
|
-
toCircuitInputs(data: TData, circuitId: string): ProveJobInputs;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Adapter registration entry
|
|
38
|
-
*/
|
|
39
|
-
interface AdapterRegistration<TConfig = unknown> {
|
|
40
|
-
/** Adapter factory function */
|
|
41
|
-
create: (config: TConfig) => DataAdapter;
|
|
42
|
-
/** Default configuration */
|
|
43
|
-
defaultConfig?: Partial<TConfig>;
|
|
44
|
-
/** Supported circuit IDs */
|
|
45
|
-
supportedCircuits: string[];
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Common telemetry data structure that adapters can transform their data into
|
|
49
|
-
*/
|
|
50
|
-
interface TelemetryData {
|
|
51
|
-
/** Array of telemetry signal readings */
|
|
52
|
-
signals: TelemetrySignal[];
|
|
53
|
-
/** Timestamp of the data collection period start */
|
|
54
|
-
periodStart: string;
|
|
55
|
-
/** Timestamp of the data collection period end */
|
|
56
|
-
periodEnd: string;
|
|
57
|
-
/** Subject identifier (e.g., vehicle ID) */
|
|
58
|
-
subjectId: string;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Individual telemetry signal reading
|
|
62
|
-
*/
|
|
63
|
-
interface TelemetrySignal {
|
|
64
|
-
timestamp: string;
|
|
65
|
-
[key: string]: string | number | boolean | string[] | null;
|
|
66
|
-
}
|
|
1
|
+
import { D as DataAdapter } from './types-Be7Jc5V8.cjs';
|
|
2
|
+
import { a as ProveJobInputs } from './types-B6S0axfE.cjs';
|
|
67
3
|
|
|
68
4
|
/**
|
|
69
5
|
* DIMO Adapter Types
|
|
@@ -152,4 +88,4 @@ declare class DimoAdapter implements DataAdapter<DimoAdapterConfig, DimoQuery, D
|
|
|
152
88
|
*/
|
|
153
89
|
declare function createDimoAdapter(config: DimoAdapterConfig): DimoAdapter;
|
|
154
90
|
|
|
155
|
-
export {
|
|
91
|
+
export { DimoAdapter as D, type DimoAdapterConfig as a, type DimoQuery as b, createDimoAdapter as c, type DimoTelemetryData as d, type DimoSignal as e, type DimoClient as f };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { D as DimoAdapter, a as DimoAdapterConfig, f as DimoClient, b as DimoQuery, e as DimoSignal, d as DimoTelemetryData, c as createDimoAdapter } from '../../
|
|
2
|
-
import '../../types-
|
|
1
|
+
export { D as DimoAdapter, a as DimoAdapterConfig, f as DimoClient, b as DimoQuery, e as DimoSignal, d as DimoTelemetryData, c as createDimoAdapter } from '../../adapter-DyAYLtIy.cjs';
|
|
2
|
+
import '../../types-Be7Jc5V8.cjs';
|
|
3
|
+
import '../../types-B6S0axfE.cjs';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* DIMO GraphQL query builders
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { D as DimoAdapter, a as DimoAdapterConfig, f as DimoClient, b as DimoQuery, e as DimoSignal, d as DimoTelemetryData, c as createDimoAdapter } from '../../
|
|
2
|
-
import '../../types-
|
|
1
|
+
export { D as DimoAdapter, a as DimoAdapterConfig, f as DimoClient, b as DimoQuery, e as DimoSignal, d as DimoTelemetryData, c as createDimoAdapter } from '../../adapter-53dB8ogG.js';
|
|
2
|
+
import '../../types-D1-qiyJO.js';
|
|
3
|
+
import '../../types-B6S0axfE.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* DIMO GraphQL query builders
|
package/dist/adapters/index.cjs
CHANGED
|
@@ -78,6 +78,505 @@ var DimoAdapter = class {
|
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
+
// src/core/errors.ts
|
|
82
|
+
var BindError = class extends Error {
|
|
83
|
+
constructor(message, code, details) {
|
|
84
|
+
super(message);
|
|
85
|
+
this.code = code;
|
|
86
|
+
this.details = details;
|
|
87
|
+
this.name = "BindError";
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var ApiError = class extends BindError {
|
|
91
|
+
constructor(message, status, response) {
|
|
92
|
+
super(message, "API_ERROR", { status, response });
|
|
93
|
+
this.status = status;
|
|
94
|
+
this.response = response;
|
|
95
|
+
this.name = "ApiError";
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
var AuthenticationError = class extends BindError {
|
|
99
|
+
constructor(message = "Authentication failed") {
|
|
100
|
+
super(message, "AUTH_ERROR");
|
|
101
|
+
this.name = "AuthenticationError";
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var TimeoutError = class extends BindError {
|
|
105
|
+
constructor(message, timeoutMs) {
|
|
106
|
+
super(message, "TIMEOUT_ERROR", { timeoutMs });
|
|
107
|
+
this.timeoutMs = timeoutMs;
|
|
108
|
+
this.name = "TimeoutError";
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var InsufficientCreditsError = class extends BindError {
|
|
112
|
+
constructor(required, available) {
|
|
113
|
+
super(
|
|
114
|
+
`Insufficient credits: need ${required}, have ${available}`,
|
|
115
|
+
"INSUFFICIENT_CREDITS",
|
|
116
|
+
{ required, available }
|
|
117
|
+
);
|
|
118
|
+
this.required = required;
|
|
119
|
+
this.available = available;
|
|
120
|
+
this.name = "InsufficientCreditsError";
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var ZkTlsSessionExpiredError = class extends BindError {
|
|
124
|
+
constructor(sessionId) {
|
|
125
|
+
super(`zkTLS session expired: ${sessionId}`, "ZKTLS_SESSION_EXPIRED", { sessionId });
|
|
126
|
+
this.sessionId = sessionId;
|
|
127
|
+
this.name = "ZkTlsSessionExpiredError";
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var ZkTlsSessionFailedError = class extends BindError {
|
|
131
|
+
constructor(sessionId, sessionError) {
|
|
132
|
+
super(`zkTLS session failed: ${sessionError}`, "ZKTLS_SESSION_FAILED", { sessionId, sessionError });
|
|
133
|
+
this.sessionId = sessionId;
|
|
134
|
+
this.sessionError = sessionError;
|
|
135
|
+
this.name = "ZkTlsSessionFailedError";
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// src/core/client.ts
|
|
140
|
+
var DEFAULT_BASE_URL = "https://api.bindprotocol.com";
|
|
141
|
+
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
142
|
+
var DEFAULT_TIMEOUT_MS = 3e5;
|
|
143
|
+
var BindClient = class {
|
|
144
|
+
apiKey;
|
|
145
|
+
baseUrl;
|
|
146
|
+
headers;
|
|
147
|
+
constructor(options) {
|
|
148
|
+
this.apiKey = options.apiKey;
|
|
149
|
+
this.baseUrl = options.baseUrl || process.env.BIND_API_URL || DEFAULT_BASE_URL;
|
|
150
|
+
this.headers = {
|
|
151
|
+
"X-API-Key": this.apiKey,
|
|
152
|
+
"Content-Type": "application/json"
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// ==========================================================================
|
|
156
|
+
// Prove Job Methods
|
|
157
|
+
// ==========================================================================
|
|
158
|
+
/**
|
|
159
|
+
* Submit a prove job for async processing
|
|
160
|
+
* @param circuitId - The circuit identifier (e.g., "bind.mobility.riskband.v1")
|
|
161
|
+
* @param inputs - Circuit inputs as key-value pairs (all values must be strings)
|
|
162
|
+
* @returns The submitted job details
|
|
163
|
+
* @throws {ApiError} If the API request fails
|
|
164
|
+
* @throws {InsufficientCreditsError} If there aren't enough credits
|
|
165
|
+
*/
|
|
166
|
+
async submitProveJob(circuitId, inputs) {
|
|
167
|
+
const response = await this.fetch("/api/prove", {
|
|
168
|
+
method: "POST",
|
|
169
|
+
body: JSON.stringify({ circuitId, inputs })
|
|
170
|
+
});
|
|
171
|
+
const result = await response.json();
|
|
172
|
+
if (!result.success && result.requiredCredits !== void 0 && result.availableCredits !== void 0) {
|
|
173
|
+
throw new InsufficientCreditsError(result.requiredCredits, result.availableCredits);
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get the status and results of a prove job
|
|
179
|
+
* @param jobId - The unique job identifier
|
|
180
|
+
* @returns The job details including status and outputs
|
|
181
|
+
*/
|
|
182
|
+
async getProveJob(jobId) {
|
|
183
|
+
const response = await this.fetch(`/api/prove/${encodeURIComponent(jobId)}`);
|
|
184
|
+
return response.json();
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* List prove jobs for the authenticated organization
|
|
188
|
+
* @param options - Optional filters for status, limit, and offset
|
|
189
|
+
* @returns Paginated list of prove jobs
|
|
190
|
+
*/
|
|
191
|
+
async listProveJobs(options = {}) {
|
|
192
|
+
const params = new URLSearchParams();
|
|
193
|
+
if (options.status) params.set("status", options.status);
|
|
194
|
+
if (options.limit !== void 0) params.set("limit", options.limit.toString());
|
|
195
|
+
if (options.offset !== void 0) params.set("offset", options.offset.toString());
|
|
196
|
+
const queryString = params.toString();
|
|
197
|
+
const path = queryString ? `/api/prove?${queryString}` : "/api/prove";
|
|
198
|
+
const response = await this.fetch(path);
|
|
199
|
+
return response.json();
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Poll for prove job completion
|
|
203
|
+
* @param jobId - The unique job identifier
|
|
204
|
+
* @param options - Polling options
|
|
205
|
+
* @returns The completed or failed job
|
|
206
|
+
* @throws {TimeoutError} If the job doesn't complete within the timeout
|
|
207
|
+
*/
|
|
208
|
+
async waitForProveJob(jobId, options = {}) {
|
|
209
|
+
const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
210
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
211
|
+
const startTime = Date.now();
|
|
212
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
213
|
+
const result = await this.getProveJob(jobId);
|
|
214
|
+
if (!result.success || !result.data) {
|
|
215
|
+
throw new ApiError(
|
|
216
|
+
result.error || "Failed to get prove job",
|
|
217
|
+
500,
|
|
218
|
+
result
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
const job = result.data;
|
|
222
|
+
if (options.onProgress) {
|
|
223
|
+
options.onProgress(job);
|
|
224
|
+
}
|
|
225
|
+
if (job.status === "completed" || job.status === "failed") {
|
|
226
|
+
return job;
|
|
227
|
+
}
|
|
228
|
+
await this.sleep(intervalMs);
|
|
229
|
+
}
|
|
230
|
+
throw new TimeoutError(
|
|
231
|
+
`Timeout waiting for prove job ${jobId} after ${timeoutMs}ms`,
|
|
232
|
+
timeoutMs
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
// ==========================================================================
|
|
236
|
+
// Policy Methods (Public, no authentication required)
|
|
237
|
+
// ==========================================================================
|
|
238
|
+
/**
|
|
239
|
+
* List all available public policies
|
|
240
|
+
* @returns Array of public policy specifications
|
|
241
|
+
*/
|
|
242
|
+
async listPolicies() {
|
|
243
|
+
const response = await fetch(`${this.baseUrl}/api/policies`, {
|
|
244
|
+
method: "GET"
|
|
245
|
+
});
|
|
246
|
+
if (!response.ok) {
|
|
247
|
+
throw new ApiError(
|
|
248
|
+
`Failed to fetch policies: ${response.statusText}`,
|
|
249
|
+
response.status
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
const json = await response.json();
|
|
253
|
+
return json.data ?? json;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Get a specific policy by ID
|
|
257
|
+
* @param policyId - The unique policy identifier
|
|
258
|
+
* @returns The public policy specification, or null if not found
|
|
259
|
+
*/
|
|
260
|
+
async getPolicy(policyId) {
|
|
261
|
+
const response = await fetch(
|
|
262
|
+
`${this.baseUrl}/api/policies/${encodeURIComponent(policyId)}`,
|
|
263
|
+
{ method: "GET" }
|
|
264
|
+
);
|
|
265
|
+
if (response.status === 404) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
if (!response.ok) {
|
|
269
|
+
throw new ApiError(
|
|
270
|
+
`Failed to fetch policy: ${response.statusText}`,
|
|
271
|
+
response.status
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
const json = await response.json();
|
|
275
|
+
return json.data ?? json;
|
|
276
|
+
}
|
|
277
|
+
// ==========================================================================
|
|
278
|
+
// zkTLS Methods
|
|
279
|
+
// ==========================================================================
|
|
280
|
+
/**
|
|
281
|
+
* List available zkTLS extractors (data sources)
|
|
282
|
+
* @returns Array of available extractors
|
|
283
|
+
*/
|
|
284
|
+
async listExtractors() {
|
|
285
|
+
const response = await this.fetch("/api/zktls/extractors");
|
|
286
|
+
return response.json();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* List zkTLS attestations for the authenticated organization
|
|
290
|
+
* @returns Array of attestations
|
|
291
|
+
*/
|
|
292
|
+
async listAttestations() {
|
|
293
|
+
const response = await this.fetch("/api/zktls/attestations");
|
|
294
|
+
return response.json();
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get a specific attestation by ID
|
|
298
|
+
* @param attestationId - The attestation UUID
|
|
299
|
+
* @returns The attestation or null if not found
|
|
300
|
+
*/
|
|
301
|
+
async getAttestation(attestationId) {
|
|
302
|
+
const response = await this.fetch(`/api/zktls/attestations/${encodeURIComponent(attestationId)}`);
|
|
303
|
+
return response.json();
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Create a new zkTLS session for data attestation
|
|
307
|
+
* @param extractorId - The extractor to use (e.g., "coinbase")
|
|
308
|
+
* @param callbackUrl - URL to redirect to after authentication
|
|
309
|
+
* @returns Session ID and auth URL to redirect user to
|
|
310
|
+
*/
|
|
311
|
+
async createZkTlsSession(extractorId, callbackUrl) {
|
|
312
|
+
const response = await this.fetch("/api/zktls/sessions", {
|
|
313
|
+
method: "POST",
|
|
314
|
+
body: JSON.stringify({ extractor: extractorId, callbackUrl })
|
|
315
|
+
});
|
|
316
|
+
return response.json();
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Get the status of a zkTLS session
|
|
320
|
+
* @param sessionId - The session UUID
|
|
321
|
+
* @returns Session status and attestation if completed
|
|
322
|
+
*/
|
|
323
|
+
async getZkTlsSession(sessionId) {
|
|
324
|
+
const response = await this.fetch(`/api/zktls/sessions/${encodeURIComponent(sessionId)}`);
|
|
325
|
+
return response.json();
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Wait for a zkTLS session to complete
|
|
329
|
+
* @param sessionId - The session UUID
|
|
330
|
+
* @param options - Polling options
|
|
331
|
+
* @returns The completed session with attestation
|
|
332
|
+
* @throws {ZkTlsSessionExpiredError} If session expires
|
|
333
|
+
* @throws {ZkTlsSessionFailedError} If session fails
|
|
334
|
+
* @throws {TimeoutError} If timeout is reached
|
|
335
|
+
*/
|
|
336
|
+
async waitForZkTlsSession(sessionId, options = {}) {
|
|
337
|
+
const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
338
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
339
|
+
const startTime = Date.now();
|
|
340
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
341
|
+
const result = await this.getZkTlsSession(sessionId);
|
|
342
|
+
if (!result.success || !result.data) {
|
|
343
|
+
throw new ApiError(
|
|
344
|
+
result.error || "Failed to get zkTLS session",
|
|
345
|
+
500,
|
|
346
|
+
result
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
const session = result.data;
|
|
350
|
+
if (options.onProgress) {
|
|
351
|
+
options.onProgress(session);
|
|
352
|
+
}
|
|
353
|
+
if (session.status === "completed") {
|
|
354
|
+
return session;
|
|
355
|
+
}
|
|
356
|
+
if (session.status === "failed") {
|
|
357
|
+
throw new ZkTlsSessionFailedError(sessionId, session.error || "Unknown error");
|
|
358
|
+
}
|
|
359
|
+
if (session.status === "expired") {
|
|
360
|
+
throw new ZkTlsSessionExpiredError(sessionId);
|
|
361
|
+
}
|
|
362
|
+
await this.sleep(intervalMs);
|
|
363
|
+
}
|
|
364
|
+
throw new TimeoutError(
|
|
365
|
+
`Timeout waiting for zkTLS session ${sessionId} after ${timeoutMs}ms`,
|
|
366
|
+
timeoutMs
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
// ==========================================================================
|
|
370
|
+
// Circuit Methods
|
|
371
|
+
// ==========================================================================
|
|
372
|
+
/**
|
|
373
|
+
* List available circuits
|
|
374
|
+
* @param options - Optional filters
|
|
375
|
+
* @returns Array of circuits
|
|
376
|
+
*/
|
|
377
|
+
async listCircuits(options = {}) {
|
|
378
|
+
const params = new URLSearchParams();
|
|
379
|
+
if (options.status) params.set("status", options.status);
|
|
380
|
+
if (options.policyId) params.set("policyId", options.policyId);
|
|
381
|
+
const queryString = params.toString();
|
|
382
|
+
const path = queryString ? `/api/circuits?${queryString}` : "/api/circuits";
|
|
383
|
+
const response = await this.fetch(path);
|
|
384
|
+
return response.json();
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Get a specific circuit by ID
|
|
388
|
+
* @param circuitId - The circuit identifier
|
|
389
|
+
* @returns The circuit details or null if not found
|
|
390
|
+
*/
|
|
391
|
+
async getCircuit(circuitId) {
|
|
392
|
+
const response = await this.fetch(`/api/circuits/${encodeURIComponent(circuitId)}`);
|
|
393
|
+
return response.json();
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Activate a circuit (requires validation to have passed)
|
|
397
|
+
* @param circuitId - The circuit identifier to activate
|
|
398
|
+
* @returns The activation result
|
|
399
|
+
*/
|
|
400
|
+
async activateCircuit(circuitId) {
|
|
401
|
+
const response = await this.fetch(`/api/circuits/${encodeURIComponent(circuitId)}/activate`, {
|
|
402
|
+
method: "POST"
|
|
403
|
+
});
|
|
404
|
+
return response.json();
|
|
405
|
+
}
|
|
406
|
+
// ==========================================================================
|
|
407
|
+
// Private Helpers
|
|
408
|
+
// ==========================================================================
|
|
409
|
+
async fetch(path, init) {
|
|
410
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
411
|
+
...init,
|
|
412
|
+
headers: {
|
|
413
|
+
...this.headers,
|
|
414
|
+
...init?.headers
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
if (response.status === 401) {
|
|
418
|
+
throw new AuthenticationError();
|
|
419
|
+
}
|
|
420
|
+
return response;
|
|
421
|
+
}
|
|
422
|
+
sleep(ms) {
|
|
423
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
// src/adapters/zktls/adapter.ts
|
|
428
|
+
var ZkTlsAdapter = class {
|
|
429
|
+
client;
|
|
430
|
+
constructor(config) {
|
|
431
|
+
this.client = new BindClient({
|
|
432
|
+
apiKey: config.apiKey,
|
|
433
|
+
baseUrl: config.baseUrl
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Fetch attestation data - either from existing attestation or by creating session
|
|
438
|
+
*/
|
|
439
|
+
async fetchData(query) {
|
|
440
|
+
if (query.attestationId) {
|
|
441
|
+
return this.fetchExistingAttestation(query.attestationId);
|
|
442
|
+
}
|
|
443
|
+
if (query.callbackUrl) {
|
|
444
|
+
return this.initiateSession(query.callbackUrl);
|
|
445
|
+
}
|
|
446
|
+
throw new Error("Either attestationId or callbackUrl must be provided");
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Get supported circuits
|
|
450
|
+
*/
|
|
451
|
+
getSupportedCircuits() {
|
|
452
|
+
return [...this.supportedCircuits];
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Create a zkTLS session and return the auth URL
|
|
456
|
+
* Client should redirect user to this URL
|
|
457
|
+
*/
|
|
458
|
+
async createSession(callbackUrl) {
|
|
459
|
+
const result = await this.client.createZkTlsSession(this.extractorId, callbackUrl);
|
|
460
|
+
if (!result.success || !result.data) {
|
|
461
|
+
throw new Error(result.error || "Failed to create zkTLS session");
|
|
462
|
+
}
|
|
463
|
+
return result.data;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Wait for session completion and return attestation
|
|
467
|
+
*/
|
|
468
|
+
async waitForSession(sessionId, options) {
|
|
469
|
+
const session = await this.client.waitForZkTlsSession(sessionId, options);
|
|
470
|
+
if (!session.attestation) {
|
|
471
|
+
throw new Error("Session completed but no attestation found");
|
|
472
|
+
}
|
|
473
|
+
const extractors = await this.client.listExtractors();
|
|
474
|
+
const extractor = extractors.data?.find((e) => e.id === this.extractorId);
|
|
475
|
+
if (!extractor) {
|
|
476
|
+
throw new Error(`Extractor not found: ${this.extractorId}`);
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
attestation: session.attestation,
|
|
480
|
+
extractor
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
// ===========================================================================
|
|
484
|
+
// Protected helpers
|
|
485
|
+
// ===========================================================================
|
|
486
|
+
async fetchExistingAttestation(attestationId) {
|
|
487
|
+
const result = await this.client.getAttestation(attestationId);
|
|
488
|
+
if (!result.success || !result.data) {
|
|
489
|
+
throw new Error(result.error || "Attestation not found");
|
|
490
|
+
}
|
|
491
|
+
const extractors = await this.client.listExtractors();
|
|
492
|
+
const extractor = extractors.data?.find((e) => e.id === result.data.extractor);
|
|
493
|
+
if (!extractor) {
|
|
494
|
+
throw new Error(`Extractor not found: ${result.data.extractor}`);
|
|
495
|
+
}
|
|
496
|
+
return {
|
|
497
|
+
attestation: result.data,
|
|
498
|
+
extractor
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
async initiateSession(callbackUrl) {
|
|
502
|
+
const { sessionId } = await this.createSession(callbackUrl);
|
|
503
|
+
return this.waitForSession(sessionId);
|
|
504
|
+
}
|
|
505
|
+
validateCircuit(circuitId) {
|
|
506
|
+
if (!this.supportedCircuits.includes(circuitId)) {
|
|
507
|
+
throw new Error(
|
|
508
|
+
`Circuit "${circuitId}" is not supported by ${this.name}. Supported circuits: ${this.supportedCircuits.join(", ")}`
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// src/adapters/zktls/coinbase.ts
|
|
515
|
+
var SUPPORTED_CIRCUITS2 = [
|
|
516
|
+
"bind.identity.kyc.v1",
|
|
517
|
+
"bind.identity.coinbase.v1"
|
|
518
|
+
];
|
|
519
|
+
var CoinbaseAdapter = class extends ZkTlsAdapter {
|
|
520
|
+
id = "coinbase-kyc";
|
|
521
|
+
name = "Coinbase KYC";
|
|
522
|
+
description = "Fetches KYC verification status from Coinbase via zkTLS attestation";
|
|
523
|
+
extractorId = "coinbase";
|
|
524
|
+
supportedCircuits = SUPPORTED_CIRCUITS2;
|
|
525
|
+
constructor(config) {
|
|
526
|
+
super(config);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Transform Coinbase attestation to circuit inputs
|
|
530
|
+
*/
|
|
531
|
+
toCircuitInputs(data, circuitId) {
|
|
532
|
+
this.validateCircuit(circuitId);
|
|
533
|
+
const claims = data.attestation.claims;
|
|
534
|
+
switch (circuitId) {
|
|
535
|
+
case "bind.identity.kyc.v1":
|
|
536
|
+
return this.toKycInputs(data, claims);
|
|
537
|
+
case "bind.identity.coinbase.v1":
|
|
538
|
+
return this.toCoinbaseInputs(data, claims);
|
|
539
|
+
default:
|
|
540
|
+
throw new Error(`No input transformer for circuit: ${circuitId}`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// ===========================================================================
|
|
544
|
+
// Private transformers
|
|
545
|
+
// ===========================================================================
|
|
546
|
+
toKycInputs(data, claims) {
|
|
547
|
+
return {
|
|
548
|
+
kycVerified: String(claims.kyc_verified),
|
|
549
|
+
kycLevel: String(claims.kyc_level ?? 0),
|
|
550
|
+
countryCode: claims.country_code ?? "",
|
|
551
|
+
attestationId: data.attestation.id,
|
|
552
|
+
witnessId: data.attestation.witness.id,
|
|
553
|
+
signature: data.attestation.signature,
|
|
554
|
+
timestamp: String(data.attestation.createdAt)
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
toCoinbaseInputs(data, claims) {
|
|
558
|
+
return {
|
|
559
|
+
kycVerified: String(claims.kyc_verified),
|
|
560
|
+
kycLevel: String(claims.kyc_level ?? 0),
|
|
561
|
+
countryCode: claims.country_code ?? "",
|
|
562
|
+
accountCreatedAt: claims.account_created_at ?? "",
|
|
563
|
+
attestationId: data.attestation.id,
|
|
564
|
+
witnessId: data.attestation.witness.id,
|
|
565
|
+
witnessPublicKey: data.attestation.witness.publicKey,
|
|
566
|
+
signature: data.attestation.signature,
|
|
567
|
+
url: data.attestation.url,
|
|
568
|
+
method: data.attestation.method,
|
|
569
|
+
expiresAt: String(data.attestation.expiresAt)
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
function createCoinbaseAdapter(config) {
|
|
574
|
+
return new CoinbaseAdapter(config);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
exports.CoinbaseAdapter = CoinbaseAdapter;
|
|
81
578
|
exports.DimoAdapter = DimoAdapter;
|
|
579
|
+
exports.ZkTlsAdapter = ZkTlsAdapter;
|
|
580
|
+
exports.createCoinbaseAdapter = createCoinbaseAdapter;
|
|
82
581
|
//# sourceMappingURL=index.cjs.map
|
|
83
582
|
//# sourceMappingURL=index.cjs.map
|