### Install @selfxyz/core Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Instructions for installing the `@selfxyz/core` package using common Node.js package managers: npm, yarn, and bun. ```bash npm install @selfxyz/core ``` ```bash yarn add @selfxyz/core ``` ```bash bun install @selfxyz/core ``` -------------------------------- ### Complete Next.js SelfQRcode Integration Example Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md A full-fledged Next.js example illustrating client-side integration of `SelfQRcodeWrapper`. It manages user ID state, dynamically configures `SelfApp` with specific `disclosures`, and renders the QR code, demonstrating a complete identity verification flow within a React application. ```javascript 'use client'; import React, { useState, useEffect } from 'react'; import SelfQRcodeWrapper, { SelfAppBuilder } from '@selfxyz/qrcode'; import { v4 as uuidv4 } from 'uuid'; function VerificationPage() { const [userId, setUserId] = useState(null); useEffect(() => { // Generate a user ID when the component mounts setUserId(uuidv4()); }, []); if (!userId) return null; // Create the SelfApp configuration const selfApp = new SelfAppBuilder({ appName: "My Application", scope: "my-application-scope", endpoint: "https://myapp.com/api/verify", userId, disclosures: { // NEW: Must match backend config minimumAge: 18, excludedCountries: ['IRN', 'PRK'], ofac: true, name: true, nationality: true } }).build(); return (

Verify Your Identity

Scan this QR code with the Self app to verify your identity

