@prosopo/provider 3.2.0 → 3.2.2

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 (233) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/api/admin/apiAdminRoutesProvider.js +26 -21
  3. package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +21 -20
  4. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +27 -27
  5. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +33 -33
  6. package/dist/api/admin/createApiAdminRoutesProvider.js +8 -5
  7. package/dist/api/blacklistRequestInspector.js +115 -98
  8. package/dist/api/block.js +13 -8
  9. package/dist/api/captcha.js +519 -356
  10. package/dist/api/domainMiddleware.js +75 -68
  11. package/dist/api/headerCheckMiddleware.js +26 -25
  12. package/dist/api/ignoreMiddleware.js +12 -10
  13. package/dist/api/ja4Middleware.js +74 -82
  14. package/dist/api/public.js +26 -23
  15. package/dist/api/robotsMiddleware.js +11 -9
  16. package/dist/api/validateAddress.js +20 -18
  17. package/dist/api/verify.js +133 -95
  18. package/dist/cjs/api/captcha.cjs +45 -36
  19. package/dist/cjs/tasks/captchaManager.cjs +24 -10
  20. package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +12 -12
  21. package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +1 -1
  22. package/dist/index.js +38 -15
  23. package/dist/rules/lang.js +14 -14
  24. package/dist/schedulers/captchaScheduler.js +28 -23
  25. package/dist/schedulers/getClientList.js +29 -24
  26. package/dist/tasks/captchaManager.js +109 -85
  27. package/dist/tasks/client/clientTasks.js +265 -204
  28. package/dist/tasks/dataset/datasetTasks.js +27 -16
  29. package/dist/tasks/dataset/datasetTasksUtils.js +31 -31
  30. package/dist/tasks/detection/decodePayload.js +378 -208
  31. package/dist/tasks/detection/getBotScore.js +12 -10
  32. package/dist/tasks/frictionless/frictionlessTasks.js +120 -119
  33. package/dist/tasks/frictionless/frictionlessTasksUtils.js +10 -5
  34. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +360 -271
  35. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +23 -16
  36. package/dist/tasks/index.js +4 -2
  37. package/dist/tasks/powCaptcha/powTasks.js +157 -97
  38. package/dist/tasks/powCaptcha/powTasksUtils.js +24 -20
  39. package/dist/tasks/tasks.js +53 -29
  40. package/dist/util.js +98 -88
  41. package/package.json +31 -27
  42. package/vite.cjs.config.ts +4 -1
  43. package/vite.esm.config.ts +20 -0
  44. package/vite.test.config.ts +15 -3
  45. package/dist/api/admin/apiAdminRoutesProvider.d.ts +0 -9
  46. package/dist/api/admin/apiAdminRoutesProvider.d.ts.map +0 -1
  47. package/dist/api/admin/apiAdminRoutesProvider.js.map +0 -1
  48. package/dist/api/admin/apiRegisterSiteKeyEndpoint.d.ts +0 -14
  49. package/dist/api/admin/apiRegisterSiteKeyEndpoint.d.ts.map +0 -1
  50. package/dist/api/admin/apiRegisterSiteKeyEndpoint.js.map +0 -1
  51. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts +0 -14
  52. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +0 -1
  53. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js.map +0 -1
  54. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.d.ts +0 -14
  55. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.d.ts.map +0 -1
  56. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js.map +0 -1
  57. package/dist/api/admin/createApiAdminRoutesProvider.d.ts +0 -4
  58. package/dist/api/admin/createApiAdminRoutesProvider.d.ts.map +0 -1
  59. package/dist/api/admin/createApiAdminRoutesProvider.js.map +0 -1
  60. package/dist/api/blacklistRequestInspector.d.ts +0 -39
  61. package/dist/api/blacklistRequestInspector.d.ts.map +0 -1
  62. package/dist/api/blacklistRequestInspector.js.map +0 -1
  63. package/dist/api/block.d.ts +0 -3
  64. package/dist/api/block.d.ts.map +0 -1
  65. package/dist/api/block.js.map +0 -1
  66. package/dist/api/captcha.d.ts +0 -4
  67. package/dist/api/captcha.d.ts.map +0 -1
  68. package/dist/api/captcha.js.map +0 -1
  69. package/dist/api/domainMiddleware.d.ts +0 -4
  70. package/dist/api/domainMiddleware.d.ts.map +0 -1
  71. package/dist/api/domainMiddleware.js.map +0 -1
  72. package/dist/api/headerCheckMiddleware.d.ts +0 -4
  73. package/dist/api/headerCheckMiddleware.d.ts.map +0 -1
  74. package/dist/api/headerCheckMiddleware.js.map +0 -1
  75. package/dist/api/ignoreMiddleware.d.ts +0 -3
  76. package/dist/api/ignoreMiddleware.d.ts.map +0 -1
  77. package/dist/api/ignoreMiddleware.js.map +0 -1
  78. package/dist/api/ja4Middleware.d.ts +0 -10
  79. package/dist/api/ja4Middleware.d.ts.map +0 -1
  80. package/dist/api/ja4Middleware.js.map +0 -1
  81. package/dist/api/public.d.ts +0 -3
  82. package/dist/api/public.d.ts.map +0 -1
  83. package/dist/api/public.js.map +0 -1
  84. package/dist/api/robotsMiddleware.d.ts +0 -3
  85. package/dist/api/robotsMiddleware.d.ts.map +0 -1
  86. package/dist/api/robotsMiddleware.js.map +0 -1
  87. package/dist/api/validateAddress.d.ts +0 -5
  88. package/dist/api/validateAddress.d.ts.map +0 -1
  89. package/dist/api/validateAddress.js.map +0 -1
  90. package/dist/api/verify.d.ts +0 -4
  91. package/dist/api/verify.d.ts.map +0 -1
  92. package/dist/api/verify.js.map +0 -1
  93. package/dist/index.d.ts +0 -15
  94. package/dist/index.d.ts.map +0 -1
  95. package/dist/index.js.map +0 -1
  96. package/dist/rules/lang.d.ts +0 -3
  97. package/dist/rules/lang.d.ts.map +0 -1
  98. package/dist/rules/lang.js.map +0 -1
  99. package/dist/schedulers/captchaScheduler.d.ts +0 -4
  100. package/dist/schedulers/captchaScheduler.d.ts.map +0 -1
  101. package/dist/schedulers/captchaScheduler.js.map +0 -1
  102. package/dist/schedulers/getClientList.d.ts +0 -4
  103. package/dist/schedulers/getClientList.d.ts.map +0 -1
  104. package/dist/schedulers/getClientList.js.map +0 -1
  105. package/dist/tasks/captchaManager.d.ts +0 -48
  106. package/dist/tasks/captchaManager.d.ts.map +0 -1
  107. package/dist/tasks/captchaManager.js.map +0 -1
  108. package/dist/tasks/client/clientTasks.d.ts +0 -21
  109. package/dist/tasks/client/clientTasks.d.ts.map +0 -1
  110. package/dist/tasks/client/clientTasks.js.map +0 -1
  111. package/dist/tasks/dataset/datasetTasks.d.ts +0 -13
  112. package/dist/tasks/dataset/datasetTasks.d.ts.map +0 -1
  113. package/dist/tasks/dataset/datasetTasks.js.map +0 -1
  114. package/dist/tasks/dataset/datasetTasksUtils.d.ts +0 -3
  115. package/dist/tasks/dataset/datasetTasksUtils.d.ts.map +0 -1
  116. package/dist/tasks/dataset/datasetTasksUtils.js.map +0 -1
  117. package/dist/tasks/detection/decodePayload.d.ts +0 -5
  118. package/dist/tasks/detection/decodePayload.d.ts.map +0 -1
  119. package/dist/tasks/detection/decodePayload.js.map +0 -1
  120. package/dist/tasks/detection/getBotScore.d.ts +0 -5
  121. package/dist/tasks/detection/getBotScore.d.ts.map +0 -1
  122. package/dist/tasks/detection/getBotScore.js.map +0 -1
  123. package/dist/tasks/frictionless/frictionlessTasks.d.ts +0 -23
  124. package/dist/tasks/frictionless/frictionlessTasks.d.ts.map +0 -1
  125. package/dist/tasks/frictionless/frictionlessTasks.js.map +0 -1
  126. package/dist/tasks/frictionless/frictionlessTasksUtils.d.ts +0 -5
  127. package/dist/tasks/frictionless/frictionlessTasksUtils.d.ts.map +0 -1
  128. package/dist/tasks/frictionless/frictionlessTasksUtils.js.map +0 -1
  129. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts +0 -29
  130. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +0 -1
  131. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +0 -1
  132. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.d.ts +0 -7
  133. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.d.ts.map +0 -1
  134. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js.map +0 -1
  135. package/dist/tasks/index.d.ts +0 -2
  136. package/dist/tasks/index.d.ts.map +0 -1
  137. package/dist/tasks/index.js.map +0 -1
  138. package/dist/tasks/powCaptcha/powTasks.d.ts +0 -16
  139. package/dist/tasks/powCaptcha/powTasks.d.ts.map +0 -1
  140. package/dist/tasks/powCaptcha/powTasks.js.map +0 -1
  141. package/dist/tasks/powCaptcha/powTasksUtils.d.ts +0 -3
  142. package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +0 -1
  143. package/dist/tasks/powCaptcha/powTasksUtils.js.map +0 -1
  144. package/dist/tasks/tasks.d.ts +0 -25
  145. package/dist/tasks/tasks.d.ts.map +0 -1
  146. package/dist/tasks/tasks.js.map +0 -1
  147. package/dist/tests/index.d.ts +0 -2
  148. package/dist/tests/index.d.ts.map +0 -1
  149. package/dist/tests/index.js +0 -2
  150. package/dist/tests/index.js.map +0 -1
  151. package/dist/tests/integration/accessRules.integration.test.d.ts +0 -2
  152. package/dist/tests/integration/accessRules.integration.test.d.ts.map +0 -1
  153. package/dist/tests/integration/accessRules.integration.test.js +0 -164
  154. package/dist/tests/integration/accessRules.integration.test.js.map +0 -1
  155. package/dist/tests/integration/imgCaptcha.integration.test.d.ts +0 -2
  156. package/dist/tests/integration/imgCaptcha.integration.test.d.ts.map +0 -1
  157. package/dist/tests/integration/imgCaptcha.integration.test.js +0 -261
  158. package/dist/tests/integration/imgCaptcha.integration.test.js.map +0 -1
  159. package/dist/tests/integration/mocks/solvedTestCaptchas.d.ts +0 -32
  160. package/dist/tests/integration/mocks/solvedTestCaptchas.d.ts.map +0 -1
  161. package/dist/tests/integration/mocks/solvedTestCaptchas.js +0 -1046
  162. package/dist/tests/integration/mocks/solvedTestCaptchas.js.map +0 -1
  163. package/dist/tests/integration/powCaptcha.integration.test.d.ts +0 -2
  164. package/dist/tests/integration/powCaptcha.integration.test.d.ts.map +0 -1
  165. package/dist/tests/integration/powCaptcha.integration.test.js +0 -306
  166. package/dist/tests/integration/powCaptcha.integration.test.js.map +0 -1
  167. package/dist/tests/integration/registerSitekey.d.ts +0 -3
  168. package/dist/tests/integration/registerSitekey.d.ts.map +0 -1
  169. package/dist/tests/integration/registerSitekey.js +0 -39
  170. package/dist/tests/integration/registerSitekey.js.map +0 -1
  171. package/dist/tests/integration/userAccessPolicy.d.ts +0 -16
  172. package/dist/tests/integration/userAccessPolicy.d.ts.map +0 -1
  173. package/dist/tests/integration/userAccessPolicy.js +0 -55
  174. package/dist/tests/integration/userAccessPolicy.js.map +0 -1
  175. package/dist/tests/unit/api/ignoreMiddleware.unit.test.d.ts +0 -2
  176. package/dist/tests/unit/api/ignoreMiddleware.unit.test.d.ts.map +0 -1
  177. package/dist/tests/unit/api/ignoreMiddleware.unit.test.js +0 -43
  178. package/dist/tests/unit/api/ignoreMiddleware.unit.test.js.map +0 -1
  179. package/dist/tests/unit/api/ja4Middleware.unit.test.d.ts +0 -2
  180. package/dist/tests/unit/api/ja4Middleware.unit.test.d.ts.map +0 -1
  181. package/dist/tests/unit/api/ja4Middleware.unit.test.js +0 -71
  182. package/dist/tests/unit/api/ja4Middleware.unit.test.js.map +0 -1
  183. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.d.ts +0 -2
  184. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.d.ts.map +0 -1
  185. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +0 -75
  186. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +0 -1
  187. package/dist/tests/unit/tasks/captchaManager.unit.test.d.ts +0 -2
  188. package/dist/tests/unit/tasks/captchaManager.unit.test.d.ts.map +0 -1
  189. package/dist/tests/unit/tasks/captchaManager.unit.test.js +0 -236
  190. package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +0 -1
  191. package/dist/tests/unit/tasks/client/clientTasks.unit.test.d.ts +0 -2
  192. package/dist/tests/unit/tasks/client/clientTasks.unit.test.d.ts.map +0 -1
  193. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js +0 -277
  194. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +0 -1
  195. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.d.ts +0 -2
  196. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.d.ts.map +0 -1
  197. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js +0 -93
  198. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js.map +0 -1
  199. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.d.ts +0 -2
  200. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.d.ts.map +0 -1
  201. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js +0 -75
  202. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js.map +0 -1
  203. package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.d.ts +0 -2
  204. package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.d.ts.map +0 -1
  205. package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js +0 -68
  206. package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js.map +0 -1
  207. package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.d.ts +0 -2
  208. package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.d.ts.map +0 -1
  209. package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.js +0 -37
  210. package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.js.map +0 -1
  211. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.d.ts +0 -2
  212. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.d.ts.map +0 -1
  213. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js +0 -402
  214. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js.map +0 -1
  215. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.d.ts +0 -2
  216. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.d.ts.map +0 -1
  217. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +0 -46
  218. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +0 -1
  219. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.d.ts +0 -2
  220. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.d.ts.map +0 -1
  221. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js +0 -228
  222. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js.map +0 -1
  223. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.d.ts +0 -2
  224. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.d.ts.map +0 -1
  225. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js +0 -68
  226. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +0 -1
  227. package/dist/tests/unit/util.unit.test.d.ts +0 -2
  228. package/dist/tests/unit/util.unit.test.d.ts.map +0 -1
  229. package/dist/tests/unit/util.unit.test.js +0 -148
  230. package/dist/tests/unit/util.unit.test.js.map +0 -1
  231. package/dist/util.d.ts +0 -13
  232. package/dist/util.d.ts.map +0 -1
  233. package/dist/util.js.map +0 -1
