# On-Chain KYC

This guide provides the steps and instructions for integrating Privado ID-based KYC verification directly in your frontend application, utilizing the **Privado ID verifier API** at `https://verifier-backend.privado.id`.

***

#### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

Before you begin integrating Privado ID verification, ensure you have the following:

* A **React-based frontend**.
* **Frontend access** to `https://verifier-backend.privado.id` for generating QR codes and checking the verification status.
* The `qrcode.react` npm package for rendering QR codes.

***

#### Integration Steps <a href="#integration-steps" id="integration-steps"></a>

**Step 1: Set up Frontend Components**

The frontend will be responsible for interacting with users, displaying the QR code, and updating the verification status.

**1.1 React Components**

* **StatusCard**: A component that shows the current KYC status (e.g., "Pending", "Verifying", "Approved", or "Failed").
* **QRCodeSection**: Displays the QR code generated for the user to scan with their Privado ID wallet.
* **ActionButtons**: Provides buttons like "Start KYC" and "Retry" to allow users to interact with the verification process.

```javascript
// Example for displaying QR code and status
import React, { useState } from 'react';
import { handlePolygonVerification, pollVerificationStatus } from './api'; // Functions to initiate verification and poll status

const KYCPage = () => {
  const [status, setStatus] = useState('pending');
  const [qrCode, setQrCode] = useState(null);
  const [sessionID, setSessionID] = useState(null);

  const startVerification = async () => {
    const result = await handlePolygonVerification();
    setQrCode(result.qrCode);
    setSessionID(result.sessionID);
    setStatus('verifying');
    pollVerificationStatus(result.sessionID, setStatus); // Poll verification status
  };

  return (
    <div>
      <h1>Privado ID KYC Verification</h1>
      <LhStatusCard status={status} />
      {status === 'verifying' && <LhQRCodeSection qrCode={qrCode} />}
      <LhActionButtons onClick={startVerification} />
    </div>
  );
};
```

**1.2 Handle Verification Requests**

Use a function to send a **POST** request to the Privado ID API to generate the QR code.

```javascript
// Function to handle verification request
export const handlePolygonVerification = async () => {
  const response = await fetch('https://verifier-backend.privado.id/sign-in', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      chainID: "1952959480", - Lumia Testnet
      scope: [
        {
          circuitId: "credentialAtomicQueryMTPV2",
          id: 1734435086,
          query: {
            allowedIssuers: ["*"],
            context: "https://raw.githubusercontent.com/shiva-decrypt/lumai-json/main/lumiav2.jsonld",
            type: "KYC",
            credentialSubject: {
              Kyc_Approved: { "$eq": true }
            }
          }
        }
      ],
      skipClaimRevocationCheck: false
    })
  });

  const data = await response.json();
  return {
    qrCode: data.qrCode,
    sessionID: data.sessionID,
  };
};
```

**Explanation of the `body` Section in the Request**

The `body` of the request is a JSON object sent to the Privado ID verifier backend. Here's a breakdown of its components:

***

**1. `chainID: "XXXXXXX"`**

* Specifies the blockchain network used.
* `1952959480` corresponds to the Lumia Testnet.
* `994873017` corresponds to the Lumia Mainnet (Prism)

***

**2. `scope`**

* **Purpose**: Defines the query parameters and the type of credential to verify.
* Contains an array of query objects. Each query object includes:
  * `circuitId`: `"credentialAtomicQueryMTPV2"`
    * Specifies the type of cryptographic circuit used for verification.
    * In this case, it's `credentialAtomicQueryMTPV2`, which supports secure and private verification of claims.
  * `id`: `1734435086`
    * A unique identifier for the query.
  * `query`: Describes the claim or condition to be checked.
    * **`allowedIssuers`: `["*"]`**
      * Allows credentials from any issuer (`*`).
    * **`context`**:
      * A URL pointing to the JSON-LD schema defining the structure of the credential.
      * In this case, it links to a schema stored in a GitHub repository.
    * **`type`: `"KYC"`**
      * Specifies the type of credential being validated.
    * **`credentialSubject`**:
      * Defines the specific conditions the credential must meet.
      * In this example, `Kyc_Approved: { "$eq": true }` requires that the `Kyc_Approved` field in the credential is `true`.

