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!" }