# Wallet API — Wallet Intelligence & Investigation

## What the Wallet API Covers

The Wallet API provides structured REST endpoints for comprehensive wallet intelligence: identity resolution, funding source tracing, balances with USD pricing, transaction history, and transfer tracking. It is currently in Beta.

- **Identity database**: Powered by Orb, tags 5,100+ accounts and 1,900+ programs across 40+ categories (exchanges, DeFi protocols, market makers, KOLs, malicious actors)
- **Unique funding source tracking**: Only API that reveals who originally funded any wallet — critical for compliance, sybil detection, and attribution
- **Batch identity lookup**: Process up to 100 addresses per request
- **USD pricing**: Token balances include USD values for top 10K tokens (hourly updates via DAS)
- **100 credits per request** (all endpoints)
- Base URL: `https://api.helius.xyz`
- Auth: `?api-key=YOUR_KEY` or header `X-Api-Key: YOUR_KEY`

## MCP Tools

All Wallet API endpoints have direct MCP tools. ALWAYS use these instead of generating raw API calls:

| MCP Tool | Endpoint | What It Does |
|---|---|---|
| `getWalletIdentity` | `GET /v1/wallet/{wallet}/identity` | Identify known wallets (exchanges, protocols, institutions) |
| `batchWalletIdentity` | `POST /v1/wallet/batch-identity` | Bulk lookup up to 100 addresses in one request |
| `getWalletBalances` | `GET /v1/wallet/{wallet}/balances` | Token + NFT balances with USD values, sorted by value |
| `getWalletHistory` | `GET /v1/wallet/{wallet}/history` | Transaction history with balance changes per tx |
| `getWalletTransfers` | `GET /v1/wallet/{wallet}/transfers` | Token transfers with direction (in/out) and counterparty |
| `getWalletFundedBy` | `GET /v1/wallet/{wallet}/funded-by` | Original funding source (first incoming SOL transfer) |

When the user asks to investigate a wallet, identify an address, check balances, or trace funds — use these MCP tools directly. Only generate raw API code when the user is building an application that needs to call these endpoints programmatically.

## Choosing the Right Tool

| You want to... | Use this |
|---|---|
| Check if a wallet is a known entity | `getWalletIdentity` |
| Label many addresses at once | `batchWalletIdentity` (up to 100) |
| See token holdings with USD values | `getWalletBalances` |
| View recent transaction activity | `getWalletHistory` |
| Track incoming/outgoing transfers | `getWalletTransfers` |
| Find who funded a wallet | `getWalletFundedBy` |
| Get fungible token list (cheaper) | `getTokenBalances` (DAS, 10 credits) — use when you don't need USD pricing or NFTs |
| Get full portfolio with NFTs | `getWalletBalances` with `showNfts: true` + DAS `getAssetsByOwner` for full NFT details |

## Identity Resolution

The identity endpoint identifies known wallets powered by Orb's tagging. Returns 404 for unknown wallets — this is normal, not an error.

**Account tag types**: Airdrop, Authority, Bridge, Casino & Gambling, DAO, DeFi, DePIN, Centralized Exchange, Exploiter/Hackers/Scams, Fees, Fundraise, Game, Governance, Hacker, Jito, Key Opinion Leader, Market Maker, Memecoin, Multisig, NFT, Oracle, Payments, Proprietary AMM, Restaking, Rugger, Scammer, Spam, Stake Pool, System, Tools, Trading App/Bot, Trading Firm, Transaction Sending, Treasury, Validator, Vault

**Program categories**: Aggregator, Airdrop, Bridge, Compression, DeFi, DePIN, Game/Casino, Governance, Infrastructure, Launchpad, Borrow Lend, Native, NFT, Oracle, Perpetuals, Prediction Market, Privacy, Proprietary AMM, RWA, Spam, Staking, Swap, Tools

**Covers**: Binance, Coinbase, Kraken, OKX, Bybit, Jupiter, Raydium, Marinade, Jito, Kamino, Jump Trading, Wintermute, notable KOLs, bridges, validators, treasuries, stake pools, and known exploiters/scammers.

### When to use batch vs single

- Investigating one wallet: `getWalletIdentity`
- Enriching a transaction list with counterparty names: `batchWalletIdentity` (collect all unique addresses, batch in chunks of 100)
- Building a UI that shows human-readable names: `batchWalletIdentity`

## Funding Source Tracking

**Unique to Helius.** The `getWalletFundedBy` tool reveals who originally funded any wallet by analyzing its first incoming SOL transfer. Returns 404 if no funding found.

Response includes:
- `funder`: address that funded the wallet
- `funderName`: human-readable name if known (e.g., "Coinbase 2")
- `funderType`: entity type (e.g., "exchange")
- `amount`: initial funding amount in SOL
- `timestamp`, `date`, `signature`, `explorerUrl`

**Use for**:
- **Sybil detection**: Group wallets by same funder address — same funder = likely related
- **Airdrop abuse**: Flag farming accounts created recently from unknown sources
- **Compliance**: Determine if wallets originated from exchanges (retail) vs unknown sources
- **Attribution**: Track user acquisition (e.g., Binance -> your dApp)
- **Risk scoring**: Assign trust levels based on funder reputation

## Wallet Balances

`getWalletBalances` returns all token holdings sorted by USD value (descending).

