Overview
The Seeker Genesis Token is a unique NFT that represents a verified owner of a Seeker device. It can only be minted once per device and is minted into the primary account in a user’s Seed Vault Wallet.
NFT Details
The Seeker Genesis Token implements Token Extensions (formerly Token-2022).
Transferability
The Seeker Genesis Token can only be transferred between a user’s wallet accounts on a permissioned basis within the Seed Vault Wallet.
A transfer occurs when a user changes their primary account in the Seed Vault Wallet.
The mint address of the SGT remains the same when it is transferred.
Anti-Sybil Example: In-App Rewards Claim
Even with transferability, the Seeker Genesis Token is still useful as an anti-sybil measure.
As an example, imagine an in-app rewards claim that wants to use the Seeker Genesis Token to limit the claim to once per Seeker device.
To implement this, the app should check for 3 properties:
The connected wallet owns a Seeker Genesis Token.
The user proves ownership of the wallet via signing a message .
The Seeker Genesis Token has not been previously used to claim a reward (i.e check that its mint address has not been seen before).
Step 3 is crucial to exclude wallets that have previously claimed the reward on another wallet (and then transferred the SGT to a new wallet).
Token Extensions
Seeker Genesis Token implements several extensions, notably:
Metadata Pointer
Token Group Member and Pointer
Key Addresses
Mint Authority : GT2zuHVaZQYZSyQMgJPLzvkmyztfyXg2NJunqFp4p3A4
Metadata Address : GT22s89nU4iWFkNXj1Bw6uYhJJWDRPpShHt4Bk8f99Te
Group Address : GT22s89nU4iWFkNXj1Bw6uYhJJWDRPpShHt4Bk8f99Te
View on an Explorer
Verifying Seeker Genesis Token Ownership
To verify a wallet owns a Seeker Genesis Token, you can use the getTokenAccountsByOwnerV2 API call provided by Helius.
Here’s an example script:
const { Connection , PublicKey } = require ( '@solana/web3.js' );
const { unpackMint , getMetadataPointerState , getTokenGroupMemberState , TOKEN_2022_PROGRAM_ID } = require ( '@solana/spl-token' );
async function checkWalletForSGT ( walletAddress ) {
const HELIUS_RPC_URL = `https://mainnet.helius-rpc.com/?api-key= ${ HELIUS_API_KEY } ` ;
const SGT_MINT_AUTHORITY = 'GT2zuHVaZQYZSyQMgJPLzvkmyztfyXg2NJunqFp4p3A4' ;
// The metadata mint and group mint address are intentionally the same.
const SGT_METADATA_ADDRESS = 'GT22s89nU4iWFkNXj1Bw6uYhJJWDRPpShHt4Bk8f99Te' ;
const SGT_GROUP_MINT_ADDRESS = 'GT22s89nU4iWFkNXj1Bw6uYhJJWDRPpShHt4Bk8f99Te' ;
try {
const connection = new Connection ( HELIUS_RPC_URL );
// Use getTokenAccountsByOwnerV2 with pagination
let allTokenAccounts = [];
let paginationKey = null ;
let pageCount = 0 ;
console . log ( `Starting paginated fetch for wallet: ${ walletAddress } ` );
do {
pageCount ++ ;
console . log ( `Fetching page ${ pageCount } ...` );
const requestPayload = {
jsonrpc: '2.0' ,
id: `page- ${ pageCount } ` ,
method: 'getTokenAccountsByOwnerV2' ,
params: [
walletAddress ,
{ "programId" : "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" }, // Token-2022 program
{
encoding: 'jsonParsed' ,
limit: 1000 , // Maximum accounts per request
... ( paginationKey && { paginationKey })
}
]
};
const response = await fetch ( HELIUS_RPC_URL , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( requestPayload )
});
if ( ! response . ok ) {
throw new Error ( `HTTP error! status: ${ response . status } ` );
}
const data = await response . json ();
if ( data . error ) {
throw new Error ( `RPC error: ${ data . error . message } ` );
}
const pageResults = data . result ?. value . accounts || [];
console . log ( `Page ${ pageCount } : Found ${ pageResults . length } token accounts` );
if ( pageResults . length > 0 ) {
allTokenAccounts . push ( ... pageResults );
}
paginationKey = data . result ?. paginationKey ;
// Log pagination info
if ( data . result . totalResults ) {
console . log ( `Total results available: ${ data . result . totalResults } ` );
}
} while ( paginationKey ); // Continue until no more pages
console . log ( ` \n Completed pagination: ${ pageCount } pages, ${ allTokenAccounts . length } total token accounts` );
if ( allTokenAccounts . length === 0 ) {
console . log ( "No Token-2022 accounts found for this wallet." );
return false ;
}
// Extract mint addresses from token accounts
const mintPubkeys = allTokenAccounts
. map (( accountInfo ) => {
try {
if ( accountInfo ?. account ?. data ?. parsed ?. info ?. mint ) {
return new PublicKey ( accountInfo . account . data . parsed . info . mint );
} else {
console . log ( 'No mint found for account:' , accountInfo );
return null ;
}
} catch ( error ) {
return null ;
}
})
. filter (( mintPubkey ) => mintPubkey !== null );
console . log ( `Extracted ${ mintPubkeys . length } mint addresses` );
// Fetch all mint account data in batches of 100 to avoid RPC limits
const BATCH_SIZE = 100 ;
const mintAccountInfos = [];
for ( let i = 0 ; i < mintPubkeys . length ; i += BATCH_SIZE ) {
const batch = mintPubkeys . slice ( i , i + BATCH_SIZE );
console . log ( `Fetching mint info batch ${ Math . floor ( i / BATCH_SIZE ) + 1 } / ${ Math . ceil ( mintPubkeys . length / BATCH_SIZE ) } ` );
const batchResults = await connection . getMultipleAccountsInfo ( batch );
mintAccountInfos . push ( ... batchResults );
}
// Check each mint for SGT verification
console . log ( `Checking ${ mintAccountInfos . length } mints for SGT verification...` );
for ( let i = 0 ; i < mintAccountInfos . length ; i ++ ) {
const mintInfo = mintAccountInfos [ i ];
if ( mintInfo ) {
const mintPubkey = mintPubkeys [ i ];
try {
// Unpack the raw mint account data
const mint = unpackMint ( mintPubkey , mintInfo , TOKEN_2022_PROGRAM_ID );
const mintAuthority = mint . mintAuthority ?. toBase58 ();
const hasCorrectMintAuthority = mintAuthority === SGT_MINT_AUTHORITY ;
// Check for correct SGT Metadata
const metadataPointer = getMetadataPointerState ( mint );
const hasCorrectMetadata = metadataPointer &&
metadataPointer . authority ?. toBase58 () === SGT_MINT_AUTHORITY &&
metadataPointer . metadataAddress ?. toBase58 () === SGT_METADATA_ADDRESS ;
// Check for correct SGT Group Member
const tokenGroupMemberState = getTokenGroupMemberState ( mint );
const hasCorrectGroupMember = tokenGroupMemberState &&
tokenGroupMemberState . group ?. toBase58 () === SGT_GROUP_MINT_ADDRESS ;
// If all extensions match and mint authority is correct, then it is an SGT
if ( hasCorrectMintAuthority && hasCorrectMetadata && hasCorrectGroupMember ) {
console . log ( ` \n VERIFIED SGT FOUND: Wallet holds a verified SGT ( ${ mint . address . toBase58 () } ).` );
return true ;
}
} catch ( mintError ) {
// Skip this mint if we can't unpack it
console . log ( `Warning: Could not unpack mint ${ mintPubkey . toBase58 () } : ${ mintError . message } ` );
continue ;
}
}
}
// No verified SGT found in wallet
console . log ( " \n No verified SGT found in wallet." );
return false ;
} catch ( error ) {
console . error ( "Error verifying SGT ownership:" , error . message );
return false ;
}
}
See all 157 lines
Last modified on February 19, 2026