@bind-protocol/sdk 0.8.0 → 0.9.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.
Files changed (36) hide show
  1. package/README.md +7 -11
  2. package/dist/{adapter-LeDOUfnn.d.ts → adapter-J6D9MZJV.d.ts} +2 -2
  3. package/dist/{adapter-DBvPax2O.d.cts → adapter-qe9f1ll3.d.cts} +2 -2
  4. package/dist/adapters/dimo/index.d.cts +3 -3
  5. package/dist/adapters/dimo/index.d.ts +3 -3
  6. package/dist/adapters/index.cjs +113 -138
  7. package/dist/adapters/index.cjs.map +1 -1
  8. package/dist/adapters/index.d.cts +4 -4
  9. package/dist/adapters/index.d.ts +4 -4
  10. package/dist/adapters/index.js +113 -138
  11. package/dist/adapters/index.js.map +1 -1
  12. package/dist/adapters/zktls/index.cjs +113 -138
  13. package/dist/adapters/zktls/index.cjs.map +1 -1
  14. package/dist/adapters/zktls/index.d.cts +3 -3
  15. package/dist/adapters/zktls/index.d.ts +3 -3
  16. package/dist/adapters/zktls/index.js +113 -138
  17. package/dist/adapters/zktls/index.js.map +1 -1
  18. package/dist/{client-Dlp02kxb.d.cts → client-CfYXpFLk.d.cts} +70 -32
  19. package/dist/{client-BsloIjSG.d.ts → client-CpJ87Xe0.d.ts} +70 -32
  20. package/dist/core/index.cjs +107 -125
  21. package/dist/core/index.cjs.map +1 -1
  22. package/dist/core/index.d.cts +2 -2
  23. package/dist/core/index.d.ts +2 -2
  24. package/dist/core/index.js +107 -125
  25. package/dist/core/index.js.map +1 -1
  26. package/dist/index.cjs +113 -138
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +4 -4
  29. package/dist/index.d.ts +4 -4
  30. package/dist/index.js +113 -138
  31. package/dist/index.js.map +1 -1
  32. package/dist/{types-D5XJykY-.d.cts → types-BcPssdQk.d.cts} +30 -174
  33. package/dist/{types-D5XJykY-.d.ts → types-BcPssdQk.d.ts} +30 -174
  34. package/dist/{types-CXWgNPXN.d.ts → types-D7Q7ymPa.d.ts} +1 -1
  35. package/dist/{types-D-cTYE3o.d.cts → types-ywkMNwun.d.cts} +1 -1
  36. package/package.json +1 -1
package/README.md CHANGED
@@ -18,13 +18,13 @@ const client = new BindClient({
18
18
  });
19
19
 
20
20
  // Submit a prove job
