@prosopo/procaptcha 1.0.2 → 2.0.1

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 (42) hide show
  1. package/dist/cjs/account/dist/extension/ExtensionWeb2.cjs +21 -28
  2. package/dist/cjs/account/dist/extension/ExtensionWeb3.cjs +5 -3
  3. package/dist/cjs/detector/src/index.cjs +4586 -0
  4. package/dist/cjs/modules/Manager.cjs +83 -168
  5. package/dist/cjs/modules/ProsopoCaptchaApi.cjs +34 -49
  6. package/dist/cjs/modules/collector.cjs +32 -8
  7. package/dist/cjs/modules/storage.cjs +8 -3
  8. package/dist/index.d.ts +2 -2
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +2 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/modules/Manager.d.ts +1 -2
  13. package/dist/modules/Manager.d.ts.map +1 -1
  14. package/dist/modules/Manager.js +92 -168
  15. package/dist/modules/Manager.js.map +1 -1
  16. package/dist/modules/ProsopoCaptchaApi.d.ts +7 -10
  17. package/dist/modules/ProsopoCaptchaApi.d.ts.map +1 -1
  18. package/dist/modules/ProsopoCaptchaApi.js +28 -48
  19. package/dist/modules/ProsopoCaptchaApi.js.map +1 -1
  20. package/dist/modules/collector.d.ts +1 -1
  21. package/dist/modules/collector.d.ts.map +1 -1
  22. package/dist/modules/collector.js +8 -8
  23. package/dist/modules/collector.js.map +1 -1
  24. package/dist/modules/index.d.ts +3 -3
  25. package/dist/modules/index.d.ts.map +1 -1
  26. package/dist/modules/index.js +3 -3
  27. package/dist/modules/index.js.map +1 -1
  28. package/dist/modules/storage.d.ts +1 -1
  29. package/dist/modules/storage.d.ts.map +1 -1
  30. package/dist/modules/storage.js +5 -5
  31. package/dist/modules/storage.js.map +1 -1
  32. package/dist/tests/modules/storage.test.js +15 -11
  33. package/dist/tests/modules/storage.test.js.map +1 -1
  34. package/dist/utils/index.d.ts +1 -1
  35. package/dist/utils/index.d.ts.map +1 -1
  36. package/dist/utils/index.js +1 -1
  37. package/dist/utils/index.js.map +1 -1
  38. package/dist/utils/utils.d.ts.map +1 -1
  39. package/dist/utils/utils.js.map +1 -1
  40. package/package.json +77 -85
  41. package/vite.cjs.config.ts +3 -3
  42. package/vite.test.config.ts +15 -15
@@ -1,17 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const types = require("@prosopo/types");
4
- const Api = require("@polkadot/api/promise/Api");
3
+ const utilCrypto = require("@polkadot/util-crypto");
4
+ const random = require("@polkadot/util-crypto/random");
5
5
  require("../account/dist/index.cjs");
6
- const keyring = require("@polkadot/keyring");
7
- const contract = require("@prosopo/contract");
8
- const common = require("@prosopo/common");
9
6
  const api = require("@prosopo/api");
10
- const ws = require("@polkadot/rpc-provider/ws");
11
- const contractInfo = require("@prosopo/captcha-contract/contract-info");
12
- const util = require("@prosopo/util");
7
+ const common = require("@prosopo/common");
8
+ const loadBalancer = require("@prosopo/load-balancer");
13
9
  const procaptchaCommon = require("@prosopo/procaptcha-common");
14
- const random = require("@polkadot/util-crypto/random");
10
+ const types = require("@prosopo/types");
11
+ const util = require("@prosopo/util");
15
12
  const utils = require("../utils/utils.cjs");
16
13
  const ProsopoCaptchaApi = require("./ProsopoCaptchaApi.cjs");
17
14
  const storage = require("./storage.cjs");
