Skip to main content

Overview

The following guide introduces how to work with peaq’s developer tooling to access live onchain data, interact with machine accounts, and build production-ready applications without managing your own indexing or infrastructure. It is achieved through Sim by Dune. To understand more please refer to the Sim By Dune Documentation.

What you’ll learn

This guide walks through the core building blocks required to develop on peaq:
  • Getting Started
Set up your development environment, confiugure API access, and connect to the peaq network.
  • Core data interfaces
Learn how to query balances, transactions, and asset metadata

Quick Start

1. Get API Key

You will need an API from the Sim dashboard to get started.
  1. Go to the Sim dashboard
  2. Click on your username in the top right corner (or create an account)
  3. Click on Keys
  4. Click on New
  5. Enter a name for your API Key
  6. Click on Create Key
  7. Copy the API Key
Save the API Key in a secure location and never share in public repositories or in your code. You will need it to access the Sim API.

2. Set up your development environment

You will need to set up your development environment to get started. We will be using JavaScript to interact with the Sim API. Open a new terminal and run the following command to create a new project:
npm init -y
npm pkg set type=module
npm install axios dotenv
Create .env file:
API_KEY=your_sim_api_key_here
WALLET_ADDRESS=0x...your_test_address
CHAIN_ID=3338

3. API Call

Create a new file called sim.js and add the following code:
import 'dotenv/config';
import axios from 'axios';
 
const SIM_API_BASE = 'https://api.sim.dune.com/v1';

const headers = {
  'X-Sim-Api-Key': process.env.API_KEY,
  'Content-Type': 'application/json'
};
 
async function getPeaqBalances() {
  try {
    console.log('Fetching peaq balances...');
    console.log(`Using wallet address: ${process.env.WALLET_ADDRESS}`);

    const response = await axios.get(`${SIM_API_BASE}/evm/balances/${process.env.WALLET_ADDRESS}?chain_ids=${process.env.CHAIN_ID}`, { headers });

    const peaqBalances = response.data.balances.filter((balance) => balance.chain === 'peaq');

    console.log('peaq Balances:');
    peaqBalances.forEach((balance) => {
      console.log(`  ${balance.symbol}: ${balance.amount / 10 ** balance.decimals} (${balance.value_usd} USD)`);
    });
  } catch (error) {
    console.error('❌ Error fetching balances:', error.response?.data || error.message);
  }
}

getPeaqBalances();
Execute with:
node sim.js

Additional API Examples

Get Token Balances

async function getPeaqBalances() {
  try {
    console.log('Fetching peaq balances...');
    console.log(`Using wallet address: ${process.env.WALLET_ADDRESS}`);

    const response = await axios.get(`${SIM_API_BASE}/evm/balances/${process.env.WALLET_ADDRESS}?chain_ids=${process.env.CHAIN_ID}`, { headers });

    const peaqBalances = response.data.balances.filter((balance) => balance.chain === 'peaq');

    console.log('peaq Balances:');
    peaqBalances.forEach((balance) => {
      console.log(`  ${balance.symbol}: ${balance.amount / 10 ** balance.decimals} (${balance.value_usd} USD)`);
    });
  } catch (error) {
    console.error('❌ Error fetching balances:', error.response?.data || error.message);
  }
}

Monitor Wallet Transactions

async function monitorPeaqTransactions() {
  try {
    console.log(`Monitoring transactions for ${process.env.WALLET_ADDRESS}...`);
 
    const response = await axios.get(`${SIM_API_BASE}/evm/transactions/${process.env.WALLET_ADDRESS}`, {
      headers,
      params: {
        chain: 'peaq',
        limit: 10
      }
    });
 
    const transactions = response.data.transactions;
 
    console.log('🔄 Recent Transactions:');
    transactions.forEach((tx) => {
      console.log(`  Hash: ${tx.hash}`);
      console.log(`  From: ${tx.from} → To: ${tx.to}`);
      console.log(`  Value: ${tx.value} PEAQ`);
      console.log(`  Gas Used: ${tx.gas_used}`);
      console.log(`  Status: ${tx.success}`);
      console.log('  ---');
    });
  } catch (error) {
    console.error('❌ Error monitoring transactions:', error.message);
  }
}

Get Token Metadata

async function getTokenInfo(tokenAddress) {
  try {
    console.log('Fetching token information...');
 
    const response = await axios.get(`${SIM_API_BASE}/evm/token-info/${tokenAddress}?chain_ids=${process.env.CHAIN_ID}`, { headers });
    const tokenInfo = response.data.tokens[0];
 
    console.log('Token Information:');
    console.log(`  Name: ${tokenInfo.name}`);
    console.log(`  Symbol: ${tokenInfo.symbol}`);
    console.log(`  Decimals: ${tokenInfo.decimals}`);
    console.log(`  Total Supply: ${tokenInfo.total_supply}`);
    console.log(`  Current Price: ${tokenInfo.price_usd}`);
    console.log(`  Logo: ${tokenInfo.logo}`);
 
    return tokenInfo;
  } catch (error) {
    console.error('❌ Error fetching token info:', error.message);
  }
}
 
