Picket Docs
  • ๐Ÿ‘‹Welcome to Picket
  • Quick Start Guides
    • ๐Ÿš€Quick Start Guides
      • โš™๏ธStart Here: Setup
      • ๐Ÿ”Wallet Login
      • ๐Ÿช™Token Gating (Ethereum / EVM)
      • ๐ŸคบToken Gating (Solana)
      • ๐Ÿคนโ€โ™‚๏ธIncremental Token Gating
      • โ›”Restrict Access to Specific Wallets
      • ๐Ÿ”‘Working with Access Tokens
  • Reference
    • ๐ŸŽ“Concepts
      • ๐ŸŒŠAuth Flow
      • ๐Ÿ—ƒ๏ธConnect
      • โœ๏ธSignatures
      • ๐Ÿ”Authentication and Authorization
      • ๐ŸคนIncremental Authorization
      • ๐Ÿช™Access Tokens
      • ๐ŸงชTesting
      • โ‰๏ธErrors
      • โ›“๏ธSupported Blockchains
      • ๐ŸŒSupported Languages (Localization)
      • ๐ŸŽจModal Themes
      • ๐Ÿ’ฟOpen Source Web3 Client Libraries
    • ๐Ÿ“šLibraries and SDKs
      • Javascript Library - picket-js
      • React SDK - picket-react
      • Node.js Library - picket-node
      • Go Library - picket-go
      • Python Library - picket-python
    • ๐Ÿ”ฅIntegrations
      • ๐ŸŒˆPicket Authentication with RainbowKit
      • โšกSupabase
      • โ˜๏ธAmazon Cognito
      • ๐Ÿ›๏ธPicket Shopify App - Merchant Documentation
      • ๐Ÿ›’Picket BigCommerce App - Merchant Documentation
    • ๐Ÿ“–API Reference
      • Projects & API Keys
      • Auth
      • Chains
      • Wallets
      • Contracts
      • OAuth 2.0
  • ๐Ÿ•น๏ธTutorials
    • ๐ŸŒŽSign-In with Wallet (React)
    • ๐ŸฐToken Gated Photo Board (React)
    • ๐Ÿ”—Link a Wallet to a Web 2.0 Account
    • ๐ŸคIncremental Authorization (React)
Powered by GitBook
On this page
  • Requirements
  • Token Gate Anything
  • Login User w/ Token Ownership Requirements
  • Using Access Tokens
  1. Quick Start Guides
  2. Quick Start Guides

Token Gating (Solana)

A guide to start token gating anything in minutes.

PreviousToken Gating (Ethereum / EVM)NextIncremental Token Gating

Last updated 2 years ago

Requirements

Before continuing make sure you've followed the

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 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:

  • Token IDs (Addresses)

  • Verified Creator Address

Token Gate on Specific Token IDs

If there are a small number of tokens that you want to token gate based off, you can simply list them out on the the login requirements.

Getting the Token ID

An easy way to get the token ID for a given token is from Solscan. Either

  • Copy it from the URL of the token

  • Copy it from the "Token Address" in the Profile Summary on Solscan.

For example, the token ID for is 2dQG4YYunFrbJjzW6UTcUmePs8UDy5jz43H6uSCZSAcS

import Picket from "@picketapi/picket-js";

const picket = new Picket('YOUR_PUBLISHABLE_KEY_HERE');

// These requirements are for the Solana Mainnet Beta
const requirements = {
    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 } = await picket.login(requirements);
console.log(user);
import { PicketProvider, usePicket } from "@picketapi/picket-react";

function MyApp({ children }) {
  return (
    <PicketProvider apiKey="YOUR_PUBLISHABLE_KEY_HERE">
      {children}
    </PicketProvider>
  );
}

// These requirements are for the Solana Mainnet Beta
const requirements = {
    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 
}

