Guides
Create Wallet

Create Wallet

This guide walks through creating a passkey-authenticated wallet with Veridex.

Prerequisites

  • Veridex SDK installed (npm install @veridex/sdk)
  • WebAuthn-compatible browser
  • Device with biometric capability (FaceID, TouchID, fingerprint)

Basic Wallet Creation

1. Initialize the SDK

import { createSDK } from '@veridex/sdk';
 
const sdk = createSDK('base', {
  network: 'testnet', // or 'mainnet'
  relayerUrl: 'https://relayer.veridex.network',
});

2. Register a Passkey

const credential = await sdk.passkey.register(
  'user@example.com',  // Username (shown in passkey prompt)
  'My Veridex Wallet'  // Display name
);
 
console.log('Credential ID:', credential.credentialId);
console.log('Key Hash:', credential.keyHash);
console.log('Public Key X:', credential.publicKeyX);
console.log('Public Key Y:', credential.publicKeyY);

The browser will prompt the user for biometric authentication (FaceID, TouchID, etc.).

3. Get Your Vault Address

const vaultAddress = sdk.getVaultAddress();
console.log('Your vault address:', vaultAddress);
 
// This address is the SAME on all EVM chains!
// You can share it as your receiving address

Returning Users (Login)

Check for Existing Credentials

// Check if user has stored credentials
const storedCredentials = sdk.passkey.getAllStoredCredentials();
 
if (storedCredentials.length > 0) {
  // User has previously registered
  console.log(`Found ${storedCredentials.length} stored passkey(s)`);
} else {
  // First time user
  console.log('No passkey found, will need to register');
}

Authenticate with Existing Passkey

// Authenticate — shows passkey picker with all available credentials
const { credential, signature } = await sdk.passkey.authenticate();
 
// Now the SDK is authenticated and ready to use
const vault = sdk.getVaultAddress();
console.log('Logged in as:', credential.keyHash);
console.log('Vault:', vault);

Complete Flow Example

import { createSDK } from '@veridex/sdk';
 
async function connectWallet() {
  const sdk = createSDK('base', {
    network: 'testnet',
    relayerUrl: 'https://relayer.veridex.network',
  });
 
  // Check for existing credentials
  const storedCredentials = sdk.passkey.getAllStoredCredentials();
 
  if (storedCredentials.length > 0) {
    // Returning user — authenticate (shows passkey picker)
    console.log('Logging in with existing passkey...');
    await sdk.passkey.authenticate();
  } else {
    // New user — register
    console.log('Creating new passkey wallet...');
    await sdk.passkey.register(
      'user@example.com',
      'My Veridex Wallet'
    );
  }
 
  // Get vault info
  const vaultAddress = sdk.getVaultAddress();
  const credential = sdk.passkey.getCredential();
 
  return {
    vaultAddress,
    credentialId: credential?.credentialId,
  };
}
 
// Usage
connectWallet()
  .then(({ vaultAddress }) => {
    console.log('Connected! Vault:', vaultAddress);
  })
  .catch((error) => {
    console.error('Failed to connect:', error);
  });

React Component Example

import { useState, useEffect } from 'react';
import { createSDK } from '@veridex/sdk';
 
const sdk = createSDK('base', { 
  network: 'testnet',
  relayerUrl: 'https://relayer.veridex.network',
});
 
export function ConnectButton() {
  const [vault, setVault] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
 
  // Check for existing credentials on mount
  useEffect(() => {
    const stored = sdk.passkey.getAllStoredCredentials();
    if (stored.length > 0) {
      // Auto-login if credentials exist
      handleConnect();
    }
  }, []);
 
  const handleConnect = async () => {
    setLoading(true);
    setError(null);
 
    try {
      const stored = sdk.passkey.getAllStoredCredentials();
      
      if (stored.length > 0) {
        await sdk.passkey.authenticate();
      } else {
        await sdk.passkey.register('user@example.com', 'My Wallet');
      }
 
      setVault(sdk.getVaultAddress());
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to connect');
    } finally {
      setLoading(false);
    }
  };
 
  const handleDisconnect = () => {
    // Clear the active credential from memory
    sdk.passkey.clearCredential();
    setVault(null);
  };
 
  if (vault) {
    return (
      <div className="flex items-center gap-4">
        <span className="text-sm font-mono">
          {vault.slice(0, 6)}...{vault.slice(-4)}
        </span>
        <button 
          onClick={handleDisconnect}
          className="text-red-500 text-sm"
        >
          Disconnect
        </button>
      </div>
    );
  }
 
  return (
    <div>
      <button
        onClick={handleConnect}
        disabled={loading}
        className="bg-blue-600 text-white px-4 py-2 rounded-lg"
      >
        {loading ? 'Connecting...' : 'Connect with Passkey'}
      </button>
      {error && (
        <p className="text-red-500 text-sm mt-2">{error}</p>
      )}
    </div>
  );
}

Credential Storage

By default, credentials are stored in localStorage under the veridex_credentials key. The PasskeyManager handles persistence automatically:

// Get all stored credentials
const all = sdk.passkey.getAllStoredCredentials();
 
// Manually save credentials (e.g., after migration)
sdk.passkey.saveCredentials(all);
 
// Add a credential to storage
sdk.passkey.addCredentialToStorage(credential);
 
// Check if any credentials exist
const hasCredentials = sdk.passkey.hasStoredCredentials();

Error Handling

try {
  await sdk.passkey.register('user@example.com', 'My Wallet');
} catch (error) {
  if (error.name === 'NotAllowedError') {
    // User cancelled the passkey prompt
    console.log('User cancelled passkey creation');
  } else if (error.name === 'NotSupportedError') {
    // WebAuthn not supported
    console.log('Passkeys not supported on this device');
  } else if (error.name === 'SecurityError') {
    // Not in secure context (need HTTPS)
    console.log('HTTPS required for passkeys');
  } else {
    console.error('Unexpected error:', error);
  }
}

Agent Wallet Creation

For AI agents that need autonomous payment capabilities:

import { createAgentWallet } from '@veridex/agentic-payments';
 
// Use the credential from passkey registration
const agent = await createAgentWallet({
  masterCredential: {
    credentialId: credential.credentialId,
    publicKeyX: credential.publicKeyX,
    publicKeyY: credential.publicKeyY,
    keyHash: credential.keyHash,
  },
  session: {
    dailyLimitUSD: 50,
    perTransactionLimitUSD: 10,
    expiryHours: 24,
    allowedChains: [10004], // Base Sepolia (Wormhole chain ID)
  },
});
 
const status = agent.getSessionStatus();
console.log('Session valid:', status.isValid);
console.log('Agent wallet:', status.address);
console.log('Daily limit:', `$${status.limits!.dailyLimitUSD}`);

Stacks Wallet

Create a wallet on Stacks with native passkey support:

import { createSDK } from '@veridex/sdk';
 
const stacksSdk = createSDK('stacks', { network: 'testnet' });
 
// Passkey verified natively via Clarity's secp256r1-verify
const credential = await stacksSdk.passkey.register('alice', 'My Stacks Wallet');
const vault = stacksSdk.getVaultAddress();
console.log('Stacks vault:', vault);

Next Steps