Server side library for accessing picket endpoints.
Installation
npminstall"@picketapi/picket-node"
Usage - Quick Start
The Picket constructor creates a new instance of the Picket class. It takes a secret API key as a parameter.
import Picket from"@picketapi/picket-node";// Use your secret key when making calls from secure serverconstpicket=newPicket("YOUR_SECRET_KEY_HERE");
Weโve placed a placeholder secret API key in this example. Replace it with your actual api keys.
Nonce
A nonce is random value generated by the Picket API to that user must sign to prove ownership a wallet address. The nonce function can be used to implement your own wallet authentication flow.
A nonce is unique to a project and wallet address. If a nonce doesn't exist for the project and wallet address, Picket will generate a new nonce; otherwise, Picket will return the existing nonce. A nonce is valid for two minutes before self-destructing.
nonce takes in an optional locale parameter, which is used to localize the signing message statement in to the given locale . When using the login function from picket-js or picket-react , the user's browser locale will automatically be passed as the locale for the signing message statement.
awaitpicket.auth({// optionally omit, the default chain is Ethereum walletAddress:"0x_WALLET_ADDRESS", signature:"SIGNATURE"});// or specifiy it explicitlyawaitpicket.auth({ chain:"ethereum", walletAddress:"0x_WALLET_ADDRESS", signature:"SIGNATURE"});
For more information on Token Gating, read the Ethereum or Solana Token Gating Getting Started Guide
awaitpicket.auth({// any supported EVM-compatible chain// if omitted, defaults to "ethereum" chain:"ethereum", walletAddress:"0x_WALLET_ADDRESS", signature:"SIGNATURE", requirements: {// restrict access to token holders contractAddress:"0xCONTRACT_ADDRESS",// omit if any number of tokens are acceptable minTokenBalance:1 }});
awaitpicket.auth({ chain:"solana", walletAddress:"0x_WALLET_ADDRESS", signature:"SIGNATURE", requirements: {// 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 },});
authz stands for authorization. Unlike Auth, which handles both authentication and authorization, Authz only handles authorization. Given an authenticated user's access token and authorization requirements, authz will issue a new access token on success (user is authorized) or, on failure, it will return a 4xx HTTP error code.
awaitpicket.authz({// chain and wallet is stored within the access token accessToken:"xxx.yyy.zzz", requirements: {// check ownership of a specific contract address contractAddress:"0xCONTRACT_ADDRESS",// omit if any number of tokens are acceptable minTokenBalance:1 }});
awaitpicket.authz({// chain and wallet is stored within the access token accessToken:"xxx.yyy.zzz", requirements: {// check ownership of a specific Metaplex Collection collection:"96d973e49267f6bf5b9d68c577fc04ce93757e2c5ae8c086ef6115b3aeee300c",// omit if any number of tokens are acceptable minTokenBalance:1 }});
Verify Token Ownership
If you only want to verify token ownership server side for a given wallet, tokenOwnership allows you to do just that.
import Picket from"@picketapi/picket-node"constpicket=newPicket('YOUR_SECRET_KEY_HERE')constrequirements= {// any supported EVM-compatible chain// if omitted, defaults to "ethereum" chain:"ethereum", walletAddress:"WALLET_ADDRESS",// Replace this example address with whichever contract you are verifying ownership for contractAddress:'0x8a90cab2b38dba80c64b7734e58ee1db38b8992e',// Replace with minimum balance you want to verify users' currently hold. minTokenBalance:1}const { allowed,contractAddress,numTokens } =awaitpicket.tokenOwnership(requirements)console.log(`Allowed == ${allowed} because ${request.walletAddress} has ${numTokens} for ${contractAddress}.`)
import Picket from"@picketapi/picket-node"constpicket=newPicket('YOUR_SECRET_KEY_HERE')constrequirements= { chain:"solana", walletAddress:"WALLET_ADDRESS",// 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 { allowed,contractAddress,numTokens } =awaitpicket.tokenOwnership(requirements)console.log(`Allowed == ${allowed} because ${requirements.walletAddress} has ${numTokens} for ${contractAddress}.`)Validate
Validate
validatevalidates an access token. validate should be called, or manually access token validation should be done, server-side before trusting a request's access token. It's common to move access token validation and decoding logic to a shared middleware across API endpoints.
If the access token is valid, validate returns the decoded claims of the access token.