***

**3. `skipClaimRevocationCheck: false`**

* Ensures that the claim revocation status is verified.
* If set to `true`, the verification would skip checking if the claim has been revoked, which might reduce security.

***

**Possible Modifications**

**1. Customizing Allowed Issuers**

* Instead of allowing any issuer (`allowedIssuers: ["*"]`), you can specify trusted issuers. **Example**:

  Copy

  ```
  "allowedIssuers": ["did:polygon:abc123", "did:polygon:def456"]
  ```

**2. Using a Custom Credential Type**

* Change the `type` from `"KYC"` to other credential types if needed. Ensure the schema in the `context` URL matches the new type.

**3. Dynamic `chainID` Selection**

* If your application supports multiple networks, the `chainID` can be dynamically passed based on the selected environment (e.g., mainnet or testnet).

**4. Revocation Check Skipping**

* For faster verification in non-critical use cases, set `skipClaimRevocationCheck` to `true`. However, this is not recommended for sensitive processes.

**5. Adding Additional Query Conditions**

* You can validate more fields by adding them to the `credentialSubject`. **Example**:

  Copy

  ```
  "credentialSubject": {
    "Kyc_Approved": { "$eq": true },
    "Age": { "$gte": 18 }
  }
  ```

  This ensures the user is at least 18 years old and has passed KYC.

**Step 2: Poll Verification Status**

After the QR code is generated, you need to periodically check the status of the verification to keep the user updated.

```javascript
// Function to poll verification status
export const pollVerificationStatus = async (sessionID, setStatus) => {
  const response = await fetch(`https://verifier-backend.privado.id/status?sessionID=${sessionID}`);
  const data = await response.json();

  if (data.status === 'success') {
    setStatus('approved');
  } 

  // Poll every 5 seconds until verification is completed
  if (data.status !== 'approved' && data.status !== 'failed') {
    setTimeout(() => pollVerificationStatus(sessionID, setStatus), 5000);
  }
};
```

**Step 3: Handle User Interaction**

Users can interact with the system by clicking the "Start KYC" button to initiate the verification process and retry if needed.

**Example UI Components**

```javascript
import { QRCodeSVG } from 'qrcode.react';

export const LhStatusCard = ({ status }) => {
  return (
    <div>
      <h2>Status: {status}</h2>
    </div>
  );
};

export const LhQRCodeSection = ({ qrCode }) => {
  return (
    <div>
    <QRCodeSVG
              value={qrCode}
              size={400}
              level="H"
              className="h-full w-full"
              includeMargin
              bgColor="#f3f4f6"
              fgColor="#4f46e5"
            />
    </div>
  );
};

export const LhActionButtons = ({ onClick }) => {
  return (
    <div>
      <button onClick={onClick}>Start KYC</button>
    </div>
  );
};
```

***

#### Final Steps <a href="#final-steps" id="final-steps"></a>

1. **Start the KYC Process**:
   * The user clicks the “Start KYC” button, triggering the `startVerification` function.
   * A **QR code** will be displayed for the user to scan with their Polygon ID wallet.
2. **Track the Verification Status**:
   * Once the user scans the QR code, the status will update to "Verifying."
   * The frontend will automatically poll the status every 5 seconds until the status is either "Approved" or "Failed."
3. **Handle Status Changes**:
   * Upon successful verification, the status will update to "Approved".
   * If verification fails, the user can click “Retry” to attempt the process again.

***

#### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

* **Issue**: QR code is not displayed.
  * **Solution**: Ensure that the API is returning a valid `qrCode` URL. Verify that your frontend is correctly displaying the image.
* **Issue**: Verification fails.
  * **Solution**: Confirm that the user's Privado ID wallet app is properly configured and connected to the internet.
* **Issue**: Status remains "Pending" for too long.
  * **Solution**: Ensure the sessionID is valid and being correctly used to check the verification status. You may also want to check for any issues with the Privado ID service.

***

#### Conclusion <a href="#conclusion" id="conclusion"></a>

By following this guide, you can integrate Privado ID verification directly into your frontend application, allowing users to verify their KYC status with ease. The process involves generating a QR code, tracking the status, and providing feedback to the user throughout the verification process.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lumia.org/build/on-chain-kyc.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