{ // Handle successful verification console.log("Verification successful!"); // Redirect or update UI }} size={350} />

User ID: {userId.substring(0, 8)}...

); } export default VerificationPage; ``` -------------------------------- ### Install Self SDK Frontend Packages (npm, yarn, bun) Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Installs the necessary Self SDK packages for frontend QR code generation and core utilities, along with ethers for Ethereum integration. Dependencies include `@selfxyz/qrcode`, `@selfxyz/core`, and `ethers`. ```npm npm install @selfxyz/qrcode @selfxyz/core ethers ``` ```yarn yarn add @selfxyz/qrcode @selfxyz/core ethers ``` ```bun bun install @selfxyz/qrcode @selfxyz/core ethers ``` -------------------------------- ### Install SelfXYZ QR Code Generator for Frontend Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md These commands show how to install the `@selfxyz/qrcode` React component. This package is essential for generating QR codes on the frontend, enabling users to initiate Self passport verification flows. ```bash npm install @selfxyz/qrcode ``` ```bash yarn add @selfxyz/qrcode ``` ```bash bun install @selfxyz/qrcode ``` -------------------------------- ### Next.js Verification Component Example Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md A complete Next.js client component demonstrating the integration of the Self QR code verification flow. It initializes the SelfApp, generates a QR code, and includes callbacks for successful verification. ```javascript 'use client'; import React, { useState, useEffect } from 'react'; import { getUniversalLink } from "@selfxyz/core"; import { SelfQRcodeWrapper, SelfAppBuilder, type SelfApp, } from "@selfxyz/qrcode"; import { ethers } from "ethers"; function VerificationPage() { const [selfApp, setSelfApp] = useState(null); const [universalLink, setUniversalLink] = useState(""); const [userId] = useState(ethers.ZeroAddress); useEffect(() => { try { const app = new SelfAppBuilder({ version: 2, appName: process.env.NEXT_PUBLIC_SELF_APP_NAME || "Self Workshop", scope: process.env.NEXT_PUBLIC_SELF_SCOPE || "self-workshop", endpoint: `${process.env.NEXT_PUBLIC_SELF_ENDPOINT}`, logoBase64: "https://i.postimg.cc/mrmVf9hm/self.png", userId: userId, endpointType: "staging_https", userIdType: "hex", userDefinedData: "Bonjour Cannes!", disclosures: { /* 1. what you want to verify from users' identity */ minimumAge: 18, // ofac: false, // excludedCountries: [countries.BELGIUM], /* 2. what you want users to reveal */ // name: false, // issuing_state: true, nationality: true, // date_of_birth: true, // passport_number: false, gender: true, // expiry_date: false, } }).build(); setSelfApp(app); setUniversalLink(getUniversalLink(app)); } catch (error) { console.error("Failed to initialize Self app:", error); } }, [userId]); const handleSuccessfulVerification = () => { console.log("Verification successful!"); // Handle success - redirect, update UI, etc. }; return (

Verify Your Identity

Scan this QR code with the Self app

{selfApp ? ( { console.error("Error: Failed to verify identity"); }} /> ) : (
Loading QR Code...
)}
); } export default VerificationPage; ``` -------------------------------- ### Install Self Protocol Contracts Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/basic-integration.md Installs the Self Protocol smart contract package from npm. This is the initial step required to integrate the contracts into your project. ```bash npm install @selfxyz/contracts ``` -------------------------------- ### Import SelfQRcode and UUID Libraries Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Imports `SelfQRcodeWrapper` and `SelfAppBuilder` from `@selfxyz/qrcode` for QR code generation and application configuration, along with `v4` from `uuid` for generating unique user identifiers. ```javascript import SelfQRcodeWrapper, { SelfAppBuilder } from '@selfxyz/qrcode'; import { v4 as uuidv4 } from 'uuid'; ``` -------------------------------- ### Universal Links for Direct App Opening Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md An example illustrating how to use the `getUniversalLink` function to generate deep links for direct interaction with the Self app. This enhances user experience on mobile by bypassing QR code scanning. ```javascript import { getUniversalLink } from "@selfxyz/core"; function VerificationPage() { const [selfApp, setSelfApp] = useState(null); const [universalLink, setUniversalLink] = useState(""); useEffect(() => { const app = new SelfAppBuilder({...}).build(); setSelfApp(app); // Generate universal link for direct app opening setUniversalLink(getUniversalLink(app)); }, []); const openSelfApp = () => { if (universalLink) { window.open(universalLink, "_blank"); } }; return (
{/* QR Code for desktop/cross-device */} {/* Universal Link button for mobile */}
); } ``` -------------------------------- ### Update Dependencies: Install Latest @selfxyz/core Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md This snippet shows how to update the Self Protocol backend SDK to the latest version using npm. Ensure you are installing the latest package to leverage V2 features and fixes. ```bash npm install @selfxyz/core@latest ``` -------------------------------- ### ProofOfHuman Solidity Contract Example Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/basic-integration.md A Solidity smart contract example demonstrating how to extend the SelfVerificationRoot abstract contract to verify human identity. It includes state variables for tracking verified users, an event for successful verifications, a constructor to initialize the contract, and an implementation of the customVerificationHook for custom logic upon successful verification. ```solidity // SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\nimport {SelfVerificationRoot} from "@selfxyz/contracts/contracts/abstract/SelfVerificationRoot.sol";\nimport {ISelfVerificationRoot} from "@selfxyz/contracts/contracts/interfaces/ISelfVerificationRoot.sol";\n\n/**\n * @title ProofOfHuman\n * @notice Simple example showing how to verify human identity using Self Protocol\n */\ncontract ProofOfHuman is SelfVerificationRoot {\n // Store verification status for each user\n mapping(address => bool) public verifiedHumans;\n bytes32 public verificationConfigId;\n address public lastUserAddress;\n \n // Event to track successful verifications\n event VerificationCompleted(\n ISelfVerificationRoot.GenericDiscloseOutputV2 output,\n bytes userData\n );\n \n /**\n * @notice Constructor for the contract\n * @param _identityVerificationHubV2Address The address of the Identity Verification Hub V2\n * @param _scope The scope of the contract\n * @param _verificationConfigId The configuration ID for the contract\n */\n constructor(\n address _identityVerificationHubV2Address,\n uint256 _scope,\n bytes32 _verificationConfigId\n ) SelfVerificationRoot(_identityVerificationHubV2Address, _scope) {\n verificationConfigId = _verificationConfigId;\n }\n\n /**\n * @notice Implementation of customVerificationHook\n * @dev This function is called by onVerificationSuccess after hub address validation\n * @param output The verification output from the hub\n * @param userData The user data passed through verification\n */\n function customVerificationHook(\n ISelfVerificationRoot.GenericDiscloseOutputV2 memory _output,\n bytes memory _userData\n ) internal override {\n lastUserAddress = address(uint160(_output.userIdentifier));\n verifiedHumans[lastUserAddress] = true;\n\n emit VerificationCompleted(_output, _userData);\n \n // Add your custom logic here:\n // - Mint NFT to verified user\n // - Add to allowlist\n // - Transfer tokens\n // - etc.\n }\n\n function getConfigId(\n bytes32 _destinationChainId,\n bytes32 _userIdentifier,\n bytes memory _userDefinedData\n ) public view override returns (bytes32) {\n return verificationConfigId;\n }\n\n /**\n * @notice Check if an address is a verified human\n */\n function isVerifiedHuman(address _user) external view returns (bool) {\n return verifiedHumans[_user];\n }\n\n function setConfigId(bytes32 _configId) external {\n verificationConfigId = _configId;\n }\n} ``` -------------------------------- ### Update Dependencies with npm Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Installs the latest version of the @selfxyz/qrcode package using npm. This command is essential for upgrading to the V2 features and ensuring compatibility. ```bash npm install @selfxyz/qrcode@latest ``` -------------------------------- ### Initialize SelfBackendVerifier Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Demonstrates how to initialize the SelfBackendVerifier with necessary parameters. This includes setting up the application scope, API endpoint, mock mode, accepted document types, configuration store, and address format. ```javascript import { SelfBackendVerifier, AllIds, DefaultConfigStore, VerificationConfig } from '@selfxyz/core'; // Define your verification requirements const verification_config = { excludedCountries: [], ofac: false, minimumAge: 18, }; // Create the configuration store const configStore = new DefaultConfigStore(verification_config); // Initialize the verifier const selfBackendVerifier = new SelfBackendVerifier( "your-app-scope", // Your app's unique scope "https://your-api-endpoint.com/api/verify", // Your API endpoint true, // true = mock for testing, false = production AllIds, // Accept all document types configStore, // Configuration store "hex" // "hex" for addresses, "uuid" for UUIDs ); // Note: The endpoint must be publicly accessible. For local development, use ngrok. ``` -------------------------------- ### Configure SelfApp Instance with Builder Pattern Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Demonstrates creating a `SelfApp` instance using `SelfAppBuilder`. It sets application details like name, scope, endpoint, and a unique `userId`. Crucially, it includes the `disclosures` object to specify required verification attributes such as age, nationality, and excluded countries, which must align with backend configurations. ```javascript // Generate a unique user ID const userId = uuidv4(); // Create a SelfApp instance using the builder pattern const selfApp = new SelfAppBuilder({ appName: "My App", scope: "my-app-scope", endpoint: "https://myapp.com/api/verify", logoBase64: "", // Optional, accepts also PNG url userId, disclosures: { // NEW: Specify verification requirements minimumAge: 18, // Must match backend config excludedCountries: ['IRN', 'PRK'], // Must match backend config ofac: true, // Must match backend config nationality: true, // Request nationality disclosure name: true, // Request name disclosure dateOfBirth: true // Request date of birth disclosure } }).build(); ``` -------------------------------- ### Update Backend Constructor: V1 vs V2 Initialization Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Compares the constructor for the SelfBackendVerifier class between V1 and V2. V2 requires additional parameters for allowed document types, configuration storage, and user ID type, promoting more flexible and explicit setup. ```javascript // V1 (Old): const verifier = new SelfBackendVerifier( "my-app-scope", "https://api.example.com/verify", false // mock mode ); ``` ```javascript // V2 (New): import { SelfBackendVerifier, AttestationId, UserIdType, IConfigStorage, AllIds } from '@selfxyz/core'; // Option 1: Use AllIds for all document types (recommended for most cases) const allowedIds = AllIds; // Option 2: Define specific allowed document types // const allowedIds = new Map(); // allowedIds.set(AttestationId.E_PASSPORT, true); // Accept passports // allowedIds.set(AttestationId.EU_ID_CARD, true); // Accept EU ID cards // Implement configuration storage class ConfigStorage implements IConfigStorage { async getConfig(configId: string) { // Return your verification requirements return { minimumAge: 18, excludedCountries: ['IRN', 'PRK'], ofac: true }; } async getActionId(userIdentifier: string, userDefinedData?: string) { // Return config ID based on your logic return 'default_config'; } } const verifier = new SelfBackendVerifier( "my-app-scope", "https://api.example.com/verify", false, // mock mode allowedIds, // NEW: allowed document types new ConfigStorage(), // NEW: config storage UserIdType.UUID // NEW: user ID type ); ``` -------------------------------- ### Match Frontend and Backend Configuration Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Highlights the critical requirement for frontend and backend verification configurations to match exactly. This ensures consistency in verification rules, such as excluded countries, OFAC status, and minimum age. ```javascript // Backend configuration const verification_config = { excludedCountries: [], ofac: false, minimumAge: 18, }; // Frontend configuration (must match) disclosures: { minimumAge: 18, // Same as backend excludedCountries: [], // Same as backend ofac: false, // Same as backend // Plus any disclosure fields you want nationality: true, gender: true, } ``` -------------------------------- ### JavaScript: Verifying Different Document Types Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Provides examples of calling the `verifier.verify` method for different document types, specifically a passport and an EU ID card. This demonstrates how to pass the correct `AttestationId` for each. ```javascript // Test passport verification const passportResult = await verifier.verify( AttestationId.E_PASSPORT, // 1 passportProof, passportSignals, userContextData ); // Test EU ID card verification const idCardResult = await verifier.verify( AttestationId.EU_ID_CARD, // 2 idCardProof, idCardSignals, userContextData ); ``` -------------------------------- ### JavaScript: Formatting User Context Data Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Provides an example of how to correctly format user context data, ensuring it meets the required 256-byte length by using proper hex encoding. Incorrect formatting can lead to validation failures. ```javascript // Create user context data (256 bytes total) const userContextData = '0x' + '0'.repeat(512); // 512 hex chars = 256 bytes ``` -------------------------------- ### Self App Configuration and QR Code Display (JavaScript) Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Demonstrates how to configure the SelfApp using `SelfAppBuilder` with essential parameters like app name, scope, and disclosures. It also shows how to use `SelfQRcodeWrapper` to display the QR code for user verification. ```javascript import SelfQRcodeWrapper, { SelfAppBuilder } from '@selfxyz/qrcode'; import { getUniversalLink } from "@selfxyz/core"; import { ethers } from "ethers"; // Use zero address for demo purposes const userId = ethers.ZeroAddress; // Create the SelfApp const selfApp = new SelfAppBuilder({ version: 2, appName: "Self Example", scope: "your-app-scope", endpoint: process.env.NEXT_PUBLIC_SELF_ENDPOINT || "", logoBase64: "https://i.postimg.cc/mrmVf9hm/self.png", userId: userId, endpointType: "staging_https", userIdType: "hex", userDefinedData: "Hello World!", disclosures: { // Verification requirements (must match backend) minimumAge: 18, // ofac: false, // excludedCountries: [], // Disclosure requests (what users reveal) nationality: true, gender: true, // Other optional fields: // name: false, // date_of_birth: true, // passport_number: false, // expiry_date: false, } }).build(); function VerificationComponent() { return ( { console.log('Verification successful'); // Handle successful verification }} onError={() => { console.error('Failed to verify identity'); }} /> ); } ``` -------------------------------- ### JavaScript Example: Dynamic Config with userDefinedData Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/frontend-configuration.md Demonstrates passing dynamic data to the contract for selecting different verification configurations. This example uses a hex string to indicate an action type. ```javascript // Pass action type for dynamic config selection const selfApp = new SelfAppBuilder({ endpoint: "YOUR_CONTRACT_ADDRESS", userDefinedData: "0x01", // Action type for contract routing disclosures: { minimumAge: 18, nationality: true } // ... other config }).build(); ``` -------------------------------- ### JavaScript: Dynamic Configuration Switching Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Illustrates a dynamic configuration strategy where the `getConfig` and `getActionId` methods of a `DynamicConfigStorage` class determine verification settings based on context or user data. ```javascript class DynamicConfigStorage { async getConfig(configId: string) { switch(configId) { case 'strict': return { minimumAge: 21, ofac: true }; case 'relaxed': return { minimumAge: 18, ofac: false }; default: return { minimumAge: 18, ofac: true }; } } async getActionId(userIdentifier: string, userDefinedData?: string) { // Select config based on user data return userDefinedData === 'premium' ? 'strict' : 'relaxed'; } } ``` -------------------------------- ### Example: Full Disclosure Configuration Source: https://github.com/selfxyz/self-docs/blob/main/use-self/disclosures.md An example demonstrating a comprehensive disclosure configuration, combining verification requirements like minimum age, OFAC checks, and country exclusions with requests for personal and document information. ```javascript disclosures: { // Verification requirements (must match backend) minimumAge: 21, excludedCountries: ['IRN'], ofac: true, // Disclosure requests (frontend only) nationality: true, gender: true, name: false, // Don't request name date_of_birth: true, passport_number: false, // Don't request for privacy } ``` -------------------------------- ### Render SelfQRcodeWrapper in a React Component Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Shows how to embed the `SelfQRcodeWrapper` component within a React functional component. It passes the pre-configured `selfApp` object and defines an `onSuccess` callback to execute logic upon successful identity verification. ```javascript function MyComponent() { return ( { console.log('Verification successful'); // Perform actions after successful verification }} /> ); } ``` -------------------------------- ### JavaScript: Frontend-Backend Configuration Sync Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Ensures consistency between frontend and backend configurations for verification disclosures. Demonstrates how to set parameters like minimum age, excluded countries, and OFAC status on both sides. ```javascript // Frontend disclosures: { minimumAge: 18, excludedCountries: ['IRN', 'PRK'], ofac: true } // Backend (in getConfig) return { minimumAge: 18, excludedCountries: ['IRN', 'PRK'], ofac: true }; ``` -------------------------------- ### DefaultConfigStore Usage Source: https://github.com/selfxyz/self-docs/blob/main/sdk-reference/selfbackendverifier.md Illustrates the setup of DefaultConfigStore for static, uniform verification requirements. This store provides the same configuration regardless of user context. ```typescript import { DefaultConfigStore } from '@selfxyz/core'; const configStore = new DefaultConfigStore({ minimumAge: 21, excludedCountries: ['IRN', 'PRK'], ofac: true }); // Always returns the same configuration regardless of user or context ``` -------------------------------- ### Solidity Contract Functions for User Defined Data Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/frontend-configuration.md Demonstrates how smart contracts can access and utilize `userDefinedData` passed from the frontend. Includes examples for `getConfigId` and `customVerificationHook`. ```solidity // In getConfigId - used for configuration selection function getConfigId( bytes32 destinationChainId, bytes32 userIdentifier, bytes memory userDefinedData // ← Your custom data here ) public view override returns (bytes32) { // Return your configuration ID return YOUR_CONFIG_ID; } // In customVerificationHook - userData contains full context including userDefinedData function customVerificationHook( ISelfVerificationRoot.GenericDiscloseOutputV2 memory output, bytes memory userData // ← First 64 bytes are destChainId+userIdentifier, rest is userDefinedData ) internal override { bytes memory userDefinedData = userData[64:]; // Extract custom data // Implement your business logic based on userDefinedData } ``` -------------------------------- ### JavaScript: Testing with Mock Passports Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Shows how to initialize and use the `SelfBackendVerifier` in mock mode for testing purposes. It includes setting up a mock `ConfigStorage` to disable OFAC checks, which is necessary for mock passports. ```javascript // Use staging/testnet for development const verifier = new SelfBackendVerifier( "test-scope", "https://test.ngrok.app/verify", true, // Enable mock mode allowedIds, configStorage, UserIdType.UUID ); // Disable OFAC for mock passports class ConfigStorage { async getConfig() { return { minimumAge: 18, ofac: false // Must be false for mock passports }; } } ``` -------------------------------- ### JavaScript: Robust Error Handling for Verification Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Demonstrates a `try...catch` block for handling potential errors during the verification process. It specifically checks for `ConfigMismatchError` to log detailed issues and return user-friendly messages. ```javascript try { const result = await verifier.verify(/* params */); } catch (error) { if (error.name === 'ConfigMismatchError') { // Log detailed issues for debugging console.error('Config issues:', error.issues); // Return user-friendly message return { error: 'Verification configuration error' }; } // Handle other errors } ``` -------------------------------- ### Update QR Code Configuration (Frontend) Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Demonstrates the migration of the SelfAppBuilder configuration from V1 to V2. Key changes include specifying the version and adding the new `disclosures` object for verification rules and data fields. ```javascript // V1 (Old): import { SelfAppBuilder } from '@selfxyz/qrcode'; const selfApp = new SelfAppBuilder({ appName: "My App", scope: "my-app-scope", endpoint: "https://api.example.com/verify", userId: userId, logoBase64: logo }).build(); ``` ```javascript // V2 (New): import { SelfAppBuilder } from '@selfxyz/qrcode'; const selfApp = new SelfAppBuilder({ appName: "My App", scope: "my-app-scope", endpoint: "https://api.example.com/verify", userId: userId, logoBase64: logo, version: 2, // NEW: Specify V2 userDefinedData: "custom-data", // NEW: Optional custom data disclosures: { // NEW: Must match backend config // Verification rules minimumAge: 18, excludedCountries: ['IRN', 'PRK'], ofac: true, // Data fields to reveal name: true, nationality: true, dateOfBirth: true } }).build(); ``` -------------------------------- ### Optimizing Data Size for User Context Source: https://github.com/selfxyz/self-docs/blob/main/concepts/user-context-data.md Demonstrates strategies for reducing the size of user-defined data to fit within a 64-byte limit. It shows examples of compact data structures and using references for larger payloads. ```javascript // ❌ Too large - will be truncated const largeData = { action: "complex_operation", metadata: { field1: "value1", field2: "value2", // ... many more fields } }; // ✅ Compact representation const compactData = { a: "transfer", // Use short keys v: 10000, // Numeric values are efficient t: Date.now() }; // For larger data, use references const referenceData = { sessionId: "abc123", // Store full data server-side version: 2 }; ``` -------------------------------- ### Smart Contract Inheritance V1 vs V2 Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Illustrates the change in smart contract inheritance for SelfXYZ integration. V1 used direct interface integration, while V2 requires inheriting from `SelfVerificationRoot` and overriding specific hooks. ```solidity // V1 (Old): import { IIdentityVerificationHub } from "@selfxyz/contracts/interfaces/IIdentityVerificationHub.sol"; contract MyContract { IIdentityVerificationHub public hub; function verify(/* params */) external { // Direct hub integration } } ``` ```solidity // V2 (New): import { SelfVerificationRoot } from "@selfxyz/contracts/abstract/SelfVerificationRoot.sol"; contract MyContract is SelfVerificationRoot { constructor( address _hub, bytes32 _scope ) SelfVerificationRoot(_hub, _scope) {} // Override to handle verification results function customVerificationHook( GenericDiscloseOutputV2 memory output, bytes memory userData ) internal override { // Your business logic here } // Override to provide configuration ID function getConfigId( bytes32 destinationChainId, bytes32 userIdentifier, bytes memory userDefinedData ) public view override returns (bytes32) { // Generate your config ID at https://tools.self.xyz/ // Default config ID: 0x7b6436b0c98f62380866d9432c2af0ee08ce16a171bda6951aecd95ee1307d61 return 0x7b6436b0c98f62380866d9432c2af0ee08ce16a171bda6951aecd95ee1307d61; } } ``` -------------------------------- ### JavaScript: Managing Allowed Document Types Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Demonstrates how to configure the 'allowedIds' variable to specify which document types are permitted for verification. This includes options for allowing all types or defining a specific subset. ```javascript // Option 1: Use AllIds for all document types const allowedIds = AllIds; // Option 2: Define specific allowed document types // const allowedIds = new Map(); // allowedIds.set(AttestationId.E_PASSPORT, true); // Add passport // allowedIds.set(AttestationId.EU_ID_CARD, true); // Add EU ID card ``` -------------------------------- ### Hard-coded Config ID in Solidity Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/basic-integration.md Demonstrates how to hard-code a verification configuration ID directly within a Solidity smart contract function. This approach is simple but requires contract redeployment for ID changes. ```solidity function getConfigId( bytes32 _destinationChainId, bytes32 _userIdentifier, bytes memory _userDefinedData ) public view override returns (bytes32) { // Replace with your actual config ID from the tool return 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; } ``` -------------------------------- ### Use Case: Complete Identity Verification Source: https://github.com/selfxyz/self-docs/blob/main/use-self/disclosures.md An example of a comprehensive identity verification setup. It includes age checks, OFAC screening, and requests for nationality, name, and date of birth. ```javascript disclosures: { minimumAge: 21, ofac: true, nationality: true, name: true, date_of_birth: true, } ``` -------------------------------- ### Verify Proof Data Source: https://github.com/selfxyz/self-docs/blob/main/use-self/quickstart.md Details the process of verifying proof data received from the frontend. It covers extracting necessary fields from the request, validating their presence, and calling the verifier's `verify` method. The snippet also shows how to handle successful and failed verification results. ```javascript // Extract data from the request const { attestationId, proof, publicSignals, userContextData } = await req.json(); // Verify all required fields are present if (!proof || !publicSignals || !attestationId || !userContextData) { return NextResponse.json({ message: "Proof, publicSignals, attestationId and userContextData are required", }, { status: 400 }); } // Verify the proof const result = await selfBackendVerifier.verify( attestationId, // Document type (1 = passport, 2 = EU ID card) proof, // The zero-knowledge proof publicSignals, // Public signals array userContextData // User context data ); // Check if verification was successful if (result.isValidDetails.isValid) { // Verification successful - process the result return NextResponse.json({ status: "success", result: true, credentialSubject: result.discloseOutput, }); } else { // Verification failed return NextResponse.json({ status: "error", result: false, message: "Verification failed", details: result.isValidDetails, }, { status: 500 }); } ``` -------------------------------- ### Setter Function for Scope in Solidity Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/basic-integration.md Provides an example of a setter function in Solidity to update an internal scope value. It includes a security note recommending access control for production environments. ```solidity /** * @notice Expose the internal _setScope function for testing * @param newScope The new scope value to set */ function setScope(uint256 newScope) external { _setScope(newScope); } ``` -------------------------------- ### Update Configuration: V1 Methods vs V2 Storage Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Illustrates the shift in configuration management from V1's direct method calls to V2's centralized approach using an `IConfigStorage` implementation. V2 consolidates settings like minimum age, excluded countries, and OFAC checks into a single configuration object. ```javascript // V1 (Old): // Direct method calls verifier.setMinimumAge(18); verifier.excludeCountries('Iran', 'North Korea'); verifier.enablePassportNoOfacCheck(); verifier.enableNameOfacCheck(); verifier.enableDobOfacCheck(); ``` ```javascript // V2 (New): // Configuration via IConfigStorage implementation class ConfigStorage implements IConfigStorage { async getConfig(configId: string) { // All configuration in one place return { minimumAge: 18, excludedCountries: ['IRN', 'PRK'], // Use ISO 3-letter codes ofac: true // Single boolean for all OFAC checks }; } } ``` -------------------------------- ### Build Self App Configuration with User Data Source: https://github.com/selfxyz/self-docs/blob/main/concepts/user-context-data.md Demonstrates frontend usage by building a Self app configuration, including setting user-defined data by encoding a JSON object to hex and ensuring it's the correct length. ```javascript const selfApp = new SelfAppBuilder({ appName: "My App", scope: "my-app", endpoint: "https://api.myapp.com/verify", userId: uuidv4(), version: 2, userDefinedData: "0x" + Buffer.from(JSON.stringify({ action: "create_account", referralCode: "SUMMER2024", tier: "premium" })).toString('hex').slice(0, 128), // Ensure exactly 64 bytes disclosures: { /* ... */ } }).build(); ``` -------------------------------- ### Use Case: Age Verification Only Source: https://github.com/selfxyz/self-docs/blob/main/use-self/disclosures.md A minimal configuration focused solely on age verification. This setup requests only the minimum age requirement, revealing no other personal data. ```javascript disclosures: { minimumAge: 18, // No personal data revealed } ``` -------------------------------- ### Solidity: Configuration Management Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/happy-birthday-example.md Details the function to retrieve the verification configuration ID, used to override or provide the configId for verification processes. This function is marked as 'view' and 'override'. ```solidity function getConfigId( bytes32 destinationChainId, bytes32 userIdentifier, bytes memory userDefinedData ) public view override returns (bytes32) { return verificationConfigId; } ``` -------------------------------- ### JavaScript Example: Geographic Restrictions Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/frontend-configuration.md Sets up geographic restrictions for verification by excluding specific countries. Requires disclosure of nationality and optionally issuing state for filtering. ```javascript disclosures: { excludedCountries: ["USA", "RUS"], nationality: true, // Required for geo-filtering issuing_state: true // Optional: additional geo data } ``` -------------------------------- ### Dynamic Configuration ID System Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/basic-integration.md Implements a dynamic system for selecting verification configuration IDs based on user context, parsed from user data. It includes mappings for access codes to contracts and config IDs, and handles different verification flows via an action code. ```solidity // Default config ID for general verifications bytes32 private constant DEFAULT_VERIFICATION_CONFIG_ID = 0x7b6436b0c98f62380866d9432c2af0ee08ce16a171bda6951aecd95ee1307d61; // Core mappings for dynamic config system mapping(bytes32 accessCode => address targetContract) public codeToContractAddress; mapping(address targetContract => bytes32 configId) public configIds; mapping(address participant => bool verified) public isVerified; // Example interface for external contract interaction interface ExternalContract { function addParticipant(address participant, bytes memory nationality) external; } /** * @notice Retrieves the appropriate configuration ID based on user data. * @dev Parses user data to determine action type and access code, then selects the config ID. * @param _destinationChainId The destination chain identifier. * @param _userIdentifier The unique identifier for the user. * @param _userDefinedData Encoded user intent, typically actionType + accessCode. * @return bytes32 The resolved configuration ID. */ function getConfigId( bytes32 _destinationChainId, bytes32 _userIdentifier, bytes memory _userDefinedData // Format: actionType + accessCode ) public view override returns (bytes32) { (uint8 actionCode, bytes32 accessCode) = parseUserData(_userDefinedData); if (actionCode == 0) { // External contract interaction - use contract-specific config address contractAddr = codeToContractAddress[accessCode]; return configIds[contractAddr]; } else if (actionCode == 1) { // General verification - use default config return DEFAULT_VERIFICATION_CONFIG_ID; } revert("Invalid action code"); } /** * @notice Hook executed after verification, performing context-specific actions. * @dev Handles external contract calls or marking users as verified based on action code. * @param _output GenericDiscloseOutputV2 containing verification results. * @param _userData Encoded user intent, typically actionType + accessCode. */ function customVerificationHook( ISelfVerificationRoot.GenericDiscloseOutputV2 memory _output, bytes memory _userData // Format: actionType + accessCode ) internal override { (uint8 actionCode, bytes32 accessCode) = parseUserData(_userData); address participant = address(uint160(_output.userIdentifier)); if (actionCode == 0) { // External contract interaction: call specific contract with nationality data address contractAddress = codeToContractAddress[accessCode]; require(contractAddress != address(0), "Contract not found"); ExternalContract externalContract = ExternalContract(contractAddress); externalContract.addParticipant(participant, _output.nationality); } else if (actionCode == 1) { // General verification: mark user as verified isVerified[participant] = true; } } // Helper function (assumed to be defined elsewhere or implicitly understood) // function parseUserData(bytes memory _userData) internal pure returns (uint8, bytes32) { // // Implementation to parse actionType and accessCode from _userData // // Example: return (_userData[0], bytes32(_userData[1:33])); // return (0, 0); // } ``` -------------------------------- ### SelfBackendVerifier Best Practices Source: https://github.com/selfxyz/self-docs/blob/main/sdk-reference/selfbackendverifier.md Provides a list of best practices for using the SelfBackendVerifier, covering instance reuse, comprehensive error handling, input validation, appropriate storage implementation, nullifier monitoring for proof reuse prevention, and testing strategies. ```APIDOC 1. Reuse Verifier Instance: - Create the verifier once and reuse it for all verifications. 2. Handle All Error Types: - Always catch and handle `ConfigMismatchError` to debug configuration issues. 3. Validate Input: - Ensure all parameters are present and valid before calling the `verify` method. 4. Use Appropriate Storage: - Implement `IConfigStorage` based on your specific needs (e.g., in-memory, database, distributed cache). 5. Monitor Nullifiers: - Store nullifiers to prevent proof reuse, ensuring each valid proof is used only once. 6. Test with Mock Passports: - Use `mockPassport: true` for development and testing environments to simulate verification without real credentials. ``` -------------------------------- ### Action-Based Configuration Pattern Source: https://github.com/selfxyz/self-docs/blob/main/concepts/user-context-data.md Implements an action-based configuration pattern. The frontend sends action details in user-defined data, and the backend uses this data to select appropriate configurations. ```javascript // Frontend userDefinedData: "0x" + Buffer.from(JSON.stringify({ action: "transfer", recipient: "0x123...", amount: 50000 })).toString('hex').padEnd(128, '0') // Backend async getActionId(userIdentifier: string, userDefinedData: string): Promise { const data = JSON.parse(Buffer.from(userDefinedData, 'hex').toString()); switch (data.action) { case 'transfer': return data.amount > 10000 ? 'transfer_high' : 'transfer_low'; case 'login': return 'login_config'; case 'register': return 'registration_config'; default: return 'default_config'; } } ``` -------------------------------- ### Solidity: Parse Unsigned Integer Helper Source: https://github.com/selfxyz/self-docs/blob/main/contract-integration/basic-integration.md A helper function to parse a byte array into an unsigned integer. It validates that each character in the byte array is a digit between '0' and '9'. ```solidity function parseUint(bytes memory _b) internal pure returns (uint256 result) { for (uint256 i = 1; i < _b.length; i++) { require(_b[i] >= 0x30 && _b[i] <= 0x39, "Invalid character"); result = result * 10 + (uint8(_b[i]) - 48); } } ``` -------------------------------- ### Solidity Data Structures: V1 vs V2 Source: https://github.com/selfxyz/self-docs/blob/main/use-self/migration-v1-v2.md Compares the V1 and V2 data structures used in verification processes. Highlights changes in data types and fields, such as attestationId from uint256 to bytes32 and the addition of new string fields. ```solidity struct VcAndDiscloseVerificationResult { uint256 attestationId; uint256 scope; uint256 userIdentifier; uint256 nullifier; uint256[3] revealedDataPacked; // Packed data } ``` ```solidity struct GenericDiscloseOutputV2 { bytes32 attestationId; // Now bytes32 uint256 userIdentifier; uint256 nullifier; string issuingState; // Pre-extracted string[] name; // Pre-extracted array string idNumber; // Renamed from passportNumber string nationality; // Pre-extracted string dateOfBirth; // Pre-extracted format string gender; // Pre-extracted string expiryDate; // Pre-extracted uint256 minimumAge; bool[3] ofac; // Bool array uint256[4] forbiddenCountriesListPacked; } ```