function MySecurePage() {
  const { 
          isAuthenticating, 
          isAuthenticated, 
          authState, 
          logout,
          login
          } = usePicket();
  
  // user is logging in
  if (isAuthenticating) return "Loading";

  // user is not logged in
  if (!isAuthenticated) {
      return (
        <div>
            <p>You are not logged in!</p>
            <button onClick={() => 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>
       <button onClick={() => logout()}>Logout</button>
    </div>
  )
}
curl https://picketapi.com/api/v1/auth \
    -X POST \
    -u PROJECT_SECRET_KEY \
    -H 'Content-Type: application/json' \
    -d '{
      "chain": "solana",
      "walletAddress": "0xWALLET_ADDRESS",
      "signature": "SUPER_SECRET_SIGNATURE",
      "tokenIds": "['78AZe2223PknLYT9mn2VCJPAsdvuB6LzFAhgQeVoxddW', '2dQG4YYunFrbJjzW6UTcUmePs8UDy5jz43H6uSCZSAcS']",
      "minTokenBalance": 1
    }'

Token Gate on a Verified Creator Address

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.

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";

const picket = new Picket('YOUR_PUBLISHABLE_KEY_HERE');

// These requirements are for the Solana Mainnet Beta
const requirements = {
    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 } = await picket.login(requirements);
console.log(user);
import { PicketProvider, usePicket } from "@picketapi/picket-react";

function MyApp({ children }) {
  return (
    <PicketProvider apiKey="YOUR_PUBLISHABLE_KEY_HERE">
      {children}
    </PicketProvider>
  );
}

// These requirements are for the Solana Mainnet Beta
const requirements = {
    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
}

function MySecurePage() {
  const { 
          isAuthenticating, 
          isAuthenticated, 
          authState, 
          logout,
          login
          } = usePicket();
  
  // user is logging in
  if (isAuthenticating) return "Loading";

  // user is not logged in
  if (!isAuthenticated) {
      return (
        <div>
            <p>You are not logged in!</p>
            <button onClick={() => 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>
       <button onClick={() => logout()}>Logout</button>
    </div>
  )
}
curl https://picketapi.com/api/v1/auth \
    -X POST \
    -u PROJECT_SECRET_KEY \
    -H 'Content-Type: application/json' \
    -d '{
      "chain": "solana",
      "walletAddress": "walLeTtAdDResS",
      "signature": "SUPER_SECRET_SIGNATURE",
      "creatorAddress": "GcRZfnNriUPJwiE5AvF71R9f5ujGhYiYx7YNeq8wizzt",
      "minTokenBalance": 1
    }'

Token Gate on a Collection ID

Getting the Collection ID

Create a Collection ID

import Picket from "@picketapi/picket-js";

const picket = new Picket('YOUR_PUBLISHABLE_KEY_HERE');

// These requirements are for the Solana Mainnet Beta
const requirements = {
    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 } = await picket.login(requirements);
console.log(user);
import { PicketProvider, usePicket } from "@picketapi/picket-react";

function MyApp({ children }) {
  return (
    <PicketProvider apiKey="YOUR_PUBLISHABLE_KEY_HERE">
      {children}
    </PicketProvider>
  );
}


// These requirements are for the Solana Mainnet Beta
const requirements = {
    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 
}

function MySecurePage() {
  const { 
          isAuthenticating, 
          isAuthenticated, 
          authState, 
          logout,
          login
          } = usePicket();
  
  // user is logging in
  if (isAuthenticating) return "Loading";

  // user is not logged in
  if (!isAuthenticated) {
      return (
        <div>
            <p>You are not logged in!</p>
            <button onClick={() => 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>
       <button onClick={() => logout()}>Logout</button>
    </div>
  )
}
curl https://picketapi.com/api/v1/auth \
    -X POST \
    -u PROJECT_SECRET_KEY \
    -H 'Content-Type: application/json' \
    -d '{
      "chain": "solana",
      "walletAddress": "wAllEtadDrEss",
      "signature": "SUPER_SECRET_SIGNATURE",
      "collection": "GuPE3LLFtTfWB4BJ6hLbtWHS5gifjZWVduC9AyaPPEWh",
      "minTokenBalance": 1
    }'

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

Otherwise, if creators exists for the tokens, then you can find it in the under the creators key. Pick one verified creator address to use.

Solana is moving towards the . 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.

If the collection ID exists, then you can find it in the under the collection key

If you are the creator of the SPL tokens, you can use to create a collection ID for your 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 .

๐Ÿš€
๐Ÿคบ
setup guide
โš™๏ธStart Here: Setup
Metaplex
Certified Collection ID
https://solscan.io/token/2dQG4YYunFrbJjzW6UTcUmePs8UDy5jz43H6uSCZSAcS
token metadata on Solscan
Metaplex Collection Standard
token metadata on Solscan
https://collections.metaplex.com/
working with access tokens guide
๐Ÿ”‘Working with Access Tokens