1+ const { PublicKey } = require ( "@solana/web3.js" ) ;
2+ const { getConnection, sumTokens2 } = require ( "../helper/solana" ) ;
3+
4+ const PROGRAM_ID = "gLHaGJsZ6G7AXZxoDL9EsSWkRbKAWhFHi73gVfNXuzK" ;
5+ const TOKEN_2022_PROGRAM = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" ;
6+
7+ // SPT token mint - your native token
8+ const SPT_MINT = "6uUU2z5GBasaxnkcqiQVHa2SXL68mAXDsq1zYN5Qxrm7" ;
9+
10+ const TOKEN_MINT_OFFSET = 40 ;
11+ const STAKING_VAULT_OFFSET = 80 ;
12+
13+ async function getVaultData ( ) {
14+ const connection = getConnection ( ) ;
15+
16+ const accounts = await connection . getProgramAccounts (
17+ new PublicKey ( PROGRAM_ID ) ,
18+ {
19+ filters : [
20+ { dataSize : 379 }
21+ ]
22+ }
23+ ) ;
24+
25+ const sptVaults = { spl : [ ] , token2022 : [ ] } ;
26+ const otherVaults = { spl : [ ] , token2022 : [ ] } ;
27+
28+ for ( const { account } of accounts ) {
29+ const data = account . data ;
30+ const tokenMint = new PublicKey ( data . slice ( TOKEN_MINT_OFFSET , TOKEN_MINT_OFFSET + 32 ) ) ;
31+ const stakingVault = new PublicKey ( data . slice ( STAKING_VAULT_OFFSET , STAKING_VAULT_OFFSET + 32 ) ) ;
32+
33+ const isSPT = tokenMint . toString ( ) === SPT_MINT ;
34+ const targetVaults = isSPT ? sptVaults : otherVaults ;
35+
36+ const vaultInfo = await connection . getAccountInfo ( stakingVault ) ;
37+ if ( vaultInfo && vaultInfo . owner . toString ( ) === TOKEN_2022_PROGRAM ) {
38+ targetVaults . token2022 . push ( {
39+ mint : tokenMint . toString ( ) ,
40+ balance : Number ( vaultInfo . data . readBigUInt64LE ( 64 ) )
41+ } ) ;
42+ } else {
43+ targetVaults . spl . push ( stakingVault . toString ( ) ) ;
44+ }
45+ }
46+
47+ return { sptVaults, otherVaults } ;
48+ }
49+
50+ async function buildBalances ( vaults ) {
51+ const balances = await sumTokens2 ( { tokenAccounts : vaults . spl } ) ;
52+
53+ for ( const { mint, balance } of vaults . token2022 ) {
54+ const mintKey = `solana:${ mint } ` ;
55+ if ( ! balances [ mintKey ] ) balances [ mintKey ] = 0 ;
56+ balances [ mintKey ] += balance ;
57+ }
58+
59+ return balances ;
60+ }
61+
62+ async function staking ( ) {
63+ const { sptVaults } = await getVaultData ( ) ;
64+ return buildBalances ( sptVaults ) ;
65+ }
66+
67+ async function tvl ( ) {
68+ const { otherVaults } = await getVaultData ( ) ;
69+ return buildBalances ( otherVaults ) ;
70+ }
71+
72+ module . exports = {
73+ timetravel : false ,
74+ solana : {
75+ tvl,
76+ staking
77+ } ,
78+ methodology : "TVL includes external tokens (USDC, SOL, etc.) in staking vaults. Staking represents SPT tokens locked in the protocol."
79+ } ;
0 commit comments