@prosopo/procaptcha 2.1.4 → 2.1.6

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 (47) hide show
  1. package/dist/cjs/index.cjs +9 -0
  2. package/dist/cjs/modules/Manager.cjs +322 -0
  3. package/dist/cjs/modules/ProsopoCaptchaApi.cjs +72 -0
  4. package/dist/cjs/modules/collector.cjs +80 -0
  5. package/dist/cjs/modules/index.cjs +8 -0
  6. package/dist/cjs/modules/storage.cjs +31 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +2 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/modules/Manager.d.ts +10 -0
  12. package/dist/modules/Manager.d.ts.map +1 -0
  13. package/dist/modules/Manager.js +292 -0
  14. package/dist/modules/Manager.js.map +1 -0
  15. package/dist/modules/ProsopoCaptchaApi.d.ts +16 -0
  16. package/dist/modules/ProsopoCaptchaApi.d.ts.map +1 -0
  17. package/dist/modules/ProsopoCaptchaApi.js +60 -0
  18. package/dist/modules/ProsopoCaptchaApi.js.map +1 -0
  19. package/dist/modules/collector.d.ts +8 -0
  20. package/dist/modules/collector.d.ts.map +1 -0
  21. package/dist/modules/collector.js +54 -0
  22. package/dist/modules/collector.js.map +1 -0
  23. package/dist/modules/index.d.ts +4 -0
  24. package/dist/modules/index.d.ts.map +1 -0
  25. package/dist/modules/index.js +4 -0
  26. package/dist/modules/index.js.map +1 -0
  27. package/dist/modules/storage.d.ts +13 -0
  28. package/dist/modules/storage.d.ts.map +1 -0
  29. package/dist/modules/storage.js +23 -0
  30. package/dist/modules/storage.js.map +1 -0
  31. package/dist/tests/modules/storage.test.d.ts +2 -0
  32. package/dist/tests/modules/storage.test.d.ts.map +1 -0
  33. package/dist/tests/modules/storage.test.js +20 -0
  34. package/dist/tests/modules/storage.test.js.map +1 -0
  35. package/dist/tests/modules/storage.unit.test.d.ts +2 -0
  36. package/dist/tests/modules/storage.unit.test.d.ts.map +1 -0
  37. package/dist/tests/modules/storage.unit.test.js +22 -0
  38. package/dist/tests/modules/storage.unit.test.js.map +1 -0
  39. package/dist/utils/index.d.ts +2 -0
  40. package/dist/utils/index.d.ts.map +1 -0
  41. package/dist/utils/index.js +2 -0
  42. package/dist/utils/index.js.map +1 -0
  43. package/dist/utils/utils.d.ts +2 -0
  44. package/dist/utils/utils.d.ts.map +1 -0
  45. package/dist/utils/utils.js +4 -0
  46. package/dist/utils/utils.js.map +1 -0
  47. package/package.json +11 -11
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ require("./modules/index.cjs");
4
+ const Manager = require("./modules/Manager.cjs");
5
+ const ProsopoCaptchaApi = require("./modules/ProsopoCaptchaApi.cjs");
6
+ const collector = require("./modules/collector.cjs");
7
+ exports.Manager = Manager.Manager;
8
+ exports.ProsopoCaptchaApi = ProsopoCaptchaApi.ProsopoCaptchaApi;
9
+ exports.startCollector = collector.startCollector;
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utilCrypto = require("@polkadot/util-crypto");
4
+ const random = require("@polkadot/util-crypto/random");
5
+ const string = require("@polkadot/util/string");
6
+ const account = require("@prosopo/account");
7
+ const api = require("@prosopo/api");
8
+ const common = require("@prosopo/common");
9
+ const procaptchaCommon = require("@prosopo/procaptcha-common");
10
+ const types = require("@prosopo/types");
11
+ const util = require("@prosopo/util");
12
+ const ProsopoCaptchaApi = require("./ProsopoCaptchaApi.cjs");
13
+ const storage = require("./storage.cjs");
14
+ const defaultState = () => {
15
+ return {
16
+ // note order matters! see buildUpdateState. These fields are set in order, so disable modal first, then set loading to false, etc.
17
+ showModal: false,
18
+ loading: false,
19
+ index: 0,
20
+ challenge: void 0,
21
+ solutions: void 0,
22
+ isHuman: false,
23
+ captchaApi: void 0,
24
+ account: void 0
25
+ // don't handle timeout here, this should be handled by the state management
26
+ };
27
+ };
28
+ function Manager(configOptional, state, onStateUpdate, callbacks) {
29
+ const events = procaptchaCommon.getDefaultEvents(onStateUpdate, state, callbacks);
30
+ const updateState = procaptchaCommon.buildUpdateState(state, onStateUpdate);
31
+ const getConfig = () => {
32
+ const config = {
33
+ userAccountAddress: "",
34
+ ...configOptional
35
+ };
36
+ if (state.account) {
37
+ config.userAccountAddress = state.account.account.address;
38
+ }
39
+ return types.ProcaptchaConfigSchema.parse(config);
40
+ };
41
+ const start = async () => {
42
+ events.onOpen();
43
+ await procaptchaCommon.providerRetry(
44
+ async () => {
45
+ if (state.loading) {
46
+ return;
47
+ }
48
+ if (state.isHuman) {
49
+ return;
50
+ }
51
+ await utilCrypto.cryptoWaitReady();
52
+ resetState();
53
+ updateState({ loading: true });
54
+ updateState({
55
+ attemptCount: state.attemptCount ? state.attemptCount + 1 : 1
56
+ });
57
+ const config = getConfig();
58
+ updateState({ dappAccount: config.account.address });
59
+ await util.sleep(100);
60
+ const account2 = await loadAccount();
61
+ const getRandomProviderResponse = await procaptchaCommon.getRandomActiveProvider(
62
+ getConfig()
63
+ );
64
+ const providerUrl = getRandomProviderResponse.provider.url;
65
+ const providerApi = await loadProviderApi(providerUrl);
66
+ const captchaApi = new ProsopoCaptchaApi.ProsopoCaptchaApi(
67
+ account2.account.address,
68
+ getRandomProviderResponse,
69
+ providerApi,
70
+ config.web2,
71
+ config.account.address || ""
72
+ );
73
+ updateState({ captchaApi });
74
+ const challenge = await captchaApi.getCaptchaChallenge();
75
+ if (challenge.error) {
76
+ updateState({
77
+ loading: false,
78
+ error: challenge.error.message
79
+ });
80
+ } else {
81
+ if (challenge.captchas.length <= 0) {
82
+ throw new common.ProsopoDatasetError("DEVELOPER.PROVIDER_NO_CAPTCHA");
83
+ }
84
+ const timeMillis = challenge.captchas.map(
85
+ (captcha) => captcha.timeLimitMs || config.captchas.image.challengeTimeout
86
+ ).reduce((a, b) => a + b);
87
+ const timeout = setTimeout(() => {
88
+ events.onChallengeExpired();
89
+ updateState({ isHuman: false, showModal: false, loading: false });
90
+ }, timeMillis);
91
+ updateState({
92
+ index: 0,
93
+ solutions: challenge.captchas.map(() => []),
94
+ challenge,
95
+ showModal: true,
96
+ timeout
97
+ });
98
+ }
99
+ },
100
+ start,
101
+ resetState,
102
+ state.attemptCount,
103
+ 10
104
+ );
105
+ };
106
+ const submit = async () => {
107
+ await procaptchaCommon.providerRetry(
108
+ async () => {
109
+ clearTimeout();
110
+ if (!state.challenge) {
111
+ throw new common.ProsopoError("CAPTCHA.NO_CAPTCHA", {
112
+ context: { error: "Cannot submit, no Captcha found in state" }
113
+ });
114
+ }
115
+ updateState({ showModal: false });
116
+ const challenge = state.challenge;
117
+ const salt = random.randomAsHex();
118
+ const captchaSolution = state.challenge.captchas.map(
119
+ (captcha, index) => {
120
+ const solution = util.at(state.solutions, index);
121
+ return {
122
+ captchaId: captcha.captchaId,
123
+ captchaContentId: captcha.captchaContentId,
124
+ salt,
125
+ solution
126
+ };
127
+ }
128
+ );
129
+ const account2 = getAccount();
130
+ const signer = getExtension(account2).signer;
131
+ const first = util.at(challenge.captchas, 0);
132
+ if (!first.datasetId) {
133
+ throw new common.ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_ID", {
134
+ context: { error: "No datasetId set for challenge" }
135
+ });
136
+ }
137
+ const captchaApi = state.captchaApi;
138
+ if (!captchaApi) {
139
+ throw new common.ProsopoError("CAPTCHA.INVALID_TOKEN", {
140
+ context: { error: "No Captcha API found in state" }
141
+ });
142
+ }
143
+ if (!signer || !signer.signRaw) {
144
+ throw new common.ProsopoEnvError("GENERAL.CANT_FIND_KEYRINGPAIR", {
145
+ context: {
146
+ error: "Signer is not defined, cannot sign message to prove account ownership"
147
+ }
148
+ });
149
+ }
150
+ const userTimestampSignature = await signer.signRaw({
151
+ address: account2.account.address,
152
+ data: string.stringToHex(challenge[types.ApiParams.timestamp]),
153
+ type: "bytes"
154
+ });
155
+ const submission = await captchaApi.submitCaptchaSolution(
156
+ userTimestampSignature.signature,
157
+ challenge.requestHash,
158
+ captchaSolution,
159
+ challenge.timestamp,
160
+ challenge.signature.provider.requestHash
161
+ );
162
+ const isHuman = submission[0].verified;
163
+ updateState({
164
+ submission,
165
+ isHuman,
166
+ loading: false
167
+ });
168
+ if (state.isHuman) {
169
+ const providerUrl = captchaApi.provider.provider.url;
170
+ storage.setProcaptchaStorage({
171
+ ...storage.getProcaptchaStorage(),
172
+ providerUrl
173
+ });
174
+ events.onHuman(
175
+ types.encodeProcaptchaOutput({
176
+ [types.ApiParams.providerUrl]: providerUrl,
177
+ [types.ApiParams.user]: account2.account.address,
178
+ [types.ApiParams.dapp]: getDappAccount(),
179
+ [types.ApiParams.commitmentId]: util.hashToHex(submission[1]),
180
+ [types.ApiParams.timestamp]: challenge.timestamp,
181
+ [types.ApiParams.signature]: {
182
+ [types.ApiParams.provider]: {
183
+ [types.ApiParams.requestHash]: challenge.signature.provider.requestHash
184
+ },
185
+ [types.ApiParams.user]: {
186
+ [types.ApiParams.timestamp]: userTimestampSignature.signature
187
+ }
188
+ }
189
+ })
190
+ );
191
+ setValidChallengeTimeout();
192
+ } else {
193
+ events.onFailed();
194
+ }
195
+ },
196
+ start,
197
+ resetState,
198
+ state.attemptCount,
199
+ 10
200
+ );
201
+ };
202
+ const cancel = async () => {
203
+ clearTimeout();
204
+ resetState();
205
+ events.onClose();
206
+ };
207
+ const reload = async () => {
208
+ clearTimeout();
209
+ resetState();
210
+ events.onClose();
211
+ await start();
212
+ };
213
+ const select = (hash) => {
214
+ if (!state.challenge) {
215
+ throw new common.ProsopoError("CAPTCHA.NO_CAPTCHA", {
216
+ context: { error: "Cannot select, no Captcha found in state" }
217
+ });
218
+ }
219
+ if (state.index >= state.challenge.captchas.length || state.index < 0) {
220
+ throw new common.ProsopoError("CAPTCHA.NO_CAPTCHA", {
221
+ context: {
222
+ error: "Cannot select, index is out of range for this Captcha"
223
+ }
224
+ });
225
+ }
226
+ const index = state.index;
227
+ const solutions = state.solutions;
228
+ const solution = util.at(solutions, index);
229
+ if (solution.includes(hash)) {
230
+ solution.splice(solution.indexOf(hash), 1);
231
+ } else {
232
+ solution.push(hash);
233
+ }
234
+ updateState({ solutions });
235
+ };
236
+ const nextRound = () => {
237
+ if (!state.challenge) {
238
+ throw new common.ProsopoError("CAPTCHA.NO_CAPTCHA", {
239
+ context: { error: "Cannot select, no Captcha found in state" }
240
+ });
241
+ }
242
+ if (state.index + 1 >= state.challenge.captchas.length) {
243
+ throw new common.ProsopoError("CAPTCHA.NO_CAPTCHA", {
244
+ context: {
245
+ error: "Cannot select, index is out of range for this Captcha"
246
+ }
247
+ });
248
+ }
249
+ updateState({ index: state.index + 1 });
250
+ };
251
+ const loadProviderApi = async (providerUrl) => {
252
+ const config = getConfig();
253
+ if (!config.account.address) {
254
+ throw new common.ProsopoEnvError("GENERAL.SITE_KEY_MISSING");
255
+ }
256
+ return new api.ProviderApi(providerUrl, config.account.address);
257
+ };
258
+ const clearTimeout = () => {
259
+ window.clearTimeout(Number(state.timeout));
260
+ updateState({ timeout: void 0 });
261
+ };
262
+ const setValidChallengeTimeout = () => {
263
+ const timeMillis = configOptional.captchas.image.solutionTimeout;
264
+ const successfullChallengeTimeout = setTimeout(() => {
265
+ updateState({ isHuman: false });
266
+ events.onExpired();
267
+ }, timeMillis);
268
+ updateState({ successfullChallengeTimeout });
269
+ };
270
+ const resetState = () => {
271
+ clearTimeout();
272
+ updateState(defaultState());
273
+ events.onReset();
274
+ };
275
+ const loadAccount = async () => {
276
+ const config = getConfig();
277
+ if (!config.web2 && !config.userAccountAddress) {
278
+ throw new common.ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", {
279
+ context: { error: "Account address has not been set for web3 mode" }
280
+ });
281
+ }
282
+ const ext = config.web2 ? new account.ExtensionWeb2() : new account.ExtensionWeb3();
283
+ const account$1 = await ext.getAccount(config);
284
+ storage.setAccount(account$1.account.address);
285
+ updateState({ account: account$1 });
286
+ return getAccount();
287
+ };
288
+ const getAccount = () => {
289
+ if (!state.account) {
290
+ throw new common.ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", {
291
+ context: { error: "Account not loaded" }
292
+ });
293
+ }
294
+ const account2 = state.account;
295
+ return account2;
296
+ };
297
+ const getDappAccount = () => {
298
+ if (!state.dappAccount) {
299
+ throw new common.ProsopoEnvError("GENERAL.SITE_KEY_MISSING");
300
+ }
301
+ const dappAccount = state.dappAccount;
302
+ return dappAccount;
303
+ };
304
+ const getExtension = (possiblyAccount) => {
305
+ const account2 = possiblyAccount || getAccount();
306
+ if (!account2.extension) {
307
+ throw new common.ProsopoEnvError("ACCOUNT.NO_POLKADOT_EXTENSION", {
308
+ context: { error: "Extension not loaded" }
309
+ });
310
+ }
311
+ return account2.extension;
312
+ };
313
+ return {
314
+ start,
315
+ cancel,
316
+ submit,
317
+ select,
318
+ nextRound,
319
+ reload
320
+ };
321
+ }
322
+ exports.Manager = Manager;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const common = require("@prosopo/common");
4
+ const datasets = require("@prosopo/datasets");
5
+ const types = require("@prosopo/types");
6
+ class ProsopoCaptchaApi {
7
+ constructor(userAccount, provider, providerApi, web2, dappAccount) {
8
+ this.userAccount = userAccount;
9
+ this.provider = provider;
10
+ this.providerApi = providerApi;
11
+ this._web2 = web2;
12
+ this.dappAccount = dappAccount;
13
+ }
14
+ get web2() {
15
+ return this._web2;
16
+ }
17
+ async getCaptchaChallenge() {
18
+ try {
19
+ const captchaChallenge = await this.providerApi.getCaptchaChallenge(
20
+ this.userAccount,
21
+ this.provider
22
+ );
23
+ if (captchaChallenge[types.ApiParams.error]) {
24
+ return captchaChallenge;
25
+ }
26
+ for (const captcha of captchaChallenge.captchas) {
27
+ for (const item of captcha.items) {
28
+ if (item.data) {
29
+ item.data = item.data.replace(/^http(s)*:\/\//, "//");
30
+ }
31
+ }
32
+ }
33
+ return captchaChallenge;
34
+ } catch (error) {
35
+ throw new common.ProsopoEnvError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
36
+ context: { error }
37
+ });
38
+ }
39
+ }
40
+ async submitCaptchaSolution(userTimestampSignature, requestHash, solutions, timestamp, providerRequestHashSignature) {
41
+ const tree = new datasets.CaptchaMerkleTree();
42
+ const captchasHashed = solutions.map(
43
+ (captcha) => datasets.computeCaptchaSolutionHash(captcha)
44
+ );
45
+ tree.build(captchasHashed);
46
+ if (!tree.root) {
47
+ throw new common.ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
48
+ context: { error: "Merkle tree root is undefined" }
49
+ });
50
+ }
51
+ const commitmentId = tree.root.hash;
52
+ const tx = void 0;
53
+ let result;
54
+ try {
55
+ result = await this.providerApi.submitCaptchaSolution(
56
+ solutions,
57
+ requestHash,
58
+ this.userAccount,
59
+ timestamp,
60
+ providerRequestHashSignature,
61
+ userTimestampSignature
62
+ );
63
+ } catch (error) {
64
+ throw new common.ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
65
+ context: { error }
66
+ });
67
+ }
68
+ return [result, commitmentId, tx];
69
+ }
70
+ }
71
+ exports.ProsopoCaptchaApi = ProsopoCaptchaApi;
72
+ exports.default = ProsopoCaptchaApi;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const COLLECTOR_LIMIT = 1e4;
4
+ const storeLog = (event, setEvents) => {
5
+ setEvents((currentEvents) => {
6
+ let newEvents = [...currentEvents, event];
7
+ if (newEvents.length > COLLECTOR_LIMIT) {
8
+ newEvents = newEvents.slice(1);
9
+ }
10
+ return newEvents;
11
+ });
12
+ };
13
+ const logMouseEvent = (event, setMouseEvent) => {
14
+ const storedEvent = {
15
+ x: event.x,
16
+ y: event.y,
17
+ timestamp: event.timeStamp
18
+ };
19
+ storeLog(storedEvent, setMouseEvent);
20
+ };
21
+ const logKeyboardEvent = (event, setKeyboardEvent) => {
22
+ const storedEvent = {
23
+ key: event.key,
24
+ timestamp: event.timeStamp,
25
+ isShiftKey: event.shiftKey,
26
+ isCtrlKey: event.ctrlKey
27
+ };
28
+ storeLog(storedEvent, setKeyboardEvent);
29
+ };
30
+ const logTouchEvent = (event, setTouchEvent) => {
31
+ for (const touch of Array.from(event.touches)) {
32
+ storeLog(
33
+ { x: touch.clientX, y: touch.clientY, timestamp: event.timeStamp },
34
+ setTouchEvent
35
+ );
36
+ }
37
+ };
38
+ const startCollector = (setStoredMouseEvents, setStoredTouchEvents, setStoredKeyboardEvents, rootElement) => {
39
+ const form = findContainingForm(rootElement);
40
+ if (form) {
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
+ );
69
+ }
70
+ };
71
+ const findContainingForm = (element) => {
72
+ if (element.tagName === "FORM") {
73
+ return element;
74
+ }
75
+ if (element.parentElement) {
76
+ return findContainingForm(element.parentElement);
77
+ }
78
+ return null;
79
+ };
80
+ exports.startCollector = startCollector;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const Manager = require("./Manager.cjs");
4
+ const ProsopoCaptchaApi = require("./ProsopoCaptchaApi.cjs");
5
+ const collector = require("./collector.cjs");
6
+ exports.Manager = Manager.Manager;
7
+ exports.ProsopoCaptchaApi = ProsopoCaptchaApi.ProsopoCaptchaApi;
8
+ exports.startCollector = collector.startCollector;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ const util = require("@polkadot/util");
3
+ const string = require("@polkadot/util/string");
4
+ const types = require("@prosopo/types");
5
+ const PROCAPTCHA_STORAGE_KEY = "@prosopo/procaptcha";
6
+ function getProcaptchaStorage() {
7
+ return types.ProsopoLocalStorageSchema.parse(
8
+ JSON.parse(
9
+ util.hexToString(localStorage.getItem(PROCAPTCHA_STORAGE_KEY) || "0x7b7d")
10
+ )
11
+ );
12
+ }
13
+ function setProcaptchaStorage(storage2) {
14
+ localStorage.setItem(
15
+ PROCAPTCHA_STORAGE_KEY,
16
+ string.stringToHex(JSON.stringify(types.ProsopoLocalStorageSchema.parse(storage2)))
17
+ );
18
+ }
19
+ function setAccount(account) {
20
+ setProcaptchaStorage({ ...getProcaptchaStorage(), account });
21
+ }
22
+ function getAccount() {
23
+ return getProcaptchaStorage().account || null;
24
+ }
25
+ const storage = {
26
+ setAccount,
27
+ getAccount,
28
+ setProcaptchaStorage,
29
+ getProcaptchaStorage
30
+ };
31
+ module.exports = storage;
@@ -0,0 +1,2 @@
1
+ export * from "./modules/index.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./modules/index.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type ProcaptchaCallbacks, type ProcaptchaClientConfigOutput, type ProcaptchaState, type ProcaptchaStateUpdateFn } from "@prosopo/types";
2
+ export declare function Manager(configOptional: ProcaptchaClientConfigOutput, state: ProcaptchaState, onStateUpdate: ProcaptchaStateUpdateFn, callbacks: ProcaptchaCallbacks): {
3
+ start: () => Promise<void>;
4
+ cancel: () => Promise<void>;
5
+ submit: () => Promise<void>;
6
+ select: (hash: string) => void;
7
+ nextRound: () => void;
8
+ reload: () => Promise<void>;
9
+ };
10
+ //# sourceMappingURL=Manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Manager.d.ts","sourceRoot":"","sources":["../../src/modules/Manager.ts"],"names":[],"mappings":"AA6BA,OAAO,EAKN,KAAK,mBAAmB,EAExB,KAAK,4BAA4B,EAEjC,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAG5B,MAAM,gBAAgB,CAAC;AAwBxB,wBAAgB,OAAO,CACtB,cAAc,EAAE,4BAA4B,EAC5C,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,uBAAuB,EACtC,SAAS,EAAE,mBAAmB;;;;mBAsQR,MAAM;;;EA6I5B"}
@@ -0,0 +1,292 @@
1
+ import { cryptoWaitReady } from "@polkadot/util-crypto";
2
+ import { randomAsHex } from "@polkadot/util-crypto/random";
3
+ import { stringToHex } from "@polkadot/util/string";
4
+ import { ExtensionWeb2, ExtensionWeb3 } from "@prosopo/account";
5
+ import { ProviderApi } from "@prosopo/api";
6
+ import { ProsopoDatasetError, ProsopoEnvError, ProsopoError, } from "@prosopo/common";
7
+ import { buildUpdateState, getDefaultEvents, getRandomActiveProvider, providerRetry, } from "@prosopo/procaptcha-common";
8
+ import { ApiParams, ProcaptchaConfigSchema, encodeProcaptchaOutput, } from "@prosopo/types";
9
+ import { at, hashToHex } from "@prosopo/util";
10
+ import { sleep } from "@prosopo/util";
11
+ import ProsopoCaptchaApi from "./ProsopoCaptchaApi.js";
12
+ import storage from "./storage.js";
13
+ const defaultState = () => {
14
+ return {
15
+ showModal: false,
16
+ loading: false,
17
+ index: 0,
18
+ challenge: undefined,
19
+ solutions: undefined,
20
+ isHuman: false,
21
+ captchaApi: undefined,
22
+ account: undefined,
23
+ };
24
+ };
25
+ export function Manager(configOptional, state, onStateUpdate, callbacks) {
26
+ const events = getDefaultEvents(onStateUpdate, state, callbacks);
27
+ const updateState = buildUpdateState(state, onStateUpdate);
28
+ const getConfig = () => {
29
+ const config = {
30
+ userAccountAddress: "",
31
+ ...configOptional,
32
+ };
33
+ if (state.account) {
34
+ config.userAccountAddress = state.account.account.address;
35
+ }
36
+ return ProcaptchaConfigSchema.parse(config);
37
+ };
38
+ const start = async () => {
39
+ events.onOpen();
40
+ await providerRetry(async () => {
41
+ if (state.loading) {
42
+ return;
43
+ }
44
+ if (state.isHuman) {
45
+ return;
46
+ }
47
+ await cryptoWaitReady();
48
+ resetState();
49
+ updateState({ loading: true });
50
+ updateState({
51
+ attemptCount: state.attemptCount ? state.attemptCount + 1 : 1,
52
+ });
53
+ const config = getConfig();
54
+ updateState({ dappAccount: config.account.address });
55
+ await sleep(100);
56
+ const account = await loadAccount();
57
+ const getRandomProviderResponse = await getRandomActiveProvider(getConfig());
58
+ const providerUrl = getRandomProviderResponse.provider.url;
59
+ const providerApi = await loadProviderApi(providerUrl);
60
+ const captchaApi = new ProsopoCaptchaApi(account.account.address, getRandomProviderResponse, providerApi, config.web2, config.account.address || "");
61
+ updateState({ captchaApi });
62
+ const challenge = await captchaApi.getCaptchaChallenge();
63
+ if (challenge.error) {
64
+ updateState({
65
+ loading: false,
66
+ error: challenge.error.message,
67
+ });
68
+ }
69
+ else {
70
+ if (challenge.captchas.length <= 0) {
71
+ throw new ProsopoDatasetError("DEVELOPER.PROVIDER_NO_CAPTCHA");
72
+ }
73
+ const timeMillis = challenge.captchas
74
+ .map((captcha) => captcha.timeLimitMs || config.captchas.image.challengeTimeout)
75
+ .reduce((a, b) => a + b);
76
+ const timeout = setTimeout(() => {
77
+ events.onChallengeExpired();
78
+ updateState({ isHuman: false, showModal: false, loading: false });
79
+ }, timeMillis);
80
+ updateState({
81
+ index: 0,
82
+ solutions: challenge.captchas.map(() => []),
83
+ challenge,
84
+ showModal: true,
85
+ timeout,
86
+ });
87
+ }
88
+ }, start, resetState, state.attemptCount, 10);
89
+ };
90
+ const submit = async () => {
91
+ await providerRetry(async () => {
92
+ clearTimeout();
93
+ if (!state.challenge) {
94
+ throw new ProsopoError("CAPTCHA.NO_CAPTCHA", {
95
+ context: { error: "Cannot submit, no Captcha found in state" },
96
+ });
97
+ }
98
+ updateState({ showModal: false });
99
+ const challenge = state.challenge;
100
+ const salt = randomAsHex();
101
+ const captchaSolution = state.challenge.captchas.map((captcha, index) => {
102
+ const solution = at(state.solutions, index);
103
+ return {
104
+ captchaId: captcha.captchaId,
105
+ captchaContentId: captcha.captchaContentId,
106
+ salt,
107
+ solution,
108
+ };
109
+ });
110
+ const account = getAccount();
111
+ const signer = getExtension(account).signer;
112
+ const first = at(challenge.captchas, 0);
113
+ if (!first.datasetId) {
114
+ throw new ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_ID", {
115
+ context: { error: "No datasetId set for challenge" },
116
+ });
117
+ }
118
+ const captchaApi = state.captchaApi;
119
+ if (!captchaApi) {
120
+ throw new ProsopoError("CAPTCHA.INVALID_TOKEN", {
121
+ context: { error: "No Captcha API found in state" },
122
+ });
123
+ }
124
+ if (!signer || !signer.signRaw) {
125
+ throw new ProsopoEnvError("GENERAL.CANT_FIND_KEYRINGPAIR", {
126
+ context: {
127
+ error: "Signer is not defined, cannot sign message to prove account ownership",
128
+ },
129
+ });
130
+ }
131
+ const userTimestampSignature = await signer.signRaw({
132
+ address: account.account.address,
133
+ data: stringToHex(challenge[ApiParams.timestamp]),
134
+ type: "bytes",
135
+ });
136
+ const submission = await captchaApi.submitCaptchaSolution(userTimestampSignature.signature, challenge.requestHash, captchaSolution, challenge.timestamp, challenge.signature.provider.requestHash);
137
+ const isHuman = submission[0].verified;
138
+ updateState({
139
+ submission,
140
+ isHuman,
141
+ loading: false,
142
+ });
143
+ if (state.isHuman) {
144
+ const providerUrl = captchaApi.provider.provider.url;
145
+ storage.setProcaptchaStorage({
146
+ ...storage.getProcaptchaStorage(),
147
+ providerUrl,
148
+ });
149
+ events.onHuman(encodeProcaptchaOutput({
150
+ [ApiParams.providerUrl]: providerUrl,
151
+ [ApiParams.user]: account.account.address,
152
+ [ApiParams.dapp]: getDappAccount(),
153
+ [ApiParams.commitmentId]: hashToHex(submission[1]),
154
+ [ApiParams.timestamp]: challenge.timestamp,
155
+ [ApiParams.signature]: {
156
+ [ApiParams.provider]: {
157
+ [ApiParams.requestHash]: challenge.signature.provider.requestHash,
158
+ },
159
+ [ApiParams.user]: {
160
+ [ApiParams.timestamp]: userTimestampSignature.signature,
161
+ },
162
+ },
163
+ }));
164
+ setValidChallengeTimeout();
165
+ }
166
+ else {
167
+ events.onFailed();
168
+ }
169
+ }, start, resetState, state.attemptCount, 10);
170
+ };
171
+ const cancel = async () => {
172
+ clearTimeout();
173
+ resetState();
174
+ events.onClose();
175
+ };
176
+ const reload = async () => {
177
+ clearTimeout();
178
+ resetState();
179
+ events.onClose();
180
+ await start();
181
+ };
182
+ const select = (hash) => {
183
+ if (!state.challenge) {
184
+ throw new ProsopoError("CAPTCHA.NO_CAPTCHA", {
185
+ context: { error: "Cannot select, no Captcha found in state" },
186
+ });
187
+ }
188
+ if (state.index >= state.challenge.captchas.length || state.index < 0) {
189
+ throw new ProsopoError("CAPTCHA.NO_CAPTCHA", {
190
+ context: {
191
+ error: "Cannot select, index is out of range for this Captcha",
192
+ },
193
+ });
194
+ }
195
+ const index = state.index;
196
+ const solutions = state.solutions;
197
+ const solution = at(solutions, index);
198
+ if (solution.includes(hash)) {
199
+ solution.splice(solution.indexOf(hash), 1);
200
+ }
201
+ else {
202
+ solution.push(hash);
203
+ }
204
+ updateState({ solutions });
205
+ };
206
+ const nextRound = () => {
207
+ if (!state.challenge) {
208
+ throw new ProsopoError("CAPTCHA.NO_CAPTCHA", {
209
+ context: { error: "Cannot select, no Captcha found in state" },
210
+ });
211
+ }
212
+ if (state.index + 1 >= state.challenge.captchas.length) {
213
+ throw new ProsopoError("CAPTCHA.NO_CAPTCHA", {
214
+ context: {
215
+ error: "Cannot select, index is out of range for this Captcha",
216
+ },
217
+ });
218
+ }
219
+ updateState({ index: state.index + 1 });
220
+ };
221
+ const loadProviderApi = async (providerUrl) => {
222
+ const config = getConfig();
223
+ if (!config.account.address) {
224
+ throw new ProsopoEnvError("GENERAL.SITE_KEY_MISSING");
225
+ }
226
+ return new ProviderApi(providerUrl, config.account.address);
227
+ };
228
+ const clearTimeout = () => {
229
+ window.clearTimeout(Number(state.timeout));
230
+ updateState({ timeout: undefined });
231
+ };
232
+ const setValidChallengeTimeout = () => {
233
+ const timeMillis = configOptional.captchas.image.solutionTimeout;
234
+ const successfullChallengeTimeout = setTimeout(() => {
235
+ updateState({ isHuman: false });
236
+ events.onExpired();
237
+ }, timeMillis);
238
+ updateState({ successfullChallengeTimeout });
239
+ };
240
+ const resetState = () => {
241
+ clearTimeout();
242
+ updateState(defaultState());
243
+ events.onReset();
244
+ };
245
+ const loadAccount = async () => {
246
+ const config = getConfig();
247
+ if (!config.web2 && !config.userAccountAddress) {
248
+ throw new ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", {
249
+ context: { error: "Account address has not been set for web3 mode" },
250
+ });
251
+ }
252
+ const ext = config.web2 ? new ExtensionWeb2() : new ExtensionWeb3();
253
+ const account = await ext.getAccount(config);
254
+ storage.setAccount(account.account.address);
255
+ updateState({ account });
256
+ return getAccount();
257
+ };
258
+ const getAccount = () => {
259
+ if (!state.account) {
260
+ throw new ProsopoEnvError("GENERAL.ACCOUNT_NOT_FOUND", {
261
+ context: { error: "Account not loaded" },
262
+ });
263
+ }
264
+ const account = state.account;
265
+ return account;
266
+ };
267
+ const getDappAccount = () => {
268
+ if (!state.dappAccount) {
269
+ throw new ProsopoEnvError("GENERAL.SITE_KEY_MISSING");
270
+ }
271
+ const dappAccount = state.dappAccount;
272
+ return dappAccount;
273
+ };
274
+ const getExtension = (possiblyAccount) => {
275
+ const account = possiblyAccount || getAccount();
276
+ if (!account.extension) {
277
+ throw new ProsopoEnvError("ACCOUNT.NO_POLKADOT_EXTENSION", {
278
+ context: { error: "Extension not loaded" },
279
+ });
280
+ }
281
+ return account.extension;
282
+ };
283
+ return {
284
+ start,
285
+ cancel,
286
+ submit,
287
+ select,
288
+ nextRound,
289
+ reload,
290
+ };
291
+ }
292
+ //# sourceMappingURL=Manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Manager.js","sourceRoot":"","sources":["../../src/modules/Manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ProviderApi } from "@prosopo/api";
2
+ import { type CaptchaResponseBody, type CaptchaSolution, type ProcaptchaApiInterface, type RandomProvider } from "@prosopo/types";
3
+ import type { TCaptchaSubmitResult } from "@prosopo/types";
4
+ export declare class ProsopoCaptchaApi implements ProcaptchaApiInterface {
5
+ userAccount: string;
6
+ provider: RandomProvider;
7
+ providerApi: ProviderApi;
8
+ dappAccount: string;
9
+ _web2: boolean;
10
+ constructor(userAccount: string, provider: RandomProvider, providerApi: ProviderApi, web2: boolean, dappAccount: string);
11
+ get web2(): boolean;
12
+ getCaptchaChallenge(): Promise<CaptchaResponseBody>;
13
+ submitCaptchaSolution(userTimestampSignature: string, requestHash: string, solutions: CaptchaSolution[], timestamp: string, providerRequestHashSignature: string): Promise<TCaptchaSubmitResult>;
14
+ }
15
+ export default ProsopoCaptchaApi;
16
+ //# sourceMappingURL=ProsopoCaptchaApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProsopoCaptchaApi.d.ts","sourceRoot":"","sources":["../../src/modules/ProsopoCaptchaApi.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD,OAAO,EAEN,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAEpB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,qBAAa,iBAAkB,YAAW,sBAAsB;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;gBAGd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,MAAM;IASpB,IAAI,IAAI,IAAI,OAAO,CAElB;IAEY,mBAAmB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IA8BnD,qBAAqB,CACjC,sBAAsB,EAAE,MAAM,EAC9B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,eAAe,EAAE,EAC5B,SAAS,EAAE,MAAM,EACjB,4BAA4B,EAAE,MAAM,GAClC,OAAO,CAAC,oBAAoB,CAAC;CAsChC;AAED,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { ProsopoDatasetError, ProsopoEnvError } from "@prosopo/common";
2
+ import { CaptchaMerkleTree, computeCaptchaSolutionHash, } from "@prosopo/datasets";
3
+ import { ApiParams, } from "@prosopo/types";
4
+ export class ProsopoCaptchaApi {
5
+ constructor(userAccount, provider, providerApi, web2, dappAccount) {
6
+ this.userAccount = userAccount;
7
+ this.provider = provider;
8
+ this.providerApi = providerApi;
9
+ this._web2 = web2;
10
+ this.dappAccount = dappAccount;
11
+ }
12
+ get web2() {
13
+ return this._web2;
14
+ }
15
+ async getCaptchaChallenge() {
16
+ try {
17
+ const captchaChallenge = await this.providerApi.getCaptchaChallenge(this.userAccount, this.provider);
18
+ if (captchaChallenge[ApiParams.error]) {
19
+ return captchaChallenge;
20
+ }
21
+ for (const captcha of captchaChallenge.captchas) {
22
+ for (const item of captcha.items) {
23
+ if (item.data) {
24
+ item.data = item.data.replace(/^http(s)*:\/\//, "//");
25
+ }
26
+ }
27
+ }
28
+ return captchaChallenge;
29
+ }
30
+ catch (error) {
31
+ throw new ProsopoEnvError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
32
+ context: { error },
33
+ });
34
+ }
35
+ }
36
+ async submitCaptchaSolution(userTimestampSignature, requestHash, solutions, timestamp, providerRequestHashSignature) {
37
+ const tree = new CaptchaMerkleTree();
38
+ const captchasHashed = solutions.map((captcha) => computeCaptchaSolutionHash(captcha));
39
+ tree.build(captchasHashed);
40
+ if (!tree.root) {
41
+ throw new ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
42
+ context: { error: "Merkle tree root is undefined" },
43
+ });
44
+ }
45
+ const commitmentId = tree.root.hash;
46
+ const tx = undefined;
47
+ let result;
48
+ try {
49
+ result = await this.providerApi.submitCaptchaSolution(solutions, requestHash, this.userAccount, timestamp, providerRequestHashSignature, userTimestampSignature);
50
+ }
51
+ catch (error) {
52
+ throw new ProsopoDatasetError("CAPTCHA.INVALID_CAPTCHA_CHALLENGE", {
53
+ context: { error },
54
+ });
55
+ }
56
+ return [result, commitmentId, tx];
57
+ }
58
+ }
59
+ export default ProsopoCaptchaApi;
60
+ //# sourceMappingURL=ProsopoCaptchaApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProsopoCaptchaApi.js","sourceRoot":"","sources":["../../src/modules/ProsopoCaptchaApi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ProsopoKeyboardEvent, ProsopoMouseEvent, ProsopoTouchEvent } from "@prosopo/types";
2
+ type SetStateAction<T> = T | ((prevState: T) => T);
3
+ type SetMouseEvent = (setValueFunc: SetStateAction<ProsopoMouseEvent[]>) => void;
4
+ type SetKeyboardEvent = (setValueFunc: SetStateAction<ProsopoKeyboardEvent[]>) => void;
5
+ type SetTouchEvent = (setValueFunc: SetStateAction<ProsopoTouchEvent[]>) => void;
6
+ export declare const startCollector: (setStoredMouseEvents: SetMouseEvent, setStoredTouchEvents: SetTouchEvent, setStoredKeyboardEvents: SetKeyboardEvent, rootElement: HTMLDivElement) => void;
7
+ export {};
8
+ //# sourceMappingURL=collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/modules/collector.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACX,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,gBAAgB,CAAC;AAIxB,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AAEnD,KAAK,aAAa,GAAG,CACpB,YAAY,EAAE,cAAc,CAAC,iBAAiB,EAAE,CAAC,KAC7C,IAAI,CAAC;AACV,KAAK,gBAAgB,GAAG,CACvB,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,CAAC,KAChD,IAAI,CAAC;AACV,KAAK,aAAa,GAAG,CACpB,YAAY,EAAE,cAAc,CAAC,iBAAiB,EAAE,CAAC,KAC7C,IAAI,CAAC;AAiDV,eAAO,MAAM,cAAc,yBACJ,aAAa,wBACb,aAAa,2BACV,gBAAgB,eAC5B,cAAc,SA+B3B,CAAC"}
@@ -0,0 +1,54 @@
1
+ const COLLECTOR_LIMIT = 10000;
2
+ const storeLog = (event, setEvents) => {
3
+ setEvents((currentEvents) => {
4
+ let newEvents = [...currentEvents, event];
5
+ if (newEvents.length > COLLECTOR_LIMIT) {
6
+ newEvents = newEvents.slice(1);
7
+ }
8
+ return newEvents;
9
+ });
10
+ };
11
+ const logMouseEvent = (event, setMouseEvent) => {
12
+ const storedEvent = {
13
+ x: event.x,
14
+ y: event.y,
15
+ timestamp: event.timeStamp,
16
+ };
17
+ storeLog(storedEvent, setMouseEvent);
18
+ };
19
+ const logKeyboardEvent = (event, setKeyboardEvent) => {
20
+ const storedEvent = {
21
+ key: event.key,
22
+ timestamp: event.timeStamp,
23
+ isShiftKey: event.shiftKey,
24
+ isCtrlKey: event.ctrlKey,
25
+ };
26
+ storeLog(storedEvent, setKeyboardEvent);
27
+ };
28
+ const logTouchEvent = (event, setTouchEvent) => {
29
+ for (const touch of Array.from(event.touches)) {
30
+ storeLog({ x: touch.clientX, y: touch.clientY, timestamp: event.timeStamp }, setTouchEvent);
31
+ }
32
+ };
33
+ export const startCollector = (setStoredMouseEvents, setStoredTouchEvents, setStoredKeyboardEvents, rootElement) => {
34
+ const form = findContainingForm(rootElement);
35
+ if (form) {
36
+ form.addEventListener("mousemove", (e) => logMouseEvent(e, setStoredMouseEvents));
37
+ form.addEventListener("keydown", (e) => logKeyboardEvent(e, setStoredKeyboardEvents));
38
+ form.addEventListener("keyup", (e) => logKeyboardEvent(e, setStoredKeyboardEvents));
39
+ form.addEventListener("touchstart", (e) => logTouchEvent(e, setStoredTouchEvents));
40
+ form.addEventListener("touchend", (e) => logTouchEvent(e, setStoredTouchEvents));
41
+ form.addEventListener("touchcancel", (e) => logTouchEvent(e, setStoredTouchEvents));
42
+ form.addEventListener("touchmove", (e) => logTouchEvent(e, setStoredTouchEvents));
43
+ }
44
+ };
45
+ const findContainingForm = (element) => {
46
+ if (element.tagName === "FORM") {
47
+ return element;
48
+ }
49
+ if (element.parentElement) {
50
+ return findContainingForm(element.parentElement);
51
+ }
52
+ return null;
53
+ };
54
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/modules/collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from "./Manager.js";
2
+ export * from "./ProsopoCaptchaApi.js";
3
+ export * from "./collector.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":"AAaA,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./Manager.js";
2
+ export * from "./ProsopoCaptchaApi.js";
3
+ export * from "./collector.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":"AAaA,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type ProcaptchaLocalStorage } from "@prosopo/types";
2
+ declare function getProcaptchaStorage(): ProcaptchaLocalStorage;
3
+ declare function setProcaptchaStorage(storage: ProcaptchaLocalStorage): void;
4
+ declare function setAccount(account: string): void;
5
+ declare function getAccount(): string | null;
6
+ declare const _default: {
7
+ setAccount: typeof setAccount;
8
+ getAccount: typeof getAccount;
9
+ setProcaptchaStorage: typeof setProcaptchaStorage;
10
+ getProcaptchaStorage: typeof getProcaptchaStorage;
11
+ };
12
+ export default _default;
13
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/modules/storage.ts"],"names":[],"mappings":"AAeA,OAAO,EACN,KAAK,sBAAsB,EAE3B,MAAM,gBAAgB,CAAC;AAOxB,iBAAS,oBAAoB,IAAI,sBAAsB,CAMtD;AAMD,iBAAS,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,QAK5D;AAKD,iBAAS,UAAU,CAAC,OAAO,EAAE,MAAM,QAElC;AAKD,iBAAS,UAAU,IAAI,MAAM,GAAG,IAAI,CAEnC;;;;;;;AAED,wBAKE"}
@@ -0,0 +1,23 @@
1
+ import { hexToString } from "@polkadot/util";
2
+ import { stringToHex } from "@polkadot/util/string";
3
+ import { ProsopoLocalStorageSchema, } from "@prosopo/types";
4
+ const PROCAPTCHA_STORAGE_KEY = "@prosopo/procaptcha";
5
+ function getProcaptchaStorage() {
6
+ return ProsopoLocalStorageSchema.parse(JSON.parse(hexToString(localStorage.getItem(PROCAPTCHA_STORAGE_KEY) || "0x7b7d")));
7
+ }
8
+ function setProcaptchaStorage(storage) {
9
+ localStorage.setItem(PROCAPTCHA_STORAGE_KEY, stringToHex(JSON.stringify(ProsopoLocalStorageSchema.parse(storage))));
10
+ }
11
+ function setAccount(account) {
12
+ setProcaptchaStorage({ ...getProcaptchaStorage(), account });
13
+ }
14
+ function getAccount() {
15
+ return getProcaptchaStorage().account || null;
16
+ }
17
+ export default {
18
+ setAccount,
19
+ getAccount,
20
+ setProcaptchaStorage,
21
+ getProcaptchaStorage,
22
+ };
23
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/modules/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAcpD,OAAO,EAEN,yBAAyB,GACzB,MAAM,gBAAgB,CAAC;AAExB,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;AAKrD,SAAS,oBAAoB;IAC5B,OAAO,yBAAyB,CAAC,KAAK,CACrC,IAAI,CAAC,KAAK,CACT,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,sBAAsB,CAAC,IAAI,QAAQ,CAAC,CACrE,CACD,CAAC;AACH,CAAC;AAMD,SAAS,oBAAoB,CAAC,OAA+B;IAC5D,YAAY,CAAC,OAAO,CACnB,sBAAsB,EACtB,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,yBAAyB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CACrE,CAAC;AACH,CAAC;AAKD,SAAS,UAAU,CAAC,OAAe;IAClC,oBAAoB,CAAC,EAAE,GAAG,oBAAoB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AAC9D,CAAC;AAKD,SAAS,UAAU;IAClB,OAAO,oBAAoB,EAAE,CAAC,OAAO,IAAI,IAAI,CAAC;AAC/C,CAAC;AAED,eAAe;IACd,UAAU;IACV,UAAU;IACV,oBAAoB;IACpB,oBAAoB;CACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.d.ts","sourceRoot":"","sources":["../../../src/tests/modules/storage.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import storage from '../../modules/storage.js';
3
+ const { setAccount, getAccount, getProcaptchaStorage, setProcaptchaStorage } = storage;
4
+ describe('storage tests', () => {
5
+ test('sets and gets account', async () => {
6
+ setAccount('abc');
7
+ expect(getAccount()).to.equal('abc');
8
+ });
9
+ test('sets provider URL and block number', async () => {
10
+ setAccount('abc');
11
+ const procaptchaStorage = getProcaptchaStorage();
12
+ setProcaptchaStorage({ ...procaptchaStorage, providerUrl: 'http://localhost:9229', blockNumber: 100 });
13
+ expect(getProcaptchaStorage()).toMatchObject({
14
+ account: 'abc',
15
+ providerUrl: 'http://localhost:9229',
16
+ blockNumber: 100,
17
+ });
18
+ });
19
+ });
20
+ //# sourceMappingURL=storage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../../src/tests/modules/storage.test.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,OAAO,MAAM,0BAA0B,CAAA;AAE9C,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAA;AAEtF,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,IAAI,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACrC,UAAU,CAAC,KAAK,CAAC,CAAA;QACjB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,UAAU,CAAC,KAAK,CAAC,CAAA;QACjB,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAA;QAChD,oBAAoB,CAAC,EAAE,GAAG,iBAAiB,EAAE,WAAW,EAAE,uBAAuB,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAA;QACtG,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC,aAAa,CAAC;YACzC,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,uBAAuB;YACpC,WAAW,EAAE,GAAG;SACnB,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.unit.test.d.ts","sourceRoot":"","sources":["../../../src/tests/modules/storage.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import storage from "../../modules/storage.js";
3
+ const { setAccount, getAccount, getProcaptchaStorage, setProcaptchaStorage } = storage;
4
+ describe("storage tests", () => {
5
+ test("sets and gets account", async () => {
6
+ setAccount("abc");
7
+ expect(getAccount()).to.equal("abc");
8
+ });
9
+ test("sets provider URL", async () => {
10
+ setAccount("abc");
11
+ const procaptchaStorage = getProcaptchaStorage();
12
+ setProcaptchaStorage({
13
+ ...procaptchaStorage,
14
+ providerUrl: "http://localhost:9229",
15
+ });
16
+ expect(getProcaptchaStorage()).toMatchObject({
17
+ account: "abc",
18
+ providerUrl: "http://localhost:9229",
19
+ });
20
+ });
21
+ });
22
+ //# sourceMappingURL=storage.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.unit.test.js","sourceRoot":"","sources":["../../../src/tests/modules/storage.unit.test.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,OAAO,MAAM,0BAA0B,CAAC;AAE/C,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,GAC3E,OAAO,CAAC;AAET,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC9B,IAAI,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACxC,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACpC,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;QACjD,oBAAoB,CAAC;YACpB,GAAG,iBAAiB;YACpB,WAAW,EAAE,uBAAuB;SACpC,CAAC,CAAC;QACH,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC,aAAa,CAAC;YAC5C,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,uBAAuB;SACpC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './utils.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAaA,cAAc,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './utils.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAaA,cAAc,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const sleep: (ms: number) => Promise<unknown>;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,KAAK,OAAQ,MAAM,qBAE/B,CAAA"}
@@ -0,0 +1,4 @@
1
+ export const sleep = (ms) => {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ };
4
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC5D,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prosopo/procaptcha",
3
- "version": "2.1.4",
3
+ "version": "2.1.6",
4
4
  "author": "PROSOPO LIMITED <info@prosopo.io>",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -33,14 +33,14 @@