// Example usage with USDC address
getTokenInfo('0xbba60da06c2c5424f03f7434542280fcad453d10');
Can see exhaustive list of token addresses on peaq’s token list

Find Top Holders

async function getTokenHolders(tokenAddress, limit = 10) {
  try {
    console.log('Fetching token holders...');
 
    const response = await axios.get(`${SIM_API_BASE}/evm/token-holders/${process.env.CHAIN_ID}/${tokenAddress}`, {
      headers,
      params: { limit }
    });
 
    const holders = response.data.holders;
    console.log(`Top ${holders.length} holders:`);
    holders.forEach((holder, index) => {
      console.log(`${index + 1}. ${holder.wallet_address}`);
      console.log(`   Balance: ${parseFloat(holder.balance)}`); // Make sure to parse if you want human readable format
      console.log(`   First Acquired: ${holder.first_acquired}`);
      console.log('   ---');
    });
 
    return holders;
  } catch (error) {
    console.error('❌ Error fetching token holders:', error.message);
  }
}

Track Swaps and Transfers

async function getWalletActivity(walletAddress, limit = 10) {
  try {
    console.log('Fetching wallet activity on peaq...');
 
    const response = await axios.get(`${SIM_API_BASE}/evm/activity/${walletAddress}?chain_ids=${process.env.CHAIN_ID}`, {
      headers,
      params: { limit }
    });
 
    const activities = response.data.activity;
 
    console.log(`Recent activities (${activities.length}):`);
    activities.forEach((activity, index) => {
      console.log(`${index + 1}. Type: ${activity.type.toUpperCase()}`);
      console.log(`   Hash: ${activity.tx_hash}`);
      console.log(`   Time: ${new Date(activity.block_time).toLocaleString()}`);
 
      if (activity.type === 'receive' && activity.asset_type === 'erc20') {
        console.log(`   Received: ${activity.value} ${activity.token_metadata?.symbol}`);
        console.log(`   From: ${activity.from}`);
      }
 
      console.log('   ---');
    });
 
    return activities;
  } catch (error) {
    console.error('❌ Error fetching activity:', error.message);
  }
}

Get NFT Collections

async function getNFTCollections(walletAddress) {
  try {
    console.log('Fetching NFT collections...');
 
    const response = await axios.get(`${SIM_API_BASE}/evm/collectibles/${walletAddress}?chain_ids=${process.env.CHAIN_ID}`, { headers });
 
    const collectibles = response.data.entries;
 
    console.log(`NFT Collections (${collectibles.length}):`);
 
    // Group by collection
    const collections = {};
    collectibles.forEach((nft) => {
      if (!collections[nft.contract_address]) {
        collections[nft.contract_address] = {
          name: nft.collection_name,
          items: []
        };
      }
      collections[nft.contract_address].items.push(nft);
    });
 
    Object.entries(collections).forEach(([address, collection]) => {
      console.log(`📚 ${collection.name} (${collection.items.length} items)`);
      console.log(`   Contract: ${address}`);
 
      collection.items.slice(0, 3).forEach((nft) => {
        console.log(`   • Token ID: ${nft.token_id}`);
        console.log(`     Name: ${nft.name || 'Unnamed'}`);
        console.log(`     Image: ${nft.image_url || 'No image'}`);
      });
 
      if (collection.items.length > 3) {
        console.log(`   ... and ${collection.items.length - 3} more`);
      }
      console.log('   ---');
    });
 
    return collectibles;
  } catch (error) {
    console.error('❌ Error fetching NFTs:', error.message);
  }
}

Advanced Operations

Portfolio Analytics

import 'dotenv/config';
import axios from 'axios';
 
const SIM_API_BASE = 'https://api.sim.dune.com/v1';

const headers = {
  'X-Sim-Api-Key': process.env.API_KEY,
  'Content-Type': 'application/json'
};
 
async function buildAdvancedPortfolio(walletAddress) {
  try {
    console.log('📊 Building advanced portfolio analytics...');
 
    // Get all data in parallel for better performance
    const [balancesRes, transactionsRes, activityRes, nftsRes] = await Promise.all([
      axios.get(`${SIM_API_BASE}/evm/balances/${walletAddress}?chain_ids=${process.env.CHAIN_ID}`, { headers }),
      axios.get(`${SIM_API_BASE}/evm/transactions/${walletAddress}`, {
        headers,
        params: { limit: 50, chain: 'peaq' }
      }),
      axios.get(`${SIM_API_BASE}/evm/activity/${walletAddress}?chain_ids=${process.env.CHAIN_ID}`, {
        headers,
        params: { limit: 50 }
      }),
      axios.get(`${SIM_API_BASE}/evm/collectibles/${walletAddress}?chain_ids=${process.env.CHAIN_ID}`, { headers })
    ]);
 
    const balances = balancesRes.data.balances;
    const transactions = transactionsRes.data.transactions;
    const activities = activityRes.data.activity;
    const nfts = nftsRes.data.entries;
 
    // Calculate comprehensive metrics
    const totalValue = balances.reduce((sum, asset) => sum + parseFloat(asset.value_usd || 0), 0);
    const peaqAssets = balances.filter((b) => b.chain === 'peaq');
    const peaqValue = peaqAssets.reduce((sum, asset) => sum + parseFloat(asset.value_usd || 0), 0);
 
    console.log('💼 Advanced Portfolio Analytics:');
    console.log(`  Total Portfolio Value: $${totalValue.toFixed(2)}`);
    console.log(`  PEAQ Network Value: $${peaqValue.toFixed(2)} (${((peaqValue / totalValue) * 100).toFixed(1)}%)`);
    console.log(`  Total Assets: ${balances.length} tokens`);
    console.log(`  NFT Collections: ${new Set(nfts.map((n) => n.contract_address)).size}`);
    console.log(`  Total NFTs: ${nfts.length}`);
 
    return { totalValue, peaqValue, balances, transactions, activities, nfts };
  } catch (error) {
    console.error('❌ Portfolio analytics error:', error.message);
  }
}
 
