@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
@@ -1,17 +1,16 @@
1
- import { AsyncFactory, ProsopoDBError, ProsopoEnvError, getLoggerDefault } from '@prosopo/common';
2
- import { CaptchaStates, DatasetWithIdsAndTreeSchema, ScheduledTaskNames, ScheduledTaskStatus, } from '@prosopo/types';
3
- import { CaptchaRecordSchema, DatasetRecordSchema, PendingRecordSchema, PowCaptchaRecordSchema, ScheduledTaskRecordSchema, ScheduledTaskSchema, SolutionRecordSchema, UserCommitmentRecordSchema, UserCommitmentSchema, UserSolutionRecordSchema, UserSolutionSchema, } from '@prosopo/types-database';
4
- import { CaptchaStatus } from '@prosopo/captcha-contract/types-returns';
5
- import { ServerApiVersion } from 'mongodb';
6
- import { isHex } from '@polkadot/util/is';
7
- import mongoose from 'mongoose';
8
- mongoose.set('strictQuery', false);
9
- const DEFAULT_ENDPOINT = 'mongodb://127.0.0.1:27017';
1
+ import { isHex } from "@polkadot/util/is";
2
+ import { AsyncFactory, ProsopoDBError, ProsopoEnvError, getLoggerDefault, } from "@prosopo/common";
3
+ import { CaptchaStates, CaptchaStatus, DatasetWithIdsAndTreeSchema, ScheduledTaskNames, ScheduledTaskStatus, } from "@prosopo/types";
4
+ import { CaptchaRecordSchema, DatasetRecordSchema, PendingRecordSchema, PowCaptchaRecordSchema, ScheduledTaskRecordSchema, ScheduledTaskSchema, SolutionRecordSchema, UserCommitmentRecordSchema, UserCommitmentSchema, UserSolutionRecordSchema, UserSolutionSchema, } from "@prosopo/types-database";
5
+ import { ServerApiVersion } from "mongodb";
6
+ import mongoose from "mongoose";
7
+ mongoose.set("strictQuery", false);
8
+ const DEFAULT_ENDPOINT = "mongodb://127.0.0.1:27017";
10
9
  export class ProsopoDatabase extends AsyncFactory {
11
10
  constructor() {
12
11
  super();
13
- this.url = '';
14
- this.dbname = '';
12
+ this.url = "";
13
+ this.dbname = "";
15
14
  this.logger = getLoggerDefault();
16
15
  }
17
16
  async init(url, dbname, logger, authSource) {
@@ -19,7 +18,7 @@ export class ProsopoDatabase extends AsyncFactory {
19
18
  const parsedUrl = new URL(baseEndpoint);
20
19
  parsedUrl.pathname = dbname;
21
20
  if (authSource) {
22
- parsedUrl.searchParams.set('authSource', authSource);
21
+ parsedUrl.searchParams.set("authSource", authSource);
23
22
  }
24
23
  this.url = parsedUrl.toString();
25
24
  this.dbname = dbname;
@@ -28,7 +27,7 @@ export class ProsopoDatabase extends AsyncFactory {
28
27
  }
29
28
  getTables() {
30
29
  if (!this.tables) {
31
- throw new ProsopoDBError('DATABASE.TABLES_UNDEFINED', {
30
+ throw new ProsopoDBError("DATABASE.TABLES_UNDEFINED", {
32
31
  context: { failedFuncName: this.getTables.name },
33
32
  logger: this.logger,
34
33
  });
@@ -37,7 +36,7 @@ export class ProsopoDatabase extends AsyncFactory {
37
36
  }
38
37
  getConnection() {
39
38
  if (!this.connection) {
40
- throw new ProsopoDBError('DATABASE.CONNECTION_UNDEFINED', {
39
+ throw new ProsopoDBError("DATABASE.CONNECTION_UNDEFINED", {
41
40
  context: { failedFuncName: this.getConnection.name },
42
41
  logger: this.logger,
43
42
  });
@@ -45,48 +44,51 @@ export class ProsopoDatabase extends AsyncFactory {
45
44
  return this.connection;
46
45
  }
47
46
  async connect() {
48
- this.logger.info(`Mongo url: ${this.url.replace(/\w+:\w+/, '<Credentials>')}`);
47
+ this.logger.info(`Mongo url: ${this.url.replace(/\w+:\w+/, "<Credentials>")}`);
49
48
  this.connection = await new Promise((resolve, reject) => {
50
49
  const connection = mongoose.createConnection(this.url, {
51
50
  dbName: this.dbname,
52
51
  serverApi: ServerApiVersion.v1,
53
52
  });
54
- connection.on('open', () => {
53
+ connection.on("open", () => {
55
54
  this.logger.info(`Database connection to ${this.url} opened`);
56
55
  resolve(connection);
57
56
  });
58
- connection.on('error', (err) => {
57
+ connection.on("error", (err) => {
59
58
  this.logger.error(`Database error: ${err}`);
60
59
  reject(err);
61
60
  });
62
- connection.on('connected', () => {
61
+ connection.on("connected", () => {
63
62
  this.logger.info(`Database connected to ${this.url}`);
63
+ resolve(connection);
64
64
  });
65
- connection.on('disconnected', () => {
65
+ connection.on("disconnected", () => {
66
66
  this.logger.info(`Database disconnected from ${this.url}`);
67
67
  });
68
- connection.on('reconnected', () => {
68
+ connection.on("reconnected", () => {
69
69
  this.logger.info(`Database reconnected to ${this.url}`);
70
+ resolve(connection);
70
71
  });
71
- connection.on('reconnectFailed', () => {
72
+ connection.on("reconnectFailed", () => {
72
73
  this.logger.error(`Database reconnect failed to ${this.url}`);
73
74
  });
74
- connection.on('close', () => {
75
+ connection.on("close", () => {
75
76
  this.logger.info(`Database connection to ${this.url} closed`);
76
77
  });
77
- connection.on('fullsetup', () => {
78
+ connection.on("fullsetup", () => {
78
79
  this.logger.info(`Database connection to ${this.url} is fully setup`);
80
+ resolve(connection);
79
81
  });
80
82
  });
81
83
  this.tables = {
82
- captcha: this.connection.model('Captcha', CaptchaRecordSchema),
83
- powCaptcha: this.connection.model('PowCaptcha', PowCaptchaRecordSchema),
84
- dataset: this.connection.model('Dataset', DatasetRecordSchema),
85
- solution: this.connection.model('Solution', SolutionRecordSchema),
86
- commitment: this.connection.model('UserCommitment', UserCommitmentRecordSchema),
87
- usersolution: this.connection.model('UserSolution', UserSolutionRecordSchema),
88
- pending: this.connection.model('Pending', PendingRecordSchema),
89
- scheduler: this.connection.model('Scheduler', ScheduledTaskRecordSchema),
84
+ captcha: this.connection.model("Captcha", CaptchaRecordSchema),
85
+ powCaptcha: this.connection.model("PowCaptcha", PowCaptchaRecordSchema),
86
+ dataset: this.connection.model("Dataset", DatasetRecordSchema),
87
+ solution: this.connection.model("Solution", SolutionRecordSchema),
88
+ commitment: this.connection.model("UserCommitment", UserCommitmentRecordSchema),
89
+ usersolution: this.connection.model("UserSolution", UserSolutionRecordSchema),
90
+ pending: this.connection.model("Pending", PendingRecordSchema),
91
+ scheduler: this.connection.model("Scheduler", ScheduledTaskRecordSchema),
90
92
  };
91
93
  }
92
94
  async close() {
@@ -95,7 +97,7 @@ export class ProsopoDatabase extends AsyncFactory {
95
97
  }
96
98
  async storeDataset(dataset) {
97
99
  try {
98
- this.logger.debug(`Storing dataset in database`);
100
+ this.logger.debug("Storing dataset in database");
99
101
  const parsedDataset = DatasetWithIdsAndTreeSchema.parse(dataset);
100
102
  const datasetDoc = {
101
103
  datasetId: parsedDataset.datasetId,
@@ -112,7 +114,7 @@ export class ProsopoDatabase extends AsyncFactory {
112
114
  index,
113
115
  solved: !!solution?.length,
114
116
  }));
115
- this.logger.debug(`Inserting captcha records`);
117
+ this.logger.debug("Inserting captcha records");
116
118
  if (captchaDocs.length) {
117
119
  await this.tables?.captcha.bulkWrite(captchaDocs.map((captchaDoc) => ({
118
120
  updateOne: {
@@ -132,7 +134,7 @@ export class ProsopoDatabase extends AsyncFactory {
132
134
  datasetId: parsedDataset.datasetId,
133
135
  datasetContentId: parsedDataset.datasetContentId,
134
136
  }));
135
- this.logger.debug(`Inserting solution records`);
137
+ this.logger.debug("Inserting solution records");
136
138
  if (captchaSolutionDocs.length) {
137
139
  await this.tables?.solution.bulkWrite(captchaSolutionDocs.map((captchaSolutionDoc) => ({
138
140
  updateOne: {
@@ -142,23 +144,23 @@ export class ProsopoDatabase extends AsyncFactory {
142
144
  },
143
145
  })));
144
146
  }
145
- this.logger.debug(`Dataset stored in database`);
147
+ this.logger.debug("Dataset stored in database");
146
148
  }
147
149
  catch (err) {
148
- throw new ProsopoDBError('DATABASE.DATASET_LOAD_FAILED', {
150
+ throw new ProsopoDBError("DATABASE.DATASET_LOAD_FAILED", {
149
151
  context: { failedFuncName: this.storeDataset.name, error: err },
150
152
  logger: this.logger,
151
153
  });
152
154
  }
153
155
  }
154
156
  async getSolutions(datasetId) {
155
- const docs = await this.tables?.solution.find({ datasetId }).lean();
157
+ const docs = await this.tables?.solution
158
+ .find({ datasetId })
159
+ .lean();
156
160
  return docs ? docs : [];
157
161
  }
158
162
  async getDataset(datasetId) {
159
- const datasetDoc = await this.tables?.dataset
160
- .findOne({ datasetId: datasetId })
161
- .lean();
163
+ const datasetDoc = await this.tables?.dataset.findOne({ datasetId: datasetId }).lean();
162
164
  if (datasetDoc) {
163
165
  const { datasetContentId, format, contentTree, solutionTree } = datasetDoc;
164
166
  const captchas = (await this.tables?.captcha.find({ datasetId }).lean()) || [];
@@ -188,13 +190,13 @@ export class ProsopoDatabase extends AsyncFactory {
188
190
  }),
189
191
  };
190
192
  }
191
- throw new ProsopoDBError('DATABASE.DATASET_GET_FAILED', {
193
+ throw new ProsopoDBError("DATABASE.DATASET_GET_FAILED", {
192
194
  context: { failedFuncName: this.getDataset.name, datasetId },
193
195
  });
194
196
  }
195
197
  async getRandomCaptcha(solved, datasetId, size) {
196
198
  if (!isHex(datasetId)) {
197
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
199
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
198
200
  context: { failedFuncName: this.getRandomCaptcha.name, datasetId },
199
201
  });
200
202
  }
@@ -214,26 +216,33 @@ export class ProsopoDatabase extends AsyncFactory {
214
216
  },
215
217
  ]);
216
218
  const docs = await cursor;
217
- if (docs && docs.length) {
219
+ if (docs?.length) {
218
220
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
219
221
  }
220
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
221
- context: { failedFuncName: this.getRandomCaptcha.name, solved, datasetId, size },
222
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
223
+ context: {
224
+ failedFuncName: this.getRandomCaptcha.name,
225
+ solved,
226
+ datasetId,
227
+ size,
228
+ },
222
229
  });
223
230
  }
224
231
  async getCaptchaById(captchaId) {
225
- const cursor = this.tables?.captcha.find({ captchaId: { $in: captchaId } }).lean();
232
+ const cursor = this.tables?.captcha
233
+ .find({ captchaId: { $in: captchaId } })
234
+ .lean();
226
235
  const docs = await cursor;
227
- if (docs && docs.length) {
236
+ if (docs?.length) {
228
237
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
229
238
  }
230
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
239
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
231
240
  context: { failedFuncName: this.getCaptchaById.name, captchaId },
232
241
  });
233
242
  }
234
243
  async updateCaptcha(captcha, datasetId) {
235
244
  if (!isHex(datasetId)) {
236
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
245
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
237
246
  context: { failedFuncName: this.updateCaptcha.name, datasetId },
238
247
  });
239
248
  }
@@ -241,7 +250,7 @@ export class ProsopoDatabase extends AsyncFactory {
241
250
  await this.tables?.captcha.updateOne({ datasetId }, { $set: captcha }, { upsert: false });
242
251
  }
243
252
  catch (err) {
244
- throw new ProsopoDBError('DATABASE.CAPTCHA_UPDATE_FAILED', {
253
+ throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
245
254
  context: { failedFuncName: this.getDatasetDetails.name, error: err },
246
255
  });
247
256
  }
@@ -251,16 +260,21 @@ export class ProsopoDatabase extends AsyncFactory {
251
260
  }
252
261
  async getDatasetDetails(datasetId) {
253
262
  if (!isHex(datasetId)) {
254
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
263
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
255
264
  context: { failedFuncName: this.getDatasetDetails.name, datasetId },
256
265
  });
257
266
  }
258
- const doc = await this.tables?.dataset.findOne({ datasetId }).lean();
267
+ const doc = await this.tables?.dataset
268
+ .findOne({ datasetId })
269
+ .lean();
259
270
  if (doc) {
260
271
  return doc;
261
272
  }
262
- throw new ProsopoDBError('DATABASE.DATASET_GET_FAILED', {
263
- context: { failedFuncName: this.getDatasetDetails.name, datasetId },
273
+ throw new ProsopoDBError("DATABASE.DATASET_GET_FAILED", {
274
+ context: {
275
+ failedFuncName: this.getDatasetDetails.name,
276
+ datasetId,
277
+ },
264
278
  });
265
279
  }
266
280
  async storeDappUserSolution(captchas, commit) {
@@ -288,24 +302,27 @@ export class ProsopoDatabase extends AsyncFactory {
288
302
  await this.tables?.usersolution.bulkWrite(ops);
289
303
  }
290
304
  }
291
- async storePowCaptchaRecord(challenge, checked) {
292
- if (!this.tables) {
293
- throw new ProsopoEnvError('DATABASE.DATABASE_UNDEFINED', {
294
- context: { failedFuncName: this.storePowCaptchaRecord.name },
295
- logger: this.logger,
296
- });
297
- }
305
+ async storePowCaptchaRecord(challenge, components, checked) {
306
+ const tables = this.getTables();
298
307
  const powCaptchaRecord = {
299
308
  challenge,
309
+ ...components,
300
310
  checked,
301
311
  };
302
312
  try {
303
- await this.tables.powCaptcha.create(powCaptchaRecord);
304
- this.logger.info('PowCaptcha record added successfully', { challenge, checked });
313
+ await tables.powCaptcha.create(powCaptchaRecord);
314
+ this.logger.info("PowCaptcha record added successfully", {
315
+ challenge,
316
+ checked,
317
+ });
305
318
  }
306
319
  catch (error) {
307
- this.logger.error('Failed to add PowCaptcha record', { error, challenge, checked });
308
- throw new ProsopoDBError('DATABASE.CAPTCHA_UPDATE_FAILED', {
320
+ this.logger.error("Failed to add PowCaptcha record", {
321
+ error,
322
+ challenge,
323
+ checked,
324
+ });
325
+ throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
309
326
  context: { error, challenge, checked },
310
327
  logger: this.logger,
311
328
  });
@@ -313,60 +330,70 @@ export class ProsopoDatabase extends AsyncFactory {
313
330
  }
314
331
  async getPowCaptchaRecordByChallenge(challenge) {
315
332
  if (!this.tables) {
316
- throw new ProsopoEnvError('DATABASE.DATABASE_UNDEFINED', {
333
+ throw new ProsopoEnvError("DATABASE.DATABASE_UNDEFINED", {
317
334
  context: { failedFuncName: this.getPowCaptchaRecordByChallenge.name },
318
335
  logger: this.logger,
319
336
  });
320
337
  }
321
338
  try {
322
- const record = await this.tables.powCaptcha.findOne({ challenge }).lean();
339
+ const record = await this.tables.powCaptcha
340
+ .findOne({ challenge })
341
+ .lean();
323
342
  if (record) {
324
- this.logger.info('PowCaptcha record retrieved successfully', { challenge });
343
+ this.logger.info("PowCaptcha record retrieved successfully", {
344
+ challenge,
345
+ });
325
346
  return record;
326
347
  }
327
- else {
328
- this.logger.info('No PowCaptcha record found', { challenge });
329
- return null;
330
- }
348
+ this.logger.info("No PowCaptcha record found", { challenge });
349
+ return null;
331
350
  }
332
351
  catch (error) {
333
- this.logger.error('Failed to retrieve PowCaptcha record', { error, challenge });
334
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
352
+ this.logger.error("Failed to retrieve PowCaptcha record", {
353
+ error,
354
+ challenge,
355
+ });
356
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
335
357
  context: { error, challenge },
336
358
  logger: this.logger,
337
359
  });
338
360
  }
339
361
  }
340
362
  async updatePowCaptchaRecord(challenge, checked) {
341
- if (!this.tables) {
342
- throw new ProsopoEnvError('DATABASE.DATABASE_UNDEFINED', {
343
- context: { failedFuncName: this.updatePowCaptchaRecord.name },
344
- logger: this.logger,
345
- });
346
- }
363
+ const tables = this.getTables();
347
364
  try {
348
- const updateResult = await this.tables.powCaptcha.updateOne({ challenge }, { $set: { checked } });
365
+ const updateResult = await tables.powCaptcha.updateOne({ challenge }, { $set: { checked } });
349
366
  if (updateResult.matchedCount === 0) {
350
- this.logger.info('No PowCaptcha record found to update', { challenge, checked });
351
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
367
+ this.logger.info("No PowCaptcha record found to update", {
368
+ challenge,
369
+ checked,
370
+ });
371
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
352
372
  context: { challenge, checked },
353
373
  logger: this.logger,
354
374
  });
355
375
  }
356
- else {
357
- this.logger.info('PowCaptcha record updated successfully', { challenge, checked });
358
- }
376
+ this.logger.info("PowCaptcha record updated successfully", {
377
+ challenge,
378
+ checked,
379
+ });
359
380
  }
360
381
  catch (error) {
361
- this.logger.error('Failed to update PowCaptcha record', { error, challenge, checked });
362
- throw new ProsopoDBError('DATABASE.CAPTCHA_UPDATE_FAILED', {
382
+ this.logger.error("Failed to update PowCaptcha record", {
383
+ error,
384
+ challenge,
385
+ checked,
386
+ });
387
+ throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
363
388
  context: { error, challenge, checked },
364
389
  logger: this.logger,
365
390
  });
366
391
  }
367
392
  }
368
393
  async getProcessedDappUserSolutions() {
369
- const docs = await this.tables?.usersolution.find({ processed: true }).lean();
394
+ const docs = await this.tables?.usersolution
395
+ .find({ processed: true })
396
+ .lean();
370
397
  return docs ? docs.map((doc) => UserSolutionSchema.parse(doc)) : [];
371
398
  }
372
399
  async getProcessedDappUserCommitments() {
@@ -388,20 +415,40 @@ export class ProsopoDatabase extends AsyncFactory {
388
415
  async markDappUserCommitmentsStored(commitmentIds) {
389
416
  await this.tables?.commitment.updateMany({ id: { $in: commitmentIds } }, { $set: { stored: true } }, { upsert: false });
390
417
  }
418
+ async getUnstoredDappUserPoWCommitments() {
419
+ const docs = await this.tables?.powCaptcha
420
+ .find({
421
+ $or: [{ stored: false }, { stored: { $exists: false } }],
422
+ })
423
+ .lean();
424
+ return docs || [];
425
+ }
426
+ async markDappUserPoWCommitmentsStored(challengeIds) {
427
+ await this.tables?.powCaptcha.updateMany({ challenge: { $in: challengeIds } }, { $set: { stored: true } }, { upsert: false });
428
+ }
391
429
  async getBatchedDappUserCommitments() {
392
430
  const docs = await this.tables?.commitment.find({ batched: true }).lean();
393
431
  return docs ? docs.map((doc) => UserCommitmentSchema.parse(doc)) : [];
394
432
  }
395
433
  async removeProcessedDappUserSolutions(commitmentIds) {
396
- return await this.tables?.usersolution.deleteMany({ processed: true, commitmentId: { $in: commitmentIds } });
434
+ return await this.tables?.usersolution.deleteMany({
435
+ processed: true,
436
+ commitmentId: { $in: commitmentIds },
437
+ });
397
438
  }
398
439
  async removeProcessedDappUserCommitments(commitmentIds) {
399
- return await this.tables?.commitment.deleteMany({ processed: true, id: { $in: commitmentIds } });
440
+ return await this.tables?.commitment.deleteMany({
441
+ processed: true,
442
+ id: { $in: commitmentIds },
443
+ });
400
444
  }
401
445
  async storeDappUserPending(userAccount, requestHash, salt, deadlineTimestamp, requestedAtBlock) {
402
446
  if (!isHex(requestHash)) {
403
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
404
- context: { failedFuncName: this.storeDappUserPending.name, requestHash },
447
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
448
+ context: {
449
+ failedFuncName: this.storeDappUserPending.name,
450
+ requestHash,
451
+ },
405
452
  });
406
453
  }
407
454
  const pendingRecord = {
@@ -416,24 +463,25 @@ export class ProsopoDatabase extends AsyncFactory {
416
463
  }
417
464
  async getDappUserPending(requestHash) {
418
465
  if (!isHex(requestHash)) {
419
- throw new ProsopoEnvError('DATABASE.INVALID_HASH', {
466
+ throw new ProsopoEnvError("DATABASE.INVALID_HASH", {
420
467
  context: { failedFuncName: this.getDappUserPending.name, requestHash },
421
468
  });
422
469
  }
423
- const doc = await this.tables?.pending
424
- .findOne({ requestHash: requestHash })
425
- .lean();
470
+ const doc = await this.tables?.pending.findOne({ requestHash: requestHash }).lean();
426
471
  if (doc) {
427
472
  return doc;
428
473
  }
429
- throw new ProsopoEnvError('DATABASE.PENDING_RECORD_NOT_FOUND', {
474
+ throw new ProsopoEnvError("DATABASE.PENDING_RECORD_NOT_FOUND", {
430
475
  context: { failedFuncName: this.getDappUserPending.name, requestHash },
431
476
  });
432
477
  }
433
478
  async updateDappUserPendingStatus(requestHash) {
434
479
  if (!isHex(requestHash)) {
435
- throw new ProsopoEnvError('DATABASE.INVALID_HASH', {
436
- context: { failedFuncName: this.updateDappUserPendingStatus.name, requestHash },
480
+ throw new ProsopoEnvError("DATABASE.INVALID_HASH", {
481
+ context: {
482
+ failedFuncName: this.updateDappUserPendingStatus.name,
483
+ requestHash,
484
+ },
437
485
  });
438
486
  }
439
487
  await this.tables?.pending.updateOne({ requestHash: requestHash }, {
@@ -453,15 +501,17 @@ export class ProsopoDatabase extends AsyncFactory {
453
501
  if (docs) {
454
502
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
455
503
  }
456
- throw new ProsopoEnvError('DATABASE.CAPTCHA_GET_FAILED');
504
+ throw new ProsopoEnvError("DATABASE.CAPTCHA_GET_FAILED");
457
505
  }
458
506
  async getAllDappUserSolutions(captchaId) {
459
- const cursor = this.tables?.usersolution?.find({ captchaId: { $in: captchaId } }).lean();
507
+ const cursor = this.tables?.usersolution
508
+ ?.find({ captchaId: { $in: captchaId } })
509
+ .lean();
460
510
  const docs = await cursor;
461
511
  if (docs) {
462
512
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
463
513
  }
464
- throw new ProsopoEnvError('DATABASE.SOLUTION_GET_FAILED');
514
+ throw new ProsopoEnvError("DATABASE.SOLUTION_GET_FAILED");
465
515
  }
466
516
  async getDatasetIdWithSolvedCaptchasOfSizeN(solvedCaptchaCount) {
467
517
  const cursor = this.tables?.solution.aggregate([
@@ -470,7 +520,7 @@ export class ProsopoDatabase extends AsyncFactory {
470
520
  },
471
521
  {
472
522
  $group: {
473
- _id: '$datasetId',
523
+ _id: "$datasetId",
474
524
  count: { $sum: 1 },
475
525
  },
476
526
  },
@@ -484,15 +534,18 @@ export class ProsopoDatabase extends AsyncFactory {
484
534
  },
485
535
  ]);
486
536
  const docs = await cursor;
487
- if (docs && docs.length) {
537
+ if (docs?.length) {
488
538
  return docs[0]._id;
489
539
  }
490
- throw new ProsopoDBError('DATABASE.DATASET_WITH_SOLUTIONS_GET_FAILED');
540
+ throw new ProsopoDBError("DATABASE.DATASET_WITH_SOLUTIONS_GET_FAILED");
491
541
  }
492
542
  async getRandomSolvedCaptchasFromSingleDataset(datasetId, size) {
493
543
  if (!isHex(datasetId)) {
494
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
495
- context: { failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name, datasetId },
544
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
545
+ context: {
546
+ failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
547
+ datasetId,
548
+ },
496
549
  });
497
550
  }
498
551
  const sampleSize = size ? Math.abs(Math.trunc(size)) : 1;
@@ -508,11 +561,15 @@ export class ProsopoDatabase extends AsyncFactory {
508
561
  },
509
562
  ]);
510
563
  const docs = await cursor;
511
- if (docs && docs.length) {
564
+ if (docs?.length) {
512
565
  return docs;
513
566
  }
514
- throw new ProsopoDBError('DATABASE.SOLUTION_GET_FAILED', {
515
- context: { failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name, datasetId, size },
567
+ throw new ProsopoDBError("DATABASE.SOLUTION_GET_FAILED", {
568
+ context: {
569
+ failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
570
+ datasetId,
571
+ size,
572
+ },
516
573
  });
517
574
  }
518
575
  async getDappUserSolutionById(commitmentId) {
@@ -525,12 +582,14 @@ export class ProsopoDatabase extends AsyncFactory {
525
582
  if (doc) {
526
583
  return doc;
527
584
  }
528
- throw new ProsopoDBError('DATABASE.SOLUTION_GET_FAILED', {
585
+ throw new ProsopoDBError("DATABASE.SOLUTION_GET_FAILED", {
529
586
  context: { failedFuncName: this.getCaptchaById.name, commitmentId },
530
587
  });
531
588
  }
532
589
  async getDappUserCommitmentById(commitmentId) {
533
- const commitmentCursor = this.tables?.commitment?.findOne({ id: commitmentId }).lean();
590
+ const commitmentCursor = this.tables?.commitment
591
+ ?.findOne({ id: commitmentId })
592
+ .lean();
534
593
  const doc = await commitmentCursor;
535
594
  return doc ? UserCommitmentSchema.parse(doc) : undefined;
536
595
  }
@@ -547,7 +606,9 @@ export class ProsopoDatabase extends AsyncFactory {
547
606
  .lean();
548
607
  }
549
608
  catch (err) {
550
- throw new ProsopoDBError('DATABASE.SOLUTION_APPROVE_FAILED', { context: { error: err, commitmentId } });
609
+ throw new ProsopoDBError("DATABASE.SOLUTION_APPROVE_FAILED", {
610
+ context: { error: err, commitmentId },
611
+ });
551
612
  }
552
613
  }
553
614
  async flagProcessedDappUserSolutions(captchaIds) {
@@ -557,7 +618,9 @@ export class ProsopoDatabase extends AsyncFactory {
557
618
  .lean();
558
619
  }
559
620
  catch (err) {
560
- throw new ProsopoDBError('DATABASE.SOLUTION_FLAG_FAILED', { context: { error: err, captchaIds } });
621
+ throw new ProsopoDBError("DATABASE.SOLUTION_FLAG_FAILED", {
622
+ context: { error: err, captchaIds },
623
+ });
561
624
  }
562
625
  }
563
626
  async flagProcessedDappUserCommitments(commitmentIds) {
@@ -568,7 +631,9 @@ export class ProsopoDatabase extends AsyncFactory {
568
631
  .lean();
569
632
  }
570
633
  catch (err) {
571
- throw new ProsopoDBError('DATABASE.COMMITMENT_FLAG_FAILED', { context: { error: err, commitmentIds } });
634
+ throw new ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", {
635
+ context: { error: err, commitmentIds },
636
+ });
572
637
  }
573
638
  }
574
639
  async flagBatchedDappUserCommitments(commitmentIds) {
@@ -579,12 +644,17 @@ export class ProsopoDatabase extends AsyncFactory {
579
644
  .lean();
580
645
  }
581
646
  catch (err) {
582
- throw new ProsopoDBError('DATABASE.COMMITMENT_FLAG_FAILED', { context: { error: err, commitmentIds } });
647
+ throw new ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", {
648
+ context: { error: err, commitmentIds },
649
+ });
583
650
  }
584
651
  }
585
652
  async getLastBatchCommitTime() {
586
653
  const cursor = this.tables?.scheduler
587
- ?.findOne({ processName: ScheduledTaskNames.BatchCommitment, status: ScheduledTaskStatus.Completed })
654
+ ?.findOne({
655
+ processName: ScheduledTaskNames.BatchCommitment,
656
+ status: ScheduledTaskStatus.Completed,
657
+ })
588
658
  .sort({ timestamp: -1 });
589
659
  const doc = await cursor?.lean();
590
660
  if (doc) {
@@ -601,7 +671,7 @@ export class ProsopoDatabase extends AsyncFactory {
601
671
  async getLastScheduledTaskStatus(task, status) {
602
672
  const lookup = { processName: task };
603
673
  if (status) {
604
- lookup['status'] = status;
674
+ lookup.status = status;
605
675
  }
606
676
  const cursor = await this.tables?.scheduler
607
677
  ?.findOne(lookup)