Skip to main content
Glama
ygfalcon

Solana Wallet Intel MCP Server

README.md
# Solana Wallet Analyzer: PnL, Win Rate, Smart Money & Bot Detector

Screen any **Solana wallet** for **realized PnL**, **win rate**, closed trades, and trading cadence. Flag **smart money**, **bot-like** cadence, **exchange / custodial** wallets, net winners, and dormant accounts. Open a full profile with priced holdings and unrealized PnL, or pull **trending Solana tokens** with liquidity, volume, age, DEX, and **rug-risk flags**.

Built for copy-traders, memecoin researchers, and airdrop hunters who need structured Solana wallet intelligence in Apify, Make, Zapier, n8n, or an MCP client. PnL is a windowed estimate. It is not financial advice and it is not tax-grade.

## What you get

| Mode | What it returns | Apify price |
|---|---|---|
| `quick` | Realized PnL, win rate, closed trades, bot / net-winner / dormant flags, portfolio value, last active, Solscan link. Per-day rates are null on this screen. Smart-money and exchange flags are set only when the payload says so | **$0.005 per wallet** |
| `profile` | Quick fields, including the behavior flags, plus priced holdings (top 10), unrealized PnL, per-day rates when the window is at least an hour, labels, and warnings. Copy-trade score and grade are null unless the backend sends them | **$0.02 per wallet** |
| `preview` | SOL balance, last active time, and 24h transaction count | **Free** |
| `trending` | Up to 25 trending Solana tokens: price, liquidity, 24h volume and change, age, DEX, chart link, rug-risk flags | **$0.01 per run** |

You are charged only for successful results. A wallet that errors, times out, or is rejected by the backend is stored as `type: "error"` with `charged: false` and is not charged. `preview` never creates a charge. `trending` charges one `trending-run` for a successful snapshot that contains at least one token, whether that is 1 token or 25. An empty snapshot is stored as an error and is not charged. Quick mode asks for wallets in batches of 10; each requested wallet is charged once. A duplicate row is not charged again, a wallet that also appears in `errors` is not charged, and a wallet that was not requested is dropped.

With `onlySmartMoney`, every quick wallet that returned a result is still charged. Wallets the payload did not mark smart-money are left out of the dataset (`filteredOut` in the run summary) and failed lookups are not charged. The current falcon.sol screen does not emit a smart-money label, so this filter only keeps a row when that boolean or label is actually present. The filter applies only to `quick`.

Set a maximum charge on the run and the Actor stops cleanly when the next paid event would exceed it. Rows that the platform cannot bill are not stored. The summary in the key-value store under `OUTPUT` includes counts, invalid addresses, duplicates, charged events, filtered rows, and `stoppedByBudget`.

## Quick start

**Screen a list of wallets**

```json
{ "mode": "quick", "addresses": ["HD1ryR3dYSXBVNGfJZydbpmnChiE1wrAQkupWWtHt4pM", "<another wallet>"] }
```

**Keep only smart-money wallets**

```json
{ "mode": "quick", "addresses": ["<wallet1>", "<wallet2>"], "onlySmartMoney": true }
```

**Full profile with a deeper transaction window**

```json
{ "mode": "profile", "addresses": ["HD1ryR3dYSXBVNGfJZydbpmnChiE1wrAQkupWWtHt4pM"], "txLimit": 20 }
```

`txLimit` is an integer from 5 to 25 (default 20). It is the number of recent transactions the profile scan asks for. A value outside that range fails the run before any lookup.

**Trending tokens with rug-risk flags**

```json
{ "mode": "trending", "trendingLimit": 25 }
```

`trendingLimit` is an integer from 1 to 25 (default 15). Trending mode ignores `addresses`.

## Output

`schemaVersion` is 2. Every item has `type`, `schemaVersion`, and `fetchedAt`. Table views choose columns for Quick wallet checks, Wallet profiles, Wallet previews, Trending tokens, and Errors (not charged). A view does not hide other rows; use `type` to tell a result from an error. A single run uses one mode.

```json
{
  "type": "wallet_quick",
  "schemaVersion": 2,
  "address": "HD1ryR3dYSXBVNGfJZydbpmnChiE1wrAQkupWWtHt4pM",
  "realizedUsd": 1284.55,
  "winRate": 0.62,
  "closedTrades": 41,
  "swapsPerDay": 7.3,
  "txsPerDay": 18.1,
  "windowTooShort": false,
  "smartMoney": true,
  "bot": false,
  "exchangeLike": false,
  "netWinner": true,
  "dormant": false,
  "portfolioUsd": 5320.1,
  "lastActiveAt": "2026-10-23T15:02:11.000Z",
  "explorerUrl": "https://solscan.io/account/HD1ryR3dYSXBVNGfJZydbpmnChiE1wrAQkupWWtHt4pM",
  "fetchedAt": "2026-10-24T00:00:00.000Z"
}
```

Numbers above are illustrative. `winRate` is a fraction from 0 to 1, not a percent. `swapsPerDay` and `txsPerDay` are null when `windowTooShort` is true. On quick they stay null, because that payload has no window span. A profile fills them from `window.from` / `window.to` and the activity counts when the span is at least an hour.

## How the flags work

The falcon.sol backend labels a wallet from the transaction window it actually fetched. This Actor copies those labels onto boolean columns:

