This skill should be used when the user asks about "BlockDrive auth flow", "wallet sync to database", "Clerk Crossmint Supabase integration", "embedded wallet sync", "user profile with wallet", "sync-crossmint-wallet", "wallet database storage", "multichain wallet flow", or needs to understand or implement the complete authentication and wallet synchronization flow used in BlockDrive. This is the core integration pattern connecting user identity to multichain blockchain wallets.
BlockDrive uses a three-service integration pattern: Clerk for identity, Crossmint for embedded wallets, and Supabase for data persistence. This creates a seamless experience where users authenticate once and automatically receive multichain blockchain wallets (Solana + EVM chains) linked to their account.
Activate this skill when:
┌─────────────────────────────────────────────────────────────────┐
│ BLOCKDRIVE AUTH ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ CLERK │────▶│ CROSSMINT │────▶│ SUPABASE │ │
│ │ Identity │ │ Multi-Wallet │ │ Database │ │
│ └──────────┘ └──────────────┘ └──────────┘ │
│ │ │ │ │
│ │ │ │ │
│ 1. User signs in 2. Creates wallets 3. Multi-chain │
│ via Clerk on ALL chains addresses stored │
│ │
│ ──────────────────────────────────────────────────────────── │
│ │
│ User Experience: Sign in once → Wallets automatically created │
│ No seed phrases, no wallet extensions, gas-sponsored txns │
│ Supported Chains: Solana + Ethereum + Base + Polygon + more │
│ │
└─────────────────────────────────────────────────────────────────┘
// User signs in via Clerk UI component
// Clerk manages the entire auth flow
import { useAuth, useUser } from '@clerk/clerk-react';
const { isSignedIn, getToken } = useAuth();
const { user } = useUser();
// Wait for successful sign-in
if (isSignedIn && user) {
// Proceed to wallet initialization
const email = user.primaryEmailAddress?.emailAddress;
}
import { CrossmintWalletProvider } from '@crossmint/client-sdk-react-ui';
// Crossmint automatically creates wallets on login
// No manual initialization required
<CrossmintWalletProvider createOnLogin={{
chain: 'solana:devnet', // Primary chain
signer: { type: 'email', email: user.email },
}}>
{children}
</CrossmintWalletProvider>
// Wallets created on ALL chains:
// - Solana (devnet/mainnet)
// - Ethereum, Base, Polygon, Arbitrum, Optimism
import { useWallet } from '@crossmint/client-sdk-react-ui';
const { wallet } = useWallet();
// Get addresses for all chains
const addresses = {
solana: wallet.address, // Primary Solana address
ethereum: await wallet.getAddress('ethereum'),
base: await wallet.getAddress('base'),
polygon: await wallet.getAddress('polygon'),
};
// Call Supabase edge function to sync wallet addresses
const response = await fetch(
`${SUPABASE_URL}/functions/v1/sync-crossmint-wallet`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${clerkToken}`,
},
body: JSON.stringify({
clerkUserId: user.id,
walletId: wallet.id,
addresses: addresses,
}),
}
);
// Edge function stores addresses in crossmint_wallets table
CREATE TABLE crossmint_wallets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES profiles(id),
clerk_user_id TEXT NOT NULL,
-- Crossmint wallet identifier
crossmint_wallet_id TEXT UNIQUE NOT NULL,
-- Multi-chain addresses
solana_address TEXT,
ethereum_address TEXT,
base_address TEXT,
polygon_address TEXT,
arbitrum_address TEXT,
optimism_address TEXT,
-- Metadata
wallet_type TEXT DEFAULT 'crossmint_embedded',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
is_active BOOLEAN DEFAULT TRUE,
CONSTRAINT unique_user_crossmint UNIQUE (user_id, clerk_user_id)
);
-- Indexes for fast lookups
CREATE INDEX idx_crossmint_wallets_clerk_user ON crossmint_wallets(clerk_user_id);
CREATE INDEX idx_crossmint_wallets_solana ON crossmint_wallets(solana_address);
CREATE INDEX idx_crossmint_wallets_ethereum ON crossmint_wallets(ethereum_address);
// supabase/functions/sync-crossmint-wallet/index.ts
import { serve } from 'https://deno.land/[email protected]/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
serve(async (req) => {
const { clerkUserId, walletId, addresses } = await req.json();
// Initialize Supabase
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);
// Get user profile
const { data: profile } = await supabase
.from('profiles')
.select('id')
.eq('clerk_user_id', clerkUserId)
.single();
// Upsert wallet addresses
await supabase
.from('crossmint_wallets')
.upsert({
user_id: profile.id,
clerk_user_id: clerkUserId,
crossmint_wallet_id: walletId,
solana_address: addresses.solana,
ethereum_address: addresses.ethereum,
base_address: addresses.base,
polygon_address: addresses.polygon,
updated_at: new Date().toISOString(),
}, {
onConflict: 'clerk_user_id',
});
return new Response(JSON.stringify({ success: true }));
});
// src/providers/CrossmintProvider.tsx
import { CrossmintProvider, CrossmintAuthProvider, CrossmintWalletProvider } from '@crossmint/client-sdk-react-ui';
import { useAuth, useUser } from '@clerk/clerk-react';
export function AppCrossmintProvider({ children }) {
const { isSignedIn } = useAuth();
const { user } = useUser();
if (!isSignedIn || !user) {
return <>{children}</>;
}
return (
<CrossmintProvider apiKey={CROSSMINT_API_KEY}>
<CrossmintAuthProvider>
<CrossmintWalletProvider createOnLogin={{
chain: 'solana:devnet',
signer: { type: 'email', email: user.primaryEmailAddress.emailAddress },
}}>
{children}
</CrossmintWalletProvider>
</CrossmintAuthProvider>
</CrossmintProvider>
);
}
For comprehensive implementation details, see:
plugins/crossmint-fullstack//crossmint:setup/crossmint:create-wallet-flowdocs/CROSSMINT_INTEGRATION_PLAN.md| Feature | Previous (Alchemy) | Current (Crossmint) |
|---|---|---|
| Chains Supported | Solana only | Solana + 50+ EVM chains |
| Wallet Creation | Manual per chain | Automatic multichain |
| Setup Complexity | Moderate | Simple (createOnLogin) |
| NFT Minting | External tools | Built-in API |
| Gas Sponsorship | Policy-based | Built-in |
| Enterprise Features | Limited | AML/KYC built-in |
Issue: Wallet not created after sign-in
createOnLogin config is setIssue: Addresses not syncing to database
Issue: Wrong chain addresses
wallet.getAddress(chain) for specific chainsnpm install @crossmint/client-sdk-react-ui/crossmint:setup/crossmint:create-wallet-flowsupabase functions deploy sync-crossmint-walletplugins/crossmint-fullstack/