Secure access control for Web3 applications
A powerful and flexible token-gating solution that verifies blockchain token ownership to grant access to exclusive content and features.
Token-gating is a Web3 access control mechanism that restricts content, features, or experiences to users who possess specific blockchain tokens or NFTs. It creates exclusive experiences for token holders while providing creators and platforms with new monetization opportunities.
Cryptographically verify token ownership without requiring users to transfer assets.
Connect with MetaMask, WalletConnect, Coinbase Wallet and other popular providers.
Define complex access rules based on token type, quantity, and attributes.
Simple integration with React components and flexible configuration options.
The Gatekeeper application provides a seamless user experience for token verification and access control:
The Gatekeeper interface consists of three main screens:
# Using npm
npm install @gatekeeper/react ethers wagmi
# Using yarn
yarn add @gatekeeper/react ethers wagmi
import React from 'react';
import { GatekeeperProvider } from '@gatekeeper/react';
import { WagmiConfig, createClient } from 'wagmi';
import { getDefaultProvider } from 'ethers';
import ProtectedContent from './ProtectedContent';
// Configure wagmi client
const client = createClient({
autoConnect: true,
provider: getDefaultProvider(),
});
const App = () => {
return (
<WagmiConfig client={client}>
<GatekeeperProvider apiKey="YOUR_API_KEY">
<div className="app">
<h1>Gatekeeper Demo</h1>
<ProtectedContent />
</div>
</GatekeeperProvider>
</WagmiConfig>
);
};
export default App;
import React from 'react';
import { useGatekeeper, TokenGate } from '@gatekeeper/react';
import { useAccount, useConnect } from 'wagmi';
import { InjectedConnector } from 'wagmi/connectors/injected';
const ProtectedContent = () => {
const { address, isConnected } = useAccount();
const { connect } = useConnect({
connector: new InjectedConnector(),
});
// Define token requirements
const tokenRequirements = {
conditions: [
{
contractAddress: '0x1234567890abcdef1234567890abcdef12345678',
chain: 'ethereum',
method: 'balanceOf',
minValue: '1',
}
]
};
return (
<div className="protected-content">
{!isConnected ? (
<div className="connect-wallet">
<h2>Connect Your Wallet</h2>
<p>Connect your wallet to verify token ownership</p>
<button onClick={() => connect()}>
Connect Wallet
</button>
</div>
) : (
<TokenGate
requirements={tokenRequirements}
onSuccess={() => console.log("Access granted!")}
onFail={() => console.log("Access denied!")}
>
{({ loading, hasAccess }) => (
<div>
{loading ? (
<p>Verifying token ownership...</p>
) : hasAccess ? (
<div className="exclusive-content">
<h2>Exclusive Content Unlocked!</h2>
<p>Welcome to the token-gated area.</p>
/* Your exclusive content here */
</div>
) : (
<div className="access-denied">
<h2>Access Denied</h2>
<p>You don't have the required tokens to access this content.</p>
<p>Required: At least 1 token from contract 0x1234...5678</p>
</div>
)}
</div>
)}
</TokenGate>
)}
</div>
);
};
export default ProtectedContent;
// Advanced token-gating configuration with multiple conditions
export const advancedRequirements = {
conditions: [
// Require either NFT ownership OR token balance
{
operator: 'OR',
conditions: [
// Option 1: Own at least one NFT from collection
{
contractAddress: '0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d', // BAYC
chain: 'ethereum',
method: 'balanceOf',
minValue: '1',
},
// Option 2: Hold at least 100 tokens
{
contractAddress: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', // UNI
chain: 'ethereum',
method: 'balanceOf',
minValue: '100000000000000000000', // 100 tokens with 18 decimals
}
]
},
// AND must have been a holder for at least 30 days
{
contractAddress: '0x1234567890abcdef1234567890abcdef12345678',
chain: 'ethereum',
method: 'tokenHoldTime',
minValue: '2592000', // 30 days in seconds
}
],
customErrorMessage: "You need to own a BAYC NFT or 100 UNI tokens, and have been a holder for at least 30 days"
};
/* Gatekeeper component styling */
.protected-content {
max-width: 600px;
margin: 0 auto;
padding: 2rem;
border-radius: 12px;
background-color: #ffffff;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
}
.connect-wallet {
text-align: center;
padding: 3rem 2rem;
}
.connect-wallet button {
background: linear-gradient(135deg, #4361ee 0%, #3a0ca3 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.connect-wallet button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(67, 97, 238, 0.3);
}
.exclusive-content {
padding: 2rem;
background-color: #f0f9ff;
border-left: 4px solid #4361ee;
border-radius: 8px;
}
.access-denied {
padding: 2rem;
background-color: #fff5f5;
border-left: 4px solid #e53e3e;
border-radius: 8px;
}
.access-denied h2 {
color: #e53e3e;
}
.loading {
display: flex;
justify-content: center;
align-items: center;
padding: 2rem;
}
.loading-spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
border-left-color: #4361ee;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
Gatekeeper supports various token verification strategies:
Gatekeeper is designed to be developer-friendly with: