Skip to main content

x401 use cases

Sample Use Cases

Token Gating [without any backend changes]

"use client";
import { useState, useEffect } from 'react';
import { detectWallets, VelocityAuth } from "velocitytunedx401"

function GatedContent() {
    const [wallets, setWallets] = useState([]);
    const [showPopup, setShowPopup] = useState(false);
  

    useEffect(() => {
        let wallets = detectWallets();
        setWallets(wallets);
    }, []);

    const getWalletIcon = (walletName) => {
        const icons = {
            metamask: "",
            phantom: "/plogo.png",
            solflare: "/solflare.svg"
        };
        return icons[walletName];
    }

    const GATING = async (wallet) => {
        const config = {
            wallet: wallet,
            required_mint: "TOKEN CA HERE",
            mint_amount: "1",
            geo_code: "false",
            geo_code_locs: "",
            coords: {
                latitude:""
                longitude:""
            }
        }

        const result = await VelocityAuth(config);

        if (result.success) {
            if (result.alreadyAuthenticated) {
                alert("Welcome back to premium content!");
                console.log(result.token);
                // no  re authentication for already authenticated client
            } else {
                console.log(result.token);
                localStorage.setItem("vjwt", result.token);

                alert("Access granted! Enjoy premium content")
                // Redirect to app
            }
        } else {
            switch(result.error) {
                case "INSUFFICIENT_TOKENS":
                    alert(`You need tokens  to access`);
                    break;
                    // custom logic  to deny access
            }
        }
    }

    return (
        <div className="items-center justify-center p-20" style={{ background: '', minHeight: '90vh' }}>
            <button
                onClick={() => setShowPopup(true)}
                className="px-10 py-1 text-lg font-bold uppercase tracking-widest rounded-lg transition duration-300 ease-in-out bg-white/10 backdrop-blur-md border border-purple-500/50 text-white shadow-[0_0_15px_rgba(168,85,247,0.7)] hover:bg-white/20 hover:border-fuchsia-500/70 transform hover:scale-[1.02]"
            >
                Access Premium Content
            </button>

            {showPopup && (
                <div 
                    className="fixed inset-0 z-50 bg-black bg-opacity-80 flex items-center justify-center p-2 backdrop-blur-sm"
                    onClick={() => setShowPopup(false)}
                >
                    <div 
                        className="bg-gray-900/95 p-6 rounded-xl shadow-[0_0_40px_rgba(124,58,237,0.9)] w-full max-w-sm border border-purple-700/70"
                        onClick={(e) => e.stopPropagation()}
                    >
                        <div className="flex justify-between items-center mb-2">
                            <h2 className="text-2xl font-bold text-white tracking-wide">
                                Connect Wallet 
                            </h2>
                            <button 
                                onClick={() => setShowPopup(false)}
                                className="text-gray-400 hover:text-white transition duration-200 p-1"
                            >
                            </button>
                        </div>
                        
                        <div className="space-y-3">
                            {wallets.map((wallet, index) => (
                                <button
                                    key={wallet.address || index}
                                    onClick={() => GATING(wallet)}
                                    className="flex items-center justify-start gap-3 w-full p-3 rounded-lg transition duration-200 bg-gray-800/80 border border-transparent hover:bg-purple-600/30 hover:border-fuchsia-500 shadow-md hover:scale-[1.02]"
                                >
                                    <img 
                                        src={getWalletIcon(wallet)} 
                                        alt={`${wallet.wallet} icon`}
                                        className="w-8 h-8 rounded-md"
                                    />
                                    <span className="text-lg font-semibold text-white font-mono">
                                        {wallet == "phantom" ? ("PHANTOM") : ("SOLFLARE")}
                                    </span>
                                </button>
                            ))}
                        </div>

                        {wallets.length === 0 && (
                            <p className="text-center text-gray-400 pt-4">No wallets detected.</p>
                        )}
                    </div>
                </div>
            )}
        </div>
    );
}

export default GatedContent;


DAO Voting Access [ without any backend changes]


"use client";
import { useState, useEffect } from 'react';
import { detectWallets,VelocityAuth } from "velocitytunedx401"

