@prosopo/datasets 3.0.9 → 3.0.11

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 (49) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/captcha/captcha.js +173 -154
  3. package/dist/captcha/dataset.js +83 -69
  4. package/dist/captcha/index.js +27 -5
  5. package/dist/captcha/merkle.js +112 -109
  6. package/dist/captcha/util.js +19 -18
  7. package/dist/index.js +31 -3
  8. package/dist/tests/mocks/data/captchas.js +1039 -1033
  9. package/dist/tests/mocks/data/captchas.json +886 -886
  10. package/dist/tests/mocks/data/captchas1.json +132 -132
  11. package/dist/tests/mocks/data/captchas2.json +175 -175
  12. package/dist/tests/mocks/data/captchas3.json +133 -133
  13. package/dist/tests/mocks/data/captchas4.json +132 -132
  14. package/package.json +15 -12
  15. package/vite.cjs.config.ts +4 -1
  16. package/vite.esm.config.ts +20 -0
  17. package/dist/captcha/captcha.d.ts +0 -21
  18. package/dist/captcha/captcha.d.ts.map +0 -1
  19. package/dist/captcha/captcha.js.map +0 -1
  20. package/dist/captcha/dataset.d.ts +0 -8
  21. package/dist/captcha/dataset.d.ts.map +0 -1
  22. package/dist/captcha/dataset.js.map +0 -1
  23. package/dist/captcha/index.d.ts +0 -5
  24. package/dist/captcha/index.d.ts.map +0 -1
  25. package/dist/captcha/index.js.map +0 -1
  26. package/dist/captcha/merkle.d.ts +0 -20
  27. package/dist/captcha/merkle.d.ts.map +0 -1
  28. package/dist/captcha/merkle.js.map +0 -1
  29. package/dist/captcha/util.d.ts +0 -2
  30. package/dist/captcha/util.d.ts.map +0 -1
  31. package/dist/captcha/util.js.map +0 -1
  32. package/dist/index.d.ts +0 -3
  33. package/dist/index.d.ts.map +0 -1
  34. package/dist/index.js.map +0 -1
  35. package/dist/tests/captcha.unit.test.d.ts +0 -2
  36. package/dist/tests/captcha.unit.test.d.ts.map +0 -1
  37. package/dist/tests/captcha.unit.test.js +0 -357
  38. package/dist/tests/captcha.unit.test.js.map +0 -1
  39. package/dist/tests/dataset.unit.test.d.ts +0 -2
  40. package/dist/tests/dataset.unit.test.d.ts.map +0 -1
  41. package/dist/tests/dataset.unit.test.js +0 -126
  42. package/dist/tests/dataset.unit.test.js.map +0 -1
  43. package/dist/tests/merkle.unit.test.d.ts +0 -2
  44. package/dist/tests/merkle.unit.test.d.ts.map +0 -1
  45. package/dist/tests/merkle.unit.test.js +0 -171
  46. package/dist/tests/merkle.unit.test.js.map +0 -1
  47. package/dist/tests/mocks/data/captchas.d.ts +0 -24
  48. package/dist/tests/mocks/data/captchas.d.ts.map +0 -1
  49. package/dist/tests/mocks/data/captchas.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @prosopo/datasets
2
2
 
3
+ ## 3.0.11
4
+ ### Patch Changes
5
+
6
+ - Updated dependencies [625fef8]
7
+ - @prosopo/types-database@3.0.11
8
+
9
+ ## 3.0.10
10
+ ### Patch Changes
11
+
12
+ - 3573f0b: fix npm scripts bundle command
13
+ - 3573f0b: build using vite, typecheck using tsc
14
+ - efd8102: Add tests for unwrap error helper
15
+ - 3573f0b: standardise all vite based npm scripts for bundling
16
+ - Updated dependencies [52dbf21]
17
+ - Updated dependencies [93d5e50]
18
+ - Updated dependencies [3573f0b]
19
+ - Updated dependencies [8a64429]
20
+ - Updated dependencies [3573f0b]
21
+ - Updated dependencies [efd8102]
22
+ - Updated dependencies [93d5e50]
23
+ - Updated dependencies [63519d7]
24
+ - Updated dependencies [f29fc7e]
25
+ - Updated dependencies [3573f0b]
26
+ - Updated dependencies [2d0dd8a]
27
+ - Updated dependencies [6d604ad]
28
+ - @prosopo/util@3.0.3
29
+ - @prosopo/util-crypto@13.5.2
30
+ - @prosopo/types@3.0.4
31
+ - @prosopo/types-database@3.0.10
32
+ - @prosopo/common@3.1.0
33
+ - @prosopo/config@3.1.1
34
+
3
35
  ## 3.0.9
