Skip to content

Commit 6bf395c

Browse files
authored
Merge pull request #428 from docknetwork/qr-code-handler
qr code handlers
2 parents ad021a6 + aaf56c1 commit 6bf395c

6 files changed

Lines changed: 1357 additions & 0 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Built-in QR Code Handlers
3+
*
4+
* This module provides pre-built handlers for common protocols used in
5+
* decentralized identity wallets. These handlers can be used directly or
6+
* extended for custom behavior.
7+
*
8+
* ## Available Handlers
9+
*
10+
* - **OID4VCHandler**: OpenID for Verifiable Credentials (OID4VC)
11+
*
12+
* ## Usage
13+
*
14+
* ```typescript
15+
* import { OID4VCHandler } from '@docknetwork/wallet-sdk-core/src/qr-handlers/builtin';
16+
*
17+
* const handler = new OID4VCHandler({
18+
* onImportCredential: async (uri) => {
19+
* // Your credential import logic
20+
* return { success: true };
21+
* },
22+
* });
23+
*
24+
* processor.registerHandler(handler);
25+
* ```
26+
*
27+
* @module qr-handlers/builtin
28+
*/
29+
30+
export * from './oid4vc-handler';
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import {
2+
QRCodeContext,
3+
QRCodeHandler,
4+
QRCodeHandlerResult,
5+
} from '../types';
6+
7+
/**
8+
* Configuration options for OID4VC handler
9+
*/
10+
export interface OID4VCHandlerConfig {
11+
/**
12+
* URI prefixes to match (default: ['openid-credential-offer://'])
13+
*/
14+
uriPrefixes?: string[];
15+
16+
/**
17+
* Priority for this handler (default: 5)
18+
*/
19+
priority?: number;
20+
21+
/**
22+
* Callback to handle credential import
23+
* This is where app-specific logic (navigation, UI, etc.) should be implemented
24+
*
25+
* @param uri - The OID4VC URI to process
26+
* @param context - The full QR code context
27+
* @returns Result of the import operation
28+
*/
29+
onImportCredential: (
30+
uri: string,
31+
context: QRCodeContext,
32+
) => Promise<OID4VCImportResult>;
33+
}
34+
35+
/**
36+
* Result from importing an OID4VC credential
37+
*/
38+
export interface OID4VCImportResult {
39+
/**
40+
* Whether the import was successful
41+
*/
42+
success: boolean;
43+
44+
/**
45+
* Credential data if import succeeded
46+
*/
47+
credential?: any;
48+
49+
/**
50+
* Error if import failed
51+
*/
52+
error?: Error;
53+
54+
/**
55+
* Additional metadata
56+
*/
57+
metadata?: Record<string, any>;
58+
}
59+
60+
/**
61+
* Built-in handler for OID4VC (OpenID for Verifiable Credentials) URIs
62+
*
63+
* This is a generic handler that can be configured with app-specific callbacks
64+
* for importing credentials. The handler itself only handles protocol detection
65+
* and delegates the actual import logic to the configured callback.
66+
*
67+
* ## Example Usage
68+
*
69+
* ```typescript
70+
* import { OID4VCHandler } from '@docknetwork/wallet-sdk-core/src/qr-handlers/builtin';
71+
* import { getCredentialProvider } from '@docknetwork/wallet-sdk-react-native';
72+
*
73+
* const handler = new OID4VCHandler({
74+
* onImportCredential: async (uri, context) => {
75+
* try {
76+
* // Use SDK to import credential
77+
* await getCredentialProvider().importCredentialFromURI({
78+
* uri,
79+
* didProvider: getDIDProvider(),
80+
* getAuthCode: async (authUrl) => {
81+
* // App-specific auth handling
82+
* return await showAuthWebView(authUrl);
83+
* },
84+
* });
85+
*
86+
* return { success: true };
87+
* } catch (error) {
88+
* return {
89+
* success: false,
90+
* error: error instanceof Error ? error : new Error(String(error)),
91+
* };
92+
* }
93+
* },
94+
* });
95+
*
96+
* processor.registerHandler(handler);
97+
* ```
98+
*
99+
* ## Handler Priority
100+
*
101+
* Default priority: 5 (very high)
102+
* This ensures OID4VC URIs are checked before other credential handlers.
103+
*
104+
* @category Built-in Handlers
105+
*/
106+
export class OID4VCHandler implements QRCodeHandler {
107+
id = 'oid4vc';
108+
priority: number;
109+
110+
private uriPrefixes: string[];
111+
private onImportCredential: (
112+
uri: string,
113+
context: QRCodeContext,
114+
) => Promise<OID4VCImportResult>;
115+
116+
constructor(config: OID4VCHandlerConfig) {
117+
if (!config.onImportCredential) {
118+
throw new Error('onImportCredential callback is required');
119+
}
120+
121+
this.priority = config.priority ?? 5;
122+
this.uriPrefixes = config.uriPrefixes ?? ['openid-credential-offer://'];
123+
this.onImportCredential = config.onImportCredential;
124+
}
125+
126+
/**
127+
* Check if this is an OID4VC URI
128+
*
129+
* Matches URIs that start with any of the configured prefixes.
130+
* By default, matches: openid-credential-offer://
131+
*
132+
* @param context - The QR code context
133+
* @returns True if this handler can process the URI
134+
*/
135+
canHandle(context: QRCodeContext): boolean {
136+
return this.uriPrefixes.some(prefix => context.data.startsWith(prefix));
137+
}
138+
139+
/**
140+
* Process the OID4VC credential offer URI
141+
*
142+
* Delegates to the configured onImportCredential callback for actual processing.
143+
* This allows apps to implement their own navigation, UI, and error handling.
144+
*
145+
* @param context - The QR code context
146+
* @returns Result of the processing
147+
*/
148+
async handle(context: QRCodeContext): Promise<QRCodeHandlerResult> {
149+
try {
150+
const result = await this.onImportCredential(context.data, context);
151+
152+
return {
153+
success: result.success,
154+
data: result.credential,
155+
error: result.error,
156+
metadata: {
157+
type: 'oid4vc',
158+
uri: context.data,
159+
...result.metadata,
160+
},
161+
};
162+
} catch (error) {
163+
const err = error instanceof Error ? error : new Error(String(error));
164+
return {
165+
success: false,
166+
error: err,
167+
metadata: {
168+
type: 'oid4vc',
169+
uri: context.data,
170+
},
171+
};
172+
}
173+
}
174+
}
175+
176+
/**
177+
* Create an OID4VC handler with custom configuration
178+
*
179+
* This is a convenience factory function for creating an OID4VC handler.
180+
*
181+
* @param config - Handler configuration
182+
* @returns Configured OID4VC handler
183+
*
184+
* @example
185+
* ```typescript
186+
* const handler = createOID4VCHandler({
187+
* onImportCredential: async (uri) => {
188+
* // Your import logic
189+
* return { success: true };
190+
* },
191+
* });
192+
* ```
193+
*/
194+
export function createOID4VCHandler(
195+
config: OID4VCHandlerConfig,
196+
): OID4VCHandler {
197+
return new OID4VCHandler(config);
198+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* QR Code Handler System
3+
*
4+
* This module provides a generic, extensible system for processing QR codes
5+
* in decentralized identity wallet applications.
6+
*
7+
* ## Overview
8+
*
9+
* The QR handler system is built around these core concepts:
10+
*
11+
* - **QRCodeContext**: Contains parsed QR data (raw string, JSON, URLs)
12+
* - **QRCodeHandler**: Interface for implementing specific QR code processors
13+
* - **QRCodeProcessor**: Manages handler registration and execution
14+
* - **ProcessOptions**: Configuration for how QR codes are processed
15+
*
16+
* ## Basic Usage
17+
*
18+
* ```typescript
19+
* import { createQRCodeProcessor } from '@docknetwork/wallet-sdk-core';
20+
*
21+
* // Create processor
22+
* const processor = createQRCodeProcessor();
23+
*
24+
* // Register handlers
25+
* processor.registerHandler({
26+
* id: 'my-handler',
27+
* priority: 10,
28+
* canHandle: (context) => context.data.startsWith('myprotocol://'),
29+
* handle: async (context) => {
30+
* // Process the QR code
31+
* return { success: true };
32+
* }
33+
* });
34+
*
35+
* // Process QR code
36+
* const result = await processor.process(scannedData);
37+
* ```
38+
*
39+
* ## Custom Handlers
40+
*
41+
* Handlers can be implemented as classes or objects:
42+
*
43+
* ```typescript
44+
* class MyCustomHandler implements QRCodeHandler {
45+
* id = 'my-custom-handler';
46+
* priority = 20;
47+
*
48+
* canHandle(context: QRCodeContext): boolean {
49+
* return context.jsonData?.type === 'my-type';
50+
* }
51+
*
52+
* async handle(context: QRCodeContext): Promise<QRCodeHandlerResult> {
53+
* // Your processing logic
54+
* return { success: true, data: processedData };
55+
* }
56+
* }
57+
*
58+
* processor.registerHandler(new MyCustomHandler());
59+
* ```
60+
*
61+
* ## Built-in Handlers
62+
*
63+
* The SDK provides built-in handlers for common protocols:
64+
* - OID4VC (OpenID for Verifiable Credentials)
65+
* - OID4VP (OpenID for Verifiable Presentations)
66+
* - DIDComm (Decentralized Identity Communication)
67+
*
68+
* These handlers are available in separate modules and can be imported
69+
* and registered as needed.
70+
*
71+
* @module qr-handlers
72+
*/
73+
74+
export * from './types';
75+
export * from './processor';
76+
export * from './builtin';

0 commit comments

Comments
 (0)