@@ -35,11 +32,30 @@ const getNetwork = (config) => {
35
32
  const network = config.networks[config.defaultNetwork];
36
33
  if (!network) {
37
34
  throw new common.ProsopoEnvError("DEVELOPER.NETWORK_NOT_FOUND", {
38
- context: { error: `No network found for environment ${config.defaultEnvironment}` }
35
+ context: {
36
+ error: `No network found for environment ${config.defaultEnvironment}`
37
+ }
39
38
  });
40
39
  }
41
40
  return network;
42
41
  };
42
+ const getRandomActiveProvider = (config) => {
43
+ const randomIntBetween = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
44
+ const PROVIDERS = loadBalancer.loadBalancer(config.defaultEnvironment);
45
+ const randomProvderObj = util.at(
46
+ PROVIDERS,
47
+ randomIntBetween(0, PROVIDERS.length - 1)
48
+ );
49
+ return {
50
+ providerAccount: randomProvderObj.address,
51
+ provider: {
52
+ url: randomProvderObj.url,
53
+ datasetId: randomProvderObj.datasetId,
54
+ datasetIdContent: randomProvderObj.datasetIdContent
55
+ },
56
+ blockNumber: 0
57
+ };
58
+ };
43
59
  function Manager(configOptional, state, onStateUpdate, callbacks) {
44
60
  const events = procaptchaCommon.getDefaultEvents(onStateUpdate, state, callbacks);
45
61
  const dispatchErrorEvent = (err) => {
@@ -75,87 +91,33 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
75
91
  if (state.isHuman) {
76
92
  return;
77
93
  }
94
+ await utilCrypto.cryptoWaitReady();
78
95
  resetState();
79
96
  updateState({ loading: true });
80
97
  const config = getConfig();
81
98
  updateState({ dappAccount: config.account.address });
82
99
  await utils.sleep(100);
83
100
  const account = await loadAccount();
84
- const contract$1 = await loadContract();
85
- let contractIsHuman = false;
86
- try {
87
- contractIsHuman = (await contract$1.query.dappOperatorIsHumanUser(account.account.address, config.solutionThreshold)).value.unwrap().unwrap();
88
- } catch (error) {
89
- console.warn(error);
90
- }
91
- if (contractIsHuman) {
92
- updateState({ isHuman: true, loading: false });
93
- events.onHuman(
94
- types.encodeProcaptchaOutput({
95
- [types.ApiParams.user]: account.account.address,
96
- [types.ApiParams.dapp]: getDappAccount(),
97
- [types.ApiParams.blockNumber]: getBlockNumber()
98
- })
99
- );
100
- setValidChallengeTimeout();
101
- return;
102
- }
103
- const procaptchaStorage = storage.getProcaptchaStorage();
104
- let providerApi;
105
- if (procaptchaStorage.providerUrl && procaptchaStorage.blockNumber) {
106
- providerApi = await loadProviderApi(procaptchaStorage.providerUrl);
107
- try {
108
- const extension = getExtension(account);
109
- if (!extension || !extension.signer || !extension.signer.signRaw) {
110
- throw new common.ProsopoEnvError("ACCOUNT.NO_POLKADOT_EXTENSION");
111
- }
112
- const signRaw = extension.signer.signRaw;
113
- const { signature } = await signRaw({
114
- address: account.account.address,
115
- data: procaptchaStorage.blockNumber.toString(),
116
- type: "bytes"
117
- });
118
- const token = types.encodeProcaptchaOutput({
119
- [types.ApiParams.user]: account.account.address,
120
- [types.ApiParams.dapp]: getDappAccount(),
121
- [types.ApiParams.blockNumber]: procaptchaStorage.blockNumber
122
- });
123
- const verifyDappUserResponse = await providerApi.verifyUser(
124
- token,
125
- signature,
126
- configOptional.captchas.image.cachedTimeout
127
- );
128
- if (verifyDappUserResponse.verified) {
129
- updateState({ isHuman: true, loading: false });
130
- const output = {
131
- [types.ApiParams.providerUrl]: procaptchaStorage.providerUrl,
132
- [types.ApiParams.user]: account.account.address,
133
- [types.ApiParams.dapp]: getDappAccount(),
134
- [types.ApiParams.commitmentId]: util.hashToHex(verifyDappUserResponse.commitmentId),
135
- [types.ApiParams.blockNumber]: verifyDappUserResponse.blockNumber
136
- };
137
- events.onHuman(types.encodeProcaptchaOutput(output));
138
- setValidChallengeTimeout();
139
- return;
140
- }
141
- } catch (err) {
142
- console.error("Error contacting provider from storage", procaptchaStorage.providerUrl);
143
- }
144
- }
145
- const getRandomProviderResponse = await contract.wrapQuery(
146
- contract$1.query.getRandomActiveProvider,
147
- contract$1.query
148
- )(account.account.address, getDappAccount());
149
- const blockNumber = parseInt(getRandomProviderResponse.blockNumber.toString());
150
- const providerUrl = common.trimProviderUrl(getRandomProviderResponse.provider.url.toString());
151
- providerApi = await loadProviderApi(providerUrl);
152
- const captchaApi = await loadCaptchaApi(contract$1, getRandomProviderResponse, providerApi);
101
+ const contract = getNetwork(config).contract.address;
102
+ const getRandomProviderResponse = getRandomActiveProvider(getConfig());
103
+ const blockNumber = getRandomProviderResponse.blockNumber;
104
+ const providerUrl = getRandomProviderResponse.provider.url;
105
+ const providerApi = await loadProviderApi(providerUrl);
106
+ const captchaApi = new ProsopoCaptchaApi.ProsopoCaptchaApi(
107
+ account.account.address,
108
+ contract,
109
+ getRandomProviderResponse,
110
+ providerApi,
111
+ config.web2,
112
+ config.account.address || ""
113
+ );
114
+ updateState({ captchaApi });
153
115
  const challenge = await captchaApi.getCaptchaChallenge();
154
116
  if (challenge.captchas.length <= 0) {
155
117
  throw new common.ProsopoDatasetError("DEVELOPER.PROVIDER_NO_CAPTCHA");
156
118
  }
157
119
  const timeMillis = challenge.captchas.map(
158
- (captcha) => captcha.captcha.timeLimitMs || config.captchas.image.challengeTimeout
120
+ (captcha) => captcha.timeLimitMs || config.captchas.image.challengeTimeout
159
121
  ).reduce((a, b) => a + b);
160
122
  const timeout = setTimeout(() => {
161
123
  events.onChallengeExpired();
@@ -186,8 +148,8 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
186
148
  (captcha, index) => {
187
149
  const solution = util.at(state.solutions, index);
188
150
  return {
189
- captchaId: captcha.captcha.captchaId,
190
- captchaContentId: captcha.captcha.captchaContentId,
151
+ captchaId: captcha.captchaId,
152
+ captchaContentId: captcha.captchaContentId,
191
153
  salt,
192
154
  solution
193
155
  };
@@ -197,18 +159,24 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
197
159
  const blockNumber = getBlockNumber();
198
160
  const signer = getExtension(account).signer;
199
161
  const first = util.at(challenge.captchas, 0);
200
- if (!first.captcha.datasetId) {
162
+ if (!first.datasetId) {
201
163
  throw new common.ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_ID", {
202
164
  context: { error: "No datasetId set for challenge" }
203
165
  });
204
166
  }
205
- const captchaApi = getCaptchaApi();
167
+ const captchaApi = state.captchaApi;
168
+ if (!captchaApi) {
169
+ throw new common.ProsopoError("CAPTCHA.INVALID_TOKEN", {
170
+ context: { error: "No Captcha API found in state" }
171
+ });
172
+ }
206
173
  const submission = await captchaApi.submitCaptchaSolution(
207
174
  signer,
208
175
  challenge.requestHash,
209
- first.captcha.datasetId,
210
176
  captchaSolution,
211
- salt
177
+ salt,
178
+ challenge.timestamp,
179
+ challenge.signature.provider.timestamp
212
180
  );
213
181
  const isHuman = submission[0].verified;
214
182
  if (!isHuman) {
@@ -220,15 +188,25 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
220
188
  loading: false
221
189
  });
222
190
  if (state.isHuman) {
223
- const providerUrl = common.trimProviderUrl(captchaApi.provider.provider.url.toString());
224
- storage.setProcaptchaStorage({ ...storage.getProcaptchaStorage(), providerUrl, blockNumber });
191
+ const providerUrl = captchaApi.provider.provider.url;
192
+ storage.setProcaptchaStorage({
193
+ ...storage.getProcaptchaStorage(),
194
+ providerUrl,
195
+ blockNumber
196
+ });
225
197
  events.onHuman(
226
198
  types.encodeProcaptchaOutput({
227
199
  [types.ApiParams.providerUrl]: providerUrl,
228
200
  [types.ApiParams.user]: account.account.address,
229
201
  [types.ApiParams.dapp]: getDappAccount(),
230
202
  [types.ApiParams.commitmentId]: util.hashToHex(submission[1]),
231
- [types.ApiParams.blockNumber]: blockNumber
203
+ [types.ApiParams.blockNumber]: blockNumber,
204
+ [types.ApiParams.timestamp]: challenge.timestamp,
205
+ [types.ApiParams.signature]: {
206
+ [types.ApiParams.provider]: {
207
+ [types.ApiParams.timestamp]: challenge.signature.provider.timestamp
208
+ }
209
+ }
232
210
  })
233
211
  );
234
212
  setValidChallengeTimeout();
@@ -248,7 +226,9 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
248
226
  }
249
227
  if (state.index >= state.challenge.captchas.length || state.index < 0) {
250
228
  throw new common.ProsopoError("CAPTCHA.NO_CAPTCHA", {
251
- context: { error: "Cannot select, index is out of range for this Captcha" }
229
+ context: {
230
+ error: "Cannot select, index is out of range for this Captcha"
231
+ }
252
232
  });
253
233
  }
254
234
  const index = state.index;
@@ -269,24 +249,13 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
269
249
  }
270
250
  if (state.index + 1 >= state.challenge.captchas.length) {
271
251
  throw new common.ProsopoError("CAPTCHA.NO_CAPTCHA", {
272
- context: { error: "Cannot select, index is out of range for this Captcha" }
252
+ context: {
253
+ error: "Cannot select, index is out of range for this Captcha"
254
+ }
273
255
  });
274
256
  }
275
257
  updateState({ index: state.index + 1 });
276
258
  };
277
- const loadCaptchaApi = async (contract2, provider, providerApi) => {
278
- const config = getConfig();
279
- const captchaApi = new ProsopoCaptchaApi.ProsopoCaptchaApi(
280
- getAccount().account.address,
281
- contract2,
282
- provider,
283
- providerApi,
284
- config.web2,
285
- getDappAccount()
286
- );
287
- updateState({ captchaApi });
288
- return getCaptchaApi();
289
- };
290
259
  const loadProviderApi = async (providerUrl) => {
291
260
  const config = getConfig();
292
261
  const network = getNetwork(config);
@@ -311,14 +280,6 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
311
280
  clearTimeout();
312
281
  updateState(defaultState());
313
282
  };
314
- const getCaptchaApi = () => {
315
- if (!state.captchaApi) {
316
- throw new common.ProsopoEnvError("API.UNKNOWN", {
317
- context: { error: "Captcha api not set", state }
318
- });
319
- }
320
- return state.captchaApi;
321
- };
322
283
  const loadAccount = async () => {
323
284
  const config = getConfig();
324
285
  if (!config.web2 && !config.userAccountAddress) {
@@ -334,7 +295,9 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
334
295
  };
335
296
  const getAccount = () => {
336
297
  if (!state.account) {
337
- throw new common.ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", { context: { error: "Account not loaded" } });
298
+ throw new common.ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", {
299
+ context: { error: "Account not loaded" }
300
+ });
338
301
  }
339
302
  const account = state.account;
340
303
  return account;
@@ -347,72 +310,24 @@ function Manager(configOptional, state, onStateUpdate, callbacks) {
347
310
  return dappAccount;
348
311
  };
349
312
  const getBlockNumber = () => {
350
- if (!state.blockNumber) {
351
- throw new common.ProsopoContractError("CAPTCHA.INVALID_BLOCK_NO", { context: { error: "Block number not found" } });
352
- }
353
- const blockNumber = state.blockNumber;
313
+ const blockNumber = state.blockNumber || 0;
354
314
  return blockNumber;
355
315
  };
356
- const getExtension = (account) => {
357
- account = account || getAccount();
316
+ const getExtension = (possiblyAccount) => {
317
+ const account = possiblyAccount || getAccount();
358
318
  if (!account.extension) {
359
- throw new common.ProsopoEnvError("ACCOUNT.NO_POLKADOT_EXTENSION", { context: { error: "Extension not loaded" } });
319
+ throw new common.ProsopoEnvError("ACCOUNT.NO_POLKADOT_EXTENSION", {
320
+ context: { error: "Extension not loaded" }
321
+ });
360
322
  }
361
323
  return account.extension;
362
324
  };
363
- const loadContract = async () => {
364
- const config = getConfig();
365
- const network = getNetwork(config);
366
- const api2 = await Api.ApiPromise.create({
367
- provider: new ws.WsProvider(network.endpoint),
368
- initWasm: false,
369
- noInitWarn: true
370
- });
371
- const type = "sr25519";
372
- const keyring$1 = new keyring.Keyring({ type, ss58Format: api2.registry.chainSS58 });
373
- return new contract.ProsopoCaptchaContract(
374
- api2,
375
- JSON.parse(contractInfo.ContractAbi),
376
- network.contract.address,
377
- "prosopo",
378
- 0,
379
- keyring$1.addFromAddress(getAccount().account.address)
380
- );
381
- };
382
- const exportData = async (events2) => {
383
- const procaptchaStorage = storage.getProcaptchaStorage();
384
- const providerUrlFromStorage = procaptchaStorage.providerUrl;
385
- let providerApi;
386
- if (providerUrlFromStorage) {
387
- providerApi = await loadProviderApi(providerUrlFromStorage);
388
- } else {
389
- const contract$1 = await loadContract();
390
- const getRandomProviderResponse = await contract.wrapQuery(
391
- contract$1.query.getRandomActiveProvider,
392
- contract$1.query
393
- )(getAccount().account.address, getDappAccount());
394
- const providerUrl2 = common.trimProviderUrl(getRandomProviderResponse.provider.url.toString());
395
- providerApi = await loadProviderApi(providerUrl2);
396
- }
397
- const providerUrl = storage.getProcaptchaStorage().providerUrl || state.captchaApi?.provider.provider.url.toString();
398
- if (!providerUrl) {
399
- return;
400
- }
401
- let account = "";
402
- try {
403
- account = getAccount().account.address;
404
- } catch (e) {
405
- console.error(e);
406
- }
407
- await providerApi.submitUserEvents(events2, account);
408
- };
409
325
  return {
410
326
  start,
411
327
  cancel,
412
328
  submit,
413
329
  select,
414
- nextRound,
415
- exportData
330
+ nextRound
416
331
  };
417
332
  }
418
333
  exports.Manager = Manager;
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
- const datasets = require("@prosopo/datasets");
4
- const common = require("@prosopo/common");
5
- const util = require("@prosopo/util");
6
3
  const string = require("@polkadot/util/string");
4
+ const common = require("@prosopo/common");
5
+ const datasets = require("@prosopo/datasets");
7
6
  class ProsopoCaptchaApi {
8
7
  constructor(userAccount, contract, provider, providerApi, web2, dappAccount) {
9
8
  this.userAccount = userAccount;
@@ -18,47 +17,43 @@ class ProsopoCaptchaApi {
18
17
  }
19
18
  async getCaptchaChallenge() {
20
19
  try {
21
- const captchaChallenge = await this.providerApi.getCaptchaChallenge(this.userAccount, this.provider);
22
- this.verifyCaptchaChallengeContent(this.provider, captchaChallenge);
23
- captchaChallenge.captchas.forEach((captcha) => {
24
- captcha.captcha.items.forEach((item) => {
20
+ const captchaChallenge = await this.providerApi.getCaptchaChallenge(
21
+ this.userAccount,
22
+ this.provider
23
+ );
24
+ for (const captcha of captchaChallenge.captchas) {
25
+ for (const item of captcha.items) {
25
26
  if (item.data) {
26
27
  item.data = item.data.replace(/^http(s)*:\/\//, "//");
27
28
  }
28
- });
29
- });
29
+ }
30
+ }
30
31
  return captchaChallenge;
31
32
  } catch (error) {
32
- throw new common.ProsopoEnvError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", { context: { error } });
33
- }
34
- }
35
- verifyCaptchaChallengeContent(provider, captchaChallenge) {
36
- const first = util.at(captchaChallenge.captchas, 0);
37
- const proofLength = first.proof.length;
38
- const last = util.at(first.proof, proofLength - 1);
39
- if (provider.provider.datasetIdContent.toString() !== util.at(last, 0)) {
40
- throw new common.ProsopoEnvError("CAPTCHA.INVALID_DATASET_CONTENT_ID");
41
- }
42
- for (const captchaWithProof of captchaChallenge.captchas) {
43
- if (!verifyCaptchaData(captchaWithProof)) {
44
- throw new common.ProsopoEnvError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE");
45
- }
46
- if (!datasets.verifyProof(captchaWithProof.captcha.captchaContentId, captchaWithProof.proof)) {
47
- throw new common.ProsopoEnvError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE");
48
- }
33
+ throw new common.ProsopoEnvError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
34
+ context: { error }
35
+ });
49
36
  }
50
- return;
51
37
  }
52
- async submitCaptchaSolution(signer, requestHash, datasetId, solutions, salt) {
38
+ async submitCaptchaSolution(signer, requestHash, solutions, salt, timestamp, providerTimestampSignature) {
53
39
  const tree = new datasets.CaptchaMerkleTree();
54
- const captchasHashed = solutions.map((captcha) => datasets.computeCaptchaSolutionHash(captcha));
40
+ const captchasHashed = solutions.map(
41
+ (captcha) => datasets.computeCaptchaSolutionHash(captcha)
42
+ );
55
43
  tree.build(captchasHashed);
44
+ if (!tree.root) {
45
+ throw new common.ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
46
+ context: { error: "Merkle tree root is undefined" }
47
+ });
48
+ }
56
49
  const commitmentId = tree.root.hash;
57
50
  const tx = void 0;
58
- let signature = void 0;
51
+ let userRequestHashSignature = void 0;
59
52
  if (!signer || !signer.signRaw) {
60
53
  throw new common.ProsopoEnvError("GENERAL.CANT_FIND_KEYRINGPAIR", {
61
- context: { error: "Signer is not defined, cannot sign message to prove account ownership" }
54
+ context: {
55
+ error: "Signer is not defined, cannot sign message to prove account ownership"
56
+ }
62
57
  });
63
58
  }
64
59
  let result;
@@ -67,34 +62,24 @@ class ProsopoCaptchaApi {
67
62
  data: string.stringToHex(requestHash),
68
63
  type: "bytes"
69
64
  });
70
- signature = signed.signature;
65
+ userRequestHashSignature = signed.signature;
71
66
  try {
72
67
  result = await this.providerApi.submitCaptchaSolution(
73
68
  solutions,
74
69
  requestHash,
75
- this.contract.pair.address,
70
+ this.userAccount,
76
71
  salt,
77
- signature
72
+ timestamp,
73
+ providerTimestampSignature,
74
+ userRequestHashSignature
78
75
  );
79
76
  } catch (error) {
80
- throw new common.ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", { context: { error } });
77
+ throw new common.ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
78
+ context: { error }
79
+ });
81
80
  }
