Repository navigation
Expand file tree
/
Copy pathllms-full.txt
More file actions
400 lines (294 loc) · 16.3 KB
/
Copy pathllms-full.txt
File metadata and controls
400 lines (294 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
# Actions SDK Integration Guide
This file is an integration playbook for AI coding agents helping developers add Actions SDK to their application. Actions SDK is an open source TypeScript toolkit by Optimism for integrating DeFi (lending, borrowing, swaps, payments) into apps.
> **For agents**: This guide uses concrete examples but the SDK evolves. When you encounter references to specific providers, assets, or chains, always verify against the actual codebase to discover what is currently supported. Source-of-truth locations are called out in each section.
## Overview
Actions SDK follows a provider pattern. Developers configure:
1. **A wallet provider** — an embedded wallet (Privy, Turnkey, Dynamic, etc.) that handles key management and signing
2. **DeFi action providers** — protocols for lending (Morpho, Aave), borrowing, swaps, etc.
3. **Chains** — which EVM networks to support
4. **Assets** — which tokens to allow or block
Then they call `createActions(config)` to get an `actions` instance, convert a user's wallet into an Actions wallet, and call DeFi operations on it.
## Step 1: Detect Project Environment
Before starting, determine the developer's environment and existing integrations.
**Check the environment** by reading the project's `package.json`:
- If `react`, `next`, `remix`, or similar React framework is in dependencies → **React/frontend** environment. Use `@eth-optimism/actions-sdk/react` imports.
- If it's a Node.js backend (hono, express, fastify, etc.) → **Node/backend** environment. Use `@eth-optimism/actions-sdk/node` imports (or the default import which resolves to node).
- The available wallet providers differ by environment. Check the SDK's `peerDependencies` in `node_modules/@eth-optimism/actions-sdk/package.json` to see which provider packages exist for each environment.
**Check for existing wallet provider integrations** by scanning the project's `package.json` dependencies for:
- `@privy-io/react-auth` or `@privy-io/node` → Privy is already integrated
- `@turnkey/*` packages → Turnkey is already integrated
- `@dynamic-labs/*` packages → Dynamic is already integrated (React only)
If a wallet provider is already present, use it. If not, see Step 3.
## Step 2: Install the SDK
```bash
npm install @eth-optimism/actions-sdk
```
The SDK has peer dependencies for whichever wallet provider the developer chooses. These are optional — only the selected provider's packages need to be installed.
## Step 3: Choose a Wallet Provider
The wallet provider is the biggest integration decision because it involves third-party account setup, authentication flows, and potentially significant frontend/backend work.
**If the developer already has a wallet provider** (detected in Step 1): skip this step and use their existing integration.
**If no wallet provider exists**: Present the available options and help the developer choose, but do not block the rest of the setup. The wallet provider can be integrated in parallel.
> **For agents with interactive UX** (e.g. choice selection): present the wallet provider options as a choice. Otherwise, list them and ask which the developer prefers.
Available wallet providers (verify the current list by checking the SDK's `peerDependencies`):
| Provider | Frontend (React) | Backend (Node) | Setup Guide |
| -------- | :--------------: | :------------: | ---------------------------- |
| Privy | Yes | Yes | https://docs.privy.io |
| Turnkey | Yes | Yes | https://docs.turnkey.com |
| Dynamic | Yes | No | https://www.dynamic.xyz/docs |
Each provider requires its own account setup, API keys, and SDK installation. Direct the developer to the provider's documentation for initial setup, then return here to wire it into Actions.
**Important**: The developer does not need to finish wallet provider setup before continuing. You can scaffold the full Actions config with a placeholder and fill in the wallet section once the provider is ready.
## Step 4: Create the Actions Config File
Create a config file (e.g. `actions.ts`) that centralizes the Actions SDK configuration. This is the main integration point.
### 4a: Wallet Config
The wallet config declares which hosted wallet provider to use and enables smart wallets. Here's an example using Privy on a React frontend:
```typescript
const walletConfig = {
hostedWalletConfig: {
provider: {
type: 'privy' as const,
},
},
smartWalletConfig: {
provider: {
type: 'default' as const,
},
},
}
```
Each provider has different config requirements depending on the environment (React vs Node). For the full setup code for each provider, see the [Integrating Wallets](https://docs.optimism.io/app-developers/reference/actions/integrating-wallets) guide.
> **Source of truth for provider config shapes**: Check the SDK source at `src/wallet/node/providers/hosted/types/` (Node) or `src/wallet/react/providers/hosted/types/` (React) for the exact config each provider expects.
### 4b: DeFi Provider Config (Lend, Borrow, Swap, etc.)
The SDK uses a modular provider pattern for DeFi actions. Each action type (lend, borrow, swap) can have one or more protocol providers. **Configure DeFi providers first** — the market selections will inform which chains and assets need to be configured in the following steps.
> **For agents**: Ask the developer which DeFi actions and providers they want to support. Check `src/lend/` for lending providers and look for other action directories (e.g. `src/borrow/`, `src/swap/`) as the SDK evolves. The `ActionsConfig` type in `src/types/actions.ts` shows all configurable action categories.
#### Morpho
Morpho uses individual vault markets. Ask the developer which Morpho vaults they want to support. The developer may:
- **Provide a vault URL** (e.g. `https://app.morpho.org/unichain/vault/0x38f4...`). Parse the chain name and vault address from the URL to construct the `LendMarketConfig`.
- **Want demo/testnet markets** for development — see `packages/demo/backend/src/config/markets.ts` for examples.
- **Not know yet** — scaffold with an empty allowlist and a TODO comment.
```typescript
// Morpho market — address is the vault address from the Morpho app URL
const MorphoUSDC: LendMarketConfig = {
address: '0x...', // e.g. from https://app.morpho.org/{chain}/vault/{address}
chainId: unichain.id,
name: 'Gauntlet USDC',
asset: USDC,
lendProvider: 'morpho',
}
```
#### Aave
Aave uses a singleton lending pool per chain — there is no per-vault address. Instead, each Aave "market" in the config represents an **underlying asset** you want to support lending for on Aave. The `address` field is the asset's token address on that chain.
> **For agents**: Ask the developer which assets they want to lend via Aave and on which chains. Then construct the `LendMarketConfig` for each, using the asset's token address on that chain. Look up the address from the SDK's built-in asset constants in `src/constants/assets.ts`, or if the asset isn't built-in, look up the token address on the target chain.
```typescript
// Aave market — address is the underlying token address on the target chain
const AaveETH: LendMarketConfig = {
address: '0x4200000000000000000000000000000000000006', // WETH on Optimism
chainId: optimism.id,
name: 'Aave ETH',
asset: ETH,
lendProvider: 'aave',
}
```
#### Bringing it together
```typescript
import type { LendConfig, LendMarketConfig } from '@eth-optimism/actions-sdk'
import { ETH, USDC } from '@eth-optimism/actions-sdk'
import { optimism, unichain } from 'viem/chains'
const lendConfig: LendConfig = {
morpho: {
marketAllowlist: [MorphoUSDC],
},
aave: {
marketAllowlist: [AaveETH],
},
}
```
For more on configuring lend providers, see the [Configuring Actions](https://docs.optimism.io/app-developers/guides/configuring-actions) guide and the [Lend Reference](https://docs.optimism.io/app-developers/reference/actions/lend-documentation).
> **Source of truth**: `src/lend/` for available lending providers. `packages/demo/backend/src/config/markets.ts` for working market examples.
### 4c: Chain Config
> **For agents**: Start by including every chain already referenced by the markets configured in 4b. Then ask the developer if they want to support any additional chains. Check `src/constants/supportedChains.ts` in the SDK for the full list, and present the remaining chains as options. If your tool supports multi-select, use it here.
Each chain needs an RPC URL and optionally a bundler for smart wallet gas sponsorship.
```typescript
import { optimism, base, unichain } from 'viem/chains'
const chains = [
{
chainId: optimism.id,
rpcUrls: [process.env.OPTIMISM_RPC_URL],
bundler: {
type: 'pimlico' as const, // or 'simple'
url: process.env.OPTIMISM_BUNDLER_URL,
},
},
{
chainId: unichain.id,
rpcUrls: [process.env.UNICHAIN_RPC_URL],
bundler: {
type: 'simple' as const,
url: process.env.UNICHAIN_BUNDLER_URL,
},
},
]
```
### 4d: Asset Config
> **For agents**: Start by including every asset already referenced by the markets configured in 4b. Then ask the developer if they want to support any additional tokens. Check `src/constants/assets.ts` for built-in asset constants (ETH, USDC, WETH, etc.) and present remaining options. If the developer needs a token not built into the SDK, help them define a custom `Asset` object — you'll need the token's contract address on each supported chain, decimals, symbol, and name.
```typescript
import { USDC, ETH } from '@eth-optimism/actions-sdk'
const assetsConfig = {
allow: [USDC, ETH], // Only these assets are available in the app
}
```
Custom assets can be defined inline:
```typescript
import type { Asset } from '@eth-optimism/actions-sdk'
import { unichain } from 'viem/chains'
const CUSTOM_TOKEN: Asset = {
address: {
[unichain.id]: '0x...',
},
metadata: {
decimals: 18,
name: 'Custom Token',
symbol: 'CUSTOM',
},
type: 'erc20',
}
```
> **Source of truth**: `src/constants/assets.ts` for built-in assets, `src/supported/tokens.ts` for the `SUPPORTED_TOKENS` list.
### 4e: Initialize Actions
Bring everything together:
```typescript
// React frontend
import { createActions } from '@eth-optimism/actions-sdk/react'
export const actions = createActions({
wallet: walletConfig,
chains,
assets: assetsConfig,
lend: lendConfig,
})
```
```typescript
// Node backend
import { createActions } from '@eth-optimism/actions-sdk/node'
export const actions = createActions({
wallet: walletConfig,
chains,
assets: assetsConfig,
lend: lendConfig,
})
```
In a backend, initialize once at startup and export a singleton. In React, memoize the instance to avoid recreating on every render.
## Step 5: Use Actions
### Convert a wallet to an Actions wallet
Once the developer has a wallet from their provider, convert it to an Actions wallet. Each provider passes different arguments. Example with Privy on React:
```typescript
import { useWallets } from '@privy-io/react-auth'
const { wallets } = useWallets()
const embeddedWallet = wallets.find(
(wallet) => wallet.walletClientType === 'privy',
)
const wallet = await actions.wallet.toActionsWallet({
connectedWallet: embeddedWallet,
})
```
For all provider-specific `toActionsWallet` code, see the [Quickstart](https://docs.optimism.io/app-developers/quickstarts/actions#choose-a-wallet-provider) guide.
### Create a smart wallet (optional)
Smart wallets add ERC-4337 features (gas sponsorship, batch transactions). Create a signer from the provider wallet, then create a smart wallet. Example with Privy on React:
```typescript
const signer = await actions.wallet.createSigner({
connectedWallet: embeddedWallet,
})
const { wallet } = await actions.wallet.createSmartWallet({ signer })
```
For all provider-specific `createSigner` parameters, see the [Integrating Wallets](https://docs.optimism.io/app-developers/reference/actions/integrating-wallets) reference.
### Perform DeFi actions
For the full list of wallet methods and lend operations, see the [Wallet Reference](https://docs.optimism.io/app-developers/reference/actions/wallet-definitions) and [Lend Reference](https://docs.optimism.io/app-developers/reference/actions/lend-documentation).
```typescript
// Get token balances across all configured chains
const balances = await wallet.getBalance()
// Open a lending position
const receipt = await wallet.lend.openPosition({
amount: 100,
asset: USDC,
...market, // { address, chainId } of the market — a LendMarketId
})
// Get current position
const position = await wallet.lend.getPosition(market)
// Close a position (withdraw)
const closeReceipt = await wallet.lend.closePosition({
amount: 50,
asset: USDC,
...market,
})
// Browse available markets
const markets = await actions.lend.getMarkets()
// ── Borrow (Morpho Blue today; Aave / Comet / Liquity follow) ──
// Quote a borrow open: positionAfter + fees + safeCeilingLtv + pre-built txs.
const quote = await wallet.borrow.openPosition({
market, // BorrowMarketConfig — { kind: 'morpho-blue', marketId, marketParams, ... }
borrowAmount: { amount: 100 }, // or { amountRaw: 100_000_000n } per #379
collateralAmount: { amount: 250 }, // optional; omit when collateral is already supplied
})
// Get the current position
const borrowPosition = await wallet.borrow.getPosition({
marketId: market,
walletAddress: wallet.address,
})
// Close with `{ max: true }` to use Morpho's dust-safe shares path
const closeReceipt = await wallet.borrow.closePosition({
market,
borrowAmount: { max: true },
collateralAmount: { max: true },
})
// Hand a pre-built quote back to wallet.borrow.* to dispatch without re-quoting
// (recipient is validated against wallet.address; quote expiration enforced).
await wallet.borrow.openPosition(quote)
```
> **Source of truth for available actions**: The wallet instance exposes namespaces for each action type. Check which namespaces exist on the `Wallet` and `SmartWallet` classes in `src/wallet/core/wallets/`. The `actions` instance also exposes top-level namespaces for read-only operations (e.g. `actions.lend.getMarkets()`, `actions.borrow.getMarket(marketId)`).
## Reference
### Key types
```typescript
import type {
ActionsConfig, // Top-level config
Asset, // Token definition (address per chain + metadata)
TokenBalance, // Balance result (total + per-chain breakdown)
LendConfig, // Lend provider configuration
LendMarketConfig, // Market definition
LendMarketId, // Market identifier ({ address, chainId })
LendMarket, // Market data (name, asset, supply, APY)
LendMarketPosition, // User position in a market
LendTransaction, // Transaction result from lend operations
BorrowConfig, // Borrow provider configuration
BorrowMarketConfig, // Borrow market definition (tagged union; Morpho Blue today)
BorrowMarketId, // Borrow market identifier ({ kind, marketId, chainId })
BorrowMarket, // Borrow market data (APY, LLTV, totals)
BorrowMarketPosition, // User position (collateral, debt, HF, LTV)
BorrowQuote, // Pre-built borrow action with calldata + position transition
BorrowReceipt, // Receipt returned from wallet.borrow.* actions
WalletConfig, // Wallet provider configuration
SupportedChainId, // Union of supported chain IDs
} from '@eth-optimism/actions-sdk'
```
### Key imports
```typescript
// Assets
import { ETH, USDC, WETH } from '@eth-optimism/actions-sdk'
// Utilities
import {
getTokenAddress,
getTokenBySymbol,
SUPPORTED_TOKENS,
} from '@eth-optimism/actions-sdk'
// Wallet classes (for type checking)
import { Wallet, SmartWallet } from '@eth-optimism/actions-sdk'
// Factory (environment-specific)
import { createActions } from '@eth-optimism/actions-sdk/react' // or /node
```
### Documentation
- Quickstart: https://docs.optimism.io/app-developers/quickstarts/actions
- Configuring Actions: https://docs.optimism.io/app-developers/guides/configuring-actions
- Integrating Wallets: https://docs.optimism.io/app-developers/reference/actions/integrating-wallets
- Wallet Reference: https://docs.optimism.io/app-developers/reference/actions/wallet-definitions
- Lend Reference: https://docs.optimism.io/app-developers/reference/actions/lend-documentation
### Example code
The demo applications in this repository show complete working integrations:
- `packages/demo/backend/` — Node.js backend with Privy, Morpho, and Aave
- `packages/demo/frontend/` — React frontend with Privy, Turnkey, and Dynamic