Quadrata Integration
  • INTRODUCTION
    • Introduction to Quadrata
    • Passport Attributes
  • HOW TO INTEGRATE
    • Quadrata SDK
      • Get Started Quickly
      • Advanced
        • Installation
        • SDK Configuration
        • Onboarding Example
        • Client Libraries
          • Client Configuration
          • Client Lazy Loading
          • Client Eager Loading
          • Client Helper Component
          • Client React Hooks
            • useOnboardStatus
          • Client Examples
            • With Wagmi Connect
            • KYC Only
            • KYB Only
            • All In One
        • API Libraries
          • API Configuration
          • API Service Options
          • API Service Libraries
            • Create Access Token
            • Create Privacy Access Token
            • Fetch Attribute Values
            • Fetch Onboard Status
            • Fetch Passport List
            • Fetch Privacy Data
            • Fetch Privacy Grants
            • Fetch Wallet Screening
            • Revoke Privacy Grants
    • Onboard users
      • Individual Passport Onboarding
        • 1. Installation
        • 2. API Authentication
        • 3. API Onboard Status
        • 4. QuadClient Package
        • 5. Privacy Data Permissions
        • 6. Full Example
      • Business Passport Onboarding
        • 1. Installation
        • 2. API Authentication
        • 3. QuadrataKyb Package
        • 4. Privacy Data Permissions
        • 5. Full Example
      • All-In-One Passport Onboarding
        • 1. Installation
        • 2. API Authentication
        • 3. QuadrataReact Package
        • 4. Full Example
    • Request Privacy Data
      • List of Privacy Data
      • Privacy Data Permissions
      • API Requests
        • How to sign API
          • Full Example
          • Generate ECDSA Key Pair
        • API Get Privacy Permissions
        • API Privacy Access Token
        • API Get Privacy Data
        • API Revoke Permissions
    • Query attributes
      • Via Smart Contract
        • Query a single attribute
        • Query multiple attributes
        • Query Helper
      • Via API
    • On-Chain Wallet Screening
      • How to sign API
        • Full Example
        • Generate ECDSA Key Pair
      • API Get On-Chain AML Score
    • Webhooks
      • Onboarding Webhooks
      • Ongoing Monitoring Webhooks
      • Webhook Request Signature
    • Burn Passports
  • additional information
    • Smart contracts
    • Quadrata Sandbox
    • Passport Issuers
    • Privileged Roles & Ownership
    • Constants
    • Flex Kit Attributes
      • Smart Contract Addresses
Powered by GitBook
On this page
  • Check the status of attributes, both on chain and off chain.
  • Example
  • Check the status of a passport
  • Privacy Status
  1. HOW TO INTEGRATE
  2. Onboard users
  3. Individual Passport Onboarding

3. API Onboard Status

V2 Onboard Status API

Check the status of attributes, both on chain and off chain.

Quadrata provides an API for integrators to call to see which attributes have been issued for a given wallet user.

Production URL: https://prod.quadrata.com/api/v2/attributes/onboard_status

GET https://int.quadrata.com/api/v2/attributes/onboard_status

Returns the status of attributes passed in to the query string, including (optionally) whether or not they have been minted on chain and when the attribute status was last verified.

Also includes an optional list of privacy data permissions indicating when a permission was allowed or revoked and if the permission has not yet been granted consent for your dApp.

Query Parameters

Name
Type
Description

wallet*

String

User Wallet Address

chainId

String

Blockchain chain id

If not provided, on chain status is not checked and mintedOnChain is omitted from the response

attributes*

List[String]

List of Required Attributes

privacyScopes

List[String]

List of Privacy Data parameters to check for existing permissions

If not provided, privacyStatus is omitted from the response.

offeringId

String

String to check the Accreditation status (INVESTOR_STATUS) of a specific company offering.

If not provided, offeringStatus is omitted from the response.

Headers

Name
Type
Description

Authorization: Bearer [JWT Token]*

String

JWT accessToken (returned by /api/v1/login)

