@proofchain/sdk 1.2.0 → 2.0.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/dist/index.js CHANGED
@@ -20,358 +20,2114 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- AttestationClient: () => AttestationClient,
24
- AttestationClientError: () => AttestationClientError,
25
- AttestationRegistryContract: () => AttestationRegistryContract,
26
- createClient: () => createClient
23
+ AuthenticationError: () => AuthenticationError,
24
+ AuthorizationError: () => AuthorizationError,
25
+ CertificatesResource: () => CertificatesResource,
26
+ ChannelsResource: () => ChannelsResource,
27
+ DataViewsClient: () => DataViewsClient,
28
+ DocumentsResource: () => DocumentsResource,
29
+ EndUsersClient: () => EndUsersClient,
30
+ EventsResource: () => EventsResource,
31
+ IngestionClient: () => IngestionClient,
32
+ NetworkError: () => NetworkError,
33
+ NotFoundError: () => NotFoundError,
34
+ PassportClient: () => PassportClient,
35
+ ProofChain: () => ProofChain,
36
+ ProofChainError: () => ProofChainError,
37
+ QuestsClient: () => QuestsClient,
38
+ RateLimitError: () => RateLimitError,
39
+ RewardsClient: () => RewardsClient,
40
+ SchemasClient: () => SchemasClient,
41
+ SearchResource: () => SearchResource,
42
+ ServerError: () => ServerError,
43
+ TenantResource: () => TenantResource,
44
+ TimeoutError: () => TimeoutError,
45
+ ValidationError: () => ValidationError,
46
+ VaultResource: () => VaultResource,
47
+ VerifyResource: () => VerifyResource,
48
+ WalletClient: () => WalletClient,
49
+ WebhooksResource: () => WebhooksResource
27
50
  });
28
51
  module.exports = __toCommonJS(index_exports);
29
52
 