- **Bot-like:** the live label is `bot-like`. It means at least 8 swaps, a median gap between swaps of 90 seconds or less, and the wallet is not dormant.
- **Net winner:** realized PnL of at least $1, at least one winning close, and the cost basis is not partial. A partial cost basis is not reported as a net winner. Realized PnL of -$1 or less, with a complete basis, is labeled net loser.
- **Dormant:** the last activity in the window is more than 14 days ago.
- **Smart-money and exchange / custodial:** true only when the payload sends that boolean or a matching label. The current screen does not emit those labels.
- **windowTooShort:** the oldest and newest transactions in the window are under 1 hour apart. Per-day rates are null so a few seconds of activity are not turned into a huge daily rate.

PnL is average cost over the fetched window. SOL used as payment is valued at the trade-hour price when that history exists, otherwise at the current SOL price. Stablecoins are pegged near $1. Sells with no in-window cost basis are excluded, and `pnl.partialCostBasis` is then true. `pnl.priceBasis` is `execution`, `current_spot`, `mixed`, or `unavailable`. Trades outside the window are missing. Read `warnings` on a profile before treating the number as a track record. It is not financial advice and it is not tax-grade.

Rug-risk flags on trending tokens are plain strings such as `low_liquidity`, `thin_volume`, `newly_launched`, `extreme_move`, `wash_suspect`, and `paid_boost`. They are heuristics, not a guarantee that a token is safe or unsafe.

## Limits, retries, and freshness

- Up to 1,000 unique wallets per run. Duplicates are skipped and counted. Invalid base58 addresses, including strings that do not decode to 32 bytes, are skipped, listed in `OUTPUT.invalid`, and not sent upstream. A quoted address, a comma-separated cell, or an explorer URL is accepted. A pure base58 string that is not 32 bytes is not sliced into a shorter address. More than 1,000 unique addresses fails the run before any lookup, so a truncated list is not billed as if it were complete.
- Profile `txLimit` is an integer from 5 to 25 (default 20).
- `maxConcurrency` is an integer from 1 to 10 (default 4).
- Plain HTTP 408, 500, 502, 503, and 504 responses get up to 4 attempts when the body does not say `retryable: false`. A client timeout is not retried. HTTP 429, and any error that sends `Retry-After`, is retried once, and only when that delay is 30 seconds or less. A longer `Retry-After` is not retried. Invalid input, an auth failure, a redirect, and a disabled channel are not retried. A retryable wallet inside a quick batch is retried once on its own; the wallets that already succeeded are not fetched again.
- The linked backend reads Solana mainnet through public RPCs and caches quick, profile, and trending responses for about 60 seconds, and preview responses for about 30 seconds. This Actor does not send those reads to a paid RPC, and it does not retry a rate limit into a burst.
- Each attempt waits up to 45 seconds.

## Run it from Apify, agents, and automations

Call this Actor as `falcon-sol/solana-wallet-intel` from the Apify API or from Python, JavaScript, Make, Zapier, or n8n. The [Apify MCP server](https://mcp.apify.com) exposes it as a tool to Claude, Cursor, and other MCP clients.

End users do not paste an API key. Apify bills the run. The Actor owner stores the backend credential as a secret environment variable on the Actor. Do not put that secret in the input, the dataset, or the git repository. If an upstream error echoes it, the Actor replaces it before writing the dataset or the OUTPUT record. `SWI_API_BASE` must be https with no embedded userinfo; redirects are not followed, so the partner key stays on that host.

The same falcon.sol service is also sold directly, without an Apify account, at [solana-wallet-intel-phi.vercel.app](https://solana-wallet-intel-phi.vercel.app). Direct calls pay USDC over x402 and use different prices from this Actor: wallet quick is $0.002, a quick batch of up to 10 is $0.015, wallet profile is $0.009, trending tokens are $0.0018, and funding-source clusters are $0.009 at `/wallet/funding`. Preview is free there too. This Actor does not call `/wallet/funding`. Profile `txLimit` on that service is an integer from 5 to 25 and defaults to 20. The live price list is the [OpenAPI document](https://solana-wallet-intel-phi.vercel.app/openapi.json), with discovery at [`/.well-known/x402`](https://solana-wallet-intel-phi.vercel.app/.well-known/x402) and an MCP server at `/mcp`.

## FAQ

**How many wallets can one run screen?** Up to 1,000 unique Solana addresses. Start another run for the rest.

**When am I charged?** Only after a successful quick wallet, a successful profile, or a successful trending snapshot. Preview is free. Errors are not charged. `onlySmartMoney` still charges successful checks that the filter hides.

**What does the maximum charge do?** The Actor does not start a paid lookup the remaining charge budget cannot cover. A lookup that fails is not charged, and a later wallet can use that room. It does not store paid rows it could not bill. When wallets are left unfetched, the run status stays successful and `OUTPUT.stoppedByBudget` is true.

**How fresh is the data?** Solana mainnet, with a short backend cache: about 60 seconds for quick, profile, and trending, and about 30 seconds for preview.

**Do I need an API key?** No. Apify handles billing for this Actor.

## Source

Open source: [github.com/ygfalcon/apify-solana-wallet-intel](https://github.com/ygfalcon/apify-solana-wallet-intel). Backend: [github.com/ygfalcon/solana-wallet-intel](https://github.com/ygfalcon/solana-wallet-intel).

---

**Built by [falcon.sol](https://x.com/ygfalcon)**: anon dev shipping pay-per-call data tools and x402 APIs for builders and agents. [X](https://x.com/ygfalcon) · [GitHub](https://github.com/ygfalcon) · [Apify](https://apify.com/falcon-sol)