@prosopo/database 1.0.2 → 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.
Files changed (44) hide show
  1. package/dist/captchaDatabase/captchaDatabase.d.ts +4 -0
  2. package/dist/captchaDatabase/captchaDatabase.d.ts.map +1 -0
  3. package/dist/captchaDatabase/captchaDatabase.js +31 -0
  4. package/dist/captchaDatabase/captchaDatabase.js.map +1 -0
  5. package/dist/captchaDatabase/index.d.ts +1 -1
  6. package/dist/captchaDatabase/index.d.ts.map +1 -1
  7. package/dist/captchaDatabase/index.js +1 -1
  8. package/dist/captchaDatabase/index.js.map +1 -1
  9. package/dist/cjs/captchaDatabase/captchaDatabase.cjs +37 -0
  10. package/dist/cjs/captchaDatabase/index.cjs +2 -2
  11. package/dist/cjs/databases/mongo.cjs +173 -68
  12. package/dist/cjs/databases/mongoMemory.cjs +1 -1
  13. package/dist/cjs/index.cjs +2 -2
  14. package/dist/databases/index.d.ts +2 -2
  15. package/dist/databases/index.d.ts.map +1 -1
  16. package/dist/databases/index.js +3 -3
  17. package/dist/databases/index.js.map +1 -1
  18. package/dist/databases/mongo.d.ts +8 -7
  19. package/dist/databases/mongo.d.ts.map +1 -1
  20. package/dist/databases/mongo.js +189 -119
  21. package/dist/databases/mongo.js.map +1 -1
  22. package/dist/databases/mongoMemory.d.ts +2 -2
  23. package/dist/databases/mongoMemory.d.ts.map +1 -1
  24. package/dist/databases/mongoMemory.js +2 -2
  25. package/dist/databases/mongoMemory.js.map +1 -1
  26. package/dist/eventsDatabase/eventsDatabase.d.ts +1 -1
  27. package/dist/eventsDatabase/eventsDatabase.d.ts.map +1 -1
  28. package/dist/eventsDatabase/eventsDatabase.js +8 -6
  29. package/dist/eventsDatabase/eventsDatabase.js.map +1 -1
  30. package/dist/eventsDatabase/index.d.ts +1 -1
  31. package/dist/eventsDatabase/index.d.ts.map +1 -1
  32. package/dist/eventsDatabase/index.js +1 -1
  33. package/dist/eventsDatabase/index.js.map +1 -1
  34. package/dist/index.d.ts +3 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -3
  37. package/dist/index.js.map +1 -1
  38. package/package.json +44 -53
  39. package/vite.cjs.config.ts +3 -3
  40. package/dist/captchaDatabase/captchaDatabse.d.ts +0 -3
  41. package/dist/captchaDatabase/captchaDatabse.d.ts.map +0 -1
  42. package/dist/captchaDatabase/captchaDatabse.js +0 -12
  43. package/dist/captchaDatabase/captchaDatabse.js.map +0 -1
  44. package/dist/cjs/captchaDatabase/captchaDatabse.cjs +0 -14