21
- const result = await client.submitProveJob('bind.mobility.riskband.v1', {
21
+ const { jobId } = await client.submitProveJob('bind.mobility.riskband.v1', {
22
22
  signals: JSON.stringify(telemetryData),
23
23
  timestamp: new Date().toISOString(),
24
24
  });
25
25
 
26
26
  // Wait for completion
27
- const job = await client.waitForProveJob(result.data.jobId);
27
+ const job = await client.waitForProveJob(jobId);
28
28
 
29
29
  if (job.status === 'completed') {
30
30
  console.log('Proof generated:', job.attestationId);
@@ -230,14 +230,10 @@ async function generateRiskCredential(vehicleTokenId: string) {
230
230
 
231
231
  // 3. Transform and submit prove job
232
232
  const inputs = dimo.toCircuitInputs(telemetry, 'bind.mobility.riskband.v1');
233
- const result = await bind.submitProveJob('bind.mobility.riskband.v1', inputs);
234
-
235
- if (!result.success) {
236
- throw new Error(result.error);
237
- }
233
+ const { jobId } = await bind.submitProveJob('bind.mobility.riskband.v1', inputs);
238
234
 
239
235
  // 4. Wait for proof generation
240
- const job = await bind.waitForProveJob(result.data.jobId, {
236
+ const job = await bind.waitForProveJob(jobId, {
241
237
  onProgress: (j) => console.log(`Status: ${j.status}`),
242
238
  });
243
239
 
@@ -268,10 +264,10 @@ import type {
268
264
  ProveJobInputs,
269
265
  ProveJob,
270
266
  ProveJobSummary,
271
- SubmitProveJobResponse,
272
- GetProveJobResponse,
267
+ SubmitProveJobResult,
273
268
  ListProveJobsOptions,
274
- ListProveJobsResponse,
269
+ Pagination,
270
+ PollOptions,
275
271
 
276
272
  // Credential types
277
273
  BindCredential,
@@ -1,5 +1,5 @@
1
- import { D as DataAdapter } from './types-CXWgNPXN.js';
2
- import { a as ProveJobInputs } from './types-D5XJykY-.js';
1
+ import { D as DataAdapter } from './types-D7Q7ymPa.js';
2
+ import { c as ProveJobInputs } from './types-BcPssdQk.js';
3
3
 
4
4
  /**
5
5
  * DIMO Adapter Types
@@ -1,5 +1,5 @@
1
- import { D as DataAdapter } from './types-D-cTYE3o.cjs';
2
- import { a as ProveJobInputs } from './types-D5XJykY-.cjs';
1
+ import { D as DataAdapter } from './types-ywkMNwun.cjs';
2
+ import { c as ProveJobInputs } from './types-BcPssdQk.cjs';
3
3
 
4
4
  /**
5
5
  * DIMO Adapter Types
@@ -1,6 +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 '../../adapter-DBvPax2O.cjs';
2
- import '../../types-D-cTYE3o.cjs';
3
- import '../../types-D5XJykY-.cjs';
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-qe9f1ll3.cjs';
2
+ import '../../types-ywkMNwun.cjs';
3
+ import '../../types-BcPssdQk.cjs';
4
4
  import '@bind-protocol/policy-spec';
5
5
 
6
6
  /**
@@ -1,6 +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 '../../adapter-LeDOUfnn.js';
2
- import '../../types-CXWgNPXN.js';
3
- import '../../types-D5XJykY-.js';
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-J6D9MZJV.js';
2
+ import '../../types-D7Q7ymPa.js';
3
+ import '../../types-BcPssdQk.js';
4
4
  import '@bind-protocol/policy-spec';
5
5
 
6
6
  /**
@@ -165,33 +165,42 @@ var BindClient = class {
165
165
  * @throws {InsufficientCreditsError} If there aren't enough credits
166
166
  */
167
167
  async submitProveJob(circuitId, inputs, options) {
168
- const response = await this.fetch("/api/prove", {
169
- method: "POST",
170
- body: JSON.stringify({
171
- circuitId,
172
- inputs,
173
- verificationMode: options?.verificationMode
174
- })
175
- });
176
- const result = await response.json();
177
- if (!result.success && result.requiredCredits !== void 0 && result.availableCredits !== void 0) {
178
- throw new InsufficientCreditsError(result.requiredCredits, result.availableCredits);
168
+ try {
169
+ return await this.fetchJson("/api/prove", {
170
+ method: "POST",
171
+ body: JSON.stringify({
172
+ circuitId,
173
+ inputs,
174
+ verificationMode: options?.verificationMode
175
+ })
176
+ });
177
+ } catch (err) {
178
+ if (err instanceof ApiError && err.response) {
179
+ const body = err.response;
180
+ if (body.requiredCredits !== void 0 && body.availableCredits !== void 0) {
181
+ throw new InsufficientCreditsError(
182
+ body.requiredCredits,
183
+ body.availableCredits
184
+ );
185
+ }
186
+ }
187
+ throw err;
179
188
  }
180
- return result;
181
189
  }
182
190
  /**
183
191
  * Get the status and results of a prove job
184
192
  * @param jobId - The unique job identifier
185
193
  * @returns The job details including status and outputs
194
+ * @throws {ApiError} If the API request fails
186
195
  */
187
196
  async getProveJob(jobId) {
188
- const response = await this.fetch(`/api/prove/${encodeURIComponent(jobId)}`);
189
- return response.json();
197
+ return this.fetchJson(`/api/prove/${encodeURIComponent(jobId)}`);
190
198
  }
191
199
  /**
192
200
  * List prove jobs for the authenticated organization
193
201
  * @param options - Optional filters for status, limit, and offset
194
202
  * @returns Paginated list of prove jobs
203
+ * @throws {ApiError} If the API request fails
195
204
  */
196
205
  async listProveJobs(options = {}) {
197
206
  const params = new URLSearchParams();
@@ -200,8 +209,7 @@ var BindClient = class {
200
209
  if (options.offset !== void 0) params.set("offset", options.offset.toString());
201
210
  const queryString = params.toString();
202
211
  const path = queryString ? `/api/prove?${queryString}` : "/api/prove";
203
- const response = await this.fetch(path);
204
- return response.json();
212
+ return this.fetchJson(path);
205
213
  }
206
214
  /**
207
215
  * Poll for prove job completion
@@ -209,21 +217,14 @@ var BindClient = class {
209
217
  * @param options - Polling options
210
218
  * @returns The completed or failed job
211
219
  * @throws {TimeoutError} If the job doesn't complete within the timeout
220
+ * @throws {ApiError} If the API request fails
212
221
  */
213
222
  async waitForProveJob(jobId, options = {}) {
214
223
  const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
215
224
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
216
225
  const startTime = Date.now();
217
226
  while (Date.now() - startTime < timeoutMs) {
218
- const result = await this.getProveJob(jobId);
219
- if (!result.success || !result.data) {
220
- throw new ApiError(
221
- result.error || "Failed to get prove job",
222
- 500,
223
- result
224
- );
225
- }
226
- const job = result.data;
227
+ const job = await this.getProveJob(jobId);
227
228
  if (options.onProgress) {
228
229
  options.onProgress(job);
229
230
  }
@@ -243,41 +244,28 @@ var BindClient = class {
243
244
  /**
244
245
  * List all available public policies
245
246
  * @returns Array of public policy specifications
247
+ * @throws {ApiError} If the API request fails
246
248
  */
247
249
  async listPolicies() {
248
- const response = await fetch(`${this.baseUrl}/api/policies`, {
249
- method: "GET"
250
- });
251
- if (!response.ok) {
252
- throw new ApiError(
253
- `Failed to fetch policies: ${response.statusText}`,
254
- response.status
255
- );
256
- }
257
- const json = await response.json();
258
- return json.data ?? json;
250
+ return this.fetchJson("/api/policies");
259
251
  }
260
252
  /**
261
253
  * Get a specific policy by ID
262
254
  * @param policyId - The unique policy identifier
263
255
  * @returns The public policy specification, or null if not found
256
+ * @throws {ApiError} If the API request fails (except 404)
264
257
  */
265
258
  async getPolicy(policyId) {
266
- const response = await fetch(
267
- `${this.baseUrl}/api/policies/${encodeURIComponent(policyId)}`,
268
- { method: "GET" }
269
- );
270
- if (response.status === 404) {
271
- return null;
272
- }
273
- if (!response.ok) {
274
- throw new ApiError(
275
- `Failed to fetch policy: ${response.statusText}`,
276
- response.status
259
+ try {
260
+ return await this.fetchJson(
261
+ `/api/policies/${encodeURIComponent(policyId)}`
277
262
  );
263
+ } catch (err) {
264
+ if (err instanceof ApiError && err.status === 404) {
265
+ return null;
266
+ }
267
+ throw err;
278
268
  }
279
- const json = await response.json();
280
- return json.data ?? json;
281
269
  }
282
270
  // ==========================================================================
283
271
  // zkTLS Methods
@@ -285,49 +273,49 @@ var BindClient = class {
285
273
  /**
286
274
  * List available zkTLS extractors (data sources)
287
275
  * @returns Array of available extractors
276
+ * @throws {ApiError} If the API request fails
288
277
  */
289
278
  async listExtractors() {
290
- const response = await this.fetch("/api/zktls/extractors");
291
- return response.json();
279
+ return this.fetchJson("/api/zktls/extractors");
292
280
  }
293
281
  /**
294
282
  * List zkTLS attestations for the authenticated organization
295
283
  * @returns Array of attestations
284
+ * @throws {ApiError} If the API request fails
296
285
  */
297
286
  async listAttestations() {
298
- const response = await this.fetch("/api/zktls/attestations");
299
- return response.json();
287
+ return this.fetchJson("/api/zktls/attestations");
300
288
  }
301
289
  /**
302
290
  * Get a specific attestation by ID
303
291
  * @param attestationId - The attestation UUID
304
- * @returns The attestation or null if not found
292
+ * @returns The attestation details
293
+ * @throws {ApiError} If the API request fails
305
294
  */
306
295
  async getAttestation(attestationId) {
307
- const response = await this.fetch(`/api/zktls/attestations/${encodeURIComponent(attestationId)}`);
308
- return response.json();
296
+ return this.fetchJson(`/api/zktls/attestations/${encodeURIComponent(attestationId)}`);
309
297
  }
310
298
  /**
311
299
  * Create a new zkTLS session for data attestation
312
300
  * @param extractorId - The extractor to use (e.g., "coinbase")
313
301
  * @param callbackUrl - URL to redirect to after authentication
314
302
  * @returns Session ID and auth URL to redirect user to
303
+ * @throws {ApiError} If the API request fails
315
304
  */
316
305
  async createZkTlsSession(extractorId, callbackUrl) {
317
- const response = await this.fetch("/api/zktls/sessions", {
306
+ return this.fetchJson("/api/zktls/sessions", {
318
307
  method: "POST",
319
308
  body: JSON.stringify({ extractor: extractorId, callbackUrl })
320
309
  });
321
- return response.json();
322
310
  }
323
311
  /**
324
312
  * Get the status of a zkTLS session
325
313
  * @param sessionId - The session UUID
326
314
  * @returns Session status and attestation if completed
315
+ * @throws {ApiError} If the API request fails
327
316
  */
328
317
  async getZkTlsSession(sessionId) {
329
- const response = await this.fetch(`/api/zktls/sessions/${encodeURIComponent(sessionId)}`);
330
- return response.json();
318
+ return this.fetchJson(`/api/zktls/sessions/${encodeURIComponent(sessionId)}`);
331
319
  }
332
320
  /**
333
321
  * Wait for a zkTLS session to complete
@@ -337,21 +325,14 @@ var BindClient = class {
337
325
  * @throws {ZkTlsSessionExpiredError} If session expires
338
326
  * @throws {ZkTlsSessionFailedError} If session fails
339
327
  * @throws {TimeoutError} If timeout is reached
328
+ * @throws {ApiError} If the API request fails
340
329
  */
341
330
  async waitForZkTlsSession(sessionId, options = {}) {
342
331
  const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
343
332
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
344
333
  const startTime = Date.now();
345
334
  while (Date.now() - startTime < timeoutMs) {
346
- const result = await this.getZkTlsSession(sessionId);
347
- if (!result.success || !result.data) {
348
- throw new ApiError(
349
- result.error || "Failed to get zkTLS session",
350
- 500,
351
- result
352
- );
353
- }
354
- const session = result.data;
335
+ const session = await this.getZkTlsSession(sessionId);
355
336
  if (options.onProgress) {
356
337
  options.onProgress(session);
357
338
  }
@@ -378,6 +359,7 @@ var BindClient = class {
378
359
  * List available circuits
379
360
  * @param options - Optional filters
380
361
  * @returns Array of circuits
362
+ * @throws {ApiError} If the API request fails
381
363
  */
382
364
  async listCircuits(options = {}) {
383
365
  const params = new URLSearchParams();
@@ -385,28 +367,27 @@ var BindClient = class {
385
367
  if (options.policyId) params.set("policyId", options.policyId);
386
368
  const queryString = params.toString();
387
369
  const path = queryString ? `/api/circuits?${queryString}` : "/api/circuits";
388
- const response = await this.fetch(path);
389
- return response.json();
370
+ return this.fetchJson(path);
390
371
  }
391
372
  /**
392
373
  * Get a specific circuit by ID
393
374
  * @param circuitId - The circuit identifier
394
- * @returns The circuit details or null if not found
375
+ * @returns The circuit details
376
+ * @throws {ApiError} If the API request fails
395
377
  */
396
378
  async getCircuit(circuitId) {
397
- const response = await this.fetch(`/api/circuits/${encodeURIComponent(circuitId)}`);
398
- return response.json();
379
+ return this.fetchJson(`/api/circuits/${encodeURIComponent(circuitId)}`);
399
380
  }
400
381
  /**
401
382
  * Activate a circuit (requires validation to have passed)
402
383
  * @param circuitId - The circuit identifier to activate
403
384
  * @returns The activation result
385
+ * @throws {ApiError} If the API request fails
404
386
  */
405
387
  async activateCircuit(circuitId) {
406
- const response = await this.fetch(`/api/circuits/${encodeURIComponent(circuitId)}/activate`, {
388
+ return this.fetchJson(`/api/circuits/${encodeURIComponent(circuitId)}/activate`, {
407
389
  method: "POST"
408
390
  });
409
- return response.json();
410
391
  }
411
392
  // ==========================================================================
412
393
  // Shared Proof Methods
@@ -415,18 +396,19 @@ var BindClient = class {
415
396
  * Share a completed proof with a verifier organization
416
397
  * @param request - Share proof request with proveJobId and verifierOrgId
417
398
  * @returns The created shared proof
399
+ * @throws {ApiError} If the API request fails
418
400
  */
419
401
  async shareProof(request) {
420
- const response = await this.fetch("/api/shared-proofs", {
402
+ return this.fetchJson("/api/shared-proofs", {
421
403
  method: "POST",
422
404
  body: JSON.stringify(request)
423
405
  });
424
- return response.json();
425
406
  }
426
407
  /**
427
408
  * List shared proofs (outgoing or incoming)
428
409
  * @param options - Filter by direction, pagination, and inclusion options
429
410
  * @returns Paginated list of shared proofs
411
+ * @throws {ApiError} If the API request fails
430
412
  */
431
413
  async listSharedProofs(options = {}) {
432
414
  const params = new URLSearchParams();
@@ -437,28 +419,27 @@ var BindClient = class {
437
419
  if (options.includeRevoked) params.set("includeRevoked", "true");
438
420
  const queryString = params.toString();
439
421
  const path = queryString ? `/api/shared-proofs?${queryString}` : "/api/shared-proofs";
440
- const response = await this.fetch(path);
441
- return response.json();
422
+ return this.fetchJson(path);
442
423
  }
443
424
  /**
444
425
  * Get a specific shared proof by ID
445
426
  * @param sharedProofId - The shared proof ID
446
427
  * @returns The shared proof details
428
+ * @throws {ApiError} If the API request fails
447
429
  */
448
430
  async getSharedProof(sharedProofId) {
449
- const response = await this.fetch(`/api/shared-proofs/${encodeURIComponent(sharedProofId)}`);
450
- return response.json();
431
+ return this.fetchJson(`/api/shared-proofs/${encodeURIComponent(sharedProofId)}`);
451
432
  }
452
433
  /**
453
434
  * Revoke a shared proof. Only the sharing organization can revoke.
454
435
  * @param sharedProofId - The shared proof ID to revoke
455
436
  * @returns The revocation result
437
+ * @throws {ApiError} If the API request fails
456
438
  */
457
439
  async revokeSharedProof(sharedProofId) {
458
- const response = await this.fetch(`/api/shared-proofs/${encodeURIComponent(sharedProofId)}`, {
440
+ return this.fetchJson(`/api/shared-proofs/${encodeURIComponent(sharedProofId)}`, {
459
441
  method: "DELETE"
460
442
  });
461
- return response.json();
462
443
  }
463
444
  // ==========================================================================
464
445
  // Verification Methods
@@ -472,84 +453,70 @@ var BindClient = class {
472
453
  * @param sharedProofId - The shared proof ID to verify
473
454
  * @param options - Optional polling configuration
474
455
  * @returns The verification result
456
+ * @throws {ApiError} If the API request fails
457
+ * @throws {TimeoutError} If verification doesn't complete within the timeout
475
458
  */
476
459
  async verifySharedProof(sharedProofId, options) {
477
- const pollIntervalMs = options?.pollIntervalMs ?? 1e3;
478
- const maxWaitMs = options?.maxWaitMs ?? 12e4;
479
- const queueResponse = await this.fetch(`/api/verify/shared/${encodeURIComponent(sharedProofId)}`, {
460
+ const intervalMs = options?.intervalMs ?? 1e3;
461
+ const timeoutMs = options?.timeoutMs ?? 12e4;
462
+ const queueResult = await this.fetchJson(`/api/verify/shared/${encodeURIComponent(sharedProofId)}`, {
480
463
  method: "POST"
481
464
  });
482
- const queueResult = await queueResponse.json();
483
- if (!queueResult.success || !queueResult.data?.jobId) {
484
- return {
485
- success: false,
486
- error: queueResult.error ?? "Failed to queue verification job"
487
- };
488
- }
489
- const jobId = queueResult.data.jobId;
465
+ const jobId = queueResult.jobId;
490
466
  const startTime = Date.now();
491
- while (Date.now() - startTime < maxWaitMs) {
467
+ while (Date.now() - startTime < timeoutMs) {
492
468
  const statusResult = await this.getVerifyJobStatus(jobId);
493
- if (!statusResult.success) {
494
- return {
495
- success: false,
496
- error: statusResult.error ?? "Failed to get verification status"
497
- };
498
- }
499
- const status = statusResult.data?.status;
500
- if (status === "completed" || status === "failed") {
469
+ if (statusResult.status === "completed" || statusResult.status === "failed") {
501
470
  return {
502
- success: true,
503
- data: {
504
- isValid: statusResult.data?.isValid ?? false,
505
- error: statusResult.data?.error,
506
- verificationTimeMs: statusResult.data?.verificationTimeMs ?? 0,
507
- creditsCharged: statusResult.data?.creditsCharged ?? queueResult.data.creditsCharged,
508
- verificationResultId: statusResult.data?.verificationResultId ?? jobId,
509
- publicInputs: statusResult.data?.publicInputs
510
- }
471
+ isValid: statusResult.isValid ?? false,
472
+ error: statusResult.error,
473
+ verificationTimeMs: statusResult.verificationTimeMs ?? 0,
474
+ creditsCharged: statusResult.creditsCharged ?? queueResult.creditsCharged,
475
+ verificationResultId: statusResult.verificationResultId ?? jobId,
476
+ publicInputs: statusResult.publicInputs
511
477
  };
512
478
  }
513
- await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
479
+ await this.sleep(intervalMs);
514
480
  }
515
- return {
516
- success: false,
517
- error: `Verification timed out after ${maxWaitMs}ms. Job ID: ${jobId}`
518
- };
481
+ throw new TimeoutError(
482
+ `Verification timed out after ${timeoutMs}ms. Job ID: ${jobId}`,
483
+ timeoutMs
484
+ );
519
485
  }
520
486
  /**
521
487
  * Get the status of a verification job
522
488
  * @param jobId - The verification job ID
523
- * @returns The job status
489
+ * @returns The job status data
490
+ * @throws {ApiError} If the API request fails
524
491
  */
525
492
  async getVerifyJobStatus(jobId) {
526
- const response = await this.fetch(`/api/verify/jobs/${encodeURIComponent(jobId)}`);
527
- return response.json();
493
+ return this.fetchJson(`/api/verify/jobs/${encodeURIComponent(jobId)}`);
528
494
  }
529
495
  /**
530
496
  * Verify an uploaded proof
531
497
  * @param proofBuffer - The proof binary as ArrayBuffer, Uint8Array, or Buffer
532
498
  * @param vkBuffer - The verification key binary as ArrayBuffer, Uint8Array, or Buffer
533
499
  * @returns The verification result
500
+ * @throws {ApiError} If the API request fails
534
501
  */
535
502
  async verifyUploadedProof(proofBuffer, vkBuffer) {
536
503
  const proofBytes = proofBuffer instanceof Uint8Array ? proofBuffer : new Uint8Array(proofBuffer);
537
504
  const vkBytes = vkBuffer instanceof Uint8Array ? vkBuffer : new Uint8Array(vkBuffer);
538
505
  const proofBase64 = typeof Buffer !== "undefined" ? Buffer.from(proofBytes).toString("base64") : btoa(String.fromCharCode(...proofBytes));
539
506
  const vkBase64 = typeof Buffer !== "undefined" ? Buffer.from(vkBytes).toString("base64") : btoa(String.fromCharCode(...vkBytes));
540
- const response = await this.fetch("/api/verify/upload", {
507
+ return this.fetchJson("/api/verify/upload", {
541
508
  method: "POST",
542
509
  body: JSON.stringify({
543
510
  proof: proofBase64,
544
511
  vk: vkBase64
545
512
  })
546
513
  });
547
- return response.json();
548
514
  }
549
515
  /**
550
516
  * Get verification history for the authenticated organization
551
517
  * @param options - Pagination options
552
518
  * @returns Paginated list of verification results
519
+ * @throws {ApiError} If the API request fails
553
520
  */
554
521
  async getVerificationHistory(options = {}) {
555
522
  const params = new URLSearchParams();
@@ -557,8 +524,7 @@ var BindClient = class {
557
524
  if (options.offset !== void 0) params.set("offset", options.offset.toString());
558
525
  const queryString = params.toString();
559
526
  const path = queryString ? `/api/verify/history?${queryString}` : "/api/verify/history";
560
- const response = await this.fetch(path);
561
- return response.json();
527
+ return this.fetchJson(path);
562
528
  }
563
529
  // ==========================================================================
564
530
  // Private Helpers
@@ -574,8 +540,24 @@ var BindClient = class {
574
540
  if (response.status === 401) {
575
541
  throw new AuthenticationError();
576
542
  }
543
+ if (!response.ok) {
544
+ const body = await response.json().catch(() => ({}));
545
+ throw new ApiError(
546
+ body.error || `HTTP ${response.status}: ${response.statusText}`,
547
+ response.status,
548
+ body
549
+ );
550
+ }
577
551
  return response;
578
552
  }
553
+ async fetchJson(path, init) {
554
+ const response = await this.fetch(path, init);
555
+ const json = await response.json();
556
+ if (json.success === false) {
557
+ throw new ApiError(json.error || "Request failed", response.status, json);
558
+ }
559
+ return json.data ?? json;
560
+ }
579
561
  sleep(ms) {
580
562
  return new Promise((resolve) => setTimeout(resolve, ms));
581
563
  }
@@ -613,11 +595,7 @@ var ZkTlsAdapter = class {
613
595
  * Client should redirect user to this URL
614
596
  */
615
597
  async createSession(callbackUrl) {
616
- const result = await this.client.createZkTlsSession(this.extractorId, callbackUrl);
617
- if (!result.success || !result.data) {
618
- throw new Error(result.error || "Failed to create zkTLS session");
619
- }
620
- return result.data;
598
+ return this.client.createZkTlsSession(this.extractorId, callbackUrl);
621
599
  }
622
600
  /**
623
601
  * Wait for session completion and return attestation
@@ -628,7 +606,7 @@ var ZkTlsAdapter = class {
628
606
  throw new Error("Session completed but no attestation found");
629
607
  }
630
608
  const extractors = await this.client.listExtractors();
631
- const extractor = extractors.data?.find((e) => e.id === this.extractorId);
609
+ const extractor = extractors.find((e) => e.id === this.extractorId);
632
610
  if (!extractor) {
633
611
  throw new Error(`Extractor not found: ${this.extractorId}`);
634
612
  }
@@ -641,17 +619,14 @@ var ZkTlsAdapter = class {
641
619
  // Protected helpers
642
620
  // ===========================================================================
643
621
  async fetchExistingAttestation(attestationId) {
644
- const result = await this.client.getAttestation(attestationId);
645
- if (!result.success || !result.data) {
646
- throw new Error(result.error || "Attestation not found");
647
- }
622
+ const attestation = await this.client.getAttestation(attestationId);
648
623
  const extractors = await this.client.listExtractors();
649
- const extractor = extractors.data?.find((e) => e.id === result.data.extractor);
624
+ const extractor = extractors.find((e) => e.id === attestation.extractor);
650
625
  if (!extractor) {
651
- throw new Error(`Extractor not found: ${result.data.extractor}`);
626
+ throw new Error(`Extractor not found: ${attestation.extractor}`);
652
627
  }
653
628
  return {
654
- attestation: result.data,
629
+ attestation,
655
630
  extractor
656
631
  };
657
632
  }