From 78b8bfacad75421fc42106f39b2d06a91e48c3a2 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 27 Sep 2023 12:04:32 +0100 Subject: [PATCH] 622 update readmes (#625) * Update main readme and procaptcha-react readme * CLI readme * Update procaptcha-react readme with current implementation * Fix explicit render in bundle demo * Make sure env files are in the correct place when bundling * lint * Explain implicit and explicit rendering * mention project is in beta * Update CLI readme and add server readme --- README.md | 134 ++++++++++++++++---------- packages/cli/README.md | 120 +++++++++++++++++++++++ packages/procaptcha-react/README.md | 144 ++++++++++++++++++---------- packages/server/README.md | 47 +++++++++ 4 files changed, 345 insertions(+), 100 deletions(-) create mode 100644 packages/cli/README.md create mode 100644 packages/server/README.md diff --git a/README.md b/README.md index fbd2a5a6b0..34beade33d 100644 --- a/README.md +++ b/README.md @@ -2,26 +2,32 @@ Prosopo Procaptcha is a drop-replacement for reCAPTCHA and hCaptcha that protects user privacy and collects zero data. -Sign up at [Prosopo](https://prosopo.io/#signup) to get your sitekey today. You need a sitekey to use this library. +Prosopo is a distributed human verification service that can be used to stop bots from interacting with your apps. -# Implementation +Sign up to be a network [beta tester](https://prosopo.io/#signup) to get your sitekey today. You need a sitekey to use +this library. + +# Configuration Prosopo captcha can be easily implemented in your application via a script tag or a React component. ## Add the Procaptcha Widget to your Web page via a script tag -Procaptcha requires two small pieces of client side code to render a captcha widget on an HTML page. First, you must -include the Procaptcha JavaScript resource somewhere in your HTML page. The ` + ``` -Second, you must add an empty DOM container where the Procaptcha widget will be inserted automatically. The container is -typically a
(but can be any element) and must have class `procaptcha` and a `data-sitekey` attribute set to your +Now, you can either render the Procaptcha widget implicitly or explicitly. + +### Implicit Rendering Using `.procaptcha` Container + +Add an empty DOM container where the Procaptcha widget will be inserted automatically. The container is +typically a `
` (but can be any element) and must have class `procaptcha` and a `data-sitekey` attribute set to your public site key. @@ -38,15 +44,18 @@ verification. You can retrieve it server side with POST parameter `procaptcha-response`. Here's a full example where Procaptcha is being used to protect a signup form from automated abuse. When the form is -submitted, the `procaptcha-response` token will be included with the email and password POST data after the captcha is +submitted, the `procaptcha-response` JSON data will be included with the email and password POST data after the captcha +is solved. +#### Example of implicit rendering + ```html Procaptcha Demo - +
@@ -60,54 +69,77 @@ solved. ``` -## Add the Procaptcha Widget to your Web page using a React Component +### Explicit Rendering -You can see Procaptcha being used as a React component in -our [React Demo](https://github.com/prosopo/captcha/blob/8b8663bf0412e5fd349d40c270dd5b1b9f56dc2a/demos/client-example/src/App.tsx#L224-L227). +If you prefer to render the widget yourself, you can use the `Procaptcha.render()` method. The `Procaptcha.render()` +must be called after the procaptcha.bundle.js script has loaded. -The Procaptcha component is called as follows: +#### Example of explicit rendering -```tsx +The script is loaded in the head of the document and given the id `procaptcha-script`. A container is created with the +id `procaptcha-container` where the widget will be rendered. +```html - + + + + + +
+ + ``` -A config object is required and must contain your sitekey. The callbacks are optional and can be used to handle the -various procaptcha events. The following config demonstrates the `REACT_APP_DAPP_SITE_KEY` variable being pulled from -environment variables. - -```tsx -const config: ProcaptchaConfigOptional = { - account: { - address: process.env.REACT_APP_DAPP_SITE_KEY || undefined, - }, - web2: 'true', - dappName: 'client-example', - defaultEnvironment: 'rococo', - networks: { - rococo: { - endpoint: 'wss://rococo-contracts-rpc.polkadot.io:443', - contract: { - address: '5HiVWQhJrysNcFNEWf2crArKht16zrhro3FcekVWocyQjx5u', - name: 'prosopo', - }, - }, - }, - solutionThreshold: 80, +An `onload` event is added to the script tag to call the render function when the script has loaded. + +```javascript +// A function that will call the render Procaptcha function when the procaptcha script has loaded +document.getElementById('procaptcha-script').addEventListener('load', function () { + + // Define a callback function to be called when the CAPTCHA is verified + window.onCaptchaVerified = function (output) { + console.log('Captcha verified, output: ' + JSON.stringify(output)) + } + + // Render the CAPTCHA explicitly on a container with id "procaptcha-container" + window.procaptcha.render('procaptcha-container', { + siteKey: 'YOUR_SITE_KEY', + theme: 'dark', + callback: 'onCaptchaVerified', + }) +}) +``` + +### Procaptcha-response + +The output from the `onCaptchaVerified` function is the `procaptcha-response` JSON data. The `procaptcha-response` JSON +data contains the following fields: + +| Key | Type | Description | +|--------------|--------|-------------------------------------------------------------------------------------------------------------------------------| +| commitmentId | string | The commitment ID of the captcha challenge. This is used to verify the user's response on-chain. | +| providerUrl | string | The URL of the provider that the user used to solve the captcha challenge. | +| dapp | string | The SITE_KEY of your application / website | +| user | string | The user's account address | +| blockNumber | number | The block number of the captcha challenge. This is used to verify that the contacted provider was randomly selected on-chain. | + +## Verify the User Response Server Side + +To verify a user's response on the server side, simpy import the `verify` function from `@prosopo/server` and pass it +the `procaptcha-response` POST data. Types can be imported from `@prosopo/types`. + +```typescript +import {ProsopoServer} from '@prosopo/server' +import {ApiParams} from '@prosopo/types' + +... + +if (await prosopoServer.isVerified(payload[ApiParams.procaptchaResponse])) { + // perform CAPTCHA protected action } ``` -### Config Options -| Key | Type | Description | -|--------------------|--------|-----------------------------------------------------------------------------------------| -| account | string | The site key you received when you signed up | -| web2 | string | Set to 'true' to enable web2 support | -| dappName | string | The name of your application / website | -| defaultEnvironment | string | The default environment to use - set to `rococo` | -| networks | object | The networks your application supports - copy paste this from the config above | -| solutionThreshold | number | The percentage of captcha that a user must have answered correctly to identify as human | +There is an example server side implementation +in [demos/client-example-server](https://github.com/prosopo/captcha/tree/main/demos/client-example-server). diff --git a/packages/cli/README.md b/packages/cli/README.md new file mode 100644 index 0000000000..1e21b232a8 --- /dev/null +++ b/packages/cli/README.md @@ -0,0 +1,120 @@ +# Prosopo Provider Command Line Interface + +The Provier CLI allows you to set up a Provider instance and begin to serve CAPTCHA challenges to the Prosopo Network. +This will allow you to obtain valuable human-labelled image data. As we are currently in beta testing, the CLI is **only +useable for development purposes**. + +The Provider CLI is intended to be used from within the Prosopo Provider Container Image. It is not intended to be used +directly from the host machine. A bundled version of the CLI is available in the Provider Container Image. + +## Container Image + +### Get the Container ID + +To execute commands against the running Provider, you must first get the Container ID of the running Provider Container. + + ```bash + $ PROVIDER_CONTAINER = docker ps -q -f name=docker-provider + ``` + +### Execute a command inside the provider container + +You can then execute the commands as follows: + + ```bash + $ docker exec -it $PROVIDER_CONTAINER bash -c "npx provider " + ``` + +### Executing Commands in the Container + +### Register your Provider + +You must first register your Provider in the network contract in order to be selected as a CAPTCHA Provider. + +```bash +$ npx provider provider_register --url https://YOUR_URL --fee 0 --payee Dapp +``` + +### Fund your Provider + +It is necessary to fund your Provider with at least the minimum fee amount in order to serve CAPTCHA challenges. The +funds are used to incentivise good behaviour by Providers. + +```bash +$ npx provider provider_update --value 1000 --address YOUR_ADDRESS +``` + +### Set a new Dataset + +You must load a dataset in to your database in order to provider CAPTCHA challenges. The dataset contains the CAPTCHA +challenges that will be served to users. The format for the dataset is +defined [here](https://github.com/prosopo/captcha/blob/main/packages/types/src/datasets/dataset.ts) and an example +dataset can be seen [here](https://github.com/prosopo/captcha/blob/main/dev/data/captchas.json). + +```bash +$ npx provider provider_set_data_set --file /path/to/dataset.json +``` + +### Start the API + +Start the API and a begin to serve CAPTCHA challenges. + +```bash +$ npx provider start +``` + +### Deregister your Provider + +When you no longer wish to be part of the Prosopo Network, you can stop serving CAPTCHA challenges by deregistering. + +```bash +$ npx provider provider_deregister +``` + +### List details of a single Provider + +```bash +$ npx provider provider_details --address PROVIDER_ADDRESS +``` + +### Get a list of provider accounts from the contract + +```bash +$ npx provider provider_accounts +``` + +### View the Provider Version + +```bash +$ npx provider version +``` + +## Full CLI Usage + +`--help` output from the CLI. + +```bash +Usage: cli.js [global options] [options] + +Commands: + cli.js provider_register Register a Provider + cli.js provider_update Update a Provider + cli.js provider_deregister Deregister a Provider + cli.js provider_set_data_set Add a dataset as a Provider + cli.js dapp_register Register a Dapp + cli.js dapp_update Register a Dapp + cli.js provider_accounts List all provider accounts + cli.js dapp_accounts List all dapp accounts + cli.js provider_details List details of a single Provider + cli.js provider_dataset Exports a dataset from the provider database + cli.js dapp_details List details of a single Dapp + cli.js calculate_captcha_solutions Calculate captcha solutions + cli.js batch_commit Batch commit user solutions to contract + cli.js version Return the version of the software + +Options: + --help Show help [boolean] + --version Show version number [boolean] + --api [boolean] [default: false] + +``` diff --git a/packages/procaptcha-react/README.md b/packages/procaptcha-react/README.md index 3f309db0c5..5717b48c67 100644 --- a/packages/procaptcha-react/README.md +++ b/packages/procaptcha-react/README.md @@ -1,8 +1,9 @@ -# React Prosopo Procaptcha Component Library +# Prosopo Procaptcha React Component Library React components for integrating the Prosopo [procaptcha](https://github.com/prosopo/procaptcha) into a React app. -Prosopo is a distributed human verification service that can be used to stop bots from interacting with smart contracts. Sign up to be a network [alpha tester](https://5b06hrhtlmh.typeform.com/to/vNpyOUfg). +Prosopo is a distributed human verification service that can be used to stop bots from interacting with your apps. +Sign up to be a network [beta tester](https://prosopo.io/#signup). ## Installation @@ -14,73 +15,118 @@ npm install @prosopo/procaptcha-react --save ## Basic Usage -See the [client example](https://github.com/prosopo/client-example) for a minimal example of these components being used in a frontend app. +See the [client example](https://github.com/prosopo/client-example) for a minimal example of these components being used +in a frontend app. -```typescript - - - - - {showCaptchas && - } - - - {!showCaptchas && - } - - +```jsx + ``` ### Callbacks -`CaptchaEventCallbacks` are passed to the captcha component at creation. -```typescript -const clientInterface = useCaptcha({ config }, { onAccountChange, onChange, onSubmit, onSolved, onCancel }); -``` +`ProcaptchaEvents` are passed to the captcha component at creation. The captcha event callbacks are defined as follows: ```typescript -export interface CaptchaEventCallbacks extends ICaptchaClientEvents, ICaptchaStateClientEvents { } - -export interface ICaptchaClientEvents { - onLoad?: (extension: IExtensionInterface, contractAddress: string) => void; - onAccountChange?: (account?: TExtensionAccount) => void; -} - -export interface ICaptchaStateClientEvents { - onLoadCaptcha?: (captchaChallenge: GetCaptchaResponse | Error) => void; - onSubmit?: (result: TCaptchaSubmitResult | Error, captchaState: ICaptchaState) => void; - onChange?: (captchaSolution: number[][], index: number) => void; - onCancel?: () => void; - onSolved?: (result: TCaptchaSubmitResult, isHuman?: boolean) => void; +/** + * A list of all events which can occur during the Procaptcha process. + */ +export interface ProcaptchaEvents { + onError: (error: Error) => void + onAccountNotFound: (address: string) => void + onHuman: (output: ProcaptchaOutput) => void + onExtensionNotFound: () => void + onExpired: () => void + onFailed: () => void } ``` -#### onAccountChange +### onHuman + +The `onHuman` callback is called when the user has successfully completed the captcha challenge. The `ProcaptchaOutput` +object contains the following fields: + +| Key | Type | Description | +|--------------|--------|-------------------------------------------------------------------------------------------------------------------------------| +| commitmentId | string | The commitment ID of the captcha challenge. This is used to verify the user's response on-chain. | +| providerUrl | string | The URL of the provider that the user used to solve the captcha challenge. | +| dapp | string | The SITE_KEY of your application / website | +| user | string | The user's account address | +| blockNumber | number | The block number of the captcha challenge. This is used to verify that the contacted provider was randomly selected on-chain. | + +### onError + +The `onError` callback is called when an error occurs during the captcha process. The `Error` object is a standard +JavaScript error. -When an account is connected or disconnected. +### onAccountNotFound -#### onLoadCaptcha +The `onAccountNotFound` callback is called when the user's account is not found in the Procaptcha config in +the [`userAccountAddress`](https://github.com/prosopo/captcha/blob/0bb4850adfe2b995dc16f7dd18e6ea844a0b6997/packages/types/src/config/config.ts#L116) field. -After a captcha challenge has loaded/failed to load, updates captchaChallenge state and resets captchaIndex. +### onExpired -#### onChange +The `onExpired` callback is called when the captcha challenge has expired. This can occur if the user takes too long to +complete the challenge. -When the captchaSolution is updated (after clicking an image). +### onFailed -#### onSubmit +The `onFailed` callback is called when the user has failed the captcha challenge. This can occur if the user answers the +challenge incorrectly. -Event fired after captcha solution has been submitted. Resets captchaSolution state. +## Add the Procaptcha Widget to your Web page using a React Component + +You can see Procaptcha being used as a React component in +our [React Demo](https://github.com/prosopo/captcha/blob/main/demos/client-example/src/App.tsx). + +The Procaptcha component is called as follows: + +```tsx + + + +``` + +A config object is required and must contain your SITE_KEY. The callbacks are optional and can be used to handle the +various Procaptcha events. The following config demonstrates the `REACT_APP_DAPP_SITE_KEY` variable being pulled from +environment variables. + +```tsx +const config: ProcaptchaConfigOptional = { + account: { + address: process.env.REACT_APP_DAPP_SITE_KEY || undefined, + }, + web2: 'true', + dappName: 'client-example', + defaultEnvironment: 'rococo', + networks: { + rococo: { + endpoint: 'wss://rococo-contracts-rpc.polkadot.io:443', + contract: { + address: '5HiVWQhJrysNcFNEWf2crArKht16zrhro3FcekVWocyQjx5u', + name: 'prosopo', + }, + }, + }, + solutionThreshold: 80, +} +``` -#### onSolved +### Config Options -When captcha is solved. after clearing captchaChallenge. +| Key | Type | Description | +|--------------------|--------|-----------------------------------------------------------------------------------------| +| account | string | The SITE_KEY you received when you signed up | +| web2 | string | Set to `true` to enable web2 support | +| dappName | string | The name of your application / website | +| defaultEnvironment | string | The default environment to use - set to `rococo` | +| networks | object | The networks your application supports - copy paste this from the config above | +| solutionThreshold | number | The percentage of captcha that a user must have answered correctly to identify as human | -#### onCancel +## Verify the User Response Server Side -When captcha is dismissed. before clearing captchaChallenge. +Please see the main [README](https://github.com/prosopo/captcha/blob/main/README.md) for instructions on how to implement the server side of Procaptcha. diff --git a/packages/server/README.md b/packages/server/README.md new file mode 100644 index 0000000000..8d0c53f96b --- /dev/null +++ b/packages/server/README.md @@ -0,0 +1,47 @@ +# @prosopo/server + +npm package to make verifying Procaptcha soltions easy. + +## Installation + +You can install this library with: + +```bash +npm install @prosopo/server --save +``` + +## Basic Usage + +Simply import the `ProsopoServer` class and instantiate it with your Procaptcha API key. + +```typescript +import {ApiParams, ProcaptchaResponse} from '@prosopo/types' +import {ProsopoServer} from '@prosopo/server' + +async function getProsopoServer() { + const config = getProsopoConfig() + const pairType = (process.env.PAIR_TYPE as KeypairType) || ('sr25519' as KeypairType) + const ss58Format = parseInt(process.env.SS58_FORMAT || '') || 42 + const pair = await getPair(pairType, ss58Format, process.env.REACT_APP_SERVER_MNEMONIC) + const prosopoServer = new ProsopoServer(pair, config) +} + +async function protectedFunction(server: ProsopoServer, payload: ProcaptchaResponse) { + + if (await server.isVerified(payload[ApiParams.procaptchaResponse])) { + // perform CAPTCHA protected action + } + +} + +const payload = getPayloadFromRequest() // your request payload +getProsopoServer().then((server) => { + protectedFunction(server, payload).then(() => { + // ... + }) +}) + + +``` + +The full example can be seen [here](https://github.com/prosopo/captcha/blob/main/demos/client-example-server/src/app.ts).