@@ -0,0 +1,4 @@
1
+ import { type UserCommitmentRecord } from "@prosopo/types-database";
2
+ import { PowCaptcha } from "@prosopo/types";
3
+ export declare const saveCaptchas: (imageCaptchaEvents: UserCommitmentRecord[], powCaptchaEvents: PowCaptcha[], atlasUri: string) => Promise<void>;
4
+ //# sourceMappingURL=captchaDatabase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captchaDatabase.d.ts","sourceRoot":"","sources":["../../src/captchaDatabase/captchaDatabase.ts"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,oBAAoB,EAE1B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAM5C,eAAO,MAAM,YAAY,uBACH,oBAAoB,EAAE,oBACxB,UAAU,EAAE,YACpB,MAAM,kBA+BjB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { getLoggerDefault } from "@prosopo/common";
2
+ import { PowCaptchaRecordSchema, UserCommitmentRecordSchema, } from "@prosopo/types-database";
3
+ import mongoose from "mongoose";
4
+ const logger = getLoggerDefault();
5
+ let StoredImageCaptcha;
6
+ let StoredPoWCaptcha;
7
+ export const saveCaptchas = async (imageCaptchaEvents, powCaptchaEvents, atlasUri) => {
8
+ const connection = mongoose.createConnection(atlasUri, {
9
+ authSource: "admin",
10
+ });
11
+ await new Promise((resolve, reject) => {
12
+ connection
13
+ .once("open", () => {
14
+ logger.info("Connected to MongoDB Atlas");
15
+ StoredImageCaptcha = connection.model("StoredImageCaptcha", UserCommitmentRecordSchema);
16
+ StoredPoWCaptcha = connection.model("StoredPoWCaptcha", PowCaptchaRecordSchema);
17
+ resolve();
18
+ })
19
+ .on("error", reject);
20
+ });
21
+ if (imageCaptchaEvents.length) {
22
+ await StoredImageCaptcha.insertMany(imageCaptchaEvents);
23
+ logger.info("Mongo Saved Image Events");
24
+ }
25
+ if (powCaptchaEvents.length) {
26
+ await StoredPoWCaptcha.insertMany(powCaptchaEvents);
27
+ logger.info("Mongo Saved PoW Events");
28
+ }
29
+ await connection.close();
30
+ };
31
+ //# sourceMappingURL=captchaDatabase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captchaDatabase.js","sourceRoot":"","sources":["../../src/captchaDatabase/captchaDatabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAcnD,OAAO,EACL,sBAAsB,EAEtB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;AAElC,IAAI,kBAAwD,CAAC;AAC7D,IAAI,gBAA4C,CAAC;AAEjD,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,kBAA0C,EAC1C,gBAA8B,EAC9B,QAAgB,EAChB,EAAE;IACF,MAAM,UAAU,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE;QACrD,UAAU,EAAE,OAAO;KACpB,CAAC,CAAC;IACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,UAAU;aACP,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;YACjB,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC1C,kBAAkB,GAAG,UAAU,CAAC,KAAK,CACnC,oBAAoB,EACpB,0BAA0B,CAC3B,CAAC;YACF,gBAAgB,GAAG,UAAU,CAAC,KAAK,CACjC,kBAAkB,EAClB,sBAAsB,CACvB,CAAC;YACF,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;aACD,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,IAAI,kBAAkB,CAAC,MAAM,EAAE;QAC7B,MAAM,kBAAkB,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;KACzC;IACD,IAAI,gBAAgB,CAAC,MAAM,EAAE;QAC3B,MAAM,gBAAgB,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;KACvC;IAED,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;AAC3B,CAAC,CAAC"}
@@ -1,2 +1,2 @@
1
- export * from './captchaDatabse.js';
1
+ export * from "./captchaDatabase.js";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/captchaDatabase/index.ts"],"names":[],"mappings":"AAaA,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/captchaDatabase/index.ts"],"names":[],"mappings":"AAaA,cAAc,sBAAsB,CAAC"}
@@ -1,2 +1,2 @@
1
- export * from './captchaDatabse.js';
1
+ export * from "./captchaDatabase.js";
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/captchaDatabase/index.ts"],"names":[],"mappings":"AAaA,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/captchaDatabase/index.ts"],"names":[],"mappings":"AAaA,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const common = require("@prosopo/common");
4
+ const typesDatabase = require("@prosopo/types-database");
5
+ const mongoose = require("mongoose");
6
+ const logger = common.getLoggerDefault();
7
+ let StoredImageCaptcha;
8
+ let StoredPoWCaptcha;
9
+ const saveCaptchas = async (imageCaptchaEvents, powCaptchaEvents, atlasUri) => {
10
+ const connection = mongoose.createConnection(atlasUri, {
11
+ authSource: "admin"
12
+ });
13
+ await new Promise((resolve, reject) => {
14
+ connection.once("open", () => {
15
+ logger.info("Connected to MongoDB Atlas");
16
+ StoredImageCaptcha = connection.model(
17
+ "StoredImageCaptcha",
18
+ typesDatabase.UserCommitmentRecordSchema
19
+ );
20
+ StoredPoWCaptcha = connection.model(
21
+ "StoredPoWCaptcha",
22
+ typesDatabase.PowCaptchaRecordSchema
23
+ );
24
+ resolve();
25
+ }).on("error", reject);
26
+ });
27
+ if (imageCaptchaEvents.length) {
28
+ await StoredImageCaptcha.insertMany(imageCaptchaEvents);
29
+ logger.info("Mongo Saved Image Events");
30
+ }
31
+ if (powCaptchaEvents.length) {
32
+ await StoredPoWCaptcha.insertMany(powCaptchaEvents);
33
+ logger.info("Mongo Saved PoW Events");
34
+ }
35
+ await connection.close();
36
+ };
37
+ exports.saveCaptchas = saveCaptchas;
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const captchaDatabse = require("./captchaDatabse.cjs");
4
- exports.saveCaptchas = captchaDatabse.saveCaptchas;
3
+ const captchaDatabase = require("./captchaDatabase.cjs");
4
+ exports.saveCaptchas = captchaDatabase.saveCaptchas;
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const is = require("@polkadot/util/is");
3
4
  const common = require("@prosopo/common");
