diff --git a/AGENTS.md b/AGENTS.md index b553dcd4..7bbbad00 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,9 +3,9 @@ ## Skills ### Available skills -- `euler-sdk` (v1.1.1): Euler V2 SDK integration guide for building production UIs, bots, scripts, and tooling. Use for tasks involving `buildEulerSDK`, SDK services (`accountService`, `portfolioService`, `vaultMetaService`, `executionService`, `swapService`), React Query integration, or SDK examples in `packages/euler-v2-sdk/examples/`. (file: `./skills/euler-sdk/SKILL.md`) +- `euler-sdk`: Euler V2 SDK integration guide for building production UIs, bots, scripts, and tooling. Use the canonical skill from [`euler-xyz/agent-skills`](https://github.com/euler-xyz/agent-skills/tree/main/skills/euler-sdk) for tasks involving `buildEulerSDK`, SDK services (`accountService`, `vaultMetaService`, `walletService`, `executionService`, `swapService`, `reulLockService`), React Query integration, or SDK examples in `packages/euler-v2-sdk/examples/`. ### How to use skills -- Trigger rule: If user asks for SDK integration help or names `euler-sdk`, load and follow `./skills/euler-sdk/SKILL.md`. +- Trigger rule: If user asks for SDK integration help or names `euler-sdk`, load and follow the canonical `euler-sdk` skill from `euler-xyz/agent-skills`. - Load minimally: Open `SKILL.md` first, then only the rule files needed for the current task. -- Prefer local skill files in this repository over globally installed copies when both exist. +- Treat the SDK implementation docs and examples in this repository as source material for SDK behavior, and treat `euler-xyz/agent-skills` as the source of truth for packaged agent skill instructions. diff --git a/README.md b/README.md index 2105ea88..7b57a07c 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,6 @@ A monorepo for Euler SDKs and tools. ### Agent Skills -Skills are at [`skills/`](./skills/) and discoverable via the root [`AGENTS.md`](./AGENTS.md). +Agent skill instructions are maintained in [`euler-xyz/agent-skills`](https://github.com/euler-xyz/agent-skills). -- `euler-sdk` (v1.1.0) - SDK integration guide. Install via `npx skills add euler-sdk` or see [`skills/euler-sdk/SKILL.md`](./skills/euler-sdk/SKILL.md). +- `euler-sdk` - SDK integration guide for building with `@eulerxyz/euler-v2-sdk`. See [`AGENTS.md`](./AGENTS.md) for agent usage guidance. diff --git a/skills/euler-sdk/AGENTS.md b/skills/euler-sdk/AGENTS.md deleted file mode 100644 index 9dbc4ae1..00000000 --- a/skills/euler-sdk/AGENTS.md +++ /dev/null @@ -1,226 +0,0 @@ -# Euler SDK Agent Skill - -**Version 1.2.0** -Euler Labs -May 2026 - ---- - -## Abstract - -Integration guide for `euler-v2-sdk` focused on building production UIs, automation scripts, and developer tools. Covers service boundaries, entity population, transaction planning, approvals, simulation safety, caching via `buildQuery`, plugin integration, V3 → onchain/subgraph/direct fallback chains, swap flows, and script templates. - ---- - -## Table of Contents - -1. [SDK Foundations](#1-sdk-foundations) — **HIGH** -2. [Execution Safety](#2-execution-safety) — **CRITICAL** -3. [Runtime Performance](#3-runtime-performance) — **HIGH** -4. [Integration Patterns](#4-integration-patterns) — **HIGH** - ---- - -## 1. SDK Foundations - -### 1.1 Architecture and Service Selection - -Use `buildEulerSDK` as the composition root and route reads through top-level services: - -- `accountService` for account/sub-account state -- `vaultMetaService` for mixed or unknown vault types -- `walletService` for native/ERC20 wallet balances and direct/Permit2 allowance state -- `executionService` for planning/encoding tx batches - - executes generic `TransactionPlan` items, including direct `contractCall` items -- `executionService` for plan simulation and pre-trade validation; CoW plans execute here but are not simulation/gas-estimation inputs -- `swapService` for quotes and providers, including `cowSwap` metadata for CoW-supported position flows -- `rewardsService` for reward reads and provider-specific reward claim planning; the default V3 path normalizes Incentra rows as Brevis and returns direct proof-backed Brevis rows when V3 lacks claim metadata -- `reulLockService` for rEUL lock reads and unlock transaction plans -- `oracleAdapterService` for oracle adapter metadata keyed by normalized `adapter.oracle` address -- `eulerLabelsService` plus exported label helpers for normalized products, Earn entries, notices, restrictions, and product/vault flags - -Built-in scalar config resolves as `config` prop, explicit SDK option, `EULER_SDK_*` env var, then default. Prefer `EULER_SDK_RPC_URL_` for examples and `buildEulerSDK({ config: { rpcUrls, v3ApiUrl, v3ApiKey } })` for app-level runtime wiring that cannot rely on env. - -Do not assume all vaults are `EVault`. Use `vaultMetaService` for polymorphic routing. -Service `fetch*` methods return diagnostics envelopes (`{ result, errors }`). Destructure `result` in examples and map `errors[].locations[]` by owner reference for UI diagnostics. - -### 1.2 UI Data Population Contract - -Computed account metrics depend on populated data. For portfolio screens, set: - -- `populateVaults: true` -- `populateMarketPrices: true` -- `populateUserRewards: true` -- `vaultFetchOptions` with needed enrichments (`collaterals`, `strategyVaults`, `rewards`, `intrinsicApy`, `labels`) - -Without these flags, metrics like `healthFactor`, `netValueUsd`, and `roe` may be missing or incomplete. -APY/ROE fields exposed by vault and portfolio entities are percentage points (`5` = `5%`); raw reward campaign APRs remain decimal fractions until converted by computed breakdowns or UI helpers. Vault rewards come back as `VaultRewardInfo`; its `getTotalRewardsApr({ viewer })`/`getActiveCampaigns({ viewer })` (and the viewer-aware `getNetApy/getRoe/getApyBreakdown/getRoeBreakdown({ viewer })` on portfolio/position/sub-account) apply Merkl-style whitelist/blacklist eligibility, while the plain getters stay headline. Breakdowns also attribute `BORROW_COLLATERAL` and `LOOPING` campaigns. -Numerical Account and Portfolio fields whose names include `Usd` are market-priced USD values; oracle and risk-unit values stay in explicit oracle/liquidity fields such as `oraclePriceRaw`, `assetRiskPrice`, `liabilityValue`, and `totalCollateralValue`. - -For batch vault reads (`fetchVaults`, `fetchVerifiedVaults`), results preserve input order and can include `undefined` entries for per-vault failures; use diagnostics locations with `owner.kind === "vault"` to map failures to addresses. - -Use entity `populated` flags to verify enrichment state in UI logic: - -- `account.populated.vaults | marketPrices | userRewards` -- `vault.populated.marketPrices | rewards | intrinsicApy | labels` -- `eVault.populated.collaterals` -- `eulerEarn.populated.strategyVaults` - ---- - -## 2. Execution Safety - -### 2.1 Planning and Approvals - -Prefer `planX` APIs over `encodeX` for user-facing transaction flows. Resolve required approvals before sending EVC batch transactions. - -Execution order: - -1. Build plan (`planDeposit`, `planBorrow`, `planRepayWithSwap`, `planSwapAndBorrowFromWallet`, etc.) or reward claim plan in `rewardsService` -2. Resolve approvals with `resolveRequiredApprovals({ chainId, account, plan })`, or fetch requested assets/spenders through `walletService.fetchWallet(...)` and use `resolveRequiredApprovalsWithWallet({ chainId, wallet, plan })` -3. Execute `contractCall` items directly when present -4. Send `evcBatch` transaction(s) -5. Wait for receipts and refresh UI state - -Use `mergePlans` to atomically combine user intents and `describeBatch` for previews. -`planX` methods group their encoded batch items into named operations inside `evcBatch` entries. Raw batch items remain valid batch entries for plugin prepends/appends. `mergePlans` preserves operation groupings and refuses to automatically merge `contractCall` items. `describeBatch` mirrors the input batch-entry shape: operation entries keep their name and contain decoded child items. - -### 2.2 Simulation Gate - -Simulate non-trivial plans before execution: - -- swap-based repayment -- leverage / multiply -- debt migration -- liquidation flows - -Block execution when `canExecute` is false or when status checks/insufficiency fields fail. Surface decoded errors to users. - ---- - -## 3. Runtime Performance - -### 3.1 buildQuery Caching Strategy - -Decorate SDK `query*` methods via `buildQuery` (e.g., with React Query). - -Use per-query stale times: - -- hours (e.g. 12-24h): deployments, ABIs, token lists, static labels -- minutes: perspectives/providers/reward catalogs -- minutes: bundled intrinsic APY lookups such as `queryV3IntrinsicApy` -- 10-30s: account/vault/wallet state -- ~5s: wallet balance and allowance queries (`queryNativeBalance`, `queryTokenBalances`, `queryAllowance`, `queryPermit2Allowance`) -- ~10s: swap quotes and Pyth update payloads - -This keeps repeated service-level `fetch*` calls inexpensive. -By default, `buildEulerSDK` applies a 5s in-memory cache to decorated `query*` methods. Supplying a custom `buildQuery` replaces that default cache layer. - -### 3.2 Plugins for Preconditions - -Use plugins when vault interactions require side data/actions: - -- `createPythPlugin` to inject price updates before reads/writes -- `createKeyringPlugin` to inject credential creation when required - -Write-path plugins run automatically inside `simulateTransactionPlan`, `estimateGasForTransactionPlan`, and `executeTransactionPlan`. The account argument is `AddressOrAccount` (`Address | Account`); pass an `Account` when available so plugins can reuse state, or pass an address to let plugins fetch minimal data. - -Keep plugin ordering deterministic. Use shared caching decorators for plugin query paths. - -### 3.3 Fallback Adapter for V3 / Onchain Routing - -`buildEulerSDK` wires `accountService`, `eVaultService`, `eulerEarnService`, `vaultMetaService`, and `rewardsService` as fallback chains (V3 → onchain / subgraph / direct) when both adapters are buildable. Configure them explicitly per service rather than relying on implicit behavior: - -```ts -const sdk = await buildEulerSDK({ - config: { - v3ApiUrl: process.env.EULER_SDK_V3_API_URL, - v3ApiKey: process.env.EULER_SDK_V3_API_KEY, - eVaultServiceAdapter: "fallback", // default when both adapters available - accountServiceAdapter: "v3", // pin to V3 only - rewardsServiceAdapter: "direct", // pin to direct only - disableV3: false, // set true for a global V3 kill switch - }, -}); -``` - -If V3 credentials are unset, fallback chains collapse to the secondary adapter with a one-line warning during construction — no throw. - -The default trigger logic is intentionally conservative. Fallback fires only when: - -- the primary throws, -- `ServiceResult.result` is `undefined`, or -- `result` is an array containing at least one `undefined` slot. - -Per-entity warnings on a fully-populated response (e.g. `SOURCE_UNAVAILABLE` on a nested oracle) do **not** trigger fallback. The secondary cannot recover information the primary already returned, and re-fetching only doubles latency. - -Observe fallback events with `onFallback`. Route on `info.trigger`, not on the count of `primaryIssues`: - -```ts -import { buildEulerSDK, type FallbackInfo } from "@eulerxyz/euler-v2-sdk"; - -const sdk = await buildEulerSDK({ - onFallback: (info: FallbackInfo) => { - metrics.increment("sdk.fallback", { - method: info.method, - adapter: info.primaryName, - trigger: info.trigger, - }); - }, -}); -``` - -`FallbackInfo.trigger` is one of `"primary-threw" | "result-undefined" | "array-missing-slots" | "custom-shouldFallback" | "circuit-open"`; `missingIndices` is populated for the array case. The secondary's `ServiceResult` is also prefixed with a `FALLBACK_USED` diagnostic for UIs that surface diagnostics. - -For non-built-in adapters, compose with `createFallbackAdapter(primary, secondary, { methods, adapterNames, circuitBreaker?, shouldFallback?, onFallback? })`. Only listed methods are wrapped; setters and other state pass through to the primary unchanged. Reference: [`docs/fallback-system.md`](../../packages/euler-v2-sdk/docs/fallback-system.md). - ---- - -## 4. Integration Patterns - -### 4.1 Swap Workflows - -Pattern: - -1. fetch quotes (`fetchDepositQuote`, `fetchRepayQuotes`) -2. pick quote (best-first ordering) -3. build plan (`planRepayWithSwap`, `planSwapCollateral`, `planSwapDebt`, `planSwapAndBorrowFromWallet`, `planSwapAndRepayFromWallet`, `planWithdrawAndSwap`, `planRedeemAndSwap`, `planMultiplyWithSwap`, `planMultiplySameAsset`, or a CoW-specific planner) -4. simulate -5. execute - -Re-quote near submission time and compare providers for advanced routing UIs. -For CoW open-position, close-position, and collateral-swap routes, pass `cowSwap` to the regular quote method, use the matching CoW planner, and execute the plan with `executionService.executeCowSwapTransactionPlan(...)`. CoW plans return `orderUids`, settle asynchronously through CoW Protocol, and are not simulation or gas-estimation inputs. Track orders with `fetchCowSwapOrderStatus` / `pollCowSwapOrderStatus`; cancel open/collateral orders with `cancelCowSwapOrder` and close-position orders with `planCancelClosePositionWithCow`. - -### 4.2 Scripts and Automation - -Use SDK examples as templates: - -- `packages/euler-v2-sdk/examples/execution/*` for transaction flows -- `packages/euler-v2-sdk/examples/wallets/*` for wallet balance and allowance reads -- `packages/euler-v2-sdk/examples/simulations/*` for pre-checks -- `sdk.executionService.executeTransactionPlan(...)` for plugin processing + approval + Permit2 + EVC execution logic -- `packages/euler-v2-sdk/examples/execution/open-position-with-cow-live-example.ts` for live CoW order submission with a real private key -- `packages/euler-v2-sdk/examples/run-examples.sh` for fork-based regression runs - -Promote constants to config/env and add explicit chain/account flags in CLI tools. - ---- - -## Primary References - -- `packages/euler-v2-sdk/README.md` -- `packages/euler-v2-sdk/docs/basic-usage.md` -- `packages/euler-v2-sdk/docs/services.md` -- `packages/euler-v2-sdk/docs/wallet-service.md` -- `packages/euler-v2-sdk/docs/entity-diagnostics.md` -- `packages/euler-v2-sdk/docs/execution-service.md` -- `packages/euler-v2-sdk/docs/simulations-and-state-overrides.md` -- `packages/euler-v2-sdk/docs/caching-external-data-queries.md` -- `packages/euler-v2-sdk/docs/labels.md` -- `packages/euler-v2-sdk/docs/plugins.md` -- `packages/euler-v2-sdk/docs/swaps.md` -- `packages/euler-v2-sdk/docs/cow-swaps.md` -- `packages/euler-v2-sdk/docs/reul-lock-service.md` -- `packages/euler-v2-sdk/examples/react-sdk-example/src/context/SdkContext.tsx` -- `packages/euler-v2-sdk/examples/react-sdk-example/src/queries/sdkQueries.ts` -- `packages/euler-v2-sdk/examples/react-sdk-example/src/utils/txProgress.ts` diff --git a/skills/euler-sdk/CHANGELOG.md b/skills/euler-sdk/CHANGELOG.md deleted file mode 100644 index 10bada76..00000000 --- a/skills/euler-sdk/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -# Changelog - -All notable changes to the `euler-sdk` skill are documented in this file. - -## 1.2.0 - 2026-05-19 -- Added `sdk-fallback-adapter` rule covering V3 → onchain/subgraph/direct fallback chains, default trigger semantics, `onFallback` telemetry (`FallbackInfo.trigger`, `missingIndices`), and custom `createFallbackAdapter` composition. -- Expanded `AGENTS.md` section 3 (Runtime Performance) with `3.3 Fallback Adapter for V3 / Onchain Routing`. -- New reference doc: `packages/euler-v2-sdk/docs/fallback-system.md`. - -## 1.1.2 - 2026-05-07 -- Added `walletService` guidance for native/ERC20 balances and direct/Permit2 allowance state. -- Added wallet query caching guidance and wallet example references. - -## 1.1.1 - 2026-04-16 -- Aligned examples with diagnostics-aware service returns (`{ result, errors }`). -- Updated approval resolution guidance to the current `plan`/`account` API shape. -- Clarified custom `buildQuery` behavior and full-debt swap mode usage. - -## 1.1.0 - 2026-03-09 -- Added explicit skill versioning policy (`VERSIONING.md`). -- Added guidance for npm-package discovery via packaged `AGENTS.md` and `skills/` paths. - -## 1.0.0 - 2026-03-02 -- Initial release of the Euler SDK skill. diff --git a/skills/euler-sdk/SKILL.md b/skills/euler-sdk/SKILL.md deleted file mode 100644 index 0bdb4d7e..00000000 --- a/skills/euler-sdk/SKILL.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: euler-sdk -description: Euler V2 SDK integration guide for building production UIs, bots, scripts, and tooling. This skill should be used when implementing apps on top of the `euler-v2-sdk` package, including account/vault/wallet reads, transaction planning, approval handling, simulation, swaps, rEUL locks, plugins, and query caching. Triggers on tasks involving `buildEulerSDK`, SDK services (`accountService`, `vaultMetaService`, `walletService`, `executionService`, `swapService`, `reulLockService`), React Query integration, or SDK examples in `packages/euler-v2-sdk/examples/`. -license: MIT -metadata: - author: Euler Labs - version: "1.2.0" ---- - -# Euler SDK Agent Skill - -Euler V2 SDK integration guide for building reliable frontends, scripts, and automation on top of `euler-v2-sdk`. - -## When to Apply - -Reference these guidelines when: -- Building UI data layers on top of SDK services and entities -- Planning and executing user transactions (deposit, borrow, repay, swap, liquidation) -- Simulating plans and showing pre-trade safety checks -- Integrating plugins (Pyth, Keyring) for read/write readiness -- Optimizing performance with `buildQuery` caching and stale-time design -- Writing scripts and automation from SDK examples - -## Rule Categories - -| Rule | Impact | Description | -|------|--------|-------------| -| `sdk-architecture` | HIGH | Build SDK once and use top-level services with correct fetch options | -| `sdk-ui-data-layer` | HIGH | Build reactive UI query layer with type-aware vault routing and population | -| `sdk-execution-flow` | CRITICAL | Plan transactions, resolve approvals, and execute EVC batch safely | -| `sdk-simulation-safety` | CRITICAL | Simulate plans before sending and gate execution on checks | -| `sdk-caching-buildquery` | HIGH | Wrap all `query*` calls via `buildQuery` with per-query stale times | -| `sdk-plugins` | HIGH | Use plugins for oracle/keyring preconditions on read and write paths | -| `sdk-fallback-adapter` | HIGH | Configure V3 → onchain/subgraph/direct fallback chains and observe `onFallback` telemetry | -| `sdk-swaps` | HIGH | Quote, select, and execute swap-driven operations safely | -| `sdk-scripts` | MEDIUM | Use SDK examples as templates for scripts, bots, and CI checks | - -## Quick Reference - -### Core SDK Entry Points - -- `buildEulerSDK({...})` as composition root -- `buildEulerSDK({ config: {...} })` for SDK-owned runtime config; `config` overrides explicit options, `EULER_SDK_*` env vars, and defaults -- `accountService` for account/sub-account positions -- `vaultMetaService` when vault type is unknown or mixed -- `walletService` for native/ERC20 wallet balances and direct/Permit2 allowance state -- `executionService` for `planX`/`encodeX` and approvals -- `executionService` for plugin-aware plan simulation, gas estimation, execution, and pre-execution validation; CoW plans execute through `executeCowSwapTransactionPlan`, expose order status/cancellation helpers, and are not simulation/gas-estimation inputs -- `swapService` for provider quotes and route payloads, including `cowSwap` metadata for CoW-supported position flows -- `rewardsService` for reward reads and provider-specific claim plans; the default V3 path normalizes Incentra rows as Brevis and returns direct proof-backed Brevis rows when V3 lacks claim metadata -- `reulLockService` for rEUL vesting lock reads and unlock transaction plans -- `eulerLabelsService` plus exported `utils/eulerLabels` helpers for normalized labels metadata, notices, restrictions, and product/vault flags -- `oracleAdapterService.fetchOracleAdapterMap(chainId)` returns metadata keyed by normalized `adapter.oracle` address - -Service `fetch*` methods return diagnostics envelopes (`{ result, errors }`). Destructure `result` in examples and map `errors[].locations[]` by owner reference for UI diagnostics. - -Built-in scalar config resolves as `config` prop, explicit SDK option, `EULER_SDK_*` env var, then default. RPC URLs can come from `config.rpcUrls` or `EULER_SDK_RPC_URL_`. Reference `packages/euler-v2-sdk/docs/config-through-env.md` for the env/config field list. - -### Preferred UI Pattern - -1. Initialize one SDK instance in app context/provider. -2. Decorate all SDK `query*` methods with `buildQuery` (React Query or equivalent cache). -3. Use service-level `fetch*` methods in hooks for reactive UI. -4. Set population flags explicitly (`populateMarketPrices`, `populateRewards`, etc.). -5. Simulate `TransactionPlan` before execution when user risk is non-trivial. - -CoW swap plans are an exception to the simulation step: build them from CoW quotes with the CoW-specific planners and execute them through `executeCowSwapTransactionPlan`, then track returned `orderUids` with `fetchCowSwapOrderStatus` or `pollCowSwapOrderStatus`. Use `cancelCowSwapOrder` for open-position/collateral-swap CoW orders and `planCancelClosePositionWithCow` for close-position CoW orders that cancel by invalidating the EVC permit nonce. - -## Companion Skills - -- `euler-vaults` - protocol-level mechanics, EVC and risk -- `euler-data` - Lens/subgraph/interfaces references -- `euler-advanced` - hooks, flash loans, debt transfer -- `euler-irm-oracles` - oracle adapters and IRM specifics -- `euler-earn` - EulerEarn vault strategy management - -## How to Use - -Read individual rule files for details and implementation patterns: - -``` -rules/sdk-architecture.md -rules/sdk-ui-data-layer.md -rules/sdk-execution-flow.md -rules/sdk-simulation-safety.md -rules/sdk-caching-buildquery.md -rules/sdk-plugins.md -rules/sdk-fallback-adapter.md -rules/sdk-swaps.md -rules/sdk-scripts.md -``` - -## Full Compiled Document - -For a longer consolidated guide with all sections: `AGENTS.md` diff --git a/skills/euler-sdk/VERSIONING.md b/skills/euler-sdk/VERSIONING.md deleted file mode 100644 index ac65fc12..00000000 --- a/skills/euler-sdk/VERSIONING.md +++ /dev/null @@ -1,13 +0,0 @@ -# Skill Versioning - -`euler-sdk` uses semantic versioning. - -- MAJOR: breaking changes to guidance structure or expected workflow. -- MINOR: new sections/rules or materially expanded guidance. -- PATCH: wording clarifications, typo fixes, non-breaking refinements. - -Version must be updated in all of: -- `SKILL.md` frontmatter: `metadata.version` -- `metadata.json`: `version` -- `AGENTS.md` header version -- `CHANGELOG.md` diff --git a/skills/euler-sdk/metadata.json b/skills/euler-sdk/metadata.json deleted file mode 100644 index 2b5636ab..00000000 --- a/skills/euler-sdk/metadata.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "version": "1.2.0", - "organization": "Euler Labs", - "date": "May 2026", - "abstract": "Euler V2 SDK integration guide for building production UIs, automation scripts, and developer tooling on top of euler-v2-sdk.", - "tldr": "Use buildEulerSDK once, fetch via accountService/vaultMetaService/walletService, plan with executionService, simulate before execute, and apply buildQuery caching, fallback-adapter routing, and plugins for robust UI and bot flows.", - "triggers": [ - "euler sdk", - "euler-v2-sdk", - "buildEulerSDK", - "executionService", - "vaultMetaService", - "walletService", - "accountService", - "createFallbackAdapter", - "FallbackInfo", - "onFallback", - "Euler SDK UI", - "Euler SDK scripts", - "Euler SDK tooling" - ], - "references": [ - "https://github.com/euler-xyz/euler-sdks", - "https://docs.euler.finance" - ] -} diff --git a/skills/euler-sdk/rules/_sections.md b/skills/euler-sdk/rules/_sections.md deleted file mode 100644 index 4914e2f2..00000000 --- a/skills/euler-sdk/rules/_sections.md +++ /dev/null @@ -1,29 +0,0 @@ -# Sections - -This file defines sections for the euler-sdk skill. - ---- - -## 1. SDK Foundations (sdk) - -**Impact:** HIGH - -**Description:** Core architecture, service selection, and fetch option strategy for correct SDK usage in UIs and tools. - -## 2. Execution Safety (execution) - -**Impact:** CRITICAL - -**Description:** Transaction planning, approval handling, simulation, and execution flows that reduce user-facing failures. - -## 3. Runtime Performance (runtime) - -**Impact:** HIGH - -**Description:** Query decoration, caching policy, and plugin-based preconditions for performant and correct reads/writes. - -## 4. Integration Patterns (integration) - -**Impact:** HIGH - -**Description:** Swap flows and script templates for production integrations, bots, and operational tooling. diff --git a/skills/euler-sdk/rules/sdk-architecture.md b/skills/euler-sdk/rules/sdk-architecture.md deleted file mode 100644 index d54d4569..00000000 --- a/skills/euler-sdk/rules/sdk-architecture.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: SDK Architecture and Service Boundaries -impact: HIGH -impactDescription: Prevents incorrect service usage and missing data in app state -tags: sdk, architecture, services, buildEulerSDK, vaultMetaService ---- - -## SDK Architecture and Service Boundaries - -Initialize the SDK once, treat services as layered APIs, and pick the right service boundary for each task. - -**Incorrect (using typed vault service when vault type is unknown):** - -```typescript -// WRONG: Fails for non-EVault addresses -const vault = await sdk.eVaultService.fetchVault(chainId, maybeAnyVault); -``` - -**Correct (route by type with vaultMetaService):** - -```typescript -const { result: vault, errors } = await sdk.vaultMetaService.fetchVault(chainId, maybeAnyVault, { - populateMarketPrices: true, - populateRewards: true, - populateIntrinsicApy: true, - populateLabels: true, -}); - -if (!vault) throw new Error(errors[0]?.message ?? "Vault could not be resolved"); -``` - -**Correct build pattern (single composition root):** - -```typescript -import { buildEulerSDK } from "euler-v2-sdk"; - -// Set EULER_SDK_RPC_URL_ in the environment for on-chain reads. -const sdk = await buildEulerSDK({ - config: { - v3ApiUrl: process.env.EULER_SDK_V3_API_URL, - v3ApiKey: process.env.EULER_SDK_V3_API_KEY, - }, -}); -``` - -Built-in scalar config resolves as `config` prop, explicit SDK option, `EULER_SDK_*` env var, then default. Use `packages/euler-v2-sdk/docs/config-through-env.md` when adding runtime config. - -Use these default boundaries: - -- `accountService`: account/sub-account portfolio state -- `vaultMetaService`: mixed/unknown vault types -- `walletService`: native/ERC20 wallet balances and direct/Permit2 allowance state -- `executionService`: `planX`/`encodeX`, approvals, batch encoding -- `executionService`: transaction planning, execution, plan validation, and post-state preview -- `swapService`: quotes and providers -- `rewardsService`: reward reads and provider-specific claim planning -- `reulLockService`: rEUL vesting lock reads and unlock transaction plans -- `eulerLabelsService`: normalized off-chain labels metadata; use exported helpers from `utils/eulerLabels` for product/vault flags, notices, and restrictions -- `oracleAdapterService`: oracle adapter metadata keyed by normalized `adapter.oracle` address - -All service `fetch*` methods return `{ result, errors }`; keep diagnostics with the fetched entity when rendering warnings or enforcing data-quality policy. - -Reference: `packages/euler-v2-sdk/docs/services.md`, `packages/euler-v2-sdk/docs/config-through-env.md`, `packages/euler-v2-sdk/docs/wallet-service.md`, `packages/euler-v2-sdk/docs/reul-lock-service.md`, `packages/euler-v2-sdk/docs/entity-diagnostics.md`, `docs/data-architecture.md`, `src/sdk/buildSDK.ts` diff --git a/skills/euler-sdk/rules/sdk-caching-buildquery.md b/skills/euler-sdk/rules/sdk-caching-buildquery.md deleted file mode 100644 index 417032f1..00000000 --- a/skills/euler-sdk/rules/sdk-caching-buildquery.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Query Decoration and Caching with buildQuery -impact: HIGH -impactDescription: Reduces RPC/API load and stabilizes UI latency -tags: caching, buildQuery, react-query, performance ---- - -## Query Decoration and Caching with buildQuery - -Wrap SDK `query*` methods through `buildQuery` instead of adding ad-hoc caches around service calls. -When adding a new RPC/API dependency, expose it as a `query*` method on the adapter or service rather than calling it directly from orchestration code. - -**Correct pattern:** - -```typescript -import { QueryClient } from "@tanstack/react-query"; -import type { BuildQueryFn } from "euler-v2-sdk"; - -const queryClient = new QueryClient(); - -const buildQuery: BuildQueryFn = (queryName, fn, _target) => { - const staleTime = queryName.startsWith("querySwap") ? 10_000 : 60_000; - return ((...args: unknown[]) => - queryClient.fetchQuery({ - queryKey: ["sdk", queryName, ...args], - queryFn: () => fn(...args), - staleTime, - })) as typeof fn; -}; -``` - -Recommended stale-time strategy: - -- hours (e.g. 12-24h): deployments, ABI, token list, static labels -- minutes: perspectives, providers, reward campaign catalogs -- minutes: external intrinsic APY queries such as `queryV3IntrinsicApy` -- 10-30s: vault/account/wallet state -- ~5s: transaction-sensitive wallet reads such as `queryNativeBalance`, `queryTokenBalances`, `queryAllowance`, and `queryPermit2Allowance` -- ~10s: swap quotes and Pyth update payloads - -This keeps service-level `fetch*` orchestration cheap because underlying `query*` calls are cached. -By default, `buildEulerSDK` applies a 5s in-memory cache to decorated `query*` methods. Supplying a custom `buildQuery` replaces that default cache layer, so include caching/deduping there if the app needs it. - -Reference: `packages/euler-v2-sdk/docs/caching-external-data-queries.md`, `examples/react-sdk-example/src/queries/sdkQueries.ts` diff --git a/skills/euler-sdk/rules/sdk-execution-flow.md b/skills/euler-sdk/rules/sdk-execution-flow.md deleted file mode 100644 index 02c18446..00000000 --- a/skills/euler-sdk/rules/sdk-execution-flow.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Transaction Planning, Approvals, and EVC Batch Execution -impact: CRITICAL -impactDescription: Prevents reverted transactions and broken wallet UX -tags: execution, planX, approvals, permit2, evc ---- - -## Transaction Planning, Approvals, and EVC Batch Execution - -Prefer `planX` over `encodeX` for app flows. `planX` includes required approvals and context-driven execution decisions. -For reward claims, use `rewardsService.buildClaimPlan(s)` instead of adding provider-specific claim logic to `executionService`. - -**Incorrect (encoding raw calls but skipping approvals):** - -```typescript -const batchItems = sdk.executionService.encodeDeposit({ ...args }); -// WRONG: no approval resolution; tx may revert on allowance -``` - -**Correct (plan + resolve + execute):** - -```typescript -const plan = sdk.executionService.planDeposit({ - account, - vault, - asset, - amount, - receiver, - enableCollateral: true, -}); - -const resolved = await sdk.executionService.resolveRequiredApprovals({ - chainId, - account: owner, - plan, -}); - -// Execute required approvals first, then handle each executable item: -// - contractCall: send directly -// - evcBatch: send through EVC.batch -``` - -Execution checklist: - -1. Build plan with `planX`. -2. Pass the plan to `sdk.executionService.executeTransactionPlan(...)`; it applies configured plugins before resolving approvals and sending transactions. -3. Use `onProgress` to surface approval, Permit2 signature, direct call, EVC batch, CoW signing/submission, and completion states. -4. Wait for the returned receipts and refetch dependent queries. -5. Decode contract errors for user-facing diagnostics. - -CoW swap plans are built with `planOpenPositionWithCoW`, `planClosePositionWithCow`, or `planSwapCollateralWithCoW`. They are executed through `executeCowSwapTransactionPlan`, return `orderUids`, and settle asynchronously through CoW Protocol. Track order state with `fetchCowSwapOrderStatus` or `pollCowSwapOrderStatus`. Cancel open-position and collateral-swap orders with `cancelCowSwapOrder`; cancel close-position orders with `planCancelClosePositionWithCow`, which invalidates the signed EVC permit nonce. Use `formatCowSwapExecutionErrorMessage` for short UI-safe errors. Do not pass CoW plans to simulation, gas estimation, `mergePlans`, or `describeBatch`. - -`executeTransactionPlan`, `simulateTransactionPlan`, and `estimateGasForTransactionPlan` accept `AddressOrAccount` (`Address | Account`) for the account argument. Pass an `Account` when the caller already has account state that plugins can reuse; pass an address when plugin-side minimal fetching is preferable. - -When the same plan is both simulated (for a Review preview) and then executed (on Confirm), call `prepareTransactionPlan({ plan, chainId, account, usePermit2?, unlimitedApproval? })` once and pass the returned `TransactionPlanPrepared` envelope to `simulatePreparedTransactionPlan(prepared, options?)` and `executePreparedTransactionPlan({ prepared, sendTransaction, signTypedData, onProgress })`. The prepared variants skip the internal plugin pipeline (and approval re-resolution for execute), so plugin reads — TOS, Keyring, Pyth — run once per Review instead of three times. Use `isPreparedTransactionPlan` to discriminate envelope vs raw plan. CoW plans are not supported by `prepareTransactionPlan`. - -Borrow and leverage planners (`planBorrow`, `planSwapAndBorrowFromWallet`, `planMultiplyWithSwap`, `planMultiplySameAsset`) automatically prepend cleanup that disables stale enabled collaterals/controllers on the target sub-account before borrowing; pass `skipCleanup: true` to opt out when you manage EVC state yourself. `planCleanup` builds that batch standalone. Full-repay `cleanupOnMax` only sweeps collateral shares for EVK vaults (non-EVK collaterals like Securitize RWA are disabled but not transferred, since they lack `transferFromMax`). - -Use `mergePlans` to atomically combine multiple intents and `describeBatch` for previews/logging. `mergePlans` collapses redundant EVC state transitions across merged batches (e.g. a cleanup `disableCollateral` cancels a borrow `enableCollateral`), so merging a `planCleanup` plan with a borrow plan yields a minimal batch. -Planner-created `evcBatch` entries contain named operations (`{ type: "operation", name, items }`). Keep those groups intact in previews and merge flows. Raw `EVCBatchItem` entries are still valid for low-level utilities and plugin-inserted setup calls. Use `convertBatchItemsToPlan(items, operationName)` when a raw encoded batch should be named as one operation; omit `operationName` to preserve the raw item array. - -Reference: `packages/euler-v2-sdk/docs/execution-service.md`, `packages/euler-v2-sdk/docs/cow-swaps.md`, `packages/euler-v2-sdk/src/services/executionService/executionService.ts`, `examples/react-sdk-example/src/utils/txProgress.ts` diff --git a/skills/euler-sdk/rules/sdk-fallback-adapter.md b/skills/euler-sdk/rules/sdk-fallback-adapter.md deleted file mode 100644 index 7dea4f03..00000000 --- a/skills/euler-sdk/rules/sdk-fallback-adapter.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Fallback Adapter for V3 / Onchain Routing -impact: HIGH -impactDescription: Prevents over-eager fallbacks, lost fast-path latency, and silent data loss -tags: sdk, fallback, v3, onchain, reliability, telemetry, runtime ---- - -## Fallback Adapter for V3 / Onchain Routing - -`buildEulerSDK` wraps `accountService`, `eVaultService`, `eulerEarnService`, `vaultMetaService`, and `rewardsService` in fallback adapters (V3 → onchain / subgraph / direct). Configure them explicitly and read telemetry through `onFallback` rather than guessing why a call fell back from `primaryIssues` alone. - -**Incorrect (over-eager fallback inferred from any SOURCE_UNAVAILABLE):** - -```typescript -// WRONG: Treats per-collateral oracle warnings as a fallback trigger. -const wrapped = createFallbackAdapter(primary, secondary, { - methods: ["fetchVaults"], - adapterNames: { primary: "v3", secondary: "onchain" }, - shouldFallback: (r) => r.errors.some((e) => e.code === "SOURCE_UNAVAILABLE"), -}); -``` - -Per-entity warnings on a fully-populated response should not trigger fallback — the secondary cannot recover information the primary already returned, and re-fetching only doubles latency. - -**Correct (rely on the default trigger logic):** - -```typescript -const wrapped = createFallbackAdapter(primary, secondary, { - methods: ["fetchVaults"], - adapterNames: { primary: "v3", secondary: "onchain" }, -}); -// Default falls back ONLY when: -// - primary throws, -// - ServiceResult.result is undefined, or -// - result is an array containing at least one undefined slot. -``` - -**Correct (route by service-level config in buildEulerSDK):** - -```typescript -const sdk = await buildEulerSDK({ - config: { - v3ApiUrl: process.env.EULER_SDK_V3_API_URL, - v3ApiKey: process.env.EULER_SDK_V3_API_KEY, - eVaultServiceAdapter: "fallback", // default when both adapters are buildable - accountServiceAdapter: "v3", // pin to V3 only - rewardsServiceAdapter: "direct", // pin to direct (no V3 calls) - disableV3: process.env.ENV === "ci", // global kill switch for V3 across all chains - }, -}); -``` - -`disableV3: true` collapses every `"fallback"` selection to its non-V3 alternative. If V3 credentials are simply missing, fallback chains auto-collapse to the secondary with a one-line warning during construction — never throw. - -**Correct (observe fallback events via telemetry):** - -```typescript -import { buildEulerSDK, type FallbackInfo } from "@eulerxyz/euler-v2-sdk"; - -const sdk = await buildEulerSDK({ - onFallback: (info: FallbackInfo) => { - // info.trigger distinguishes the real cause: - // "primary-threw" | "result-undefined" | "array-missing-slots" - // | "custom-shouldFallback" | "circuit-open" - // info.missingIndices is populated for "array-missing-slots". - metrics.increment("sdk.fallback", { - method: info.method, - adapter: info.primaryName, - trigger: info.trigger, - }); - }, -}); -``` - -Use `info.trigger` for routing logic; treat `info.primaryIssues` as context only. Per-entity warnings appear in `primaryIssues` whenever the primary returned a `ServiceResult`, but they never by themselves cause the fallback — the actual cause is whatever `trigger` says. - -**Correct (custom fallback for a non-built-in adapter):** - -```typescript -import { createFallbackAdapter } from "@eulerxyz/euler-v2-sdk"; - -const wrapped = createFallbackAdapter(primary, secondary, { - methods: ["fetchThings"], - adapterNames: { primary: "v3", secondary: "onchain" }, - // Trip the circuit after 3 consecutive primary failures, skip primary for 30s. - circuitBreaker: { failures: 3, cooldownMs: 30_000 }, - onFallback: (info) => console.log("fallback", info.method, info.trigger), -}); -``` - -Only methods listed in `methods` are wrapped; setters and other state (`setConfig`, `setPlugins`, internal caches) pass through to the primary unchanged. Methods that return a plain `Promise` (not a `ServiceResult`) fall back only on throw. - -Diagnostics on the returned secondary `ServiceResult` are prefixed with a `FALLBACK_USED` issue (`severity: "info"`, `source: ""`, `originalValue` carries the primary error or its `errors[]`). UIs that surface diagnostics already pick this up; routing decisions should still come from `onFallback`'s `trigger`, not from scraping the `errors` array. - -See [`packages/euler-v2-sdk/docs/fallback-system.md`](../../../packages/euler-v2-sdk/docs/fallback-system.md) for the full reference, [`packages/euler-v2-sdk/docs/entity-diagnostics.md`](../../../packages/euler-v2-sdk/docs/entity-diagnostics.md) for `DataIssue` shape, and `packages/euler-v2-sdk/test/fallbackAdapter.test.ts` for the trigger-by-trigger test matrix. diff --git a/skills/euler-sdk/rules/sdk-plugins.md b/skills/euler-sdk/rules/sdk-plugins.md deleted file mode 100644 index 5b1fbb64..00000000 --- a/skills/euler-sdk/rules/sdk-plugins.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Plugin Integration for Read and Write Preconditions -impact: HIGH -impactDescription: Prevents stale-oracle and credential-gating failures -tags: plugins, pyth, keyring, processPlan, batchSimulation ---- - -## Plugin Integration for Read and Write Preconditions - -Use plugins whenever vault interactions require preconditions that are not part of core calls. - -**Correct initialization with plugin support:** - -```typescript -import { buildEulerSDK, createPythPlugin, createKeyringPlugin } from "euler-v2-sdk"; - -const sdk = await buildEulerSDK({ - plugins: [ - createPythPlugin(), - createKeyringPlugin({ - hookTargets, - getCredentialData: async (args) => fetchCredential(args), - }), - ], -}); -``` - -Plugin behavior: - -- `getReadPrepend`: prepends calls before lens reads (`batchSimulation` path) -- `processPlan`: transforms plans before `simulateTransactionPlan`, `estimateGasForTransactionPlan`, and `executeTransactionPlan` - -Guidelines: - -1. Keep plugin list deterministic and ordered. -2. Use same `buildQuery` wrapper for plugin queries where possible. -3. For plan previews, call `sdk.executionService.simulateTransactionPlan(...)` or `estimateGasForTransactionPlan(...)`; these apply the same plugin pipeline as execution. -4. Treat the execution account argument as `AddressOrAccount` (`Address | Account`). Passing an `Account` lets plugins reuse account state; passing an address lets plugins fetch minimal data. - -Implementation notes: - -- `EulerPlugin.processPlan(plan, account, chainId, sdk)` receives the full SDK instance. -- Pyth write processing uses the generic `calculateHealthCheckSets(plan, account)` utility, which requires a vault-populated `Account` and returns per-batch controller/collateral sets. -- Keyring uses vaults already present on a passed `Account`; it fetches target vaults only when the account argument is an address. - -Reference: `packages/euler-v2-sdk/docs/plugins.md`, `src/plugins/pyth/pythPlugin.ts`, `src/plugins/keyring/keyringPlugin.ts` diff --git a/skills/euler-sdk/rules/sdk-scripts.md b/skills/euler-sdk/rules/sdk-scripts.md deleted file mode 100644 index 64c7c11d..00000000 --- a/skills/euler-sdk/rules/sdk-scripts.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Script and Tooling Workflows from SDK Examples -impact: MEDIUM -impactDescription: Speeds up reliable bot/script development with proven patterns -tags: scripts, examples, automation, anvil, fork-testing ---- - -## Script and Tooling Workflows from SDK Examples - -Use `packages/euler-v2-sdk/examples/` as canonical templates for script structure, then parameterize config/env. - -Suggested workflow: - -1. Start from nearest example (`deposit`, `repay-with-swap`, `swap-and-borrow-from-wallet`, `withdraw-and-swap`, `multiply-same-asset`, `liquidation`, etc.). -2. Move chain/account/vault constants into a shared `config.ts`, and put SDK runtime config behind `buildEulerSDK({ config })` or `EULER_SDK_*` env vars. -3. Use `sdk.executionService.executeTransactionPlan(...)` for plugin processing, approval resolution, Permit2, and EVC batch execution. -4. Add simulation gates before submission for bots. CoW plans are submitted to the CoW orderbook and cannot be simulated through SDK plan simulation; print `getCowSwapOrderExplorerUrl(orderUid)` and track them with `fetchCowSwapOrderStatus` / `pollCowSwapOrderStatus` after submission. -5. Run non-CoW flows against fork first (Anvil), then production RPC. CoW orderbook examples require live chain/RPC credentials. - -**Correct starting points:** - -- `packages/euler-v2-sdk/examples/execution/*.ts` for transaction flows -- `packages/euler-v2-sdk/examples/wallets/*.ts` for wallet balance and allowance reads -- `packages/euler-v2-sdk/examples/simulations/*.ts` for safety checks -- `sdk.executionService.executeTransactionPlan(...)` for plugin-aware execution plumbing -- `packages/euler-v2-sdk/examples/execution/open-position-with-cow-live-example.ts` for live CoW order submission with a real private key -- `packages/euler-v2-sdk/examples/run-examples.sh` for local fork regression pass - -When building CLI tools, prefer idempotent commands and explicit chain/account flags. -Use `EULER_SDK_RPC_URL_` for RPC URLs and `EULER_SDK_V3_API_KEY` for the shared V3 key in example `.env` files. - -Reference: `packages/euler-v2-sdk/examples/`, `packages/euler-v2-sdk/examples/run-examples.sh`, `packages/euler-v2-sdk/docs/config-through-env.md`, `packages/euler-v2-sdk/docs/cow-swaps.md` diff --git a/skills/euler-sdk/rules/sdk-simulation-safety.md b/skills/euler-sdk/rules/sdk-simulation-safety.md deleted file mode 100644 index 10c65020..00000000 --- a/skills/euler-sdk/rules/sdk-simulation-safety.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Pre-Execution Simulation and Safety Gates -impact: CRITICAL -impactDescription: Catches failing routes and unhealthy positions before users sign -tags: simulation, batchSimulation, safety, health, state-overrides ---- - -## Pre-Execution Simulation and Safety Gates - -Simulate any non-trivial plan before execution, especially swaps, leverage, debt migration, and liquidation paths. - -**Correct simulation flow:** - -```typescript -const result = await sdk.executionService.simulateTransactionPlan( - chainId, - ownerOrAccount, - plan, - { - stateOverrides: true, - accountFetchOptions: { - populateVaults: true, - populateMarketPrices: true, - populateUserRewards: true, - vaultFetchOptions: { - populateMarketPrices: true, - populateRewards: true, - populateIntrinsicApy: true, - }, - }, - }, -); - -if (!result.canExecute) { - throw new Error("Simulation failed safety checks"); -} -``` - -Simulation and gas estimation use the same plugin processing path as execution. Their account argument is `AddressOrAccount` (`Address | Account`), so passing an already-fetched account can avoid duplicate plugin account fetches. - -Gate execution on: - -- `result.canExecute` -- `result.failedBatchItems` -- `result.accountStatusErrors` and `result.vaultStatusErrors` -- insufficiency fields (`insufficientWalletAssets`, allowances) - -If simulation fails, decode and surface actionable messages rather than raw revert bytes. - -For UI fan-outs that simulate N candidate plans per user action (swap-quote sweeps, leverage explorers), avoid blowing up RPC + Hermes traffic: - -- Pass `stateOverrideOptions` (`SimulationStateOverrideOptions`) to skip overrides the form already validated: `noBalanceOverride: true` when the form gates submit on wallet balance, `wallet.balances`/`wallet.allowances` from the snapshot the form already holds, and `slotHints` pre-fetched once per token with `fetchErc20SlotHints(provider, token, { allowanceSpender })`. -- Compute `prefetch` once per sweep with `executionService.prefetchPluginDataForPlan(plan, account, chainId)` and thread it through every `prepareTransactionPlan` / `simulatePreparedTransactionPlan` / `estimateGasForPreparedTransactionPlan` / `executePreparedTransactionPlan` call. The Pyth / Keyring plugin work happens once instead of N times. - -These options are additive and degrade gracefully — omit them and the SDK falls back to full derivation + per-call plugin fetch. - -Reference: `packages/euler-v2-sdk/docs/simulations-and-state-overrides.md`, `docs/execution-service.md`, `docs/decode-smart-contract-errors.md`, `examples/simulations/simulate-deposit-example.ts` diff --git a/skills/euler-sdk/rules/sdk-swaps.md b/skills/euler-sdk/rules/sdk-swaps.md deleted file mode 100644 index 22276d3f..00000000 --- a/skills/euler-sdk/rules/sdk-swaps.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Swap Quotes and Swap-Driven Execution Flows -impact: HIGH -impactDescription: Avoids incorrect quote usage and repay/swap mismatches -tags: swaps, quote, repay, collateral, multiply ---- - -## Swap Quotes and Swap-Driven Execution Flows - -Use `swapService` as the first step for any swap-driven action, then feed selected quotes into `executionService.plan*`. - -**Correct flow:** - -```typescript -import { SwapperMode } from "euler-v2-sdk"; - -const quotes = await sdk.swapService.fetchRepayQuotes({ - chainId, - fromVault, - fromAsset, - fromAccount, - liabilityVault, - liabilityAsset, - liabilityAmount, - currentDebt, - toAccount, - origin, - swapperMode: SwapperMode.TARGET_DEBT, - slippage: 0.5, -}); - -const plan = sdk.executionService.planRepayWithSwap({ - account, - swapQuote: quotes[0]!, -}); -``` - -Rules: - -1. Always re-quote close to execution time. -2. Use the planner that matches the quote verifier mode: `planSwapFromWallet` for `transferMin`, `planDepositWithSwapFromWallet` / `planSwapAndBorrowFromWallet` / `planSwapCollateral` for `skimMin`, and `planRepayWithSwap` / `planSwapDebt` / `planSwapAndRepayFromWallet` for `debtMax`. -3. For full debt repay, set `liabilityAmount` to `currentDebt` with `SwapperMode.TARGET_DEBT`. -4. For wallet-sourced repay, request the quote with a real `fromVault` and `fromAccount` as the router sweep context, then let `planSwapAndRepayFromWallet` pull the input token from the wallet. Use `BigInt(quote.amountIn)` for exact-input quotes and `BigInt(quote.amountInMax || quote.amountIn)` for target-debt quotes. -5. For CoW open-position, close-position, and collateral-swap routes, pass `cowSwap` into `fetchDepositQuote` / `fetchRepayQuotes`, then use `planOpenPositionWithCoW`, `planClosePositionWithCow`, or `planSwapCollateralWithCoW`. Execute the returned plan with `executeCowSwapTransactionPlan`; do not simulate or gas-estimate CoW plans. Track orders with `fetchCowSwapOrderStatus` / `pollCowSwapOrderStatus`; cancel open/collateral orders with `cancelCowSwapOrder` and close-position orders with `planCancelClosePositionWithCow`. -6. For same-asset debt migration, ensure the destination debt vault has positive-LTV collateral enabled on the account before executing the migration plan. -7. Validate quote-provider assumptions (quotes are best-first, but still simulate non-CoW plans). -8. Compare providers when building professional routing UIs. - -Reference: `packages/euler-v2-sdk/docs/swaps.md`, `packages/euler-v2-sdk/docs/cow-swaps.md`, `examples/execution/repay-with-swap-example.ts`, `examples/execution/swap-and-borrow-from-wallet-example.ts`, `examples/execution/swap-and-repay-from-wallet-example.ts`, `examples/execution/withdraw-and-swap-example.ts`, `examples/execution/redeem-and-swap-example.ts`, `examples/execution/open-position-with-cow-live-example.ts` diff --git a/skills/euler-sdk/rules/sdk-ui-data-layer.md b/skills/euler-sdk/rules/sdk-ui-data-layer.md deleted file mode 100644 index 1af5391f..00000000 --- a/skills/euler-sdk/rules/sdk-ui-data-layer.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: UI Data Layer with Fetch Options and Population -impact: HIGH -impactDescription: Prevents undefined computed values and stale portfolio views -tags: react, queries, accountService, population, computed-properties ---- - -## UI Data Layer with Fetch Options and Population - -Explicitly set population flags based on what the screen needs. Computed metrics require populated dependencies. - -**Incorrect (expecting computed USD/risk metrics without population):** - -```typescript -const { result: account } = await sdk.accountService.fetchAccount(chainId, owner, { - populateVaults: false, -}); - -console.log(account.getSubAccount(owner)?.netValueUsd); // undefined -``` - -**Correct (declare population requirements):** - -```typescript -const { result: account, errors } = await sdk.accountService.fetchAccount(chainId, owner, { - populateVaults: true, - populateMarketPrices: true, - populateUserRewards: true, - vaultFetchOptions: { - populateMarketPrices: true, - populateCollaterals: true, - populateStrategyVaults: true, - populateRewards: true, - populateIntrinsicApy: true, - populateLabels: true, - }, -}); -``` - -Use `populated` flags as a hard guard before rendering computed fields: - -```typescript -if (!account.populated.marketPrices) return null; -if (!account.populated.vaults) return null; -``` - -Keep `errors` alongside the entity snapshot. Diagnostics are not entity state; use them for field-level badges, telemetry, and policy decisions. - -APY/ROE values on SDK vault and portfolio entities are percentage points (`5` = `5%`). Raw reward campaign APRs are decimal fractions; convert them before adding them to vault APYs in custom UI code, or use the SDK's computed breakdown fields. - -Vault rewards are exposed as a `VaultRewardInfo` whose `getTotalRewardsApr({ viewer })` / `getActiveCampaigns({ viewer })` apply Merkl-style whitelist/blacklist eligibility — the plain `totalRewardsApr` getter stays headline (no viewer). Portfolio, per-position, and sub-account views mirror this: headline `netApy`/`roe`/`apyBreakdown`/`roeBreakdown` getters vs viewer-aware `getNetApy/getRoe/getApyBreakdown/getRoeBreakdown({ viewer })`. Pass the connected address as `viewer` once a wallet is connected so gated campaigns don't inflate displayed APY. These breakdowns also pick up `BORROW_COLLATERAL` and `LOOPING` reward campaigns. - -USD market price and value fields (`marketPriceUsd`, `suppliedValueUsd`, `borrowedValueUsd`, `totalRewardsValueUsd`, portfolio USD totals) are plain `number` values. Direct oracle/risk fields such as `oraclePriceRaw`, `assetRiskPrice`, `healthFactor`, and LTV ratios remain `bigint`. - -For React UIs: - -1. Build SDK in a provider/context once. -2. Use query hooks per feature (`vault list`, `vault detail`, `account`, `rewards`). -3. Use short UI stale times and let `buildQuery` handle deeper caching. -4. Re-fetch account/vault data after successful execution receipts. -5. For batch vault calls, handle sparse arrays (`undefined` entries) and map diagnostics by `locations[].owner` to show per-address failures. - -Reference: `packages/euler-v2-sdk/docs/basic-usage.md`, `docs/cross-service-data-population.md`, `docs/account-computed-properties.md`, `docs/entity-diagnostics.md`, `examples/react-sdk-example/src/queries/sdkQueries.ts`