82
81
  return [result, commitmentId, tx];
83
82
  }
84
83
  }
85
- async function verifyCaptchaData(captchaWithProof) {
86
- const captcha = captchaWithProof.captcha;
87
- const proof = captchaWithProof.proof;
88
- if (!(await Promise.all(captcha.items.map(async (item) => (await datasets.computeItemHash(item)).hash === item.hash))).every(
89
- (hash) => hash === true
90
- )) {
91
- return false;
92
- }
93
- const captchaHash = datasets.computeCaptchaHash(captcha, false, false, false);
94
- if (captchaHash !== captcha.captchaContentId) {
95
- return false;
96
- }
97
- return util.at(proof, 0).indexOf(captchaHash) !== -1;
98
- }
99
84
  exports.ProsopoCaptchaApi = ProsopoCaptchaApi;
100
85
  exports.default = ProsopoCaptchaApi;
@@ -29,19 +29,43 @@ const logKeyboardEvent = (event, setKeyboardEvent) => {
29
29
  };
30
30
  const logTouchEvent = (event, setTouchEvent) => {
31
31
  for (const touch of Array.from(event.touches)) {
32
- storeLog({ x: touch.clientX, y: touch.clientY, timestamp: event.timeStamp }, setTouchEvent);
32
+ storeLog(
33
+ { x: touch.clientX, y: touch.clientY, timestamp: event.timeStamp },
34
+ setTouchEvent
35
+ );
33
36
  }
34
37
  };
