A comprehensive Next.js 15 test application for the Veridex Protocol SDK, featuring passkey-based cross-chain authentication, gasless token transfers, and multi-chain vault management.
This test app demonstrates the @veridex/sdk package:
npm install @veridex/sdk- Passkey Registration & Login: Test WebAuthn passkey creation and authentication
- Gasless Transfers: Send tokens without paying gas - relayer covers all fees
- Wormhole Queries: Fetch Guardian-attested balances across all chains
- Multi-Chain Vaults: Automatic sponsored vault creation on all supported chains
- Cross-Chain Transfers: Execute token transfers across different chains using passkeys
- Beautiful UI: Modern glassmorphic design with real-time status indicators
- Node.js 18+ installed
- MetaMask browser extension (optional - only needed for gas-paying flows)
- Base Sepolia testnet ETH (optional - gasless transfers don't require user ETH)
- A WebAuthn-compatible device (most modern browsers support this)
-
Install Dependencies
npm install
-
Environment Variables
Create
.env.localfrom the example:cp .env.local.example .env.local
Configure the following:
# Required: Relayer URL (run locally or use hosted) NEXT_PUBLIC_RELAYER_URL=http://localhost:3001 # Optional: Wormhole Query API key (for Guardian-attested balances) NEXT_PUBLIC_WORMHOLE_QUERY_API_KEY=your-api-key-here # Optional: Sponsor key for gasless vault creation NEXT_PUBLIC_VERIDEX_SPONSOR_KEY=0x...
-
Start the Relayer (in separate terminal)
cd ../packages/relayer npm run dev -
Run Development Server
npm run dev
Note: Uses
--webpackflag for compatibility with local SDK symlinks. -
Open Browser Navigate to http://localhost:3000
- Enter a username (e.g., "alice")
- Enter a display name (e.g., "Alice")
- Click "Register Passkey"
- Follow your browser's WebAuthn prompt to create a passkey
- Your credential will be saved to localStorage
For gasless transfers, wallet connection is not required. The relayer pays all gas fees.
For legacy gas-paying flows:
- Click "Connect MetaMask"
- Approve the connection in MetaMask
- The app will automatically switch to Base Sepolia
- Ensure you have some testnet ETH for gas fees
With sponsored vault creation enabled:
- Vaults are automatically created on all supported chains
- The sponsor wallet pays for deployment gas
- No user interaction required
For manual vault creation:
- Connect your wallet first
- Click "Create Vault"
- Approve the transaction in MetaMask
The app uses gasless transfers by default:
- Select a target chain (Optimism Sepolia, Arbitrum Sepolia)
- Enter a recipient address
- Enter the amount to transfer
- Click "Send"
- Authenticate with your passkey when prompted
- No wallet approval needed - relayer pays the gas!
The transfer flow:
- SDK fetches nonce from relayer
- You sign with your passkey
- Relayer submits to Hub chain (paying gas)
- Relayer automatically relays VAA to destination chain
The app uses WebAuthn for secure, passwordless authentication:
- Registration: Creates a new passkey credential tied to your device
- Login: Authenticates using your existing passkey
- Signing: Uses the passkey to sign cross-chain transactions
Credentials are stored in localStorage and include:
- Credential ID
- Public Key (X and Y coordinates)
- Key Hash (used for vault identification)
The test app is configured for Base Sepolia as the hub chain:
| Chain | Wormhole ID | Type | Role |
|---|---|---|---|
| Base Sepolia | 10004 | EVM | Hub |
| Optimism Sepolia | 10005 | EVM | Spoke |
| Arbitrum Sepolia | 10003 | EVM | Spoke |
| Solana Devnet | 1 | Solana | Spoke |
| Aptos Testnet | 22 | Aptos | Spoke |
import { VeridexSDK, EVMClient } from '@veridex/sdk';
import { ethers } from 'ethers';
// Initialize SDK with relayer (for gasless)
const provider = new ethers.JsonRpcProvider('https://sepolia.base.org');
const evmClient = new EVMClient({
provider,
testnet: true,
hubAddress: '0x66D87dE68327f48A099c5B9bE97020Feab9a7c82',
});
const sdk = new VeridexSDK({
chain: evmClient,
testnet: true,
relayerUrl: 'http://localhost:3001',
queryApiKey: process.env.WORMHOLE_QUERY_API_KEY,
});
// Register passkey
const credential = await sdk.passkey.register('alice', 'Alice');
// Get vault address (derived from keyHash)
const vaultAddress = await sdk.getVaultAddress();
// Gasless transfer - no wallet needed!
const result = await sdk.transferViaRelayer({
targetChain: 10005, // Optimism Sepolia
token: 'native',
recipient: '0x...',
amount: ethers.parseEther('0.01'),
});
console.log('TX:', result.transactionHash);test-app/
├── app/
│ ├── globals.css # Tailwind + glassmorphic styles
│ ├── layout.tsx # Root layout with VeridexProvider
│ └── page.tsx # Main wallet/send UI
├── components/
│ ├── BalanceDisplay.tsx # Multi-chain balance cards
│ ├── ChainSelector.tsx # Chain tab navigation
│ ├── QRCode.tsx # Receive QR code modal
│ └── SendForm.tsx # Transfer form (gasless + legacy)
├── lib/
│ ├── config.ts # Chain configurations
│ └── VeridexContext.tsx # React context with SDK
└── .env.local # Environment variables
}, signer);
The app features:
- Status Cards: Real-time display of passkey, wallet, and vault status
- Registration Form: Clean form for passkey creation
- Transfer Form: Comprehensive form for cross-chain transfers
- Credential Details: Display of public key coordinates and key hash
- Error/Success Messages: User-friendly feedback for all operations
- Ensure you're using a WebAuthn-compatible browser (Chrome, Firefox, Safari, Edge)
- Check that you're on HTTPS or localhost
- Try a different authenticator (platform vs cross-platform)
- Make sure MetaMask is installed and unlocked
- Check that you're on the correct network (Base Sepolia)
- Ensure you have testnet ETH for gas fees
- Verify you have a registered passkey
- Ensure your wallet is connected
- Check you have sufficient ETH for gas
- Verify the vault exists
- Check token address is valid
- Ensure vault has sufficient token balance
- Verify recipient address is correct
- EVM Chains (Base, Optimism): Optimism Faucet
- Arbitrum, Aptos & other chains: HackQuest Faucets
- Solana Devnet: Solana Faucet
- Sui Testnet: Sui Faucet
test-app/
├── app/
│ ├── layout.tsx # Root layout with VeridexProvider
│ ├── page.tsx # Main test interface
│ └── globals.css # Global styles
├── lib/
│ ├── config.ts # SDK configuration
│ └── VeridexContext.tsx # React context for SDK state
└── package.json # Dependencies
- This is a test application for development purposes only
- Never use real funds or production keys
- Passkeys are stored in localStorage (not recommended for production)
- Always verify transactions before signing
If you run into any issues or have questions, reach out to us on Telegram:
MIT