buildAdvancedPortfolio(process.env.WALLET_ADDRESS);

Token Analysis Tool:

import 'dotenv/config';
import axios from 'axios';
 
const SIM_API_BASE = 'https://api.sim.dune.com/v1';

const headers = {
  'X-Sim-Api-Key': process.env.API_KEY,
  'Content-Type': 'application/json'
};
 
async function analyzeToken(tokenAddress) {
  try {
    console.log(`Analyzing token: ${tokenAddress}`);
 
    // Get comprehensive token data
    const [infoRes, holdersRes] = await Promise.all([
      axios.get(`${SIM_API_BASE}/evm/token-info/${tokenAddress}?chain_ids=${process.env.CHAIN_ID}`, { headers }),
      axios.get(`${SIM_API_BASE}/evm/token-holders/${process.env.CHAIN_ID}/${tokenAddress}`, {
        headers,
        params: { limit: 100 }
      })
    ]);
 
    const tokenInfo = infoRes.data.tokens[0];
    const holders = holdersRes.data.holders;
 
    // Calculate holder distribution
    const totalSupply = parseFloat(tokenInfo.total_supply);
    const holderAnalysis = {
      whales: holders.filter((h) => parseFloat(h.balance) / totalSupply > 0.01).length, // >1%
      large: holders.filter((h) => {
        const pct = parseFloat(h.balance) / totalSupply;
        return pct > 0.001 && pct <= 0.01; // 0.1% - 1%
      }).length,
      medium: holders.filter((h) => {
        const pct = parseFloat(h.balance) / totalSupply;
        return pct > 0.0001 && pct <= 0.001; // 0.01% - 0.1%
      }).length
    };
 
    // Top holder concentration
    const top10Concentration = holders.slice(0, 10).reduce((sum, holder) => sum + parseFloat(holder.balance) / totalSupply, 0) * 100;
 
    console.log('📊 Token Analysis Results:');
    console.log(`  Name: ${tokenInfo.name} (${tokenInfo.symbol})`);
    console.log(`  Price: ${tokenInfo.price_usd}`);
    console.log(`  Total Supply: ${parseFloat(tokenInfo.total_supply).toLocaleString()}`);
    console.log(`  Total Holders: ${holders.length}`);
    console.log(`  Whales (>1%): ${holderAnalysis.whales}`);
    console.log(`  Large Holders (0.1-1%): ${holderAnalysis.large}`);
    console.log(`  Medium Holders (0.01-0.1%): ${holderAnalysis.medium}`);
    console.log(`  Top 10 Concentration: ${top10Concentration.toFixed(2)}%`);
 
    return { tokenInfo, holders, holderAnalysis };
  } catch (error) {
    console.error('❌ Token analysis failed:', error.message);
  }
}

analyzeToken('0xbba60da06c2c5424f03f7434542280fcad453d10'); // USDC address
Can see exhaustive list of token addresses on peaq’s token list

Conclusion

You now have a complete, working foundation for accessing peaq onchain data using Sim by Dune. This guide demonstrated how to:
  • Connect to the peaq network without running your own indexers
  • Query balances, transactions, token metadata, and NFT holdings
  • Track wallet and token activity at scale
  • Build higher-level analytics such as portfolio view and token distribution insights
These building blocks are sufficient for most production use cases, including dashboards, analytics services, DePIN backends, and automated agents.

Where to go next

From here, you can extend this setup in several directions:
  • Integrate machine identities - Combine onchain data with machine DIDs to build identity-aware applications.
  • Build persistent analytics - Store queried data in a database to support historical analysis, alerting, or reporting.
  • Add automation - Trigger workflows based on onchain activity, such as rewards distribution or machine state changes.
  • Harden for production - Implement caching, request batching, rate limiting, and monitoring to support higher throughput.
  • Explore the broader peaq stack - Pair Sim by Dune with peaq-native smart contracts, Machine Accounts, and DePIN primitives to build end-to-end systems.
For deeper architectural concepts and advanced integrations, refer to the official peaq developer documentation and the Sim by Dune docs.