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";// Ethersimport {id} from"ethers/lib/utils";// RainbowKit + Wagmiimport { ConnectButton } from"@rainbow-me/rainbowkit";import { useAccount } from"wagmi";// Quadrata Clientimport { QuadClient, QuadAttribute, PrivacyConsentScopeParamKey, PrivacyConsentScopeParams} from"@quadrata/client-react";exportinterfaceAttributeOnboardStatusDto { 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; }; }; };}functiongetAttributesToClaim(onboardStatus:any, isBypassMint:boolean) {constattributesToClaim= [];for (constattributeNamein onboardStatus) {const { status,mintedOnchain } = onboardStatus[attributeName];if ( (status !==AttributeStatus.READY&& status !=='NOT_APPLICABLE') || (!isBypassMint &&!mintedOnchain && status ===AttributeStatus.READY) ) {attributesToClaim.push(attributeName asQuadAttribute); } }return attributesToClaim;}functioncheckConsentNeeded(privacyStatus:any) {if (privacyStatus) {for (constprivacyScopeKeyin privacyStatus) {const { status } = privacyStatus[privacyScopeKey];if (status !=='ALLOWED') {// if any permission is not allowed, all of the desired // permissions need to be requested againreturntrue; } } }returnfalse;}exportfunctionparseOnboardStatusResponse( resp:AttributeOnboardStatusDto, isBypassMint:boolean=false) {const { data: { onboardStatus,privacyStatus,offeringStatus } } = resp;constattributesToClaim=getAttributesToClaim(onboardStatus, isBypassMint);constisConsentNeeded=checkConsentNeeded(privacyStatus);if (offeringStatus) {// merge attribute to attest from offeringStatus into attributesToClaimconstattributesToAttest=getAttributesToClaim(offeringStatus,true);for (constnameof attributesToAttest) {if (!attributesToClaim.includes(name)) {attributesToClaim.push(name); } } }return { attributesToClaim, isConsentNeeded };}exportconstMyComponent:React.FC= () => {// stateconst [attributesToClaim,setAttributesToClaim] =useState<QuadAttribute[]>([]);const [privacyScopes,setPrivacyScopes] =useState<PrivacyConsentScopeParamKey[]>([]);// JWT accessToken returned by /api/v1/loginconstaccessToken='.............'; // Blockchain chainId (optional)constchainId=1; // Required AttributesconstrequiredAttributes= [QuadAttribute.DID,QuadAttribute.AML,QuadAttribute.COUNTRY];// Required Privacy Permissions (optional)constrequiredPrivacyScopes= [PrivacyConsentScopeParams.FN,PrivacyConsentScopeParams.LN,PrivacyConsentScopeParams.EM,PrivacyConsentScopeParams.DOB ];// set this to true if you want to bypass minting on chainconstisBypassMint=false;// Current Wallet connectedconstaccount=useAccount();if (!account) {return <ConnectButton/>; }constapiAttributesOnboardStatus=async () => {setIsLoading(true);const { NEXT_PUBLIC_QUADRATA_API_URL } =process.env;constattributes= requiredAttributes.map((attr) =>attr.toLowerCase()).join(',');constprivacyScopes=requiredPrivacyScopes.join(','); const url = `${NEXT_PUBLIC_QUADRATA_API_URL}/api/v2/attributes/onboard_status?wallet=${account}&chainId=${chainId}&attributes=${attributes}&privacyScopes=${privacyScopes}`;
constheaders= {'Content-Type':'application/json', Authorization:`Bearer ${accessToken}`, };constresponse=awaitfetch(url, { method:'GET', headers });if (!response.ok) {setIsLoading(true);setError(true);thrownewError('Onboard status failed'); }return (awaitresponse.json()) asAttributeOnboardStatusDto; };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) => {thrownewError(`/attributes/onboard_status error : ${err}`); }, retry:false, } );return (!!attributesToClaim.length||!!privacyScopes.length) ? ( <QuadClientbypassMint={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.
See the bypassMint property in the QuadClient Package documentation page.
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
When integrating with Privacy Data Permissions, it's necessary to check the status of the permissions you need before launching the UI flow.
The Onboard Status API will give you an summary of which permissions have been allowed and which have not.