npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@concordium/verification-web-ui

v0.1.0

Published

> A lightweight, framework-agnostic SDK for Concordium wallet integration and identity verification with pre-built UI components.

Readme

Concordium Verification WebUI

A lightweight, framework-agnostic SDK for Concordium wallet integration and identity verification with pre-built UI components.

npm version License TypeScript

Integrate Concordium wallet connections into your app with just a few lines of code. The SDK provides beautiful, responsive modals for desktop and mobile, handles all WalletConnect complexity, and supports Vue, React, and vanilla JavaScript.

Verification WebUI - Event-Driven Usage Guide

Architecture

SDK Responsibilities:
├── UI Modals (Landing, Scan, Processing, Success)
├── WalletConnect Session Management
├── QR Code Generation & Display
└── Event Emission

Merchant Responsibilities:
├── Listen to SDK Events
├── Create Presentation/ZKP Requests
├── Verify ZKP Responses
└── Handle Business Logic

Two Integration Modes

Case 1: SDK-Managed WalletConnect (Recommended)

SDK initializes WalletConnect, generates QR codes automatically.

Case 2: Merchant-Managed WalletConnect

Merchant manages WalletConnect, SDK only displays QR codes.


Installation

npm install @concordium/verification-web-ui

Case 1: SDK-Managed WalletConnect

Step 1: Initialize SDK

import { ConcordiumVerificationWebUI } from '@concordium/verification-web-ui';
import '@concordium/verification-web-ui/styles';

const sdk = new ConcordiumVerificationWebUI({
    network: 'testnet', // or 'mainnet'
    projectId: 'YOUR_WALLETCONNECT_PROJECT_ID',
    metadata: {
        name: 'Your App Name',
        description: 'Your app description',
        url: 'https://yourapp.com',
        icons: ['https://yourapp.com/icon.png'],
    },
});

Step 2: Listen to SDK Events

window.addEventListener('@concordium/verification-web-ui-event', async (event) => {
    const { type, data } = event.detail;

    switch (type) {
        case 'session_approved':
            await handleSessionApproved(data);
            break;

        case 'presentation_received':
            await handlePresentationReceived(data);
            break;

        case 'session_disconnected':
            handleDisconnected(data);
            break;

        case 'error':
            handleError(data);
            break;
    }
});

Step 3: Show Connection Modal

// This will:
// 1. Initialize WalletConnect
// 2. Generate QR code
// 3. Show scan modal
await sdk.renderUIModals();

Step 4: Handle Session Approval

When user scans QR code, SDK emits session_approved:

async function handleSessionApproved(sessionData) {
    const { topic, accounts, namespaces } = sessionData;

    console.log('Session approved!');
    console.log('Topic:', topic);
    console.log('Accounts:', accounts);

    // Create your presentation request
    const presentationRequest = {
        challenge: generateChallenge(), // Your challenge generation
        credentialSubject: {
            attributes: ['age'],
            threshold: 18,
            operator: 'gte',
        },
    };

    // Send request through SDK
    await sdk.sendPresentationRequest(presentationRequest);
}

Step 5: Handle ZKP Response

When wallet responds, SDK emits presentation_received:

async function handlePresentationReceived(zkpResponse) {
    // Verify the ZKP proof at your backend or locally
    const isValid = await verifyProof(zkpResponse);

    if (isValid) {
        // Show success state in SDK
        await sdk.showSuccessState();

        // Your business logic
        onVerificationSuccess(zkpResponse);
    } else {
        console.error('Verification failed');
        sdk.closeModal();
    }
}

Case 2: Merchant-Managed WalletConnect

Step 1: Initialize Your Own WalletConnect

import { SignClient } from '@walletconnect/sign-client';

const wcClient = await SignClient.init({
    projectId: 'YOUR_PROJECT_ID',
    metadata: {
        /* ... */
    },
});

const { uri, approval } = await wcClient.connect({
    requiredNamespaces: {
        ccd: {
            methods: ['request_verifiable_presentation_v1'],
            chains: ['ccd:4221332d34e1694168c2a0c0b3fd0f27'],
            events: [],
        },
    },
});

Step 2: Show QR Code via SDK

import { ConcordiumVerificationWebUI } from '@concordium/verification-web-ui';

const sdk = new ConcordiumVerificationWebUI({ network: 'testnet' });

// SDK will display the QR code
await sdk.showWalletConnectPopup(uri);

Step 3: Handle Session Approval

const session = await approval();