33
33
  "@polkadot/api-contract": "10.13.1",
34
34
  "@polkadot/util": "12.6.2",
35
35
  "@polkadot/util-crypto": "12.6.2",
36
- "@prosopo/account": "2.1.4",
37
- "@prosopo/api": "2.1.4",
38
- "@prosopo/common": "2.1.4",
39
- "@prosopo/datasets": "2.1.4",
40
- "@prosopo/load-balancer": "2.1.4",
41
- "@prosopo/procaptcha-common": "2.1.4",
42
- "@prosopo/types": "2.1.4",
43
- "@prosopo/util": "2.1.4",
36
+ "@prosopo/account": "2.1.6",
37
+ "@prosopo/api": "2.1.6",
38
+ "@prosopo/common": "2.1.6",
39
+ "@prosopo/datasets": "2.1.6",
40
+ "@prosopo/load-balancer": "2.1.6",
41
+ "@prosopo/procaptcha-common": "2.1.6",
42
+ "@prosopo/types": "2.1.6",
43
+ "@prosopo/util": "2.1.6",
44
44
  "jsdom": "25.0.0"
45
45
  },
46
46
  "overrides": {
@@ -56,12 +56,12 @@
56
56
  }
57
57
  },
58
58
  "devDependencies": {
59
- "@prosopo/config": "2.1.4",
59
+ "@prosopo/config": "2.1.6",
60
60
  "@vitest/coverage-v8": "2.1.1",
61
61
  "concurrently": "9.0.1",
62
62
  "dotenv": "16.4.5",
63
63
  "npm-run-all": "4.1.5",
64
- "rimraf": "6.0.1",
64
+ "del-cli": "6.0.0",
65
65
  "tslib": "2.7.0",
66
66
  "tsx": "4.19.1",
67
67
  "typescript": "5.6.2",