30
- // src/client.ts
31
- var AttestationClientError = class extends Error {
32
- constructor(message, status, body) {
53
+ // src/errors.ts
54
+ var ProofChainError = class extends Error {
55
+ constructor(message, statusCode, responseBody) {
33
56
  super(message);
34
- this.status = status;
35
- this.body = body;
36
- this.name = "AttestationClientError";
57
+ this.name = "ProofChainError";
58
+ this.statusCode = statusCode;
59
+ this.responseBody = responseBody;
37
60
  }
38
61
  };
39
- var AttestationClient = class {
40
- constructor(config) {
41
- this.baseUrl = config.baseUrl.replace(/\/$/, "");
42
- this.accessToken = config.accessToken;
43
- this.timeout = config.timeout ?? 3e4;
44
- }
45
- // ============ Internal Methods ============
46
- async request(method, path, body, options) {
47
- const url = `${this.baseUrl}${path}`;
62
+ var AuthenticationError = class extends ProofChainError {
63
+ constructor(message = "Invalid or missing API key") {
64
+ super(message, 401);
65
+ this.name = "AuthenticationError";
66
+ }
67
+ };
68
+ var AuthorizationError = class extends ProofChainError {
69
+ constructor(message = "Access denied") {
70
+ super(message, 403);
71
+ this.name = "AuthorizationError";
72
+ }
73
+ };
74
+ var NotFoundError = class extends ProofChainError {
75
+ constructor(message = "Resource not found") {
76
+ super(message, 404);
77
+ this.name = "NotFoundError";
78
+ }
79
+ };
80
+ var ValidationError = class extends ProofChainError {
81
+ constructor(message = "Validation error", errors = []) {
82
+ super(message, 422);
83
+ this.name = "ValidationError";
84
+ this.errors = errors;
85
+ }
86
+ };
87
+ var RateLimitError = class extends ProofChainError {
88
+ constructor(retryAfter) {
89
+ super("Rate limit exceeded", 429);
90
+ this.name = "RateLimitError";
91
+ this.retryAfter = retryAfter;
92
+ }
93
+ };
94
+ var ServerError = class extends ProofChainError {
95
+ constructor(message = "Server error", statusCode = 500) {
96
+ super(message, statusCode);
97
+ this.name = "ServerError";
98
+ }
99
+ };
100
+ var NetworkError = class extends ProofChainError {
101
+ constructor(message = "Network error", cause) {
102
+ super(message);
103
+ this.name = "NetworkError";
104
+ this.cause = cause;
105
+ }
106
+ };
107
+ var TimeoutError = class extends ProofChainError {
108
+ constructor(message = "Request timed out") {
109
+ super(message);
110
+ this.name = "TimeoutError";
111
+ }
112
+ };
113
+
114
+ // src/http.ts
115
+ var DEFAULT_BASE_URL = "https://api.proofchain.co.za";
116
+ var DEFAULT_TIMEOUT = 3e4;
117
+ var USER_AGENT = "proofchain-js/0.1.0";
118
+ var HttpClient = class {
119
+ constructor(options) {
120
+ this.apiKey = options.apiKey;
121
+ this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
122
+ this.timeout = options.timeout || DEFAULT_TIMEOUT;
123
+ this.maxRetries = options.maxRetries ?? 3;
124
+ }
125
+ getHeaders() {
126
+ return {
127
+ "X-API-Key": this.apiKey,
128
+ "Content-Type": "application/json",
129
+ "User-Agent": USER_AGENT
130
+ };
131
+ }
132
+ async handleResponse(response) {
133
+ const contentType = response.headers.get("content-type");
134
+ const isJson = contentType?.includes("application/json");
135
+ if (response.ok) {
136
+ if (response.status === 204 || !isJson) {
137
+ return {};
138
+ }
139
+ return response.json();
140
+ }
141
+ const body = isJson ? await response.json().catch(() => ({})) : {};
142
+ const message = body.detail || body.message || `HTTP ${response.status}`;
143
+ switch (response.status) {
144
+ case 401:
145
+ throw new AuthenticationError(message);
146
+ case 403:
147
+ throw new AuthorizationError(message);
148
+ case 404:
149
+ throw new NotFoundError(message);
150
+ case 422:
151
+ case 400:
152
+ throw new ValidationError(message, body.errors);
153
+ case 429:
154
+ const retryAfter = response.headers.get("Retry-After");
155
+ throw new RateLimitError(retryAfter ? parseInt(retryAfter, 10) : void 0);
156
+ default:
157
+ if (response.status >= 500) {
158
+ throw new ServerError(message, response.status);
159
+ }
160
+ throw new ProofChainError(message, response.status, body);
161
+ }
162
+ }
163
+ async fetchWithRetry(url, options, retries = 0) {
48
164
  const controller = new AbortController();
49
165
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
50
- const headers = {
51
- "Content-Type": "application/json",
52
- ...options?.headers
166
+ try {
167
+ const response = await fetch(url, {
168
+ ...options,
169
+ signal: controller.signal
170
+ });
171
+ clearTimeout(timeoutId);
172
+ return this.handleResponse(response);
173
+ } catch (error) {
174
+ clearTimeout(timeoutId);
175
+ if (error instanceof ProofChainError) {
176
+ if (error instanceof RateLimitError && retries < this.maxRetries) {
177
+ const delay = Math.min((error.retryAfter || 1) * 1e3, 6e4);
178
+ await new Promise((resolve) => setTimeout(resolve, delay));
179
+ return this.fetchWithRetry(url, options, retries + 1);
180
+ }
181
+ throw error;
182
+ }
183
+ if (error instanceof Error) {
184
+ if (error.name === "AbortError") {
185
+ throw new TimeoutError();
186
+ }
187
+ if (retries < this.maxRetries) {
188
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (retries + 1)));
189
+ return this.fetchWithRetry(url, options, retries + 1);
190
+ }
191
+ throw new NetworkError(error.message, error);
192
+ }
193
+ throw new NetworkError("Unknown error");
194
+ }
195
+ }
196
+ async request(method, path, options = {}) {
197
+ let url = `${this.baseUrl}${path}`;
198
+ if (options.params) {
199
+ const searchParams = new URLSearchParams();
200
+ for (const [key, value] of Object.entries(options.params)) {
201
+ if (value !== void 0) {
202
+ searchParams.append(key, String(value));
203
+ }
204
+ }
205
+ const queryString = searchParams.toString();
206
+ if (queryString) {
207
+ url += `?${queryString}`;
208
+ }
209
+ }
210
+ const fetchOptions = {
211
+ method,
212
+ headers: this.getHeaders()
53
213
  };
54
- if (this.accessToken) {
55
- headers["Authorization"] = `Bearer ${this.accessToken}`;
214
+ if (options.body) {
215
+ fetchOptions.body = JSON.stringify(options.body);
56
216
  }
217
+ return this.fetchWithRetry(url, fetchOptions);
218
+ }
219
+ async requestMultipart(path, formData) {
220
+ const url = `${this.baseUrl}${path}`;
221
+ const headers = {
222
+ "X-API-Key": this.apiKey,
223
+ "User-Agent": USER_AGENT
224
+ };
225
+ return this.fetchWithRetry(url, {
226
+ method: "POST",
227
+ headers,
228
+ body: formData
229
+ });
230
+ }
231
+ async getRaw(path) {
232
+ const url = `${this.baseUrl}${path}`;
233
+ const controller = new AbortController();
234
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
57
235
  try {
58
236
  const response = await fetch(url, {
59
- method,
60
- headers,
61
- body: body ? JSON.stringify(body) : void 0,
62
- signal: options?.signal ?? controller.signal
237
+ method: "GET",
238
+ headers: {
239
+ "X-API-Key": this.apiKey,
240
+ "User-Agent": USER_AGENT
241
+ },
242
+ signal: controller.signal
63
243
  });
64
244
  clearTimeout(timeoutId);
65
245
  if (!response.ok) {
66
- const errorBody = await response.json().catch(() => null);
67
- throw new AttestationClientError(
68
- `Request failed: ${response.status} ${response.statusText}`,
69
- response.status,
70
- errorBody
71
- );
246
+ throw new ProofChainError(`HTTP ${response.status}`, response.status);
72
247
  }
73
- return response.json();
248
+ return response.arrayBuffer();
74
249
  } catch (error) {
75
250
  clearTimeout(timeoutId);
76
- if (error instanceof AttestationClientError) throw error;
77
- throw new AttestationClientError(
78
- `Request failed: ${error.message}`,
79
- 0
80
- );
251
+ if (error instanceof ProofChainError) throw error;
252
+ throw new NetworkError(error.message);
253
+ }
254
+ }
255
+ get(path, params) {
256
+ return this.request("GET", path, { params });
257
+ }
258
+ post(path, body) {
259
+ return this.request("POST", path, { body });
260
+ }
261
+ put(path, body) {
262
+ return this.request("PUT", path, { body });
263
+ }
264
+ patch(path, body) {
265
+ return this.request("PATCH", path, { body });
266
+ }
267
+ delete(path) {
268
+ return this.request("DELETE", path);
269
+ }
270
+ };
271
+
272
+ // src/resources/vault.ts
273
+ var VaultResource = class {
274
+ constructor(http) {
275
+ this.http = http;
276
+ }
277
+ /**
278
+ * List files and folders in the vault.
279
+ */
280
+ async list(folderId) {
281
+ const params = {};
282
+ if (folderId) params.folder_id = folderId;
283
+ return this.http.get("/tenant/vault", params);
284
+ }
285
+ /**
286
+ * Upload a file to the vault.
287
+ */
288
+ async upload(request) {
289
+ const formData = new FormData();
290
+ if (request.file instanceof Blob) {
291
+ formData.append("file", request.file, request.filename || "file");
292
+ } else if (request.file instanceof ArrayBuffer) {
293
+ const blob = new Blob([request.file]);
294
+ formData.append("file", blob, request.filename || "file");
295
+ } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(request.file)) {
296
+ const uint8 = new Uint8Array(request.file);
297
+ const blob = new Blob([uint8]);
298
+ formData.append("file", blob, request.filename || "file");
81
299
  }
300
+ formData.append("user_id", request.userId);
301
+ if (request.folderId) formData.append("folder_id", request.folderId);
302
+ formData.append("access_mode", request.accessMode || "private");
303
+ return this.http.requestMultipart("/tenant/vault/upload", formData);
82
304
  }
83
- // ============ Auth Methods ============
84
- setAccessToken(token) {
85
- this.accessToken = token;
305
+ /**
306
+ * Get file details.
307
+ */
308
+ async get(fileId) {
309
+ return this.http.get(`/tenant/vault/files/${fileId}`);
86
310
  }
87
- clearAccessToken() {
88
- this.accessToken = void 0;
311
+ /**
312
+ * Download a file.
313
+ */
314
+ async download(fileId) {
315
+ return this.http.getRaw(`/tenant/vault/files/${fileId}/download`);
89
316
  }
90
- // ============ Health ============
91
- async health() {
92
- return this.request("GET", "/health");
317
+ /**
318
+ * Delete a file.
319
+ */
320
+ async delete(fileId) {
321
+ await this.http.delete(`/tenant/vault/files/${fileId}`);
93
322
  }
94
- // ============ Authentication ============
95
- async requestChallenge(walletAddress) {
96
- return this.request("POST", "/auth/web3/challenge", {
97
- wallet_address: walletAddress
323
+ /**
324
+ * Move a file to a folder.
325
+ */
326
+ async move(fileId, folderId) {
327
+ return this.http.post(`/tenant/vault/files/${fileId}/move`, {
328
+ folder_id: folderId
98
329
  });
99
330
  }
100
- async verifySignature(walletAddress, signature, message) {
101
- const response = await this.request("POST", "/auth/web3/verify", {
102
- wallet_address: walletAddress,
103
- signature,
104
- message
331
+ /**
332
+ * Create a folder.
333
+ */
334
+ async createFolder(name, parentId) {
335
+ return this.http.post("/tenant/vault/folders", {
336
+ name,
337
+ parent_id: parentId
105
338
  });
106
- if (response.access_token) {
107
- this.setAccessToken(response.access_token);
108
- }
109
- return response;
110
339
  }
111
- // ============ Events ============
112
- async createEvent(event) {
113
- return this.request("POST", "/events", event);
340
+ /**
341
+ * Delete a folder.
342
+ */
343
+ async deleteFolder(folderId) {
344
+ await this.http.delete(`/tenant/vault/folders/${folderId}`);
114
345
  }
115
- async getEvents(userId, options) {
116
- const params = new URLSearchParams();
117
- if (options?.limit) params.set("limit", options.limit.toString());
118
- if (options?.offset) params.set("offset", options.offset.toString());
119
- if (options?.eventType) params.set("event_type", options.eventType);
120
- if (options?.fetchData) params.set("fetch_data", "true");
121
- const query = params.toString();
122
- return this.request(
123
- "GET",
124
- `/data/events/${userId}${query ? `?${query}` : ""}`
125
- );
346
+ /**
347
+ * Get vault statistics.
348
+ */
349
+ async stats() {
350
+ return this.http.get("/tenant/vault/stats");
126
351
  }
127
- async queryEvents(userId, query) {
128
- return this.request(
129
- "POST",
130
- `/data/events/${userId}/query`,
131
- query
132
- );
352
+ /**
353
+ * Create a shareable link.
354
+ */
355
+ async share(fileId, expiresInHours) {
356
+ return this.http.post("/tenant/vault/share", {
357
+ file_id: fileId,
358
+ expires_in_hours: expiresInHours
359
+ });
360
+ }
361
+ };
362
+
363
+ // src/resources/search.ts
364
+ var SearchResource = class {
365
+ constructor(http) {
366
+ this.http = http;
367
+ }
368
+ /**
369
+ * Search events with filters.
370
+ */
371
+ async query(request = {}) {
372
+ return this.http.post("/search", {
373
+ filters: request.filters,
374
+ offset: request.offset,
375
+ limit: request.limit,
376
+ include_data: request.includeData
377
+ });
378
+ }
379
+ /**
380
+ * Quick search across all fields.
381
+ */
382
+ async quick(query, limit = 20) {
383
+ return this.http.get("/search/quick", { q: query, limit });
384
+ }
385
+ /**
386
+ * Get events for a specific user.
387
+ */
388
+ async byUser(userId, limit, offset) {
389
+ return this.http.get(`/search/by-user/${userId}`, { limit, offset });
390
+ }
391
+ /**
392
+ * Get event by certificate ID.
393
+ */
394
+ async byCertificate(certificateId) {
395
+ return this.http.get(`/search/by-certificate/${certificateId}`);
396
+ }
397
+ /**
398
+ * Get faceted aggregations.
399
+ */
400
+ async facets(fromDate, toDate) {
401
+ return this.http.get("/search/facets", {
402
+ from_date: fromDate,
403
+ to_date: toDate
404
+ });
405
+ }
406
+ /**
407
+ * Get search statistics.
408
+ */
409
+ async stats() {
410
+ return this.http.get("/search/stats");
133
411
  }
134
- // ============ Merkle Tree ============
135
- async rebuildMerkleTree(userId) {
136
- return this.request("POST", `/merkle/rebuild/${userId}`);
412
+ };
413
+
414
+ // src/resources/verify.ts
415
+ var VerifyResource = class {
416
+ constructor(http) {
417
+ this.http = http;
137
418
  }
138
- async getMerkleRoot(userId) {
139
- return this.request("GET", `/merkle/root/${userId}`);
419
+ /**
420
+ * Verify a certificate by ID.
421
+ */
422
+ async certificate(certificateId) {
423
+ return this.http.get(`/verify/cert/${certificateId}`);
140
424
  }
141
- async getMerkleProof(userId, ipfsHash) {
142
- return this.request("GET", `/merkle/proof/${userId}/${ipfsHash}`);
425
+ /**
426
+ * Verify an event by IPFS hash.
427
+ */
428
+ async event(ipfsHash) {
429
+ return this.http.get(`/verify/event/${ipfsHash}`);
143
430
  }
144
- async verifyMerkleProof(leaf, proof, root) {
145
- return this.request("POST", "/merkle/verify", {
431
+ /**
432
+ * Verify a Merkle proof.
433
+ */
434
+ async proof(leaf, proof, root) {
435
+ return this.http.post("/verify/proof", {
146
436
  leaf,
147
437
  proof,
148
438
  root
149
439
  });
150
440
  }
151
- // ============ Wallets ============
152
- async linkWallet(request) {
153
- return this.request("POST", "/wallet/link", request);
441
+ /**
442
+ * Verify a batch by ID.
443
+ */
444
+ async batch(batchId) {
445
+ return this.http.get(`/verify/batch/${batchId}`);
446
+ }
447
+ /**
448
+ * Get batch proof for an event.
449
+ */
450
+ async eventBatchProof(eventId) {
451
+ return this.http.get(`/verify/event/${eventId}/batch-proof`);
452
+ }
453
+ /**
454
+ * Batch verify multiple items.
455
+ */
456
+ async batchVerify(items) {
457
+ return this.http.post("/verify/batch", { items });
458
+ }
459
+ };
460
+
461
+ // src/resources/tenant.ts
462
+ var TenantResource = class {
463
+ constructor(http) {
464
+ this.http = http;
465
+ }
466
+ /**
467
+ * List all API keys.
468
+ */
469
+ async listApiKeys() {
470
+ return this.http.get("/tenant/api-keys");
471
+ }
472
+ /**
473
+ * Create a new API key.
474
+ */
475
+ async createApiKey(request) {
476
+ return this.http.post("/tenant/api-keys", {
477
+ name: request.name,
478
+ permissions: request.permissions,
479
+ expires_in_days: request.expiresInDays
480
+ });
481
+ }
482
+ /**
483
+ * Delete an API key.
484
+ */
485
+ async deleteApiKey(keyId) {
486
+ await this.http.delete(`/tenant/api-keys/${keyId}`);
154
487
  }
155
- async getWalletStatus(userId) {
156
- return this.request("GET", `/wallet/status/${userId}`);
488
+ /**
489
+ * Get detailed usage statistics.
490
+ */
491
+ async usageDetailed(fromDate, toDate) {
492
+ return this.http.get("/tenant/usage/detailed", {
493
+ from_date: fromDate,
494
+ to_date: toDate
495
+ });
157
496
  }
158
- // ============ Quests ============
159
497
  /**
160
- * List available quests for a user
161
- * @param userId - End user external ID
162
- * @param options - Filter options
498
+ * Get tenant context.
163
499
  */
164
- async getAvailableQuests(userId, options) {
165
- const params = new URLSearchParams();
166
- params.set("user_id", userId);
167
- if (options?.category) params.set("category", options.category);
168
- if (options?.limit) params.set("limit", options.limit.toString());
169
- return this.request(
170
- "GET",
171
- `/quests/available?${params.toString()}`
172
- );
500
+ async context() {
501
+ return this.http.get("/tenant/context");
173
502
  }
174
503
  /**
175
- * Get a specific quest by ID with all steps
176
- * @param questId - Quest ID
504
+ * Get blockchain statistics.
177
505
  */
178
- async getQuest(questId) {
179
- return this.request("GET", `/quests/${questId}`);
506
+ async blockchainStats() {
507
+ return this.http.get("/tenant/blockchain/stats");
180
508
  }
181
509
  /**
182
- * Start a quest for a user
183
- * @param questId - Quest ID
184
- * @param userId - End user external ID
510
+ * Verify a certificate on the blockchain.
185
511
  */
186
- async startQuest(questId, userId) {
187
- return this.request(
188
- "POST",
189
- `/quests/${questId}/start?user_id=${encodeURIComponent(userId)}`,
190
- {}
191
- );
512
+ async blockchainVerify(certificateId) {
513
+ return this.http.get(`/tenant/blockchain/verify/${certificateId}`);
192
514
  }
193
515
  /**
194
- * Get user's progress on a specific quest
195
- * @param questId - Quest ID
196
- * @param userId - End user external ID
516
+ * List blockchain certificates.
197
517
  */
198
- async getQuestProgress(questId, userId) {
199
- return this.request(
200
- "GET",
201
- `/quests/${questId}/progress/${encodeURIComponent(userId)}`
202
- );
518
+ async blockchainCertificates(limit, offset) {
519
+ return this.http.get("/tenant/blockchain/certificates", {
520
+ limit,
521
+ offset
522
+ });
203
523
  }
204
524
  /**
205
- * Get all quest progress for a user
206
- * @param userId - End user external ID
207
- * @param status - Optional status filter
525
+ * Force batch settlement.
208
526
  */
209
- async getUserQuestProgress(userId, status) {
210
- const params = new URLSearchParams();
211
- if (status) params.set("status", status);
212
- const query = params.toString();
213
- return this.request(
214
- "GET",
215
- `/quests/user/${encodeURIComponent(userId)}/progress${query ? `?${query}` : ""}`
216
- );
527
+ async forceBatch() {
528
+ return this.http.post("/tenant/events/force-batch");
217
529
  }
218
530
  /**
219
- * Complete or increment a quest step
220
- * @param questId - Quest ID
221
- * @param userId - End user external ID
222
- * @param stepIndex - Step index (0-based)
223
- * @param options - Completion options
531
+ * Settle all pending events.
224
532
  */
225
- async completeQuestStep(questId, userId, stepIndex, options) {
226
- const params = new URLSearchParams();
227
- if (options?.count) params.set("count", options.count.toString());
228
- if (options?.value) params.set("value", options.value);
229
- const query = params.toString();
230
- return this.request(
231
- "POST",
232
- `/quests/${questId}/progress/${encodeURIComponent(userId)}/step/${stepIndex}/complete${query ? `?${query}` : ""}`,
233
- {}
234
- );
533
+ async settleAll() {
534
+ return this.http.post("/tenant/events/settle-all");
535
+ }
536
+ /**
537
+ * Settle a specific event.
538
+ */
539
+ async settleEvent(eventId) {
540
+ return this.http.post(`/tenant/events/${eventId}/settle`);
235
541
  }
236
542
  };
237
543
 
238
- // src/contract.ts
239
- var import_ethers = require("ethers");
240
- var ATTESTATION_REGISTRY_ABI = [
241
- // Read functions
242
- "function attestationRoots(address wallet) view returns (bytes32 merkleRoot, uint256 eventCount, uint256 lastUpdated, string latestIpfsHash)",
243
- "function getRoot(address wallet) view returns (bytes32 root, uint256 eventCount, uint256 lastUpdated, string latestIpfsHash)",
244
- "function getHistoryCount(address wallet) view returns (uint256 count)",
245
- "function getHistoricalRoot(address wallet, uint256 index) view returns (bytes32 root, uint256 eventCount, uint256 timestamp)",
246
- "function verifyAttestation(address wallet, bytes32 leaf, bytes32[] proof) view returns (bool valid)",
247
- "function computeLeaf(string ipfsHash, string eventType, uint256 timestamp) pure returns (bytes32 leaf)",
248
- "function getWalletByIpfsHash(string ipfsHash) view returns (address wallet)",
249
- "function authorizedUpdaters(address) view returns (bool)",
250
- "function owner() view returns (address)",
251
- // Write functions
252
- "function updateRoot(address wallet, bytes32 newRoot, uint256 eventCount, string latestIpfsHash)",
253
- "function batchUpdateRoots(address[] wallets, bytes32[] roots, uint256[] eventCounts, string[] ipfsHashes)",
254
- "function setAuthorizedUpdater(address updater, bool authorized)",
255
- // Events
256
- "event RootUpdated(address indexed wallet, bytes32 indexed newRoot, bytes32 indexed previousRoot, uint256 eventCount, string latestIpfsHash)",
257
- "event AttestationVerified(address indexed wallet, bytes32 indexed leaf, string ipfsHash, bool valid)",
258
- "event UpdaterAuthorized(address indexed updater, bool authorized)"
259
- ];
260
- var AttestationRegistryContract = class {
261
- constructor(contractAddress, signerOrProvider) {
262
- this.contract = new import_ethers.ethers.Contract(
263
- contractAddress,
264
- ATTESTATION_REGISTRY_ABI,
265
- signerOrProvider
266
- );
267
- if ("getAddress" in signerOrProvider) {
268
- this.signer = signerOrProvider;
269
- }
544
+ // src/passports.ts
545
+ var PassportClient = class {
546
+ constructor(http) {
547
+ this.http = http;
270
548
  }
271
- // ============ Read Functions ============
272
- async getRoot(wallet) {
273
- const [merkleRoot, eventCount, lastUpdated, latestIpfsHash] = await this.contract.getRoot(wallet);
274
- return {
275
- merkleRoot,
276
- eventCount,
277
- lastUpdated,
278
- latestIpfsHash
279
- };
549
+ // ---------------------------------------------------------------------------
550
+ // Passports
551
+ // ---------------------------------------------------------------------------
552
+ /**
553
+ * List all passports for the tenant
554
+ */
555
+ async list(options = {}) {
556
+ const params = new URLSearchParams();
557
+ if (options.limit) params.append("limit", options.limit.toString());
558
+ if (options.offset) params.append("offset", options.offset.toString());
559
+ return this.http.get(`/passports?${params.toString()}`);
280
560
  }
281
- async getHistoryCount(wallet) {
282
- return this.contract.getHistoryCount(wallet);
561
+ /**
562
+ * Get a passport by user ID
563
+ */
564
+ async get(userId) {
565
+ return this.http.get(`/passports/${encodeURIComponent(userId)}`);
283
566
  }
284
- async getHistoricalRoot(wallet, index) {
285
- const [merkleRoot, eventCount, timestamp] = await this.contract.getHistoricalRoot(wallet, index);
286
- return { merkleRoot, eventCount, timestamp };
567
+ /**
568
+ * Get a passport with all field values
569
+ */
570
+ async getWithFields(userId) {
571
+ const passport = await this.get(userId);
572
+ const fields = await this.getFieldValues(userId);
573
+ return { ...passport, field_values: fields };
287
574
  }
288
- async verifyAttestation(wallet, leaf, proof) {
289
- return this.contract.verifyAttestation(wallet, leaf, proof);
575
+ /**
576
+ * Create a new passport for a user
577
+ */
578
+ async create(data) {
579
+ return this.http.post("/passports", data);
290
580
  }
291
- async computeLeaf(ipfsHash, eventType, timestamp) {
292
- return this.contract.computeLeaf(ipfsHash, eventType, timestamp);
581
+ /**
582
+ * Update a passport
583
+ */
584
+ async update(userId, data) {
585
+ return this.http.put(`/passports/${encodeURIComponent(userId)}`, data);
293
586
  }
294
- async getWalletByIpfsHash(ipfsHash) {
295
- return this.contract.getWalletByIpfsHash(ipfsHash);
587
+ /**
588
+ * Delete a passport
589
+ */
590
+ async delete(userId) {
591
+ await this.http.delete(`/passports/${encodeURIComponent(userId)}`);
296
592
  }
297
- async isAuthorizedUpdater(address) {
298
- return this.contract.authorizedUpdaters(address);
593
+ /**
594
+ * Add points to a passport
595
+ */
596
+ async addPoints(userId, points, reason) {
597
+ return this.http.post(`/passports/${encodeURIComponent(userId)}/add-points`, {
598
+ points,
599
+ reason
600
+ });
299
601
  }
300
- async owner() {
301
- return this.contract.owner();
602
+ /**
603
+ * Level up a passport
604
+ */
605
+ async levelUp(userId) {
606
+ return this.http.post(`/passports/${encodeURIComponent(userId)}/level-up`, {});
302
607
  }
303
- // ============ Write Functions ============
304
- async updateRoot(wallet, newRoot, eventCount, latestIpfsHash) {
305
- if (!this.signer) {
306
- throw new Error("Signer required for write operations");
307
- }
308
- return this.contract.updateRoot(wallet, newRoot, eventCount, latestIpfsHash);
608
+ /**
609
+ * Link a wallet address to a passport
610
+ */
611
+ async linkWallet(userId, walletAddress) {
612
+ return this.update(userId, { wallet_address: walletAddress });
309
613
  }
310
- async batchUpdateRoots(wallets, roots, eventCounts, ipfsHashes) {
311
- if (!this.signer) {
312
- throw new Error("Signer required for write operations");
313
- }
314
- return this.contract.batchUpdateRoots(wallets, roots, eventCounts, ipfsHashes);
614
+ // ---------------------------------------------------------------------------
615
+ // Field Values
616
+ // ---------------------------------------------------------------------------
617
+ /**
618
+ * Get all field values for a passport
619
+ */
620
+ async getFieldValues(userId) {
621
+ return this.http.get(`/passports/${encodeURIComponent(userId)}/fields`);
315
622
  }
316
- async setAuthorizedUpdater(updater, authorized) {
317
- if (!this.signer) {
318
- throw new Error("Signer required for write operations");
319
- }
320
- return this.contract.setAuthorizedUpdater(updater, authorized);
321
- }
322
- // ============ Event Listeners ============
323
- onRootUpdated(callback, filter) {
324
- const eventFilter = this.contract.filters.RootUpdated(filter?.wallet);
325
- this.contract.on(eventFilter, (wallet, newRoot, previousRoot, eventCount, latestIpfsHash) => {
326
- callback({
327
- wallet,
328
- newRoot,
329
- previousRoot,
330
- eventCount,
331
- latestIpfsHash
332
- });
623
+ /**
624
+ * Set a field value manually
625
+ */
626
+ async setFieldValue(userId, fieldKey, value) {
627
+ await this.http.put(`/passports/${encodeURIComponent(userId)}/fields/${fieldKey}`, value);
628
+ }
629
+ /**
630
+ * Recompute all computed field values
631
+ */
632
+ async recomputeFields(userId) {
633
+ return this.http.post(`/passports/${encodeURIComponent(userId)}/recompute`, {});
634
+ }
635
+ /**
636
+ * Assign a template to a passport
637
+ */
638
+ async assignTemplate(userId, templateId) {
639
+ await this.http.post(`/passports/${encodeURIComponent(userId)}/assign-template/${templateId}`, {});
640
+ }
641
+ // ---------------------------------------------------------------------------
642
+ // Templates
643
+ // ---------------------------------------------------------------------------
644
+ /**
645
+ * List all passport templates
646
+ */
647
+ async listTemplates() {
648
+ return this.http.get("/passports/templates");
649
+ }
650
+ /**
651
+ * Get a template by ID
652
+ */
653
+ async getTemplate(templateId) {
654
+ return this.http.get(`/passports/templates/${templateId}`);
655
+ }
656
+ /**
657
+ * Create a new template
658
+ */
659
+ async createTemplate(data) {
660
+ return this.http.post("/passports/templates", data);
661
+ }
662
+ /**
663
+ * Add a field to a template
664
+ */
665
+ async addTemplateField(templateId, field) {
666
+ return this.http.post(`/passports/templates/${templateId}/fields`, field);
667
+ }
668
+ /**
669
+ * Delete a template
670
+ */
671
+ async deleteTemplate(templateId) {
672
+ await this.http.delete(`/passports/templates/${templateId}`);
673
+ }
674
+ // ---------------------------------------------------------------------------
675
+ // Badges
676
+ // ---------------------------------------------------------------------------
677
+ /**
678
+ * List all badges
679
+ */
680
+ async listBadges() {
681
+ return this.http.get("/passports/badges");
682
+ }
683
+ /**
684
+ * Create a badge
685
+ */
686
+ async createBadge(data) {
687
+ return this.http.post("/passports/badges", data);
688
+ }
689
+ /**
690
+ * Award a badge to a user
691
+ */
692
+ async awardBadge(userId, badgeId, metadata) {
693
+ return this.http.post(`/passports/${encodeURIComponent(userId)}/badges/${badgeId}`, {
694
+ metadata
333
695
  });
334
696
  }
335
- removeAllListeners() {
336
- this.contract.removeAllListeners();
697
+ /**
698
+ * Get badges earned by a user
699
+ */
700
+ async getUserBadges(userId) {
701
+ return this.http.get(`/passports/${encodeURIComponent(userId)}/badges`);
702
+ }
703
+ // ---------------------------------------------------------------------------
704
+ // Achievements
705
+ // ---------------------------------------------------------------------------
706
+ /**
707
+ * List all achievements
708
+ */
709
+ async listAchievements() {
710
+ return this.http.get("/passports/achievements");
711
+ }
712
+ /**
713
+ * Create an achievement
714
+ */
715
+ async createAchievement(data) {
716
+ return this.http.post("/passports/achievements", data);
717
+ }
718
+ /**
719
+ * Get achievements for a user
720
+ */
721
+ async getUserAchievements(userId) {
722
+ return this.http.get(`/passports/${encodeURIComponent(userId)}/achievements`);
723
+ }
724
+ /**
725
+ * Update achievement progress
726
+ */
727
+ async updateAchievementProgress(userId, achievementId, progress) {
728
+ return this.http.put(
729
+ `/passports/${encodeURIComponent(userId)}/achievements/${achievementId}`,
730
+ { progress }
731
+ );
337
732
  }
338
- // ============ Utilities ============
339
- static computeLeafOffchain(ipfsHash, eventType, timestamp) {
340
- return import_ethers.ethers.keccak256(
341
- import_ethers.ethers.solidityPacked(
342
- ["string", "string", "uint256"],
343
- [ipfsHash, eventType, timestamp]
344
- )
733
+ // ---------------------------------------------------------------------------
734
+ // History
735
+ // ---------------------------------------------------------------------------
736
+ /**
737
+ * Get passport history/activity log
738
+ */
739
+ async getHistory(userId, options = {}) {
740
+ const params = new URLSearchParams();
741
+ if (options.limit) params.append("limit", options.limit.toString());
742
+ if (options.offset) params.append("offset", options.offset.toString());
743
+ return this.http.get(
744
+ `/passports/${encodeURIComponent(userId)}/history?${params.toString()}`
345
745
  );
346
746
  }
347
- static verifyProofOffchain(leaf, proof, root) {
348
- let computedHash = leaf;
349
- for (const proofElement of proof) {
350
- if (computedHash < proofElement) {
351
- computedHash = import_ethers.ethers.keccak256(
352
- import_ethers.ethers.solidityPacked(["bytes32", "bytes32"], [computedHash, proofElement])
353
- );
354
- } else {
355
- computedHash = import_ethers.ethers.keccak256(
356
- import_ethers.ethers.solidityPacked(["bytes32", "bytes32"], [proofElement, computedHash])
357
- );
358
- }
359
- }
360
- return computedHash === root;
747
+ // ---------------------------------------------------------------------------
748
+ // Passport V2 (Data View Integration)
749
+ // ---------------------------------------------------------------------------
750
+ /**
751
+ * Get passport data for a user using Passport V2 API.
752
+ * This integrates with custom data views for dynamic computation.
753
+ *
754
+ * @param userId - The user ID
755
+ * @param passportId - Optional specific passport definition ID
756
+ * @returns Passport data with computed fields from data view
757
+ */
758
+ async getPassportV2(userId, passportId) {
759
+ const params = passportId ? `?passport_id=${passportId}` : "";
760
+ return this.http.get(`/passport-v2/users/${encodeURIComponent(userId)}${params}`);
361
761
  }
362
- };
363
-
364
- // src/index.ts
365
- function createClient(baseUrl, accessToken) {
366
- return new AttestationClient({
367
- baseUrl,
368
- accessToken
369
- });
370
- }
762
+ /**
763
+ * Get passport view data for a user (alias for getPassportV2).
764
+ *
765
+ * @param userId - The user ID
766
+ * @param passportId - Optional specific passport definition ID
767
+ * @returns Passport data with computed fields from data view
768
+ */
769
+ async getPassportView(userId, passportId) {
770
+ return this.getPassportV2(userId, passportId);
771
+ }
772
+ /**
773
+ * Get user milestones from Passport V2.
774
+ *
775
+ * @param userId - The user ID
776
+ * @param passportId - Optional passport ID to filter milestones
777
+ * @returns List of milestones achieved by the user
778
+ */
779
+ async getMilestones(userId, passportId) {
780
+ const params = passportId ? `?passport_id=${passportId}` : "";
781
+ return this.http.get(`/passport-v2/users/${encodeURIComponent(userId)}/milestones${params}`);
782
+ }
783
+ /**
784
+ * List available data views that can be used for passports.
785
+ * Includes built-in views and custom data views.
786
+ *
787
+ * @returns List of available views with their columns
788
+ */
789
+ async listAvailableViews() {
790
+ return this.http.get("/passport-v2/available-views");
791
+ }
792
+ /**
793
+ * List passport definitions for the tenant.
794
+ *
795
+ * @returns List of passport definitions
796
+ */
797
+ async listPassportDefinitions() {
798
+ return this.http.get("/passport-v2/definitions");
799
+ }
800
+ /**
801
+ * Create a new passport definition linked to a data view.
802
+ *
803
+ * @param definition - The passport definition to create
804
+ * @returns Created passport definition
805
+ *
806
+ * @example
807
+ * ```typescript
808
+ * const passport = await client.passports.createPassportDefinition({
809
+ * name: 'Fan Engagement Passport',
810
+ * description: 'Track fan engagement metrics',
811
+ * data_view_id: 'builtin-fan-profile', // or custom view UUID
812
+ * display_columns: ['fan_score', 'loyalty_tier', 'total_events'],
813
+ * column_labels: {
814
+ * fan_score: 'Engagement Score',
815
+ * loyalty_tier: 'Tier',
816
+ * total_events: 'Activities'
817
+ * }
818
+ * });
819
+ * ```
820
+ */
821
+ async createPassportDefinition(definition) {
822
+ return this.http.post("/passport-v2/definitions", definition);
823
+ }
824
+ };
825
+
826
+ // src/wallets.ts
827
+ var WalletClient = class {
828
+ constructor(http) {
829
+ this.http = http;
830
+ }
831
+ // ---------------------------------------------------------------------------
832
+ // Single Wallets
833
+ // ---------------------------------------------------------------------------
834
+ /**
835
+ * Create a single wallet for a user
836
+ */
837
+ async create(data) {
838
+ return this.http.post("/wallets", data);
839
+ }
840
+ /**
841
+ * Get a wallet by ID
842
+ */
843
+ async get(walletId) {
844
+ return this.http.get(`/wallets/${walletId}`);
845
+ }
846
+ /**
847
+ * List wallets for a user
848
+ */
849
+ async listByUser(userId) {
850
+ return this.http.get(`/wallets/user/${encodeURIComponent(userId)}`);
851
+ }
852
+ /**
853
+ * Get wallet statistics
854
+ */
855
+ async stats() {
856
+ return this.http.get("/wallets/stats");
857
+ }
858
+ // ---------------------------------------------------------------------------
859
+ // Dual Wallets (EOA + Smart Account)
860
+ // ---------------------------------------------------------------------------
861
+ /**
862
+ * Create dual wallets (EOA asset wallet + Smart Account) for a user
863
+ */
864
+ async createDual(data) {
865
+ return this.http.post("/wallets/dual", data);
866
+ }
867
+ /**
868
+ * Bulk create dual wallets for multiple users
869
+ */
870
+ async createDualBulk(userIds, network = "base-sepolia") {
871
+ return this.http.post("/wallets/dual/bulk", {
872
+ user_ids: userIds,
873
+ network
874
+ });
875
+ }
876
+ // ---------------------------------------------------------------------------
877
+ // Balances
878
+ // ---------------------------------------------------------------------------
879
+ /**
880
+ * Get wallet balance
881
+ */
882
+ async getBalance(walletId) {
883
+ return this.http.get(`/wallets/${walletId}/balance`);
884
+ }
885
+ /**
886
+ * Get comprehensive wallet information in a single call.
887
+ *
888
+ * Returns everything about a wallet:
889
+ * - Basic wallet details (address, type, network)
890
+ * - Token balances (native + ERC20)
891
+ * - NFT holdings with metadata
892
+ * - Recent activity (swaps, transfers)
893
+ *
894
+ * @param walletId - Wallet ID to query
895
+ * @param options - Control what data is included
896
+ */
897
+ async getInfo(walletId, options = {}) {
898
+ const params = new URLSearchParams();
899
+ if (options.includeBalances !== void 0) {
900
+ params.set("include_balances", String(options.includeBalances));
901
+ }
902
+ if (options.includeNfts !== void 0) {
903
+ params.set("include_nfts", String(options.includeNfts));
904
+ }
905
+ if (options.includeActivity !== void 0) {
906
+ params.set("include_activity", String(options.includeActivity));
907
+ }
908
+ const query = params.toString();
909
+ return this.http.get(
910
+ `/wallets/${walletId}/info${query ? `?${query}` : ""}`
911
+ );
912
+ }
913
+ /**
914
+ * Get comprehensive summary of all wallets for a user.
915
+ *
916
+ * Returns all wallets (EOA + Smart) with aggregated stats:
917
+ * - Total NFTs across all wallets
918
+ * - Total swaps executed
919
+ * - Token balances (optional)
920
+ *
921
+ * @param userId - User ID to query
922
+ * @param includeBalances - Include token balances (requires Alchemy)
923
+ */
924
+ async getUserSummary(userId, includeBalances = true) {
925
+ return this.http.get(
926
+ `/wallets/user/${encodeURIComponent(userId)}/summary?include_balances=${includeBalances}`
927
+ );
928
+ }
929
+ // ---------------------------------------------------------------------------
930
+ // Key Export
931
+ // ---------------------------------------------------------------------------
932
+ /**
933
+ * Export private key for an EOA wallet (requires acknowledgment)
934
+ */
935
+ async exportKey(walletId) {
936
+ return this.http.post(`/wallets/${walletId}/export-key`, {
937
+ acknowledge_warning: true
938
+ });
939
+ }
940
+ // ---------------------------------------------------------------------------
941
+ // Token Transfers
942
+ // ---------------------------------------------------------------------------
943
+ /**
944
+ * Transfer tokens from one address to another.
945
+ *
946
+ * @param request - Transfer details
947
+ * @returns Transaction result with hash and status
948
+ *
949
+ * @example
950
+ * ```typescript
951
+ * const result = await client.wallets.transfer({
952
+ * from_address: '0x123...',
953
+ * to_address: '0x456...',
954
+ * amount: '0.1',
955
+ * token: 'ETH',
956
+ * network: 'base-sepolia',
957
+ * });
958
+ * console.log('TX Hash:', result.tx_hash);
959
+ * ```
960
+ */
961
+ async transfer(request) {
962
+ return this.http.post("/wallets/transfer", request);
963
+ }
964
+ // ---------------------------------------------------------------------------
965
+ // Token Swaps
966
+ // ---------------------------------------------------------------------------
967
+ /**
968
+ * Get a swap quote
969
+ */
970
+ async getSwapQuote(request) {
971
+ return this.http.post("/wallets/swaps/quote", request);
972
+ }
973
+ /**
974
+ * Execute a token swap
975
+ */
976
+ async executeSwap(request) {
977
+ return this.http.post("/wallets/swaps/execute", request);
978
+ }
979
+ // ---------------------------------------------------------------------------
980
+ // NFTs
981
+ // ---------------------------------------------------------------------------
982
+ /**
983
+ * Get NFTs for a wallet
984
+ */
985
+ async getNFTs(walletId) {
986
+ return this.http.get(`/wallets/${walletId}/nfts`);
987
+ }
988
+ /**
989
+ * Get all NFTs for a user (across all wallets)
990
+ */
991
+ async getUserNFTs(userId) {
992
+ return this.http.get(`/wallets/user/${encodeURIComponent(userId)}/nfts`);
993
+ }
994
+ /**
995
+ * Add an NFT to wallet tracking
996
+ */
997
+ async addNFT(walletId, nft) {
998
+ return this.http.post(`/wallets/${walletId}/nfts`, nft);
999
+ }
1000
+ };
1001
+
1002
+ // src/users.ts
1003
+ var EndUsersClient = class {
1004
+ constructor(http) {
1005
+ this.http = http;
1006
+ }
1007
+ /**
1008
+ * List end-users with pagination and filters
1009
+ */
1010
+ async list(options = {}) {
1011
+ const params = new URLSearchParams();
1012
+ if (options.page) params.append("page", options.page.toString());
1013
+ if (options.page_size) params.append("page_size", options.page_size.toString());
1014
+ if (options.search) params.append("search", options.search);
1015
+ if (options.status) params.append("status", options.status);
1016
+ if (options.segment) params.append("segment", options.segment);
1017
+ if (options.has_wallet !== void 0) params.append("has_wallet", options.has_wallet.toString());
1018
+ if (options.sort_by) params.append("sort_by", options.sort_by);
1019
+ if (options.sort_order) params.append("sort_order", options.sort_order);
1020
+ return this.http.get(`/end-users?${params.toString()}`);
1021
+ }
1022
+ /**
1023
+ * Get an end-user by ID
1024
+ */
1025
+ async get(userId) {
1026
+ return this.http.get(`/end-users/${userId}`);
1027
+ }
1028
+ /**
1029
+ * Get an end-user by external ID
1030
+ */
1031
+ async getByExternalId(externalId) {
1032
+ return this.http.get(`/end-users/external/${encodeURIComponent(externalId)}`);
1033
+ }
1034
+ /**
1035
+ * Create an end-user manually
1036
+ */
1037
+ async create(data) {
1038
+ return this.http.post("/end-users", data);
1039
+ }
1040
+ /**
1041
+ * Update an end-user profile
1042
+ */
1043
+ async update(userId, data) {
1044
+ return this.http.patch(`/end-users/${userId}`, data);
1045
+ }
1046
+ /**
1047
+ * Delete an end-user
1048
+ */
1049
+ async delete(userId) {
1050
+ await this.http.delete(`/end-users/${userId}`);
1051
+ }
1052
+ /**
1053
+ * Link a wallet to an end-user
1054
+ */
1055
+ async linkWallet(userId, request) {
1056
+ return this.http.post(`/end-users/${userId}/wallet`, request);
1057
+ }
1058
+ /**
1059
+ * Unlink wallet from an end-user
1060
+ */
1061
+ async unlinkWallet(userId) {
1062
+ return this.http.delete(`/end-users/${userId}/wallet`);
1063
+ }
1064
+ /**
1065
+ * Get user activity/events
1066
+ */
1067
+ async getActivity(userId, options = {}) {
1068
+ const params = new URLSearchParams();
1069
+ if (options.page) params.append("page", options.page.toString());
1070
+ if (options.page_size) params.append("page_size", options.page_size.toString());
1071
+ if (options.event_type) params.append("event_type", options.event_type);
1072
+ return this.http.get(`/end-users/${userId}/activity?${params.toString()}`);
1073
+ }
1074
+ /**
1075
+ * Add points to a user
1076
+ */
1077
+ async addPoints(userId, points, reason) {
1078
+ return this.http.post(`/end-users/${userId}/points`, { points, reason });
1079
+ }
1080
+ /**
1081
+ * Add a segment to a user
1082
+ */
1083
+ async addSegment(userId, segment) {
1084
+ return this.http.post(`/end-users/${userId}/segments`, { segment });
1085
+ }
1086
+ /**
1087
+ * Remove a segment from a user
1088
+ */
1089
+ async removeSegment(userId, segment) {
1090
+ return this.http.delete(`/end-users/${userId}/segments/${encodeURIComponent(segment)}`);
1091
+ }
1092
+ /**
1093
+ * Merge two users (moves all data from source to target)
1094
+ */
1095
+ async merge(request) {
1096
+ return this.http.post("/end-users/merge", request);
1097
+ }
1098
+ /**
1099
+ * Export users as CSV
1100
+ */
1101
+ async export(options = {}) {
1102
+ const params = new URLSearchParams();
1103
+ if (options.segment) params.append("segment", options.segment);
1104
+ if (options.format) params.append("format", options.format);
1105
+ const response = await fetch(`/end-users/export?${params.toString()}`, {
1106
+ headers: { "Accept": "text/csv" }
1107
+ });
1108
+ return response.blob();
1109
+ }
1110
+ };
1111
+
1112
+ // src/rewards.ts
1113
+ var RewardsClient = class {
1114
+ constructor(http) {
1115
+ this.http = http;
1116
+ }
1117
+ // ---------------------------------------------------------------------------
1118
+ // Reward Definitions
1119
+ // ---------------------------------------------------------------------------
1120
+ /**
1121
+ * List reward definitions
1122
+ */
1123
+ async listDefinitions(options = {}) {
1124
+ const params = new URLSearchParams();
1125
+ if (options.is_active !== void 0) params.append("is_active", options.is_active.toString());
1126
+ if (options.reward_type) params.append("reward_type", options.reward_type);
1127
+ return this.http.get(`/rewards/definitions?${params.toString()}`);
1128
+ }
1129
+ /**
1130
+ * Get a reward definition by ID
1131
+ */
1132
+ async getDefinition(definitionId) {
1133
+ return this.http.get(`/rewards/definitions/${definitionId}`);
1134
+ }
1135
+ /**
1136
+ * Create a reward definition
1137
+ */
1138
+ async createDefinition(data) {
1139
+ return this.http.post("/rewards/definitions", data);
1140
+ }
1141
+ /**
1142
+ * Update a reward definition
1143
+ */
1144
+ async updateDefinition(definitionId, data) {
1145
+ return this.http.patch(`/rewards/definitions/${definitionId}`, data);
1146
+ }
1147
+ /**
1148
+ * Delete a reward definition
1149
+ */
1150
+ async deleteDefinition(definitionId) {
1151
+ await this.http.delete(`/rewards/definitions/${definitionId}`);
1152
+ }
1153
+ /**
1154
+ * Activate a reward definition
1155
+ */
1156
+ async activateDefinition(definitionId) {
1157
+ return this.http.post(`/rewards/definitions/${definitionId}/activate`, {});
1158
+ }
1159
+ /**
1160
+ * Deactivate a reward definition
1161
+ */
1162
+ async deactivateDefinition(definitionId) {
1163
+ return this.http.post(`/rewards/definitions/${definitionId}/deactivate`, {});
1164
+ }
1165
+ // ---------------------------------------------------------------------------
1166
+ // Earned Rewards
1167
+ // ---------------------------------------------------------------------------
1168
+ /**
1169
+ * List earned rewards
1170
+ */
1171
+ async listEarned(options = {}) {
1172
+ const params = new URLSearchParams();
1173
+ if (options.user_id) params.append("user_id", options.user_id);
1174
+ if (options.definition_id) params.append("definition_id", options.definition_id);
1175
+ if (options.status) params.append("status", options.status);
1176
+ if (options.limit) params.append("limit", options.limit.toString());
1177
+ if (options.offset) params.append("offset", options.offset.toString());
1178
+ return this.http.get(`/rewards/earned?${params.toString()}`);
1179
+ }
1180
+ /**
1181
+ * Get earned rewards for a user
1182
+ */
1183
+ async getUserRewards(userId) {
1184
+ return this.http.get(`/rewards/earned/user/${userId}`);
1185
+ }
1186
+ /**
1187
+ * Manually award rewards to users
1188
+ */
1189
+ async awardManual(request) {
1190
+ return this.http.post("/rewards/award", request);
1191
+ }
1192
+ /**
1193
+ * Distribute pending rewards (mint NFTs, transfer tokens)
1194
+ */
1195
+ async distributePending(earnedRewardId) {
1196
+ return this.http.post(`/rewards/earned/${earnedRewardId}/distribute`, {});
1197
+ }
1198
+ // ---------------------------------------------------------------------------
1199
+ // Reward Assets
1200
+ // ---------------------------------------------------------------------------
1201
+ /**
1202
+ * Upload an asset for a reward (image, metadata JSON)
1203
+ */
1204
+ async uploadAsset(definitionId, file, assetType) {
1205
+ const formData = new FormData();
1206
+ formData.append("file", file);
1207
+ formData.append("asset_type", assetType);
1208
+ return this.http.requestMultipart(
1209
+ `/rewards/definitions/${definitionId}/assets`,
1210
+ formData
1211
+ );
1212
+ }
1213
+ /**
1214
+ * List assets for a reward definition
1215
+ */
1216
+ async listAssets(definitionId) {
1217
+ return this.http.get(`/rewards/definitions/${definitionId}/assets`);
1218
+ }
1219
+ };
1220
+
1221
+ // src/quests.ts
1222
+ var QuestsClient = class {
1223
+ constructor(http) {
1224
+ this.http = http;
1225
+ }
1226
+ // ---------------------------------------------------------------------------
1227
+ // Quest CRUD
1228
+ // ---------------------------------------------------------------------------
1229
+ /**
1230
+ * List quests
1231
+ */
1232
+ async list(options = {}) {
1233
+ const params = new URLSearchParams();
1234
+ if (options.status) params.append("status", options.status);
1235
+ if (options.category) params.append("category", options.category);
1236
+ if (options.is_public !== void 0) params.append("is_public", options.is_public.toString());
1237
+ if (options.is_featured !== void 0) params.append("is_featured", options.is_featured.toString());
1238
+ if (options.limit) params.append("limit", options.limit.toString());
1239
+ if (options.offset) params.append("offset", options.offset.toString());
1240
+ return this.http.get(`/quests?${params.toString()}`);
1241
+ }
1242
+ /**
1243
+ * Get a quest by ID
1244
+ */
1245
+ async get(questId) {
1246
+ return this.http.get(`/quests/${questId}`);
1247
+ }
1248
+ /**
1249
+ * Get a quest by slug
1250
+ */
1251
+ async getBySlug(slug) {
1252
+ return this.http.get(`/quests/slug/${encodeURIComponent(slug)}`);
1253
+ }
1254
+ /**
1255
+ * Create a quest
1256
+ */
1257
+ async create(data) {
1258
+ return this.http.post("/quests", data);
1259
+ }
1260
+ /**
1261
+ * Update a quest
1262
+ */
1263
+ async update(questId, data) {
1264
+ return this.http.put(`/quests/${questId}`, data);
1265
+ }
1266
+ /**
1267
+ * Delete a quest
1268
+ */
1269
+ async delete(questId) {
1270
+ await this.http.delete(`/quests/${questId}`);
1271
+ }
1272
+ // ---------------------------------------------------------------------------
1273
+ // Quest Status
1274
+ // ---------------------------------------------------------------------------
1275
+ /**
1276
+ * Activate a quest
1277
+ */
1278
+ async activate(questId) {
1279
+ return this.http.post(`/quests/${questId}/activate`, {});
1280
+ }
1281
+ /**
1282
+ * Pause a quest
1283
+ */
1284
+ async pause(questId) {
1285
+ return this.http.post(`/quests/${questId}/pause`, {});
1286
+ }
1287
+ /**
1288
+ * Archive a quest
1289
+ */
1290
+ async archive(questId) {
1291
+ return this.http.post(`/quests/${questId}/archive`, {});
1292
+ }
1293
+ // ---------------------------------------------------------------------------
1294
+ // User Progress
1295
+ // ---------------------------------------------------------------------------
1296
+ /**
1297
+ * Get quest with user progress
1298
+ */
1299
+ async getWithProgress(questId, userId) {
1300
+ return this.http.get(`/quests/${questId}/progress/${encodeURIComponent(userId)}`);
1301
+ }
1302
+ /**
1303
+ * List quests with progress for a user
1304
+ */
1305
+ async listWithProgress(userId, options = {}) {
1306
+ const params = new URLSearchParams();
1307
+ params.append("user_id", userId);
1308
+ if (options.status) params.append("status", options.status);
1309
+ if (options.category) params.append("category", options.category);
1310
+ return this.http.get(`/quests/with-progress?${params.toString()}`);
1311
+ }
1312
+ /**
1313
+ * Start a quest for a user
1314
+ */
1315
+ async startQuest(questId, userId) {
1316
+ return this.http.post(`/quests/${questId}/start`, { user_id: userId });
1317
+ }
1318
+ /**
1319
+ * Get user's progress on a quest
1320
+ */
1321
+ async getUserProgress(questId, userId) {
1322
+ return this.http.get(`/quests/${questId}/progress/${encodeURIComponent(userId)}`);
1323
+ }
1324
+ /**
1325
+ * Complete a step manually
1326
+ */
1327
+ async completeStep(questId, userId, stepId) {
1328
+ return this.http.post(`/quests/${questId}/steps/${stepId}/complete`, {
1329
+ user_id: userId
1330
+ });
1331
+ }
1332
+ /**
1333
+ * Get all quest progress for a user
1334
+ */
1335
+ async getAllUserProgress(userId) {
1336
+ return this.http.get(`/quests/user/${encodeURIComponent(userId)}/progress`);
1337
+ }
1338
+ // ---------------------------------------------------------------------------
1339
+ // Quest Steps
1340
+ // ---------------------------------------------------------------------------
1341
+ /**
1342
+ * Add a step to a quest
1343
+ */
1344
+ async addStep(questId, step) {
1345
+ return this.http.post(`/quests/${questId}/steps`, step);
1346
+ }
1347
+ /**
1348
+ * Update a step
1349
+ */
1350
+ async updateStep(questId, stepId, data) {
1351
+ return this.http.put(`/quests/${questId}/steps/${stepId}`, data);
1352
+ }
1353
+ /**
1354
+ * Delete a step
1355
+ */
1356
+ async deleteStep(questId, stepId) {
1357
+ await this.http.delete(`/quests/${questId}/steps/${stepId}`);
1358
+ }
1359
+ /**
1360
+ * Reorder steps
1361
+ */
1362
+ async reorderSteps(questId, stepIds) {
1363
+ return this.http.post(`/quests/${questId}/steps/reorder`, { step_ids: stepIds });
1364
+ }
1365
+ };
1366
+
1367
+ // src/schemas.ts
1368
+ var SchemasClient = class {
1369
+ constructor(http) {
1370
+ this.http = http;
1371
+ }
1372
+ /**
1373
+ * List schemas
1374
+ */
1375
+ async list(options = {}) {
1376
+ const params = new URLSearchParams();
1377
+ if (options.status) params.append("status", options.status);
1378
+ if (options.search) params.append("search", options.search);
1379
+ if (options.limit) params.append("limit", options.limit.toString());
1380
+ if (options.offset) params.append("offset", options.offset.toString());
1381
+ return this.http.get(`/schemas?${params.toString()}`);
1382
+ }
1383
+ /**
1384
+ * Get a schema by name and optional version
1385
+ */
1386
+ async get(name, version) {
1387
+ const path = version ? `/schemas/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/schemas/${encodeURIComponent(name)}`;
1388
+ return this.http.get(path);
1389
+ }
1390
+ /**
1391
+ * Create a schema from YAML content
1392
+ *
1393
+ * Example YAML:
1394
+ * ```yaml
1395
+ * name: my_event
1396
+ * version: "1.0"
1397
+ * description: My custom event schema
1398
+ *
1399
+ * fields:
1400
+ * user_id:
1401
+ * type: string
1402
+ * required: true
1403
+ * amount:
1404
+ * type: number
1405
+ * min: 0
1406
+ * status:
1407
+ * type: enum
1408
+ * values: [pending, completed, failed]
1409
+ * ```
1410
+ */
1411
+ async create(yamlContent) {
1412
+ return this.http.post("/schemas", { yaml_content: yamlContent });
1413
+ }
1414
+ /**
1415
+ * Update a schema (creates new version)
1416
+ */
1417
+ async update(name, yamlContent) {
1418
+ return this.http.put(`/schemas/${encodeURIComponent(name)}`, {
1419
+ yaml_content: yamlContent
1420
+ });
1421
+ }
1422
+ /**
1423
+ * Delete a schema
1424
+ */
1425
+ async delete(name, version) {
1426
+ const path = version ? `/schemas/${encodeURIComponent(name)}/${encodeURIComponent(version)}` : `/schemas/${encodeURIComponent(name)}`;
1427
+ await this.http.delete(path);
1428
+ }
1429
+ /**
1430
+ * Activate a schema (make it available for validation)
1431
+ */
1432
+ async activate(name, version) {
1433
+ const path = version ? `/schemas/${encodeURIComponent(name)}/${encodeURIComponent(version)}/activate` : `/schemas/${encodeURIComponent(name)}/activate`;
1434
+ return this.http.post(path, {});
1435
+ }
1436
+ /**
1437
+ * Deprecate a schema
1438
+ */
1439
+ async deprecate(name, version) {
1440
+ const path = version ? `/schemas/${encodeURIComponent(name)}/${encodeURIComponent(version)}/deprecate` : `/schemas/${encodeURIComponent(name)}/deprecate`;
1441
+ return this.http.post(path, {});
1442
+ }
1443
+ /**
1444
+ * Set a schema as the default for its name
1445
+ */
1446
+ async setDefault(name, version) {
1447
+ return this.http.post(
1448
+ `/schemas/${encodeURIComponent(name)}/${encodeURIComponent(version)}/set-default`,
1449
+ {}
1450
+ );
1451
+ }
1452
+ /**
1453
+ * Validate data against a schema
1454
+ */
1455
+ async validate(request) {
1456
+ return this.http.post("/schemas/validate", request);
1457
+ }
1458
+ /**
1459
+ * Validate data against multiple schemas
1460
+ */
1461
+ async validateMultiple(schemaNames, data) {
1462
+ return this.http.post("/schemas/validate/batch", {
1463
+ schema_names: schemaNames,
1464
+ data
1465
+ });
1466
+ }
1467
+ /**
1468
+ * Get schema usage statistics
1469
+ */
1470
+ async getUsageStats(name) {
1471
+ return this.http.get(`/schemas/${encodeURIComponent(name)}/stats`);
1472
+ }
1473
+ /**
1474
+ * Clone a schema with a new name
1475
+ */
1476
+ async clone(sourceName, newName, newVersion) {
1477
+ return this.http.post(`/schemas/${encodeURIComponent(sourceName)}/clone`, {
1478
+ new_name: newName,
1479
+ new_version: newVersion
1480
+ });
1481
+ }
1482
+ };
1483
+
1484
+ // src/dataviews.ts
1485
+ var DataViewsClient = class {
1486
+ constructor(http) {
1487
+ this.http = http;
1488
+ }
1489
+ /**
1490
+ * List all available data views.
1491
+ * Returns own views, public views from other tenants, and builtin views.
1492
+ */
1493
+ async list() {
1494
+ return this.http.get("/data-mesh/views");
1495
+ }
1496
+ /**
1497
+ * Get detailed information about a specific data view.
1498
+ */
1499
+ async get(viewName) {
1500
+ return this.http.get(`/data-mesh/views/custom/${viewName}`);
1501
+ }
1502
+ /**
1503
+ * Create a new custom data view.
1504
+ *
1505
+ * @example
1506
+ * ```typescript
1507
+ * const view = await client.dataViews.create({
1508
+ * name: 'engagement_score',
1509
+ * display_name: 'User Engagement Score',
1510
+ * description: 'Weighted score based on user activity',
1511
+ * view_type: 'multi-computation',
1512
+ * computation: [
1513
+ * {
1514
+ * type: 'score',
1515
+ * name: 'activity_score',
1516
+ * event_types: ['page_view', 'purchase'],
1517
+ * event_weights: { page_view: 1, purchase: 10 },
1518
+ * max_score: 1000
1519
+ * },
1520
+ * {
1521
+ * type: 'tier',
1522
+ * name: 'loyalty_tier',
1523
+ * score_source: 'activity_score',
1524
+ * tiers: [
1525
+ * { name: 'Bronze', min: 0, max: 100 },
1526
+ * { name: 'Silver', min: 100, max: 500 },
1527
+ * { name: 'Gold', min: 500, max: 1000 }
1528
+ * ]
1529
+ * }
1530
+ * ]
1531
+ * });
1532
+ * ```
1533
+ */
1534
+ async create(request) {
1535
+ return this.http.post("/data-mesh/views/custom", request);
1536
+ }
1537
+ /**
1538
+ * Update an existing data view.
1539
+ */
1540
+ async update(viewName, request) {
1541
+ return this.http.patch(`/data-mesh/views/custom/${viewName}`, request);
1542
+ }
1543
+ /**
1544
+ * Delete a data view.
1545
+ */
1546
+ async delete(viewName) {
1547
+ await this.http.delete(`/data-mesh/views/custom/${viewName}`);
1548
+ }
1549
+ /**
1550
+ * Execute a data view for a specific user.
1551
+ *
1552
+ * The identifier can be either:
1553
+ * - A wallet address (0x...) - queries web3-bound events
1554
+ * - A user_id - queries all events for that user
1555
+ *
1556
+ * @example
1557
+ * ```typescript
1558
+ * // By user ID
1559
+ * const result = await client.dataViews.execute('user-123', 'fan_score');
1560
+ *
1561
+ * // By wallet address
1562
+ * const result = await client.dataViews.execute('0x123...abc', 'fan_score');
1563
+ *
1564
+ * console.log('Data:', result.data);
1565
+ * console.log('Events processed:', result.total_events);
1566
+ * ```
1567
+ */
1568
+ async execute(identifier, viewName) {
1569
+ return this.http.get(
1570
+ `/data-mesh/views/${identifier}/custom/${viewName}`
1571
+ );
1572
+ }
1573
+ /**
1574
+ * Preview a data view computation without saving it.
1575
+ * Useful for testing computation configurations before creating a view.
1576
+ *
1577
+ * @example
1578
+ * ```typescript
1579
+ * const preview = await client.dataViews.preview({
1580
+ * wallet_address: '0x123...',
1581
+ * computation: {
1582
+ * type: 'score',
1583
+ * event_types: ['purchase', 'login'],
1584
+ * event_weights: { purchase: 10, login: 1 },
1585
+ * max_score: 1000
1586
+ * },
1587
+ * time_window_days: 30
1588
+ * });
1589
+ * ```
1590
+ */
1591
+ async preview(request) {
1592
+ return this.http.post("/data-mesh/views/preview", request);
1593
+ }
1594
+ /**
1595
+ * Get the fan profile view for a wallet.
1596
+ * This is a builtin view that aggregates user activity into a profile.
1597
+ */
1598
+ async getFanProfile(walletAddress) {
1599
+ return this.http.get(`/data-mesh/views/${walletAddress}/fan-profile`);
1600
+ }
1601
+ /**
1602
+ * Get the activity summary view for a wallet.
1603
+ * This is a builtin view that summarizes user activity over time.
1604
+ */
1605
+ async getActivitySummary(walletAddress, days = 30) {
1606
+ return this.http.get(
1607
+ `/data-mesh/views/${walletAddress}/activity-summary`,
1608
+ { days }
1609
+ );
1610
+ }
1611
+ /**
1612
+ * Get event metadata including available event types and their counts.
1613
+ * Useful for building dynamic UIs that show available event types.
1614
+ */
1615
+ async getEventMetadata() {
1616
+ return this.http.get("/data-mesh/event-metadata");
1617
+ }
1618
+ /**
1619
+ * Get available view templates for creating new views.
1620
+ * Templates provide pre-configured computation patterns.
1621
+ */
1622
+ async getTemplates() {
1623
+ const response = await this.http.get("/data-mesh/views/templates");
1624
+ return response.templates || [];
1625
+ }
1626
+ };
1627
+
1628
+ // src/client.ts
1629
+ var DocumentsResource = class {
1630
+ constructor(http) {
1631
+ this.http = http;
1632
+ }
1633
+ /**
1634
+ * Attest a document file.
1635
+ */
1636
+ async attest(request) {
1637
+ const formData = new FormData();
1638
+ if (request.file instanceof Blob) {
1639
+ formData.append("file", request.file, request.filename || "document");
1640
+ } else if (request.file instanceof ArrayBuffer) {
1641
+ const blob = new Blob([request.file]);
1642
+ formData.append("file", blob, request.filename || "document");
1643
+ } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(request.file)) {
1644
+ const uint8 = new Uint8Array(request.file);
1645
+ const blob = new Blob([uint8]);
1646
+ formData.append("file", blob, request.filename || "document");
1647
+ }
1648
+ formData.append("user_id", request.userId);
1649
+ formData.append("event_type", request.eventType || "document_uploaded");
1650
+ if (request.metadata) {
1651
+ formData.append("metadata", JSON.stringify(request.metadata));
1652
+ }
1653
+ if (request.encrypt) {
1654
+ formData.append("encrypt", "1");
1655
+ }
1656
+ return this.http.requestMultipart("/tenant/documents", formData);
1657
+ }
1658
+ /**
1659
+ * Get a document by its IPFS hash.
1660
+ */
1661
+ async get(ipfsHash) {
1662
+ return this.http.get(`/tenant/events/by-hash/${ipfsHash}`);
1663
+ }
1664
+ };
1665
+ var EventsResource = class {
1666
+ constructor(http) {
1667
+ this.http = http;
1668
+ }
1669
+ /**
1670
+ * Create a new attestation event.
1671
+ */
1672
+ async create(request) {
1673
+ return this.http.post("/tenant/events", {
1674
+ event_type: request.eventType,
1675
+ user_id: request.userId,
1676
+ event_source: request.source || "api",
1677
+ data: request.data || {}
1678
+ });
1679
+ }
1680
+ /**
1681
+ * Get an event by ID.
1682
+ */
1683
+ async get(eventId) {
1684
+ return this.http.get(`/tenant/events/${eventId}`);
1685
+ }
1686
+ /**
1687
+ * List events with optional filters.
1688
+ */
1689
+ async list(request = {}) {
1690
+ const response = await this.http.get("/tenant/events", {
1691
+ user_id: request.userId,
1692
+ event_type: request.eventType,
1693
+ status: request.status,
1694
+ start_date: request.startDate,
1695
+ end_date: request.endDate,
1696
+ limit: request.limit,
1697
+ offset: request.offset
1698
+ });
1699
+ return response.events || [];
1700
+ }
1701
+ /**
1702
+ * Search events by query.
1703
+ */
1704
+ async search(request) {
1705
+ return this.http.post("/search", {
1706
+ query: request.query,
1707
+ user_id: request.userId,
1708
+ event_type: request.eventType,
1709
+ start_date: request.startDate,
1710
+ end_date: request.endDate,
1711
+ limit: request.limit,
1712
+ page: request.page
1713
+ });
1714
+ }
1715
+ /**
1716
+ * Get an event by its IPFS hash.
1717
+ */
1718
+ async byHash(ipfsHash) {
1719
+ return this.http.get(`/tenant/events/by-hash/${ipfsHash}`);
1720
+ }
1721
+ /**
1722
+ * Create multiple events in a batch.
1723
+ *
1724
+ * Note: For high-throughput ingestion, use the IngestionClient instead.
1725
+ * This method is a convenience wrapper that creates events sequentially.
1726
+ *
1727
+ * @param events - Array of event requests
1728
+ * @returns Array of created events
1729
+ */
1730
+ async createBatch(events) {
1731
+ const results = [];
1732
+ for (const event of events) {
1733
+ const created = await this.create(event);
1734
+ results.push(created);
1735
+ }
1736
+ return results;
1737
+ }
1738
+ };
1739
+ var ChannelsResource = class {
1740
+ constructor(http) {
1741
+ this.http = http;
1742
+ }
1743
+ /**
1744
+ * Create a new state channel.
1745
+ */
1746
+ async create(request) {
1747
+ return this.http.post("/channels", {
1748
+ name: request.name,
1749
+ description: request.description
1750
+ });
1751
+ }
1752
+ /**
1753
+ * Get a channel by ID.
1754
+ */
1755
+ async get(channelId) {
1756
+ return this.http.get(`/channels/${channelId}`);
1757
+ }
1758
+ /**
1759
+ * Get detailed status of a channel.
1760
+ */
1761
+ async status(channelId) {
1762
+ return this.http.get(`/channels/${channelId}/status`);
1763
+ }
1764
+ /**
1765
+ * List all channels.
1766
+ */
1767
+ async list(limit = 50, offset = 0) {
1768
+ const response = await this.http.get("/channels", {
1769
+ limit,
1770
+ offset
1771
+ });
1772
+ return response.channels || [];
1773
+ }
1774
+ /**
1775
+ * Stream an event to a channel.
1776
+ */
1777
+ async stream(channelId, request) {
1778
+ return this.http.post(`/channels/${channelId}/stream`, {
1779
+ event_type: request.eventType,
1780
+ user_id: request.userId,
1781
+ event_source: request.source || "sdk",
1782
+ data: request.data
1783
+ });
1784
+ }
1785
+ /**
1786
+ * Stream multiple events in a single request.
1787
+ */
1788
+ async streamBatch(channelId, events) {
1789
+ return this.http.post(`/channels/${channelId}/stream/batch`, {
1790
+ events
1791
+ });
1792
+ }
1793
+ /**
1794
+ * Settle a channel on-chain.
1795
+ */
1796
+ async settle(channelId) {
1797
+ return this.http.post(`/channels/${channelId}/settle`);
1798
+ }
1799
+ /**
1800
+ * Close a channel.
1801
+ */
1802
+ async close(channelId) {
1803
+ return this.http.post(`/channels/${channelId}/close`);
1804
+ }
1805
+ };
1806
+ var CertificatesResource = class {
1807
+ constructor(http) {
1808
+ this.http = http;
1809
+ }
1810
+ /**
1811
+ * Issue a new certificate.
1812
+ */
1813
+ async issue(request) {
1814
+ return this.http.post("/certificates", {
1815
+ recipient_name: request.recipientName,
1816
+ recipient_email: request.recipientEmail,
1817
+ title: request.title,
1818
+ description: request.description,
1819
+ metadata: request.metadata,
1820
+ expires_at: request.expiresAt
1821
+ });
1822
+ }
1823
+ /**
1824
+ * Get a certificate by ID.
1825
+ */
1826
+ async get(certificateId) {
1827
+ return this.http.get(`/certificates/${certificateId}`);
1828
+ }
1829
+ /**
1830
+ * List certificates.
1831
+ */
1832
+ async list(request = {}) {
1833
+ const response = await this.http.get(
1834
+ "/certificates",
1835
+ {
1836
+ recipient_email: request.recipientEmail,
1837
+ limit: request.limit,
1838
+ offset: request.offset
1839
+ }
1840
+ );
1841
+ return response.certificates || [];
1842
+ }
1843
+ /**
1844
+ * Revoke a certificate.
1845
+ */
1846
+ async revoke(certificateId, reason) {
1847
+ return this.http.post(`/certificates/${certificateId}/revoke`, {
1848
+ reason
1849
+ });
1850
+ }
1851
+ /**
1852
+ * Verify a certificate.
1853
+ */
1854
+ async verify(certificateId) {
1855
+ return this.http.get(`/verify/cert/${certificateId}`);
1856
+ }
1857
+ };
1858
+ var WebhooksResource = class {
1859
+ constructor(http) {
1860
+ this.http = http;
1861
+ }
1862
+ /**
1863
+ * Create a new webhook.
1864
+ */
1865
+ async create(request) {
1866
+ return this.http.post("/webhooks", {
1867
+ url: request.url,
1868
+ events: request.events,
1869
+ secret: request.secret
1870
+ });
1871
+ }
1872
+ /**
1873
+ * Get a webhook by ID.
1874
+ */
1875
+ async get(webhookId) {
1876
+ return this.http.get(`/webhooks/${webhookId}`);
1877
+ }
1878
+ /**
1879
+ * List all webhooks.
1880
+ */
1881
+ async list() {
1882
+ const response = await this.http.get("/webhooks");
1883
+ return response.webhooks || [];
1884
+ }
1885
+ /**
1886
+ * Update a webhook.
1887
+ */
1888
+ async update(webhookId, request) {
1889
+ return this.http.patch(`/webhooks/${webhookId}`, request);
1890
+ }
1891
+ /**
1892
+ * Delete a webhook.
1893
+ */
1894
+ async delete(webhookId) {
1895
+ await this.http.delete(`/webhooks/${webhookId}`);
1896
+ }
1897
+ /**
1898
+ * Send a test event to a webhook.
1899
+ */
1900
+ async test(webhookId) {
1901
+ return this.http.post(`/webhooks/${webhookId}/test`);
1902
+ }
1903
+ };
1904
+ var ProofChain = class _ProofChain {
1905
+ constructor(options) {
1906
+ this.http = new HttpClient(options);
1907
+ this.documents = new DocumentsResource(this.http);
1908
+ this.events = new EventsResource(this.http);
1909
+ this.channels = new ChannelsResource(this.http);
1910
+ this.certificates = new CertificatesResource(this.http);
1911
+ this.webhooks = new WebhooksResource(this.http);
1912
+ this.vault = new VaultResource(this.http);
1913
+ this.search = new SearchResource(this.http);
1914
+ this.verifyResource = new VerifyResource(this.http);
1915
+ this.tenant = new TenantResource(this.http);
1916
+ this.passports = new PassportClient(this.http);
1917
+ this.wallets = new WalletClient(this.http);
1918
+ this.users = new EndUsersClient(this.http);
1919
+ this.rewards = new RewardsClient(this.http);
1920
+ this.quests = new QuestsClient(this.http);
1921
+ this.schemas = new SchemasClient(this.http);
1922
+ this.dataViews = new DataViewsClient(this.http);
1923
+ }
1924
+ /**
1925
+ * Create a client from environment variables.
1926
+ * Reads PROOFCHAIN_API_KEY and optionally PROOFCHAIN_BASE_URL.
1927
+ */
1928
+ static fromEnv() {
1929
+ const env = typeof process !== "undefined" ? process.env : {};
1930
+ const apiKey = env.PROOFCHAIN_API_KEY;
1931
+ if (!apiKey) {
1932
+ throw new Error("PROOFCHAIN_API_KEY environment variable not set");
1933
+ }
1934
+ return new _ProofChain({
1935
+ apiKey,
1936
+ baseUrl: env.PROOFCHAIN_BASE_URL
1937
+ });
1938
+ }
1939
+ /**
1940
+ * Verify a document or event by its IPFS hash.
1941
+ */
1942
+ async verify(ipfsHash) {
1943
+ return this.http.get(`/verify/${ipfsHash}`);
1944
+ }
1945
+ /**
1946
+ * Get information about the current tenant.
1947
+ */
1948
+ async tenantInfo() {
1949
+ return this.http.get("/tenant/me");
1950
+ }
1951
+ /**
1952
+ * Get API usage statistics.
1953
+ */
1954
+ async usage(period = "month") {
1955
+ return this.http.get("/tenant/usage", { period });
1956
+ }
1957
+ };
1958
+
1959
+ // src/ingestion.ts
1960
+ var DEFAULT_INGEST_URL = "https://ingest.proofchain.co.za";
1961
+ var USER_AGENT2 = "proofchain-js/0.1.0";
1962
+ var IngestionClient = class {
1963
+ constructor(options) {
1964
+ this.apiKey = options.apiKey;
1965
+ this.ingestUrl = (options.ingestUrl || DEFAULT_INGEST_URL).replace(/\/$/, "");
1966
+ this.timeout = options.timeout || 3e4;
1967
+ }
1968
+ getHeaders() {
1969
+ return {
1970
+ "X-API-Key": this.apiKey,
1971
+ "Content-Type": "application/json",
1972
+ "User-Agent": USER_AGENT2
1973
+ };
1974
+ }
1975
+ async handleResponse(response) {
1976
+ const contentType = response.headers.get("content-type");
1977
+ const isJson = contentType?.includes("application/json");
1978
+ if (response.ok) {
1979
+ if (response.status === 204 || !isJson) {
1980
+ return {};
1981
+ }
1982
+ return response.json();
1983
+ }
1984
+ const body = isJson ? await response.json().catch(() => ({})) : {};
1985
+ const message = body.detail || body.message || `HTTP ${response.status}`;
1986
+ switch (response.status) {
1987
+ case 401:
1988
+ throw new AuthenticationError(message);
1989
+ case 422:
1990
+ case 400:
1991
+ throw new ValidationError(message, body.errors);
1992
+ case 429:
1993
+ const retryAfter = response.headers.get("Retry-After");
1994
+ throw new RateLimitError(retryAfter ? parseInt(retryAfter, 10) : void 0);
1995
+ default:
1996
+ if (response.status >= 500) {
1997
+ throw new ServerError(message, response.status);
1998
+ }
1999
+ throw new ProofChainError(message, response.status, body);
2000
+ }
2001
+ }
2002
+ /**
2003
+ * Ingest a single event using the high-performance Rust API.
2004
+ * Events are attested immediately upon ingestion.
2005
+ */
2006
+ async ingest(request) {
2007
+ const controller = new AbortController();
2008
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2009
+ try {
2010
+ const headers = this.getHeaders();
2011
+ if (request.schemaIds?.length) {
2012
+ headers["X-Schemas"] = request.schemaIds.join(",");
2013
+ }
2014
+ const response = await fetch(`${this.ingestUrl}/events/ingest`, {
2015
+ method: "POST",
2016
+ headers,
2017
+ body: JSON.stringify({
2018
+ user_id: request.userId,
2019
+ event_type: request.eventType,
2020
+ data: request.data || {},
2021
+ event_source: request.eventSource || "sdk"
2022
+ }),
2023
+ signal: controller.signal
2024
+ });
2025
+ const result = await this.handleResponse(response);
2026
+ return {
2027
+ eventId: result.event_id,
2028
+ certificateId: result.certificate_id,
2029
+ status: result.status,
2030
+ queuePosition: result.queue_position,
2031
+ estimatedConfirmation: result.estimated_confirmation
2032
+ };
2033
+ } catch (error) {
2034
+ if (error instanceof Error && error.name === "AbortError") {
2035
+ throw new NetworkError("Request timed out");
2036
+ }
2037
+ throw error;
2038
+ } finally {
2039
+ clearTimeout(timeoutId);
2040
+ }
2041
+ }
2042
+ /**
2043
+ * Ingest multiple events in a single request (up to 1000 events).
2044
+ * More efficient than individual calls for bulk data.
2045
+ */
2046
+ async ingestBatch(request) {
2047
+ if (request.events.length > 1e3) {
2048
+ throw new ValidationError("Batch size cannot exceed 1000 events");
2049
+ }
2050
+ const controller = new AbortController();
2051
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout * 2);
2052
+ try {
2053
+ const response = await fetch(`${this.ingestUrl}/events/ingest/batch`, {
2054
+ method: "POST",
2055
+ headers: this.getHeaders(),
2056
+ body: JSON.stringify(
2057
+ request.events.map((e) => ({
2058
+ user_id: e.userId,
2059
+ event_type: e.eventType,
2060
+ data: e.data || {},
2061
+ event_source: e.eventSource || "sdk"
2062
+ }))
2063
+ ),
2064
+ signal: controller.signal
2065
+ });
2066
+ const result = await this.handleResponse(response);
2067
+ return {
2068
+ totalEvents: result.total_events || result.total,
2069
+ queued: result.queued,
2070
+ failed: result.failed,
2071
+ results: (result.results || result.responses || []).map((r) => ({
2072
+ eventId: r.event_id,
2073
+ certificateId: r.certificate_id,
2074
+ status: r.status
2075
+ }))
2076
+ };
2077
+ } catch (error) {
2078
+ if (error instanceof Error && error.name === "AbortError") {
2079
+ throw new NetworkError("Request timed out");
2080
+ }
2081
+ throw error;
2082
+ } finally {
2083
+ clearTimeout(timeoutId);
2084
+ }
2085
+ }
2086
+ /**
2087
+ * Get the status of an event by ID.
2088
+ */
2089
+ async getEventStatus(eventId) {
2090
+ const controller = new AbortController();
2091
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2092
+ try {
2093
+ const response = await fetch(`${this.ingestUrl}/events/${eventId}/status`, {
2094
+ method: "GET",
2095
+ headers: this.getHeaders(),
2096
+ signal: controller.signal
2097
+ });
2098
+ return this.handleResponse(response);
2099
+ } finally {
2100
+ clearTimeout(timeoutId);
2101
+ }
2102
+ }
2103
+ };
371
2104
  // Annotate the CommonJS export names for ESM import in node:
372
2105
  0 && (module.exports = {
373
- AttestationClient,
374
- AttestationClientError,
375
- AttestationRegistryContract,
376
- createClient
2106
+ AuthenticationError,
2107
+ AuthorizationError,
2108
+ CertificatesResource,
2109
+ ChannelsResource,
2110
+ DataViewsClient,
2111
+ DocumentsResource,
2112
+ EndUsersClient,
2113
+ EventsResource,
2114
+ IngestionClient,
2115
+ NetworkError,
2116
+ NotFoundError,
2117
+ PassportClient,
2118
+ ProofChain,
2119
+ ProofChainError,
2120
+ QuestsClient,
2121
+ RateLimitError,
2122
+ RewardsClient,
2123
+ SchemasClient,
2124
+ SearchResource,
2125
+ ServerError,
2126
+ TenantResource,
2127
+ TimeoutError,
2128
+ ValidationError,
2129
+ VaultResource,
2130
+ VerifyResource,
2131
+ WalletClient,
2132
+ WebhooksResource
377
2133
  });