4
36
  ### Patch Changes
5
37
 
@@ -1,175 +1,194 @@
1
1
  import { isHex } from "@polkadot/util";
2
- import { ProsopoDatasetError, ProsopoEnvError, hexHash, hexHashArray, } from "@prosopo/common";
3
- import { CaptchaSolutionArraySchema, DatasetWithNumericSolutionSchema, } from "@prosopo/types";
2
+ import { ProsopoDatasetError, ProsopoEnvError, hexHashArray, hexHash } from "@prosopo/common";
3
+ import { DatasetWithNumericSolutionSchema, CaptchaSolutionArraySchema } from "@prosopo/types";
4
4
  import { at } from "@prosopo/util";
5
5
  import { downloadImage } from "./util.js";
6
- export const NO_SOLUTION_VALUE = "NO_SOLUTION";
7
- export function parseCaptchaDataset(datasetJSON) {
8
- try {
9
- const result = DatasetWithNumericSolutionSchema.parse(datasetJSON);
10
- const result2 = {
11
- format: result.format,
12
- captchas: result.captchas.map((captcha) => {
13
- return {
14
- ...captcha,
15
- solution: captcha.solution
16
- ? matchItemsToSolutions(captcha.solution, captcha.items)
17
- : [],
18
- unlabelled: captcha.unlabelled
19
- ? matchItemsToSolutions(captcha.unlabelled, captcha.items)
20
- : [],
21
- };
22
- }),
23
- };
24
- if (result.datasetId !== undefined)
25
- result2.datasetId = result.datasetId;
26
- if (result.contentTree !== undefined)
27
- result2.contentTree = result.contentTree;
28
- if (result.datasetContentId !== undefined)
29
- result2.datasetContentId = result.datasetContentId;
30
- if (result.solutionTree !== undefined)
31
- result2.solutionTree = result.solutionTree;
32
- return result2;
33
- }
34
- catch (err) {
35
- throw new ProsopoDatasetError("DATASET.DATASET_PARSE_ERROR", {
36
- context: { error: err },
37
- });
38
- }
39
- }
40
- export function parseAndSortCaptchaSolutions(captchaJSON) {
41
- try {
42
- return CaptchaSolutionArraySchema.parse(captchaJSON).map((captcha) => ({
43
- ...captcha,
44
- solution: captcha.solution.sort(),
45
- }));
46
- }
47
- catch (err) {
48
- throw new ProsopoDatasetError("DATASET.SOLUTION_PARSE_ERROR", {
49
- context: { error: err },
50
- });
51
- }
52
- }
53
- export function captchaSort(a, b) {
54
- return a.captchaId.localeCompare(b.captchaId);
55
- }
56
- export function sortAndComputeHashes(received, stored) {
57
- received.sort(captchaSort);
58
- stored.sort(captchaSort);
59
- return stored.map(({ salt, items = [], target = "", captchaId, solved }, index) => {
60
- const item = at(received, index);
61
- if (captchaId !== item.captchaId) {
62
- throw new ProsopoEnvError("CAPTCHA.ID_MISMATCH");
63
- }
6
+ const NO_SOLUTION_VALUE = "NO_SOLUTION";
7
+ function parseCaptchaDataset(datasetJSON) {
8
+ try {
9
+ const result = DatasetWithNumericSolutionSchema.parse(datasetJSON);
10
+ const result2 = {
11
+ format: result.format,
12
+ captchas: result.captchas.map((captcha) => {
64
13
  return {
65
- hash: computeCaptchaHash({
66
- solution: solved ? item.solution : [],
67
- salt,
68
- items,
69
- target,
70
- }, true, true, false),
71
- captchaId,
14
+ ...captcha,
15
+ solution: captcha.solution ? matchItemsToSolutions(captcha.solution, captcha.items) : [],
16
+ unlabelled: captcha.unlabelled ? matchItemsToSolutions(captcha.unlabelled, captcha.items) : []
72
17
  };
18
+ })
19
+ };
20
+ if (result.datasetId !== void 0) result2.datasetId = result.datasetId;
21
+ if (result.contentTree !== void 0)
22
+ result2.contentTree = result.contentTree;
23
+ if (result.datasetContentId !== void 0)
24
+ result2.datasetContentId = result.datasetContentId;
25
+ if (result.solutionTree !== void 0)
26
+ result2.solutionTree = result.solutionTree;
27
+ return result2;
28
+ } catch (err) {
29
+ throw new ProsopoDatasetError("DATASET.DATASET_PARSE_ERROR", {
30
+ context: { error: err }
73
31
  });
32
+ }
74
33
  }
75
- export function compareCaptchaSolutions(received, solutions, totalImages, threshold) {
76
- received.sort(captchaSort);
77
- solutions.sort(captchaSort);
78
- if (received.length !== solutions.length) {
79
- return false;
80
- }
81
- if (received.length &&
82
- solutions.length &&
83
- received.length === solutions.length) {
84
- const captchaIdMismatch = received.some((captcha, index) => solutions[index] && captcha.captchaId !== solutions[index].captchaId);
85
- if (captchaIdMismatch) {
86
- return false;
87
- }
88
- }
89
- return received.every((captcha, index) => {
90
- const sortedReceivedSolution = captcha.solution.sort();
91
- const targetSolution = solutions[index]?.solution.sort();
92
- if (!targetSolution) {
93
- return false;
94
- }
95
- const incorrectCount = sortedReceivedSolution.filter((solution) => !targetSolution.includes(solution)).length;
96
- const missingCount = targetSolution.filter((solution) => !sortedReceivedSolution.includes(solution)).length;
97
- const totalIncorrect = incorrectCount + missingCount;
98
- const percentageCorrect = 1 - totalIncorrect / totalImages;
99
- return percentageCorrect >= threshold;
34
+ function parseAndSortCaptchaSolutions(captchaJSON) {
35
+ try {
36
+ return CaptchaSolutionArraySchema.parse(captchaJSON).map((captcha) => ({
37
+ ...captcha,
38
+ solution: captcha.solution.sort()
39
+ }));
40
+ } catch (err) {
41
+ throw new ProsopoDatasetError("DATASET.SOLUTION_PARSE_ERROR", {
42
+ context: { error: err }
100
43
  });
44
+ }
101
45
  }
102
- export function computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes) {
103
- try {
104
- const itemHashes = captcha.items.map((item, index) => {
105
- if (item.hash) {
106
- return item.hash;
107
- }
108
- throw new ProsopoDatasetError("CAPTCHA.MISSING_ITEM_HASH", {
109
- context: {
110
- computeCaptchaHashName: computeCaptchaHash.name,
111
- index,
112
- },
113
- });
114
- });
115
- return hexHashArray([
116
- captcha.target,
117
- ...(includeSolution ? getSolutionValueToHash(captcha.solution) : []),
118
- includeSalt ? captcha.salt : "",
119
- sortItemHashes ? itemHashes.sort() : itemHashes,
120
- ]);
121
- }
122
- catch (err) {
123
- throw new ProsopoDatasetError("DATASET.HASH_ERROR", {
124
- context: { error: err },
125
- });
126
- }
46
+ function captchaSort(a, b) {
47
+ return a.captchaId.localeCompare(b.captchaId);
127
48
  }
128
- export function getSolutionValueToHash(solution) {
129
- return solution !== undefined ? solution.sort() : [NO_SOLUTION_VALUE];
49
+ function sortAndComputeHashes(received, stored) {
50
+ received.sort(captchaSort);
51
+ stored.sort(captchaSort);
52
+ return stored.map(
53
+ ({ salt, items = [], target = "", captchaId, solved }, index) => {
54
+ const item = at(received, index);
55
+ if (captchaId !== item.captchaId) {
56
+ throw new ProsopoEnvError("CAPTCHA.ID_MISMATCH");
57
+ }
58
+ return {
59
+ hash: computeCaptchaHash(
60
+ {
61
+ solution: solved ? item.solution : [],
62
+ salt,
63
+ items,
64
+ target
65
+ },
66
+ true,
67
+ true,
68
+ false
69
+ ),
70
+ captchaId
71
+ };
72
+ }
73
+ );
130
74
  }
131
- export async function computeItemHash(item) {
132
- if (item.type === "text") {
133
- return { ...item, hash: hexHash(item.data) };
75
+ function compareCaptchaSolutions(received, solutions, totalImages, threshold) {
76
+ received.sort(captchaSort);
77
+ solutions.sort(captchaSort);
78
+ if (received.length !== solutions.length) {
79
+ return false;
80
+ }
81
+ if (received.length && solutions.length && received.length === solutions.length) {
82
+ const captchaIdMismatch = received.some(
83
+ (captcha, index) => solutions[index] && captcha.captchaId !== solutions[index].captchaId
84
+ );
85
+ if (captchaIdMismatch) {
86
+ return false;
134
87
  }
135
- if (item.type === "image") {
136
- return { ...item, hash: hexHash(await downloadImage(item.data)) };
88
+ }
89
+ return received.every((captcha, index) => {
90
+ const sortedReceivedSolution = captcha.solution.sort();
91
+ const targetSolution = solutions[index]?.solution.sort();
92
+ if (!targetSolution) {
93
+ return false;
137
94
  }
138
- throw new ProsopoDatasetError("CAPTCHA.INVALID_ITEM_FORMAT");
95
+ const incorrectCount = sortedReceivedSolution.filter(
96
+ (solution) => !targetSolution.includes(solution)
97
+ ).length;
98
+ const missingCount = targetSolution.filter(
99
+ (solution) => !sortedReceivedSolution.includes(solution)
100
+ ).length;
101
+ const totalIncorrect = incorrectCount + missingCount;
102
+ const percentageCorrect = 1 - totalIncorrect / totalImages;
103
+ return percentageCorrect >= threshold;
104
+ });
139
105
  }
140
- export function matchItemsToSolutions(solutions, items) {
141
- if (!items) {
142
- return [];
143
- }
144
- return solutions.map((solution) => {
145
- if (typeof solution === "string" && isHex(solution)) {
146
- if (!items?.some((item) => item.hash === solution)) {
147
- throw new ProsopoDatasetError("CAPTCHA.INVALID_ITEM_HASH");
148
- }
149
- return solution;
106
+ function computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes) {
107
+ try {
108
+ const itemHashes = captcha.items.map((item, index) => {
109
+ if (item.hash) {
110
+ return item.hash;
111
+ }
112
+ throw new ProsopoDatasetError("CAPTCHA.MISSING_ITEM_HASH", {
113
+ context: {
114
+ computeCaptchaHashName: computeCaptchaHash.name,
115
+ index
150
116
  }
151
- if (typeof solution === "number") {
152
- const item = at(items, solution);
153
- return item.hash;
154
- }
155
- throw new ProsopoDatasetError("CAPTCHA.INVALID_SOLUTION_TYPE");
117
+ });
156
118
  });
157
- }
158
- export function computeCaptchaSolutionHash(captcha) {
159
119
  return hexHashArray([
160
- captcha.captchaId,
161
- captcha.captchaContentId,
162
- [...captcha.solution].sort(),
163
- captcha.salt,
120
+ captcha.target,
121
+ // empty array hashes as empty string, undefined solution results in the array [`NO_SOLUTION`]
122
+ // [undefined] also hashes as empty string, which is why we don't use it
123
+ ...includeSolution ? getSolutionValueToHash(captcha.solution) : [],
124
+ includeSalt ? captcha.salt : "",
125
+ sortItemHashes ? itemHashes.sort() : itemHashes
164
126
  ]);
127
+ } catch (err) {
128
+ throw new ProsopoDatasetError("DATASET.HASH_ERROR", {
129
+ context: { error: err }
130
+ });
131
+ }
165
132
  }
166
- export function computePendingRequestHash(captchaIds, userAccount, salt) {
167
- return hexHashArray([...captchaIds.sort(), userAccount, salt]);
133
+ function getSolutionValueToHash(solution) {
134
+ return solution !== void 0 ? solution.sort() : [NO_SOLUTION_VALUE];
168
135
  }
169
- export function parseCaptchaAssets(item, assetsResolver) {
170
- return {
171
- ...item,
172
- data: assetsResolver?.resolveAsset(item.data).getURL() || item.data,
173
- };
136
+ async function computeItemHash(item) {
137
+ if (item.type === "text") {
138
+ return { ...item, hash: hexHash(item.data) };
139
+ }
140
+ if (item.type === "image") {
141
+ return { ...item, hash: hexHash(await downloadImage(item.data)) };
142
+ }
143
+ throw new ProsopoDatasetError("CAPTCHA.INVALID_ITEM_FORMAT");
144
+ }
145
+ function matchItemsToSolutions(solutions, items) {
146
+ if (!items) {
147
+ return [];
148
+ }
149
+ return solutions.map((solution) => {
150
+ if (typeof solution === "string" && isHex(solution)) {
151
+ if (!items?.some((item) => item.hash === solution)) {
152
+ throw new ProsopoDatasetError("CAPTCHA.INVALID_ITEM_HASH");
153
+ }
154
+ return solution;
155
+ }
156
+ if (typeof solution === "number") {
157
+ const item = at(items, solution);
158
+ return item.hash;
159
+ }
160
+ throw new ProsopoDatasetError("CAPTCHA.INVALID_SOLUTION_TYPE");
161
+ });
162
+ }
163
+ function computeCaptchaSolutionHash(captcha) {
164
+ return hexHashArray([
165
+ captcha.captchaId,
166
+ captcha.captchaContentId,
167
+ [...captcha.solution].sort(),
168
+ captcha.salt
169
+ ]);
170
+ }
171
+ function computePendingRequestHash(captchaIds, userAccount, salt) {
172
+ return hexHashArray([...captchaIds.sort(), userAccount, salt]);
173
+ }
174
+ function parseCaptchaAssets(item, assetsResolver) {
175
+ return {
176
+ ...item,
177
+ data: assetsResolver?.resolveAsset(item.data).getURL() || item.data
178
+ };
174
179
  }
175
- //# sourceMappingURL=captcha.js.map
180
+ export {
181
+ NO_SOLUTION_VALUE,
182
+ captchaSort,
183
+ compareCaptchaSolutions,
184
+ computeCaptchaHash,
185
+ computeCaptchaSolutionHash,
186
+ computeItemHash,
187
+ computePendingRequestHash,
188
+ getSolutionValueToHash,
189
+ matchItemsToSolutions,
190
+ parseAndSortCaptchaSolutions,
191
+ parseCaptchaAssets,
192
+ parseCaptchaDataset,
193
+ sortAndComputeHashes
194
+ };
@@ -1,79 +1,93 @@
1
- import { ProsopoEnvError, getLogger } from "@prosopo/common";
1
+ import { getLogger, ProsopoEnvError } from "@prosopo/common";
2
2
  import { at } from "@prosopo/util";
3
- import { computeCaptchaHash, computeItemHash, matchItemsToSolutions, } from "./captcha.js";
3
+ import { computeItemHash, computeCaptchaHash, matchItemsToSolutions } from "./captcha.js";
4
4
  import { CaptchaMerkleTree } from "./merkle.js";
5
5
  const logger = getLogger("info", import.meta.url);
6
- export async function hashDatasetItems(datasetRaw) {
7
- return datasetRaw.captchas.map(async (captcha) => {
8
- const items = await Promise.all(captcha.items.map(async (item) => computeItemHash(item)));
9
- return {
10
- ...captcha,
11
- items,
12
- };
13
- });
14
- }
15
- export async function validateDatasetContent(datasetOriginal) {
16
- const captchaPromises = await hashDatasetItems(datasetOriginal);
17
- const captchas = await Promise.all(captchaPromises);
18
- const dataset = {
19
- ...datasetOriginal,
20
- captchas,
6
+ async function hashDatasetItems(datasetRaw) {
7
+ return datasetRaw.captchas.map(async (captcha) => {
8
+ const items = await Promise.all(
9
+ captcha.items.map(async (item) => computeItemHash(item))
10
+ );
11
+ return {
12
+ ...captcha,
13
+ items
21
14
  };
22
- const hashes = dataset.captchas.map((captcha) => {
23
- const captchaRaw = datasetOriginal.captchas.find((captchaRaw) => "captchaId" in captchaRaw
24
- ? captchaRaw.captchaId === captcha.captchaId
25
- : false);
26
- if (captchaRaw) {
27
- return captcha.items.every((item, index) => item.hash === at(captchaRaw.items, index).hash);
28
- }
29
- return false;
30
- });
31
- return hashes.every((hash) => hash);
32
- }
33
- export async function buildDataset(datasetRaw) {
34
- logger.debug(() => ({ msg: "Adding solution hashes to dataset" }));
35
- const dataset = await addSolutionHashesToDataset(datasetRaw);
36
- logger.debug(() => ({ msg: "Building dataset merkle trees" }));
37
- const contentTree = await buildCaptchaTree(dataset, false, false, true);
38
- const solutionTree = await buildCaptchaTree(dataset, true, true, false);
39
- dataset.captchas = dataset.captchas.map((captcha, index) => ({
40
- ...captcha,
41
- captchaId: at(solutionTree.leaves, index).hash,
42
- captchaContentId: at(contentTree.leaves, index).hash,
43
- datasetId: solutionTree.root?.hash,
44
- datasetContentId: contentTree.root?.hash,
45
- }));
46
- dataset.solutionTree = solutionTree.layers;
47
- dataset.contentTree = contentTree.layers;
48
- dataset.datasetId = solutionTree.root?.hash;
49
- dataset.datasetContentId = contentTree.root?.hash;
50
- return dataset;
15
+ });
51
16
  }
52
- export async function buildCaptchaTree(dataset, includeSolution, includeSalt, sortItemHashes) {
53
- try {
54
- const tree = new CaptchaMerkleTree();
55
- const datasetWithItemHashes = { ...dataset };
56
- const captchaHashes = datasetWithItemHashes.captchas.map((captcha) => computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes));
57
- tree.build(captchaHashes);
58
- return tree;
59
- }
60
- catch (err) {
61
- throw new ProsopoEnvError("DATASET.HASH_ERROR");
17
+ async function validateDatasetContent(datasetOriginal) {
18
+ const captchaPromises = await hashDatasetItems(datasetOriginal);
19
+ const captchas = await Promise.all(captchaPromises);
20
+ const dataset = {
21
+ ...datasetOriginal,
22
+ captchas
23
+ };
24
+ const hashes = dataset.captchas.map((captcha) => {
25
+ const captchaRaw = datasetOriginal.captchas.find(
26
+ (captchaRaw2) => "captchaId" in captchaRaw2 ? captchaRaw2.captchaId === captcha.captchaId : false
27
+ );
28
+ if (captchaRaw) {
29
+ return captcha.items.every(
30
+ (item, index) => item.hash === at(captchaRaw.items, index).hash
31
+ );
62
32
  }
33
+ return false;
34
+ });
35
+ return hashes.every((hash) => hash);
36
+ }
37
+ async function buildDataset(datasetRaw) {
38
+ logger.debug(() => ({ msg: "Adding solution hashes to dataset" }));
39
+ const dataset = await addSolutionHashesToDataset(datasetRaw);
40
+ logger.debug(() => ({ msg: "Building dataset merkle trees" }));
41
+ const contentTree = await buildCaptchaTree(dataset, false, false, true);
42
+ const solutionTree = await buildCaptchaTree(dataset, true, true, false);
43
+ dataset.captchas = dataset.captchas.map(
44
+ (captcha, index) => ({
45
+ ...captcha,
46
+ captchaId: at(solutionTree.leaves, index).hash,
47
+ captchaContentId: at(contentTree.leaves, index).hash,
48
+ datasetId: solutionTree.root?.hash,
49
+ datasetContentId: contentTree.root?.hash
50
+ })
51
+ );
52
+ dataset.solutionTree = solutionTree.layers;
53
+ dataset.contentTree = contentTree.layers;
54
+ dataset.datasetId = solutionTree.root?.hash;
55
+ dataset.datasetContentId = contentTree.root?.hash;
56
+ return dataset;
57
+ }
58
+ async function buildCaptchaTree(dataset, includeSolution, includeSalt, sortItemHashes) {
59
+ try {
60
+ const tree = new CaptchaMerkleTree();
61
+ const datasetWithItemHashes = { ...dataset };
62
+ const captchaHashes = datasetWithItemHashes.captchas.map(
63
+ (captcha) => computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes)
64
+ );
65
+ tree.build(captchaHashes);
66
+ return tree;
67
+ } catch (err) {
68
+ throw new ProsopoEnvError("DATASET.HASH_ERROR");
69
+ }
63
70
  }
64
- export function addSolutionHashesToDataset(datasetRaw) {
65
- const captchas = datasetRaw.captchas.map((captcha) => {
66
- return {
67
- ...captcha,
68
- items: captcha.items,
69
- ...(captcha.solution !== undefined && {
70
- solution: matchItemsToSolutions(captcha.solution, captcha.items),
71
- }),
72
- };
73
- });
71
+ function addSolutionHashesToDataset(datasetRaw) {
72
+ const captchas = datasetRaw.captchas.map((captcha) => {
74
73
  return {
75
- ...datasetRaw,
76
- captchas,
74
+ ...captcha,
75
+ items: captcha.items,
76
+ // some captcha challenges will not have a solution
77
+ ...captcha.solution !== void 0 && {
78
+ solution: matchItemsToSolutions(captcha.solution, captcha.items)
79
+ }
77
80
  };
81
+ });
82
+ return {
83
+ ...datasetRaw,
84
+ captchas
85
+ };
78
86
  }
79
- //# sourceMappingURL=dataset.js.map
87
+ export {
88
+ addSolutionHashesToDataset,
89
+ buildCaptchaTree,
90
+ buildDataset,
91
+ hashDatasetItems,
92
+ validateDatasetContent
93
+ };
@@ -1,5 +1,27 @@
1
- export * from "./captcha.js";
2
- export * from "./merkle.js";
3
- export * from "./util.js";
4
- export * from "./dataset.js";
5
- //# sourceMappingURL=index.js.map
1
+ import { NO_SOLUTION_VALUE, captchaSort, compareCaptchaSolutions, computeCaptchaHash, computeCaptchaSolutionHash, computeItemHash, computePendingRequestHash, getSolutionValueToHash, matchItemsToSolutions, parseAndSortCaptchaSolutions, parseCaptchaAssets, parseCaptchaDataset, sortAndComputeHashes } from "./captcha.js";
2
+ import { CaptchaMerkleTree, verifyProof } from "./merkle.js";
3
+ import { downloadImage } from "./util.js";
4
+ import { addSolutionHashesToDataset, buildCaptchaTree, buildDataset, hashDatasetItems, validateDatasetContent } from "./dataset.js";
5
+ export {
6
+ CaptchaMerkleTree,
7
+ NO_SOLUTION_VALUE,
8
+ addSolutionHashesToDataset,
9
+ buildCaptchaTree,
10
+ buildDataset,
11
+ captchaSort,
12
+ compareCaptchaSolutions,
13
+ computeCaptchaHash,
14
+ computeCaptchaSolutionHash,
15
+ computeItemHash,
16
+ computePendingRequestHash,
17
+ downloadImage,
18
+ getSolutionValueToHash,
19
+ hashDatasetItems,
20
+ matchItemsToSolutions,
21
+ parseAndSortCaptchaSolutions,
22
+ parseCaptchaAssets,
23
+ parseCaptchaDataset,
24
+ sortAndComputeHashes,
25
+ validateDatasetContent,
26
+ verifyProof
27
+ };