4
5
  const types = require("@prosopo/types");
5
6
  const typesDatabase = require("@prosopo/types-database");
6
- const typesReturns = require("@prosopo/captcha-contract/types-returns");
7
7
  const mongodb = require("mongodb");
8
- const is = require("@polkadot/util/is");
9
8
  const mongoose = require("mongoose");
10
9
  mongoose.set("strictQuery", false);
11
10
  const DEFAULT_ENDPOINT = "mongodb://127.0.0.1:27017";
@@ -50,7 +49,9 @@ class ProsopoDatabase extends common.AsyncFactory {
50
49
  * @description Connect to the database and set the various tables
51
50
  */
52
51
  async connect() {
53
- this.logger.info(`Mongo url: ${this.url.replace(/\w+:\w+/, "<Credentials>")}`);
52
+ this.logger.info(
53
+ `Mongo url: ${this.url.replace(/\w+:\w+/, "<Credentials>")}`
54
+ );
54
55
  this.connection = await new Promise((resolve, reject) => {
55
56
  const connection = mongoose.createConnection(this.url, {
56
57
  dbName: this.dbname,
@@ -66,12 +67,14 @@ class ProsopoDatabase extends common.AsyncFactory {
66
67
  });
67
68
  connection.on("connected", () => {
68
69
  this.logger.info(`Database connected to ${this.url}`);
70
+ resolve(connection);
69
71
  });
70
72
  connection.on("disconnected", () => {
71
73
  this.logger.info(`Database disconnected from ${this.url}`);
72
74
  });
73
75
  connection.on("reconnected", () => {
74
76
  this.logger.info(`Database reconnected to ${this.url}`);
77
+ resolve(connection);
75
78
  });
76
79
  connection.on("reconnectFailed", () => {
77
80
  this.logger.error(`Database reconnect failed to ${this.url}`);
@@ -81,6 +84,7 @@ class ProsopoDatabase extends common.AsyncFactory {
81
84
  });
82
85
  connection.on("fullsetup", () => {
83
86
  this.logger.info(`Database connection to ${this.url} is fully setup`);
87
+ resolve(connection);
84
88
  });
85
89
  });
86
90
  this.tables = {
@@ -88,8 +92,14 @@ class ProsopoDatabase extends common.AsyncFactory {
88
92
  powCaptcha: this.connection.model("PowCaptcha", typesDatabase.PowCaptchaRecordSchema),
89
93
  dataset: this.connection.model("Dataset", typesDatabase.DatasetRecordSchema),
90
94
  solution: this.connection.model("Solution", typesDatabase.SolutionRecordSchema),
91
- commitment: this.connection.model("UserCommitment", typesDatabase.UserCommitmentRecordSchema),
92
- usersolution: this.connection.model("UserSolution", typesDatabase.UserSolutionRecordSchema),
95
+ commitment: this.connection.model(
96
+ "UserCommitment",
97
+ typesDatabase.UserCommitmentRecordSchema
98
+ ),
99
+ usersolution: this.connection.model(
100
+ "UserSolution",
101
+ typesDatabase.UserSolutionRecordSchema
102
+ ),
93
103
  pending: this.connection.model("Pending", typesDatabase.PendingRecordSchema),
94
104
  scheduler: this.connection.model("Scheduler", typesDatabase.ScheduledTaskRecordSchema)
95
105
  };
@@ -105,7 +115,7 @@ class ProsopoDatabase extends common.AsyncFactory {
105
115
  */
106
116
  async storeDataset(dataset) {
107
117
  try {
108
- this.logger.debug(`Storing dataset in database`);
118
+ this.logger.debug("Storing dataset in database");
109
119
  const parsedDataset = types.DatasetWithIdsAndTreeSchema.parse(dataset);
110
120
  const datasetDoc = {
111
121
  datasetId: parsedDataset.datasetId,
@@ -119,14 +129,16 @@ class ProsopoDatabase extends common.AsyncFactory {
119
129
  { $set: datasetDoc },
120
130
  { upsert: true }
121
131
  );
122
- const captchaDocs = parsedDataset.captchas.map(({ solution, ...captcha }, index) => ({
123
- ...captcha,
124
- datasetId: parsedDataset.datasetId,
125
- datasetContentId: parsedDataset.datasetContentId,
126
- index,
127
- solved: !!solution?.length
128
- }));
129
- this.logger.debug(`Inserting captcha records`);
132
+ const captchaDocs = parsedDataset.captchas.map(
133
+ ({ solution, ...captcha }, index) => ({
134
+ ...captcha,
135
+ datasetId: parsedDataset.datasetId,
136
+ datasetContentId: parsedDataset.datasetContentId,
137
+ index,
138
+ solved: !!solution?.length
139
+ })
140
+ );
141
+ this.logger.debug("Inserting captcha records");
130
142
  if (captchaDocs.length) {
131
143
  await this.tables?.captcha.bulkWrite(
132
144
  captchaDocs.map((captchaDoc) => ({
@@ -146,7 +158,7 @@ class ProsopoDatabase extends common.AsyncFactory {
146
158
  datasetId: parsedDataset.datasetId,
147
159
  datasetContentId: parsedDataset.datasetContentId
148
160
  }));
149
- this.logger.debug(`Inserting solution records`);
161
+ this.logger.debug("Inserting solution records");
150
162
  if (captchaSolutionDocs.length) {
151
163
  await this.tables?.solution.bulkWrite(
152
164
  captchaSolutionDocs.map((captchaSolutionDoc) => ({
@@ -158,7 +170,7 @@ class ProsopoDatabase extends common.AsyncFactory {
158
170
  }))
159
171
  );
160
172
  }
161
- this.logger.debug(`Dataset stored in database`);
173
+ this.logger.debug("Dataset stored in database");
162
174
  } catch (err) {
163
175
  throw new common.ProsopoDBError("DATABASE.DATASET_LOAD_FAILED", {
164
176
  context: { failedFuncName: this.storeDataset.name, error: err },
@@ -239,11 +251,16 @@ class ProsopoDatabase extends common.AsyncFactory {
239
251
  }
240
252
  ]);
241
253
  const docs = await cursor;
242
- if (docs && docs.length) {
254
+ if (docs?.length) {
243
255
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
244
256
  }
245
257
  throw new common.ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
246
- context: { failedFuncName: this.getRandomCaptcha.name, solved, datasetId, size }
258
+ context: {
259
+ failedFuncName: this.getRandomCaptcha.name,
260
+ solved,
261
+ datasetId,
262
+ size
263
+ }
247
264
  });
248
265
  }
249
266
  /**
@@ -253,7 +270,7 @@ class ProsopoDatabase extends common.AsyncFactory {
253
270
  async getCaptchaById(captchaId) {
254
271
  const cursor = this.tables?.captcha.find({ captchaId: { $in: captchaId } }).lean();
255
272
  const docs = await cursor;
256
- if (docs && docs.length) {
273
+ if (docs?.length) {
257
274
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
258
275
  }
259
276
  throw new common.ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
@@ -272,7 +289,11 @@ class ProsopoDatabase extends common.AsyncFactory {
272
289
  });
273
290
  }
274
291
  try {
275
- await this.tables?.captcha.updateOne({ datasetId }, { $set: captcha }, { upsert: false });
292
+ await this.tables?.captcha.updateOne(
293
+ { datasetId },
294
+ { $set: captcha },
295
+ { upsert: false }
296
+ );
276
297
  } catch (err) {
277
298
  throw new common.ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
278
299
  context: { failedFuncName: this.getDatasetDetails.name, error: err }
@@ -299,7 +320,10 @@ class ProsopoDatabase extends common.AsyncFactory {
299
320
  return doc;
300
321
  }
301
322
  throw new common.ProsopoDBError("DATABASE.DATASET_GET_FAILED", {
302
- context: { failedFuncName: this.getDatasetDetails.name, datasetId }
323
+ context: {
324
+ failedFuncName: this.getDatasetDetails.name,
325
+ datasetId
326
+ }
303
327
  });
304
328
  }
305
329
  /**
@@ -337,25 +361,29 @@ class ProsopoDatabase extends common.AsyncFactory {
337
361
  /**
338
362
  * @description Adds a new PoW Captcha record to the database.
339
363
  * @param {string} challenge The challenge string for the captcha.
364
+ * @param components The components of the PoW challenge.
340
365
  * @param {boolean} checked Indicates if the captcha has been checked.
341
366
  * @returns {Promise<void>} A promise that resolves when the record is added.
342
367
  */
343
- async storePowCaptchaRecord(challenge, checked) {
344
- if (!this.tables) {
345
- throw new common.ProsopoEnvError("DATABASE.DATABASE_UNDEFINED", {
346
- context: { failedFuncName: this.storePowCaptchaRecord.name },
347
- logger: this.logger
348
- });
349
- }
368
+ async storePowCaptchaRecord(challenge, components, checked) {
369
+ const tables = this.getTables();
350
370
  const powCaptchaRecord = {
351
371
  challenge,
372
+ ...components,
352
373
  checked
353
374
  };
354
375
  try {
355
- await this.tables.powCaptcha.create(powCaptchaRecord);
356
- this.logger.info("PowCaptcha record added successfully", { challenge, checked });
376
+ await tables.powCaptcha.create(powCaptchaRecord);
377
+ this.logger.info("PowCaptcha record added successfully", {
378
+ challenge,
379
+ checked
380
+ });
357
381
  } catch (error) {
358
- this.logger.error("Failed to add PowCaptcha record", { error, challenge, checked });
382
+ this.logger.error("Failed to add PowCaptcha record", {
383
+ error,
384
+ challenge,
385
+ checked
386
+ });
359
387
  throw new common.ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
360
388
  context: { error, challenge, checked },
361
389
  logger: this.logger
@@ -377,14 +405,18 @@ class ProsopoDatabase extends common.AsyncFactory {
377
405
  try {
378
406
  const record = await this.tables.powCaptcha.findOne({ challenge }).lean();
379
407
  if (record) {
380
- this.logger.info("PowCaptcha record retrieved successfully", { challenge });
408
+ this.logger.info("PowCaptcha record retrieved successfully", {
409
+ challenge
410
+ });
381
411
  return record;
382
- } else {
383
- this.logger.info("No PowCaptcha record found", { challenge });
384
- return null;
385
412
  }
413
+ this.logger.info("No PowCaptcha record found", { challenge });
414
+ return null;
386
415
  } catch (error) {
387
- this.logger.error("Failed to retrieve PowCaptcha record", { error, challenge });
416
+ this.logger.error("Failed to retrieve PowCaptcha record", {
417
+ error,
418
+ challenge
419
+ });
388
420
  throw new common.ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
389
421
  context: { error, challenge },
390
422
  logger: this.logger
@@ -398,25 +430,32 @@ class ProsopoDatabase extends common.AsyncFactory {
398
430
  * @returns {Promise<void>} A promise that resolves when the record is updated.
399
431
  */
400
432
  async updatePowCaptchaRecord(challenge, checked) {
401
- if (!this.tables) {
402
- throw new common.ProsopoEnvError("DATABASE.DATABASE_UNDEFINED", {
403
- context: { failedFuncName: this.updatePowCaptchaRecord.name },
404
- logger: this.logger
405
- });
406
- }
433
+ const tables = this.getTables();
407
434
  try {
408
- const updateResult = await this.tables.powCaptcha.updateOne({ challenge }, { $set: { checked } });
435
+ const updateResult = await tables.powCaptcha.updateOne(
436
+ { challenge },
437
+ { $set: { checked } }
438
+ );
409
439
  if (updateResult.matchedCount === 0) {
410
- this.logger.info("No PowCaptcha record found to update", { challenge, checked });
440
+ this.logger.info("No PowCaptcha record found to update", {
441
+ challenge,
442
+ checked
443
+ });
411
444
  throw new common.ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
412
445
  context: { challenge, checked },
413
446
  logger: this.logger
414
447
  });
415
- } else {
416
- this.logger.info("PowCaptcha record updated successfully", { challenge, checked });
417
448
  }
449
+ this.logger.info("PowCaptcha record updated successfully", {
450
+ challenge,
451
+ checked
452
+ });
418
453
  } catch (error) {
419
- this.logger.error("Failed to update PowCaptcha record", { error, challenge, checked });
454
+ this.logger.error("Failed to update PowCaptcha record", {
455
+ error,
456
+ challenge,
457
+ checked
458
+ });
420
459
  throw new common.ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
421
460
  context: { error, challenge, checked },
422
461
  logger: this.logger
@@ -441,7 +480,8 @@ class ProsopoDatabase extends common.AsyncFactory {
441
480
  const docs = await this.tables?.commitment.find({ batched: false }).lean();
442
481
  return docs ? docs.map((doc) => typesDatabase.UserCommitmentSchema.parse(doc)) : [];
443
482
  }
444
- /** @description Get Dapp User captcha commitments from the commitments table that have not been batched on-chain
483
+ /** @description Get Dapp User captcha commitments from the commitments table that have not been counted towards the
484
+ * client's total
445
485
  */
446
486
  async getUnstoredDappUserCommitments() {
447
487
  const docs = await this.tables?.commitment.find({
@@ -458,6 +498,23 @@ class ProsopoDatabase extends common.AsyncFactory {
458
498
  { upsert: false }
459
499
  );
460
500
  }
501
+ /** @description Get Dapp User PoW captcha commitments that have not been counted towards the client's total
502
+ */
503
+ async getUnstoredDappUserPoWCommitments() {
504
+ const docs = await this.tables?.powCaptcha.find({
505
+ $or: [{ stored: false }, { stored: { $exists: false } }]
506
+ }).lean();
507
+ return docs || [];
508
+ }
509
+ /** @description Mark a list of PoW captcha commits as stored
510
+ */
511
+ async markDappUserPoWCommitmentsStored(challengeIds) {
512
+ await this.tables?.powCaptcha.updateMany(
513
+ { challenge: { $in: challengeIds } },
514
+ { $set: { stored: true } },
515
+ { upsert: false }
516
+ );
517
+ }
461
518
  /** @description Get Dapp User captcha commitments from the commitments table that have been batched on-chain
462
519
  */
463
520
  async getBatchedDappUserCommitments() {
@@ -467,12 +524,18 @@ class ProsopoDatabase extends common.AsyncFactory {
467
524
  /** @description Remove processed Dapp User captcha solutions from the user solution table
468
525
  */
469
526
  async removeProcessedDappUserSolutions(commitmentIds) {
470
- return await this.tables?.usersolution.deleteMany({ processed: true, commitmentId: { $in: commitmentIds } });
527
+ return await this.tables?.usersolution.deleteMany({
528
+ processed: true,
529
+ commitmentId: { $in: commitmentIds }
530
+ });
471
531
  }
472
532
  /** @description Remove processed Dapp User captcha commitments from the user commitments table
473
533
  */
474
534
  async removeProcessedDappUserCommitments(commitmentIds) {
475
- return await this.tables?.commitment.deleteMany({ processed: true, id: { $in: commitmentIds } });
535
+ return await this.tables?.commitment.deleteMany({
536
+ processed: true,
537
+ id: { $in: commitmentIds }
538
+ });
476
539
  }
477
540
  /**
478
541
  * @description Store a Dapp User's pending record
@@ -480,7 +543,10 @@ class ProsopoDatabase extends common.AsyncFactory {
480
543
  async storeDappUserPending(userAccount, requestHash, salt, deadlineTimestamp, requestedAtBlock) {
481
544
  if (!is.isHex(requestHash)) {
482
545
  throw new common.ProsopoDBError("DATABASE.INVALID_HASH", {
483
- context: { failedFuncName: this.storeDappUserPending.name, requestHash }
546
+ context: {
547
+ failedFuncName: this.storeDappUserPending.name,
548
+ requestHash
549
+ }
484
550
  });
485
551
  }
486
552
  const pendingRecord = {
@@ -491,7 +557,11 @@ class ProsopoDatabase extends common.AsyncFactory {
491
557
  deadlineTimestamp,
492
558
  requestedAtBlock
493
559
  };
494
- await this.tables?.pending.updateOne({ requestHash }, { $set: pendingRecord }, { upsert: true });
560
+ await this.tables?.pending.updateOne(
561
+ { requestHash },
562
+ { $set: pendingRecord },
563
+ { upsert: true }
564
+ );
495
565
  }
496
566
  /**
497
567
  * @description Get a Dapp user's pending record
@@ -516,7 +586,10 @@ class ProsopoDatabase extends common.AsyncFactory {
516
586
  async updateDappUserPendingStatus(requestHash) {
517
587
  if (!is.isHex(requestHash)) {
518
588
  throw new common.ProsopoEnvError("DATABASE.INVALID_HASH", {
519
- context: { failedFuncName: this.updateDappUserPendingStatus.name, requestHash }
589
+ context: {
590
+ failedFuncName: this.updateDappUserPendingStatus.name,
591
+ requestHash
592
+ }
520
593
  });
521
594
  }
522
595
  await this.tables?.pending.updateOne(
@@ -550,7 +623,9 @@ class ProsopoDatabase extends common.AsyncFactory {
550
623
  const cursor = this.tables?.usersolution?.find({ captchaId: { $in: captchaId } }).lean();
551
624
  const docs = await cursor;
552
625
  if (docs) {
553
- return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
626
+ return docs.map(
627
+ ({ _id, ...keepAttrs }) => keepAttrs
628
+ );
554
629
  }
555
630
  throw new common.ProsopoEnvError("DATABASE.SOLUTION_GET_FAILED");
556
631
  }
@@ -575,7 +650,7 @@ class ProsopoDatabase extends common.AsyncFactory {
575
650
  }
576
651
  ]);
577
652
  const docs = await cursor;
578
- if (docs && docs.length) {
653
+ if (docs?.length) {
579
654
  return docs[0]._id;
580
655
  }
581
656
  throw new common.ProsopoDBError("DATABASE.DATASET_WITH_SOLUTIONS_GET_FAILED");
@@ -583,7 +658,10 @@ class ProsopoDatabase extends common.AsyncFactory {
583
658
  async getRandomSolvedCaptchasFromSingleDataset(datasetId, size) {
584
659
  if (!is.isHex(datasetId)) {
585
660
  throw new common.ProsopoDBError("DATABASE.INVALID_HASH", {
586
- context: { failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name, datasetId }
661
+ context: {
662
+ failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
663
+ datasetId
664
+ }
587
665
  });
588
666
  }
589
667
  const sampleSize = size ? Math.abs(Math.trunc(size)) : 1;
@@ -599,11 +677,15 @@ class ProsopoDatabase extends common.AsyncFactory {
599
677
  }
600
678
  ]);
601
679
  const docs = await cursor;
602
- if (docs && docs.length) {
680
+ if (docs?.length) {
603
681
  return docs;
604
682
  }
605
683
  throw new common.ProsopoDBError("DATABASE.SOLUTION_GET_FAILED", {
606
- context: { failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name, datasetId, size }
684
+ context: {
685
+ failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
686
+ datasetId,
687
+ size
688
+ }
607
689
  });
608
690
  }
609
691
  /**
@@ -650,11 +732,13 @@ class ProsopoDatabase extends common.AsyncFactory {
650
732
  try {
651
733
  await this.tables?.commitment?.findOneAndUpdate(
652
734
  { id: commitmentId },
653
- { $set: { status: typesReturns.CaptchaStatus.approved } },
735
+ { $set: { status: types.CaptchaStatus.approved } },
654
736
  { upsert: false }
655
737
  ).lean();
656
738
  } catch (err) {
657
- throw new common.ProsopoDBError("DATABASE.SOLUTION_APPROVE_FAILED", { context: { error: err, commitmentId } });
739
+ throw new common.ProsopoDBError("DATABASE.SOLUTION_APPROVE_FAILED", {
740
+ context: { error: err, commitmentId }
741
+ });
658
742
  }
659
743
  }
660
744
  /**
@@ -663,9 +747,15 @@ class ProsopoDatabase extends common.AsyncFactory {
663
747
  */
664
748
  async flagProcessedDappUserSolutions(captchaIds) {
665
749
  try {
666
- await this.tables?.usersolution?.updateMany({ captchaId: { $in: captchaIds } }, { $set: { processed: true } }, { upsert: false }).lean();
750
+ await this.tables?.usersolution?.updateMany(
751
+ { captchaId: { $in: captchaIds } },
752
+ { $set: { processed: true } },
753
+ { upsert: false }
754
+ ).lean();
667
755
  } catch (err) {
668
- throw new common.ProsopoDBError("DATABASE.SOLUTION_FLAG_FAILED", { context: { error: err, captchaIds } });
756
+ throw new common.ProsopoDBError("DATABASE.SOLUTION_FLAG_FAILED", {
757
+ context: { error: err, captchaIds }
758
+ });
669
759
  }
670
760
  }
671
761
  /**
@@ -675,9 +765,15 @@ class ProsopoDatabase extends common.AsyncFactory {
675
765
  async flagProcessedDappUserCommitments(commitmentIds) {
676
766
  try {
677
767
  const distinctCommitmentIds = [...new Set(commitmentIds)];
678
- await this.tables?.commitment?.updateMany({ id: { $in: distinctCommitmentIds } }, { $set: { processed: true } }, { upsert: false }).lean();
768
+ await this.tables?.commitment?.updateMany(
769
+ { id: { $in: distinctCommitmentIds } },
770
+ { $set: { processed: true } },
771
+ { upsert: false }
772
+ ).lean();
679
773
  } catch (err) {
680
- throw new common.ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", { context: { error: err, commitmentIds } });
774
+ throw new common.ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", {
775
+ context: { error: err, commitmentIds }
776
+ });
681
777
  }
682
778
  }
683
779
  /**
@@ -687,16 +783,25 @@ class ProsopoDatabase extends common.AsyncFactory {
687
783
  async flagBatchedDappUserCommitments(commitmentIds) {
688
784
  try {
689
785
  const distinctCommitmentIds = [...new Set(commitmentIds)];
690
- await this.tables?.commitment?.updateMany({ id: { $in: distinctCommitmentIds } }, { $set: { batched: true } }, { upsert: false }).lean();
786
+ await this.tables?.commitment?.updateMany(
787
+ { id: { $in: distinctCommitmentIds } },
788
+ { $set: { batched: true } },
789
+ { upsert: false }
790
+ ).lean();
691
791
  } catch (err) {
692
- throw new common.ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", { context: { error: err, commitmentIds } });
792
+ throw new common.ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", {
793
+ context: { error: err, commitmentIds }
794
+ });
693
795
  }
694
796
  }
695
797
  /**
696
798
  * @description Get the last batch commit time or return 0 if none
697
799
  */
698
800
  async getLastBatchCommitTime() {
699
- const cursor = this.tables?.scheduler?.findOne({ processName: types.ScheduledTaskNames.BatchCommitment, status: types.ScheduledTaskStatus.Completed }).sort({ timestamp: -1 });
801
+ const cursor = this.tables?.scheduler?.findOne({
802
+ processName: types.ScheduledTaskNames.BatchCommitment,
803
+ status: types.ScheduledTaskStatus.Completed
804
+ }).sort({ timestamp: -1 });
700
805
  const doc = await cursor?.lean();
701
806
  if (doc) {
702
807
  return doc.datetime;
@@ -716,7 +821,7 @@ class ProsopoDatabase extends common.AsyncFactory {
716
821
  async getLastScheduledTaskStatus(task, status) {
717
822
  const lookup = { processName: task };
718
823
  if (status) {
719
- lookup["status"] = status;
824
+ lookup.status = status;
720
825
  }
721
826
  const cursor = await this.tables?.scheduler?.findOne(lookup).sort({ datetime: -1 }).lean();
722
827
  return cursor ? cursor : void 0;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const mongo = require("./mongo.cjs");
4
3
  const mongodbMemoryServer = require("mongodb-memory-server");
4
+ const mongo = require("./mongo.cjs");
5
5
  class MongoMemoryDatabase extends mongo.ProsopoDatabase {
6
6
  constructor() {
7
7
  super(...arguments);
@@ -4,7 +4,7 @@ const index = require("./databases/index.cjs");
4
4
  require("./eventsDatabase/index.cjs");
5
5
  require("./captchaDatabase/index.cjs");
6
6
  const eventsDatabase = require("./eventsDatabase/eventsDatabase.cjs");
7
- const captchaDatabse = require("./captchaDatabase/captchaDatabse.cjs");
7
+ const captchaDatabase = require("./captchaDatabase/captchaDatabase.cjs");
8
8
  exports.Databases = index.Databases;
9
9
  exports.saveCaptchaEvent = eventsDatabase.saveCaptchaEvent;
10
- exports.saveCaptchas = captchaDatabse.saveCaptchas;
10
+ exports.saveCaptchas = captchaDatabase.saveCaptchas;
@@ -1,5 +1,5 @@
1
- import { ProsopoDatabase as MongoDatabase } from './mongo.js';
2
- import { MongoMemoryDatabase } from './mongoMemory.js';
1
+ import { ProsopoDatabase as MongoDatabase } from "./mongo.js";
2
+ import { MongoMemoryDatabase } from "./mongoMemory.js";
3
3
  export declare const Databases: {
4
4
  mongo: typeof MongoDatabase;
5
5
  mongoMemory: typeof MongoMemoryDatabase;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/databases/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,IAAI,aAAa,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,eAAO,MAAM,SAAS;;;CAGrB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/databases/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,IAAI,aAAa,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,eAAO,MAAM,SAAS;;;CAGrB,CAAC"}
@@ -1,6 +1,6 @@
1
- import { DatabaseTypes } from '@prosopo/types';
2
- import { ProsopoDatabase as MongoDatabase } from './mongo.js';
3
- import { MongoMemoryDatabase } from './mongoMemory.js';
1
+ import { DatabaseTypes } from "@prosopo/types";
2
+ import { ProsopoDatabase as MongoDatabase } from "./mongo.js";
3
+ import { MongoMemoryDatabase } from "./mongoMemory.js";
4
4
  export const Databases = {
5
5
  [DatabaseTypes.Values.mongo]: MongoDatabase,
6
6
  [DatabaseTypes.Values.mongoMemory]: MongoMemoryDatabase,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/databases/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,eAAe,IAAI,aAAa,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,MAAM,CAAC,MAAM,SAAS,GAAG;IACrB,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa;IAC3C,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,mBAAmB;CAC1D,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/databases/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,eAAe,IAAI,aAAa,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,MAAM,CAAC,MAAM,SAAS,GAAG;IACxB,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa;IAC3C,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,mBAAmB;CACvD,CAAC"}