// SDK emits session_approved event
window.addEventListener('@concordium/verification-web-ui-event', async (event) => {
    if (event.detail.type === 'session_approved') {
        // Send your presentation request through YOUR WalletConnect client
        const response = await wcClient.request({
            topic: session.topic,
            chainId: 'ccd:4221332d34e1694168c2a0c0b3fd0f27',
            request: {
                method: 'request_verifiable_presentation_v1',
                params: yourPresentationRequest,
            },
        });

        // Verify and show success
        if (await verifyProof(response)) {
            await sdk.showSuccessState();
        }
    }
});

Existing Session Usage

If you already have an active WalletConnect session:

// Send a new request to existing session
await sdk.sendRequestToExistingSession(presentationRequest, existingSessionTopic);

// SDK will:
// 1. Show processing modal
// 2. Send request
// 3. Emit presentation_received event

SDK Events Reference

session_approved

Emitted when WalletConnect session is established.

{
  type: 'session_approved',
  data: {
    topic: string,
    accounts: string[],
    namespaces: Record<string, any>
  }
}

presentation_received

Emitted when ZKP response is received from wallet.

{
  type: 'presentation_received',
  data: {
    verifiablePresentation: any,
    presentationContext: any,
    proof: any,
    type: any,
    verifiableCredential: any
  }
}

session_disconnected

Emitted when WalletConnect session is disconnected.

{
  type: 'session_disconnected',
  data: {
    topic: string
  }
}

error

Emitted when any error occurs.

{
  type: 'error',
  data: {
    message: string,
    error: any
  }
}

SDK Methods Reference

renderUIModals()

Initialize and show connection modal (SDK-managed mode).

await sdk.renderUIModals();

showWalletConnectPopup(uri, onClose?)

Display QR code for merchant-provided URI.

await sdk.showWalletConnectPopup(walletConnectUri);

sendPresentationRequest(request, sessionTopic?)

Send ZKP/presentation request through WalletConnect.

await sdk.sendPresentationRequest({
    challenge: 'your-challenge',
    credentialSubject: {
        /* ... */
    },
});

sendRequestToExistingSession(request, sessionTopic)

Send request to existing session with processing modal.

await sdk.sendRequestToExistingSession(request, topic);

showSuccessState()

Display success state in processing modal.

await sdk.showSuccessState();

closeModal()

Close any open modal.

sdk.closeModal();

getCurrentSession()

Get current active session.

const session = sdk.getCurrentSession();

Complete Example (Vue 3)

<template>
  <div>
    <button @click="connect">Connect Wallet</button>
    <div v-if="connected">
      <button @click="verify">Verify Age</button>
      <p v-if="verified">✅ Verified!</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { ConcordiumVerificationWebUI } from '@concordium/verification-web-ui';
import '@concordium/verification-web-ui/styles';

const connected = ref(false);
const verified = ref(false);
let sdk;

onMounted(() => {
  sdk = new ConcordiumVerificationWebUI({
    network: 'testnet',
    projectId: process.env.VUE_APP_WC_PROJECT_ID,
    metadata: {
      name: 'My App',
      description: 'Age verification app',
      url: window.location.origin,
      icons: [`${window.location.origin}/logo.png`],
    },
  });

  // Listen to SDK events
  window.addEventListener(
    '@concordium/verification-web-ui-event',
    handleSDKEvent
  );
});

async function handleSDKEvent(event) {
  const { type, data } = event.detail;

  if (type === 'session_approved') {
    connected.value = true;

    // Automatically send age verification request
    const request = {
      challenge: generateChallenge(),
      credentialSubject: {
        attributes: ['age'],
        threshold: 18,
      },
    };

    await sdk.sendPresentationRequest(request);
  }

  if (type === 'presentation_received') {
    // Verify the proof
    const isValid = await verifyAtBackend(data);

    if (isValid) {
      verified.value = true;
      await sdk.showSuccessState();

      // Auto-close after 2 seconds
      setTimeout(() => sdk.closeModal(), 2000);
    }
  }

  if (type === 'error') {
    console.error('SDK Error:', data);
    alert('Verification failed');
  }
}

async function connect() {
  await sdk.renderUIModals();
}

async function verify() {
  // Re-verify using existing session
  const session = sdk.getCurrentSession();
  if (session) {
    await sdk.sendRequestToExistingSession(
      createVerificationRequest(),
      session.topic
    );
  }
}

function generateChallenge() {
  return crypto.randomUUID();
}

async function verifyAtBackend(zkpResponse) {
  // Your verification logic
  const response = await fetch('/api/verify', {
    method: 'POST',
    body: JSON.stringify(zkpResponse),
  });
  return response.ok;
}
</script>