WalletHandlers


The WalletHandlers class is a high-level utility designed to seamlessly integrate the DID Connect workflow into an Express.js or similar server-side framework. It automates the setup of all required API endpoints for a given action, handling the communication between your application and the user's DID Wallet.

It works in tandem with the WalletAuthenticator, which manages the cryptographic signing and verification of messages. Since WalletHandlers is built on Node.js's EventEmitter, you can listen for various lifecycle events as the session state changes in your token storage.

Constructor#

Creates an instance of the DID Connect handlers. This instance orchestrates the handling of HTTP requests for the DID Connect process.

DID Connect Handler Setup

const { WalletHandlers } = require('@did-connect/handler');
const { WalletAuthenticator } = require('@did-connect/authenticator');
const { FileStorage } = require('@did-connect/storage-file');

// 1. Initialize the authenticator with your app's wallet and info
const authenticator = new WalletAuthenticator({ wallet, appInfo, chainInfo });

// 2. Initialize a storage adapter to manage session state
const tokenStorage = new FileStorage({ dbPath: './sessions.json' });

// 3. Create the handlers instance
const handlers = new WalletHandlers({
  authenticator,
  tokenStorage,
});

Parameters#

config
object
required
Configuration object for the WalletHandlers instance.
5 subfields

Methods#

attach(config)#

This is the primary method of the WalletHandlers class. It attaches the necessary DID Connect routes to your Express app for a specific user action (e.g., 'login', 'payment'). This method creates a full set of endpoints to handle the entire connection lifecycle, from token generation to wallet response handling.

Once attached, the following routes are created for the given action:

  • GET {prefix}/{action}/token: Creates a new session token.
  • POST {prefix}/{action}/token: Creates a new session token.
  • GET {prefix}/{action}/status: Checks the status of a session token (e.g., pending, scanned, approved).
  • GET {prefix}/{action}/timeout: Manually expires a session token.
  • GET {prefix}/{action}/auth: The endpoint for the wallet to fetch authentication requirements.
  • POST {prefix}/{action}/auth: The endpoint for the wallet to submit the signed response.

Parameters#

config
object
required
Configuration object for attaching the routes.
12 subfields

Example#

Attach Login Handler

const express = require('express');
// ... setup for authenticator and tokenStorage from the constructor example

const app = express();
const handlers = new WalletHandlers({ authenticator, tokenStorage });

handlers.attach({
  app,
  action: 'login',
  claims: [{ type: 'profile' }], // Request user's profile
  onAuth: async ({ userDid, claims }) => {
    // Core logic after a successful login.
    // Find or create a user in your database with userDid.
    const profile = claims.find(x => x.type === 'profile');
    console.log(`User ${userDid} logged in with name: ${profile.fullName}.`);
    // You can now set a cookie or JWT for the user's web session.
  },
  onComplete: ({ token }) => {
    console.log(`Session ${token} completed and cleaned up.`);
  },
  onError: ({ error }) => {
    console.error('An error occurred in the login flow:', error);
  }
});

See all 3 lines

Events#

Since WalletHandlers extends EventEmitter and listens to the tokenStorage instance, you can subscribe to events to monitor the session lifecycle. This is particularly useful for providing real-time feedback to the user, for example, by using WebSockets to update the UI when a QR code is scanned.

Event

Payload

Description

created

object

Emitted when a new session token is created. The payload contains the token and initial session data.

updated

object

Emitted when a session is updated. The payload includes the updated session data. A common use is to check for status: 'scanned'.

deleted

object

Emitted when a session token is destroyed, either upon completion, expiration, or manual timeout. The payload contains the token that was removed.

Example#

Listening to Session Events

// Assuming 'io' is a Socket.IO server instance attached to your Express app
handlers.on('updated', (payload) => {
  // Notify the specific web client that the QR code has been scanned
  if (payload.status === 'scanned') {
    console.log(`Wallet scanned token: ${payload.token}`);
    // The 'sid' (socket ID) should be stored in the session when it's created
    if (payload.sid) {
      io.to(payload.sid).emit('wallet_scanned');
    }
  }
});

handlers.on('deleted', ({ token }) => {
  console.log(`Token ${token} was deleted from storage.`);
});