# API Reference

All methods accept an optional trailing `RequestOptions` parameter for cache/retry/abort control.

Transport model: the SDK is JSON-RPC-native. Public namespace methods call Spectrum's `POST /v1` JSON-RPC 2.0 API and map those low-level method names to a typed TypeScript interface.

Historical reads: where the upstream API supports it, the SDK exposes an optional `blockHeight` parameter so you can pin balances, approvals, NFT metadata, contract code, and similar reads to a specific block.

Examples live in [docs/examples.md](./examples.md) and the runnable scripts under [examples/](../examples). Source API comments stay intentionally concise.

For example:

- `spectrum.core.getBlockHeight('ethereum')` sends JSON-RPC method `getBlockHeight`
- `spectrum.defi.getAvantisPrice('base', { vault: 'avUSDC' })` sends JSON-RPC method `getAvantisPrice`
- `spectrum.rpc.request('ethereum', ...)` sends JSON-RPC method `rpcProxy`

## Index

- [spectrum.core](#spectrumcore--blocks--gas)
- [spectrum.tokens](#spectrumtokens--balances--metadata)
- [spectrum.yields](#spectrumyields--defi-yields)
- [spectrum.prices](#spectrumprices--prices--token-discovery)
- [spectrum.defi](#spectrumdefi--defi-protocol-interactions)
- [spectrum.nfts](#spectrumnfts--nfts)
- [spectrum.ens](#spectrumens--ens-resolution)
- [spectrum.registry](#spectrumregistry--protocol-registry)
- [spectrum.jsonRpc](#spectrumjsonrpcrequest-options)
- [spectrum.rpc](#spectrumrpc--direct-json-rpc-proxy)
- [spectrum.contracts](#spectrumcontracts--smart-contract-reads)
- [spectrum.solana](#spectrumsolana--solana-specific-methods)
- [spectrum.cosmos](#spectrumcosmos--cosmos-staking--accounts)
- [spectrum.data](#spectrumdata--logs-transfers-receipts-portfolio--more)
- [spectrum.utils](#spectrumutils--health--utilities)
- [spectrum.parallel](#spectrumparallelpromises)
- [spectrum.setChain / getChain](#spectrumsetchainchain--spectrumgetchain)

---

## `spectrum.core` — Blocks & Gas

### `getBlockHeight(chain?, options?): Promise<BlockHeightData>`

```typescript
const result = await spectrum.core.getBlockHeight('ethereum');
// { chain: "ethereum", height: 19432156 }
```

### `getGasComparison(options?): Promise<GasComparisonData>`

```typescript
const gas = await spectrum.core.getGasComparison();
// { results: [{ chain: "ethereum", baseFeeGwei: 12.5, priorityFeeGwei: 1.2, estimatedTxCostUsd: 3.45 }], updatedAt: "..." }
```

### `getBlockTransactions(chain, blockNumber, options?): Promise<BlockTransactionsData>`

```typescript
const block = await spectrum.core.getBlockTransactions('ethereum', 19432156);
```

### `getBlockByNumber(items, options?): Promise<BatchBlockResultsData>`

Batch block lookup by height. Pass an array of `{ chain, block }` pairs (1–50
items). Mix any supported chains in the same batch — EVM, Solana, **Bitcoin**.

```typescript
// Single Bitcoin block
const btc = await spectrum.core.getBlockByNumber([{ chain: 'bitcoin', block: 900000 }]);
// { count: 1, results: [{ chain: 'bitcoin', height: 900000, block: { hash, height, confirmations, tx: [...], ... } }] }

// Cross-chain batch
const blocks = await spectrum.core.getBlockByNumber([
  { chain: 'ethereum', block: 21000000 },
  { chain: 'bitcoin', block: 900000 },
]);
```

Bitcoin block payloads mirror Bitcoin Core's `getblock` verbosity-1 response.
`confirmations = tip_height − block_height` is included and drifts every
~10 min as new blocks arrive; ignore it in equality checks.

### `getBlockByHash(items, options?): Promise<BatchBlockResultsData>`

Batch block lookup by hash. Same shape as `getBlockByNumber` but with a `hash`
field instead of `block`. EVM and Solana chains are routinely tested; Bitcoin
is supported by the backend but conventionally fetched via `getBlockByNumber`.

```typescript
const block = await spectrum.core.getBlockByHash([
  { chain: 'ethereum', hash: '0xf16da847a49abb4ac50ef7c83aa694bc2186b63a09e96b8f6525a461353e75f4' },
]);
```

### `getTransactionByHash(items, options?): Promise<BatchTransactionResultsData>`

Batch transaction lookup by hash (1–50 items). Each result contains the chain
slug, the requested hash, and the transaction body (or an `error` field).

```typescript
const txs = await spectrum.core.getTransactionByHash([
  { chain: 'ethereum', hash: '0x...' },
  { chain: 'polygon', hash: '0x...' },
]);
```

### `estimateGas(chain, params, options?): Promise<GasEstimateData>`

```typescript
const est = await spectrum.core.estimateGas('ethereum', { to: '0x...', value: '0x0' });
// { chain: "ethereum", gasEstimate: 21000, gasEstimateHex: "0x5208" }
```

### `simulateCall(chain, params, options?): Promise<SimulateCallData>`

Run a read-only contract call without submitting a tx. EVM chains return the hex
`eth_call` output (`{ chain, result }`); Starknet returns `{ chain, contractAddress,
entryPointSelector, calldata, result }`, mapping `to` → contract address, `data` →
entry-point selector, and `value` → a single calldata felt (for multi-felt calldata use
`starknet.call(...)`). Other chain types are rejected by the server.

```typescript
const sim = await spectrum.core.simulateCall('ethereum', {
  to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  data: '0x70a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045', // balanceOf(vitalik.eth)
});
// { chain: "ethereum", result: "0x000…0de0b6b3a7640000" }

const snSim = await spectrum.core.simulateCall('starknet', {
  to: '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d', // STRK
  data: '0x004c4fb1ab068f6039d5780c68dd0fa2f8742cceb3426d19667778ca7f3518a9', // decimals()
});
// { chain: "starknet", contractAddress: "0x0471…", entryPointSelector: "0x004c…", calldata: [], result: ["0x12"] }
```

---

## `spectrum.tokens` — Balances & Metadata

### `getBalance(chain, address, params?, options?): Promise<BalanceData>`

```typescript
const result = await spectrum.tokens.getBalance('ethereum', '0xd8dA6BF...');
// { chain: "ethereum", address: "0x...", token: "ETH", balance: "1.5" }

const historical = await spectrum.tokens.getBalance('ethereum', '0xd8dA6BF...', {
  blockHeight: 19834521,
});
```

### `getTokenBalance(chain, address, token, params?, options?): Promise<BalanceData>`

```typescript
const result = await spectrum.tokens.getTokenBalance('ethereum', '0xWallet...', '0xUSDC...');
```

### `getMetadata(chain, tokenAddress, params?, options?): Promise<TokenMetadataData>`

```typescript
const meta = await spectrum.tokens.getMetadata('ethereum', '0xA0b8...');
// { chain: "ethereum", address: "0xA0b8...", name: "USD Coin", symbol: "USDC", decimals: 6, totalSupply: "26000000000000000" }
```

---

## `spectrum.yields` — DeFi Yields

**Supported Protocols:**

| Type    | Protocols                                 |
| ------- | ----------------------------------------- |
| Lending | `aave`, `compound`, `morpho`, `hyperlend` |
| Vaults  | `beefy`, `yearn`, `pendle`, `hyperliquid` |
| Staking | `lido`, `rocketpool`, `jito`, `marinade`  |

### `getLending(filter?, options?): Promise<YieldsData>`

```typescript
const lending = await spectrum.yields.getLending({
  chain: 'ethereum',
  protocol: 'aave',
  pool: 'USDC',
});
```

### `getVaults(filter?, options?): Promise<YieldsData>`

Same signature and response as `getLending`.

### `getStaking(filter?, options?): Promise<BestYieldsData>`

Filters server response down to entries with `type === 'staking'`. The `chain` filter is applied client-side after fetch. Default `limit` is 100.

```typescript
const staking = await spectrum.yields.getStaking({ chain: 'ethereum', token: 'ETH' });
```

### `getBest(filter?, options?): Promise<BestYieldsData>`

```typescript
const best = await spectrum.yields.getBest({
  token: 'USDC',
  minTvl: 1_000_000,
  limit: 10,
  type: 'lending',
});
```

### `getBalance(filter, options?): Promise<PoolBalanceData>`

```typescript
const bal = await spectrum.yields.getBalance({
  chain: 'ethereum',
  protocol: 'aave',
  pool: 'USDC',
  address: '0x...',
});
```

### `getPrice(filter, options?): Promise<PoolPriceData>`

Supported protocols: aave, morpho, pendle, midas.

```typescript
const price = await spectrum.yields.getPrice({ chain: 'ethereum', protocol: 'aave', pool: 'USDC' });
```

### `getPendleImpliedApy(filter, options?): Promise<YieldsData>`

```typescript
const apy = await spectrum.yields.getPendleImpliedApy({
  chain: 'ethereum',
  pool: '0x...',
  address: '0x...',
});
```

### `getMorphoVaults(chain, options?): Promise<MorphoVaultsData>`

List every Morpho vault on a chain (one HTTP round-trip).

```typescript
const vaults = await spectrum.yields.getMorphoVaults('ethereum');
// { chain, count, vaults: [{ address, name, asset, ... }] }
```

### `getMorphoVaultData(chain, vaults, options?): Promise<MorphoVaultDataList>`

Detailed data (APY, TVL, fees, rewards) for up to 50 specific Morpho vaults.

```typescript
const data = await spectrum.yields.getMorphoVaultData('ethereum', ['0xVault1...', '0xVault2...']);
```

---

## `spectrum.prices` — Prices & Token Discovery

### `getPrice(symbol, options?): Promise<PriceData>`

```typescript
const eth = await spectrum.prices.getPrice('ETH');
// { symbol: "ETH", name: "Ethereum", priceUsd: 3456.78, priceEur: 3200.0, lastUpdated: "..." }
```

### `getPriceHistory(symbol, params?, options?): Promise<PriceHistoryData>`

`days` defaults to 30 (max 90), `currency` defaults to `'USD'`.

```typescript
const history = await spectrum.prices.getPriceHistory('BTC', { days: 7 });
// { symbol: "BTC", name: "Bitcoin", currency: "USD", prices: [{ date: "2026-03-01", price: 65000.0 }, ...] }
```

### `getTopPrices(params?, options?): Promise<TopPricesData>`

```typescript
const top = await spectrum.prices.getTopPrices({ limit: 10, currency: 'EUR' });
```

### `searchTokens(query, params?, options?): Promise<TokenSearchData>`

```typescript
const results = await spectrum.prices.searchTokens('uniswap', { limit: 5 });
```

### `getTokenAddresses(symbol, options?): Promise<TokenAddressesData>`

```typescript
const addrs = await spectrum.prices.getTokenAddresses('USDC');
// { symbol: "USDC", name: "USDC", priceUsd: 1.0, addresses: [{ chain: "ethereum", chainName: "Ethereum", address: "0xA0b8...", decimals: 6 }, ...] }
```

---

## `spectrum.defi` — DeFi Protocol Interactions

### Swap Quotes

```typescript
// Uniswap V3
const quote = await spectrum.defi.getUniswapV3Quote('ethereum', {
  tokenIn: '0xA0b8...',
  tokenOut: '0xC02a...',
  amount: '1.0',
  fee: 3000,
  blockHeight: 19834521,
});
// { chain, tokenIn, tokenOut, amountIn, amountOut, fee, gasEstimate }

// Uniswap V2
const v2 = await spectrum.defi.getUniswapV2Quote('ethereum', {
  tokenIn: '0xA0b8...',
  tokenOut: '0xC02a...',
  amount: '1.0',
});

// Uniswap V4
const v4 = await spectrum.defi.getUniswapV4Quote('ethereum', {
  tokenIn: '0xA0b8...',
  tokenOut: '0xC02a...',
  amount: '1.0',
  fee: 3000,
  tickSpacing: 60,
  blockHeight: 19834521,
});

// Jupiter (Solana)
const jup = await spectrum.defi.getJupiterQuote({
  inputMint: 'So11...',
  outputMint: 'EPjF...',
  amount: '1000000000',
  slippageBps: 50,
});
const jupPrice = await spectrum.defi.getJupiterPrice({
  inputMint: 'So11...',
  outputMint: 'EPjF...',
});
```

### Protocol Positions

```typescript
const pos = await spectrum.defi.getPosition('ethereum', 'aave-v3', '0xAddress...');
// Supported: aave-v3, aave-v2, compound-v3, compound-v2, morpho-blue, lido
```

### Avantis

```typescript
const price = await spectrum.defi.getAvantisPrice('base', { vault: 'avUSDC' });
// { chain, protocol, vault, vaultAddress, depositPrice: { USD }, redemptionPrice: { USD }, decimals }
```

### Curve

```typescript
const pools = await spectrum.defi.getCurvePools('ethereum');
const markets = await spectrum.defi.getCurveLlamaLendMarkets('ethereum');
const pos = await spectrum.defi.getCurveLlamaLendPosition('ethereum', '0xAddr...');
```

### Pendle

```typescript
const info = await spectrum.defi.getPendleInfo('ethereum');
```

### Cross-Protocol

```typescript
const summary = await spectrum.defi.getSummary('ethereum', '0xAddress...');
const approvals = await spectrum.defi.getApprovals('ethereum', '0xAddress...', {
  blockHeight: 19834521,
});
const revokeTx = await spectrum.defi.getRevokeTransaction('ethereum', '0xAddress...', {
  token: '0xUSDC...',
  spender: '0xRouter...',
});
```

### Perps / Funding Rates

```typescript
const rates = await spectrum.defi.getAllFundingRates();
const hlFunding = await spectrum.defi.getHyperliquidFunding({ coin: 'ETH' });
const dydxFunding = await spectrum.defi.getDydxFunding({ ticker: 'ETH-USD' });
```

---

## `spectrum.nfts` — NFTs

```typescript
const collection = await spectrum.nfts.getCollection('ethereum', '0xBC4CA...', {
  blockHeight: 19834521,
});
const balance = await spectrum.nfts.getBalance('ethereum', '0xBC4CA...', '0xOwner...', {
  blockHeight: 19834521,
});
const tokens = await spectrum.nfts.getOwnedTokens('ethereum', '0xBC4CA...', '0xOwner...');
const batch = await spectrum.nfts.getBatchBalance('ethereum', '0xContract...', {
  addresses: ['0xAddr1...'],
  tokenIds: ['1'],
});
const erc1155bal = await spectrum.nfts.getTokenBalance(
  'ethereum',
  '0xContract...',
  '0xOwner...',
  '42',
);
const owner = await spectrum.nfts.getTokenOwner('ethereum', '0xBC4CA...', '42');
const meta = await spectrum.nfts.getTokenMetadata('ethereum', '0xBC4CA...', '42', {
  blockHeight: 19834521,
});
```

---

## `spectrum.ens` — ENS Resolution

```typescript
const resolved = await spectrum.ens.resolve('vitalik.eth');
// { name: "vitalik.eth", address: "0xd8dA6BF...", avatar?: "..." }

const reverse = await spectrum.ens.reverse('0xd8dA6BF...');
// { address: "0xd8dA6BF...", name: "vitalik.eth" }
```

---

## `spectrum.registry` — Protocol Registry

```typescript
const protocols = await spectrum.registry.getProtocols({ category: 'lending' });
const aave = await spectrum.registry.getProtocol('aave-v3');
const contracts = await spectrum.registry.getProtocolContracts('aave-v3', { chain: 'ethereum' });
const addr = await spectrum.registry.getAddress('aave-v3', 'pool', 'ethereum');
const categories = await spectrum.registry.getCategories();
const chains = await spectrum.registry.getChains();
```

---

## `spectrum.jsonRpc(request, options?)`

Send a raw JSON-RPC request or request array directly to Spectrum's unified `POST /v1` handler.

```typescript
const single = await spectrum.jsonRpc({
  jsonrpc: '2.0',
  method: 'getBlockHeight',
  params: { chain: 'ethereum' },
  id: 1,
});

const batch = await spectrum.jsonRpc([
  { jsonrpc: '2.0', method: 'getBlockHeight', params: { chain: 'ethereum' }, id: 1 },
  {
    jsonrpc: '2.0',
    method: 'getBalance',
    params: { chain: 'ethereum', address: '0x...', blockHeight: 19834521 },
    id: 2,
  },
]);
```

---

## `spectrum.rpc` — Direct JSON-RPC Proxy

This namespace proxies raw node JSON-RPC through Spectrum's `rpcProxy` method. Use it when you want node-level methods such as `eth_blockNumber` or `eth_chainId` instead of the higher-level typed SDK helpers.

```typescript
// Send a single RPC call
const blockNum = await spectrum.rpc.send<string>('ethereum', 'eth_blockNumber');

// Full request/response
const res = await spectrum.rpc.request('ethereum', { method: 'eth_chainId', params: [] });

// Batch RPC
const results = await spectrum.rpc.requestBatch('ethereum', [
  { method: 'eth_blockNumber', params: [] },
  { method: 'eth_chainId', params: [] },
]);
```

---

## `spectrum.contracts` — Smart Contract Reads

```typescript
// Read a single function
const decimals = await spectrum.contracts.readContract('ethereum', {
  address: '0xUSDC...',
  abi: [{ name: 'decimals', type: 'function', inputs: [], outputs: [{ type: 'uint8' }] }],
  functionName: 'decimals',
});

// Multicall (batch multiple reads)
const results = await spectrum.contracts.multicall('ethereum', {
  calls: [
    { address: '0xUSDC...', abi: [...], functionName: 'decimals' },
    { address: '0xUSDC...', abi: [...], functionName: 'symbol' },
  ],
});

// Simulate contract call (returns result + gas estimate)
const sim = await spectrum.contracts.simulateContract('ethereum', {
  address: '0xUSDC...', abi: [...], functionName: 'decimals',
});
// { result: 6n, gasUsed: "..." }

// Check if address is a contract
const code = await spectrum.contracts.getCode('ethereum', '0xUSDC...');
const historicalCode = await spectrum.contracts.getCode('ethereum', '0xUSDC...', { blockHeight: 19834521 });
// { chain, address, isContract: true, bytecodeSize: 12345, bytecode: "0x..." }
```

---

## `spectrum.solana` — Solana-Specific Methods

These helpers also go through Spectrum's JSON-RPC surface. Solana node methods are proxied through the same `rpcProxy` transport and wrapped in Solana-friendly convenience methods.

```typescript
const slot = await spectrum.solana.getSlot();
const height = await spectrum.solana.getBlockHeight();
const balance = await spectrum.solana.getBalance('9WzDXw...');
const lamports = await spectrum.solana.getBalanceLamports('9WzDXw...');
const account = await spectrum.solana.getAccountInfo('9WzDXw...');
const tokens = await spectrum.solana.getTokenAccountsByOwner('9WzDXw...', {
  programId: 'Token...',
});
const tx = await spectrum.solana.getTransaction('5abc...');
const sigs = await spectrum.solana.getSignaturesForAddress('9WzDXw...', { limit: 10 });
const bh = await spectrum.solana.getLatestBlockhash();
const rent = await spectrum.solana.getMinimumBalanceForRentExemption(128);
const valid = await spectrum.solana.isBlockhashValid(bh.blockhash);
const epoch = await spectrum.solana.getEpochInfo();
const supply = await spectrum.solana.getTokenSupply('EPjF...');

// Raw RPC
const res = await spectrum.solana.request({ method: 'getHealth' });
```

---

## `spectrum.cosmos` — Cosmos Staking & Accounts

REST-backed auth/staking helpers for Cosmos SDK chains (`cosmoshub`, `osmosis`, `axelar`, `noble`, `agoric`). `chain` is optional and falls back to the SDK default chain (`setChain` / `defaultChain` config), like the EVM namespaces — the resolved chain is validated against the Cosmos slugs, so a non-Cosmos default throws `ValidationError`. Cosmos token balances, denom supply, token metadata, block transactions, and transaction lookups reuse the cross-chain `tokens.*` / `core.*` methods with a Cosmos chain slug.

```typescript
const account = await spectrum.cosmos.getAccount('cosmoshub', 'cosmos1...');
const delegations = await spectrum.cosmos.getDelegations('cosmoshub', 'cosmos1...');
const unbonding = await spectrum.cosmos.getUnbondingDelegations('cosmoshub', 'cosmos1...');
const rewards = await spectrum.cosmos.getStakingRewards('cosmoshub', 'cosmos1...');
const validators = await spectrum.cosmos.getValidators('cosmoshub');
const validator = await spectrum.cosmos.getValidator('cosmoshub', 'cosmosvaloper1...');
const pool = await spectrum.cosmos.getStakingPool('cosmoshub');
const supply = await spectrum.cosmos.getDenomSupply('cosmoshub', 'uatom');
const blockResults = await spectrum.cosmos.getBlockResults('cosmoshub', 19834521);
```

`getStakingRewards` is supported on `cosmoshub`, `osmosis`, `axelar`, and `agoric`.

---

## `spectrum.data` — Logs, Transfers, Receipts, Portfolio & More

```typescript
const logs = await spectrum.data.getLogs('ethereum', {
  address: '0xContract...',
  topic0: '0xddf2...',
  fromBlock: '19000000',
  toBlock: 'latest',
});

const transfers = await spectrum.data.getTransfers('ethereum', '0xAddr...', {
  fromBlock: '19000000',
  toBlock: 'latest',
  cursor: undefined,
});
const receipt = await spectrum.data.getReceipt('ethereum', '0xTxHash...');
const portfolio = await spectrum.data.getPortfolio('ethereum', '0xAddr...');
const historicalPortfolio = await spectrum.data.getPortfolio('ethereum', '0xAddr...', {
  blockHeight: 19834521,
});
const health = await spectrum.data.getChainHealth('ethereum');
const trace = await spectrum.data.traceTransaction('ethereum', '0xTxHash...');

const allowance = await spectrum.data.getAllowance('ethereum', '0xUSDC...', {
  owner: '0xOwner...',
  spender: '0xRouter...',
  blockHeight: 19834521,
});
// { chain, token, symbol, owner, spender, allowance, allowanceRaw, isUnlimited }
```

---

## `spectrum.networkCalendar` — Releases & Upgrades

Lists approved network calendar entries. Optional filters: `month` (UTC `YYYY-MM`), `day` (UTC `YYYY-MM-DD` or `"today"`), and `chain` (network slug). Omit `chain` for all networks. When both `month` and `day` are set, `day` must fall within `month`; if `day` is set it takes precedence over the month range.

```typescript
const calendar = await spectrum.networkCalendar.getNetworkCalendar({ month: '2026-08', chain: 'ethereum' });
// { entries: [{ id, chain, date, description, chainType, eventType }, ...] }

const today = await spectrum.networkCalendar.getNetworkCalendar({ day: 'today' });
```

---

## `spectrum.utils` — Health & Utilities

```typescript
const health = await spectrum.utils.health();
// { status: "ok", timestamp: "..." }
```

---

## `spectrum.parallel(...promises)`

Client-side `Promise.all` wrapper. **Fail-fast**: if any promise rejects, the whole call rejects and successful results from the others are discarded. Use `Promise.allSettled` directly if you need partial results.

```typescript
const [ethBlock, gas, staking] = await spectrum.parallel(
  spectrum.core.getBlockHeight('ethereum'),
  spectrum.core.getGasComparison(),
  spectrum.yields.getStaking(),
);
```

## `spectrum.setChain(chain)` / `spectrum.getChain()`

Change or read the SDK's default chain at runtime. `setChain` overrides the `defaultChain` option for all subsequent calls; `getChain` returns the currently set value (or `undefined`).

```typescript
spectrum.setChain('arbitrum');
const balance = await spectrum.tokens.getBalance(undefined, '0xAddr...');
spectrum.getChain(); // 'arbitrum'
```

## `spectrum.clearCache()`

Clear all cached responses.