@@ -1,18 +1,25 @@
1
1
  import { ProsopoEnvError } from "@prosopo/common";
2
- import { CaptchaMerkleTree, computeCaptchaSolutionHash, } from "@prosopo/datasets";
3
- export const buildTreeAndGetCommitmentId = (captchaSolutions) => {
4
- const tree = new CaptchaMerkleTree();
5
- const solutionsHashed = captchaSolutions.map((captcha) => computeCaptchaSolutionHash(captcha));
6
- tree.build(solutionsHashed);
7
- const commitmentId = tree.root?.hash;
8
- if (!commitmentId) {
9
- throw new ProsopoEnvError("CONTRACT.CAPTCHA_SOLUTION_COMMITMENT_DOES_NOT_EXIST", {
10
- context: {
11
- failedFuncName: buildTreeAndGetCommitmentId.name,
12
- commitmentId: commitmentId,
13
- },
14
- });
15
- }
16
- return { tree, commitmentId };
2
+ import { CaptchaMerkleTree, computeCaptchaSolutionHash } from "@prosopo/datasets";
3
+ const buildTreeAndGetCommitmentId = (captchaSolutions) => {
4
+ const tree = new CaptchaMerkleTree();
5
+ const solutionsHashed = captchaSolutions.map(
6
+ (captcha) => computeCaptchaSolutionHash(captcha)
7
+ );
8
+ tree.build(solutionsHashed);
9
+ const commitmentId = tree.root?.hash;
10
+ if (!commitmentId) {
11
+ throw new ProsopoEnvError(
12
+ "CONTRACT.CAPTCHA_SOLUTION_COMMITMENT_DOES_NOT_EXIST",
13
+ {
14
+ context: {
15
+ failedFuncName: buildTreeAndGetCommitmentId.name,
16
+ commitmentId
17
+ }
18
+ }
19
+ );
20
+ }
21
+ return { tree, commitmentId };
22
+ };
23
+ export {
24
+ buildTreeAndGetCommitmentId
17
25
  };
18
- //# sourceMappingURL=imgCaptchaTasksUtils.js.map
@@ -1,2 +1,4 @@
1
- export * from "./tasks.js";
2
- //# sourceMappingURL=index.js.map
1
+ import { Tasks } from "./tasks.js";
2
+ export {
3
+ Tasks
4
+ };
@@ -1,111 +1,171 @@
1
- import { stringToHex, u8aToHex } from "@polkadot/util";
1
+ import { u8aToHex, stringToHex } from "@polkadot/util";
2
2
  import { ProsopoApiError, ProsopoEnvError } from "@prosopo/common";
3
- import { ApiParams, CaptchaStatus, POW_SEPARATOR, } from "@prosopo/types";
3
+ import { POW_SEPARATOR, ApiParams, CaptchaStatus } from "@prosopo/types";
4
4
  import { at, verifyRecency } from "@prosopo/util";
5
5
  import { validateIpAddress } from "../../util.js";
6
6
  import { CaptchaManager } from "../captchaManager.js";
7
7
  import { computeFrictionlessScore } from "../frictionless/frictionlessTasksUtils.js";
8
8
  import { checkPowSignature, validateSolution } from "./powTasksUtils.js";
9
9
  const DEFAULT_POW_DIFFICULTY = 4;
10
- export class PowCaptchaManager extends CaptchaManager {
11
- constructor(db, pair, logger) {
12
- super(db, pair, logger);
13
- this.POW_SEPARATOR = POW_SEPARATOR;
10
+ class PowCaptchaManager extends CaptchaManager {
11
+ constructor(db, pair, logger) {
12
+ super(db, pair, logger);
13
+ this.POW_SEPARATOR = POW_SEPARATOR;
14
+ }
15
+ /**
16
+ * @description Generates a PoW Captcha for a given user and dapp
17
+ *
18
+ * @param {string} userAccount - user that is solving the captcha
19
+ * @param {string} dappAccount - dapp that is requesting the captcha
20
+ * @param origin - not currently used
21
+ * @param powDifficulty
22
+ */
23
+ async getPowCaptchaChallenge(userAccount, dappAccount, origin, powDifficulty) {
24
+ const difficulty = powDifficulty || DEFAULT_POW_DIFFICULTY;
25
+ const requestedAtTimestamp = Date.now();
26
+ const nonce = Math.floor(Math.random() * 1e6);
27
+ const challenge = `${requestedAtTimestamp}___${userAccount}___${dappAccount}___${nonce}`;
28
+ const challengeSignature = u8aToHex(this.pair.sign(stringToHex(challenge)));
29
+ return {
30
+ challenge,
31
+ difficulty,
32
+ providerSignature: challengeSignature,
33
+ requestedAtTimestamp
34
+ };
35
+ }
36
+ /**
37
+ * @description Verifies a PoW Captcha for a given user and dapp
38
+ *
39
+ * @param {string} challenge - the starting string for the PoW challenge
40
+ * @param {string} difficulty - how many leading zeroes the solution must have
41
+ * @param {string} providerChallengeSignature - proof that the Provider provided the challenge
42
+ * @param {string} nonce - the string that the user has found that satisfies the PoW challenge
43
+ * @param {number} timeout - the time in milliseconds since the Provider was selected to provide the PoW captcha
44
+ * @param {string} userTimestampSignature
45
+ * @param ipAddress
46
+ * @param headers
47
+ */
48
+ async verifyPowCaptchaSolution(challenge, difficulty, providerChallengeSignature, nonce, timeout, userTimestampSignature, ipAddress, headers) {
49
+ checkPowSignature(
50
+ challenge,
51
+ providerChallengeSignature,
52
+ this.pair.address,
53
+ ApiParams.challenge
54
+ );
55
+ const challengeSplit = challenge.split(this.POW_SEPARATOR);
56
+ const timestamp = Number.parseInt(at(challengeSplit, 0));
57
+ const userAccount = at(challengeSplit, 1);
58
+ checkPowSignature(
59
+ timestamp.toString(),
60
+ userTimestampSignature,
61
+ userAccount,
62
+ ApiParams.timestamp
63
+ );
64
+ const challengeRecord = await this.db.getPowCaptchaRecordByChallenge(challenge);
65
+ if (!challengeRecord) {
66
+ this.logger.debug(() => ({
67
+ msg: `No record of this challenge: ${challenge}`
68
+ }));
69
+ return false;
14
70
  }
15
- async getPowCaptchaChallenge(userAccount, dappAccount, origin, powDifficulty) {
16
- const difficulty = powDifficulty || DEFAULT_POW_DIFFICULTY;
17
- const requestedAtTimestamp = Date.now();
18
- const nonce = Math.floor(Math.random() * 1000000);
19
- const challenge = `${requestedAtTimestamp}___${userAccount}___${dappAccount}___${nonce}`;
20
- const challengeSignature = u8aToHex(this.pair.sign(stringToHex(challenge)));
21
- return {
22
- challenge,
23
- difficulty,
24
- providerSignature: challengeSignature,
25
- requestedAtTimestamp,
26
- };
71
+ if (!verifyRecency(challenge, timeout)) {
72
+ await this.db.updatePowCaptchaRecord(
73
+ challenge,
74
+ {
75
+ status: CaptchaStatus.disapproved,
76
+ reason: "CAPTCHA.INVALID_TIMESTAMP"
77
+ },
78
+ false,
79
+ //serverchecked
80
+ true,
81
+ // usersubmitted
82
+ userTimestampSignature
83
+ );
84
+ return false;
27
85
  }
28
- async verifyPowCaptchaSolution(challenge, difficulty, providerChallengeSignature, nonce, timeout, userTimestampSignature, ipAddress, headers) {
29
- checkPowSignature(challenge, providerChallengeSignature, this.pair.address, ApiParams.challenge);
30
- const challengeSplit = challenge.split(this.POW_SEPARATOR);
31
- const timestamp = Number.parseInt(at(challengeSplit, 0));
32
- const userAccount = at(challengeSplit, 1);
33
- checkPowSignature(timestamp.toString(), userTimestampSignature, userAccount, ApiParams.timestamp);
34
- const challengeRecord = await this.db.getPowCaptchaRecordByChallenge(challenge);
35
- if (!challengeRecord) {
36
- this.logger.debug(() => ({
37
- msg: `No record of this challenge: ${challenge}`,
38
- }));
39
- return false;
40
- }
41
- if (!verifyRecency(challenge, timeout)) {
42
- await this.db.updatePowCaptchaRecord(challenge, {
43
- status: CaptchaStatus.disapproved,
44
- reason: "CAPTCHA.INVALID_TIMESTAMP",
45
- }, false, true, userTimestampSignature);
46
- return false;
47
- }
48
- const correct = validateSolution(nonce, challenge, difficulty);
49
- let result = { status: CaptchaStatus.approved };
50
- if (!correct) {
51
- result = {
52
- status: CaptchaStatus.disapproved,
53
- reason: "CAPTCHA.INVALID_SOLUTION",
54
- };
55
- }
56
- await this.db.updatePowCaptchaRecord(challenge, result, false, true, userTimestampSignature);
57
- return correct;
86
+ const correct = validateSolution(nonce, challenge, difficulty);
87
+ let result = { status: CaptchaStatus.approved };
88
+ if (!correct) {
89
+ result = {
90
+ status: CaptchaStatus.disapproved,
91
+ reason: "CAPTCHA.INVALID_SOLUTION"
92
+ };
58
93
  }
59
- async serverVerifyPowCaptchaSolution(dappAccount, challenge, timeout, ip) {
60
- const challengeRecord = await this.db.getPowCaptchaRecordByChallenge(challenge);
61
- if (!challengeRecord) {
62
- this.logger.debug(() => ({
63
- msg: `No record of this challenge: ${challenge}`,
64
- }));
65
- return { verified: false };
66
- }
67
- const ipValidation = validateIpAddress(ip, challengeRecord.ipAddress, this.logger);
68
- if (!ipValidation.isValid) {
69
- return { verified: false };
70
- }
71
- if (challengeRecord.result.status !== CaptchaStatus.approved) {
72
- throw new ProsopoApiError("CAPTCHA.INVALID_SOLUTION", {
73
- context: {
74
- failedFuncName: this.serverVerifyPowCaptchaSolution.name,
75
- challenge,
76
- },
77
- });
78
- }
79
- if (challengeRecord.serverChecked)
80
- return { verified: false };
81
- const challengeDappAccount = challengeRecord.dappAccount;
82
- if (dappAccount !== challengeDappAccount) {
83
- throw new ProsopoEnvError("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND", {
84
- context: {
85
- failedFuncName: this.serverVerifyPowCaptchaSolution.name,
86
- dappAccount,
87
- challengeDappAccount,
88
- },
89
- });
94
+ await this.db.updatePowCaptchaRecord(
95
+ challenge,
96
+ result,
97
+ false,
98
+ true,
99
+ userTimestampSignature
100
+ );
101
+ return correct;
102
+ }
103
+ /**
104
+ * @description Verifies a PoW Captcha for a given user and dapp. This is called by the server to verify the user's solution
105
+ * and update the record in the database to show that the user has solved the captcha
106
+ *
107
+ * @param {string} dappAccount - the dapp that is requesting the captcha
108
+ * @param {string} challenge - the starting string for the PoW challenge
109
+ * @param {number} timeout - the time in milliseconds since the Provider was selected to provide the PoW captcha
110
+ * @param ip
111
+ */
112
+ async serverVerifyPowCaptchaSolution(dappAccount, challenge, timeout, ip) {
113
+ const challengeRecord = await this.db.getPowCaptchaRecordByChallenge(challenge);
114
+ if (!challengeRecord) {
115
+ this.logger.debug(() => ({
116
+ msg: `No record of this challenge: ${challenge}`
117
+ }));
118
+ return { verified: false };
119
+ }
120
+ const ipValidation = validateIpAddress(
121
+ ip,
122
+ challengeRecord.ipAddress,
123
+ this.logger
124
+ );
125
+ if (!ipValidation.isValid) {
126
+ return { verified: false };
127
+ }
128
+ if (challengeRecord.result.status !== CaptchaStatus.approved) {
129
+ throw new ProsopoApiError("CAPTCHA.INVALID_SOLUTION", {
130
+ context: {
131
+ failedFuncName: this.serverVerifyPowCaptchaSolution.name,
132
+ challenge
90
133
  }
91
- verifyRecency(challenge, timeout);
92
- await this.db.markDappUserPoWCommitmentsChecked([
93
- challengeRecord.challenge,
94
- ]);
95
- let score;
96
- if (challengeRecord.frictionlessTokenId) {
97
- const tokenRecord = await this.db.getFrictionlessTokenRecordByTokenId(challengeRecord.frictionlessTokenId);
98
- if (tokenRecord) {
99
- score = computeFrictionlessScore(tokenRecord?.scoreComponents);
100
- this.logger.info(() => ({
101
- data: {
102
- tscoreComponents: { ...(tokenRecord?.scoreComponents || {}) },
103
- score,
104
- },
105
- }));
106
- }
134
+ });
135
+ }
136
+ if (challengeRecord.serverChecked) return { verified: false };
137
+ const challengeDappAccount = challengeRecord.dappAccount;
138
+ if (dappAccount !== challengeDappAccount) {
139
+ throw new ProsopoEnvError("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND", {
140
+ context: {
141
+ failedFuncName: this.serverVerifyPowCaptchaSolution.name,
142
+ dappAccount,
143
+ challengeDappAccount
107
144
  }
108
- return { verified: true, ...(score ? { score } : {}) };
145
+ });
146
+ }
147
+ verifyRecency(challenge, timeout);
148
+ await this.db.markDappUserPoWCommitmentsChecked([
149
+ challengeRecord.challenge
150
+ ]);
151
+ let score;
152
+ if (challengeRecord.frictionlessTokenId) {
153
+ const tokenRecord = await this.db.getFrictionlessTokenRecordByTokenId(
154
+ challengeRecord.frictionlessTokenId
155
+ );
156
+ if (tokenRecord) {
157
+ score = computeFrictionlessScore(tokenRecord?.scoreComponents);
158
+ this.logger.info(() => ({
159
+ data: {
160
+ tscoreComponents: { ...tokenRecord?.scoreComponents || {} },
161
+ score
162
+ }
163
+ }));
164
+ }
109
165
  }
166
+ return { verified: true, ...score ? { score } : {} };
167
+ }
110
168
  }
111
- //# sourceMappingURL=powTasks.js.map
169
+ export {
170
+ PowCaptchaManager
171
+ };
@@ -1,24 +1,28 @@
1
1
  import { sha256 } from "@noble/hashes/sha256";
2
2
  import { stringToHex } from "@polkadot/util";
3
- import { ProsopoContractError } from "@prosopo/common";
3
+ import { ProsopoApiError } from "@prosopo/common";
4
4
  import { signatureVerify } from "@prosopo/util-crypto";
5
- export const validateSolution = (nonce, challenge, difficulty) => Array.from(sha256(new TextEncoder().encode(nonce + challenge)))
6
- .map((byte) => byte.toString(16).padStart(2, "0"))
7
- .join("")
8
- .startsWith("0".repeat(difficulty));
9
- export const checkPowSignature = (message, signature, address, signatureType) => {
10
- const signatureVerification = signatureVerify(stringToHex(message), signature, address);
11
- if (!signatureVerification.isValid) {
12
- throw new ProsopoContractError("GENERAL.INVALID_SIGNATURE", {
13
- context: {
14
- ERROR: `Signature is invalid for this message: ${signatureType}`,
15
- failedFuncName: checkPowSignature.name,
16
- address,
17
- message,
18
- signature,
19
- signatureType,
20
- },
21
- });
22
- }
5
+ const validateSolution = (nonce, challenge, difficulty) => Array.from(sha256(new TextEncoder().encode(nonce + challenge))).map((byte) => byte.toString(16).padStart(2, "0")).join("").startsWith("0".repeat(difficulty));
6
+ const checkPowSignature = (message, signature, address, signatureType) => {
7
+ const signatureVerification = signatureVerify(
8
+ stringToHex(message),
9
+ signature,
10
+ address
11
+ );
12
+ if (!signatureVerification.isValid) {
13
+ throw new ProsopoApiError("GENERAL.INVALID_SIGNATURE", {
14
+ context: {
15
+ ERROR: `Signature is invalid for this message: ${signatureType}`,
16
+ failedFuncName: checkPowSignature.name,
17
+ address,
18
+ message,
19
+ signature,
20
+ signatureType
21
+ }
22
+ });
23
+ }
24
+ };
25
+ export {
26
+ checkPowSignature,
27
+ validateSolution
23
28
  };
24
- //# sourceMappingURL=powTasksUtils.js.map
@@ -1,36 +1,60 @@
1
- import { ProsopoEnvError, getLogger, parseLogLevel, } from "@prosopo/common";
1
+ import { getLogger, parseLogLevel, ProsopoEnvError } from "@prosopo/common";
2
2
  import { ClientTaskManager } from "./client/clientTasks.js";
3
3
  import { DatasetManager } from "./dataset/datasetTasks.js";
4
4
  import { FrictionlessManager } from "./frictionless/frictionlessTasks.js";
5
5
  import { ImgCaptchaManager } from "./imgCaptcha/imgCaptchaTasks.js";
6
6
  import { PowCaptchaManager } from "./powCaptcha/powTasks.js";
7
- export class Tasks {
8
- constructor(env, logger) {
9
- this.config = env.config;
10
- this.db = env.getDb();
11
- this.captchaConfig = env.config.captchas;
12
- this.logger =
13
- logger || getLogger(parseLogLevel(env.config.logLevel), "Tasks");
14
- if (!env.pair) {
15
- throw new ProsopoEnvError("DEVELOPER.MISSING_PROVIDER_PAIR", {
16
- context: { failedFuncName: "Tasks.constructor" },
17
- });
18
- }
19
- this.pair = env.pair;
20
- this.powCaptchaManager = new PowCaptchaManager(this.db, this.pair, this.logger);
21
- this.datasetManager = new DatasetManager(this.config, this.logger, this.captchaConfig, this.db);
22
- this.imgCaptchaManager = new ImgCaptchaManager(this.db, this.pair, this.config, this.logger);
23
- this.clientTaskManager = new ClientTaskManager(this.config, this.logger, this.db);
24
- this.frictionlessManager = new FrictionlessManager(this.db, this.pair, this.config, this.logger);
25
- }
26
- setLogger(logger) {
27
- this.logger = logger;
28
- this.powCaptchaManager.logger = logger;
29
- this.datasetManager.logger = logger;
30
- this.imgCaptchaManager.logger = logger;
31
- this.clientTaskManager.logger = logger;
32
- this.frictionlessManager.logger = logger;
33
- this.db.logger = logger;
7
+ class Tasks {
8
+ constructor(env, logger) {
9
+ this.config = env.config;
10
+ this.db = env.getDb();
11
+ this.captchaConfig = env.config.captchas;
12
+ this.logger = logger || getLogger(parseLogLevel(env.config.logLevel), "Tasks");
13
+ if (!env.pair) {
14
+ throw new ProsopoEnvError("DEVELOPER.MISSING_PROVIDER_PAIR", {
15
+ context: { failedFuncName: "Tasks.constructor" }
16
+ });
34
17
  }
18
+ this.pair = env.pair;
19
+ this.powCaptchaManager = new PowCaptchaManager(
20
+ this.db,
21
+ this.pair,
22
+ this.logger
23
+ );
24
+ this.datasetManager = new DatasetManager(
25
+ this.config,
26
+ this.logger,
27
+ this.captchaConfig,
28
+ this.db
29
+ );
30
+ this.imgCaptchaManager = new ImgCaptchaManager(
31
+ this.db,
32
+ this.pair,
33
+ this.config,
34
+ this.logger
35
+ );
36
+ this.clientTaskManager = new ClientTaskManager(
37
+ this.config,
38
+ this.logger,
39
+ this.db
40
+ );
41
+ this.frictionlessManager = new FrictionlessManager(
42
+ this.db,
43
+ this.pair,
44
+ this.config,
45
+ this.logger
46
+ );
47
+ }
48
+ setLogger(logger) {
49
+ this.logger = logger;
50
+ this.powCaptchaManager.logger = logger;
51
+ this.datasetManager.logger = logger;
52
+ this.imgCaptchaManager.logger = logger;
53
+ this.clientTaskManager.logger = logger;
54
+ this.frictionlessManager.logger = logger;
55
+ this.db.logger = logger;
56
+ }
35
57
  }
36
- //# sourceMappingURL=tasks.js.map
58
+ export {
59
+ Tasks
60
+ };
package/dist/util.js CHANGED
@@ -1,102 +1,112 @@
1
1
  import { hexToU8a } from "@polkadot/util/hex";
2
2
  import { isHex } from "@polkadot/util/is";
3
- import { ProsopoContractError, ProsopoEnvError, } from "@prosopo/common";
4
- import { ScheduledTaskStatus, } from "@prosopo/types";
3
+ import { ProsopoContractError, ProsopoEnvError } from "@prosopo/common";
4
+ import { ScheduledTaskStatus } from "@prosopo/types";
5
5
  import { at } from "@prosopo/util";
6
- import { decodeAddress, encodeAddress } from "@prosopo/util-crypto";
6
+ import { encodeAddress, decodeAddress } from "@prosopo/util-crypto";
7
7
  import { Address4, Address6 } from "ip-address";
8
- export function encodeStringAddress(address) {
9
- try {
10
- return encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address));
11
- }
12
- catch (err) {
13
- throw new ProsopoContractError("CONTRACT.INVALID_ADDRESS", {
14
- context: { address },
15
- });
16
- }
8
+ function encodeStringAddress(address) {
9
+ try {
10
+ return encodeAddress(
11
+ isHex(address) ? hexToU8a(address) : decodeAddress(address)
12
+ );
13
+ } catch (err) {
14
+ throw new ProsopoContractError("CONTRACT.INVALID_ADDRESS", {
15
+ context: { address }
16
+ });
17
+ }
17
18
  }
18
- export function shuffleArray(array) {
19
- for (let arrayIndex = array.length - 1; arrayIndex > 0; arrayIndex--) {
20
- const randIndex = Math.floor(Math.random() * (arrayIndex + 1));
21
- const tmp = at(array, randIndex);
22
- array[randIndex] = at(array, arrayIndex);
23
- array[arrayIndex] = tmp;
24
- }
25
- return array;
19
+ function shuffleArray(array) {
20
+ for (let arrayIndex = array.length - 1; arrayIndex > 0; arrayIndex--) {
21
+ const randIndex = Math.floor(Math.random() * (arrayIndex + 1));
22
+ const tmp = at(array, randIndex);
23
+ array[randIndex] = at(array, arrayIndex);
24
+ array[arrayIndex] = tmp;
25
+ }
26
+ return array;
26
27
  }
27
- export async function checkIfTaskIsRunning(taskName, db) {
28
- const runningTask = await db.getLastScheduledTaskStatus(taskName, ScheduledTaskStatus.Running);
29
- const twoMinutesAgo = new Date().getTime() - 1000 * 60 * 2;
30
- if (runningTask && runningTask.datetime > twoMinutesAgo) {
31
- const completedTask = await db.getScheduledTaskStatus(runningTask._id, ScheduledTaskStatus.Completed);
32
- return !completedTask;
33
- }
34
- return false;
28
+ async function checkIfTaskIsRunning(taskName, db) {
29
+ const runningTask = await db.getLastScheduledTaskStatus(
30
+ taskName,
31
+ ScheduledTaskStatus.Running
32
+ );
33
+ const twoMinutesAgo = (/* @__PURE__ */ new Date()).getTime() - 1e3 * 60 * 2;
34
+ if (runningTask && runningTask.datetime > twoMinutesAgo) {
35
+ const completedTask = await db.getScheduledTaskStatus(
36
+ runningTask._id,
37
+ ScheduledTaskStatus.Completed
38
+ );
39
+ return !completedTask;
40
+ }
41
+ return false;
35
42
  }
36
- export const getIPAddress = (ipAddressString) => {
43
+ const getIPAddress = (ipAddressString) => {
44
+ try {
37
45
  try {
38
- try {
39
- return new Address4(ipAddressString);
40
- }
41
- catch (e) {
42
- return new Address6(ipAddressString);
43
- }
44
- }
45
- catch (e) {
46
- throw new ProsopoEnvError("API.INVALID_IP");
46
+ return new Address4(ipAddressString);
47
+ } catch (e) {
48
+ return new Address6(ipAddressString);
47
49
  }
50
+ } catch (e) {
51
+ throw new ProsopoEnvError("API.INVALID_IP");
52
+ }
48
53
  };
49
- export const getIPAddressFromBigInt = (ipAddressBigInt) => {
50
- try {
51
- if (ipAddressBigInt > 4228250626n) {
52
- return Address6.fromBigInt(BigInt(ipAddressBigInt));
53
- }
54
- return Address4.fromBigInt(BigInt(ipAddressBigInt));
55
- }
56
- catch (e) {
57
- throw new ProsopoEnvError("API.INVALID_IP");
54
+ const getIPAddressFromBigInt = (ipAddressBigInt) => {
55
+ try {
56
+ if (ipAddressBigInt > 4228250626n) {
57
+ return Address6.fromBigInt(BigInt(ipAddressBigInt));
58
58
  }
59
+ return Address4.fromBigInt(BigInt(ipAddressBigInt));
60
+ } catch (e) {
61
+ throw new ProsopoEnvError("API.INVALID_IP");
62
+ }
59
63
  };
60
- export const validateIpAddress = (ip, challengeRecordIpAddress, logger) => {
61
- if (!ip) {
62
- return { isValid: true };
63
- }
64
- let ipV4orV6Address;
65
- try {
66
- ipV4orV6Address = getIPAddress(ip);
67
- logger.info(() => ({ data: { ipV4orV6Address } }));
68
- }
69
- catch (e) {
70
- const errorMessage = `Invalid IP address: ${ip}`;
71
- logger.info(() => ({ msg: errorMessage }));
72
- return { isValid: false, errorMessage };
73
- }
74
- let challengeIpV4orV6Address = getIPAddressFromBigInt(challengeRecordIpAddress);
75
- ipV4orV6Address =
76
- "address4" in ipV4orV6Address && ipV4orV6Address.address4
77
- ? ipV4orV6Address.address4
78
- : ipV4orV6Address;
79
- challengeIpV4orV6Address =
80
- "address4" in challengeIpV4orV6Address && challengeIpV4orV6Address.address4
81
- ? challengeIpV4orV6Address.address4
82
- : challengeIpV4orV6Address;
83
- if (ipV4orV6Address.v4 && !challengeIpV4orV6Address.v4) {
84
- challengeIpV4orV6Address = new Address4(challengeIpV4orV6Address.to4().correctForm());
85
- }
86
- if (!ipV4orV6Address.v4 && challengeIpV4orV6Address.v4) {
87
- ipV4orV6Address = new Address6(ipV4orV6Address.to4().correctForm());
88
- }
89
- if (challengeIpV4orV6Address.bigInt() - ipV4orV6Address.bigInt() !== 0n) {
90
- const errorMessage = `IP address mismatch: ${challengeIpV4orV6Address.address} !== ${ipV4orV6Address.address}`;
91
- logger.info(() => ({
92
- msg: errorMessage,
93
- data: {
94
- challengeIp: challengeIpV4orV6Address.address,
95
- providedIp: ipV4orV6Address.address,
96
- },
97
- }));
98
- return { isValid: false, errorMessage };
99
- }
64
+ const validateIpAddress = (ip, challengeRecordIpAddress, logger) => {
65
+ if (!ip) {
100
66
  return { isValid: true };
67
+ }
68
+ let ipV4orV6Address;
69
+ try {
70
+ ipV4orV6Address = getIPAddress(ip);
71
+ logger.info(() => ({ data: { ipV4orV6Address } }));
72
+ } catch (e) {
73
+ const errorMessage = `Invalid IP address: ${ip}`;
74
+ logger.info(() => ({ msg: errorMessage }));
75
+ return { isValid: false, errorMessage };
76
+ }
77
+ let challengeIpV4orV6Address = getIPAddressFromBigInt(
78
+ challengeRecordIpAddress
79
+ );
80
+ ipV4orV6Address = "address4" in ipV4orV6Address && ipV4orV6Address.address4 ? ipV4orV6Address.address4 : ipV4orV6Address;
81
+ challengeIpV4orV6Address = "address4" in challengeIpV4orV6Address && challengeIpV4orV6Address.address4 ? challengeIpV4orV6Address.address4 : challengeIpV4orV6Address;
82
+ if (ipV4orV6Address.v4 && !challengeIpV4orV6Address.v4) {
83
+ challengeIpV4orV6Address = new Address4(
84
+ challengeIpV4orV6Address.to4().correctForm()
85
+ );
86
+ }
87
+ if (!ipV4orV6Address.v4 && challengeIpV4orV6Address.v4) {
88
+ ipV4orV6Address = new Address6(
89
+ ipV4orV6Address.to4().correctForm()
90
+ );
91
+ }
92
+ if (challengeIpV4orV6Address.bigInt() - ipV4orV6Address.bigInt() !== 0n) {
93
+ const errorMessage = `IP address mismatch: ${challengeIpV4orV6Address.address} !== ${ipV4orV6Address.address}`;
94
+ logger.info(() => ({
95
+ msg: errorMessage,
96
+ data: {
97
+ challengeIp: challengeIpV4orV6Address.address,
98
+ providedIp: ipV4orV6Address.address
99
+ }
100
+ }));
101
+ return { isValid: false, errorMessage };
102
+ }
103
+ return { isValid: true };
104
+ };
105
+ export {
106
+ checkIfTaskIsRunning,
107
+ encodeStringAddress,
108
+ getIPAddress,
109
+ getIPAddressFromBigInt,
110
+ shuffleArray,
111
+ validateIpAddress
101
112
  };
102
- //# sourceMappingURL=util.js.map