Get DAO Treasury Info

Fetch all DAO treasury wallets and their holdings.

Given a DAO, we need to fetch its treasury info. In order to do this, we need the DAO's realm address. -

  • Once we have the realm address, we will fetch all the governance accounts for it.

  • Treasury wallets are a PDA(program derived address) of governance pubkeys and 'native-treasury' text. Code snippet in the below section.

  • Once we have the treasury wallets, we use Get Portfolio to fetch Sol, Token balances and NFTs in a single call. You can usr any other approach you want.

Here's a fully working code snippet for you to try out in replit.

Fetch Treasury Info For Grape Dao

// Node doesn't implement fetch so we have to import it
import fetch from "node-fetch";
import { PublicKey } from "@solana/web3.js";
import { promises } from "dns";

const SHYFT_API_KEY = "YOUR-KEY"

async function fetchGraphQL(query, variables = {}, name = "MyQuery") {
  const result = await fetch(
    `https://programs.shyft.to/v0/graphql/?api_key=${SHYFT_API_KEY}`,
    {
      method: "POST",
      body: JSON.stringify({
        query: query,
        variables: variables,
        operationName: name
      })
    }
  );

  return await result.json();
}

async function getGovernanceAccountsForDAO(realmAddress) {

  //realms should be an array
  const query = `
  query MyQuery($_in: [String!] = "") {
  GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV1(
    where: {realm: {_eq: ${JSON.stringify(realmAddress)}}}
  ) {
    pubkey
  }
  GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2(
    where: {realm: {_eq: ${JSON.stringify(realmAddress)}}}
  ) {
    pubkey
  }
}
`
  const { errors, data } = await fetchGraphQL(query);

  if (errors) {
    // handle those errors like a pro
    console.error(errors);
  }

  const govAccts = []
  data.GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV1.forEach((dao) => {
      govAccts.push(dao?.pubkey)
  })

  data.GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw_GovernanceV2.forEach((dao) => {
      govAccts.push(dao?.pubkey)
  })

  console.log(govAccts);

  return govAccts;
}

function getNativeTreasuryAddress(governanceAccounts) {
  const programId = new PublicKey("GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw")
  const treasuryAddress = []
  
  governanceAccounts.forEach(async (governance) => {
    const acc = new PublicKey(governance)
    const [address] = await PublicKey.findProgramAddress(
    [Buffer.from('native-treasury'), acc.toBuffer()],
    programId
  );
    const addy = address.toBase58()
    console.log(addy)
    treasuryAddress.push(address.toBase58());
  })

  return treasuryAddress;
}

async function fetchTreasuryInfo(wallets) {
  console.time('portfolio')
  const promises = []
  //Once we have the treasury wallets, we can fetch their holdings
  wallets.map(async (wallet) => {
    promises.push(getPortfolio(wallet))
  })
  
  return await Promise.all(promises);
}

async function getPortfolio(wallet) {
  try {
    console.log('fetching portfolio for ', wallet)
    const result = await fetch(
      `https://api.shyft.to/sol/v1/wallet/get_portfolio?network=mainnet-beta&wallet=${wallet}`,
      {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          "x-api-key": SHYFT_API_KEY
        },
      }
    );
    const res = await result.json()

    return res;
    
  } catch (err) {
    console.error(err)
  }
}

async function getDaoTreasury(realmAddress) {
  
  //Get governance accounts for all realms
  const governanceAccounts = await   getGovernanceAccountsForDAO(realmAddress);

  console.log('gov accounts fetched');
  const treasuryWallets = await getNativeTreasuryAddress(governanceAccounts);
  
  console.log('treasury wallets: ', treasuryWallets);
  
  return await fetchTreasuryInfo(treasuryWallets);
}

//Grape DAO treasury
const treasury = await getDaoTreasury("By2sVGZXwfQq6rAiAM3rNPJ9iQfb5e2QhnF4YjJ4Bip");
console.dir(treasury, {depth: null})

Last updated