// Example Response
{
  "type": "attributes",
  "offeringStatus": {
      "INVESTOR_STATUS": {
          "status": "READY",          // "IN_REVIEW", "NA", "NOT_APPLICABLE", "READY"
          "verifiedAt": 1682560310,   // Date when the attribute has been last verified
      }
  },
  "onboardStatus": {
    "DID":  {
      "status": "READY",          // "IN_REVIEW", "NA", "NOT_APPLICABLE", "READY"
      "onboardedAt": 1682560310,  // Date when the attribute has been last verified
      "mintedOnchain": true,      // If the attribute value has been minted/updated onchain
    },
    "AML":  {
      "status": "IN_REVIEW",
      "onboardedAt": 1682560310,  // Date when the attribute has been last verified
      "mintedOnchain": false,     // not updated onchain yet
    },
  },
  "privacyStatus": {
    "FN": {
      "status": "ALLOWED",        // currently granted
      "allowedAt": 1682560310     // date when consent was granted
    },
    "EM": {
      "status": "REVOKED",              // previously granted but since revoked
      "allowedAt": 1682560310,          // date when consent was last granted
      "revokedAt": 1682580310,          // date when consent was revoked
      "revokedReason": "USER_REVOKED"   // reason for revoke (in consent table)
    },
    "ADR": {
      "status": "NEEDS_CONSENT"   // consent not yet given
    }
  }
}

Example

import React from "react";

// Ethers
import {id} from "ethers/lib/utils";

// RainbowKit + Wagmi
import { ConnectButton } from "@rainbow-me/rainbowkit";
import { useAccount } from "wagmi";

// Quadrata Client
import {
    QuadClient, 
    QuadAttribute, 
    PrivacyConsentScopeParamKey,
    PrivacyConsentScopeParams
} from "@quadrata/client-react";

export interface AttributeOnboardStatusDto {
    data: {
        type: 'attributes';
        onboardStatus:{
            [attributeName: string]: {
                status: string;
                onboardedAt?: number;
                mintedOnchain?: boolean;
            };
        };
        offeringStatus?: {
            [attributeName: string]: {
                status: string;
                verifiedAt?: number;
            };
        };
        privacyStatus?: {
            [privacyPermission: string]: {
                status: string;
                allowedAt?: number;
                revokedAt?: number;
                revokedReason?: string;
            };
        };
    };
}

function getAttributesToClaim(onboardStatus: any, isBypassMint: boolean) {
    const attributesToClaim = [];
    for (const attributeName in onboardStatus) {
        const { status, mintedOnchain } = onboardStatus[attributeName];
        if (
            (status !== AttributeStatus.READY && status !== 'NOT_APPLICABLE') ||
            (!isBypassMint && !mintedOnchain && status === AttributeStatus.READY)
        ) {
            attributesToClaim.push(attributeName as QuadAttribute);
        }
    }
    return attributesToClaim;
}

function checkConsentNeeded(privacyStatus: any) {
    if (privacyStatus) {
        for (const privacyScopeKey in privacyStatus) {
            const { status } = privacyStatus[privacyScopeKey];
            if (status !== 'ALLOWED') {
                // if any permission is not allowed, all of the desired 
                // permissions need to be requested again
                return true;
            }
        }
    }
    return false;
}

export function parseOnboardStatusResponse(
    resp: AttributeOnboardStatusDto,
    isBypassMint: boolean = false
) {
    const { data: { onboardStatus, privacyStatus, offeringStatus } } = resp;

    const attributesToClaim = getAttributesToClaim(onboardStatus, isBypassMint);
    const isConsentNeeded = checkConsentNeeded(privacyStatus);

    if (offeringStatus) {
        // merge attribute to attest from offeringStatus into attributesToClaim
        const attributesToAttest = getAttributesToClaim(offeringStatus, true);
        for (const name of attributesToAttest) {
            if (!attributesToClaim.includes(name)) {
                attributesToClaim.push(name);
            }
        }
    }

    return { attributesToClaim, isConsentNeeded };
}

