Installation and configuration
Quickstart
Goal: With the quick start example, you will get a complete and working application running in less than 15 minutes to verify user credentials. Follow the following steps to clone the starter repository, configure your Github token, and running a minimal Next.js application that uses the Averer Web SDK.
Prerequisites
- Node.js v18 or later
- A GitHub account with a Personal Access Token (classic) that has the
read:packagesscope
Step 1: Clone the starter kit
We've created a pre-configured Next.js starter kit with the basic backend and frontend structure already in place so you can use it as a guide for your implementation.
git clone https://github.com/averer/averer-websdk-quickstart.git
cd averer-websdk-quickstart
Step 2: Configure npm and install dependencies
The starter kit uses GitHub Packages for the @averer scope. To install Averer packages, you need to configure npm so it knows where to find them and how to authenticate.
- Create the
.npmrcfile: Inside theaverer-websdk-quickstartdirectory, edit a file named.npmrc - Add configuration: Paste the following lines into
.npmrc, replacingYOUR_GITHUB_TOKENwith your actual token.
@averer:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
- Install packages: Authenticate with your GitHub token when prompted.
npm install
Step 3: Setup env
Create a .env file by copying the .env.sample or use this command
cp .env.sample .env
Note: To obtain the
VITE_CONFIG_ID, please contact Averer support.
Step 4: Run the application
The starter kit is configured to run both the backend verifier and the frontend application at the same time.
npm run dev
This starts the Next.js app at http://localhost:3000, where you can complete your first eligibility check using the Averer Web SDK.
SDK Setup
Prerequisites
- Node.js v18 or later
Install the SDK
npm install @averer/averer-websdk
Initialise the SDK
The snippet below demonstrates how to render the SDK inside a Next.js App Router page. Adjust imports and component placement in your application.
Note: To obtain a
configId, please contact Averer support.
'use client';
import {
AvererWebSdk,
AvererSdkProvider,
type SdkQuery,
type SdkSuccessRes,
} from '@averer/averer-websdk';
export default function EligibilityPage() {
const sdkQuery: SdkQuery = [
{
id: 5,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
circuitId: 'credentialAtomicQuerySigV2' as any,
subjectTitle: 'Pass AML & CTF Checks',
query: {
allowedIssuers: [
'did:receptor:redbelly:testnet:31K3oHpCV428AkXUYTL89q6LCvHcSqHirdv7z6LHtu9',
],
type: 'AMLCTFCredential',
context:
'https://raw.githubusercontent.com/redbellynetwork/receptor-schema/refs/heads/main/schemas/json-ld/AMLCTFCredential.jsonld',
skipClaimRevocationCheck: true,
credentialSubject: {
amlCheckStatus: { $eq: 'passed' },
},
},
},
];
const handleSuccess = (data: SdkSuccessRes) => {
if (data.eligibility.passed) {
console.log('✅ Verification successful', data);
}
};
const handleError = (reason: string) => {
console.error('❌ Verification failed:', reason);
};
return (
<AvererSdkProvider configId="your-config-id">
<AvererWebSdk
appName="Refund"
sdkQuery={sdkQuery}
onSuccess={handleSuccess}
onError={handleError}
/>
</AvererSdkProvider>
);
}
For other examples on how to setup the queries based on your preferred Proof Method and Eligibility Criteria, refer to Choosing Your Proof Method and Configuring Eligibility Criteria
API Reference
The AvererWebSdkProps type defines the configuration for the AvererWebSdk component.
type AvererWebSdkProps = {
appName: string;
sdkQuery: SdkQuery;
onSuccess?: (data: SdkSuccessRes) => void;
onError?: (reason: string) => void;
};
- appName : Name of your application displayed in the averer-websdk UI.
- sdkQuery : Eligibility criteria the external user must satisfy.
- onSuccess : Callback fired when all queries are successfully proven.
- onError : Callback fired when the user cancels, rejects, or an error occurs in the SDK flow.
Sub-types Used
1. SdkQuery
type SdkQuery = Array<{
id: number;
circuitId: string;
subjectTitle: string;
optional?: boolean;
query: ZeroKnowledgeProofQuery;
params?: {
nullifierSessionId?: string | number;
};
}>;
- id : A unique numeric identifier for the query.
- circuitId : The identifier of the circuit used for zero-knowledge proof generation(e.g., credentialAtomicQuerySigV2).
- subjectTitle : A short title describing the verification purpose (e.g., “Age above 18 check”).
- query : Contains the proof requirements and constraints defined in ZeroKnowledgeProofQuery.
2. ZeroKnowledgeProofQuery
type ZeroKnowledgeProofQuery = {
allowedIssuers: string[];
context: string;
credentialSubject?: JsonDocumentObject;
proofType?: string;
skipClaimRevocationCheck?: boolean;
groupId?: number;
type: string;
};
- allowedIssuers : List of issuer DIDs permitted to provide the credential for this proof.
- context : JSON-LD context defining the schema/environment of the credential.
- credentialSubject : Data object describing the fields required from the user’s verifiable credential (e.g. age, citizenship).
- type : The credential type the query expects (e.g. a specific VC schema type).
3. SdkSuccessRes
type SdkSuccessRes = {
walletAddress: string;
user: {
email?: string;
isAuthenticated: boolean;
did?: string;
};
proofs: Array<{
id: string | number;
circuitId: string;
subjectTitle: string;
status: 'valid' | 'failed';
proofData: {
credentialType: string;
rawProof?: {
id: number | string;
circuitId: string;
vp?: {
type: string;
verifiableCredential: {
type: string | string[];
credentialSubject: JsonDocumentObject;
};
};
};
};
}>;
eligibility: {
passed: boolean;
summary: string;
};
};
-
proofs[].proofData.rawProof.vp.verifiableCredential.credentialSubject : Represents the actual credential data contained inside the user’s submitted verifiable credential. This includes the specific fields that were proven (for example: age, nationality, membership, etc.). This is the final resolved credential subject after verification.
-
eligibility.passed : Indicates whether the user satisfied all required proof checks.
Averer Wallet
Read only actions/Viem Public Client
If you want to read data from the blockchain, you will want a “Public Client” (Viem terminology)
import { useAvererWallet } from '@averer/averer-websdk';
const EnsName = () => {
const wallet = useAvererWallet();
const [ens, setEns] = useState<string | null>(null);
const fetchEnsName = async () => {
if (wallet) {
const publicClient = await wallet.getPublicClient();
const name = await publicClient.getEnsName({
address: wallet.address,
});
setEns(name);
}
};
return (
<div>
<button onClick={fetchEnsName}>Get ENS Name</button>
{ens && <p>ENS Name: {ens}</p>}
</div>
);
};
Write actions/Viem Wallet Client
If you want to write data to the blockchain, you will need a “Wallet Client” (Viem terminology), or a “Signer” (Ethers terminology). Both allow you to sign transactions with the private key.
const SendTransaction = () => {
const wallet = useAvererWallet();
const SendTransaction = async () => {
if (!wallet) {
console.error('No wallet connected');
return;
}
try {
const walletClient = await wallet.getWalletClient();
const txHash = await walletClient.sendTransaction({
to: '0xRecipientAddressHere',
value: 1000000000000000000n,
});
console.log('Transaction sent with hash:', txHash);
} catch (error) {
console.error('Error sending transaction:', error);
}
};
return (
<div>
<button onClick={SendTransaction}>Send Transaction</button>
</div>
);
};
Get balance
const WalletBalance = () => {
const avererWallet = useAvererWallet();
const [balance, setBalance] = useState<string | undefined>(undefined);
const fetchBalance = async () => {
if (avererWallet) {
const bal = await avererWallet.getBalance();
setBalance(bal);
}
};
return (
<div>
<button onClick={fetchBalance}>Get Wallet Balance</button>
{balance && <p>Balance: {balance} ETH</p>}
</div>
);
};
Sign a message
const SignMessageButton = () => {
const avererWallet = useAvererWallet();
const handleSignMessage = async () => {
if (!avererWallet) {
console.error('No Averer wallet connected');
return;
}
try {
const message = 'Hello from Averer Wallet!';
const signature = await avererWallet.signMessage(message);
console.log('Message signed successfully:', signature);
} catch (error) {
console.error('Error signing message:', error);
}
};
return <button onClick={handleSignMessage}>Sign Message</button>;
};