# Steakhouse SDK > Type-safe SDK for Steakhouse-curated DeFi vaults ## Getting Started :::info You'll need a Steakhouse API key. [Reach out to Steakhouse](mailto\:chefs@steakhouse.financial) to get one. ::: ### Installation :::code-group ```bash [pnpm] pnpm add @whisk/steakhouse ``` ```bash [npm] npm install @whisk/steakhouse ``` ```bash [yarn] yarn add @whisk/steakhouse ``` ::: ### Quick Start ```ts twoslash import { SteakhouseClient, getVaults, getVault, getStats } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: process.env.STEAKHOUSE_API_KEY!, }) // List Steakhouse-curated vaults const vaults = await getVaults(client) // Get vault details const vault = await getVault(client, { chainId: 1, vaultAddress: "0x...", }) // Get stats & TVL const stats = await getStats(client) ``` ### Next Steps * [Queries](/queries) - Full query API reference * [Direct GraphQL](/graphql) - Custom queries with full type safety :::info React hooks are available via `@whisk/steakhouse/react` but are not yet stable. See the [source](https://github.com/papercliplabs/whisk-sdk/tree/main/packages/steakhouse/src/react) for usage. ::: ### Requirements | Requirement | Version | | ----------- | ------- | | Node.js | >= 18 | | TypeScript | >= 5.0 | `@whisk/steakhouse` is an **ESM-only** package. ## Direct GraphQL Queries Write your own GraphQL queries against the Whisk API with full type safety. Use this when the built-in [query functions](/queries) don't cover your use case. ### Playground The [Whisk GraphQL playground](https://api-v2.whisk.so/graphql) is the best way to explore the schema and test queries before writing code. This is the production API — use your production API key here. :::info The Whisk API is currently read-only. Mutations are not supported. ::: :::steps #### Add your authorization header In the `Headers` section of the playground: ```json [Headers] { "Authorization": "Bearer " } ``` #### Write and test your query Try running a query like this: ```graphql { steakhouseStats { uniqueDepositors tvl { current { totalUsd byChain { chain { name } tvlUsd } } } } } ``` ::: ### Using in Your App To write custom queries, install `@whisk/graphql` alongside `@whisk/steakhouse`: :::code-group ```bash [pnpm] pnpm add @whisk/graphql ``` ```bash [npm] npm install @whisk/graphql ``` ```bash [yarn] yarn add @whisk/graphql ``` ::: The `graphql` function from `@whisk/graphql` gives you a type-safe tagged template for writing queries. Pair it with `SteakhouseClient.query()` to execute them. #### 1. Write a query ```ts import { graphql } from "@whisk/graphql" const myQuery = graphql(` query MyCustomQuery { steakhouseStats { uniqueDepositors tvl { current { totalUsd byChain { chain { name id } tvlUsd } } } } } `) ``` The result type is **fully inferred** from the schema — no code generation step needed. #### 2. Execute the query ```ts import { SteakhouseClient } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: process.env.STEAKHOUSE_API_KEY!, }) const data = await client.query(myQuery, {}) // data.steakhouseStats.uniqueDepositors is typed as number | null // data.steakhouseStats.tvl.current.byChain is typed as an array ``` ### Using Variables ```ts import { graphql } from "@whisk/graphql" const vaultQuery = graphql(` query GetVaults($chainIds: [Int!]!) { morphoVaults(where: { chainId_in: $chainIds, whitelisted: true }, limit: 10) { items { name totalSupplied { formatted usd } } } } `) const data = await client.query(vaultQuery, { chainIds: [1] }) // Variables are type-checked too ``` ### Editor IntelliSense By default, you get full **type inference** on query results (return types, variable types). To also get **autocomplete inside the `graphql()` template literal** — field name suggestions, inline validation, and documentation — set up the gql.tada TypeScript plugin. :::steps #### Add the plugin to your `tsconfig.json` ```json { "compilerOptions": { "plugins": [ { "name": "gql.tada/ts-plugin", "schema": "node_modules/@whisk/graphql/src/generated/schema.graphql" } ] } } ``` #### Use the workspace TypeScript version The plugin only works with the workspace TypeScript, not VS Code's built-in version. In VS Code: `Cmd+Shift+P` (or `Ctrl+Shift+P`) → **TypeScript: Select TypeScript Version** → **Use Workspace Version**. To make this automatic for your team, add to `.vscode/settings.json`: ```json { "typescript.tsdk": "node_modules/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true } ``` #### Restart the TypeScript server `Cmd+Shift+P` → **TypeScript: Restart TS Server** ::: You should now get full autocomplete and error checking as you write queries. ## Queries Fully typed query functions for Steakhouse data. All examples below assume a client is already created: ```ts import { SteakhouseClient } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: process.env.STEAKHOUSE_API_KEY!, }) ``` ### getVaults Fetch all Steakhouse-curated vaults. Designed for vault discovery and table views. ```ts twoslash import { SteakhouseClient, getVaults } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const vaults = await getVaults(client) // [!code focus] for (const vault of vaults) { vault.name vault.address vault.symbol vault.decimals vault.icon vault.priceUsd vault.chain vault.asset vault.totalAssets vault.apyInstant vault.apy1d vault.apy7d vault.apy30d vault.riskAssessment vault.__typename vault.strategy vault.isListed } ``` ### getVault Fetch detailed data for a single vault. Includes all summary fields plus protocol-specific data. The vault must be in the Steakhouse registry (returned by `getVaults`) or queried as a Box vault with `isBox: true`. :::warning Throws an error if the vault is not in the Steakhouse registry and `isBox` is not set to `true`, or if the vault is not found by the API. ::: ```ts twoslash import { SteakhouseClient, getVault } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const vault = await getVault(client, { // [!code focus] chainId: 1, // [!code focus] vaultAddress: "0x...", // [!code focus] }) // [!code focus] // Common fields (same as getVaults, plus description) vault.name vault.address vault.symbol vault.decimals vault.icon vault.priceUsd vault.chain vault.asset vault.totalAssets vault.apyInstant vault.apy1d vault.apy7d vault.apy30d vault.riskAssessment vault.__typename vault.strategy vault.description vault.isListed ``` #### Protocol-specific fields Narrow on `__typename` to access protocol-specific fields. **Morpho V1**: ```ts twoslash import { SteakhouseClient, getVault } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const vault = await getVault(client, { chainId: 1, vaultAddress: "0x..." }) // ---cut--- if (vault.__typename === "MorphoVault") { vault.deploymentTimestamp vault.performanceFeeV1 vault.curatorAddress vault.guardianAddress vault.totalLiquidity vault.allocations } ``` **Morpho V2**: ```ts twoslash import { SteakhouseClient, getVault } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const vault = await getVault(client, { chainId: 1, vaultAddress: "0x..." }) // ---cut--- if (vault.__typename === "MorphoVaultV2") { vault.deploymentTimestamp vault.performanceFee vault.managementFee vault.nav vault.liquidityAssets vault.idleAssets vault.allocations } ``` **Box**: ```ts twoslash import { SteakhouseClient, getVault } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const vault = await getVault(client, { chainId: 1, vaultAddress: "0x..." }) // ---cut--- if (vault.__typename === "BoxVault") { vault.leverage vault.allocations vault.fundingModules } ``` #### Box vaults Box vaults are not in the Steakhouse registry. Pass `isBox: true` to query them directly. ```ts twoslash import { SteakhouseClient, getVault } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const vault = await getVault(client, { // [!code focus] chainId: 1, // [!code focus] vaultAddress: "0x...", // [!code focus] isBox: true, // [!code focus] }) // [!code focus] ``` ### getVaultHistory Fetch daily and weekly snapshots with APY and total supplied. :::info Historical data is only available for Morpho vaults (V1 and V2). For non-Morpho vaults or vaults not in the Steakhouse registry, returns `{ daily: null, weekly: null }`. ::: ```ts twoslash import { SteakhouseClient, getVaultHistory } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const historical = await getVaultHistory(client, { // [!code focus] chainId: 1, // [!code focus] vaultAddress: "0x...", // [!code focus] }) // [!code focus] historical.daily historical.weekly ``` ### getStats Fetch Steakhouse aggregate stats. ```ts twoslash import { SteakhouseClient, getStats } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const stats = await getStats(client) // [!code focus] stats.uniqueDepositors stats.tvl.current.totalUsd stats.tvl.current.byChain stats.tvl.current.byProtocol stats.tvl.current.byAssetCategory ``` #### With historical TVL ```ts twoslash import { SteakhouseClient, getStats } from "@whisk/steakhouse" const client = new SteakhouseClient({ apiKey: "your-api-key" }) const stats = await getStats(client, { includeHistorical: true }) // [!code focus] stats.tvl.historical // daily snapshots (last 365 days) ```