Query and act on DeFi lending, yield, bridge, and swap — across protocols and chains, from a single CLI.
Built for AI agents and scripts. Stable JSON output, canonical identifiers (CAIP-2/CAIP-19), and deterministic exit codes make it easy to pipe into any workflow.
- Lending — query markets/rates from Aave/Morpho/Kamino/Moonwell, account positions from Aave/Morpho/Moonwell, and execute loan actions (
lend supply|withdraw|borrow|repay). - Yield — compare opportunities, query positions, fetch historical series, and execute deposit/withdraw flows (Aave, Morpho, Moonwell).
- Bridging — get cross-chain quotes (Across, LiFi, Bungee), bridge analytics, and execute bridge plans (Across, LiFi).
- Swapping — get swap quotes (1inch, Uniswap, Jupiter, Tempo, TaikoSwap, Fibrous, Bungee) and execute swap plans (Tempo with native type 0x76 transactions and batched calls, TaikoSwap).
- Approvals, transfers & rewards — ERC-20 approvals/transfers and Aave rewards claim/compound flows.
- Wallet — query native and ERC-20 token balances on any supported EVM chain (no API key required).
- Chains & protocols — browse top chains by TVL, inspect chain TVL by asset, query live gas prices, discover protocols, track stablecoin market caps, resolve asset identifiers.
- Automation-friendly — JSON-first output, field selection (
--select), structured JSON/file input (--input-json,--input-file), and a machine-readable schema export with required flags, enums, input constraints, auth, and request/response metadata.
This repo includes a dedicated Mintlify docs site under docs/ (docs/docs.json + .mdx pages).
Preview locally:
cd docs
npx --yes mint@4.2.378 dev --no-openValidate before publishing:
cd docs
npx --yes mint@4.2.378 validate
npx --yes mint@4.2.378 broken-links
npx --yes mint@4.2.378 a11yProduction docs deployment should target docs-live in Mintlify Git settings. The release workflow syncs docs-live on stable release tags (non-prerelease) so live docs align with main-channel binaries.
Installs the latest tagged release from GitHub:
curl -fsSL https://raw.githubusercontent.com/ggonzalez94/defi-cli/main/scripts/install.sh | shInstall a specific version (accepted: latest, stable, vX.Y.Z, X.Y.Z):
curl -fsSL https://raw.githubusercontent.com/ggonzalez94/defi-cli/main/scripts/install.sh | sh -s -- v0.5.0go install github.com/ggonzalez94/defi-cli/cmd/defi@latest- Download the right archive from GitHub Releases:
- Linux/macOS:
defi_<version>_<os>_<arch>.tar.gz - Windows:
defi_<version>_windows_<arch>.zip
- Linux/macOS:
- Verify checksums with
checksums.txt. - Extract and move
defiinto yourPATH.
go build -o defi ./cmd/defiVerify install:
defi version --longExecution commands (plan, submit, status) support two signing backends:
Open Wallet Standard (OWS) keeps keys encrypted at rest with built-in policy controls.
Setup:
npm install -g @open-wallet-standard/core
ows wallet create --name agent-treasury
export DEFI_OWS_TOKEN=$(ows token create --wallet agent-treasury --ttl 24h)Plan and submit:
defi lend supply plan --provider aave --chain 1 --asset USDC --amount 1000000 --wallet agent-treasury
defi lend supply submit --action-id <action_id>Sign directly with a local private key — no external tooling required.
Plan and submit:
defi lend supply plan --provider aave --chain 1 --asset USDC --amount 1000000 --from-address 0xYourEOA
export DEFI_PRIVATE_KEY_FILE=~/.config/defi/key.hex
defi lend supply submit --action-id <action_id>Read-only commands (
markets,positions,quote, etc.) do not require either backend.
defi providers list --results-only
defi chains list --results-only --select slug,caip2,namespace
defi chains gas --chain 1 --results-only
defi chains gas --chain 1,10,137,8453,42161 --results-only # multi-chain batch
defi chains top --limit 10 --results-only --select rank,chain,tvl_usd
defi chains assets --chain 1 --asset USDC --results-only # Requires DEFI_DEFILLAMA_API_KEY
defi protocols fees --limit 10 --results-only --select rank,protocol,fees_24h_usd,change_1d_pct
defi protocols revenue --limit 10 --results-only --select rank,protocol,revenue_24h_usd,change_1d_pct
defi dexes volume --limit 10 --results-only --select rank,protocol,volume_24h_usd,change_1d_pct
defi dexes volume --chain Arbitrum --limit 5 --results-only # Filter DEXes active on Arbitrum
defi stablecoins top --limit 10 --results-only --select rank,symbol,circulating_usd,price
defi stablecoins chains --limit 10 --results-only --select rank,chain,circulating_usd
defi wallet balance --chain 1 --address 0xYourEOA --results-only
defi wallet balance --chain base --address 0xYourEOA --asset USDC --results-only
defi assets resolve --chain base --symbol USDC --results-only
defi lend markets --provider aave --chain 1 --asset USDC --results-only
defi lend positions --provider aave --chain 1 --address 0xYourEOA --type all --results-only
defi yield opportunities --chain 1 --asset USDC --providers aave,morpho --limit 10 --results-only
defi yield history --chain 1 --asset USDC --providers aave --metrics apy_total --interval day --window 7d --limit 1 --results-only
defi bridge quote --provider across --from 1 --to 8453 --asset USDC --amount 1000000 --results-only
defi swap quote --provider tempo --chain tempo --from-asset pathUSD --to-asset USDC.e --amount 1000000 --results-only# Plan standard EVM actions with an OWS wallet reference
defi lend supply plan --provider aave --chain 1 --asset USDC --amount 1000000 --wallet agent-treasury --results-only
defi bridge plan --provider across --from 1 --to 8453 --asset USDC --amount 1000000 --wallet agent-treasury --results-only
defi swap plan --provider taikoswap --chain taiko --from-asset USDC --to-asset WETH --amount 1000000 --wallet agent-treasury --results-only
# Tempo remains the explicit exception and still plans with --from-address
defi swap plan --provider tempo --chain tempo --from-asset pathUSD --to-asset USDC.e --amount 1000000 --from-address 0xYourEOA --results-only
# Execute a wallet-backed action
export DEFI_OWS_TOKEN=...
defi lend supply submit --action-id <action_id> --results-only
# Local signer: plan and submit with a local private key
defi lend supply plan --provider aave --chain 1 --asset USDC --amount 1000000 --from-address 0xYourEOA --results-only
export DEFI_PRIVATE_KEY_FILE=~/.config/defi/key.hex
defi lend supply submit --action-id <action_id> --results-only
# Structured input for agents
defi lend supply plan --input-json '{"provider":"aave","chain":"1","asset":"USDC","amount":"1000000","wallet":"agent-treasury"}' --results-only
# Inspect actions
defi actions list --results-only
defi actions estimate --action-id <action_id> --results-onlyswap plan|submit|status(Tempo, TaikoSwap)bridge plan|submit|status(Across, LiFi)lend supply|withdraw|borrow|repay plan|submit|status(Aave, Morpho, Moonwell)yield deposit|withdraw plan|submit|status(Aave, Morpho, Moonwell)rewards claim|compound plan|submit|status(Aave)approvals plan|submit|statustransfer plan|submit|statusactions list|show|estimate
All plan commands support --rpc-url to override chain default RPCs.
plan and submit accept --input-json / --input-file for structured input; explicit flags override JSON values.
--providers flags accept provider names from defi providers list (e.g. aave,morpho,kamino,moonwell).
defi swap quote --provider 1inch --chain 1 --from-asset USDC --to-asset DAI --amount 1000000 --results-only # requires DEFI_1INCH_API_KEY
defi swap quote --provider uniswap --chain 1 --from-asset USDC --to-asset DAI --amount 1000000 --from-address 0xYourEOA --results-only # requires DEFI_UNISWAP_API_KEY
defi swap quote --provider uniswap --chain 1 --from-asset USDC --to-asset DAI --type exact-output --amount-out 1000000000000000000 --from-address 0xYourEOA --results-only
defi swap quote --provider tempo --chain tempo --from-asset pathUSD --to-asset USDC.e --type exact-output --amount-out 1000000 --results-only
defi bridge quote --provider lifi --from 1 --to 8453 --asset USDC --amount 1000000 --from-amount-for-gas 100000 --results-onlyMost commands do not require provider API keys.
When a provider requires authentication, bring your own key:
defi swap quote --provider 1inch->DEFI_1INCH_API_KEYdefi swap quote --provider uniswap->DEFI_UNISWAP_API_KEYdefi chains assets->DEFI_DEFILLAMA_API_KEYdefi bridge list->DEFI_DEFILLAMA_API_KEYdefi bridge details->DEFI_DEFILLAMA_API_KEYdefi swap quote --provider tempo-> no API key requireddefi swap quote --provider taikoswap-> no API key required
defi providers list includes both provider-level key metadata and capability-level key metadata (capability_auth).
DEFI_1INCH_API_KEY(required forswap quote --provider 1inch)DEFI_UNISWAP_API_KEY(required forswap quote --provider uniswap)DEFI_DEFILLAMA_API_KEY(required forchains assets,bridge list, andbridge details)
Configure keys with environment variables (recommended):
export DEFI_1INCH_API_KEY=...
export DEFI_UNISWAP_API_KEY=...
export DEFI_DEFILLAMA_API_KEY=...For persistent shell setup, add exports to your shell profile (for example ~/.zshrc).
If a keyed provider is used without a key, CLI exits with code 10.
Two signing backends are supported. The backend is determined at plan time and persisted with the action.
OWS (recommended):
- Plan with
--walletto create anows-backed action. - Submit reads the persisted
wallet_idand requiresDEFI_OWS_TOKEN. - Does not accept local signer flags during submit.
export DEFI_OWS_TOKEN=...
defi bridge submit --action-id <action_id> --results-onlyLocal signer:
- Plan with
--from-addressto create alegacy_local-backed action. - Submit uses local key inputs (
--private-key, env vars, keystore).
Key input precedence (when --key-source auto and --private-key is unset):
DEFI_PRIVATE_KEY(hex string)DEFI_PRIVATE_KEY_FILE(key file path)~/.config/defi/key.hex(or$XDG_CONFIG_HOME/defi/key.hex)DEFI_KEYSTORE_PATH+ password env
Force source with --key-source env|file|keystore.
Tempo exception:
- Tempo swap planning uses
--from-address(OWS does not cover Tempo-native execution yet). - Tempo submit uses
--signer tempo.
submit commands support optional --from-address as an explicit sender-address guard.
Most users only need env vars for provider keys. Use config when you want persistent non-secret defaults (output mode, timeout/retries, cache behavior).
Config precedence is:
flags > env > config file > defaults
Default config path:
${XDG_CONFIG_HOME:-~/.config}/defi/config.yaml
Default cache paths:
${XDG_CACHE_HOME:-~/.cache}/defi/cache.db${XDG_CACHE_HOME:-~/.cache}/defi/cache.lock
Example optional config:
output: json
strict: false
timeout: 10s
retries: 2
cache:
enabled: true
max_stale: 5m
execution:
actions_path: ~/.cache/defi/actions.db
actions_lock_path: ~/.cache/defi/actions.lock
providers:
uniswap:
api_key_env: DEFI_UNISWAP_API_KEYswap quote (on-chain quote providers) and execution plan --rpc-url flags override chain default RPCs for that invocation.
submit/status commands use stored per-step RPC URLs from the persisted action.
internal/registry: canonical execution endpoints/contracts/ABI fragments and default chain RPC map used when no--rpc-urlis provided.internal/providers/*/client.go: provider quote/read API base URLs and external source URLs.internal/id/id.go: bootstrap token symbol/address registry used for deterministic symbol parsing.
- Command TTLs are fixed in code (
chains/protocols/stablecoins/chains assets:5m,lend markets:60s,lend rates:30s,lend positions:30s,yield opportunities:60s,yield positions:30s,yield history:5m,wallet balance:15s,bridge/swap quotes:15s). - Cache entries are served directly only while fresh (
age <= ttl). - After TTL expiry, the CLI fetches provider data immediately.
cache.max_stale/--max-staleis only a temporary provider-failure fallback window (currentlyunavailable/rate_limited).- If fallback is disabled (
--no-staleor--max-stale 0s) or stale data exceeds the budget, the CLI exits with code14. - Metadata commands (
version,schema,providers list,chains list) bypass cache initialization. - Execution commands (
swap|bridge|approvals|transfer|lend|yield|rewards ... plan|submit|status,actions list|show|estimate) bypass cache reads/writes. - Expired entries (past TTL +
max_stale) are automatically pruned on startup to prevent unbounded growth.
wallet balancecurrently supports EVM chains only; Solana is not yet supported.wallet balanceuseseth_getBalancefor native tokens and ERC-20balanceOffor tokens; it does not query pending/unconfirmed balances.- Morpho can surface extreme APY values on very small markets; use
--min-tvl-usdwhen ranking. yield opportunitiesreturnsapy_total,tvl_usd,liquidity_usd, andbacking_assets(objective metrics only).yield history --metricssupportsapy_totalandtvl_usd; Aave currently supportsapy_totalonly. Use--windowfor Aave history.lend positions --type allreturns disjoint rows:supply,collateral, andborrow.- For chains without bootstrap symbol entries, pass token address or CAIP-19 for deterministic resolution.
--chainsupports CAIP-2, numeric IDs, and aliases (tempo,presto,moderato,tempo devnet,mantle,megaeth,taiko,gnosis,linea,zksync,hyperevm,monad,citrea, and more).chains assetsrequiresDEFI_DEFILLAMA_API_KEY;bridge list/bridge detailsalso require it; quote providers (across,lifi) do not.protocols feesrankings are sorted by 24h fees descending; protocols with null or zero 24h fees are excluded.protocols revenuerankings are sorted by 24h revenue descending; protocols with null or zero 24h revenue are excluded. Revenue represents the portion of fees retained by the protocol (not LPs/validators).dexes volumerankings are sorted by 24h volume descending; DEXes with null or zero 24h volume are excluded.--chainfilters by chain presence.chains gasreturns live EVM gas prices via RPC; it is EVM-only and bypasses cache. Use--rpc-urlto override the default chain RPC. Pass comma-separated chains (e.g.--chain 1,10,8453) for parallel multi-chain queries;--rpc-urlis only allowed with a single chain.
swap quote --typedefaults toexact-input;exact-outputis currently supported byuniswapandtempo(--amount-out/--amount-out-decimal).- Uniswap requires
--from-address;--slippage-pctis optional (default: provider auto). - Tempo DEX currently supports USD-denominated TIP-20 swaps only and auto-routes supported pairs through quote-token relationships; non-USD assets such as
EURC.eare rejected. - Tempo swap execution settles to the sender only; omit
--recipientor keep it equal to--from-address. actions estimatereturns fee-token-denominated estimates for Tempo actions (includesfee_unitandfee_tokenfields instead of native-gas EIP-1559 pricing).fibrouscurrently supportsbase,hyperevm, andcitrea.- Bungee dedicated backend requires both
DEFI_BUNGEE_API_KEYandDEFI_BUNGEE_AFFILIATE.
yieldandlendare split by intent:yieldfor passive deposits/withdrawals,lendfor loan lifecycle.- Morpho:
yield deposit|withdrawtargets vaults (--vault-address),lendtargets markets (--market-id). - Aave execution auto-resolves pool addresses on Ethereum, Optimism, Polygon, Base, Arbitrum, and Avalanche; use
--pool-addresson other chains. - Moonwell execution targets mToken contracts (Compound v2 style) on Base and Optimism; use
--pool-addressto specify the mToken directly or let auto-resolution match by underlying asset. The mWETH market auto-unwraps to native ETH on borrow/withdraw; the planner uses ERC-20 paths, so callers must handle ETH/WETH wrapping externally. - Bridge execution waits for destination settlement; adjust
--step-timeoutfor slower routes. - Pre-sign checks enforce bounded ERC-20 approvals by default; use
--allow-max-approvalto opt in to larger approvals. - Bridge pre-sign checks validate settlement endpoints; use
--unsafe-provider-txto bypass. - All
submitcommands broadcast signed transactions. --signer tempoenables agent wallet support via the Tempo CLI (tempo wallet -j whoami), with delegated access keys and expiry checks.--provideris required for multi-provider flows (no implicit defaults).
0: success1: internal error2: usage/validation error10: auth required/failed11: rate limited12: provider unavailable13: unsupported input/provider pair14: stale data beyond SLA15: partial results in strict mode16: blocked by command allowlist20: action plan validation failed21: action simulation failed22: execution rejected by policy23: action timed out while waiting for confirmation24: signer unavailable or signing failed
cmd/
defi/main.go # CLI entrypoint
internal/
app/runner.go # command wiring, routing, cache flow
providers/ # external adapters
aave/ morpho/ moonwell/ # lending + yield (read + execution)
defillama/ # normalization + fallback + bridge analytics
across/ lifi/ # bridge quotes + lifi execution planning
oneinch/ uniswap/ taikoswap/ # swap (quote + taikoswap execution planning)
types.go # provider interfaces
execution/ # action store + planner helpers + signer + executor
registry/ # canonical execution endpoints/contracts/ABI fragments
config/ # file/env/flags precedence
cache/ # sqlite cache + file lock
id/ # CAIP + amount normalization
model/ # envelope + domain models
out/ # renderers
errors/ # typed errors / exit codes
schema/ # machine-readable CLI schema
policy/ # command allowlist
httpx/ # shared HTTP client
.github/workflows/ci.yml # CI (test/vet/build)
.github/workflows/nightly-execution-smoke.yml # nightly live execution planning smoke
docs/ # Mintlify docs site (docs.json + MDX pages)
AGENTS.md # contributor guide for agents
go test ./...
go test -race ./...
go vet ./...
bash scripts/nightly_execution_smoke.shThe docs/ directory contains a Mintlify docs site (docs.json + .mdx pages).
cd docs
npx --yes mint@4.2.378 dev --no-open # local preview
npx --yes mint@4.2.378 validate # validate before publishing
npx --yes mint@4.2.378 broken-links
npx --yes mint@4.2.378 a11yProduction docs deploy from the docs-live branch, which the release workflow syncs on stable (non-prerelease) tags.