export const MyComponent: React.FC = () => {
    // state
    const [attributesToClaim, setAttributesToClaim] = useState<QuadAttribute[]>([]);
    const [privacyScopes, setPrivacyScopes] = useState<PrivacyConsentScopeParamKey[]>([]);

    // JWT accessToken returned by /api/v1/login
    const accessToken = '.............';    
    
    // Blockchain chainId (optional)
    const chainId = 1;        
    
    // Required Attributes
    const requiredAttributes = [QuadAttribute.DID, QuadAttribute.AML, QuadAttribute.COUNTRY];
    
    // Required Privacy Permissions (optional)
    const requiredPrivacyScopes = [
        PrivacyConsentScopeParams.FN,
        PrivacyConsentScopeParams.LN,
        PrivacyConsentScopeParams.EM,
        PrivacyConsentScopeParams.DOB
    ];
    
    // set this to true if you want to bypass minting on chain
    const isBypassMint = false;
    
    // Current Wallet connected
    const account = useAccount();
    if (!account) {
        return <ConnectButton/>;
    }
    
    const apiAttributesOnboardStatus = async () => {
        setIsLoading(true);
        const { NEXT_PUBLIC_QUADRATA_API_URL } = process.env;
        const attributes = requiredAttributes
            .map((attr) => attr.toLowerCase())
            .join(',');
        const privacyScopes = requiredPrivacyScopes.join(',');
        const url = `${NEXT_PUBLIC_QUADRATA_API_URL}/api/v2/attributes/onboard_status?wallet=${account}&chainId=${chainId}&attributes=${attributes}&privacyScopes=${privacyScopes}`;
        const headers = {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${accessToken}`,
        };
        
        const response = await fetch(url, { method: 'GET', headers });
        
        if (!response.ok) {
            setIsLoading(true);
            setError(true);
            throw new Error('Onboard status failed');
        }
        return (await response.json()) as AttributeOnboardStatusDto;
    };
    
    useQuery(
        'QUAD_API_ATTR_ONBOARD_STAUS', 
        () => apiAttributesOnboardStatus(), 
        {
            enabled: accessToken !== '',
            onSuccess: (resp: AttributeOnboardStatusDto) => {
                const { 
                    attributesToClaim, 
                    isConsentNeeded 
                } = parseOnboardStatusResponseForClient(resp, isBypassMint);
                
                setAttributesToClaim(attributesToClaim);
                setPrivacyScopes(
                    isConsentNeeded
                        ? requiredPrivacyScopes
                        : []
                );
            },
            onError: (err) => {
                throw new Error(`/attributes/onboard_status error : ${err}`);
            },
            retry: false,
        }
    );

    return (!!attributesToClaim.length || !!privacyScopes.length) ? (
        <QuadClient 
            bypassMint={isBypassMint}
            attributes={attributesToClaim} 
            privacyScopes={privacyScopes} 
        />
    ) : (
        <>
            <strong>
                Welcome, You have all required attributes and permissions.
            </strong>
        </>
    );
};

Check the status of a passport

Quadrata provides an API for integrators to call to see which attributes have been issued for a given wallet user, and whether or not those attributes have been minted on chain.

When a passport is claimed, the associated attributes are minted on chain, but remain in various states, internally, until then.

If your application only needs to KYC the onboarding individual, bypassing the minting process altogether, then attributes are not minted on chain.

When integrating the Quadrata Passport UI, it's necessary to check the status of attributes so the onboarding process can determine which next steps to take. This check can also help integrators determine if onboarding is necessary before displaying a call to action that launches the UI flow.

Privacy Status

The Onboard Status API will give you an summary of which permissions have been allowed and which have not.

Previous2. API AuthenticationNext4. QuadClient Package

Last updated 1 year ago

See "" page

See the bypassMint property in the documentation page.

When integrating with , it's necessary to check the status of the permissions you need before launching the UI flow.

QuadClient Package
Privacy Data Permissions
List of Privacy Data