function DAOVoting() {
    const [wallets, setWallets] = useState([]);
    const [showPopup, setShowPopup] = useState(false);
  
   

    useEffect(() => {
        let wallets = detectWallets();
        setWallets(wallets);
    }, []);

    const getWalletIcon = (walletName) => {
        const icons = {
            metamask: "",
            phantom: "/plogo.png",
            solflare: "/solflare.svg"
        };
        return icons[walletName];
    }

    const DAOACCESS = async (wallet) => {
        const config = {
            wallet: wallet,
            required_mint: "DAO_TOKEN_CA",
            mint_amount: "100.0",
            geo_code: "false",
            geo_code_locs: "",
            coords: {
                latitude: "",
                longitude:""
            }
        }

        const result = await VelocityAuth(config);

        if (result.success) {
            if (result.alreadyAuthenticated) {
                alert("already authenticated");
                console.log(result.token);
                // Show voting interface
            } else {
                console.log(result.token);
                localStorage.setItem("vjwt", result.token);
                alert("authenticated - you can now vote");
                // Load proposals
            }
        } else {
            switch(result.error) {
                case "INSUFFICIENT_TOKENS":
                    alert(`You need ${result.required} tokens to vote`);
                    break;
        }
    }

    return (
        <div className="items-center justify-center p-20" style={{ background: '', minHeight: '90vh' }}>
            <button
                onClick={() => setShowPopup(true)}
                className="px-10 py-1 text-lg font-bold uppercase tracking-widest rounded-lg transition duration-300 ease-in-out bg-white/10 backdrop-blur-md border border-purple-500/50 text-white shadow-[0_0_15px_rgba(168,85,247,0.7)] hover:bg-white/20 hover:border-fuchsia-500/70 transform hover:scale-[1.02]"
            >
                Connect to Vote
            </button>

            {showPopup && (
                <div 
                    className="fixed inset-0 z-50 bg-black bg-opacity-80 flex items-center justify-center p-2 backdrop-blur-sm"
                    onClick={() => setShowPopup(false)}
                >
                    <div 
                        className="bg-gray-900/95 p-6 rounded-xl shadow-[0_0_40px_rgba(124,58,237,0.9)] w-full max-w-sm border border-purple-700/70"
                        onClick={(e) => e.stopPropagation()}
                    >
                        <div className="flex justify-between items-center mb-2">
                            <h2 className="text-2xl font-bold text-white tracking-wide">
                                Connect Wallet 
                            </h2>
                            <button 
                                onClick={() => setShowPopup(false)}
                                className="text-gray-400 hover:text-white transition duration-200 p-1"
                            >
                            </button>
                        </div>
                        
                        <div className="space-y-3">
                            {wallets.map((wallet, index) => (
                                <button
                                    key={wallet.address || index}
                                    onClick={() => DAOACCESS(wallet)}
                                    className="flex items-center justify-start gap-3 w-full p-3 rounded-lg transition duration-200 bg-gray-800/80 border border-transparent hover:bg-purple-600/30 hover:border-fuchsia-500 shadow-md hover:scale-[1.02]"
                                >
                                    <img 
                                        src={getWalletIcon(wallet)} 
                                        alt={`${wallet.wallet} icon`}
                                        className="w-8 h-8 rounded-md"
                                    />
                                    <span className="text-lg font-semibold text-white font-mono">
                                        {wallet == "phantom" ? ("PHANTOM") : ("SOLFLARE")}
                                    </span>
                                </button>
                            ))}
                        </div>

                        {wallets.length === 0 && (
                            <p className="text-center text-gray-400 pt-4">No wallets detected.</p>
                        )}
                    </div>
                </div>
            )}
        </div>
    );
}

export default DAOVoting;

Geo Restricted Access [without any backend changes]

"use client";
import { useState, useEffect } from 'react';
import { detectWallets, getGeolocationData, VelocityAuth } from "velocitytunedx401"

function GeoRestrictedEntry() {
    
    const [wallets, setWallets] = useState([]);
    const [showPopup, setShowPopup] = useState(false);
    const [location, setLocation] = useState({
        latitude: null,
        longitude: null,
        error: null,
        isFetching: false,
    });

    useEffect(() => {
        async function fetchLocation() {
            const locationdata = await getGeolocationData(); 
            setLocation({
                latitude: locationdata.latitude || null, 
                longitude: locationdata.longitude || null,
                error: locationdata.error || null,
                isFetching: false,
            });
        }
        fetchLocation(); 
    }, []);

    useEffect(() => {
        let wallets = detectWallets();
        setWallets(wallets);
    }, []);

    const getWalletIcon = (walletName) => {
        const icons = {
            metamask: "",
            phantom: "/plogo.png",
            solflare: "/solflare.svg"
        };
        return icons[walletName];
    }

    const RUN = async (wallet) => {
        const config = {
            wallet: wallet,
            required_mint: "TOURNAMENT_TOKEN_CA",
            mint_amount: "50.0",
            geo_code: "true",
            geo_code_locs: "US",
            coords: {
                latitude: location.latitude,
                longitude: location.longitude
            }
        }

        const result = await VelocityAuth(config);

        if (result.success) {
            if (result.alreadyAuthenticated) {
                alert("already registered for tournament");
                console.log(result.token);
                
            } else {
                console.log(result.token);
                localStorage.setItem("vjwt", result.token);
                alert("entry approved!");
                // Enter
            }
        } else {
            switch(result.error) {
                case "INSUFFICIENT_TOKENS":
                    alert(`You need ${result.required} tokens to enter`);
                    break;
                case "LOCATION_DENIED":
                    alert("Tournament only available in US, CA, MX");
                    break;
                case "LOCATION_ERROR":
                    alert("Location permission denied");
                    break;
            }
        }
    }

    return (
        <div className="items-center justify-center p-20" style={{ background: '', minHeight: '90vh' }}>
            <button
                onClick={() => setShowPopup(true)}
                className="px-10 py-1 text-lg font-bold uppercase tracking-widest rounded-lg transition duration-300 ease-in-out bg-white/10 backdrop-blur-md border border-purple-500/50 text-white shadow-[0_0_15px_rgba(168,85,247,0.7)] hover:bg-white/20 hover:border-fuchsia-500/70 transform hover:scale-[1.02]"
            >
                Join Tournament
            </button>

            {showPopup && (
                <div 
                    className="fixed inset-0 z-50 bg-black bg-opacity-80 flex items-center justify-center p-2 backdrop-blur-sm"
                    onClick={() => setShowPopup(false)}
                >
                    <div 
                        className="bg-gray-900/95 p-6 rounded-xl shadow-[0_0_40px_rgba(124,58,237,0.9)] w-full max-w-sm border border-purple-700/70"
                        onClick={(e) => e.stopPropagation()}
                    >
                        <div className="flex justify-between items-center mb-2">
                            <h2 className="text-2xl font-bold text-white tracking-wide">
                                Connect Wallet 
                            </h2>
                            <button 
                                onClick={() => setShowPopup(false)}
                                className="text-gray-400 hover:text-white transition duration-200 p-1"
                            >
                            </button>
                        </div>
                        
                        <div className="space-y-3">
                            {wallets.map((wallet, index) => (
                                <button
                                    key={wallet.address || index}
                                    onClick={() => RUN(wallet)}
                                    className="flex items-center justify-start gap-3 w-full p-3 rounded-lg transition duration-200 bg-gray-800/80 border border-transparent hover:bg-purple-600/30 hover:border-fuchsia-500 shadow-md hover:scale-[1.02]"
                                >
                                    <img 
                                        src={getWalletIcon(wallet)} 
                                        alt={`${wallet.wallet} icon`}
                                        className="w-8 h-8 rounded-md"
                                    />
                                    <span className="text-lg font-semibold text-white font-mono">
                                        {wallet == "phantom" ? ("PHANTOM") : ("SOLFLARE")}
                                    </span>
                                </button>
                            ))}
                        </div>

                        {wallets.length === 0 && (
                            <p className="text-center text-gray-400 pt-4">No wallets detected.</p>
                        )}
                    </div>
                </div>
            )}
        </div>
    );
}

export default GeoRestrictedEntry;