@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/LICENSE +21 -0
- package/README.md +254 -114
- package/dist/index.d.mts +2501 -276
- package/dist/index.d.ts +2501 -276
- package/dist/index.js +2031 -275
- package/dist/index.mjs +2004 -271
- package/package.json +43 -19
- package/src/client.ts +0 -312
- package/src/contract.ts +0 -212
- package/src/index.ts +0 -65
- package/src/types.ts +0 -228
- package/tsconfig.json +0 -18
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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/
|
|
31
|
-
var
|
|
32
|
-
constructor(message,
|
|
53
|
+
// src/errors.ts
|
|
54
|
+
var ProofChainError = class extends Error {
|
|
55
|
+
constructor(message, statusCode, responseBody) {
|
|
33
56
|
super(message);
|
|
34
|
-
this.
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
57
|
+
this.name = "ProofChainError";
|
|
58
|
+
this.statusCode = statusCode;
|
|
59
|
+
this.responseBody = responseBody;
|
|
37
60
|
}
|
|
38
61
|
};
|
|
39
|
-
var
|
|
40
|
-
constructor(
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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 (
|
|
55
|
-
|
|
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
|
-
|
|
62
|
-
|
|
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
|
-
|
|
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.
|
|
248
|
+
return response.arrayBuffer();
|
|
74
249
|
} catch (error) {
|
|
75
250
|
clearTimeout(timeoutId);
|
|
76
|
-
if (error instanceof
|
|
77
|
-
throw new
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Get file details.
|
|
307
|
+
*/
|
|
308
|
+
async get(fileId) {
|
|
309
|
+
return this.http.get(`/tenant/vault/files/${fileId}`);
|
|
86
310
|
}
|
|
87
|
-
|
|
88
|
-
|
|
311
|
+
/**
|
|
312
|
+
* Download a file.
|
|
313
|
+
*/
|
|
314
|
+
async download(fileId) {
|
|
315
|
+
return this.http.getRaw(`/tenant/vault/files/${fileId}/download`);
|
|
89
316
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
317
|
+
/**
|
|
318
|
+
* Delete a file.
|
|
319
|
+
*/
|
|
320
|
+
async delete(fileId) {
|
|
321
|
+
await this.http.delete(`/tenant/vault/files/${fileId}`);
|
|
93
322
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
340
|
+
/**
|
|
341
|
+
* Delete a folder.
|
|
342
|
+
*/
|
|
343
|
+
async deleteFolder(folderId) {
|
|
344
|
+
await this.http.delete(`/tenant/vault/folders/${folderId}`);
|
|
114
345
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// src/resources/verify.ts
|
|
415
|
+
var VerifyResource = class {
|
|
416
|
+
constructor(http) {
|
|
417
|
+
this.http = http;
|
|
137
418
|
}
|
|
138
|
-
|
|
139
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Verify a certificate by ID.
|
|
421
|
+
*/
|
|
422
|
+
async certificate(certificateId) {
|
|
423
|
+
return this.http.get(`/verify/cert/${certificateId}`);
|
|
140
424
|
}
|
|
141
|
-
|
|
142
|
-
|
|
425
|
+
/**
|
|
426
|
+
* Verify an event by IPFS hash.
|
|
427
|
+
*/
|
|
428
|
+
async event(ipfsHash) {
|
|
429
|
+
return this.http.get(`/verify/event/${ipfsHash}`);
|
|
143
430
|
}
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
156
|
-
|
|
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
|
-
*
|
|
161
|
-
* @param userId - End user external ID
|
|
162
|
-
* @param options - Filter options
|
|
498
|
+
* Get tenant context.
|
|
163
499
|
*/
|
|
164
|
-
async
|
|
165
|
-
|
|
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
|
|
176
|
-
* @param questId - Quest ID
|
|
504
|
+
* Get blockchain statistics.
|
|
177
505
|
*/
|
|
178
|
-
async
|
|
179
|
-
return this.
|
|
506
|
+
async blockchainStats() {
|
|
507
|
+
return this.http.get("/tenant/blockchain/stats");
|
|
180
508
|
}
|
|
181
509
|
/**
|
|
182
|
-
*
|
|
183
|
-
* @param questId - Quest ID
|
|
184
|
-
* @param userId - End user external ID
|
|
510
|
+
* Verify a certificate on the blockchain.
|
|
185
511
|
*/
|
|
186
|
-
async
|
|
187
|
-
return this.
|
|
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
|
-
*
|
|
195
|
-
* @param questId - Quest ID
|
|
196
|
-
* @param userId - End user external ID
|
|
516
|
+
* List blockchain certificates.
|
|
197
517
|
*/
|
|
198
|
-
async
|
|
199
|
-
return this.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
);
|
|
518
|
+
async blockchainCertificates(limit, offset) {
|
|
519
|
+
return this.http.get("/tenant/blockchain/certificates", {
|
|
520
|
+
limit,
|
|
521
|
+
offset
|
|
522
|
+
});
|
|
203
523
|
}
|
|
204
524
|
/**
|
|
205
|
-
*
|
|
206
|
-
* @param userId - End user external ID
|
|
207
|
-
* @param status - Optional status filter
|
|
525
|
+
* Force batch settlement.
|
|
208
526
|
*/
|
|
209
|
-
async
|
|
210
|
-
|
|
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
|
-
*
|
|
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
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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/
|
|
239
|
-
var
|
|
240
|
-
|
|
241
|
-
|
|
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
|
-
//
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
-
|
|
282
|
-
|
|
561
|
+
/**
|
|
562
|
+
* Get a passport by user ID
|
|
563
|
+
*/
|
|
564
|
+
async get(userId) {
|
|
565
|
+
return this.http.get(`/passports/${encodeURIComponent(userId)}`);
|
|
283
566
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
289
|
-
|
|
575
|
+
/**
|
|
576
|
+
* Create a new passport for a user
|
|
577
|
+
*/
|
|
578
|
+
async create(data) {
|
|
579
|
+
return this.http.post("/passports", data);
|
|
290
580
|
}
|
|
291
|
-
|
|
292
|
-
|
|
581
|
+
/**
|
|
582
|
+
* Update a passport
|
|
583
|
+
*/
|
|
584
|
+
async update(userId, data) {
|
|
585
|
+
return this.http.put(`/passports/${encodeURIComponent(userId)}`, data);
|
|
293
586
|
}
|
|
294
|
-
|
|
295
|
-
|
|
587
|
+
/**
|
|
588
|
+
* Delete a passport
|
|
589
|
+
*/
|
|
590
|
+
async delete(userId) {
|
|
591
|
+
await this.http.delete(`/passports/${encodeURIComponent(userId)}`);
|
|
296
592
|
}
|
|
297
|
-
|
|
298
|
-
|
|
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
|
-
|
|
301
|
-
|
|
602
|
+
/**
|
|
603
|
+
* Level up a passport
|
|
604
|
+
*/
|
|
605
|
+
async levelUp(userId) {
|
|
606
|
+
return this.http.post(`/passports/${encodeURIComponent(userId)}/level-up`, {});
|
|
302
607
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
-
|
|
336
|
-
|
|
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
|
-
//
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
return
|
|
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
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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
|
});
|