diff --git a/cmd/sim/auth.go b/cmd/sim/auth.go
index 4ae6123..767a275 100644
--- a/cmd/sim/auth.go
+++ b/cmd/sim/auth.go
@@ -15,13 +15,24 @@ import (
func NewAuthCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "auth",
- Short: "Authenticate with the Sim API",
- Long: "Save your Sim API key so you don't need to pass --sim-api-key or set DUNE_SIM_API_KEY every time.",
+ Short: "Save your Sim API key to the local configuration file",
+ Long: "Persist your Sim API key to ~/.config/dune/config.yaml so subsequent\n" +
+ "'dune sim' commands authenticate automatically without requiring\n" +
+ "--sim-api-key or the DUNE_SIM_API_KEY environment variable.\n\n" +
+ "The key can be provided via:\n" +
+ " 1. --api-key flag\n" +
+ " 2. DUNE_SIM_API_KEY environment variable\n" +
+ " 3. Interactive prompt (if neither of the above is set)\n\n" +
+ "The saved key is used as the lowest-priority fallback; --sim-api-key and\n" +
+ "DUNE_SIM_API_KEY always take precedence when set.\n\n" +
+ "Examples:\n" +
+ " dune sim auth\n" +
+ " dune sim auth --api-key sim_abc123...",
Annotations: map[string]string{"skipSimAuth": "true"},
RunE: runSimAuth,
}
- cmd.Flags().String("api-key", "", "Sim API key to save")
+ cmd.Flags().String("api-key", "", "Sim API key to save (prefixed 'sim_'); if omitted, reads from DUNE_SIM_API_KEY or prompts interactively")
return cmd
}
diff --git a/cmd/sim/evm/activity.go b/cmd/sim/evm/activity.go
index 5b79320..9ca52a0 100644
--- a/cmd/sim/evm/activity.go
+++ b/cmd/sim/evm/activity.go
@@ -14,23 +14,39 @@ import (
func NewActivityCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "activity
",
- Short: "Get EVM activity feed for a wallet address",
- Long: "Return a chronological feed of on-chain activity for the given wallet address\n" +
- "including native transfers, ERC20 movements, NFT transfers, swaps, and contract calls.\n\n" +
+ Short: "Get a decoded activity feed for a wallet address across EVM chains",
+ Long: "Return a reverse-chronological feed of human-readable on-chain activity for\n" +
+ "the given wallet address. Unlike raw transactions, activity entries are decoded\n" +
+ "and classified into semantic types: sends, receives, mints, burns, token swaps,\n" +
+ "approvals, and contract calls.\n\n" +
+ "Activity types:\n" +
+ " - send/receive: native or token transfers to/from the wallet\n" +
+ " - mint/burn: token creation or destruction involving the wallet\n" +
+ " - swap: DEX token exchanges (includes from/to token details)\n" +
+ " - approve: ERC20/ERC721 spending approvals\n" +
+ " - call: contract interactions with decoded function name and inputs\n\n" +
+ "Asset types: native, erc20, erc721, erc1155.\n\n" +
+ "Each activity item includes the transaction context, transfer amounts with\n" +
+ "USD values, and token metadata. Swap entries include both sides of the trade.\n" +
+ "Call entries include the decoded function name and inputs.\n\n" +
+ "By default, returns all activity types across all default chains.\n" +
+ "Run 'dune sim evm supported-chains' to see which chains support activity.\n\n" +
+ "For raw transaction data (hashes, gas, calldata), use 'dune sim evm transactions'.\n\n" +
"Examples:\n" +
" dune sim evm activity 0xd8da6bf26964af9d7eed9e03e53415d37aa96045\n" +
" dune sim evm activity 0xd8da... --activity-type send,receive --chain-ids 1\n" +
- " dune sim evm activity 0xd8da... --asset-type erc20 --limit 50 -o json",
+ " dune sim evm activity 0xd8da... --asset-type erc20 --limit 50 -o json\n" +
+ " dune sim evm activity 0xd8da... --token-address 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
Args: cobra.ExactArgs(1),
RunE: runActivity,
}
- cmd.Flags().String("chain-ids", "", "Comma-separated chain IDs or tags (default: all default chains)")
- cmd.Flags().String("token-address", "", "Filter by token contract address (comma-separated for multiple)")
- cmd.Flags().String("activity-type", "", "Filter by type: send,receive,mint,burn,swap,approve,call")
- cmd.Flags().String("asset-type", "", "Filter by asset standard: native,erc20,erc721,erc1155")
- cmd.Flags().Int("limit", 0, "Max results (1-100)")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().String("chain-ids", "", "Restrict to specific chains by numeric ID or tag name (comma-separated, e.g. '1,8453' or 'default'); defaults to all chains tagged 'default'")
+ cmd.Flags().String("token-address", "", "Filter activities involving specific token contracts (comma-separated ERC20/ERC721/ERC1155 addresses)")
+ cmd.Flags().String("activity-type", "", "Filter by activity classification (comma-separated): send, receive, mint, burn, swap, approve, call; defaults to all types")
+ cmd.Flags().String("asset-type", "", "Filter by token standard (comma-separated): native, erc20, erc721, erc1155; defaults to all standards")
+ cmd.Flags().Int("limit", 0, "Maximum number of activity items to return per page (1-100, default: server-determined)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
output.AddFormatFlag(cmd, "text")
return cmd
diff --git a/cmd/sim/evm/balance.go b/cmd/sim/evm/balance.go
index 7e80c11..01d36c2 100644
--- a/cmd/sim/evm/balance.go
+++ b/cmd/sim/evm/balance.go
@@ -14,21 +14,26 @@ import (
func NewBalanceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "balance ",
- Short: "Get balance for a single token",
- Long: "Return the balance of a single token for the given wallet address on one chain.\n" +
- "Use \"native\" as the --token value to query the native asset (e.g. ETH).\n\n" +
+ Short: "Get the balance of a single token for a wallet on one chain",
+ Long: "Return the balance of a specific token for the given wallet address on a\n" +
+ "single EVM chain. This is a targeted lookup that returns exactly one balance\n" +
+ "entry, unlike 'dune sim evm balances' which returns all tokens across chains.\n\n" +
+ "Both --token and --chain-ids are required. Use the literal string 'native'\n" +
+ "as the --token value to query the chain's native asset (e.g. ETH on Ethereum,\n" +
+ "MATIC on Polygon), or pass an ERC20 contract address.\n\n" +
+ "For multi-token or multi-chain lookups, use 'dune sim evm balances' instead.\n\n" +
"Examples:\n" +
" dune sim evm balance 0xd8da... --token native --chain-ids 1\n" +
- " dune sim evm balance 0xd8da... --token 0xa0b8...eb48 --chain-ids 8453\n" +
- " dune sim evm balance 0xd8da... --token native --chain-ids 1 -o json",
+ " dune sim evm balance 0xd8da... --token 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --chain-ids 8453\n" +
+ " dune sim evm balance 0xd8da... --token native --chain-ids 1 --historical-prices 168,24 -o json",
Args: cobra.ExactArgs(1),
RunE: runBalance,
}
- cmd.Flags().String("token", "", "Token contract address or \"native\" (required)")
- cmd.Flags().String("chain-ids", "", "Chain ID (required)")
- cmd.Flags().String("metadata", "", "Extra metadata fields: logo,url,pools")
- cmd.Flags().String("historical-prices", "", "Hour offsets for historical prices (e.g. 720,168,24)")
+ cmd.Flags().String("token", "", "Token to query: an ERC20 contract address (0x...) or the literal string 'native' for the chain's native asset (required)")
+ cmd.Flags().String("chain-ids", "", "Numeric EVM chain ID to query (required, single value, e.g. '1' for Ethereum, '8453' for Base)")
+ cmd.Flags().String("metadata", "", "Request additional metadata fields in the response (comma-separated): 'logo' (token icon URL), 'url' (project website), 'pools' (liquidity pool details)")
+ cmd.Flags().String("historical-prices", "", "Include historical USD prices at the specified hour offsets from now (comma-separated, e.g. '720,168,24' for 30d, 7d, 1d ago)")
_ = cmd.MarkFlagRequired("token")
_ = cmd.MarkFlagRequired("chain-ids")
output.AddFormatFlag(cmd, "text")
diff --git a/cmd/sim/evm/balances.go b/cmd/sim/evm/balances.go
index 0745543..5eebee6 100644
--- a/cmd/sim/evm/balances.go
+++ b/cmd/sim/evm/balances.go
@@ -15,19 +15,28 @@ import (
func NewBalancesCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "balances ",
- Short: "Get EVM token balances for a wallet address",
- Long: "Return native and ERC20 token balances for the given wallet address\n" +
- "across supported EVM chains, including USD valuations.\n\n" +
+ Short: "Get EVM token balances for a wallet address across multiple chains",
+ Long: "Return native and ERC20 token balances for the given wallet address across\n" +
+ "supported EVM chains. Each balance entry includes the token identity, raw\n" +
+ "balance amount, current USD price, total USD value, and liquidity indicators.\n" +
+ "Data comes from Dune's real-time index.\n\n" +
+ "By default, queries all chains tagged 'default'. Use --chain-ids to restrict\n" +
+ "to specific networks. Run 'dune sim evm supported-chains' to see valid IDs.\n\n" +
+ "For a single-token balance lookup, use 'dune sim evm balance' instead.\n" +
+ "For stablecoin-only balances, use 'dune sim evm stablecoins'.\n\n" +
+ "Results are paginated; use --offset with the next_offset value from a\n" +
+ "previous response to retrieve additional pages.\n\n" +
"Examples:\n" +
" dune sim evm balances 0xd8da6bf26964af9d7eed9e03e53415d37aa96045\n" +
" dune sim evm balances 0xd8da... --chain-ids 1,8453 --exclude-spam\n" +
- " dune sim evm balances 0xd8da... --historical-prices 168 -o json",
+ " dune sim evm balances 0xd8da... --filters erc20 --metadata logo,url\n" +
+ " dune sim evm balances 0xd8da... --historical-prices 720,168,24 -o json",
Args: cobra.ExactArgs(1),
RunE: runBalances,
}
addBalanceFlags(cmd)
- cmd.Flags().String("asset-class", "", "Asset class filter: stablecoin")
+ cmd.Flags().String("asset-class", "", "Filter by asset classification: 'stablecoin' (returns only stablecoins like USDC, USDT, DAI); prefer 'dune sim evm stablecoins' as a shorthand")
return cmd
}
@@ -103,13 +112,13 @@ func runBalances(cmd *cobra.Command, args []string) error {
// addBalanceFlags registers the common flags shared by the balances and
// stablecoins commands.
func addBalanceFlags(cmd *cobra.Command) {
- cmd.Flags().String("chain-ids", "", "Comma-separated chain IDs or tags (default: all default chains)")
- cmd.Flags().String("filters", "", "Token filter: erc20 or native")
- cmd.Flags().String("metadata", "", "Extra metadata fields: logo,url,pools")
- cmd.Flags().Bool("exclude-spam", false, "Exclude tokens with <100 USD liquidity")
- cmd.Flags().String("historical-prices", "", "Hour offsets for historical prices (e.g. 720,168,24)")
- cmd.Flags().Int("limit", 0, "Max results (1-1000)")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().String("chain-ids", "", "Restrict to specific chains by numeric ID or tag name (comma-separated, e.g. '1,8453' or 'default'); defaults to all chains tagged 'default'. Run 'dune sim evm supported-chains' for valid values")
+ cmd.Flags().String("filters", "", "Filter by token standard: 'erc20' (only ERC20 tokens) or 'native' (only native chain assets like ETH)")
+ cmd.Flags().String("metadata", "", "Request additional metadata fields in the response (comma-separated): 'logo' (token icon URL), 'url' (project website), 'pools' (liquidity pool details)")
+ cmd.Flags().Bool("exclude-spam", false, "Exclude low-liquidity tokens (less than $100 USD pool size) commonly associated with spam airdrops")
+ cmd.Flags().String("historical-prices", "", "Include historical USD prices at the specified hour offsets from now (comma-separated, e.g. '720,168,24' for 30d, 7d, 1d ago)")
+ cmd.Flags().Int("limit", 0, "Maximum number of balance entries to return per page (1-1000, default: server-determined)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
output.AddFormatFlag(cmd, "text")
}
diff --git a/cmd/sim/evm/collectibles.go b/cmd/sim/evm/collectibles.go
index 489e2e6..31b52d1 100644
--- a/cmd/sim/evm/collectibles.go
+++ b/cmd/sim/evm/collectibles.go
@@ -14,22 +14,31 @@ import (
func NewCollectiblesCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "collectibles ",
- Short: "Get NFT collectibles for a wallet address",
- Long: "Return ERC721 and ERC1155 collectibles (NFTs) held by the given wallet address\n" +
- "across supported EVM chains. Spam filtering is enabled by default.\n\n" +
+ Short: "Get NFT collectibles (ERC721/ERC1155) held by a wallet address",
+ Long: "Return ERC721 and ERC1155 collectibles (NFTs) held by the given wallet\n" +
+ "address across supported EVM chains. Each entry includes the collection and\n" +
+ "token identity, image URL, quantity held, acquisition timestamp, and spam\n" +
+ "classification when requested. Spam filtering is enabled by default to hide\n" +
+ "airdropped junk NFTs.\n\n" +
+ "Spam filtering uses a scoring model based on collection traits (holder count,\n" +
+ "transfer patterns, metadata quality). Disable with --filter-spam=false to see\n" +
+ "all NFTs including suspected spam.\n\n" +
+ "By default, queries all chains tagged 'default'. Run 'dune sim evm\n" +
+ "supported-chains' to see which chains support collectibles.\n\n" +
"Examples:\n" +
" dune sim evm collectibles 0xd8da6bf26964af9d7eed9e03e53415d37aa96045\n" +
" dune sim evm collectibles 0xd8da... --chain-ids 1\n" +
- " dune sim evm collectibles 0xd8da... --filter-spam=false --show-spam-scores -o json",
+ " dune sim evm collectibles 0xd8da... --filter-spam=false --show-spam-scores -o json\n" +
+ " dune sim evm collectibles 0xd8da... --limit 100 -o json",
Args: cobra.ExactArgs(1),
RunE: runCollectibles,
}
- cmd.Flags().String("chain-ids", "", "Comma-separated chain IDs or tags (default: all default chains)")
- cmd.Flags().Bool("filter-spam", true, "Hide collectibles identified as spam")
- cmd.Flags().Bool("show-spam-scores", false, "Include spam scoring details")
- cmd.Flags().Int("limit", 0, "Max results per page (1-2500, default 250)")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().String("chain-ids", "", "Restrict to specific chains by numeric ID or tag name (comma-separated, e.g. '1,8453' or 'default'); defaults to all chains tagged 'default'")
+ cmd.Flags().Bool("filter-spam", true, "Hide collectibles identified as spam by the scoring model (default: true); set --filter-spam=false to include all NFTs")
+ cmd.Flags().Bool("show-spam-scores", false, "Include spam classification details in the response: is_spam flag, numeric spam_score, and per-feature explanations with weights")
+ cmd.Flags().Int("limit", 0, "Maximum number of collectibles to return per page (1-2500, default: 250)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
output.AddFormatFlag(cmd, "text")
return cmd
diff --git a/cmd/sim/evm/defi_positions.go b/cmd/sim/evm/defi_positions.go
index c0b05d2..cf3d58d 100644
--- a/cmd/sim/evm/defi_positions.go
+++ b/cmd/sim/evm/defi_positions.go
@@ -18,11 +18,24 @@ import (
func NewDefiPositionsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "defi-positions ",
- Short: "Get DeFi positions for a wallet address",
- Long: "Return DeFi positions for the given wallet address including USD values,\n" +
- "position-specific metadata, and aggregation summaries across supported protocols.\n\n" +
- "Supported position types: Erc4626 (vaults), Tokenized (lending, e.g. aTokens),\n" +
- "UniswapV2 (AMM LP), Nft (Uniswap V3 NFT), NftV4 (Uniswap V4 NFT).\n\n" +
+ Short: "Get DeFi positions (lending, LPs, vaults) for a wallet address",
+ Long: "Return DeFi positions for the given wallet address across supported EVM\n" +
+ "chains and protocols. Each position includes USD valuation and protocol-\n" +
+ "specific metadata. The response also includes aggregation summaries with\n" +
+ "total USD value and per-chain breakdowns.\n\n" +
+ "Note: This endpoint is in beta (served under /beta/evm/defi/positions/*).\n\n" +
+ "Supported position types:\n" +
+ " - Erc4626: ERC-4626 vault positions (e.g. yield vaults, staking wrappers)\n" +
+ " - Tokenized: lending protocol positions with receipt tokens (e.g. Aave\n" +
+ " aTokens, Compound cTokens)\n" +
+ " - UniswapV2: AMM liquidity provider positions (Uniswap V2 and forks)\n" +
+ " - Nft: Uniswap V3 concentrated liquidity positions (NFT-based)\n" +
+ " - NftV4: Uniswap V4 concentrated liquidity positions (NFT-based)\n\n" +
+ "Each position includes the chain, USD value, protocol name, and type-\n" +
+ "specific details (token identities, pool info, balances). The response\n" +
+ "also includes aggregation summaries with total value and per-chain\n" +
+ "breakdowns. Use -o json for the full structured response.\n\n" +
+ "Run 'dune sim evm supported-chains' to see which chains support defi-positions.\n\n" +
"Examples:\n" +
" dune sim evm defi-positions 0xd8da6bf26964af9d7eed9e03e53415d37aa96045\n" +
" dune sim evm defi-positions 0xd8da... --chain-ids 1,8453\n" +
@@ -31,7 +44,7 @@ func NewDefiPositionsCmd() *cobra.Command {
RunE: runDefiPositions,
}
- cmd.Flags().String("chain-ids", "", "Comma-separated chain IDs or tags (default: all default chains)")
+ cmd.Flags().String("chain-ids", "", "Restrict to specific chains by numeric ID or tag name (comma-separated, e.g. '1,8453' or 'default'); defaults to all chains tagged 'default'")
output.AddFormatFlag(cmd, "text")
return cmd
diff --git a/cmd/sim/evm/evm.go b/cmd/sim/evm/evm.go
index 1329f2f..f66cb26 100644
--- a/cmd/sim/evm/evm.go
+++ b/cmd/sim/evm/evm.go
@@ -32,10 +32,25 @@ func SimClientFromCmd(cmd *cobra.Command) SimClient {
func NewEvmCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "evm",
- Short: "Query EVM chain data (balances, activity, transactions, etc.)",
- Long: "Access real-time EVM blockchain data including token balances, activity feeds,\n" +
- "transaction history, NFT collectibles, token metadata, token holders,\n" +
- "and DeFi positions.",
+ Short: "Query EVM chain data (balances, activity, transactions, tokens, NFTs, DeFi)",
+ Long: "Access real-time, indexed EVM blockchain data. All commands accept an\n" +
+ "Ethereum-style address (0x...) as the primary argument and return data\n" +
+ "across multiple EVM chains simultaneously.\n\n" +
+ "Available subcommands:\n" +
+ " supported-chains - List all supported EVM chains and endpoint availability (public, no auth)\n" +
+ " balances - Native + ERC20 token balances with USD valuations\n" +
+ " balance - Single-token balance lookup on one chain\n" +
+ " stablecoins - Stablecoin-only balances (USDC, USDT, DAI, etc.)\n" +
+ " activity - Chronological feed of transfers, swaps, mints, burns, approvals\n" +
+ " transactions - Raw transaction history with optional ABI decoding\n" +
+ " collectibles - ERC721 and ERC1155 NFT holdings with spam filtering\n" +
+ " token-info - Token metadata, pricing, supply, and market cap\n" +
+ " token-holders - Top holders of an ERC20 token ranked by balance\n" +
+ " defi-positions - DeFi positions across lending, AMM, and vault protocols (beta)\n\n" +
+ "Most commands support --chain-ids to restrict results to specific networks.\n" +
+ "Run 'dune sim evm supported-chains' to discover valid chain IDs, tags, and\n" +
+ "which endpoints are available per chain.\n\n" +
+ "All commands except 'supported-chains' require a Sim API key.",
}
cmd.AddCommand(NewSupportedChainsCmd())
diff --git a/cmd/sim/evm/stablecoins.go b/cmd/sim/evm/stablecoins.go
index 9b6dc34..9cdfde7 100644
--- a/cmd/sim/evm/stablecoins.go
+++ b/cmd/sim/evm/stablecoins.go
@@ -8,13 +8,20 @@ import (
func NewStablecoinsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "stablecoins ",
- Short: "Get stablecoin balances for a wallet address",
- Long: "Return stablecoin balances for the given wallet address across supported\n" +
- "EVM chains, including USD valuations.\n\n" +
+ Short: "Get stablecoin balances for a wallet address across multiple chains",
+ Long: "Return only stablecoin balances (USDC, USDT, DAI, FRAX, etc.) for the given\n" +
+ "wallet address across supported EVM chains. This is a convenience shorthand\n" +
+ "for 'dune sim evm balances --asset-class stablecoin'.\n\n" +
+ "Each balance entry includes the token amount, current USD price, and total\n" +
+ "USD value. The same response format and pagination as 'dune sim evm balances'\n" +
+ "applies.\n\n" +
+ "By default, queries all chains tagged 'default'. Use --chain-ids to restrict\n" +
+ "to specific networks. Run 'dune sim evm supported-chains' for valid IDs.\n\n" +
+ "For all token balances (not just stablecoins), use 'dune sim evm balances'.\n\n" +
"Examples:\n" +
" dune sim evm stablecoins 0xd8da6bf26964af9d7eed9e03e53415d37aa96045\n" +
" dune sim evm stablecoins 0xd8da... --chain-ids 1,8453\n" +
- " dune sim evm stablecoins 0xd8da... -o json",
+ " dune sim evm stablecoins 0xd8da... --exclude-spam -o json",
Args: cobra.ExactArgs(1),
RunE: runStablecoins,
}
diff --git a/cmd/sim/evm/supported_chains.go b/cmd/sim/evm/supported_chains.go
index 84a87f5..9d6df7e 100644
--- a/cmd/sim/evm/supported_chains.go
+++ b/cmd/sim/evm/supported_chains.go
@@ -15,9 +15,13 @@ func NewSupportedChainsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "supported-chains",
Short: "List supported EVM chains and their endpoint availability",
- Long: "Display all EVM chains supported by the Sim API and which endpoints\n" +
- "(balances, activity, transactions, etc.) are available for each chain.\n\n" +
- "This endpoint is public and does not require a Sim API key.\n\n" +
+ Long: "Display all EVM chains supported by the Sim API along with a capability\n" +
+ "matrix showing which endpoints are available for each chain. Each chain\n" +
+ "entry includes the chain name, numeric ID, tags, and boolean flags\n" +
+ "indicating which Sim API endpoints are supported.\n\n" +
+ "This is a public endpoint and does not require a Sim API key.\n\n" +
+ "Use the chain IDs or tag names from this output as --chain-ids\n" +
+ "arguments in other 'dune sim evm' commands.\n\n" +
"Examples:\n" +
" dune sim evm supported-chains\n" +
" dune sim evm supported-chains -o json",
diff --git a/cmd/sim/evm/token_holders.go b/cmd/sim/evm/token_holders.go
index 64efdf9..acf221a 100644
--- a/cmd/sim/evm/token_holders.go
+++ b/cmd/sim/evm/token_holders.go
@@ -15,9 +15,19 @@ import (
func NewTokenHoldersCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "token-holders ",
- Short: "Get token holders ranked by balance",
- Long: "Return a list of holders for a given ERC20 token contract on a specified chain,\n" +
- "ranked by balance descending.\n\n" +
+ Short: "Get the top holders of an ERC20 token ranked by balance",
+ Long: "Return a leaderboard of holders for a given ERC20 token contract on a single\n" +
+ "EVM chain, ranked by balance in descending order. Useful for analyzing token\n" +
+ "distribution, identifying whales, and checking concentration.\n\n" +
+ "Both --chain-id (single numeric chain ID) and the token address argument are\n" +
+ "required. Unlike other sim evm commands that accept --chain-ids (plural),\n" +
+ "this command uses --chain-id (singular) and queries exactly one chain.\n\n" +
+ "Each holder entry includes the wallet address, token balance, earliest\n" +
+ "acquisition timestamp, and whether they have ever initiated an outgoing\n" +
+ "transfer (useful for distinguishing active holders from airdrop recipients).\n\n" +
+ "Results are paginated; use --offset with the next_offset value from a\n" +
+ "previous response to retrieve additional pages.\n\n" +
+ "Run 'dune sim evm supported-chains' to see which chains support token-holders.\n\n" +
"Examples:\n" +
" dune sim evm token-holders 0x63706e401c06ac8513145b7687A14804d17f814b --chain-id 8453\n" +
" dune sim evm token-holders 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --chain-id 1 --limit 50\n" +
@@ -26,9 +36,9 @@ func NewTokenHoldersCmd() *cobra.Command {
RunE: runTokenHolders,
}
- cmd.Flags().String("chain-id", "", "Numeric chain ID (required)")
- cmd.Flags().Int("limit", 0, "Max results (1-500, default 500)")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().String("chain-id", "", "Numeric EVM chain ID to query (required, single value, e.g. '1' for Ethereum, '8453' for Base); note: singular --chain-id, not --chain-ids")
+ cmd.Flags().Int("limit", 0, "Maximum number of holders to return per page (1-500, default: 500)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
_ = cmd.MarkFlagRequired("chain-id")
output.AddFormatFlag(cmd, "text")
diff --git a/cmd/sim/evm/token_info.go b/cmd/sim/evm/token_info.go
index 224cc8e..77669d9 100644
--- a/cmd/sim/evm/token_info.go
+++ b/cmd/sim/evm/token_info.go
@@ -14,9 +14,17 @@ import (
func NewTokenInfoCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "token-info ",
- Short: "Get token metadata and pricing",
- Long: "Return metadata and pricing for a token contract address (or \"native\" for the\n" +
- "chain's native asset) on a specified chain.\n\n" +
+ Short: "Get token metadata, pricing, supply, and market cap for a token address",
+ Long: "Return metadata and real-time pricing for a token contract address on a\n" +
+ "specified EVM chain. Use the literal string 'native' as the address to query\n" +
+ "the chain's native asset (e.g. ETH on chain 1, MATIC on chain 137).\n\n" +
+ "The --chain-ids flag is required and should specify a single chain ID.\n\n" +
+ "Returns the token identity, current USD price (from on-chain DEX pools),\n" +
+ "total supply, estimated market cap, and logo. Use --historical-prices to\n" +
+ "include past USD prices at specified hour offsets.\n\n" +
+ "This command is useful for looking up token details before querying\n" +
+ "balances or activity. For wallet-scoped token data, use\n" +
+ "'dune sim evm balances' or 'dune sim evm balance'.\n\n" +
"Examples:\n" +
" dune sim evm token-info native --chain-ids 1\n" +
" dune sim evm token-info 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --chain-ids 8453\n" +
@@ -25,10 +33,10 @@ func NewTokenInfoCmd() *cobra.Command {
RunE: runTokenInfo,
}
- cmd.Flags().String("chain-ids", "", "Chain ID (required)")
- cmd.Flags().String("historical-prices", "", "Hour offsets for historical prices (e.g. 720,168,24)")
- cmd.Flags().Int("limit", 0, "Max results")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().String("chain-ids", "", "Numeric EVM chain ID to query (required, single value, e.g. '1' for Ethereum, '8453' for Base)")
+ cmd.Flags().String("historical-prices", "", "Include historical USD prices at the specified hour offsets from now (comma-separated, e.g. '720,168,24' for 30d, 7d, 1d ago)")
+ cmd.Flags().Int("limit", 0, "Maximum number of token entries to return (default: server-determined)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
_ = cmd.MarkFlagRequired("chain-ids")
output.AddFormatFlag(cmd, "text")
diff --git a/cmd/sim/evm/transactions.go b/cmd/sim/evm/transactions.go
index f60fe96..1e5e6da 100644
--- a/cmd/sim/evm/transactions.go
+++ b/cmd/sim/evm/transactions.go
@@ -14,9 +14,19 @@ import (
func NewTransactionsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "transactions ",
- Short: "Get EVM transactions for a wallet address",
- Long: "Return transaction history for the given wallet address across supported EVM chains.\n" +
- "Use --decode with -o json to include decoded function calls and event logs.\n\n" +
+ Short: "Get raw EVM transaction history for a wallet address across chains",
+ Long: "Return raw transaction history for the given wallet address across supported\n" +
+ "EVM chains. Transactions are returned in reverse-chronological order. Each\n" +
+ "transaction includes the hash, sender/recipient, value, block context, gas\n" +
+ "parameters, and raw calldata.\n\n" +
+ "Use --decode with -o json to include ABI-decoded function calls and event\n" +
+ "logs. Decoded data adds 'decoded' fields with function name and typed inputs,\n" +
+ "plus 'logs' with decoded event emissions. Note: --decode data is only visible\n" +
+ "in JSON output mode; the text table cannot display nested decoded structures.\n\n" +
+ "For human-readable, classified activity (sends, swaps, approvals, etc.),\n" +
+ "use 'dune sim evm activity' instead.\n\n" +
+ "By default, queries all chains tagged 'default'. Run 'dune sim evm\n" +
+ "supported-chains' to see which chains support transactions.\n\n" +
"Examples:\n" +
" dune sim evm transactions 0xd8da6bf26964af9d7eed9e03e53415d37aa96045\n" +
" dune sim evm transactions 0xd8da... --chain-ids 1 --decode -o json\n" +
@@ -25,10 +35,10 @@ func NewTransactionsCmd() *cobra.Command {
RunE: runTransactions,
}
- cmd.Flags().String("chain-ids", "", "Comma-separated chain IDs or tags (default: all default chains)")
- cmd.Flags().Bool("decode", false, "Include decoded transaction data and logs (use with -o json)")
- cmd.Flags().Int("limit", 0, "Max results (1-100)")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().String("chain-ids", "", "Restrict to specific chains by numeric ID or tag name (comma-separated, e.g. '1,8453' or 'default'); defaults to all chains tagged 'default'")
+ cmd.Flags().Bool("decode", false, "Include ABI-decoded function calls and event logs in the response; only visible in JSON output (-o json), ignored in text table mode")
+ cmd.Flags().Int("limit", 0, "Maximum number of transactions to return per page (1-100, default: server-determined)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
output.AddFormatFlag(cmd, "text")
return cmd
diff --git a/cmd/sim/sim.go b/cmd/sim/sim.go
index 2204730..8d16b92 100644
--- a/cmd/sim/sim.go
+++ b/cmd/sim/sim.go
@@ -20,18 +20,33 @@ var simAPIKeyFlag string
func NewSimCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "sim",
- Short: "Query real-time blockchain data via the Sim API",
- Long: "Access real-time blockchain data including balances, activity, transactions,\n" +
- "collectibles, token info, token holders, and DeFi positions across EVM and SVM chains.\n\n" +
- "Authenticate with a Sim API key via --sim-api-key, the DUNE_SIM_API_KEY environment\n" +
- "variable, or by running `dune sim auth`.",
+ Short: "Query real-time blockchain data via the Dune Sim API",
+ Long: "Access real-time, indexed blockchain data through the Dune Sim API. Unlike\n" +
+ "'dune query run' which executes SQL against historical data warehouses, Sim API\n" +
+ "endpoints return pre-indexed, low-latency responses for common wallet and token\n" +
+ "lookups.\n\n" +
+ "Available subcommands:\n" +
+ " evm - Query EVM chains: balances, activity, transactions, collectibles,\n" +
+ " token-info, token-holders, defi-positions, supported-chains\n" +
+ " svm - Query SVM chains (Solana, Eclipse): balances, transactions\n" +
+ " auth - Save your Sim API key to the local config file\n\n" +
+ "Authentication:\n" +
+ " Most commands require a Sim API key. The key is resolved in priority order:\n" +
+ " 1. --sim-api-key flag\n" +
+ " 2. DUNE_SIM_API_KEY environment variable\n" +
+ " 3. Saved key in ~/.config/dune/config.yaml (set via 'dune sim auth')\n\n" +
+ " Exception: 'dune sim evm supported-chains' is a public endpoint and does\n" +
+ " not require authentication.\n\n" +
+ "Each API call consumes compute units based on the number of chains queried\n" +
+ "and the complexity of the request. Use -o json on any command to get the\n" +
+ "full structured response for programmatic consumption.",
Annotations: map[string]string{"skipAuth": "true"},
PersistentPreRunE: simPreRun,
}
cmd.PersistentFlags().StringVar(
&simAPIKeyFlag, "sim-api-key", "",
- "Sim API key (overrides DUNE_SIM_API_KEY env var)",
+ "Sim API key for authentication (overrides DUNE_SIM_API_KEY env var and saved config); keys are prefixed 'sim_'",
)
cmd.AddCommand(NewAuthCmd())
diff --git a/cmd/sim/svm/balances.go b/cmd/sim/svm/balances.go
index 48e2870..eb813a4 100644
--- a/cmd/sim/svm/balances.go
+++ b/cmd/sim/svm/balances.go
@@ -14,9 +14,15 @@ import (
func NewBalancesCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "balances ",
- Short: "Get SVM token balances for a wallet address",
- Long: "Return token balances for the given SVM wallet address across\n" +
- "Solana and Eclipse chains, including USD valuations.\n\n" +
+ Short: "Get SPL token balances for an SVM wallet address with USD valuations",
+ Long: "Return SPL token balances for the given SVM (Solana Virtual Machine) wallet\n" +
+ "address. Each balance entry includes the token identity, balance (both raw\n" +
+ "and human-readable), current USD price, total USD value, and liquidity data.\n" +
+ "Data comes from Dune's real-time index.\n\n" +
+ "Supported chains: Solana, Eclipse (default: Solana only).\n\n" +
+ "Note: This endpoint is in beta (served under /beta/svm/balances/*).\n\n" +
+ "Results are paginated; use --offset with the next_offset value from a\n" +
+ "previous response to retrieve additional pages.\n\n" +
"Examples:\n" +
" dune sim svm balances 86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\n" +
" dune sim svm balances 86xCnPeV... --chains solana,eclipse\n" +
@@ -25,9 +31,9 @@ func NewBalancesCmd() *cobra.Command {
RunE: runBalances,
}
- cmd.Flags().String("chains", "", "Comma-separated chains: solana, eclipse (default: solana)")
- cmd.Flags().Int("limit", 0, "Max results (1-1000, default 1000)")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().String("chains", "", "Restrict to specific SVM chains (comma-separated): 'solana', 'eclipse' (default: solana only)")
+ cmd.Flags().Int("limit", 0, "Maximum number of balance entries to return per page (1-1000, default: 1000)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
output.AddFormatFlag(cmd, "text")
return cmd
diff --git a/cmd/sim/svm/svm.go b/cmd/sim/svm/svm.go
index cc1b03b..d81e0da 100644
--- a/cmd/sim/svm/svm.go
+++ b/cmd/sim/svm/svm.go
@@ -42,9 +42,15 @@ func requireSimClient(cmd *cobra.Command) (SimClient, error) {
func NewSvmCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "svm",
- Short: "Query SVM chain data (balances, transactions)",
- Long: "Access real-time SVM blockchain data including token balances and\n" +
- "transaction history for Solana and Eclipse chains.",
+ Short: "Query SVM chain data (Solana, Eclipse) for balances and transactions",
+ Long: "Access real-time, indexed SVM (Solana Virtual Machine) blockchain data.\n" +
+ "Commands accept a Solana-style base58 wallet address as the primary argument.\n\n" +
+ "Supported chains: Solana, Eclipse.\n\n" +
+ "Available subcommands:\n" +
+ " balances - SPL token balances with USD valuations and liquidity data\n" +
+ " transactions - Raw transaction history with block slot and signature\n\n" +
+ "Note: SVM endpoints are currently in beta (served under /beta/svm/*).\n" +
+ "All commands require a Sim API key.",
}
cmd.AddCommand(NewBalancesCmd())
diff --git a/cmd/sim/svm/transactions.go b/cmd/sim/svm/transactions.go
index d5f7888..45106d8 100644
--- a/cmd/sim/svm/transactions.go
+++ b/cmd/sim/svm/transactions.go
@@ -15,9 +15,14 @@ import (
func NewTransactionsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "transactions ",
- Short: "Get SVM transactions for a wallet address",
- Long: "Return transactions for the given SVM wallet address.\n" +
- "Raw transaction data is available in JSON output.\n\n" +
+ Short: "Get Solana transaction history for an SVM wallet address",
+ Long: "Return transaction history for the given SVM (Solana Virtual Machine) wallet\n" +
+ "address. Transactions are returned in reverse-chronological order by block slot.\n" +
+ "Each entry includes the chain, block slot, block time, and in JSON output the\n" +
+ "full raw Solana transaction with signatures, instructions, and account keys.\n\n" +
+ "Note: This endpoint is in beta (served under /beta/svm/transactions/*).\n\n" +
+ "Results are paginated; use --offset with the next_offset value from a\n" +
+ "previous response to retrieve additional pages.\n\n" +
"Examples:\n" +
" dune sim svm transactions 86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY\n" +
" dune sim svm transactions 86xCnPeV... --limit 20\n" +
@@ -26,8 +31,8 @@ func NewTransactionsCmd() *cobra.Command {
RunE: runTransactions,
}
- cmd.Flags().Int("limit", 0, "Max results (1-1000, default 100)")
- cmd.Flags().String("offset", "", "Pagination cursor from previous response")
+ cmd.Flags().Int("limit", 0, "Maximum number of transactions to return per page (1-1000, default: 100)")
+ cmd.Flags().String("offset", "", "Pagination cursor returned as next_offset in a previous response; use to fetch the next page of results")
output.AddFormatFlag(cmd, "text")
return cmd
diff --git a/install.sh b/install.sh
index c1b9eab..7e5030a 100755
--- a/install.sh
+++ b/install.sh
@@ -91,6 +91,7 @@ main() {
echo "" >&2
log "Tip: Run 'npx skills add duneanalytics/skills' to install the Dune AI coding skill."
log "Tip: Run 'dune auth' to authenticate with your Dune account."
+ log "Tip: Run 'dune sim auth' to access real-time blockchain data (balances, tokens, NFTs)."
fi
}
@@ -134,14 +135,42 @@ post_install() {
;;
*)
echo "" >&2
- log "You'll need a Dune API key."
- log "Go to https://dune.com and navigate to APIs and Connectors > API Keys."
+ log "You'll need a Dune API key. To create one:"
+ log " 1. Go to https://dune.com and login or create an account"
+ log " 2. Navigate to 'APIs & Connectors'"
+ log " 3. Click 'API Keys' and create a new key"
echo "" >&2
"$dune_bin" auth < /dev/tty || log "Authentication failed. You can retry with: dune auth"
;;
esac
fi
+ echo "" >&2
+
+ # --- Sim API Authentication ---
+ if "$dune_bin" sim evm token-info native --chain-ids 1 > /dev/null 2>&1; then
+ log "Already authenticated with Sim API."
+ else
+ log "Authenticate with the Sim API to access real-time blockchain data"
+ log "(wallet balances, token prices, NFTs, DeFi positions, etc.)."
+ printf " Authenticate with Sim API now? [Y/n] " >&2
+ read -r answer < /dev/tty || answer=""
+ case "$answer" in
+ [nN]*)
+ log "Skipped. You can authenticate later with: dune sim auth"
+ ;;
+ *)
+ echo "" >&2
+ log "You'll need a Sim API key. To create one:"
+ log " 1. Go to https://sim.dune.com/ and login or create an account"
+ log " 2. Click 'Keys'"
+ log " 3. Click 'New' to create a new API key"
+ echo "" >&2
+ "$dune_bin" sim auth < /dev/tty || log "Authentication failed. You can retry with: dune sim auth"
+ ;;
+ esac
+ fi
+
echo "" >&2
log "Dune CLI ${dune_version} installed successfully!"
}