35
38
  const startCollector = (setStoredMouseEvents, setStoredTouchEvents, setStoredKeyboardEvents, rootElement) => {
36
39
  const form = findContainingForm(rootElement);
37
40
  if (form) {
38
- form.addEventListener("mousemove", (e) => logMouseEvent(e, setStoredMouseEvents));
39
- form.addEventListener("keydown", (e) => logKeyboardEvent(e, setStoredKeyboardEvents));
40
- form.addEventListener("keyup", (e) => logKeyboardEvent(e, setStoredKeyboardEvents));
41
- form.addEventListener("touchstart", (e) => logTouchEvent(e, setStoredTouchEvents));
42
- form.addEventListener("touchend", (e) => logTouchEvent(e, setStoredTouchEvents));
43
- form.addEventListener("touchcancel", (e) => logTouchEvent(e, setStoredTouchEvents));
44
- form.addEventListener("touchmove", (e) => logTouchEvent(e, setStoredTouchEvents));
41
+ form.addEventListener(
42
+ "mousemove",
43
+ (e) => logMouseEvent(e, setStoredMouseEvents)
44
+ );
45
+ form.addEventListener(
46
+ "keydown",
47
+ (e) => logKeyboardEvent(e, setStoredKeyboardEvents)
48
+ );
49
+ form.addEventListener(
50
+ "keyup",
51
+ (e) => logKeyboardEvent(e, setStoredKeyboardEvents)
52
+ );
53
+ form.addEventListener(
54
+ "touchstart",
55
+ (e) => logTouchEvent(e, setStoredTouchEvents)
56
+ );
57
+ form.addEventListener(
58
+ "touchend",
59
+ (e) => logTouchEvent(e, setStoredTouchEvents)
60
+ );
61
+ form.addEventListener(
62
+ "touchcancel",
63
+ (e) => logTouchEvent(e, setStoredTouchEvents)
64
+ );
65
+ form.addEventListener(
66
+ "touchmove",
67
+ (e) => logTouchEvent(e, setStoredTouchEvents)
68
+ );
45
69
  }
46
70
  };