**Parameters**:
- `page` (default: 1) — pagination starts at 1
- `limit` (1-100, default: 100)
- `showNfts` (default: false) — include NFTs (max 100, first page only)
- `showZeroBalance` (default: false)
- `showNative` (default: true) — include native SOL

**Pricing notes**: USD values sourced from DAS, updated hourly, covers top 10K tokens. `pricePerToken` and `usdValue` may be `null` for unlisted tokens. These are estimates, not real-time market rates.

## Transaction History

`getWalletHistory` returns parsed, human-readable transactions with balance changes.

**Parameters**:
- `limit` (1-100, default: 100)
- `before` — pagination cursor (pass `nextCursor` from previous response)
- `after` — forward pagination cursor
- `type` — filter: `SWAP`, `TRANSFER`, `BID`, `NFT_SALE`, `NFT_BID`, `NFT_LISTING`, `NFT_MINT`, `NFT_CANCEL_LISTING`, `TOKEN_MINT`, `BURN`, `COMPRESSED_NFT_MINT`, `COMPRESSED_NFT_TRANSFER`, `COMPRESSED_NFT_BURN`
- `tokenAccounts` — controls token account inclusion:
  - `balanceChanged` (default, recommended): includes transactions that changed token balances, filters spam
  - `none`: only direct wallet interactions
  - `all`: everything including spam

## Token Transfers

`getWalletTransfers` returns transfer-only activity with direction and counterparty.

**Parameters**:
- `limit` (1-50, default: 50)
- `cursor` — pagination cursor

Each transfer includes: `direction` (in/out), `counterparty`, `mint`, `symbol`, `amount`, `timestamp`, `signature`.

## Common Patterns

### Portfolio View

Use MCP tools directly for investigation:
1. `getWalletBalances` — current holdings with USD values
2. `getWalletHistory` — recent activity
3. `getWalletIdentity` — check if the wallet is a known entity

For building a portfolio app, call `GET /v1/wallet/{address}/balances?api-key=KEY&showNative=true`. Paginate via `page` param — loop until `pagination.hasMore` is false.

### Wallet Investigation

Three-step pattern: call identity (handle 404 → unknown), funded-by (handle 404 → no funding data), then history with a limit.

```typescript
const identity = await fetch(`${BASE}/v1/wallet/${address}/identity?api-key=${KEY}`).then(r => r.ok ? r.json() : null);
const funding = await fetch(`${BASE}/v1/wallet/${address}/funded-by?api-key=${KEY}`).then(r => r.ok ? r.json() : null);
const { data: history } = await fetch(`${BASE}/v1/wallet/${address}/history?api-key=${KEY}&limit=20`).then(r => r.json());
```

### Sybil Detection

Call `getWalletFundedBy` for each address, group results by `funder` field. Clusters where 2+ wallets share the same funder are suspicious. Use `Promise.all` for parallel fetches.

### Batch Enrich Transactions with Names

Collect unique counterparty addresses, then call `batchWalletIdentity` in chunks of 100 (`POST /v1/wallet/batch-identity`). Build a `Map<address, name>` from the results.

### Risk Assessment

Combine `getWalletIdentity` + `getWalletFundedBy` in parallel. Score based on:
- Known entity → lower risk. Malicious tags (`Exploiter`, `Hacker`, `Scammer`, `Rugger`) → highest risk.
- Exchange-funded → lower risk. Unknown funder + wallet age < 7 days → higher risk.

## SDK Usage

```typescript
// TypeScript — all methods take { wallet } object param
const identity = await helius.wallet.getIdentity({ wallet: 'ADDRESS' });
const balances = await helius.wallet.getBalances({ wallet: 'ADDRESS' });
const history = await helius.wallet.getHistory({ wallet: 'ADDRESS' });
const transfers = await helius.wallet.getTransfers({ wallet: 'ADDRESS' });
const funding = await helius.wallet.getFundedBy({ wallet: 'ADDRESS' });
```

```rust
// Rust
let identity = helius.wallet().get_identity("ADDRESS").await?;
let balances = helius.wallet().get_balances("ADDRESS").await?;
```

## Error Handling

**Important**: 404 on identity and funded-by endpoints is expected behavior for unknown wallets, not an error. It means the wallet isn't in the Orb database. Always handle it gracefully (return `null`, not throw).

## Best Practices

- Use MCP tools (`getWalletIdentity`, `getWalletBalances`, etc.) for direct investigation — they call the API and return formatted results
- Use `batchWalletIdentity` for multiple addresses — 100x faster than individual lookups
- Cache identity and funding data — it rarely changes
- Handle 404s gracefully on identity/funded-by endpoints — most wallets are not known entities
- Use `tokenAccounts: "balanceChanged"` (default) for history to filter spam
- Combine identity + funding for complete wallet profiles
- Use `getWalletBalances` when you need USD pricing; use DAS `getTokenBalances` when you don't (cheaper)
- For portfolio UIs, display human-readable names from identity lookups instead of raw addresses

## Common Mistakes

- Treating 404 on identity/funded-by as an error — it just means the wallet isn't in the database
- Using individual `getWalletIdentity` calls in a loop instead of `batchWalletIdentity`
- Expecting real-time USD pricing — prices update hourly and cover only top 10K tokens
- Using `tokenAccounts: "all"` for history — includes spam; use `"balanceChanged"` instead
- Confusing `getWalletBalances` (Wallet API, 100 credits, USD pricing) with `getTokenBalances` (DAS, 10 credits, no pricing)
- Not paginating balances — wallets with 100+ tokens need multiple pages
