Before continuing make sure you've followed the setup guide
Token Gate Anything
You can use Picket to token gate anything. If you want to authenticate users and verify their token ownership, you can pass the token ownership requirements to the login() function.
Login User w/ Token Ownership Requirements
Unlike Ethereum, Solana SPL tokens do not have a natural grouping under a single contract address.
Solana and Metaplex are actively working to change this; however, in the meantime, there are several different ways to reference the SPL tokens you want to token gate based off of:
import Picket from"@picketapi/picket-js";constpicket=newPicket('YOUR_PUBLISHABLE_KEY_HERE');// These requirements are for the Solana Mainnet Betaconstrequirements= { chain:"solana",// Replace this the tokens you want to verify ownership for// the token ID is the mint associated with a SPL token// user needs to own the minTokenBalance of at least one of the listed token tokenIds: ["78AZe2223PknLYT9mn2VCJPAsdvuB6LzFAhgQeVoxddW","2dQG4YYunFrbJjzW6UTcUmePs8UDy5jz43H6uSCZSAcS"],// Replace with minimum balance you want to verify users' currently hold across all token IDs, // or omit if any number of tokens is sufficient minTokenBalance:1}const { accessToken,user } =awaitpicket.login(requirements);console.log(user);
import { PicketProvider, usePicket } from"@picketapi/picket-react";functionMyApp({ children }) {return ( <PicketProviderapiKey="YOUR_PUBLISHABLE_KEY_HERE"> {children} </PicketProvider> );}// These requirements are for the Solana Mainnet Betaconstrequirements= { chain:"solana",// Replace this the tokens you want to verify ownership for// the token ID is the mint associated with a SPL token// user needs to own the minTokenBalance of at least one of the listed token tokenIds: ["78AZe2223PknLYT9mn2VCJPAsdvuB6LzFAhgQeVoxddW","2dQG4YYunFrbJjzW6UTcUmePs8UDy5jz43H6uSCZSAcS"],// Replace with minimum balance you want to verify users' currently hold across all token IDs, // or omit if any number of tokens is sufficient minTokenBalance:1}functionMySecurePage() {const { isAuthenticating,isAuthenticated,authState,logout,login } =usePicket();// user is logging inif (isAuthenticating) return"Loading";// user is not logged inif (!isAuthenticated) {return ( <div> <p>You are not logged in!</p> <buttononClick={() =>login(requirements)}>Login with Wallet</button> </div> ) }// user is logged in ๐const { user } = authState;const { walletAddress } = user;return ( <div> <p>You are logged in as {walletAddress} </p> <buttononClick={() =>logout()}>Logout</button> </div> )}
If you have a large collection of tokens that don't support the upcoming Metaplex Collection Standard, then the best proxy is a verified creator address.
Getting the Verified Creator Address
If you are the creator of the tokens and included it when you minted them, you can use your wallet address as the verified creator address.
Otherwise, if creators exists for the tokens, then you can find it in the token metadata on Solscan under the creators key. Pick one verified creator address to use.
If there are multiple token collections created by the same wallet address, users who own a token from any of the creators collections will be granted access.
import Picket from"@picketapi/picket-js";constpicket=newPicket('YOUR_PUBLISHABLE_KEY_HERE');// These requirements are for the Solana Mainnet Betaconstrequirements= { chain:"solana",// Replace this with a verified creatorAddress for your SPL tokens// If you created the tokens, it will often be your wallet address creatorAddress:"GcRZfnNriUPJwiE5AvF71R9f5ujGhYiYx7YNeq8wizzt",// Replace with minimum balance you want to verify users' currently hold across all token IDs, // or omit if any number of tokens is sufficient minTokenBalance:1}const { accessToken,user } =awaitpicket.login(requirements);console.log(user);
import { PicketProvider, usePicket } from"@picketapi/picket-react";functionMyApp({ children }) {return ( <PicketProviderapiKey="YOUR_PUBLISHABLE_KEY_HERE"> {children} </PicketProvider> );}// These requirements are for the Solana Mainnet Betaconstrequirements= { chain:"solana",// Replace this with a verified creatorAddress for your SPL tokens// If you created the tokens, it will often be your wallet address creatorAddress:"GcRZfnNriUPJwiE5AvF71R9f5ujGhYiYx7YNeq8wizzt",// Replace with minimum balance you want to verify users' currently hold across all token IDs, // or omit if any number of tokens is sufficient minTokenBalance:1}functionMySecurePage() {const { isAuthenticating,isAuthenticated,authState,logout,login } =usePicket();// user is logging inif (isAuthenticating) return"Loading";// user is not logged inif (!isAuthenticated) {return ( <div> <p>You are not logged in!</p> <buttononClick={() =>login(requirements)}>Login with Wallet</button> </div> ) }// user is logged in ๐const { user } = authState;const { walletAddress } = user;return ( <div> <p>You are logged in as {walletAddress} </p> <buttononClick={() =>logout()}>Logout</button> </div> )}
Solana is moving towards the Metaplex Collection Standard. Collections will make referencing a set of SPL tokens as it is on Ethereum. Unfortunately, at the time of writing this the adoption is low, especially for the earlier Solana NFT projects. If you are the creator of the SPL tokens, you can follow the instructions below to create a collection for your SPL tokens.
Getting the Collection ID
If the collection ID exists, then you can find it in the token metadata on Solscan under the collection key
import Picket from"@picketapi/picket-js";constpicket=newPicket('YOUR_PUBLISHABLE_KEY_HERE');// These requirements are for the Solana Mainnet Betaconstrequirements= { chain:"solana",// Replace this with your Metaplex Certified Collection ID collection:"GuPE3LLFtTfWB4BJ6hLbtWHS5gifjZWVduC9AyaPPEWh",// Replace with minimum balance you want to verify users' currently hold across all token IDs, // or omit if any number of tokens is sufficient minTokenBalance:1}const { accessToken,user } =awaitpicket.login(requirements);console.log(user);
import { PicketProvider, usePicket } from"@picketapi/picket-react";functionMyApp({ children }) {return ( <PicketProviderapiKey="YOUR_PUBLISHABLE_KEY_HERE"> {children} </PicketProvider> );}// These requirements are for the Solana Mainnet Betaconstrequirements= { chain:"solana",// Replace this with your Metaplex Certified Collection ID collection:"GuPE3LLFtTfWB4BJ6hLbtWHS5gifjZWVduC9AyaPPEWh",// Replace with minimum balance you want to verify users' currently hold across all token IDs, // or omit if any number of tokens is sufficient minTokenBalance:1}functionMySecurePage() {const { isAuthenticating,isAuthenticated,authState,logout,login } =usePicket();// user is logging inif (isAuthenticating) return"Loading";// user is not logged inif (!isAuthenticated) {return ( <div> <p>You are not logged in!</p> <buttononClick={() =>login(requirements)}>Login with Wallet</button> </div> ) }// user is logged in ๐const { user } = authState;const { walletAddress } = user;return ( <div> <p>You are logged in as {walletAddress} </p> <buttononClick={() =>logout()}>Logout</button> </div> )}
You successfully validated a user's wallet and token ownership!
The returned access token can now act as secure proof of token ownership until expiration. It can be passed server side and verified there in order to restrict resources to authenticated wallets with whichever token ownership requirements you have.
Using Access Tokens
Congrats ๐ your user is now successfully logged in. After authenticated/authorizing a user, you get an access token. You can use this access token to make secure requests to your backend. Read more in the working with access tokens guide.