solana-age-verify-sdk 2.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +193 -0
  2. package/dist/adapters/blazeface.d.ts +15 -0
  3. package/dist/adapters/blazeface.js +258 -0
  4. package/dist/adapters/mediapipe.d.ts +7 -0
  5. package/dist/adapters/mediapipe.js +55 -0
  6. package/dist/adapters/onnx.d.ts +10 -0
  7. package/dist/adapters/onnx.js +171 -0
  8. package/dist/camera.d.ts +15 -0
  9. package/dist/camera.js +76 -0
  10. package/dist/embedding/descriptor.d.ts +22 -0
  11. package/dist/embedding/descriptor.js +134 -0
  12. package/dist/hashing/facehash.d.ts +3 -0
  13. package/dist/hashing/facehash.js +27 -0
  14. package/dist/hashing/webcrypto.d.ts +1 -0
  15. package/dist/hashing/webcrypto.js +1 -0
  16. package/dist/index.d.ts +6 -0
  17. package/dist/index.js +7 -0
  18. package/dist/liveness/challenges.d.ts +3 -0
  19. package/dist/liveness/challenges.js +34 -0
  20. package/dist/liveness/scorer.d.ts +1 -0
  21. package/dist/liveness/scorer.js +3 -0
  22. package/dist/liveness/texture.d.ts +72 -0
  23. package/dist/liveness/texture.js +266 -0
  24. package/dist/security.d.ts +14 -0
  25. package/dist/security.js +73 -0
  26. package/dist/types.d.ts +87 -0
  27. package/dist/types.js +9 -0
  28. package/dist/ui/spinner.d.ts +5 -0
  29. package/dist/ui/spinner.js +36 -0
  30. package/dist/verify.d.ts +4 -0
  31. package/dist/verify.js +970 -0
  32. package/dist/worker/frame.d.ts +5 -0
  33. package/dist/worker/frame.js +1 -0
  34. package/dist/worker/infer.d.ts +4 -0
  35. package/dist/worker/infer.js +22 -0
  36. package/dist/worker/worker.d.ts +0 -0
  37. package/dist/worker/worker.js +61 -0
  38. package/package.json +50 -0
  39. package/public/models/age_gender.onnx +1446 -0
  40. package/public/models/age_gender_model-weights_manifest.json +62 -0
  41. package/public/models/age_gender_model.shard1 +1447 -0
  42. package/public/models/face_landmark_68_model-weights_manifest.json +60 -0
  43. package/public/models/face_landmark_68_model.shard1 +1447 -0
  44. package/public/models/face_recognition_model-weights_manifest.json +128 -0
  45. package/public/models/face_recognition_model.shard1 +1447 -0
  46. package/public/models/face_recognition_model.shard2 +1447 -0
  47. package/public/models/ort-wasm-simd-threaded.asyncify.wasm +0 -0
  48. package/public/models/ort-wasm-simd-threaded.jsep.wasm +0 -0
  49. package/public/models/ort-wasm-simd-threaded.wasm +0 -0
  50. package/public/models/tiny_face_detector_model-weights_manifest.json +30 -0
  51. package/public/models/tiny_face_detector_model.shard1 +1447 -0
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Texture Analysis for Passive Liveness Detection
3
+ *
4
+ * This module analyzes the surface characteristics of a face to distinguish between:
5
+ * - Real human faces (3D, natural skin texture, pores, wrinkles)
6
+ * - Spoofing attempts (2D photos, screens, masks)
7
+ *
8
+ * Techniques used:
9
+ * 1. Local Binary Patterns (LBP) - Detects local texture patterns
10
+ * 2. Frequency Analysis - Identifies print/screen artifacts
11
+ * 3. Moiré Pattern Detection - Detects screen recapture
12
+ * 4. Reflectance Analysis - Analyzes light interaction with surface
13
+ */
14
+ /**
15
+ * Analyzes texture from a face region to detect liveness
16
+ */
17
+ export class TextureAnalyzer {
18
+ constructor() {
19
+ Object.defineProperty(this, "canvas", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: void 0
24
+ });
25
+ Object.defineProperty(this, "ctx", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: void 0
30
+ });
31
+ // Use OffscreenCanvas in worker, HTMLCanvasElement in main thread
32
+ if (typeof OffscreenCanvas !== 'undefined') {
33
+ this.canvas = new OffscreenCanvas(256, 256);
34
+ this.ctx = this.canvas.getContext('2d');
35
+ }
36
+ else {
37
+ this.canvas = document.createElement('canvas');
38
+ this.canvas.width = 256;
39
+ this.canvas.height = 256;
40
+ this.ctx = this.canvas.getContext('2d');
41
+ }
42
+ }
43
+ /**
44
+ * Main analysis function
45
+ */
46
+ async analyze(frame, faceRegion) {
47
+ // Extract face region or use entire frame
48
+ const imageData = this.extractRegion(frame, faceRegion);
49
+ // Run parallel analyses
50
+ const [lbpScore, freqScore, moireDetected, reflectance] = await Promise.all([
51
+ this.analyzeLBP(imageData),
52
+ this.analyzeFrequency(imageData),
53
+ this.detectMoire(imageData),
54
+ this.analyzeReflectance(imageData)
55
+ ]);
56
+ // Combine scores
57
+ const skinComplexity = lbpScore;
58
+ const frequencyScore = freqScore;
59
+ // Decision logic: Real if complexity is high AND no moiré AND natural reflectance
60
+ const complexityThreshold = 0.3;
61
+ const frequencyThreshold = 0.35;
62
+ const isReal = skinComplexity > complexityThreshold &&
63
+ frequencyScore > frequencyThreshold &&
64
+ !moireDetected &&
65
+ reflectance !== 'artificial';
66
+ // Confidence based on how far from thresholds
67
+ const complexityDist = Math.abs(skinComplexity - complexityThreshold);
68
+ const freqDist = Math.abs(frequencyScore - frequencyThreshold);
69
+ const confidence = Math.min(1.0, (complexityDist + freqDist) / 2 + 0.5);
70
+ return {
71
+ isReal,
72
+ confidence,
73
+ features: {
74
+ skinComplexity,
75
+ moireDetected,
76
+ frequencyScore,
77
+ reflectancePattern: reflectance
78
+ }
79
+ };
80
+ }
81
+ /**
82
+ * Extract region of interest from frame
83
+ */
84
+ extractRegion(frame, region) {
85
+ // Draw to canvas
86
+ if (frame instanceof ImageData) {
87
+ this.ctx.putImageData(frame, 0, 0);
88
+ }
89
+ else {
90
+ this.ctx.drawImage(frame, 0, 0, this.canvas.width, this.canvas.height);
91
+ }
92
+ // Extract region if specified
93
+ if (region) {
94
+ const { x, y, width, height } = region;
95
+ return this.ctx.getImageData(x, y, width, height);
96
+ }
97
+ return this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
98
+ }
99
+ /**
100
+ * Local Binary Patterns (LBP) Analysis
101
+ * Detects micro-texture patterns in skin
102
+ */
103
+ async analyzeLBP(imageData) {
104
+ const { data, width, height } = imageData;
105
+ const grayscale = this.toGrayscale(data, width, height);
106
+ // LBP histogram (256 bins for uniform LBP)
107
+ const histogram = new Array(256).fill(0);
108
+ // Calculate LBP for each pixel (excluding borders)
109
+ for (let y = 1; y < height - 1; y++) {
110
+ for (let x = 1; x < width - 1; x++) {
111
+ const center = grayscale[y * width + x];
112
+ let lbpValue = 0;
113
+ // 8 neighbors in clockwise order
114
+ const neighbors = [
115
+ grayscale[(y - 1) * width + (x - 1)], // top-left
116
+ grayscale[(y - 1) * width + x], // top
117
+ grayscale[(y - 1) * width + (x + 1)], // top-right
118
+ grayscale[y * width + (x + 1)], // right
119
+ grayscale[(y + 1) * width + (x + 1)], // bottom-right
120
+ grayscale[(y + 1) * width + x], // bottom
121
+ grayscale[(y + 1) * width + (x - 1)], // bottom-left
122
+ grayscale[y * width + (x - 1)] // left
123
+ ];
124
+ // Build LBP code
125
+ for (let i = 0; i < 8; i++) {
126
+ if (neighbors[i] >= center) {
127
+ lbpValue |= (1 << i);
128
+ }
129
+ }
130
+ histogram[lbpValue]++;
131
+ }
132
+ }
133
+ // Normalize histogram
134
+ const totalPixels = (width - 2) * (height - 2);
135
+ const normalizedHist = histogram.map(v => v / totalPixels);
136
+ // Calculate entropy (measure of texture complexity)
137
+ let entropy = 0;
138
+ for (const p of normalizedHist) {
139
+ if (p > 0) {
140
+ entropy -= p * Math.log2(p);
141
+ }
142
+ }
143
+ // Normalize entropy to 0-1 range (max entropy for 256 bins is 8)
144
+ const normalizedEntropy = entropy / 8;
145
+ // Real skin has moderate-to-high entropy (complex texture)
146
+ // Photos/screens have lower entropy (uniform patterns)
147
+ return normalizedEntropy;
148
+ }
149
+ /**
150
+ * Frequency Domain Analysis
151
+ * Detects print patterns and screen grids
152
+ */
153
+ async analyzeFrequency(imageData) {
154
+ const { data, width, height } = imageData;
155
+ const grayscale = this.toGrayscale(data, width, height);
156
+ // Simple frequency analysis using gradient magnitude
157
+ let totalGradient = 0;
158
+ let highFreqCount = 0;
159
+ for (let y = 1; y < height - 1; y++) {
160
+ for (let x = 1; x < width - 1; x++) {
161
+ // Sobel gradients
162
+ const gx = -grayscale[(y - 1) * width + (x - 1)] +
163
+ grayscale[(y - 1) * width + (x + 1)] +
164
+ -2 * grayscale[y * width + (x - 1)] +
165
+ 2 * grayscale[y * width + (x + 1)] +
166
+ -grayscale[(y + 1) * width + (x - 1)] +
167
+ grayscale[(y + 1) * width + (x + 1)];
168
+ const gy = -grayscale[(y - 1) * width + (x - 1)] +
169
+ -2 * grayscale[(y - 1) * width + x] +
170
+ -grayscale[(y - 1) * width + (x + 1)] +
171
+ grayscale[(y + 1) * width + (x - 1)] +
172
+ 2 * grayscale[(y + 1) * width + x] +
173
+ grayscale[(y + 1) * width + (x + 1)];
174
+ const magnitude = Math.sqrt(gx * gx + gy * gy);
175
+ totalGradient += magnitude;
176
+ // Count high-frequency components (sharp edges)
177
+ if (magnitude > 50) {
178
+ highFreqCount++;
179
+ }
180
+ }
181
+ }
182
+ const avgGradient = totalGradient / ((width - 2) * (height - 2));
183
+ const highFreqRatio = highFreqCount / ((width - 2) * (height - 2));
184
+ // Real skin has moderate gradients with natural variation
185
+ // Printed images have either too uniform or too sharp edges
186
+ // Score based on "naturalness" of gradient distribution
187
+ const naturalGradientRange = avgGradient > 5 && avgGradient < 30;
188
+ const naturalFreqRatio = highFreqRatio > 0.01 && highFreqRatio < 0.15;
189
+ return (naturalGradientRange && naturalFreqRatio) ? 0.7 : 0.3;
190
+ }
191
+ /**
192
+ * Moiré Pattern Detection
193
+ * Detects interference patterns from screen recapture
194
+ */
195
+ async detectMoire(imageData) {
196
+ const { data, width, height } = imageData;
197
+ // Look for periodic patterns that indicate moiré
198
+ // Simple approach: check for regular oscillations in intensity
199
+ let periodicityScore = 0;
200
+ const sampleRows = 10;
201
+ for (let i = 0; i < sampleRows; i++) {
202
+ const y = Math.floor((height / sampleRows) * i);
203
+ const rowData = [];
204
+ for (let x = 0; x < width; x++) {
205
+ const idx = (y * width + x) * 4;
206
+ const gray = (data[idx] + data[idx + 1] + data[idx + 2]) / 3;
207
+ rowData.push(gray);
208
+ }
209
+ // Count zero-crossings (sign changes in derivative)
210
+ let crossings = 0;
211
+ for (let x = 1; x < rowData.length - 1; x++) {
212
+ const diff1 = rowData[x] - rowData[x - 1];
213
+ const diff2 = rowData[x + 1] - rowData[x];
214
+ if (diff1 * diff2 < 0)
215
+ crossings++;
216
+ }
217
+ // High crossing count indicates periodic pattern
218
+ const crossingRatio = crossings / width;
219
+ if (crossingRatio > 0.3)
220
+ periodicityScore++;
221
+ }
222
+ // Moiré detected if multiple rows show high periodicity
223
+ return periodicityScore > sampleRows * 0.5;
224
+ }
225
+ /**
226
+ * Reflectance Pattern Analysis
227
+ * Analyzes how light interacts with the surface
228
+ */
229
+ async analyzeReflectance(imageData) {
230
+ const { data } = imageData;
231
+ // Analyze brightness distribution
232
+ const brightnesses = [];
233
+ for (let i = 0; i < data.length; i += 4) {
234
+ const brightness = (data[i] + data[i + 1] + data[i + 2]) / 3;
235
+ brightnesses.push(brightness);
236
+ }
237
+ // Calculate statistics
238
+ const mean = brightnesses.reduce((a, b) => a + b, 0) / brightnesses.length;
239
+ const variance = brightnesses.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / brightnesses.length;
240
+ const stdDev = Math.sqrt(variance);
241
+ // Real skin has moderate variance (natural shadows and highlights)
242
+ // Photos/screens tend to have either too uniform or too high contrast
243
+ const coefficientOfVariation = stdDev / (mean + 1); // +1 to avoid division by zero
244
+ if (coefficientOfVariation > 0.15 && coefficientOfVariation < 0.5) {
245
+ return 'natural';
246
+ }
247
+ else if (coefficientOfVariation < 0.1 || coefficientOfVariation > 0.7) {
248
+ return 'artificial';
249
+ }
250
+ return 'unknown';
251
+ }
252
+ /**
253
+ * Convert RGBA to grayscale
254
+ */
255
+ toGrayscale(data, width, height) {
256
+ const grayscale = new Uint8Array(width * height);
257
+ for (let i = 0; i < grayscale.length; i++) {
258
+ const idx = i * 4;
259
+ // Luminance formula
260
+ grayscale[i] = Math.floor(0.299 * data[idx] +
261
+ 0.587 * data[idx + 1] +
262
+ 0.114 * data[idx + 2]);
263
+ }
264
+ return grayscale;
265
+ }
266
+ }
@@ -0,0 +1,14 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ /**
3
+ * Gets the platform's public key from the obfuscated store.
4
+ * This is the address that receives the protocol fee and signs the verification record.
5
+ */
6
+ export declare function getPlatformPublicKey(): PublicKey;
7
+ /**
8
+ * Gets the protocol fee in SOL.
9
+ */
10
+ export declare function getProtocolFee(override?: number): number;
11
+ /**
12
+ * Security wrapper to ensure the transaction destination is correct.
13
+ */
14
+ export declare function validateTransactionDestination(destination: PublicKey): boolean;
@@ -0,0 +1,73 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ /**
3
+ * CORE SECURITY CONFIGURATION
4
+ * This file contains the platform's public configuration.
5
+ * It is designed to be minified and obfuscated during the build process
6
+ * to ensure immutability and prevent easy tampering in the distributed SDK.
7
+ */
8
+ // Obfuscation placeholder removed as it's currently unused to avoid build errors.
9
+ // Fallback fee (0.001 SOL)
10
+ const _F_B = 0.001;
11
+ let _cachedPlatformPubKey = null;
12
+ /**
13
+ * Gets the platform's public key from the obfuscated store.
14
+ * This is the address that receives the protocol fee and signs the verification record.
15
+ */
16
+ export function getPlatformPublicKey() {
17
+ if (_cachedPlatformPubKey)
18
+ return _cachedPlatformPubKey;
19
+ // In a production build, this would be swapped or populated from env
20
+ // For now, we use the VITE environment variable if available (Vite/Vercel)
21
+ // We check VITE_TREASURY_ADDRESS first as per configuration, then fallback to legacy VITE_PLATFORM_PUBLIC_KEY
22
+ const envKey = import.meta.env?.VITE_TREASURY_ADDRESS || import.meta.env?.VITE_PLATFORM_PUBLIC_KEY;
23
+ if (envKey) {
24
+ _cachedPlatformPubKey = new PublicKey(envKey);
25
+ return _cachedPlatformPubKey;
26
+ }
27
+ // Default/Fallback logic
28
+ // We use a base58 encoded version that is "minified" in the code.
29
+ // The string here is obfuscated to avoid plain text search and easy replacement.
30
+ const _ob = "OUJLV3dwUG9WSHVIVXNqbzltdmRRNlBaWG5uc0FFd0NzVlRCMTJOVER0aGo=";
31
+ const _dec = (str) => {
32
+ try {
33
+ // Browser-safe atob
34
+ if (typeof window !== 'undefined' && window.atob) {
35
+ return window.atob(str);
36
+ }
37
+ // If window.atob is missing (unlikely in modern browser), final hard fallback
38
+ return "9BKWwpPoVHuHUsjo9mvdQ6PZXnnsAEwCsVTB12NTDthj";
39
+ }
40
+ catch (e) {
41
+ // Final fallback to avoid crash, but return something that doesn't reveal the key in plain text
42
+ return "9BKWwpPoVHuHUsjo9mvdQ6PZXnnsAEwCsVTB12NTDthj";
43
+ }
44
+ };
45
+ const _t = _dec(_ob);
46
+ try {
47
+ _cachedPlatformPubKey = new PublicKey(_t);
48
+ // Ensure the object itself cannot be modified
49
+ Object.freeze(_cachedPlatformPubKey);
50
+ }
51
+ catch (e) {
52
+ console.error("CRITICAL: Failed to construct Platform PublicKey from fallback. This indicates a build-time corruption.");
53
+ _cachedPlatformPubKey = new PublicKey("11111111111111111111111111111111");
54
+ Object.freeze(_cachedPlatformPubKey);
55
+ }
56
+ return _cachedPlatformPubKey;
57
+ }
58
+ /**
59
+ * Gets the protocol fee in SOL.
60
+ */
61
+ export function getProtocolFee(override) {
62
+ if (override !== undefined)
63
+ return override;
64
+ const envFee = import.meta.env?.VITE_PROTOCOL_FEE_SOL;
65
+ return envFee ? parseFloat(envFee) : _F_B;
66
+ }
67
+ /**
68
+ * Security wrapper to ensure the transaction destination is correct.
69
+ */
70
+ export function validateTransactionDestination(destination) {
71
+ const platformKey = getPlatformPublicKey();
72
+ return destination.equals(platformKey);
73
+ }
@@ -0,0 +1,87 @@
1
+ export interface VerifyHost18PlusOptions {
2
+ walletPubkeyBase58: string;
3
+ videoElement?: HTMLVideoElement;
4
+ uiMountEl?: HTMLElement;
5
+ signal?: AbortSignal;
6
+ config?: Partial<VerifyConfig>;
7
+ onChallenge?: (challenge: string) => void;
8
+ modelPath?: string;
9
+ workerFactory?: () => Worker;
10
+ connection?: any;
11
+ wallet?: {
12
+ publicKey: any;
13
+ signTransaction: (tx: any) => Promise<any>;
14
+ };
15
+ }
16
+ export interface VerifyConfig {
17
+ challenges: string[];
18
+ minLivenessScore: number;
19
+ minAgeConfidence: number;
20
+ minAgeEstimate: number;
21
+ timeoutMs: number;
22
+ maxRetries: number;
23
+ cooldownMinutes: number;
24
+ protocolFeeSol?: number;
25
+ }
26
+ export declare const DEFAULT_CONFIG: VerifyConfig;
27
+ export interface ChallengeResult {
28
+ type: string;
29
+ passed: boolean;
30
+ score: number;
31
+ }
32
+ export interface VerifyResult {
33
+ over18: boolean;
34
+ facehash: string;
35
+ description: string;
36
+ verifiedAt: string;
37
+ protocolFeePaid?: boolean;
38
+ protocolFeeTxId?: string;
39
+ evidence: {
40
+ ageEstimate: number;
41
+ ageConfidence: number;
42
+ livenessScore: number;
43
+ textureScore?: number;
44
+ textureFeatures?: TextureFeatures;
45
+ ageMethod?: string;
46
+ challenges: ChallengeResult[];
47
+ modelVersions: Record<string, string>;
48
+ saltHex: string;
49
+ sessionNonceHex: string;
50
+ };
51
+ }
52
+ export interface FrameData {
53
+ data: Uint8ClampedArray;
54
+ width: number;
55
+ height: number;
56
+ timestamp: number;
57
+ }
58
+ export interface WorkerResponse {
59
+ type: 'RESULT' | 'ERROR' | 'LOADED';
60
+ payload?: any;
61
+ error?: string;
62
+ }
63
+ export interface WorkerRequest {
64
+ type: 'PROCESS_FRAME' | 'LOAD_MODELS';
65
+ payload?: any;
66
+ }
67
+ export interface TextureFeatures {
68
+ skinComplexity: number;
69
+ moireDetected: boolean;
70
+ frequencyScore: number;
71
+ reflectancePattern: 'natural' | 'artificial' | 'unknown';
72
+ }
73
+ export interface DetectionResult {
74
+ faceFound: boolean;
75
+ landmarks?: number[];
76
+ ageEstimate?: number;
77
+ embedding?: number[];
78
+ confidence?: number;
79
+ textureScore?: number;
80
+ textureFeatures?: TextureFeatures;
81
+ ageConfidence?: number;
82
+ ageMethod?: 'onnx' | 'geometric' | 'unknown';
83
+ }
84
+ export interface FaceModelAdapter {
85
+ load(basePath?: string): Promise<void>;
86
+ detect(frame: ImageData | HTMLCanvasElement | OffscreenCanvas): Promise<DetectionResult>;
87
+ }
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ export const DEFAULT_CONFIG = Object.freeze({
2
+ challenges: [],
3
+ minLivenessScore: 0.85,
4
+ minAgeConfidence: 0.65,
5
+ minAgeEstimate: 18,
6
+ timeoutMs: 90000,
7
+ maxRetries: 3,
8
+ cooldownMinutes: 15
9
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generates a premium gradient spinner HTML string for use in SDK UI overlays
3
+ * Matches Solana brand colors (purple to cyan gradient)
4
+ */
5
+ export declare function createSpinnerHTML(): string;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Generates a premium gradient spinner HTML string for use in SDK UI overlays
3
+ * Matches Solana brand colors (purple to cyan gradient)
4
+ */
5
+ export function createSpinnerHTML() {
6
+ return `
7
+ <div style="display: flex; align-items: center; justify-content: center; padding: 20px;">
8
+ <div style="
9
+ width: 64px;
10
+ height: 64px;
11
+ border: 4px solid transparent;
12
+ border-radius: 50%;
13
+ background: linear-gradient(#0f172a, #0f172a) padding-box, linear-gradient(135deg, #a78bfa 0%, #60a5fa 50%, #14b8a6 100%) border-box;
14
+ animation: spin 0.8s linear infinite;
15
+ position: relative;
16
+ " aria-label="Loading">
17
+ <div style="
18
+ position: absolute;
19
+ top: 50%;
20
+ left: 50%;
21
+ transform: translate(-50%, -50%);
22
+ width: 48px;
23
+ height: 48px;
24
+ border-radius: 50%;
25
+ background: #0f172a;
26
+ "></div>
27
+ </div>
28
+ </div>
29
+ <style>
30
+ @keyframes spin {
31
+ from { transform: rotate(0deg); }
32
+ to { transform: rotate(360deg); }
33
+ }
34
+ </style>
35
+ `;
36
+ }
@@ -0,0 +1,4 @@
1
+ import { VerifyHost18PlusOptions, VerifyResult } from './types';
2
+ export declare function verifyHost18Plus(options: VerifyHost18PlusOptions): Promise<VerifyResult>;
3
+ export declare function createVerificationUI(): HTMLElement;
4
+ export declare function setExecutionBackend(backend: 'tfjs' | 'onnx'): void;