47
71
  const findContainingForm = (element) => {
@@ -1,15 +1,20 @@
1
1
  "use strict";
2
- const types = require("@prosopo/types");
3
2
  const util = require("@polkadot/util");
4
3
  const string = require("@polkadot/util/string");
4
+ const types = require("@prosopo/types");
5
5
  const PROCAPTCHA_STORAGE_KEY = "@prosopo/procaptcha";
6
6
  function getProcaptchaStorage() {
7
7
  return types.ProsopoLocalStorageSchema.parse(
8
- JSON.parse(util.hexToString(localStorage.getItem(PROCAPTCHA_STORAGE_KEY) || "0x7b7d"))
8
+ JSON.parse(
9
+ util.hexToString(localStorage.getItem(PROCAPTCHA_STORAGE_KEY) || "0x7b7d")
10
+ )
9
11
  );
10
12
  }
11
13
  function setProcaptchaStorage(storage2) {
12
- localStorage.setItem(PROCAPTCHA_STORAGE_KEY, string.stringToHex(JSON.stringify(types.ProsopoLocalStorageSchema.parse(storage2))));
14
+ localStorage.setItem(
15
+ PROCAPTCHA_STORAGE_KEY,
16
+ string.stringToHex(JSON.stringify(types.ProsopoLocalStorageSchema.parse(storage2)))
17
+ );
13
18
  }
14
19
  function setAccount(account) {
15
20
  setProcaptchaStorage({ ...getProcaptchaStorage(), account });
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from './modules/index.js';
2
- export * from './utils/index.js';
1
+ export * from "./modules/index.js";
2
+ export * from "./utils/index.js";
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export * from './modules/index.js';
2
- export * from './utils/index.js';
1
+ export * from "./modules/index.js";
2
+ export * from "./utils/index.js";
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
@@ -1,10 +1,9 @@
1
- import { ProcaptchaCallbacks, ProcaptchaClientConfigOutput, ProcaptchaState, ProcaptchaStateUpdateFn, StoredEvents } from '@prosopo/types';
1
+ import { type ProcaptchaCallbacks, type ProcaptchaClientConfigOutput, type ProcaptchaState, type ProcaptchaStateUpdateFn } from "@prosopo/types";
2
2
  export declare function Manager(configOptional: ProcaptchaClientConfigOutput, state: ProcaptchaState, onStateUpdate: ProcaptchaStateUpdateFn, callbacks: ProcaptchaCallbacks): {
3
3
  start: () => Promise<void>;
4
4
  cancel: () => Promise<void>;
5
5
  submit: () => Promise<void>;
6
6
  select: (hash: string) => void;
7
7
  nextRound: () => void;
8
- exportData: (events: StoredEvents) => Promise<void>;
9
8
  };
10
9
  //# sourceMappingURL=Manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Manager.d.ts","sourceRoot":"","sources":["../../src/modules/Manager.ts"],"names":[],"mappings":"AAaA,OAAO,EAMH,mBAAmB,EAEnB,4BAA4B,EAE5B,eAAe,EACf,uBAAuB,EACvB,YAAY,EAGf,MAAM,gBAAgB,CAAA;AAmDvB,wBAAgB,OAAO,CACnB,cAAc,EAAE,4BAA4B,EAC5C,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,uBAAuB,EACtC,SAAS,EAAE,mBAAmB;;;;mBAkSR,MAAM;;yBA0LM,YAAY;EAwCjD"}
1
+ {"version":3,"file":"Manager.d.ts","sourceRoot":"","sources":["../../src/modules/Manager.ts"],"names":[],"mappings":"AAyBA,OAAO,EAKL,KAAK,mBAAmB,EAExB,KAAK,4BAA4B,EAEjC,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAK7B,MAAM,gBAAgB,CAAC;AA8DxB,wBAAgB,OAAO,CACrB,cAAc,EAAE,4BAA4B,EAC5C,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,uBAAuB,EACtC,SAAS,EAAE,mBAAmB;;;;mBA4OR,MAAM;;EAiJ7B"}